From 3e820c5daef942b7418ded75bb63a31dff7d8635 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Thu, 10 Jun 2004 13:21:42 +0000 Subject: [PATCH] bitkeeper revision 1.950 (40c86066TdQwTUVQtZ0q0py10MTUgg) Removed old I/O world and cleaned up. --- .rootkeys | 265 - docs/HOWTOs/Xen-HOWTO | 6 - extras/mini-os/h/hypervisor.h | 35 - .../Documentation/Configure.help | 29164 ---------------- linux-2.4.26-xen-sparse/arch/xen/Makefile | 10 - linux-2.4.26-xen-sparse/arch/xen/config.in | 6 +- .../arch/xen/defconfigs/dom0 | 1 - .../arch/xen/defconfigs/unprivileged | 3 +- .../arch/xen/drivers/blkif/backend/common.h | 8 +- .../arch/xen/drivers/blkif/backend/main.c | 8 +- .../arch/xen/drivers/blkif/frontend/common.h | 1 - .../arch/xen/drivers/blkif/frontend/main.c | 37 +- .../arch/xen/drivers/blkif/frontend/vbd.c | 20 +- .../arch/xen/drivers/block/Makefile | 3 - .../arch/xen/drivers/block/block.c | 625 - .../arch/xen/drivers/block/block.h | 82 - .../arch/xen/drivers/block/vbd.c | 561 - .../arch/xen/drivers/dom0/Makefile | 2 +- .../arch/xen/drivers/dom0/vfr.c | 343 - .../arch/xen/drivers/netif/backend/main.c | 6 +- .../arch/xen/drivers/netif/frontend/main.c | 12 +- .../arch/xen/drivers/network/Makefile | 3 - .../arch/xen/drivers/network/network.c | 656 - .../drivers/block/ll_rw_blk.c | 2 +- .../include/asm-xen/hypervisor.h | 33 - linux-2.4.26-xen-sparse/include/linux/blk.h | 4 +- linux-2.4.26-xen-sparse/include/linux/major.h | 206 - linux-2.4.26-xen-sparse/init/do_mounts.c | 1084 - tools/examples/xc_dom_control.py | 103 - tools/examples/xc_dom_create.py | 161 +- tools/xc/lib/xc.h | 84 +- tools/xc/lib/xc_linux_build.c | 1 - tools/xc/lib/xc_linux_restore.c | 1 - tools/xc/lib/xc_netbsd_build.c | 1 - tools/xc/lib/xc_private.h | 46 - tools/xc/lib/xc_vbd.c | 212 - tools/xc/lib/xc_vif.c | 69 - tools/xc/py/Xc.c | 486 - tools/xenctl/lib/utils.py | 58 - xen/Makefile | 6 +- xen/Rules.mk | 14 - xen/arch/i386/entry.S | 15 +- xen/arch/i386/io_apic.c | 71 - xen/arch/i386/setup.c | 12 +- xen/arch/i386/smp.c | 27 - xen/common/Makefile | 4 - xen/common/brlock.c | 69 - xen/common/domain.c | 82 +- xen/common/kernel.c | 17 +- xen/common/network.c | 615 - xen/common/rbtree.c | 295 - xen/drivers/Makefile | 14 - xen/drivers/acpi_ksyms.c | 157 - xen/drivers/block/Makefile | 16 - xen/drivers/block/blkpg.c | 315 - xen/drivers/block/cciss.c | 3448 -- xen/drivers/block/cciss.h | 293 - xen/drivers/block/cciss_cmd.h | 271 - xen/drivers/block/cciss_scsi.c | 1590 - xen/drivers/block/cciss_scsi.h | 99 - xen/drivers/block/elevator.c | 224 - xen/drivers/block/genhd.c | 280 - xen/drivers/block/ll_rw_blk.c | 1469 - xen/drivers/block/xen_block.c | 663 - xen/drivers/block/xen_vbd.c | 726 - xen/drivers/cdrom/Makefile | 7 - xen/drivers/cdrom/cdrom.c | 2662 -- xen/drivers/ide/Makefile | 8 - xen/drivers/ide/ide-cd.c | 3084 -- xen/drivers/ide/ide-cd.h | 746 - xen/drivers/ide/ide-disk.c | 1553 - xen/drivers/ide/ide-dma.c | 897 - xen/drivers/ide/ide-features.c | 384 - xen/drivers/ide/ide-geometry.c | 219 - xen/drivers/ide/ide-pci.c | 1016 - xen/drivers/ide/ide-probe.c | 1066 - xen/drivers/ide/ide-taskfile.c | 1733 - xen/drivers/ide/ide-xen.c | 61 - xen/drivers/ide/ide.c | 4211 --- xen/drivers/ide/ide_modes.h | 236 - xen/drivers/ide/piix.c | 542 - xen/drivers/message/fusion/Config.in | 38 - xen/drivers/message/fusion/Makefile | 11 - xen/drivers/message/fusion/isense.h | 95 - xen/drivers/message/fusion/linux_compat.h | 295 - xen/drivers/message/fusion/lsi/fc_log.h | 89 - xen/drivers/message/fusion/lsi/mpi.h | 678 - xen/drivers/message/fusion/lsi/mpi_cnfg.h | 1569 - xen/drivers/message/fusion/lsi/mpi_fc.h | 362 - .../message/fusion/lsi/mpi_history.txt | 276 - xen/drivers/message/fusion/lsi/mpi_init.h | 318 - xen/drivers/message/fusion/lsi/mpi_ioc.h | 698 - xen/drivers/message/fusion/lsi/mpi_lan.h | 212 - xen/drivers/message/fusion/lsi/mpi_raid.h | 225 - xen/drivers/message/fusion/lsi/mpi_targ.h | 429 - xen/drivers/message/fusion/lsi/mpi_type.h | 91 - xen/drivers/message/fusion/mptbase.c | 6130 ---- xen/drivers/message/fusion/mptbase.h | 1123 - xen/drivers/message/fusion/mptscsih.c | 7957 ----- xen/drivers/message/fusion/mptscsih.h | 343 - xen/drivers/message/fusion/scsi3.h | 707 - xen/drivers/net/3c59x.c | 2988 -- xen/drivers/net/8139too.c | 2715 -- xen/drivers/net/Makefile | 16 - xen/drivers/net/SUPPORTED_CARDS | 14 - xen/drivers/net/Space.c | 44 - xen/drivers/net/dummy.c | 79 - xen/drivers/net/e100/LICENSE | 339 - xen/drivers/net/e100/Makefile | 8 - xen/drivers/net/e100/e100.h | 1005 - xen/drivers/net/e100/e100_config.c | 639 - xen/drivers/net/e100/e100_config.h | 167 - xen/drivers/net/e100/e100_eeprom.c | 565 - xen/drivers/net/e100/e100_main.c | 4265 --- xen/drivers/net/e100/e100_phy.c | 1160 - xen/drivers/net/e100/e100_phy.h | 158 - xen/drivers/net/e100/e100_test.c | 435 - xen/drivers/net/e100/e100_ucode.h | 365 - xen/drivers/net/e1000/LICENSE | 339 - xen/drivers/net/e1000/Makefile | 39 - xen/drivers/net/e1000/e1000.h | 259 - xen/drivers/net/e1000/e1000_ethtool.c | 1749 - xen/drivers/net/e1000/e1000_hw.c | 5095 --- xen/drivers/net/e1000/e1000_hw.h | 2121 -- xen/drivers/net/e1000/e1000_main.c | 2940 -- xen/drivers/net/e1000/e1000_osdep.h | 104 - xen/drivers/net/e1000/e1000_param.c | 698 - xen/drivers/net/e1000/kcompat.c | 170 - xen/drivers/net/e1000/kcompat.h | 307 - xen/drivers/net/net_init.c | 745 - xen/drivers/net/pcnet32.c | 1761 - xen/drivers/net/setup.c | 173 - xen/drivers/net/tg3.c | 7934 ----- xen/drivers/net/tg3.h | 1999 -- xen/drivers/net/tulip/21142.c | 240 - xen/drivers/net/tulip/ChangeLog | 563 - xen/drivers/net/tulip/Makefile | 8 - xen/drivers/net/tulip/eeprom.c | 376 - xen/drivers/net/tulip/interrupt.c | 585 - xen/drivers/net/tulip/media.c | 563 - xen/drivers/net/tulip/pnic.c | 171 - xen/drivers/net/tulip/pnic2.c | 407 - xen/drivers/net/tulip/timer.c | 220 - xen/drivers/net/tulip/tulip.h | 501 - xen/drivers/net/tulip/tulip_core.c | 1938 - xen/drivers/pci/pci.c | 83 +- xen/drivers/scsi/BusLogic.c | 5010 --- xen/drivers/scsi/BusLogic.h | 1811 - xen/drivers/scsi/FlashPoint.c.inc | 12159 ------- xen/drivers/scsi/Makefile | 21 - xen/drivers/scsi/aacraid/Makefile | 13 - xen/drivers/scsi/aacraid/README | 55 - xen/drivers/scsi/aacraid/TODO | 5 - xen/drivers/scsi/aacraid/aachba.c | 1745 - xen/drivers/scsi/aacraid/aacraid.h | 1420 - xen/drivers/scsi/aacraid/commctrl.c | 445 - xen/drivers/scsi/aacraid/comminit.c | 347 - xen/drivers/scsi/aacraid/commsup.c | 1052 - xen/drivers/scsi/aacraid/dpcsup.c | 230 - xen/drivers/scsi/aacraid/linit.c | 777 - xen/drivers/scsi/aacraid/rx.c | 415 - xen/drivers/scsi/aacraid/sa.c | 410 - xen/drivers/scsi/aic7xxx/Makefile | 74 - xen/drivers/scsi/aic7xxx/aic7770.c | 369 - xen/drivers/scsi/aic7xxx/aic7770_osm.c | 150 - xen/drivers/scsi/aic7xxx/aic79xx.h | 1297 - xen/drivers/scsi/aic7xxx/aic79xx.reg | 3716 -- xen/drivers/scsi/aic7xxx/aic79xx.seq | 1723 - xen/drivers/scsi/aic7xxx/aic79xx_core.c | 8345 ----- xen/drivers/scsi/aic7xxx/aic79xx_host.h | 97 - xen/drivers/scsi/aic7xxx/aic79xx_inline.h | 997 - xen/drivers/scsi/aic7xxx/aic79xx_osm.c | 2968 -- xen/drivers/scsi/aic7xxx/aic79xx_osm.h | 1303 - xen/drivers/scsi/aic7xxx/aic79xx_osm_pci.c | 428 - xen/drivers/scsi/aic7xxx/aic79xx_pci.c | 792 - xen/drivers/scsi/aic7xxx/aic79xx_proc.c | 365 - xen/drivers/scsi/aic7xxx/aic79xx_reg.h | 1357 - xen/drivers/scsi/aic7xxx/aic79xx_seq.h | 824 - xen/drivers/scsi/aic7xxx/aic7xxx.h | 1245 - xen/drivers/scsi/aic7xxx/aic7xxx.reg | 1588 - xen/drivers/scsi/aic7xxx/aic7xxx.seq | 2365 -- xen/drivers/scsi/aic7xxx/aic7xxx_93cx6.c | 306 - xen/drivers/scsi/aic7xxx/aic7xxx_93cx6.h | 102 - xen/drivers/scsi/aic7xxx/aic7xxx_core.c | 7127 ---- xen/drivers/scsi/aic7xxx/aic7xxx_host.h | 103 - xen/drivers/scsi/aic7xxx/aic7xxx_inline.h | 563 - xen/drivers/scsi/aic7xxx/aic7xxx_osm.c | 3073 -- xen/drivers/scsi/aic7xxx/aic7xxx_osm.h | 1199 - xen/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | 416 - xen/drivers/scsi/aic7xxx/aic7xxx_pci.c | 2277 -- xen/drivers/scsi/aic7xxx/aic7xxx_proc.c | 405 - xen/drivers/scsi/aic7xxx/aic7xxx_reg.h | 722 - xen/drivers/scsi/aic7xxx/aic7xxx_seq.h | 1301 - xen/drivers/scsi/aic7xxx/aicasm/Makefile | 65 - xen/drivers/scsi/aic7xxx/aicasm/aicasm.c | 809 - xen/drivers/scsi/aic7xxx/aicasm/aicasm.h | 93 - xen/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y | 1858 - .../scsi/aic7xxx/aicasm/aicasm_insformat.h | 131 - .../scsi/aic7xxx/aicasm/aicasm_macro_gram.y | 164 - .../scsi/aic7xxx/aicasm/aicasm_macro_scan.l | 154 - xen/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l | 594 - .../scsi/aic7xxx/aicasm/aicasm_symbol.c | 500 - .../scsi/aic7xxx/aicasm/aicasm_symbol.h | 202 - xen/drivers/scsi/aic7xxx/cam.h | 138 - xen/drivers/scsi/aic7xxx/queue.h | 501 - xen/drivers/scsi/aic7xxx/scsi_iu.h | 31 - xen/drivers/scsi/aic7xxx/scsi_message.h | 70 - xen/drivers/scsi/constants.c | 1005 - xen/drivers/scsi/constants.h | 5 - xen/drivers/scsi/hosts.c | 316 - xen/drivers/scsi/hosts.h | 591 - xen/drivers/scsi/megaraid.c | 5544 --- xen/drivers/scsi/megaraid.h | 1049 - xen/drivers/scsi/scsi.c | 2970 -- xen/drivers/scsi/scsi.h | 899 - xen/drivers/scsi/scsi_dma.c | 455 - xen/drivers/scsi/scsi_error.c | 2063 -- xen/drivers/scsi/scsi_ioctl.c | 538 - xen/drivers/scsi/scsi_lib.c | 1210 - xen/drivers/scsi/scsi_merge.c | 1182 - xen/drivers/scsi/scsi_module.c.inc | 55 - xen/drivers/scsi/scsi_obsolete.c | 1160 - xen/drivers/scsi/scsi_obsolete.h | 106 - xen/drivers/scsi/scsi_proc.c | 329 - xen/drivers/scsi/scsi_queue.c | 151 - xen/drivers/scsi/scsi_scan.c | 906 - xen/drivers/scsi/scsi_syms.c | 103 - xen/drivers/scsi/scsicam.c | 236 - xen/drivers/scsi/sd.c | 1568 - xen/drivers/scsi/sd.h | 66 - xen/drivers/scsi/sym53c8xx_2/ChangeLog.txt | 148 - .../scsi/sym53c8xx_2/Documentation.txt | 1149 - xen/drivers/scsi/sym53c8xx_2/Makefile | 18 - xen/drivers/scsi/sym53c8xx_2/sym53c8xx.h | 375 - xen/drivers/scsi/sym53c8xx_2/sym_conf.h | 329 - xen/drivers/scsi/sym53c8xx_2/sym_defs.h | 957 - xen/drivers/scsi/sym53c8xx_2/sym_fw.c | 617 - xen/drivers/scsi/sym53c8xx_2/sym_fw.h | 232 - xen/drivers/scsi/sym53c8xx_2/sym_fw1.h | 1874 - xen/drivers/scsi/sym53c8xx_2/sym_fw2.h | 1994 -- xen/drivers/scsi/sym53c8xx_2/sym_glue.c | 3049 -- xen/drivers/scsi/sym53c8xx_2/sym_glue.h | 683 - xen/drivers/scsi/sym53c8xx_2/sym_hipd.c | 6021 ---- xen/drivers/scsi/sym53c8xx_2/sym_hipd.h | 1446 - xen/drivers/scsi/sym53c8xx_2/sym_malloc.c | 421 - xen/drivers/scsi/sym53c8xx_2/sym_misc.c | 336 - xen/drivers/scsi/sym53c8xx_2/sym_misc.h | 311 - xen/drivers/scsi/sym53c8xx_2/sym_nvram.c | 730 - xen/drivers/tables.c | 588 - xen/include/asm-i386/byteorder.h | 47 - xen/include/asm-i386/ioctl.h | 75 - xen/include/asm-x86_64/byteorder.h | 32 - xen/include/asm-x86_64/ioctl.h | 75 - xen/include/hypervisor-ifs/block.h | 116 - xen/include/hypervisor-ifs/dom0_ops.h | 2 +- xen/include/hypervisor-ifs/hypervisor-if.h | 16 +- xen/include/hypervisor-ifs/network.h | 222 - xen/include/hypervisor-ifs/vbd.h | 103 - xen/include/scsi/scsi.h | 237 - xen/include/scsi/scsi_ioctl.h | 51 - xen/include/scsi/scsicam.h | 17 - xen/include/scsi/sg.h | 330 - xen/include/xen/blk.h | 409 - xen/include/xen/blkdev.h | 411 - xen/include/xen/blkpg.h | 64 - xen/include/xen/brlock.h | 220 - xen/include/xen/byteorder/big_endian.h | 68 - xen/include/xen/byteorder/generic.h | 180 - xen/include/xen/byteorder/little_endian.h | 68 - xen/include/xen/byteorder/pdp_endian.h | 88 - xen/include/xen/byteorder/swab.h | 190 - xen/include/xen/byteorder/swabb.h | 137 - xen/include/xen/cdrom.h | 1067 - xen/include/xen/crc32.h | 49 - xen/include/xen/elevator.h | 104 - xen/include/xen/etherdevice.h | 71 - xen/include/xen/ethtool.h | 361 - xen/include/xen/genhd.h | 313 - xen/include/xen/hdreg.h | 662 - xen/include/xen/hdsmart.h | 124 - xen/include/xen/ide.h | 1105 - xen/include/xen/if.h | 141 - xen/include/xen/if_ether.h | 100 - xen/include/xen/if_packet.h | 102 - xen/include/xen/if_vlan.h | 256 - xen/include/xen/in.h | 191 - xen/include/xen/ioctl.h | 7 - xen/include/xen/kdev_t.h | 123 - xen/include/xen/major.h | 199 - xen/include/xen/mii.h | 200 - xen/include/xen/net_headers.h | 128 - xen/include/xen/netdevice.h | 616 - xen/include/xen/notifier.h | 64 - xen/include/xen/perfc.h | 6 +- xen/include/xen/perfc_defn.h | 6 - xen/include/xen/rbtree.h | 134 - xen/include/xen/reboot.h | 43 - xen/include/xen/sched.h | 21 - xen/include/xen/skbuff.h | 454 - xen/include/xen/socket.h | 136 - xen/include/xen/sockios.h | 132 - xen/include/xen/timex.h | 284 - xen/include/xen/vbd.h | 67 - xen/include/xen/vif.h | 123 - xen/net/Makefile | 8 - xen/net/dev.c | 2448 -- xen/net/dev_mcast.c | 276 - xen/net/devinit.c | 109 - xen/net/eth.c | 252 - xen/net/skbuff.c | 483 - 310 files changed, 148 insertions(+), 268903 deletions(-) delete mode 100644 linux-2.4.26-xen-sparse/Documentation/Configure.help delete mode 100644 linux-2.4.26-xen-sparse/arch/xen/drivers/block/Makefile delete mode 100644 linux-2.4.26-xen-sparse/arch/xen/drivers/block/block.c delete mode 100644 linux-2.4.26-xen-sparse/arch/xen/drivers/block/block.h delete mode 100644 linux-2.4.26-xen-sparse/arch/xen/drivers/block/vbd.c delete mode 100644 linux-2.4.26-xen-sparse/arch/xen/drivers/dom0/vfr.c delete mode 100644 linux-2.4.26-xen-sparse/arch/xen/drivers/network/Makefile delete mode 100644 linux-2.4.26-xen-sparse/arch/xen/drivers/network/network.c delete mode 100644 linux-2.4.26-xen-sparse/include/linux/major.h delete mode 100644 linux-2.4.26-xen-sparse/init/do_mounts.c delete mode 100644 tools/xc/lib/xc_vbd.c delete mode 100644 tools/xc/lib/xc_vif.c delete mode 100644 xen/common/brlock.c delete mode 100644 xen/common/network.c delete mode 100644 xen/common/rbtree.c delete mode 100644 xen/drivers/acpi_ksyms.c delete mode 100644 xen/drivers/block/Makefile delete mode 100644 xen/drivers/block/blkpg.c delete mode 100644 xen/drivers/block/cciss.c delete mode 100644 xen/drivers/block/cciss.h delete mode 100644 xen/drivers/block/cciss_cmd.h delete mode 100644 xen/drivers/block/cciss_scsi.c delete mode 100644 xen/drivers/block/cciss_scsi.h delete mode 100644 xen/drivers/block/elevator.c delete mode 100644 xen/drivers/block/genhd.c delete mode 100644 xen/drivers/block/ll_rw_blk.c delete mode 100644 xen/drivers/block/xen_block.c delete mode 100644 xen/drivers/block/xen_vbd.c delete mode 100644 xen/drivers/cdrom/Makefile delete mode 100644 xen/drivers/cdrom/cdrom.c delete mode 100644 xen/drivers/ide/Makefile delete mode 100644 xen/drivers/ide/ide-cd.c delete mode 100644 xen/drivers/ide/ide-cd.h delete mode 100644 xen/drivers/ide/ide-disk.c delete mode 100644 xen/drivers/ide/ide-dma.c delete mode 100644 xen/drivers/ide/ide-features.c delete mode 100644 xen/drivers/ide/ide-geometry.c delete mode 100644 xen/drivers/ide/ide-pci.c delete mode 100644 xen/drivers/ide/ide-probe.c delete mode 100644 xen/drivers/ide/ide-taskfile.c delete mode 100644 xen/drivers/ide/ide-xen.c delete mode 100644 xen/drivers/ide/ide.c delete mode 100644 xen/drivers/ide/ide_modes.h delete mode 100644 xen/drivers/ide/piix.c delete mode 100644 xen/drivers/message/fusion/Config.in delete mode 100644 xen/drivers/message/fusion/Makefile delete mode 100644 xen/drivers/message/fusion/isense.h delete mode 100644 xen/drivers/message/fusion/linux_compat.h delete mode 100644 xen/drivers/message/fusion/lsi/fc_log.h delete mode 100644 xen/drivers/message/fusion/lsi/mpi.h delete mode 100644 xen/drivers/message/fusion/lsi/mpi_cnfg.h delete mode 100644 xen/drivers/message/fusion/lsi/mpi_fc.h delete mode 100644 xen/drivers/message/fusion/lsi/mpi_history.txt delete mode 100644 xen/drivers/message/fusion/lsi/mpi_init.h delete mode 100644 xen/drivers/message/fusion/lsi/mpi_ioc.h delete mode 100644 xen/drivers/message/fusion/lsi/mpi_lan.h delete mode 100644 xen/drivers/message/fusion/lsi/mpi_raid.h delete mode 100644 xen/drivers/message/fusion/lsi/mpi_targ.h delete mode 100644 xen/drivers/message/fusion/lsi/mpi_type.h delete mode 100644 xen/drivers/message/fusion/mptbase.c delete mode 100644 xen/drivers/message/fusion/mptbase.h delete mode 100644 xen/drivers/message/fusion/mptscsih.c delete mode 100644 xen/drivers/message/fusion/mptscsih.h delete mode 100644 xen/drivers/message/fusion/scsi3.h delete mode 100644 xen/drivers/net/3c59x.c delete mode 100644 xen/drivers/net/8139too.c delete mode 100644 xen/drivers/net/Makefile delete mode 100644 xen/drivers/net/SUPPORTED_CARDS delete mode 100644 xen/drivers/net/Space.c delete mode 100644 xen/drivers/net/dummy.c delete mode 100644 xen/drivers/net/e100/LICENSE delete mode 100644 xen/drivers/net/e100/Makefile delete mode 100644 xen/drivers/net/e100/e100.h delete mode 100644 xen/drivers/net/e100/e100_config.c delete mode 100644 xen/drivers/net/e100/e100_config.h delete mode 100644 xen/drivers/net/e100/e100_eeprom.c delete mode 100644 xen/drivers/net/e100/e100_main.c delete mode 100644 xen/drivers/net/e100/e100_phy.c delete mode 100644 xen/drivers/net/e100/e100_phy.h delete mode 100644 xen/drivers/net/e100/e100_test.c delete mode 100644 xen/drivers/net/e100/e100_ucode.h delete mode 100644 xen/drivers/net/e1000/LICENSE delete mode 100644 xen/drivers/net/e1000/Makefile delete mode 100644 xen/drivers/net/e1000/e1000.h delete mode 100644 xen/drivers/net/e1000/e1000_ethtool.c delete mode 100644 xen/drivers/net/e1000/e1000_hw.c delete mode 100644 xen/drivers/net/e1000/e1000_hw.h delete mode 100644 xen/drivers/net/e1000/e1000_main.c delete mode 100644 xen/drivers/net/e1000/e1000_osdep.h delete mode 100644 xen/drivers/net/e1000/e1000_param.c delete mode 100644 xen/drivers/net/e1000/kcompat.c delete mode 100644 xen/drivers/net/e1000/kcompat.h delete mode 100644 xen/drivers/net/net_init.c delete mode 100644 xen/drivers/net/pcnet32.c delete mode 100644 xen/drivers/net/setup.c delete mode 100644 xen/drivers/net/tg3.c delete mode 100644 xen/drivers/net/tg3.h delete mode 100644 xen/drivers/net/tulip/21142.c delete mode 100644 xen/drivers/net/tulip/ChangeLog delete mode 100644 xen/drivers/net/tulip/Makefile delete mode 100644 xen/drivers/net/tulip/eeprom.c delete mode 100644 xen/drivers/net/tulip/interrupt.c delete mode 100644 xen/drivers/net/tulip/media.c delete mode 100644 xen/drivers/net/tulip/pnic.c delete mode 100644 xen/drivers/net/tulip/pnic2.c delete mode 100644 xen/drivers/net/tulip/timer.c delete mode 100644 xen/drivers/net/tulip/tulip.h delete mode 100644 xen/drivers/net/tulip/tulip_core.c delete mode 100644 xen/drivers/scsi/BusLogic.c delete mode 100644 xen/drivers/scsi/BusLogic.h delete mode 100644 xen/drivers/scsi/FlashPoint.c.inc delete mode 100644 xen/drivers/scsi/Makefile delete mode 100644 xen/drivers/scsi/aacraid/Makefile delete mode 100644 xen/drivers/scsi/aacraid/README delete mode 100644 xen/drivers/scsi/aacraid/TODO delete mode 100644 xen/drivers/scsi/aacraid/aachba.c delete mode 100644 xen/drivers/scsi/aacraid/aacraid.h delete mode 100644 xen/drivers/scsi/aacraid/commctrl.c delete mode 100644 xen/drivers/scsi/aacraid/comminit.c delete mode 100644 xen/drivers/scsi/aacraid/commsup.c delete mode 100644 xen/drivers/scsi/aacraid/dpcsup.c delete mode 100644 xen/drivers/scsi/aacraid/linit.c delete mode 100644 xen/drivers/scsi/aacraid/rx.c delete mode 100644 xen/drivers/scsi/aacraid/sa.c delete mode 100644 xen/drivers/scsi/aic7xxx/Makefile delete mode 100644 xen/drivers/scsi/aic7xxx/aic7770.c delete mode 100644 xen/drivers/scsi/aic7xxx/aic7770_osm.c delete mode 100644 xen/drivers/scsi/aic7xxx/aic79xx.h delete mode 100644 xen/drivers/scsi/aic7xxx/aic79xx.reg delete mode 100644 xen/drivers/scsi/aic7xxx/aic79xx.seq delete mode 100644 xen/drivers/scsi/aic7xxx/aic79xx_core.c delete mode 100644 xen/drivers/scsi/aic7xxx/aic79xx_host.h delete mode 100644 xen/drivers/scsi/aic7xxx/aic79xx_inline.h delete mode 100644 xen/drivers/scsi/aic7xxx/aic79xx_osm.c delete mode 100644 xen/drivers/scsi/aic7xxx/aic79xx_osm.h delete mode 100644 xen/drivers/scsi/aic7xxx/aic79xx_osm_pci.c delete mode 100644 xen/drivers/scsi/aic7xxx/aic79xx_pci.c delete mode 100644 xen/drivers/scsi/aic7xxx/aic79xx_proc.c delete mode 100644 xen/drivers/scsi/aic7xxx/aic79xx_reg.h delete mode 100644 xen/drivers/scsi/aic7xxx/aic79xx_seq.h delete mode 100644 xen/drivers/scsi/aic7xxx/aic7xxx.h delete mode 100644 xen/drivers/scsi/aic7xxx/aic7xxx.reg delete mode 100644 xen/drivers/scsi/aic7xxx/aic7xxx.seq delete mode 100644 xen/drivers/scsi/aic7xxx/aic7xxx_93cx6.c delete mode 100644 xen/drivers/scsi/aic7xxx/aic7xxx_93cx6.h delete mode 100644 xen/drivers/scsi/aic7xxx/aic7xxx_core.c delete mode 100644 xen/drivers/scsi/aic7xxx/aic7xxx_host.h delete mode 100644 xen/drivers/scsi/aic7xxx/aic7xxx_inline.h delete mode 100644 xen/drivers/scsi/aic7xxx/aic7xxx_osm.c delete mode 100644 xen/drivers/scsi/aic7xxx/aic7xxx_osm.h delete mode 100644 xen/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c delete mode 100644 xen/drivers/scsi/aic7xxx/aic7xxx_pci.c delete mode 100644 xen/drivers/scsi/aic7xxx/aic7xxx_proc.c delete mode 100644 xen/drivers/scsi/aic7xxx/aic7xxx_reg.h delete mode 100644 xen/drivers/scsi/aic7xxx/aic7xxx_seq.h delete mode 100644 xen/drivers/scsi/aic7xxx/aicasm/Makefile delete mode 100644 xen/drivers/scsi/aic7xxx/aicasm/aicasm.c delete mode 100644 xen/drivers/scsi/aic7xxx/aicasm/aicasm.h delete mode 100644 xen/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y delete mode 100644 xen/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h delete mode 100644 xen/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y delete mode 100644 xen/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l delete mode 100644 xen/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l delete mode 100644 xen/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c delete mode 100644 xen/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h delete mode 100644 xen/drivers/scsi/aic7xxx/cam.h delete mode 100644 xen/drivers/scsi/aic7xxx/queue.h delete mode 100644 xen/drivers/scsi/aic7xxx/scsi_iu.h delete mode 100644 xen/drivers/scsi/aic7xxx/scsi_message.h delete mode 100644 xen/drivers/scsi/constants.c delete mode 100644 xen/drivers/scsi/constants.h delete mode 100644 xen/drivers/scsi/hosts.c delete mode 100644 xen/drivers/scsi/hosts.h delete mode 100644 xen/drivers/scsi/megaraid.c delete mode 100644 xen/drivers/scsi/megaraid.h delete mode 100644 xen/drivers/scsi/scsi.c delete mode 100644 xen/drivers/scsi/scsi.h delete mode 100644 xen/drivers/scsi/scsi_dma.c delete mode 100644 xen/drivers/scsi/scsi_error.c delete mode 100644 xen/drivers/scsi/scsi_ioctl.c delete mode 100644 xen/drivers/scsi/scsi_lib.c delete mode 100644 xen/drivers/scsi/scsi_merge.c delete mode 100644 xen/drivers/scsi/scsi_module.c.inc delete mode 100644 xen/drivers/scsi/scsi_obsolete.c delete mode 100644 xen/drivers/scsi/scsi_obsolete.h delete mode 100644 xen/drivers/scsi/scsi_proc.c delete mode 100644 xen/drivers/scsi/scsi_queue.c delete mode 100644 xen/drivers/scsi/scsi_scan.c delete mode 100644 xen/drivers/scsi/scsi_syms.c delete mode 100644 xen/drivers/scsi/scsicam.c delete mode 100644 xen/drivers/scsi/sd.c delete mode 100644 xen/drivers/scsi/sd.h delete mode 100644 xen/drivers/scsi/sym53c8xx_2/ChangeLog.txt delete mode 100644 xen/drivers/scsi/sym53c8xx_2/Documentation.txt delete mode 100644 xen/drivers/scsi/sym53c8xx_2/Makefile delete mode 100644 xen/drivers/scsi/sym53c8xx_2/sym53c8xx.h delete mode 100644 xen/drivers/scsi/sym53c8xx_2/sym_conf.h delete mode 100644 xen/drivers/scsi/sym53c8xx_2/sym_defs.h delete mode 100644 xen/drivers/scsi/sym53c8xx_2/sym_fw.c delete mode 100644 xen/drivers/scsi/sym53c8xx_2/sym_fw.h delete mode 100644 xen/drivers/scsi/sym53c8xx_2/sym_fw1.h delete mode 100644 xen/drivers/scsi/sym53c8xx_2/sym_fw2.h delete mode 100644 xen/drivers/scsi/sym53c8xx_2/sym_glue.c delete mode 100644 xen/drivers/scsi/sym53c8xx_2/sym_glue.h delete mode 100644 xen/drivers/scsi/sym53c8xx_2/sym_hipd.c delete mode 100644 xen/drivers/scsi/sym53c8xx_2/sym_hipd.h delete mode 100644 xen/drivers/scsi/sym53c8xx_2/sym_malloc.c delete mode 100644 xen/drivers/scsi/sym53c8xx_2/sym_misc.c delete mode 100644 xen/drivers/scsi/sym53c8xx_2/sym_misc.h delete mode 100644 xen/drivers/scsi/sym53c8xx_2/sym_nvram.c delete mode 100644 xen/drivers/tables.c delete mode 100644 xen/include/asm-i386/byteorder.h delete mode 100644 xen/include/asm-i386/ioctl.h delete mode 100644 xen/include/asm-x86_64/byteorder.h delete mode 100644 xen/include/asm-x86_64/ioctl.h delete mode 100644 xen/include/hypervisor-ifs/block.h delete mode 100644 xen/include/hypervisor-ifs/network.h delete mode 100644 xen/include/hypervisor-ifs/vbd.h delete mode 100644 xen/include/scsi/scsi.h delete mode 100644 xen/include/scsi/scsi_ioctl.h delete mode 100644 xen/include/scsi/scsicam.h delete mode 100644 xen/include/scsi/sg.h delete mode 100644 xen/include/xen/blk.h delete mode 100644 xen/include/xen/blkdev.h delete mode 100644 xen/include/xen/blkpg.h delete mode 100644 xen/include/xen/brlock.h delete mode 100644 xen/include/xen/byteorder/big_endian.h delete mode 100644 xen/include/xen/byteorder/generic.h delete mode 100644 xen/include/xen/byteorder/little_endian.h delete mode 100644 xen/include/xen/byteorder/pdp_endian.h delete mode 100644 xen/include/xen/byteorder/swab.h delete mode 100644 xen/include/xen/byteorder/swabb.h delete mode 100644 xen/include/xen/cdrom.h delete mode 100644 xen/include/xen/crc32.h delete mode 100644 xen/include/xen/elevator.h delete mode 100644 xen/include/xen/etherdevice.h delete mode 100644 xen/include/xen/ethtool.h delete mode 100644 xen/include/xen/genhd.h delete mode 100644 xen/include/xen/hdreg.h delete mode 100644 xen/include/xen/hdsmart.h delete mode 100644 xen/include/xen/ide.h delete mode 100644 xen/include/xen/if.h delete mode 100644 xen/include/xen/if_ether.h delete mode 100644 xen/include/xen/if_packet.h delete mode 100644 xen/include/xen/if_vlan.h delete mode 100644 xen/include/xen/in.h delete mode 100644 xen/include/xen/ioctl.h delete mode 100644 xen/include/xen/kdev_t.h delete mode 100644 xen/include/xen/major.h delete mode 100644 xen/include/xen/mii.h delete mode 100644 xen/include/xen/net_headers.h delete mode 100644 xen/include/xen/netdevice.h delete mode 100644 xen/include/xen/notifier.h delete mode 100644 xen/include/xen/rbtree.h delete mode 100644 xen/include/xen/skbuff.h delete mode 100644 xen/include/xen/socket.h delete mode 100644 xen/include/xen/sockios.h delete mode 100644 xen/include/xen/vbd.h delete mode 100644 xen/include/xen/vif.h delete mode 100644 xen/net/Makefile delete mode 100644 xen/net/dev.c delete mode 100644 xen/net/dev_mcast.c delete mode 100644 xen/net/devinit.c delete mode 100644 xen/net/eth.c delete mode 100644 xen/net/skbuff.c diff --git a/.rootkeys b/.rootkeys index bc27ebb1f8..ef162ef6ca 100644 --- a/.rootkeys +++ b/.rootkeys @@ -39,7 +39,6 @@ 3f815145CB8XdPUqsmhAjSDFuwOoqA extras/mini-os/mm.c 3f815145vGYx1WY79voKkZB9yKwJKQ extras/mini-os/time.c 3f815145xlKBAQmal9oces3G_Mvxqw extras/mini-os/traps.c -3f05a939TA3SLPY7ZiScMotLjg9owQ linux-2.4.26-xen-sparse/Documentation/Configure.help 3e5a4e6589G-U42lFKs43plskXoFxQ linux-2.4.26-xen-sparse/Makefile 3e5a4e65IEPjnWPZ5w3TxS5scV8Ewg linux-2.4.26-xen-sparse/arch/xen/Makefile 3e5a4e65n-KhsEAs-A4ULiStBp-r6w linux-2.4.26-xen-sparse/arch/xen/boot/Makefile @@ -60,15 +59,10 @@ 4075806d4-j7vN0Mn0bklI1cRUX1vQ linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/common.h 4075806d3fJqqDC1pYYPTZPc575iKg linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/main.c 4075806dibjCcfuXv6CINMhxWTw3jQ linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/vbd.c -3e5a4e65iHEuC5sjFhj42XALYbLVRw linux-2.4.26-xen-sparse/arch/xen/drivers/block/Makefile -3e5a4e65pP5spJErBW69pJxSSdK9RA linux-2.4.26-xen-sparse/arch/xen/drivers/block/block.c -3e67f822FOPwqHiaRKbrskgWgoNL5g linux-2.4.26-xen-sparse/arch/xen/drivers/block/block.h -3e676eb5RXnHzSHgA1BvM0B1aIm4qg linux-2.4.26-xen-sparse/arch/xen/drivers/block/vbd.c 3e5a4e65G3e2s0ghPMgiJ-gBTUJ0uQ linux-2.4.26-xen-sparse/arch/xen/drivers/console/Makefile 3e5a4e651TH-SXHoufurnWjgl5bfOA linux-2.4.26-xen-sparse/arch/xen/drivers/console/console.c 3e5a4e656nfFISThfbyXQOA6HN6YHw linux-2.4.26-xen-sparse/arch/xen/drivers/dom0/Makefile 3e5a4e65BXtftInNHUC2PjDfPhdZZA linux-2.4.26-xen-sparse/arch/xen/drivers/dom0/core.c -3e5a4e65gfn_ltB8ujHMVFApnTTNRQ linux-2.4.26-xen-sparse/arch/xen/drivers/dom0/vfr.c 40420a6ebRqDjufoN1WSJvolEW2Wjw linux-2.4.26-xen-sparse/arch/xen/drivers/evtchn/Makefile 40420a73Wou6JlsZDiu6YwjYomsm7A linux-2.4.26-xen-sparse/arch/xen/drivers/evtchn/evtchn.c 4083dc16-Kd5y9psK_yk161sme5j5Q linux-2.4.26-xen-sparse/arch/xen/drivers/netif/Makefile @@ -80,8 +74,6 @@ 405853f2wg7JXZJNltspMwOZJklxgw linux-2.4.26-xen-sparse/arch/xen/drivers/netif/frontend/Makefile 405853f6nbeazrNyEWNHBuoSg2PiPA linux-2.4.26-xen-sparse/arch/xen/drivers/netif/frontend/main.c 4097ba83Qy2eafeFUhGhm6_4iMIIDw linux-2.4.26-xen-sparse/arch/xen/drivers/netif/netif.h -3e5a4e65gZBRBB6RsSVg1c9iahigAw linux-2.4.26-xen-sparse/arch/xen/drivers/network/Makefile -3e5a4e65ZxKrbFetVB84JhrTyZ1YuQ linux-2.4.26-xen-sparse/arch/xen/drivers/network/network.c 3e5a4e65lWzkiPXsZdzPt2RNnJGG1g linux-2.4.26-xen-sparse/arch/xen/kernel/Makefile 4075806dE5mQwlVUf8-t3YXjiMMWDQ linux-2.4.26-xen-sparse/arch/xen/kernel/ctrl_if.c 3e5a4e65_hqfuxtGG8IUy6wRM86Ecg linux-2.4.26-xen-sparse/arch/xen/kernel/entry.S @@ -142,12 +134,10 @@ 3f689063nhrIRsMMZjZxMFk7iEINqQ linux-2.4.26-xen-sparse/include/asm-xen/xen_proc.h 40659defgWA92arexpMGn8X3QMDj3w linux-2.4.26-xen-sparse/include/asm-xen/xor.h 3f056927gMHl7mWB89rb73JahbhQIA linux-2.4.26-xen-sparse/include/linux/blk.h -3e5a4e68WLX3B8owTvktP3HHOtznPQ linux-2.4.26-xen-sparse/include/linux/major.h 401c0590D_kwJDU59X8NyvqSv_Cl2A linux-2.4.26-xen-sparse/include/linux/sched.h 40a248afgI0_JKthdYAe8beVfXSTpQ linux-2.4.26-xen-sparse/include/linux/skbuff.h 3e5a4e686V0nioX2ZpFf056sgvdiQw linux-2.4.26-xen-sparse/include/linux/sunrpc/debug.h 401c0592pLrp_aCbQRo9GXiYQQaVVA linux-2.4.26-xen-sparse/include/linux/timer.h -3e5a4e68W_hpMlM3u_-QOKMp3gzcwQ linux-2.4.26-xen-sparse/init/do_mounts.c 3f9d4b44247udoqWEgFkaHiWv6Uvyg linux-2.4.26-xen-sparse/kernel/time.c 401c059bjLBFYHRD4Py2uM3eA1D4zQ linux-2.4.26-xen-sparse/kernel/timer.c 3e6e7c1efbQe93xCvOpOVCnXTMmQ5w linux-2.4.26-xen-sparse/mkbuildtree @@ -209,8 +199,6 @@ 3fbba6dctWRWlFJkYb6hdix2X4WMuw tools/xc/lib/xc_private.c 3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/xc/lib/xc_private.h 40589968UQFnJeOMn8UIFLbXBuwXjw tools/xc/lib/xc_rrobin.c -3fbba6dcoGq9hQlksrBUfC2P5F6sGg tools/xc/lib/xc_vbd.c -3fbba6dc38q-ioRlwSR_quw4G3qUeQ tools/xc/lib/xc_vif.c 3fbd0a3dTwnDcfdw0-v46dPbX98zDw tools/xc/py/Makefile 3fbd0a42l40lM0IICw2jXbQBVZSdZg tools/xc/py/Xc.c 3fbd0a40yT6G3M9hMpaz5xTUdl0E4g tools/xc/py/setup.py @@ -279,7 +267,6 @@ 404f1b91uzXgPOtIhs8UZPGbZvlHfg xen/arch/x86_64/Rules.mk 3ddb79bdff-gj-jFGKjOejeHLqL8Lg xen/common/Makefile 3e397e66AyyD5fYraAySWuwi9uqSXg xen/common/ac_timer.c -3ddb79bdrqnW93GR9gZk1OJe1qK-iQ xen/common/brlock.c 4022a73c_BbDFd2YJ_NQYVvKX5Oz7w xen/common/debug-linux.c 3fa152581E5KhrAtqZef2Sr5NKTz4w xen/common/debug.c 3ddb79bdLX_P6iB7ILiblRLWvebapg xen/common/dom0_ops.c @@ -291,11 +278,9 @@ 3e4cd9d8LAAghUY0hNIK72uc2ch_Nw xen/common/keyhandler.c 3ddb79bduhSEZI8xa7IbGQCpap5y2A xen/common/lib.c 3ddb79bdS39UXxUtZnaScie83-7VTQ xen/common/memory.c -3ddb79bdN51qpRC-6bOH-v5hl_AK6A xen/common/network.c 3ddb79bdD4SLmmdMD7yLW5HcUWucXw xen/common/page_alloc.c 3e54c38dkHAev597bPr71-hGzTdocg xen/common/perfc.c 4051bcecFeq4DE70p4zGO5setf47CA xen/common/physdev.c -4006e659i9j-doVxY7DKOGU4XVin1Q xen/common/rbtree.c 3ddb79bdHqdQpATqC0rmUZNbsb6L6A xen/common/resource.c 4064773cJ31vZt-zhbSoxqft1Jaw0w xen/common/sched_atropos.c 40589968dD2D1aejwSOvrROg7fOvGQ xen/common/sched_bvt.c @@ -312,103 +297,10 @@ 40715b2bi9gU43-cYzlmPDgreYQchw xen/drivers/acpi/Makefile 40715b2bDxNCz5LFV8FAXihmYJZFUQ xen/drivers/acpi/acpi_ksyms.c 40715b2cNVOegtvyft_AHFKJYRprfA xen/drivers/acpi/tables.c -40715b2br9s0oHQxre-rWM8KSpa0RA xen/drivers/acpi_ksyms.c -3ddb79beWzgPS8ozf2BL2g3ZkiWhhQ xen/drivers/block/Makefile -3ddb79be04dyXzyXqDbMRS_1funwXQ xen/drivers/block/blkpg.c -400be8220k_K_8-GFqi_KI7DtnG4wg xen/drivers/block/cciss.c -400be822U6rx3myRzz2fCoqMbQTKjQ xen/drivers/block/cciss.h -400be822MTFR0Ue17PyB6X6vU5lmzw xen/drivers/block/cciss_cmd.h -400be822o5kwrfC5oI8PY4A-GoXeoA xen/drivers/block/cciss_scsi.c -400be822HEA8ZLcYGxSl_CprccJDkg xen/drivers/block/cciss_scsi.h -3ddb79beME_0abStePF6fU8XLuQnWw xen/drivers/block/elevator.c -3ddb79beNQVrdGyoI4njXhgAjD6a4A xen/drivers/block/genhd.c -3ddb79beyWwLRP_BiM2t1JKgr_plEw xen/drivers/block/ll_rw_blk.c -3e4a8cb7RhubVgsPwO7cK0pgAN8WCQ xen/drivers/block/xen_block.c -3e5d129asHNyZOjBKTkqs-9AFzxemA xen/drivers/block/xen_vbd.c -3e9c248afxxsnAzIt2na7Ej24yNFzg xen/drivers/cdrom/Makefile -3e9c248ajUkn2W3n4vgm72Hp2ftZ8A xen/drivers/cdrom/cdrom.c 3e4a8cb7alzQCDKS7MlioPoHBKYkdQ xen/drivers/char/Makefile 4049e6bfNSIq7s7OV-Bd69QD0RpR2Q xen/drivers/char/console.c 3e4a8cb7WmiYdC-ASGiCSG_CL8vsqg xen/drivers/char/keyboard.c 3e4a8cb7nMChlro4wvOBo76n__iCFA xen/drivers/char/serial.c -3ddb79bdhcqD9ebrslr0O0oHqTiiXg xen/drivers/ide/Makefile -3e9c248aCM6Lex1Am8_NJIeesN4kKg xen/drivers/ide/ide-cd.c -3e9c248aFfSNR_hl-WQBbv-R9CTgzg xen/drivers/ide/ide-cd.h -3ddb79bdErDn_WC3G-fWxKNR3viLnA xen/drivers/ide/ide-disk.c -3ddb79bdIPNW36FrlId94jTXaW8HoA xen/drivers/ide/ide-dma.c -3ddb79be5Ysvhn4se_Z-LQY_hI6UPw xen/drivers/ide/ide-features.c -3ddb79bdh1ohsWYRH_KdaXr7cqs12w xen/drivers/ide/ide-geometry.c -3ddb79bdYcxXT-2UEaDcG0Ic4MIK1g xen/drivers/ide/ide-pci.c -3ddb79bdOXTbcImJo8DwmlNX88k78Q xen/drivers/ide/ide-probe.c -3ddb79bdDWFwINnKn29RlFDwGJhjYg xen/drivers/ide/ide-taskfile.c -3e4a8d40XMqvT05EwZwJg1HMsFDUBA xen/drivers/ide/ide-xen.c -3ddb79bdkDY1bSOYkToP1Cc49VdBxg xen/drivers/ide/ide.c -3ddb79bdPyAvT_WZTAFhaX0jp-yXSw xen/drivers/ide/ide_modes.h -3e4a8d401aSwOzCScQXR3lsmNlAwUQ xen/drivers/ide/piix.c -3fcdb64eEYjJwVTDdATmditDL6GreA xen/drivers/message/fusion/Config.in -3fcdb64ee9dgWh8x0sR-le703mbyaQ xen/drivers/message/fusion/Makefile -3fcdb64e_e-c5pG7ev4Ebpc1TSyqBA xen/drivers/message/fusion/isense.h -3fcdb64ekZ3CRQVYOvtBY-jcdWLxFg xen/drivers/message/fusion/linux_compat.h -3fcdb64e_ar-OB7FSvk8aIOQeETx-Q xen/drivers/message/fusion/lsi/fc_log.h -3fcdb64eSDjgD3W3MypMOae50Fe4BA xen/drivers/message/fusion/lsi/mpi.h -3fcdb64e9iLTo9Etbdxrr_dC-1bb5g xen/drivers/message/fusion/lsi/mpi_cnfg.h -3fcdb64egl5jNkfKyC7Co6NNNsfY4w xen/drivers/message/fusion/lsi/mpi_fc.h -3fcdb64edETmgJSw8KhkrQgyY67BTA xen/drivers/message/fusion/lsi/mpi_history.txt -3fcdb64eHxLXhIqEfYi8_UPf4j7Kng xen/drivers/message/fusion/lsi/mpi_init.h -3fcdb64fG8Mm8Jt4Il-jsVcKTfRTpg xen/drivers/message/fusion/lsi/mpi_ioc.h -3fcdb64fjt9nuJga7t5dRK1-FCrURQ xen/drivers/message/fusion/lsi/mpi_lan.h -3fcdb64fnnYbvcLibeLTNR81zMi8Lw xen/drivers/message/fusion/lsi/mpi_raid.h -3fcdb64fpRM8NpPlaagM3dQ1jW3YNQ xen/drivers/message/fusion/lsi/mpi_targ.h -3fcdb64fXgeuSY_4Uy_OWSyjWlwnaQ xen/drivers/message/fusion/lsi/mpi_type.h -3fcdb64fQjcOsOCcCMQSBgA0kuttPA xen/drivers/message/fusion/mptbase.c -3fcdb64fz22QsBDCmRylGcrYz2X2YQ xen/drivers/message/fusion/mptbase.h -3fcdb64fqClM55cDs-jlCSJ7fhqmqg xen/drivers/message/fusion/mptscsih.c -3fcdb64fTVgpQj9UQw5aHN_eUHlzGQ xen/drivers/message/fusion/mptscsih.h -3fcdb64fl9djvIFAYQozgMVDUNPIkQ xen/drivers/message/fusion/scsi3.h -3ddb79bfMlOcWUwjtg6oMYhGySHDDw xen/drivers/net/3c59x.c -404470fdR6z_nJ196-p-JE76DGEvvg xen/drivers/net/8139too.c -3ddb79c0tWiE8xIFHszxipeVCGKTSA xen/drivers/net/Makefile -3f0c4247730LYUgz3p5ziYqy-s_glw xen/drivers/net/SUPPORTED_CARDS -3ddb79bfU-H1Hms4BuJEPPydjXUEaQ xen/drivers/net/Space.c -3f574c95CQT9g-GDSJJ4YqiwCEQ72Q xen/drivers/net/dummy.c -3f0c428e41JP96bh-J0jnX59vJyUeQ xen/drivers/net/e100/LICENSE -3f0c428es_xrZnnZQXXHhjzuqj9CTg xen/drivers/net/e100/Makefile -3f0c428eCEnifr-r6XCZKUkzIEHdYw xen/drivers/net/e100/e100.h -3f0c428eyYDJIqvO7W_QbgnGnbgPqA xen/drivers/net/e100/e100_config.c -3f0c428e-NvNXlOyIw8H3YllFL6lfA xen/drivers/net/e100/e100_config.h -3f0c428ecPXSlA_4rp_-6O09uQqHbg xen/drivers/net/e100/e100_eeprom.c -3f0c428eWlXUzaulDjS1UpUP7Ckejg xen/drivers/net/e100/e100_main.c -3f0c428eKW1sEaCen-HIMUwMtQXnVQ xen/drivers/net/e100/e100_phy.c -3f0c428eR00XnyLIZKb5H5QF_I9QDg xen/drivers/net/e100/e100_phy.h -3f0c428eII-G2i_Qv_aCQjLzHcDKEQ xen/drivers/net/e100/e100_test.c -3f0c428eJ_gqbOFzS3bWSI7geA--Eg xen/drivers/net/e100/e100_ucode.h -3e4540ccS4bfbx9rLiLElP0F1OVwZA xen/drivers/net/e1000/LICENSE -3e4540ccXG6af_6-u0IiKKvtdGHJyA xen/drivers/net/e1000/Makefile -3e4540ccoY2eo4VIkbR4sCOj0bVzSA xen/drivers/net/e1000/e1000.h -3e4540ccvUz0j2ejQ9Z9djEGc93wRA xen/drivers/net/e1000/e1000_ethtool.c -3e4540ccjqsc94nU3C4w3ZJaxFZFjA xen/drivers/net/e1000/e1000_hw.c -3e4540cczrrQVyyj-s1-viyX1kMUlA xen/drivers/net/e1000/e1000_hw.h -3e4540ccvQ9Dtoh9tV-L3ULUwN9X7g xen/drivers/net/e1000/e1000_main.c -3e4540cc3t7_y-YLeyMG2pX9xtdXPA xen/drivers/net/e1000/e1000_osdep.h -3e4540cct_8Ig-Y1W_vM2gS_u7mC0A xen/drivers/net/e1000/e1000_param.c -3fd76772aP8tdbOsmFpbsSr90TP0YA xen/drivers/net/e1000/kcompat.c -3fd76773I15-QqRK-uQAdEd-cBFVZw xen/drivers/net/e1000/kcompat.h -3ddb79bfKvn9mt0kofpkw0QaWjxO6A xen/drivers/net/net_init.c -3f0c428exbF4as5zi8GyGyDSUITmxg xen/drivers/net/pcnet32.c -3ddb79bf_CBcu3QWYwq4bNAOnM2RqQ xen/drivers/net/setup.c -3e45a0c6u66EL2AI36eLOmf_abXs7g xen/drivers/net/tg3.c -3e45a0c6yrXj5pmQT0PvVSJ01YLABQ xen/drivers/net/tg3.h -3f0c428e0tn3ZknveWidRNtHYcyHzw xen/drivers/net/tulip/21142.c -3f0c428esCXQWoJHSJ5zUZ7iQc_rlQ xen/drivers/net/tulip/ChangeLog -3f0c428eB8pVjwDolFZDa0YZMQW1rw xen/drivers/net/tulip/Makefile -3f0c428el4rtJgjSoK_K04g5Udg2Tw xen/drivers/net/tulip/eeprom.c -3f0c428eYyDHq5AnrB60p3g0uXWYwA xen/drivers/net/tulip/interrupt.c -3f0c428eI99GG-HH2aQCIQ4tyISe8w xen/drivers/net/tulip/media.c -3f0c428eErjUSQiTzPJJlSrR0ORJog xen/drivers/net/tulip/pnic.c -3f0c428eyyo0-aI_fj4gDBiNYe-Idw xen/drivers/net/tulip/pnic2.c -3f0c428eZQhoTueBPxOO5YbuzoTofw xen/drivers/net/tulip/timer.c -3f0c428eoDFGJZJrBRnA7918Yovt0A xen/drivers/net/tulip/tulip.h -3f0c428e46klSV-upTm6D8tCdzQs8Q xen/drivers/net/tulip/tulip_core.c 3ddb79beUWngyIhMHgyPtuTem4o4JA xen/drivers/pci/Makefile 3ddb79beU9td0Mnm0VUMklerBa37qQ xen/drivers/pci/compat.c 3ddb79beHkGQE58z5t5gyUCYiwOxvw xen/drivers/pci/gen-devlist.c @@ -421,109 +313,6 @@ 3ddb79bfl1H1arbB0pzAEC2uPmY_3g xen/drivers/pci/setup-irq.c 3ddb79bfJaf0bkE1Y67bnll8-kjEPg xen/drivers/pci/setup-res.c 3ddb79bfIcCWJsBDNcQQE3ok2Azn-Q xen/drivers/pci/syscall.c -3facce119oL2_kMylnMRUQlTsUw-OA xen/drivers/scsi/BusLogic.c -3facce12hrTrkdXJQR0MjOG3ud0K0A xen/drivers/scsi/BusLogic.h -3facce0dDkxv278IqO4gxypPDiw3Ow xen/drivers/scsi/FlashPoint.c.inc -3ddb79be3kwzyKagpMHGoXZFdan7dg xen/drivers/scsi/Makefile -3e564137sVLmo7rTnKLNzLSCvuUz8g xen/drivers/scsi/aacraid/Makefile -3e5641379FXvLDjV-0OrRNOBTwL_Lw xen/drivers/scsi/aacraid/README -3e564137MAHzHSRYoWGNmIferNjFVA xen/drivers/scsi/aacraid/TODO -3e564137QLUGVlcwTpnMYATKahDmCg xen/drivers/scsi/aacraid/aachba.c -3e564137Tm_t6rMYyxFtnY9yo_abMg xen/drivers/scsi/aacraid/aacraid.h -3e564137AtfQtRJZiS9B00To0AmKSg xen/drivers/scsi/aacraid/commctrl.c -3e564137a9aOGMOFgQ5CYQJBOD3DvQ xen/drivers/scsi/aacraid/comminit.c -3e564137fw_bPuKcvVi0qwntc_RB-Q xen/drivers/scsi/aacraid/commsup.c -3e564137iEHmY_e6xGZ7TLsjy5yS-g xen/drivers/scsi/aacraid/dpcsup.c -3e564137taxQbEVa39h3mEVLFxRydQ xen/drivers/scsi/aacraid/linit.c -3e564137vmALxpfK7vNINqEklSmQ1A xen/drivers/scsi/aacraid/rx.c -3e564137EuYUJgvqnOunPERWxnp_mw xen/drivers/scsi/aacraid/sa.c -3e7f358amV8HBe1Cyges2wsBHfh-cw xen/drivers/scsi/aic7xxx/Makefile -3e7f358al_wJbBvERr7NzW5mLuTRpQ xen/drivers/scsi/aic7xxx/aic7770.c -3e7f358aCCSVBMcmsh64S7CCVIgVQg xen/drivers/scsi/aic7xxx/aic7770_osm.c -3e7f358aLNpSseMxk_DY6a-Ln9OyGg xen/drivers/scsi/aic7xxx/aic79xx.h -3e7f358ad7OR21rmyDNJfKyE1X1sxg xen/drivers/scsi/aic7xxx/aic79xx.reg -3e7f358a9Z39hG2enFVrNWjizvwthg xen/drivers/scsi/aic7xxx/aic79xx.seq -3e7f358aKzcs8L8XYcLD0bF8FrmtVg xen/drivers/scsi/aic7xxx/aic79xx_core.c -3e7f358ayrUAqJ9b8GxdRJQr5Po1zg xen/drivers/scsi/aic7xxx/aic79xx_host.h -3e7f358aVDB0b6qAf__XSDPubVM1RA xen/drivers/scsi/aic7xxx/aic79xx_inline.h -3e7f358aQFjWLEqUzd98Gy8z86vk2g xen/drivers/scsi/aic7xxx/aic79xx_osm.c -3e7f358adsO2cSMKATR_r9hPZ9KCUg xen/drivers/scsi/aic7xxx/aic79xx_osm.h -3e7f358avC9liKFAUFFRyWlVIIGZ2g xen/drivers/scsi/aic7xxx/aic79xx_osm_pci.c -3e7f358aQ0ZpnmwtiT16raQb1QSGKQ xen/drivers/scsi/aic7xxx/aic79xx_pci.c -3e7f358af6BTct89-TCB31Rtw8NzQg xen/drivers/scsi/aic7xxx/aic79xx_proc.c -3e7f358aK54-KV7Wj014Yf5FnWo2VQ xen/drivers/scsi/aic7xxx/aic79xx_reg.h -3e7f358aZiCJAqEBttlmEDCMFcM-aA xen/drivers/scsi/aic7xxx/aic79xx_seq.h -3e7f358aPZhHGnMNAM3YCQcBIAnCfw xen/drivers/scsi/aic7xxx/aic7xxx.h -3e7f358aZRO8yoMXVLyDUyoFhsFnBw xen/drivers/scsi/aic7xxx/aic7xxx.reg -3e7f358aADKO4MLsWISX0-d2hpru0g xen/drivers/scsi/aic7xxx/aic7xxx.seq -3e7f358aB5x1ljQE7yWp63nvcfp4Mg xen/drivers/scsi/aic7xxx/aic7xxx_93cx6.c -3e7f358aDCmrU2Q35Ay765z7gWTSmQ xen/drivers/scsi/aic7xxx/aic7xxx_93cx6.h -3e7f358aXOqteLTeEH8XOlAeLPbXuQ xen/drivers/scsi/aic7xxx/aic7xxx_core.c -3e7f358adzSPC6RFtP4NyHB2PoT-Ew xen/drivers/scsi/aic7xxx/aic7xxx_host.h -3e7f358asCAiwyDZ1fBaiIxABh30BA xen/drivers/scsi/aic7xxx/aic7xxx_inline.h -3e7f358aDwj6BY9tJ4spPuZnQqBiew xen/drivers/scsi/aic7xxx/aic7xxx_osm.c -3e7f358anOWiWoFl7baNMWjqsPiYzg xen/drivers/scsi/aic7xxx/aic7xxx_osm.h -3e7f358a1sRjg-XkczIXH7dUX8K1ZA xen/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c -3e7f358aj6uST9miAVmB9WNLqAGkCA xen/drivers/scsi/aic7xxx/aic7xxx_pci.c -3e7f358aCwRu3fI3NP7MQsLRpWV73w xen/drivers/scsi/aic7xxx/aic7xxx_proc.c -3e7f358aW8xbofV6VW2L8FPphmAXvg xen/drivers/scsi/aic7xxx/aic7xxx_reg.h -3e7f358ayQSlIZBIAGWYXBM5dtAFrA xen/drivers/scsi/aic7xxx/aic7xxx_seq.h -3e7f358acS9V8TbKLuyxvw-0SlgYmQ xen/drivers/scsi/aic7xxx/aicasm/Makefile -3e7f358arkcPw6k1oC2Wrp5TXFbovg xen/drivers/scsi/aic7xxx/aicasm/aicasm.c -3e7f358aF_JURnGn6q5V951k1TTnLg xen/drivers/scsi/aic7xxx/aicasm/aicasm.h -3e7f358a2aopdml6zsS1HF9oibF5RQ xen/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y -3e7f358a2JQOz8ASFfi2oV5-k127RA xen/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h -3e7f358a5kU_nwzMFh0xbG96yLgJKA xen/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y -3e7f358a4FjmeDBfwgynM1InqFQ2nA xen/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l -3e7f358aoXDwp6vozr1x2Fwvb7x5BQ xen/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l -3e7f358aUYJHOx790PiwQiJIlYECbA xen/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c -3e7f358aPn8RK1slOgqrXC12x0FlgQ xen/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h -3e7f358a6BujWXsqDmuts6N_A8dGhw xen/drivers/scsi/aic7xxx/cam.h -3e7f358anzaPhN49caB9AqMVw0_XKQ xen/drivers/scsi/aic7xxx/queue.h -3e7f358a3ggaLCNsnuArANSmNT1t2A xen/drivers/scsi/aic7xxx/scsi_iu.h -3e7f358arKN4VFRDcEasaM6Wj_VwTg xen/drivers/scsi/aic7xxx/scsi_message.h -3e56411aOLzeD5CRbuXquOrX0lRijw xen/drivers/scsi/constants.c -3ddb79beXZxwKh7cGyPfr40bhDyRrA xen/drivers/scsi/constants.h -3e564120ZeinH9nf3IVSerB80T7dHg xen/drivers/scsi/hosts.c -3ddb79beGiGljlTNq_kRnCBZECgC9Q xen/drivers/scsi/hosts.h -3e8827bdE8FgsI-QxZ4zKzYTRmACOQ xen/drivers/scsi/megaraid.c -3e8827bdEMIzjyF9OHnDRmJGp_O68g xen/drivers/scsi/megaraid.h -3ddb79bexarQo1tQ541PPUyK9HXNDA xen/drivers/scsi/scsi.c -3ddb79beBOiYxQUiWTHosepRlJyuGA xen/drivers/scsi/scsi.h -3ddb79beVTYJj6_KMxYLJmCP7p9MuQ xen/drivers/scsi/scsi_dma.c -3ddb79beDrImFCFGgB_GLgUbeuHjog xen/drivers/scsi/scsi_error.c -3ddb79bepDvUltYDsInaUsH9lII9Sw xen/drivers/scsi/scsi_ioctl.c -3ddb79berPStE_-ILQHgcl1BLDLywA xen/drivers/scsi/scsi_lib.c -3ddb79beRXjB7_nNUbJMIRyjDmeByQ xen/drivers/scsi/scsi_merge.c -3e56412a_O2cnz-e36volrKvofGe-Q xen/drivers/scsi/scsi_module.c.inc -3faf8290uGugKdeePovsS2MCkm6NYw xen/drivers/scsi/scsi_obsolete.c -3ddb79beQgG_st0eBZUX8AQI7kBkHA xen/drivers/scsi/scsi_obsolete.h -3ddb79beK65cNRldY0CFGXjZ3-A74Q xen/drivers/scsi/scsi_proc.c -3ddb79beeIuwGDE0Ldl8wy6mt86Bag xen/drivers/scsi/scsi_queue.c -3ddb79beQVxjXLLSY896cqce3j6Ehg xen/drivers/scsi/scsi_scan.c -3ddb79beVrSvakLg_9MSo22vJ_TGrA xen/drivers/scsi/scsi_syms.c -3ddb79beC6PIqDEaxAfO3bLKcmMLeA xen/drivers/scsi/scsicam.c -3ddb79bedAG8DPsr3S1N4IASxUuBug xen/drivers/scsi/sd.c -3ddb79beA27dAK0xtNh4k6SJniKnlA xen/drivers/scsi/sd.h -3fd432fb0fW430_7mzTegOyjjFB-Iw xen/drivers/scsi/sym53c8xx_2/ChangeLog.txt -3fd432fbzXmGBq60nilWbfafyDXrtQ xen/drivers/scsi/sym53c8xx_2/Documentation.txt -3fd432fbVpHp1vv8A6GQBZQnKMFS7Q xen/drivers/scsi/sym53c8xx_2/Makefile -3fd432fbAOAdNUuPUOlRmT723POpnQ xen/drivers/scsi/sym53c8xx_2/sym53c8xx.h -3fd432fbO-kotluBDNXwt3AJ_yiuAw xen/drivers/scsi/sym53c8xx_2/sym_conf.h -3fd432fbFiHM-XyIhDIU3wLuVTEe8Q xen/drivers/scsi/sym53c8xx_2/sym_defs.h -3fd432fbc6E0FNW2CfDhY18WV4fIcA xen/drivers/scsi/sym53c8xx_2/sym_fw.c -3fd432fbEYdbqLET81nisgPiVVlRtA xen/drivers/scsi/sym53c8xx_2/sym_fw.h -3fd432fbiymG2mfG5k2HHz1w1hPcHQ xen/drivers/scsi/sym53c8xx_2/sym_fw1.h -3fd432fbITAwK8BK6-6c8yPfxpxROg xen/drivers/scsi/sym53c8xx_2/sym_fw2.h -3fd432fbr5_OuwNUNPjLfbDdS9iMLw xen/drivers/scsi/sym53c8xx_2/sym_glue.c -3fd432fbRLKL6mW2K5n_pHiTnMxA3Q xen/drivers/scsi/sym53c8xx_2/sym_glue.h -3fd432fbkCURaCXa7kKXvnHI1Y0B6A xen/drivers/scsi/sym53c8xx_2/sym_hipd.c -3fd432fbpPgJcz6YrCxWNx934bK7BQ xen/drivers/scsi/sym53c8xx_2/sym_hipd.h -3fd432fbHyYMzfNAB_5mKGOvh1HTrg xen/drivers/scsi/sym53c8xx_2/sym_malloc.c -3fd432fbFBLr85q2xIgdvDR7S2kvlw xen/drivers/scsi/sym53c8xx_2/sym_misc.c -3fd432fbOri8Ue9-QTi6X-WviC2JYA xen/drivers/scsi/sym53c8xx_2/sym_misc.h -3fd432fbM9qma6nz_-GWRpZ7v1pqrg xen/drivers/scsi/sym53c8xx_2/sym_nvram.c -40715b2bZb6VFx6gPELSuItqa-E84w xen/drivers/tables.c 40715b2cFpte_UNWnBZW0Du7z9AhTQ xen/include/acpi/acconfig.h 40715b2cEQWX-PaxEH30qI48K1krnQ xen/include/acpi/acdebug.h 40715b2c_7j-oy3ZNAuqE3IFNPzArg xen/include/acpi/acdisasm.h @@ -563,7 +352,6 @@ 3ddb79c3QJYWr8LLGdonLbWmNb9pQQ xen/include/asm-i386/apicdef.h 3ddb79c3OiG9eTsi9Dy3F_OkuRAzKA xen/include/asm-i386/atomic.h 3ddb79c3rM-Ote0Xn6Ytg8Y6YqAG-A xen/include/asm-i386/bitops.h -3ddb79c3pXaTAGGWSIZF9EnRV5PlRw xen/include/asm-i386/byteorder.h 3ddb79c3KhTI0F_Iw_hRL9QEyOVK-g xen/include/asm-i386/cache.h 404f1b920OQVnrbnXnySS-WxrH9Wzw xen/include/asm-i386/config.h 3ddb79c2LLt11EQHjrd6sB7FUqvFfA xen/include/asm-i386/cpufeature.h @@ -582,7 +370,6 @@ 3ddb79c3otbjpnqFDSzSeD0J-0xcwg xen/include/asm-i386/ide.h 3ddb79c3fQ_O3o5NHK2N8AJdk0Ea4Q xen/include/asm-i386/io.h 3ddb79c2TKeScYHQZreTdHqYNLbehQ xen/include/asm-i386/io_apic.h -3ddb79c3S9Tga4XZRPrD4-aN3XIV6w xen/include/asm-i386/ioctl.h 3ddb79c2L7rTlFzazOLW1XuSZefpFw xen/include/asm-i386/irq.h 404f1b93OjLO4bFfBXYNaJdIqlNz-Q xen/include/asm-i386/ldt.h 3ddb79c3I98vWcQR8xEo34JMJ4Ahyw xen/include/asm-i386/mc146818rtc.h @@ -612,7 +399,6 @@ 404f1b95_OZH-rw_durHSa_Kgdo95A xen/include/asm-x86_64/apicdef.h 404f1b967UWSPkB0cwT9v-rilNzkHw xen/include/asm-x86_64/atomic.h 404f1b97UDomt73PizniyrCaxVRkXQ xen/include/asm-x86_64/bitops.h -404f1b98bhUJO45dacAaIRV7OE7P3A xen/include/asm-x86_64/byteorder.h 404f1b99W-dMUlFpsvt--tVpQvNgEQ xen/include/asm-x86_64/cache.h 404f1b9b_phpQlRnyiWqP6RodfZDpg xen/include/asm-x86_64/config.h 404f1b9cz7UV611DK6CTY1ZAiwGtTw xen/include/asm-x86_64/cpufeature.h @@ -630,7 +416,6 @@ 404f1ba8yxfnHH0NWC1B-wmd6bK2wg xen/include/asm-x86_64/ide.h 404f1ba9_7NIylhSRmokesN8TNIiNg xen/include/asm-x86_64/io.h 404f1baaiXXy7vChbzKmluSyJ5LWIw xen/include/asm-x86_64/io_apic.h -404f1bab38sz6Fd2LyLPDD4mMYgd7w xen/include/asm-x86_64/ioctl.h 404f1baceMqjaYFs7oZoNsPkaZJ0WQ xen/include/asm-x86_64/irq.h 404f1badfXZJZ2sU8sh9PS2EZvd19Q xen/include/asm-x86_64/ldt.h 404f1bae_yI5vMg-_k4EySMERbbz2Q xen/include/asm-x86_64/mc146818rtc.h @@ -660,90 +445,48 @@ 400304fcmRQmDdFYEzDh0wcBba9alg xen/include/hypervisor-ifs/COPYING 404f1bc68SXxmv0zQpXBWGrCzSyp8w xen/include/hypervisor-ifs/arch-i386/hypervisor-if.h 404f1bc7IwU-qnH8mJeVu0YsNGMrcw xen/include/hypervisor-ifs/arch-x86_64/hypervisor-if.h -3ddb79c2YTaZwOqWin9-QNgHge5RVw xen/include/hypervisor-ifs/block.h 3ddb79c2PMeWTK86y4C3F4MzHw4A1g xen/include/hypervisor-ifs/dom0_ops.h 403cd194j2pyLqXD8FJ-ukvZzkPenw xen/include/hypervisor-ifs/event_channel.h 3ddb79c25UE59iu4JJcbRalx95mvcg xen/include/hypervisor-ifs/hypervisor-if.h 3ead095dE_VF-QA88rl_5cWYRWtRVQ xen/include/hypervisor-ifs/kbd.h -3ddb79c2oRPrzClk3zbTkRHlpumzKA xen/include/hypervisor-ifs/network.h 4051db79512nOCGweabrFWO2M2h5ng xen/include/hypervisor-ifs/physdev.h 40589968wmhPmV5-ENbBYmMjnedgKw xen/include/hypervisor-ifs/sched_ctl.h 404f3d2eR2Owk-ZcGOx9ULGHg3nrww xen/include/hypervisor-ifs/trace.h -3f0d22cbroqp_BkoDPwkfRJhaw1LiQ xen/include/hypervisor-ifs/vbd.h -3ddb79c4qbCoOFHrv9sCGshbWzBVlQ xen/include/scsi/scsi.h -3ddb79c4R4iVwqIIeychVQYmIH4FUg xen/include/scsi/scsi_ioctl.h -3ddb79c4yw_mfd4Uikn3v_IOPRpa1Q xen/include/scsi/scsicam.h -3ddb79c4HKPMLvDBP9LxzPi_szVxGA xen/include/scsi/sg.h 3e397e66m2tO3s-J8Jnr7Ws_tGoPTg xen/include/xen/ac_timer.h 40715b2epYl2jBbxzz9CI2rgIca7Zg xen/include/xen/acpi.h -3ddb79c0nTsjSpVK4ZVTI9WwN24xtQ xen/include/xen/blk.h -3ddb79c0dVhTHLsv6CPTf4baKix4mA xen/include/xen/blkdev.h -3ddb79c18ePBgitnOs7GiOCFilODVw xen/include/xen/blkpg.h -3ddb79c1oOjpQbp68MW7yiUpoi-S-w xen/include/xen/brlock.h -3ddb79c1x7Ie3kifu7dQRx8y7HVyvA xen/include/xen/byteorder/big_endian.h -3ddb79c1qFXOEX1eD0yXJ_gsGkUt8w xen/include/xen/byteorder/generic.h -3ddb79c1VbwFALNpgx6uC_iZKFHD-A xen/include/xen/byteorder/little_endian.h -3ddb79c1VvNRMM35bpdZMekirCXP-A xen/include/xen/byteorder/pdp_endian.h -3ddb79c116WbJV8bwGZXFFJy_GNNvw xen/include/xen/byteorder/swab.h -3ddb79c1pwmlw8VXW8aaSKAVGVmjDA xen/include/xen/byteorder/swabb.h 3ddb79c0c0cX_DZE209-Bb-Rx1v-Aw xen/include/xen/cache.h -3e9c248aEG_nCngztiFmv5CfayNkcA xen/include/xen/cdrom.h 3f840f12CkbYSlwMrY2S11Mpyxg7Nw xen/include/xen/compiler.h 3ddb79c259jh8hE7vre_8NuE7nwNSA xen/include/xen/config.h 3eb165e0eawr3R-p2ZQtSdLWtLRN_A xen/include/xen/console.h -3f0c428eIwGr7n9fj4FkBdX2YvA_Rw xen/include/xen/crc32.h 3ddb79c1V44RD26YqCUm-kqIupM37A xen/include/xen/ctype.h 3ddb79c05DdHQ0UxX_jKsXdR4QlMCA xen/include/xen/delay.h -3ddb79c1uaWQZj551j1O0B5z8AnHOg xen/include/xen/elevator.h 3ddb79c2O729EttZTYu1c8LcsUO_GQ xen/include/xen/elf.h 3ddb79c0HIghfBF8zFUdmXhOU8i6hA xen/include/xen/errno.h -3ddb79c0rMjudDKkJku_mkm0J-BZgw xen/include/xen/etherdevice.h -3ddb79c0T3X07lFnM9OSE-W5bqIDSQ xen/include/xen/ethtool.h 3ddb79c1W0lQca8gRV7sN6j3iY4Luw xen/include/xen/event.h -3ddb79c1J4I_AjNflZL-1c1jOIlSyg xen/include/xen/genhd.h -3ddb79c1i-chIoeniqgYwMM3EgaR5w xen/include/xen/hdreg.h -3ddb79c12GuUuaxBKiMuwf-Qvuwpng xen/include/xen/hdsmart.h -3ddb79c0MM575N4YvMSiw9EqKH4JDA xen/include/xen/ide.h -3ddb79c1yHLp08JhgPxIMcZ8DwN9hg xen/include/xen/if.h -3ddb79c1RCWOkWPQRzbYVTX_e-E7CA xen/include/xen/if_ether.h -3ddb79c2IYah7z7hkzPyOiG8szKkyw xen/include/xen/if_packet.h -3e4540ccefnCkeqtD_dW_CBOjXUSYw xen/include/xen/if_vlan.h -3df0af1c-QrOEqpPHq4uL3NZzCeJCg xen/include/xen/in.h 3ddb79c0GurNF9tDWqQbAwJFH8ugfA xen/include/xen/init.h 3ddb79c1Vi5VleJAOKHAlY0G2zAsgw xen/include/xen/interrupt.h -3ddb79c2J6EnruiygRhBCgftzMzTeQ xen/include/xen/ioctl.h 3ddb79c1nzaWu8NoF4xCCMSFJR4MlA xen/include/xen/ioport.h 3ddb79c2qAxCOABlkKtD8Txohe-qEw xen/include/xen/irq.h 3ddb79c2b3qe-6Ann09FqZBF4IrJaQ xen/include/xen/irq_cpustat.h -3ddb79c11w_O7z7YZJnzuDSxaK5LlA xen/include/xen/kdev_t.h 3e4540ccPHqIIv2pvnQ1gV8LUnoHIg xen/include/xen/kernel.h 3e4cd9d8elj_7EgAs9Of56RQ2Yq_4g xen/include/xen/keyhandler.h 3ddb79c1NfYlOrWNqgZkj9EwtFfJow xen/include/xen/lib.h 3ddb79c18Ajy7micDGQQfJ0zWgEHtA xen/include/xen/list.h -3ddb79c0_s2_wgV0cA6tztEaeyy1NA xen/include/xen/major.h -3ddb79c1fsWuKI2sGlW5bqoG2lPVNA xen/include/xen/mii.h 3ddb79c1gs2VbLbQlw0dcDUXYIepDA xen/include/xen/mm.h 3ddb79c13p9iHn1XAp0IS1qvj4yDsg xen/include/xen/module.h 3ddb79c1ieLZfGSFwfvvSQ2NK1BMSg xen/include/xen/multiboot.h -3ec92e46saEJq7v1vgEJD3HZSufSBg xen/include/xen/net_headers.h -3ddb79c0CLfAlJLg1ohdPD-Jjn-jxg xen/include/xen/netdevice.h -3e4540ccaugeWGdOuphJKj6WFw1jkw xen/include/xen/notifier.h 3ddb79c2Fg44_PBPVxHSC0gTOMq4Ow xen/include/xen/pci.h 3ddb79c0MOVXq8qZDQRGb6z64_xAwg xen/include/xen/pci_ids.h 3e54c38dlSCVdyVM4PKcrSfzLLxWUQ xen/include/xen/perfc.h 3e54c38de9SUSYSAwxDf_DwkpAnQFA xen/include/xen/perfc_defn.h 3ddb79c04nQVR3EYM5L4zxDV_MCo1g xen/include/xen/prefetch.h -4006e65fWMwLqcocgik6wbF0Eeh0Og xen/include/xen/rbtree.h 3e4540ccU1sgCx8seIMGlahmMfv7yQ xen/include/xen/reboot.h 40589969nPq3DMzv24RDb5LXE9brHw xen/include/xen/sched-if.h 3ddb79c0LzqqS0LhAQ50ekgj4oGl7Q xen/include/xen/sched.h 403a06a7H0hpHcKpAiDe5BPnaXWTlA xen/include/xen/serial.h 405b8599BsDsDwKEJLS0XipaiQW3TA xen/include/xen/shadow.h -3ddb79c0VDeD-Oft5eNfMneTU3D1dQ xen/include/xen/skbuff.h 3ddb79c14dXIhP7C2ahnoD08K90G_w xen/include/xen/slab.h 3ddb79c09xbS-xxfKxuV3JETIhBzmg xen/include/xen/smp.h -3ddb79c1-yIt89RT02wIPp2xDR8YjQ xen/include/xen/socket.h -3ddb79c2V2P9F2xMCzDJ9vbUofSg_Q xen/include/xen/sockios.h 3ddb79c2iIcESrDAB8samy_yAh6olQ xen/include/xen/spinlock.h 3e7f358aMtFMUVvN_Zjg5qvEJIqEBA xen/include/xen/string.h 3ddb79c0BnA20PbgmuMPSGIBljNRQw xen/include/xen/time.h @@ -752,15 +495,7 @@ 3ddb79c2e2C14HkndNEJlYwXaPrF5A xen/include/xen/tqueue.h 403a3edbG9K5uZjuY19_LORbQGmFbA xen/include/xen/trace.h 3ddb79c1-kVvF8cVa0k3ZHDdBMj01Q xen/include/xen/types.h -3f055a3dwldYR102YcSuBaxIf9t3Jw xen/include/xen/vbd.h 3e8827bdaqPeZAWGVOwswgY9bWSx4g xen/include/xen/version.h -3ddb79c2Ae5KpzhC9LCYG7mP_Vi4Aw xen/include/xen/vif.h -3ddb79c4YQCQ6r0xNLLu0jfbM7pVmA xen/net/Makefile -3ddb79c4AkfDkTCw0comx4L8wsUOMg xen/net/dev.c -3ddb79c4x1L_soh8b-r_1jQW_37Icw xen/net/dev_mcast.c -3ddb79c4KZhNxUuYJ7lul8cc-wRkyg xen/net/devinit.c -3ddb79c4NSDwiQ-AmrYdxcRAwLPzwQ xen/net/eth.c -3ddb79c4TZj1wXPKQt36O72SddtBNQ xen/net/skbuff.c 3ddb79c4x8dvwPtzclghWAKFWpEBFA xen/tools/Makefile 3ddb79c4yGZ7_22QAFFwPzqP4NSHwA xen/tools/elf-reloc.c 3eb3c87fc79FXLA6R9TvdBJNTvQDwA xen/tools/figlet/LICENSE diff --git a/docs/HOWTOs/Xen-HOWTO b/docs/HOWTOs/Xen-HOWTO index ed990c9b4b..0c64ecd409 100644 --- a/docs/HOWTOs/Xen-HOWTO +++ b/docs/HOWTOs/Xen-HOWTO @@ -49,12 +49,6 @@ to 'n' or off): applications. For more information see the XenDebugger-HOWTO. - old_drivers=y -- Enable the old hardware-device architecture, in - which network and block devices are managed by - Xen. The new (and default) model requires such - devices to be managed by a suitably-privileged - guest OS (e.g., within domain 0). - perfc=y -- Enable performance-counters for significant events within Xen. The counts can be reset or displayed on Xen's console via console control keys. diff --git a/extras/mini-os/h/hypervisor.h b/extras/mini-os/h/hypervisor.h index 500dcdf99e..52bc13a947 100644 --- a/extras/mini-os/h/hypervisor.h +++ b/extras/mini-os/h/hypervisor.h @@ -12,8 +12,6 @@ #include /* include the hypervisor interface */ -#include -#include #include #include "../../../tools/xend/lib/domain_controller.h" @@ -112,17 +110,6 @@ static __inline__ int HYPERVISOR_set_callbacks( return ret; } -static __inline__ int HYPERVISOR_net_io_op(netop_t *op) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_net_io_op), - "b" (op) : "memory" ); - - return ret; -} - static __inline__ int HYPERVISOR_fpu_taskswitch(void) { int ret; @@ -214,28 +201,6 @@ static __inline__ int HYPERVISOR_dom0_op(void *dom0_op) return ret; } -static __inline__ int HYPERVISOR_network_op(void *network_op) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_network_op), - "b" (network_op) : "memory" ); - - return ret; -} - -static __inline__ int HYPERVISOR_block_io_op(unsigned int op) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_block_io_op), - "b" (op) : "memory" ); - - return ret; -} - static __inline__ int HYPERVISOR_set_debugreg(int reg, unsigned long value) { int ret; diff --git a/linux-2.4.26-xen-sparse/Documentation/Configure.help b/linux-2.4.26-xen-sparse/Documentation/Configure.help deleted file mode 100644 index e39bed91d6..0000000000 --- a/linux-2.4.26-xen-sparse/Documentation/Configure.help +++ /dev/null @@ -1,29164 +0,0 @@ -# Maintained by: -# Eric S. Raymond -# Steven Cole -# -# Translations of this file available on the WWW: -# -# - Japanese, maintained by the JF Project , at -# -# - Russian, by , at -# -# - French, by Pierre Tane , at -# -# - Polish, by Dominik Mierzejewski , at -# -# - German, by SuSE, at . This patch -# also includes infrastructure to support different languages. -# - Catalan, by Antoni Bella , at -# -# -# Information about what a kernel is, what it does, how to patch and -# compile it and much more is contained in the Kernel-HOWTO, available -# at . Before you start -# compiling, make sure that you have the necessary versions of all -# programs and libraries required to compile and run this kernel; they -# are listed in the . Make sure to read the -# toplevel kernel README file as well. -# -# Format of this file: descriptionvariablehelp text. -# The help texts may contain empty lines, but every non-empty line must -# be indented two positions. Order of the help texts does not matter, -# however, no variable should be documented twice: if it is, only the -# first occurrence will be used. We try to keep the help texts of related -# variables close together. Lines starting with `#' are ignored. To be -# nice to menuconfig, limit your line length to 70 characters. Use emacs' -# kfill.el to edit and ispell.el to spell check this file or you lose. -# -# Comments of the form "# Choice:" followed by a menu name are used -# internally by the maintainers' consistency-checking tools. -# -# If you add a help text to this file, please try to be as gentle as -# possible. Don't use unexplained acronyms and generally write for the -# hypothetical ignorant but intelligent user who has just bought a PC, -# removed Windows, installed Linux and is now recompiling the kernel -# for the first time. Tell them what to do if they're unsure. Technical -# information should go in a README in the Documentation directory. -# -# Mention all the relevant READMEs and HOWTOs in the help text. -# Make them file URLs relative to the top level of the source tree so -# that help browsers can turn them into hotlinks. All URLs should be -# surrounded by <>. -# -# Repetitions are fine since the help texts are not meant to be read -# in sequence. It is good style to include URLs pointing to more -# detailed technical information, pictures of the hardware, etc. -# -# The most important thing to include in a help entry is *motivation*. -# Explain why someone configuring a kernel might want to select your -# option. -# -# All this was shamelessly stolen from numerous different sources. Many -# thanks to all the contributors. Feel free to use these help texts in -# your own kernel configuration tools. The texts are copyrighted (c) -# 1995-2000 by Axel Boldt and many others and are governed by the GNU -# General Public License. - -Prompt for development and/or incomplete code/drivers -CONFIG_EXPERIMENTAL - Some of the various things that Linux supports (such as network - drivers, file systems, network protocols, etc.) can be in a state - of development where the functionality, stability, or the level of - testing is not yet high enough for general use. This is usually - known as the "alpha-test" phase among developers. If a feature is - currently in alpha-test, then the developers usually discourage - uninformed widespread use of this feature by the general public to - avoid "Why doesn't this work?" type mail messages. However, active - testing and use of these systems is welcomed. Just be aware that it - may not meet the normal level of reliability or it may fail to work - in some special cases. Detailed bug reports from people familiar - with the kernel internals are usually welcomed by the developers - (before submitting bug reports, please read the documents - , , , - , and - in the kernel source). - - This option will also make obsoleted drivers available. These are - drivers that have been replaced by something else, and/or are - scheduled to be removed in a future kernel release. - - Unless you intend to help test and develop a feature or driver that - falls into this category, or you have a situation that requires - using these features, you should probably say N here, which will - cause the configurator to present you with fewer choices. If - you say Y here, you will be offered the choice of using features or - drivers that are currently considered to be in the alpha-test phase. - -Prompt for drivers for obsolete features and hardware -CONFIG_OBSOLETE - Obsolete drivers have usually been replaced by more recent software - that can talk to the same hardware. Obsolete hardware is things - like MGA monitors that you are very unlikely to see on today's - systems. - -Prompt for advanced kernel configuration options -CONFIG_ADVANCED_OPTIONS - This option will enable prompting for a variety of advanced kernel - configuration options. These options can cause the kernel to not - work if they are set incorrectly, but can be used to optimize certain - aspects of kernel memory management. - - Unless you know what you are doing you *should not* enable this option. - -Symmetric Multi-Processing support -CONFIG_SMP - This enables support for systems with more than one CPU. If you have - a system with only one CPU, like most personal computers, say N. If - you have a system with more than one CPU, say Y. - - If you say N here, the kernel will run on single and multiprocessor - machines, but will use only one CPU of a multiprocessor machine. If - you say Y here, the kernel will run on many, but not all, - single machines. On a singleprocessor machine, the kernel - will run faster if you say N here. - - Note that if you say Y here and choose architecture "586" or - "Pentium" under "Processor family", the kernel will not work on 486 - architectures. Similarly, multiprocessor kernels for the "PPro" - architecture may not work on all Pentium based boards. - - People using multiprocessor machines who say Y here should also say - Y to "Enhanced Real Time Clock Support", below. The "Advanced Power - Management" code will be disabled if you say Y here. - - See also the , - , , - and the SMP-HOWTO available at - . - - If you don't know what to do here, say N. - -Maximum number of CPUs -CONFIG_NR_CPUS - This allows you to specify the maximum number of CPUs which this - kernel will support. The maximum supported value is 32 and the - mimimum value which makes sense is 2. - - This is purely to save memory - each supported CPU adds - approximately eight kilobytes to the kernel image. - -Intel or compatible 80x86 processor -CONFIG_X86 - This is Linux's home port. Linux was originally native to the Intel - 386, and runs on all the later x86 processors including the Intel - 486, 586, Pentiums, and various instruction-set-compatible chips by - AMD, Cyrix, and others. - -Alpha processor -CONFIG_ALPHA - The Alpha is a 64-bit general-purpose processor designed and - marketed by the Digital Equipment Corporation of blessed memory, now - Compaq. Alpha Linux dates from 1995-1996 and was the first non-x86 - port. The Alpha Linux project has a home page at - . - -32-bit Sun Sparc -CONFIG_SPARC32 - SPARC is a family of RISC microprocessors designed and marketed by - Sun Microsystems, incorporated. They are very widely found in Sun - workstations and clones. This port covers the original 32-bit SPARC; - it is old and stable and usually considered one of the "big three" - along with the Intel and Alpha ports. The UltraLinux project - maintains both the SPARC32 and SPARC64 ports; its web page is - available at . - -64-bit Sun Sparc -CONFIG_SPARC64 - SPARC is a family of RISC microprocessors designed and marketed by - Sun Microsystems, incorporated. This port covers the newer 64-bit - UltraSPARC. The UltraLinux project maintains both the SPARC32 and - SPARC64 ports; its web page is available at - . - -Power PC processor -CONFIG_PPC - The PowerPC is a very capable 32-bit RISC processor from Motorola, - the successor to their 68000 and 88000 series. It powers recent - Macintoshes and also a widely-used series of single-board computers - from Motorola. The Linux PowerPC port has a home page at - . - -Motorola 68K processors -CONFIG_M68K - The Motorola 68K microprocessors are now obsolete, having been - superseded by the PowerPC line also from Motorola. But they powered - the first wave of workstation hardware in the 1980s, including Sun - workstations; they were also the basis of the original Amiga and - later Atari personal computers. A lot of this hardware is still - around. The m68k project has a home page at - . - -ARM processors -CONFIG_ARM - The ARM series is a line of low-power-consumption RISC chip designs - licensed by ARM ltd and targeted at embedded applications and - handhelds such as the Compaq IPAQ. ARM-based PCs are no longer - manufactured, but legacy ARM-based PC hardware remains popular in - Europe. There is an ARM Linux project with a web page at - . - -SuperH processors -CONFIG_SUPERH - The SuperH is a RISC processor targeted for use in embedded systems - and consumer electronics; it was also used in the Sega Dreamcast - gaming console. The SuperH port has a home page at - . - -IA64 processors, including Intel Itanium -CONFIG_IA64 - The Itanium is Intel's 64-bit successor to the 32-bit X86 line. As - of early 2001 it is not yet in widespread production use. The Linux - IA-64 project has a home page at . - -HP PA-RISC processor -CONFIG_PARISC - The PA-RISC microprocessor is a RISC chip designed by - Hewlett-Packard and used in their line of workstations. The PA-RISC - Linux project has a home page at . - -IBM System/390 -CONFIG_S390 - Linux now runs on the venerable System/390 mainframe from IBM, in a - guest partition under VM. In fact, over 40,000 simultaneous Linux - images have been run on a single mainframe! The S390 Linux project - has a home page at . - -Axis Communications ETRAX 100LX embedded network CPU -CONFIG_CRIS - Linux has been ported to run on the Axis Communications ETRAX 100LX - CPU and the single-board computers built around it, targeted for - network and embedded applications. For more information see the - Axis Communication site, . - -Unsynced TSC support -CONFIG_X86_TSC_DISABLE - This option is used for getting Linux to run on a NUMA multi-node - boxes, laptops and other systems suffering from unsynced TSCs or - TSC drift, which can cause gettimeofday to return non-monotonic values. - Choosing this option will disable the CONFIG_X86_TSC optimization, - and allows you to then specify "notsc" as a boot option regardless of - which processor you have compiled for. - - NOTE: If your system hangs when init should run, you are probably - using a i686 compiled glibc which reads the TSC without checking for - availability. Boot without "notsc" and install a i386 compiled glibc - to solve the problem. - - If unsure, say N. - -Multiquad support for NUMAQ systems -CONFIG_X86_NUMAQ - This option is used for getting Linux to run on a (IBM/Sequent) NUMA - multiquad box. This changes the way that processors are bootstrapped, - and uses Clustered Logical APIC addressing mode instead of Flat Logical. - You will need a new lynxer.elf file to flash your firmware with - send - email to Martin.Bligh@us.ibm.com - -Support for IBM Summit (EXA) systems -CONFIG_X86_SUMMIT - This option is needed for IBM systems that use the Summit/EXA chipset. - (EXA: Extendable Xseries Architecture)In particular, it is needed for - the x440 (even for the 4-CPU model). - - If you don't have this computer, you may safely say N. - -IO-APIC support on uniprocessors -CONFIG_X86_UP_IOAPIC - An IO-APIC (I/O Advanced Programmable Interrupt Controller) is an - SMP-capable replacement for PC-style interrupt controllers. Most - SMP systems and a small number of uniprocessor systems have one. - If you have a single-CPU system with an IO-APIC, you can say Y here - to use it. If you say Y here even though your machine doesn't have - an IO-APIC, then the kernel will still run with no slowdown at all. - - If you have a system with several CPUs, you do not need to say Y - here: the IO-APIC will be used automatically. - -Local APIC Support on Uniprocessors -CONFIG_X86_UP_APIC - A local APIC (Advanced Programmable Interrupt Controller) is an - integrated interrupt controller in the CPU. If you have a single-CPU - system which has a processor with a local APIC, you can say Y here to - enable and use it. If you say Y here even though your machine doesn't - have a local APIC, then the kernel will still run with no slowdown at - all. The local APIC supports CPU-generated self-interrupts (timer, - performance counters), and the NMI watchdog which detects hard lockups. - - If you have a system with several CPUs, you do not need to say Y - here: the local APIC will be used automatically. - -Kernel math emulation -CONFIG_MATH_EMULATION - Linux can emulate a math coprocessor (used for floating point - operations) if you don't have one. 486DX and Pentium processors have - a math coprocessor built in, 486SX and 386 do not, unless you added - a 487DX or 387, respectively. (The messages during boot time can - give you some hints here ["man dmesg"].) Everyone needs either a - coprocessor or this emulation. - - If you don't have a math coprocessor, you need to say Y here; if you - say Y here even though you have a coprocessor, the coprocessor will - be used nevertheless. (This behaviour can be changed with the kernel - command line option "no387", which comes handy if your coprocessor - is broken. Try "man bootparam" or see the documentation of your boot - loader (lilo or loadlin) about how to pass options to the kernel at - boot time.) This means that it is a good idea to say Y here if you - intend to use this kernel on different machines. - - More information about the internals of the Linux math coprocessor - emulation can be found in . - - If you are not sure, say Y; apart from resulting in a 66 KB bigger - kernel, it won't hurt. - -Timer and CPU usage LEDs -CONFIG_LEDS - If you say Y here, the LEDs on your machine will be used - to provide useful information about your current system status. - - If you are compiling a kernel for a NetWinder or EBSA-285, you will - be able to select which LEDs are active using the options below. If - you are compiling a kernel for the EBSA-110 or the LART however, the - red LED will simply flash regularly to indicate that the system is - still functional. It is safe to say Y here if you have a CATS - system, but the driver will do nothing. - -Timer LED -CONFIG_LEDS_TIMER - If you say Y here, one of the system LEDs (the green one on the - NetWinder, the amber one on the EBSA285, or the red one on the LART) - will flash regularly to indicate that the system is still - operational. This is mainly useful to kernel hackers who are - debugging unstable kernels. - - The LART uses the same LED for both Timer LED and CPU usage LED - functions. You may choose to use both, but the Timer LED function - will overrule the CPU usage LED. - -CPU usage LED -CONFIG_LEDS_CPU - If you say Y here, the red LED will be used to give a good real - time indication of CPU usage, by lighting whenever the idle task - is not currently executing. - - The LART uses the same LED for both Timer LED and CPU usage LED - functions. You may choose to use both, but the Timer LED function - will overrule the CPU usage LED. - -Kernel FP software completion -CONFIG_MATHEMU - This option is required for IEEE compliant floating point arithmetic - on the Alpha. The only time you would ever not say Y is to say M in - order to debug the code. Say Y unless you know what you are doing. - -# Choice: himem -High Memory support -CONFIG_NOHIGHMEM - Linux can use up to 64 Gigabytes of physical memory on x86 systems. - However, the address space of 32-bit x86 processors is only 4 - Gigabytes large. That means that, if you have a large amount of - physical memory, not all of it can be "permanently mapped" by the - kernel. The physical memory that's not permanently mapped is called - "high memory". - - If you are compiling a kernel which will never run on a machine with - more than 960 megabytes of total physical RAM, answer "off" here (default - choice and suitable for most users). This will result in a "3GB/1GB" - split: 3GB are mapped so that each process sees a 3GB virtual memory - space and the remaining part of the 4GB virtual memory space is used - by the kernel to permanently map as much physical memory as - possible. - - If the machine has between 1 and 4 Gigabytes physical RAM, then - answer "4GB" here. - - If more than 4 Gigabytes is used then answer "64GB" here. This - selection turns Intel PAE (Physical Address Extension) mode on. - PAE implements 3-level paging on IA32 processors. PAE is fully - supported by Linux, PAE mode is implemented on all recent Intel - processors (Pentium Pro and better). NOTE: If you say "64GB" here, - then the kernel will not boot on CPUs that don't support PAE! - - The actual amount of total physical memory will either be auto - detected or can be forced by using a kernel command line option such - as "mem=256M". (Try "man bootparam" or see the documentation of your - boot loader (grub, lilo or loadlin) about how to pass options to the - kernel at boot time.) - - If unsure, say "off". - -4GB -CONFIG_HIGHMEM4G - Select this if you have a 32-bit processor and between 1 and 4 - gigabytes of physical RAM. - -64GB -CONFIG_HIGHMEM64G - Select this if you have a 32-bit processor and more than 4 - gigabytes of physical RAM. - -HIGHMEM I/O support -CONFIG_HIGHIO - If you want to be able to do I/O to high memory pages, say Y. - Otherwise low memory pages are used as bounce buffers causing a - degrade in performance. - -OOM killer support -CONFIG_OOM_KILLER - This option selects the kernel behaviour during total out of memory - condition. - - The default behaviour is to, as soon as no freeable memory and no swap - space are available, kill the task which tries to allocate memory. - The default behaviour is very reliable. - - If you select this option, as soon as no freeable memory is available, - the kernel will try to select the "best" task to be killed. - - If unsure, say N. - -Normal floppy disk support -CONFIG_BLK_DEV_FD - If you want to use the floppy disk drive(s) of your PC under Linux, - say Y. Information about this driver, especially important for IBM - Thinkpad users, is contained in . - That file also contains the location of the Floppy driver FAQ as - well as location of the fdutils package used to configure additional - parameters of the driver at run time. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called floppy.o. If you want to compile it as a - module, say M here and read . - -iSeries Virtual I/O Disk Support -CONFIG_VIODASD - If you are running on an iSeries system and you want to use - virtual disks created and managed by OS/400, say Y. - -iSeries Virtual I/O Disk IDE Emulation -CONFIG_VIODASD_IDE - This causes the iSeries virtual disks to look like IDE disks. - If you have programs or utilities that only support certain - kinds of disks, this option will cause iSeries virtual disks - to pretend to be IDE disks, which may satisfy the program. - -Support for PowerMac floppy -CONFIG_MAC_FLOPPY - If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple) - floppy controller, say Y here. Most commonly found in PowerMacs. - -RAM disk support -CONFIG_BLK_DEV_RAM - Saying Y here will allow you to use a portion of your RAM memory as - a block device, so that you can make file systems on it, read and - write to it and do all the other things that you can do with normal - block devices (such as hard drives). It is usually used to load and - store a copy of a minimal root file system off of a floppy into RAM - during the initial install of Linux. - - Note that the kernel command line option "ramdisk=XX" is now - obsolete. For details, read . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M and read . The module will be - called rd.o. - - Most normal users won't need the RAM disk functionality, and can - thus say N here. - -Default RAM disk size -CONFIG_BLK_DEV_RAM_SIZE - The default value is 4096. Only change this if you know what are - you doing. If you are using IBM S/390, then set this to 8192. - -Initial RAM disk (initrd) support -CONFIG_BLK_DEV_INITRD - The initial RAM disk is a RAM disk that is loaded by the boot loader - (loadlin or lilo) and that is mounted as root before the normal boot - procedure. It is typically used to load modules needed to mount the - "real" root file system, etc. See - for details. - -Embed root filesystem ramdisk into the kernel -CONFIG_EMBEDDED_RAMDISK - Select this option if you want to build the ramdisk image into the - the final kernel binary. - -Filename of gziped ramdisk image -CONFIG_EMBEDDED_RAMDISK_IMAGE - This is the filename of the ramdisk image to be built into the - kernel. Relative pathnames are relative to arch/mips/ramdisk/. - The ramdisk image is not part of the kernel distribution; you must - provide one yourself. - -Loopback device support -CONFIG_BLK_DEV_LOOP - Saying Y here will allow you to use a regular file as a block - device; you can then create a file system on that block device and - mount it just as you would mount other block devices such as hard - drive partitions, CD-ROM drives or floppy drives. The loop devices - are block special device files with major number 7 and typically - called /dev/loop0, /dev/loop1 etc. - - This is useful if you want to check an ISO 9660 file system before - burning the CD, or if you want to use floppy images without first - writing them to floppy. Furthermore, some Linux distributions avoid - the need for a dedicated Linux partition by keeping their complete - root file system inside a DOS FAT file using this loop device - driver. - - The loop device driver can also be used to "hide" a file system in a - disk partition, floppy, or regular file, either using encryption - (scrambling the data) or steganography (hiding the data in the low - bits of, say, a sound file). This is also safe if the file resides - on a remote file server. If you want to do this, you will first have - to acquire and install a kernel patch from - , and then you need to - say Y to this option. - - Note that alternative ways to use encrypted file systems are - provided by the cfs package, which can be gotten from - , and the newer tcfs - package, available at . You do not need - to say Y here if you want to use one of these. However, using cfs - requires saying Y to "NFS file system support" below while using - tcfs requires applying a kernel patch. An alternative steganography - solution is provided by StegFS, also available from - . - - To use the loop device, you need the losetup utility and a recent - version of the mount program, both contained in the util-linux - package. The location and current version number of util-linux is - contained in the file . - - Note that this loop device has nothing to do with the loopback - device used for network connections from the machine to itself. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called loop.o. - - Most users will answer N here. - -Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL) -CONFIG_BLK_DEV_UMEM - Saying Y here will include support for the MM5415 family of - battery backed (Non-volatile) RAM cards. - - - The cards appear as block devices that can be partitioned into - as many as 15 partitions. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called umem.o. - - The umem driver has been allocated block major number 116. - See Documentation/devices.txt for recommended device naming. - -Network block device support -CONFIG_BLK_DEV_NBD - Saying Y here will allow your computer to be a client for network - block devices, i.e. it will be able to use block devices exported by - servers (mount file systems on them etc.). Communication between - client and server works over TCP/IP networking, but to the client - program this is hidden: it looks like a regular local file access to - a block device special file such as /dev/nd0. - - Network block devices also allows you to run a block-device in - userland (making server and client physically the same computer, - communicating using the loopback network device). - - Read for more information, especially - about where to find the server code, which runs in user space and - does not need special kernel support. - - Note that this has nothing to do with the network file systems NFS - or Coda; you can say N here even if you intend to use NFS or Coda. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called nbd.o. - - If unsure, say N. - -XenoLinux virtual block device support -CONFIG_XEN_VBD - Xen can export virtual block devices which map back to extents of - blocks on the physical partitions. This option is needed for - Linux to make use of such devices when running as a Xen guest. - - If unsure, say Y. - -Per partition statistics in /proc/partitions -CONFIG_BLK_STATS - If you say yes here, your kernel will keep statistical information - for every partition. The information includes things as numbers of - read and write accesses, the number of merged requests etc. - - This is required for the full functionality of sar(8) and interesting - if you want to do performance tuning, by tweaking the elevator, e.g. - - If unsure, say N. - -ATA/IDE/MFM/RLL support -CONFIG_IDE - If you say Y here, your kernel will be able to manage low cost mass - storage units such as ATA/(E)IDE and ATAPI units. The most common - cases are IDE hard drives and ATAPI CD-ROM drives. - - If your system is pure SCSI and doesn't use these interfaces, you - can say N here. - - Integrated Disk Electronics (IDE aka ATA-1) is a connecting standard - for mass storage units such as hard disks. It was designed by - Western Digital and Compaq Computer in 1984. It was then named - ST506. Quite a number of disks use the IDE interface. - - AT Attachment (ATA) is the superset of the IDE specifications. - ST506 was also called ATA-1. - - Fast-IDE is ATA-2 (also named Fast ATA), Enhanced IDE (EIDE) is - ATA-3. It provides support for larger disks (up to 8.4GB by means of - the LBA standard), more disks (4 instead of 2) and for other mass - storage units such as tapes and cdrom. UDMA/33 (aka UltraDMA/33) is - ATA-4 and provides faster (and more CPU friendly) transfer modes - than previous PIO (Programmed processor Input/Output) from previous - ATA/IDE standards by means of fast DMA controllers. - - ATA Packet Interface (ATAPI) is a protocol used by EIDE tape and - CD-ROM drives, similar in many respects to the SCSI protocol. - - SMART IDE (Self Monitoring, Analysis and Reporting Technology) was - designed in order to prevent data corruption and disk crash by - detecting pre hardware failure conditions (heat, access time, and - the like...). Disks built since June 1995 may follow this standard. - The kernel itself don't manage this; however there are quite a - number of user programs such as smart that can query the status of - SMART parameters disk. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ide.o. - - For further information, please read . - - If unsure, say Y. - -Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support -CONFIG_BLK_DEV_IDE - If you say Y here, you will use the full-featured IDE driver to - control up to ten ATA/IDE interfaces, each being able to serve a - "master" and a "slave" device, for a total of up to twenty ATA/IDE - disk/cdrom/tape/floppy drives. - - Useful information about large (>540 MB) IDE disks, multiple - interfaces, what to do if ATA/IDE devices are not automatically - detected, sound card ATA/IDE ports, module support, and other - topics, is contained in . For detailed - information about hard drives, consult the Disk-HOWTO and the - Multi-Disk-HOWTO, available from - . - - To fine-tune ATA/IDE drive/interface parameters for improved - performance, look for the hdparm package at - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read and - . The module will be called ide-mod.o. - Do not compile this driver as a module if your root file system (the - one containing the directory /) is located on an IDE device. - - If you have one or more IDE drives, say Y or M here. If your system - has no IDE drives, or if memory requirements are really tight, you - could say N here, and select the "Old hard disk driver" below - instead to save about 13 KB of memory in the kernel. - -Old hard disk (MFM/RLL/IDE) driver -CONFIG_BLK_DEV_HD_ONLY - There are two drivers for MFM/RLL/IDE hard disks. Most people use - the newer enhanced driver, but this old one is still around for two - reasons. Some older systems have strange timing problems and seem to - work only with the old driver (which itself does not work with some - newer systems). The other reason is that the old driver is smaller, - since it lacks the enhanced functionality of the new one. This makes - it a good choice for systems with very tight memory restrictions, or - for systems with only older MFM/RLL/ESDI drives. Choosing the old - driver can save 13 KB or so of kernel memory. - - If you are unsure, then just choose the Enhanced IDE/MFM/RLL driver - instead of this one. For more detailed information, read the - Disk-HOWTO, available from - . - -Use old disk-only driver on primary interface -CONFIG_BLK_DEV_HD_IDE - There are two drivers for MFM/RLL/IDE disks. Most people use just - the new enhanced driver by itself. This option however installs the - old hard disk driver to control the primary IDE/disk interface in - the system, leaving the new enhanced IDE driver to take care of only - the 2nd/3rd/4th IDE interfaces. Doing this will prevent you from - having an IDE/ATAPI CD-ROM or tape drive connected to the primary - IDE interface. Choosing this option may be useful for older systems - which have MFM/RLL/ESDI controller+drives at the primary port - address (0x1f0), along with IDE drives at the secondary/3rd/4th port - addresses. - - Normally, just say N here; you will then use the new driver for all - 4 interfaces. - -Include IDE/ATA-2 DISK support -CONFIG_BLK_DEV_IDEDISK - This will include enhanced support for MFM/RLL/IDE hard disks. If - you have a MFM/RLL/IDE disk, and there is no special reason to use - the old hard disk driver instead, say Y. If you have an SCSI-only - system, you can say N here. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ide-disk.o. Do not compile this driver as a module - if your root file system (the one containing the directory /) is - located on the IDE disk. If unsure, say Y. - -Use multi-mode by default -CONFIG_IDEDISK_MULTI_MODE - If you get this error, try to say Y here: - - hda: set_multmode: status=0x51 { DriveReady SeekComplete Error } - hda: set_multmode: error=0x04 { DriveStatusError } - - If in doubt, say N. - -PCMCIA IDE support -CONFIG_BLK_DEV_IDECS - Support for outboard IDE disks, tape drives, and CD-ROM drives - connected through a PCMCIA card. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - ide-cs.o - -Include IDE/ATAPI CD-ROM support -CONFIG_BLK_DEV_IDECD - If you have a CD-ROM drive using the ATAPI protocol, say Y. ATAPI is - a newer protocol used by IDE CD-ROM and TAPE drives, similar to the - SCSI protocol. Most new CD-ROM drives use ATAPI, including the - NEC-260, Mitsumi FX400, Sony 55E, and just about all non-SCSI - double(2X) or better speed drives. - - If you say Y here, the CD-ROM drive will be identified at boot time - along with other IDE devices, as "hdb" or "hdc", or something - similar (check the boot messages with dmesg). If this is your only - CD-ROM drive, you can say N to all other CD-ROM options, but be sure - to say Y or M to "ISO 9660 CD-ROM file system support". - - Note that older versions of LILO (LInux LOader) cannot properly deal - with IDE/ATAPI CD-ROMs, so install LILO 16 or higher, available from - . - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ide-cd.o. - -Include IDE/ATAPI TAPE support -CONFIG_BLK_DEV_IDETAPE - If you have an IDE tape drive using the ATAPI protocol, say Y. - ATAPI is a newer protocol used by IDE tape and CD-ROM drives, - similar to the SCSI protocol. If you have an SCSI tape drive - however, you can say N here. - - You should also say Y if you have an OnStream DI-30 tape drive; this - will not work with the SCSI protocol, until there is support for the - SC-30 and SC-50 versions. - - If you say Y here, the tape drive will be identified at boot time - along with other IDE devices, as "hdb" or "hdc", or something - similar, and will be mapped to a character device such as "ht0" - (check the boot messages with dmesg). Be sure to consult the - and files - for usage information. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ide-tape.o. - -Include IDE/ATAPI FLOPPY support -CONFIG_BLK_DEV_IDEFLOPPY - If you have an IDE floppy drive which uses the ATAPI protocol, - answer Y. ATAPI is a newer protocol used by IDE CD-ROM/tape/floppy - drives, similar to the SCSI protocol. - - The LS-120 and the IDE/ATAPI Iomega ZIP drive are also supported by - this driver. For information about jumper settings and the question - of when a ZIP drive uses a partition table, see - . - (ATAPI PD-CD/CDR drives are not supported by this driver; support - for PD-CD/CDR drives is available if you answer Y to - "SCSI emulation support", below). - - If you say Y here, the FLOPPY drive will be identified along with - other IDE devices, as "hdb" or "hdc", or something similar (check - the boot messages with dmesg). - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ide-floppy.o. - -AWARD Bios Work-Around -CONFIG_IDEDISK_STROKE - Should you have a system w/ an AWARD Bios and your drives are larger - than 32GB and it will not boot, one is required to perform a few OEM - operations first. The option is called "STROKE" because it allows - one to "soft clip" the drive to work around a barrier limit. For - Maxtor drives it is called "jumpon.exe". Please search Maxtor's - web-site for "JUMPON.EXE". IBM has a similar tool at: - . - - If you are unsure, say N here. - -Raw Access to Media -CONFIG_IDE_TASK_IOCTL - This is a direct raw access to the media. It is a complex but - elegant solution to test and validate the domain of the hardware and - perform below the driver data recover if needed. This is the most - basic form of media-forensics. - - If you are unsure, say N here. - -Use Taskfile I/O -CONFIG_IDE_TASKFILE_IO - This is the "Jewel" of the patch. It will go away and become the new - driver core. Since all the chipsets/host side hardware deal w/ their - exceptions in "their local code" currently, adoption of a - standardized data-transport is the only logical solution. - Additionally we packetize the requests and gain rapid performance and - a reduction in system latency. Additionally by using a memory struct - for the commands we can redirect to a MMIO host hardware in the next - generation of controllers, specifically second generation Ultra133 - and Serial ATA. - - Since this is a major transition, it was deemed necessary to make the - driver paths buildable in separate models. Therefore if using this - option fails for your arch then we need to address the needs for that - arch. - - If you want to test this functionality, say Y here. - -Force DMA -CONFIG_BLK_DEV_IDEDMA_FORCED - This is an old piece of lost code from Linux 2.0 Kernels. - - Generally say N here. - -DMA Only on Disks -CONFIG_IDEDMA_ONLYDISK - This is used if you know your ATAPI Devices are going to fail DMA - Transfers. - - Generally say N here. - -SCSI emulation support -CONFIG_BLK_DEV_IDESCSI - This will provide SCSI host adapter emulation for IDE ATAPI devices, - and will allow you to use a SCSI device driver instead of a native - ATAPI driver. - - This is useful if you have an ATAPI device for which no native - driver has been written (for example, an ATAPI PD-CD or CDR drive); - you can then use this emulation together with an appropriate SCSI - device driver. In order to do this, say Y here and to "SCSI support" - and "SCSI generic support", below. You must then provide the kernel - command line "hdx=scsi" (try "man bootparam" or see the - documentation of your boot loader (lilo or loadlin) about how to - pass options to the kernel at boot time) for devices if you want the - native EIDE sub-drivers to skip over the native support, so that - this SCSI emulation can be used instead. This is required for use of - CD-RW's. - - Note that this option does NOT allow you to attach SCSI devices to a - box that doesn't have a SCSI host adapter installed. - - If both this SCSI emulation and native ATAPI support are compiled - into the kernel, the native support will be used. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - ide-scsi.o - -Use the NOOP Elevator (WARNING) -CONFIG_BLK_DEV_ELEVATOR_NOOP - If you are using a raid class top-level driver above the ATA/IDE core, - one may find a performance boost by preventing a merging and re-sorting - of the new requests. - - If unsure, say N. - -ISA-PNP EIDE support -CONFIG_BLK_DEV_ISAPNP - If you have an ISA EIDE card that is PnP (Plug and Play) and - requires setup first before scanning for devices, say Y here. - - If unsure, say N. - -CMD640 chipset bugfix/support -CONFIG_BLK_DEV_CMD640 - The CMD-Technologies CMD640 IDE chip is used on many common 486 and - Pentium motherboards, usually in combination with a "Neptune" or - "SiS" chipset. Unfortunately, it has a number of rather nasty - design flaws that can cause severe data corruption under many common - conditions. Say Y here to include code which tries to automatically - detect and correct the problems under Linux. This option also - enables access to the secondary IDE ports in some CMD640 based - systems. - - This driver will work automatically in PCI based systems (most new - systems have PCI slots). But if your system uses VESA local bus - (VLB) instead of PCI, you must also supply a kernel boot parameter - to enable the CMD640 bugfix/support: "ide0=cmd640_vlb". (Try "man - bootparam" or see the documentation of your boot loader about how to - pass options to the kernel.) - - The CMD640 chip is also used on add-in cards by Acculogic, and on - the "CSA-6400E PCI to IDE controller" that some people have. For - details, read . - -CMD640 enhanced support -CONFIG_BLK_DEV_CMD640_ENHANCED - This option includes support for setting/autotuning PIO modes and - prefetch on CMD640 IDE interfaces. For details, read - . If you have a CMD640 IDE interface - and your BIOS does not already do this for you, then say Y here. - Otherwise say N. - -RZ1000 chipset bugfix/support -CONFIG_BLK_DEV_RZ1000 - The PC-Technologies RZ1000 IDE chip is used on many common 486 and - Pentium motherboards, usually along with the "Neptune" chipset. - Unfortunately, it has a rather nasty design flaw that can cause - severe data corruption under many conditions. Say Y here to include - code which automatically detects and corrects the problem under - Linux. This may slow disk throughput by a few percent, but at least - things will operate 100% reliably. - -Generic PCI IDE chipset support -CONFIG_BLK_DEV_IDEPCI - Say Y here for PCI systems which use IDE drive(s). - This option helps the IDE driver to automatically detect and - configure all PCI-based IDE interfaces in your system. - -Support for sharing PCI IDE interrupts -CONFIG_IDEPCI_SHARE_IRQ - Some ATA/IDE chipsets have hardware support which allows for - sharing a single IRQ with other cards. To enable support for - this in the ATA/IDE driver, say Y here. - - It is safe to say Y to this question, in most cases. - If unsure, say N. - -Generic PCI bus-master DMA support -CONFIG_BLK_DEV_IDEDMA_PCI - If your PCI system uses IDE drive(s) (as opposed to SCSI, say) and - is capable of bus-master DMA operation (most Pentium PCI systems), - you will want to say Y here to reduce CPU overhead. You can then use - the "hdparm" utility to enable DMA for drives for which it was not - enabled automatically. By default, DMA is not enabled automatically - for these drives, but you can change that by saying Y to the - following question "Use DMA by default when available". You can get - the latest version of the hdparm utility from - . - - Read the comments at the beginning of - and the file for more information. - - It is safe to say Y to this question. - -Good-Bad DMA Model-Firmware (WIP) -CONFIG_IDEDMA_NEW_DRIVE_LISTINGS - If you say Y here, the model and firmware revision of your drive - will be compared against a blacklist of buggy drives that claim to - be (U)DMA capable but aren't. This is a blanket on/off test with no - speed limit options. - - Straight GNU GCC 2.7.3/2.8.X compilers are known to be safe; - whereas, many versions of EGCS have a problem and miscompile if you - say Y here. - - If in doubt, say N. - -Attempt to HACK around Chipsets that TIMEOUT (WIP) -CONFIG_BLK_DEV_IDEDMA_TIMEOUT - If you say Y here, this is a NASTY UGLY HACK! - - We have to issue an abort and requeue the request DMA engine got - turned off by a goofy ASIC, and we have to clean up the mess, and - here is as good as any. Do it globally for all chipsets. - - If in doubt, say N. - -Boot off-board chipsets first support -CONFIG_BLK_DEV_OFFBOARD - Normally, IDE controllers built into the motherboard (on-board - controllers) are assigned to ide0 and ide1 while those on add-in PCI - cards (off-board controllers) are relegated to ide2 and ide3. - Answering Y here will allow you to reverse the situation, with - off-board controllers on ide0/1 and on-board controllers on ide2/3. - This can improve the usability of some boot managers such as lilo - when booting from a drive on an off-board controller. - - If you say Y here, and you actually want to reverse the device scan - order as explained above, you also need to issue the kernel command - line option "ide=reverse". (Try "man bootparam" or see the - documentation of your boot loader (lilo or loadlin) about how to - pass options to the kernel at boot time.) - - Note that, if you do this, the order of the hd* devices will be - rearranged which may require modification of fstab and other files. - - If in doubt, say N. - -Use PCI DMA by default when available -CONFIG_IDEDMA_PCI_AUTO - Prior to kernel version 2.1.112, Linux used to automatically use - DMA for IDE drives and chipsets which support it. Due to concerns - about a couple of cases where buggy hardware may have caused damage, - the default is now to NOT use DMA automatically. To revert to the - previous behaviour, say Y to this question. - - If you suspect your hardware is at all flakey, say N here. - Do NOT email the IDE kernel people regarding this issue! - - It is normally safe to answer Y to this question unless your - motherboard uses a VIA VP2 chipset, in which case you should say N. - -IGNORE word93 Validation BITS -CONFIG_IDEDMA_IVB - There are unclear terms in ATA-4 and ATA-5 standards how certain - hardware (an 80c ribbon) should be detected. Different interpretations - of the standards have been released in hardware. This causes problems: - for example, a host with Ultra Mode 4 (or higher) will not run - in that mode with an 80c ribbon. - - If you are experiencing compatibility or performance problems, you - MAY try to answering Y here. However, it does not necessarily solve - any of your problems, it could even cause more of them. - - It is normally safe to answer Y; however, the default is N. - -ATA Work(s) In Progress (EXPERIMENTAL) -CONFIG_IDEDMA_PCI_WIP - If you enable this you will be able to use and test highly - developmental projects. If you say N, the configurator will - simply skip those options. - - It is SAFEST to say N to this question. - -Asynchronous DMA support (EXPERIMENTAL) -CONFIG_BLK_DEV_ADMA - Please read the comments at the top of - . - -Pacific Digital A-DMA support (EXPERIMENTAL) -CONFIG_BLK_DEV_PDC_ADMA - Please read the comments at the top of . - -3ware Hardware ATA-RAID support -CONFIG_BLK_DEV_3W_XXXX_RAID - 3ware is the only hardware ATA-Raid product in Linux to date. - This card is 2,4, or 8 channel master mode support only. - SCSI support required!!! - - - - Please read the comments at the top of - . - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called 3w-xxxx.o. - -AEC62XX chipset support -CONFIG_BLK_DEV_AEC62XX - This driver adds up to 4 more EIDE devices sharing a single - interrupt. This add-on card is a bootable PCI UDMA controller. In - order to get this card to initialize correctly in some cases, you - should say Y here, and preferably also to "Use DMA by default when - available". - - The ATP850U/UF is an UltraDMA 33 chipset base. - The ATP860 is an UltraDMA 66 chipset base. - The ATP860M(acintosh) version is an UltraDMA 66 chipset base. - - Please read the comments at the top of . - If you say Y here, then say Y to "Use DMA by default when available" - as well. - -AEC62XX Tuning support -CONFIG_AEC62XX_TUNING - Please read the comments at the top of . - If unsure, say N. - -ALI M15x3 chipset support -CONFIG_BLK_DEV_ALI15X3 - This driver ensures (U)DMA support for ALI 1533, 1543 and 1543C - onboard chipsets. It also tests for Simplex mode and enables - normal dual channel support. - - If you say Y here, you also need to say Y to "Use DMA by default - when available", above. Please read the comments at the top of - . - - If unsure, say N. - -ALI M15x3 WDC support (DANGEROUS) -CONFIG_WDC_ALI15X3 - This allows for UltraDMA support for WDC drives that ignore CRC - checking. You are a fool for enabling this option, but there have - been requests. DO NOT COMPLAIN IF YOUR DRIVE HAS FS CORRUPTION, IF - YOU ENABLE THIS! No one will listen, just laugh for ignoring this - SERIOUS WARNING. - - Using this option can allow WDC drives to run at ATA-4/5 transfer - rates with only an ATA-2 support structure. - - SAY N! - -AMD and nVidia IDE support -CONFIG_BLK_DEV_AMD74XX - This driver adds explicit support for AMD-7xx and AMD-8111 chips - and also for the nVidia nForce chip. This allows the kernel to - change PIO, DMA and UDMA speeds and to configure the chip to - optimum performance. - - If you say Y here, you also need to say Y to "Use DMA by default - when available", above. - Please read the comments at the top of . - - If unsure, say N. - -AMD Viper ATA-66 Override support (WIP) -CONFIG_AMD74XX_OVERRIDE - This option auto-forces the ata66 flag. - This effect can be also invoked by calling "idex=ata66" - If unsure, say N. - -ATI IXP chipset IDE support -CONFIG_BLK_DEV_ATIIXP - This driver adds explicit support for ATI IXP chipset. - This allows the kernel to change PIO, DMA and UDMA speeds - and to configure the chip to optimum performance. - - Say Y here if you have an ATI IXP chipset IDE controller. - -CMD64X/CMD680 chipset support -CONFIG_BLK_DEV_CMD64X - Say Y here if you have an IDE controller which uses any of these - chipsets: CMD643, CMD646 and CMD648. - -Compaq Triflex IDE support -CONFIG_BLK_DEV_TRIFLEX - Say Y here if you have a Compaq Triflex IDE controller, such - as those commonly found on Compaq Pentium-Pro systems - - If you want to compile it as a module, say M here and read - . The module will be called - triflex.o. - -CY82C693 chipset support -CONFIG_BLK_DEV_CY82C693 - This driver adds detection and support for the CY82C693 chipset - used on Digital's PC-Alpha 164SX boards. - - If you say Y here, you need to say Y to "Use DMA by default - when available" as well. - -Cyrix CS5530 MediaGX chipset support -CONFIG_BLK_DEV_CS5530 - Include support for UDMA on the Cyrix MediaGX 5530 chipset. This - will automatically be detected and configured if found. - - It is safe to say Y to this question. - - People with SCSI-only systems should say N here. If unsure, say Y. - -HPT34X chipset support -CONFIG_BLK_DEV_HPT34X - This driver adds up to 4 more EIDE devices sharing a single - interrupt. The HPT343 chipset in its current form is a non-bootable - controller; the HPT345/HPT363 chipset is a bootable (needs BIOS FIX) - PCI UDMA controllers. This driver requires dynamic tuning of the - chipset during the ide-probe at boot time. It is reported to support - DVD II drives, by the manufacturer. - -HPT34X AUTODMA support (WIP) -CONFIG_HPT34X_AUTODMA - This is a dangerous thing to attempt currently! Please read the - comments at the top of . If you say Y - here, then say Y to "Use DMA by default when available" as well. - - If unsure, say N. - -HPT36X/37X chipset support -CONFIG_BLK_DEV_HPT366 - HPT366 is an Ultra DMA chipset for ATA-66. - HPT368 is an Ultra DMA chipset for ATA-66 RAID Based. - HPT370 is an Ultra DMA chipset for ATA-100. - HPT372 is an Ultra DMA chipset for ATA-133. - HPT374 is an Ultra DMA chipset for ATA-133. - - This driver adds up to 4 more EIDE devices sharing a single - interrupt. - - The HPT366 chipset in its current form is bootable. One solution - for this problem are special LILO commands for redirecting the - reference to device 0x80. The other solution is to say Y to "Boot - off-board chipsets first support" (CONFIG_BLK_DEV_OFFBOARD) unless - your mother board has the chipset natively mounted. Regardless one - should use the fore mentioned option and call at LILO or include - "ide=reverse" in LILO's append-line. - - This driver requires dynamic tuning of the chipset during the - ide-probe at boot. It is reported to support DVD II drives, by the - manufacturer. - -NS87415 chipset support (EXPERIMENTAL) -CONFIG_BLK_DEV_NS87415 - This driver adds detection and support for the NS87415 chip - (used in SPARC64, among others). - - Please read the comments at the top of . - -OPTi 82C621 chipset enhanced support (EXPERIMENTAL) -CONFIG_BLK_DEV_OPTI621 - This is a driver for the OPTi 82C621 EIDE controller. - Please read the comments at the top of . - -National SCx200 chipset support -CONFIG_BLK_DEV_SC1200 - This driver adds support for the built in IDE on the National - SCx200 series of embedded x86 "Geode" systems - - If you want to compile it as a module, say M here and read - . The module will be called - sc1200.o. - -ServerWorks OSB4/CSB5 chipset support -CONFIG_BLK_DEV_SVWKS - This driver adds PIO/(U)DMA support for the ServerWorks OSB4/CSB5 - chipsets. - -SGI IOC4 chipset support -CONFIG_BLK_DEV_SGIIOC4 - This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4 - chipset. Please say Y here, if you have an Altix System from - Silicon Graphics Inc. - -Intel PIIXn chipsets support -CONFIG_BLK_DEV_PIIX - This driver adds PIO mode setting and tuning for all PIIX IDE - controllers by Intel. Since the BIOS can sometimes improperly tune - PIO 0-4 mode settings, this allows dynamic tuning of the chipset - via the standard end-user tool 'hdparm'. - - Please read the comments at the top of . - - If you say Y here, you should also say Y to "PIIXn Tuning support", - below. - - If unsure, say N. - -PIIXn Tuning support -CONFIG_PIIX_TUNING - This driver extension adds DMA mode setting and tuning for all PIIX - IDE controllers by Intel. Since the BIOS can sometimes improperly - set up the device/adapter combination and speed limits, it has - become a necessity to back/forward speed devices as needed. - - Case 430HX/440FX PIIX3 need speed limits to reduce UDMA to DMA mode - 2 if the BIOS can not perform this task at initialization. - - If unsure, say N. - -PROMISE PDC20246/PDC20262/PDC20265/PDC20267/PDC20268 support -CONFIG_BLK_DEV_PDC202XX_OLD - Promise Ultra33 or PDC20246 - Promise Ultra66 or PDC20262 - Promise Ultra100 or PDC20265/PDC20267/PDC20268 - - This driver adds up to 4 more EIDE devices sharing a single - interrupt. This add-on card is a bootable PCI UDMA controller. Since - multiple cards can be installed and there are BIOS ROM problems that - happen if the BIOS revisions of all installed cards (three-max) do - not match, the driver attempts to do dynamic tuning of the chipset - at boot-time for max-speed. Ultra33 BIOS 1.25 or newer is required - for more than one card. This card may require that you say Y to - "Special UDMA Feature". - - If you say Y here, you need to say Y to "Use DMA by default when - available" as well. - - Please read the comments at the top of - . - - If unsure, say N. - -PROMISE PDC202{68|69|70|71|75|76|77} support -CONFIG_BLK_DEV_PDC202XX_NEW - Promise Ultra 100 TX2 [PDC20268] - Promise Ultra 133 PTX2 [PDC20269] - Promise FastTrak LP/TX2/TX4 [PDC20270] - Promise FastTrak TX2000 [PDC20271] - Promise MB Ultra 133 [PDC20275] - Promise MB FastTrak 133 [PDC20276] - Promise FastTrak 133 [PDC20277] - - This driver adds up to 4 more EIDE devices sharing a single - interrupt. This device is a bootable PCI UDMA controller. Since - multiple cards can be installed and there are BIOS ROM problems that - happen if the BIOS revisions of all installed cards (max of five) do - not match, the driver attempts to do dynamic tuning of the chipset - at boot-time for max speed. Ultra33 BIOS 1.25 or newer is required - for more than one card. - - If you say Y here, you need to say Y to "Use DMA by default when - available" as well. - - If unsure, say N. - -Special UDMA Feature -CONFIG_PDC202XX_BURST - This option causes the pdc202xx driver to enable UDMA modes on the - PDC202xx even when the PDC202xx BIOS has not done so. - - It was originally designed for the PDC20246/Ultra33, whose BIOS will - only setup UDMA on the first two PDC20246 cards. It has also been - used successfully on a PDC20265/Ultra100, allowing use of UDMA modes - when the PDC20265 BIOS has been disabled (for faster boot up). - - Please read the comments at the top of - . - - If unsure, say N. - -Special FastTrak Feature -CONFIG_PDC202XX_FORCE - For FastTrak enable overriding BIOS. - -SiS5513 chipset support -CONFIG_BLK_DEV_SIS5513 - This driver ensures (U)DMA support for SIS5513 chipset family based - mainboards. - - The following chipsets are supported: - ATA16: SiS5511, SiS5513 - ATA33: SiS5591, SiS5597, SiS5598, SiS5600 - ATA66: SiS530, SiS540, SiS620, SiS630, SiS640 - ATA100: SiS635, SiS645, SiS650, SiS730, SiS735, SiS740, - SiS745, SiS750 - - If you say Y here, you need to say Y to "Use DMA by default when - available" as well. - - Please read the comments at the top of . - -Silicon Image chipset support -CONFIG_BLK_DEV_SIIMAGE - This driver provides (U)DMA support for the SII3112 SATA controllers and - for the CMD/SI680 UDMA/DMA ATA controller. - -SLC90E66 chipset support -CONFIG_BLK_DEV_SLC90E66 - This driver ensures (U)DMA support for Victroy66 SouthBridges for - SMsC with Intel NorthBridges. This is an Ultra66 based chipset. - The nice thing about it is that you can mix Ultra/DMA/PIO devices - and it will handle timing cycles. Since this is an improved - look-a-like to the PIIX4 it should be a nice addition. - - If you say Y here, you need to say Y to "Use DMA by default when - available" as well. - - Please read the comments at the top of - . - -Winbond SL82c105 support -CONFIG_BLK_DEV_SL82C105 - If you have a Winbond SL82c105 IDE controller, say Y here to enable - special configuration for this chip. This is common on various CHRP - motherboards, but could be used elsewhere. If in doubt, say Y. - -Tekram TRM290 chipset support -CONFIG_BLK_DEV_TRM290 - This driver adds support for bus master DMA transfers - using the Tekram TRM290 PCI IDE chip. Volunteers are - needed for further tweaking and development. - Please read the comments at the top of . - -VIA82CXXX chipset support -CONFIG_BLK_DEV_VIA82CXXX - This allows you to configure your chipset for a better use while - running PIO/(U)DMA, it will allow you to enable efficiently the - second channel dma usage, as it may not be set by BIOS. It will try - to set fifo configuration at its best. It will allow you to get - information from /proc/ide/via provided you enabled "/proc file - system" support. - - Please read the comments at the top of - . - - If you say Y here, then say Y to "Use DMA by default when available" - as well. - - If unsure, say N. - -RapIDE interface support -CONFIG_BLK_DEV_IDE_RAPIDE - Say Y here if you want to support the Yellowstone RapIDE controller - manufactured for use with Acorn computers. - -Other IDE chipset support -CONFIG_IDE_CHIPSETS - Say Y here if you want to include enhanced support for various IDE - interface chipsets used on motherboards and add-on cards. You can - then pick your particular IDE chip from among the following options. - This enhanced support may be necessary for Linux to be able to - access the 3rd/4th drives in some systems. It may also enable - setting of higher speed I/O rates to improve system performance with - these chipsets. Most of these also require special kernel boot - parameters to actually turn on the support at runtime; you can find - a list of these in the file . - - People with SCSI-only systems can say N here. - -Generic 4 drives/port support -CONFIG_BLK_DEV_4DRIVES - Certain older chipsets, including the Tekram 690CD, use a single set - of I/O ports at 0x1f0 to control up to four drives, instead of the - customary two drives per port. Support for this can be enabled at - runtime using the "ide0=four" kernel boot parameter if you say Y - here. - -ALI M14xx support -CONFIG_BLK_DEV_ALI14XX - This driver is enabled at runtime using the "ide0=ali14xx" kernel - boot parameter. It enables support for the secondary IDE interface - of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster - I/O speeds to be set as well. See the files - and for - more info. - -DTC-2278 support -CONFIG_BLK_DEV_DTC2278 - This driver is enabled at runtime using the "ide0=dtc2278" kernel - boot parameter. It enables support for the secondary IDE interface - of the DTC-2278 card, and permits faster I/O speeds to be set as - well. See the and - files for more info. - -Holtek HT6560B support -CONFIG_BLK_DEV_HT6560B - This driver is enabled at runtime using the "ide0=ht6560b" kernel - boot parameter. It enables support for the secondary IDE interface - of the Holtek card, and permits faster I/O speeds to be set as well. - See the and - files for more info. - -PROMISE DC4030 support (EXPERIMENTAL) -CONFIG_BLK_DEV_PDC4030 - This driver provides support for the secondary IDE interface and - cache of Promise IDE chipsets, e.g. DC4030 and DC5030. This driver - is known to incur timeouts/retries during heavy I/O to drives - attached to the secondary interface. CD-ROM and TAPE devices are - not supported yet. This driver is enabled at runtime using the - "ide0=dc4030" kernel boot parameter. See the - and files - for more info. - -QDI QD65XX support -CONFIG_BLK_DEV_QD65XX - This driver is enabled at runtime using the "ide0=qd65xx" kernel - boot parameter. It permits faster I/O speeds to be set. See the - and for - more info. - -UMC 8672 support -CONFIG_BLK_DEV_UMC8672 - This driver is enabled at runtime using the "ide0=umc8672" kernel - boot parameter. It enables support for the secondary IDE interface - of the UMC-8672, and permits faster I/O speeds to be set as well. - See the files and - for more info. - -Amiga Gayle IDE interface support -CONFIG_BLK_DEV_GAYLE - This is the IDE driver for the Amiga Gayle IDE interface. It supports - both the `A1200 style' and `A4000 style' of the Gayle IDE interface, - This includes builtin IDE interfaces on some Amiga models (A600, - A1200, A4000, and A4000T), and IDE interfaces on the Zorro expansion - bus (M-Tech E-Matrix 530 expansion card). - Say Y if you have an Amiga with a Gayle IDE interface and want to use - IDE devices (hard disks, CD-ROM drives, etc.) that are connected to it. - Note that you also have to enable Zorro bus support if you want to - use Gayle IDE interfaces on the Zorro expansion bus. - -Falcon IDE interface support -CONFIG_BLK_DEV_FALCON_IDE - This is the IDE driver for the builtin IDE interface on the Atari - Falcon. Say Y if you have a Falcon and want to use IDE devices (hard - disks, CD-ROM drives, etc.) that are connected to the builtin IDE - interface. - -Amiga Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL) -CONFIG_BLK_DEV_BUDDHA - This is the IDE driver for the IDE interfaces on the Buddha, - Catweasel and X-Surf expansion boards. It supports up to two interfaces - on the Buddha, three on the Catweasel and two on the X-Surf. - - Say Y if you have a Buddha or Catweasel expansion board and want to - use IDE devices (hard disks, CD-ROM drives, etc.) that are connected - to one of its IDE interfaces. - -Amiga IDE Doubler support (EXPERIMENTAL) -CONFIG_BLK_DEV_IDEDOUBLER - This driver provides support for the so-called `IDE doublers' (made - by various manufacturers, e.g. Eyetech) that can be connected to the - builtin IDE interface of some Amiga models. Using such an IDE - doubler, you can connect up to four instead of two IDE devices on - the Amiga's builtin IDE interface. - - Note that the normal Amiga Gayle IDE driver may not work correctly - if you have an IDE doubler and don't enable this driver! - - Say Y if you have an IDE doubler. The driver is enabled at kernel - runtime using the "ide=doubler" kernel boot parameter. - -Builtin PowerMac IDE support -CONFIG_BLK_DEV_IDE_PMAC - This driver provides support for the built-in IDE controller on - most of the recent Apple Power Macintoshes and PowerBooks. - If unsure, say Y. - -PowerMac IDE DMA support -CONFIG_BLK_DEV_IDEDMA_PMAC - This option allows the driver for the built-in IDE controller on - Power Macintoshes and PowerBooks to use DMA (direct memory access) - to transfer data to and from memory. Saying Y is safe and improves - performance. - -Broadcom SiByte onboard IDE support -CONFIG_BLK_DEV_IDE_SIBYTE - Include the driver for on-board IDE on the SiByte Generic Bus. Note - that this limits the number of IDE devices to 4 (ide0...ide3). - -Use DMA by default -CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO - This option allows the driver for the built-in IDE controller on - Power Macintoshes and PowerBooks to use DMA automatically, without - it having to be explicitly enabled. This option is provided because - of concerns about a couple of cases where using DMA on buggy PC - hardware may have caused damage. Saying Y should be safe on all - Apple machines. - -Macintosh Quadra/Powerbook IDE interface support -CONFIG_BLK_DEV_MAC_IDE - This is the IDE driver for the builtin IDE interface on some m68k - Macintosh models. It supports both the `Quadra style' (used in - Quadra/ Centris 630 and Performa 588 models) and `Powerbook style' - (used in the Powerbook 150 and 190 models) IDE interface. - - Say Y if you have such an Macintosh model and want to use IDE - devices (hard disks, CD-ROM drives, etc.) that are connected to the - builtin IDE interface. - -ICS IDE interface support -CONFIG_BLK_DEV_IDE_ICSIDE - On Acorn systems, say Y here if you wish to use the ICS IDE - interface card. This is not required for ICS partition support. - If you are unsure, say N to this. - -ICS DMA support -CONFIG_BLK_DEV_IDEDMA_ICS - Say Y here if you want to add DMA (Direct Memory Access) support to - the ICS IDE driver. - -Use ICS DMA by default -CONFIG_IDEDMA_ICS_AUTO - Prior to kernel version 2.1.112, Linux used to automatically use - DMA for IDE drives and chipsets which support it. Due to concerns - about a couple of cases where buggy hardware may have caused damage, - the default is now to NOT use DMA automatically. To revert to the - previous behaviour, say Y to this question. - - If you suspect your hardware is at all flakey, say N here. - Do NOT email the IDE kernel people regarding this issue! - -XT hard disk support -CONFIG_BLK_DEV_XD - Very old 8 bit hard disk controllers used in the IBM XT computer - will be supported if you say Y here. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called xd.o. - - It's pretty unlikely that you have one of these: say N. - -PS/2 ESDI hard disk support -CONFIG_BLK_DEV_PS2 - Say Y here if you have a PS/2 machine with a MCA bus and an ESDI - hard disk. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ps2esdi.o. - -Mylex DAC960/DAC1100 PCI RAID Controller support -CONFIG_BLK_DEV_DAC960 - This driver adds support for the Mylex DAC960, AcceleRAID, and - eXtremeRAID PCI RAID controllers. See the file - for further information about - this driver. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called DAC960.o. - -Parallel port IDE device support -CONFIG_PARIDE - There are many external CD-ROM and disk devices that connect through - your computer's parallel port. Most of them are actually IDE devices - using a parallel port IDE adapter. This option enables the PARIDE - subsystem which contains drivers for many of these external drives. - Read for more information. - - If you have said Y to the "Parallel-port support" configuration - option, you may share a single port between your printer and other - parallel port devices. Answer Y to build PARIDE support into your - kernel, or M if you would like to build it as a loadable module. If - your parallel port support is in a loadable module, you must build - PARIDE as a module. If you built PARIDE support into your kernel, - you may still build the individual protocol modules and high-level - drivers as loadable modules. If you build this support as a module, - it will be called paride.o. - - To use the PARIDE support, you must say Y or M here and also to at - least one high-level driver (e.g. "Parallel port IDE disks", - "Parallel port ATAPI CD-ROMs", "Parallel port ATAPI disks" etc.) and - to at least one protocol driver (e.g. "ATEN EH-100 protocol", - "MicroSolutions backpack protocol", "DataStor Commuter protocol" - etc.). - -Parallel port IDE disks -CONFIG_PARIDE_PD - This option enables the high-level driver for IDE-type disk devices - connected through a parallel port. If you chose to build PARIDE - support into your kernel, you may answer Y here to build in the - parallel port IDE driver, otherwise you should answer M to build - it as a loadable module. The module will be called pd.o. You - must also have at least one parallel port protocol driver in your - system. Among the devices supported by this driver are the SyQuest - EZ-135, EZ-230 and SparQ drives, the Avatar Shark and the backpack - hard drives from MicroSolutions. - -Parallel port ATAPI CD-ROMs -CONFIG_PARIDE_PCD - This option enables the high-level driver for ATAPI CD-ROM devices - connected through a parallel port. If you chose to build PARIDE - support into your kernel, you may answer Y here to build in the - parallel port ATAPI CD-ROM driver, otherwise you should answer M to - build it as a loadable module. The module will be called pcd.o. You - must also have at least one parallel port protocol driver in your - system. Among the devices supported by this driver are the - MicroSolutions backpack CD-ROM drives and the Freecom Power CD. If - you have such a CD-ROM drive, you should also say Y or M to "ISO - 9660 CD-ROM file system support" below, because that's the file - system used on CD-ROMs. - -Parallel port ATAPI disks -CONFIG_PARIDE_PF - This option enables the high-level driver for ATAPI disk devices - connected through a parallel port. If you chose to build PARIDE - support into your kernel, you may answer Y here to build in the - parallel port ATAPI disk driver, otherwise you should answer M - to build it as a loadable module. The module will be called pf.o. - You must also have at least one parallel port protocol driver in - your system. Among the devices supported by this driver are the - MicroSolutions backpack PD/CD drive and the Imation Superdisk - LS-120 drive. - -Parallel port ATAPI tapes -CONFIG_PARIDE_PT - This option enables the high-level driver for ATAPI tape devices - connected through a parallel port. If you chose to build PARIDE - support into your kernel, you may answer Y here to build in the - parallel port ATAPI disk driver, otherwise you should answer M - to build it as a loadable module. The module will be called pt.o. - You must also have at least one parallel port protocol driver in - your system. Among the devices supported by this driver is the - parallel port version of the HP 5GB drive. - -Parallel port generic ATAPI devices -CONFIG_PARIDE_PG - This option enables a special high-level driver for generic ATAPI - devices connected through a parallel port. The driver allows user - programs, such as cdrtools, to send ATAPI commands directly to a - device. - - If you chose to build PARIDE support into your kernel, you may - answer Y here to build in the parallel port generic ATAPI driver, - otherwise you should answer M to build it as a loadable module. The - module will be called pg.o. - - You must also have at least one parallel port protocol driver in - your system. - - This driver implements an API loosely related to the generic SCSI - driver. See . for details. - - You can obtain the most recent version of cdrtools from - . Versions 1.6.1a3 and - later fully support this driver. - -ATEN EH-100 protocol -CONFIG_PARIDE_ATEN - This option enables support for the ATEN EH-100 parallel port IDE - protocol. This protocol is used in some inexpensive low performance - parallel port kits made in Hong Kong. If you chose to build PARIDE - support into your kernel, you may answer Y here to build in the - protocol driver, otherwise you should answer M to build it as a - loadable module. The module will be called aten.o. You must also - have a high-level driver for the type of device that you want to - support. - -Micro Solutions BACKPACK Series 5 protocol -CONFIG_PARIDE_BPCK - This option enables support for the Micro Solutions BACKPACK - parallel port Series 5 IDE protocol. (Most BACKPACK drives made - before 1999 were Series 5) Series 5 drives will NOT always have the - Series noted on the bottom of the drive. Series 6 drivers will. - - In other words, if your BACKPACK drive dosen't say "Series 6" on the - bottom, enable this option. - - If you chose to build PARIDE support into your kernel, you may - answer Y here to build in the protocol driver, otherwise you should - answer M to build it as a loadable module. The module will be - called bpck.o. You must also have a high-level driver for the type - of device that you want to support. - -Micro Solutions BACKPACK Series 6 protocol -CONFIG_PARIDE_BPCK6 - This option enables support for the Micro Solutions BACKPACK - parallel port Series 6 IDE protocol. (Most BACKPACK drives made - after 1999 were Series 6) Series 6 drives will have the Series noted - on the bottom of the drive. Series 5 drivers don't always have it - noted. - - In other words, if your BACKPACK drive says "Series 6" on the - bottom, enable this option. - - If you chose to build PARIDE support into your kernel, you may - answer Y here to build in the protocol driver, otherwise you should - answer M to build it as a loadable module. The module will be - called bpck6.o. You must also have a high-level driver for the type - of device that you want to support. - -DataStor Commuter protocol -CONFIG_PARIDE_COMM - This option enables support for the Commuter parallel port IDE - protocol from DataStor. If you chose to build PARIDE support - into your kernel, you may answer Y here to build in the protocol - driver, otherwise you should answer M to build it as a loadable - module. The module will be called comm.o. You must also have - a high-level driver for the type of device that you want to support. - -DataStor EP-2000 protocol -CONFIG_PARIDE_DSTR - This option enables support for the EP-2000 parallel port IDE - protocol from DataStor. If you chose to build PARIDE support - into your kernel, you may answer Y here to build in the protocol - driver, otherwise you should answer M to build it as a loadable - module. The module will be called dstr.o. You must also have - a high-level driver for the type of device that you want to support. - -Shuttle EPAT/EPEZ protocol -CONFIG_PARIDE_EPAT - This option enables support for the EPAT parallel port IDE protocol. - EPAT is a parallel port IDE adapter manufactured by Shuttle - Technology and widely used in devices from major vendors such as - Hewlett-Packard, SyQuest, Imation and Avatar. If you chose to build - PARIDE support into your kernel, you may answer Y here to build in - the protocol driver, otherwise you should answer M to build it as a - loadable module. The module will be called epat.o. You must also - have a high-level driver for the type of device that you want to - support. - -Shuttle EPAT c7/c8 extension -CONFIG_PARIDE_EPATC8 - This option enables support for the newer Shuttle EP1284 (aka c7 and - c8) chip. You need this if you are using any recent Imation SuperDisk - (LS-120) drive. - -Shuttle EPIA protocol -CONFIG_PARIDE_EPIA - This option enables support for the (obsolete) EPIA parallel port - IDE protocol from Shuttle Technology. This adapter can still be - found in some no-name kits. If you chose to build PARIDE support - into your kernel, you may answer Y here to build in the protocol - driver, otherwise you should answer M to build it as a loadable - module. The module will be called epia.o. You must also have a - high-level driver for the type of device that you want to support. - -FIT TD-2000 protocol -CONFIG_PARIDE_FIT2 - This option enables support for the TD-2000 parallel port IDE - protocol from Fidelity International Technology. This is a simple - (low speed) adapter that is used in some portable hard drives. If - you chose to build PARIDE support into your kernel, you may answer Y - here to build in the protocol driver, otherwise you should answer M - to build it as a loadable module. The module will be called fit2.o. - You must also have a high-level driver for the type of device that - you want to support. - -FIT TD-3000 protocol -CONFIG_PARIDE_FIT3 - This option enables support for the TD-3000 parallel port IDE - protocol from Fidelity International Technology. This protocol is - used in newer models of their portable disk, CD-ROM and PD/CD - devices. If you chose to build PARIDE support into your kernel, you - may answer Y here to build in the protocol driver, otherwise you - should answer M to build it as a loadable module. The module will be - called fit3.o. You must also have a high-level driver for the type - of device that you want to support. - -Freecom IQ ASIC-2 protocol -CONFIG_PARIDE_FRIQ - This option enables support for version 2 of the Freecom IQ parallel - port IDE adapter. This adapter is used by the Maxell Superdisk - drive. If you chose to build PARIDE support into your kernel, you - may answer Y here to build in the protocol driver, otherwise you - should answer M to build it as a loadable module. The module will be - called friq.o. You must also have a high-level driver for the type - of device that you want to support. - -FreeCom power protocol -CONFIG_PARIDE_FRPW - This option enables support for the Freecom power parallel port IDE - protocol. If you chose to build PARIDE support into your kernel, you - may answer Y here to build in the protocol driver, otherwise you - should answer M to build it as a loadable module. The module will be - called frpw.o. You must also have a high-level driver for the type - of device that you want to support. - -KingByte KBIC-951A/971A protocols -CONFIG_PARIDE_KBIC - This option enables support for the KBIC-951A and KBIC-971A parallel - port IDE protocols from KingByte Information Corp. KingByte's - adapters appear in many no-name portable disk and CD-ROM products, - especially in Europe. If you chose to build PARIDE support into your - kernel, you may answer Y here to build in the protocol driver, - otherwise you should answer M to build it as a loadable module. The - module will be called kbic.o. You must also have a high-level driver - for the type of device that you want to support. - -KT PHd protocol -CONFIG_PARIDE_KTTI - This option enables support for the "PHd" parallel port IDE protocol - from KT Technology. This is a simple (low speed) adapter that is - used in some 2.5" portable hard drives. If you chose to build PARIDE - support into your kernel, you may answer Y here to build in the - protocol driver, otherwise you should answer M to build it as a - loadable module. The module will be called ktti.o. You must also - have a high-level driver for the type of device that you want to - support. - -OnSpec 90c20 protocol -CONFIG_PARIDE_ON20 - This option enables support for the (obsolete) 90c20 parallel port - IDE protocol from OnSpec (often marketed under the ValuStore brand - name). If you chose to build PARIDE support into your kernel, you - may answer Y here to build in the protocol driver, otherwise you - should answer M to build it as a loadable module. The module will - be called on20.o. You must also have a high-level driver for the - type of device that you want to support. - -OnSpec 90c26 protocol -CONFIG_PARIDE_ON26 - This option enables support for the 90c26 parallel port IDE protocol - from OnSpec Electronics (often marketed under the ValuStore brand - name). If you chose to build PARIDE support into your kernel, you - may answer Y here to build in the protocol driver, otherwise you - should answer M to build it as a loadable module. The module will be - called on26.o. You must also have a high-level driver for the type - of device that you want to support. - -Logical Volume Manager (LVM) support -CONFIG_BLK_DEV_LVM - This driver lets you combine several hard disks, hard disk - partitions, multiple devices or even loop devices (for evaluation - purposes) into a volume group. Imagine a volume group as a kind of - virtual disk. Logical volumes, which can be thought of as virtual - partitions, can be created in the volume group. You can resize - volume groups and logical volumes after creation time, corresponding - to new capacity needs. Logical volumes are accessed as block - devices named /dev/VolumeGroupName/LogicalVolumeName. - - For details see . You will need - supporting user space software; location is in - . - - If you want to compile this support as a module ( = code which can - be inserted in and removed from the running kernel whenever you - want), say M here and read . The - module will be called lvm-mod.o. - -Multiple devices driver support (RAID and LVM) -CONFIG_MD - Support multiple physical spindles through a single logical device. - Required for RAID and logical volume management (LVM). - -Multiple devices driver support -CONFIG_BLK_DEV_MD - This driver lets you combine several hard disk partitions into one - logical block device. This can be used to simply append one - partition to another one or to combine several redundant hard disks - into a RAID1/4/5 device so as to provide protection against hard - disk failures. This is called "Software RAID" since the combining of - the partitions is done by the kernel. "Hardware RAID" means that the - combining is done by a dedicated controller; if you have such a - controller, you do not need to say Y here. - - More information about Software RAID on Linux is contained in the - Software RAID mini-HOWTO, available from - . There you will also learn - where to get the supporting user space utilities raidtools. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - md.o - - If unsure, say N. - -Linear (append) mode -CONFIG_MD_LINEAR - If you say Y here, then your multiple devices driver will be able to - use the so-called linear mode, i.e. it will combine the hard disk - partitions by simply appending one to the other. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called linear.o. - - If unsure, say Y. - -RAID-0 (striping) mode -CONFIG_MD_RAID0 - If you say Y here, then your multiple devices driver will be able to - use the so-called raid0 mode, i.e. it will combine the hard disk - partitions into one logical device in such a fashion as to fill them - up evenly, one chunk here and one chunk there. This will increase - the throughput rate if the partitions reside on distinct disks. - - Information about Software RAID on Linux is contained in the - Software-RAID mini-HOWTO, available from - . There you will also - learn where to get the supporting user space utilities raidtools. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called raid0.o. - - If unsure, say Y. - -RAID-1 (mirroring) mode -CONFIG_MD_RAID1 - A RAID-1 set consists of several disk drives which are exact copies - of each other. In the event of a mirror failure, the RAID driver - will continue to use the operational mirrors in the set, providing - an error free MD (multiple device) to the higher levels of the - kernel. In a set with N drives, the available space is the capacity - of a single drive, and the set protects against a failure of (N - 1) - drives. - - Information about Software RAID on Linux is contained in the - Software-RAID mini-HOWTO, available from - . There you will also - learn where to get the supporting user space utilities raidtools. - - If you want to use such a RAID-1 set, say Y. This code is also - available as a module called raid1.o ( = code which can be inserted - in and removed from the running kernel whenever you want). If you - want to compile it as a module, say M here and read - . - - If unsure, say Y. - -RAID-4/RAID-5 mode -CONFIG_MD_RAID5 - A RAID-5 set of N drives with a capacity of C MB per drive provides - the capacity of C * (N - 1) MB, and protects against a failure - of a single drive. For a given sector (row) number, (N - 1) drives - contain data sectors, and one drive contains the parity protection. - For a RAID-4 set, the parity blocks are present on a single drive, - while a RAID-5 set distributes the parity across the drives in one - of the available parity distribution methods. - - Information about Software RAID on Linux is contained in the - Software-RAID mini-HOWTO, available from - . There you will also - learn where to get the supporting user space utilities raidtools. - - If you want to use such a RAID-4/RAID-5 set, say Y. This code is - also available as a module called raid5.o ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . - - If unsure, say Y. - -Multipath I/O support -CONFIG_MD_MULTIPATH - Multipath-IO is the ability of certain devices to address the same - physical disk over multiple 'IO paths'. The code ensures that such - paths can be defined and handled at runtime, and ensures that a - transparent failover to the backup path(s) happens if a IO errors - arrives on the primary path. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - multipath.o - - If unsure, say N. - -Support for IDE Raid controllers -CONFIG_BLK_DEV_ATARAID - Say Y or M if you have an IDE Raid controller and want linux - to use its softwareraid feature. You must also select an - appropriate for your board low-level driver below. - - Note, that Linux does not use the Raid implementation in BIOS, and - the main purpose for this feature is to retain compatibility and - data integrity with other OS-es, using the same disk array. Linux - has its own Raid drivers, which you should use if you need better - performance. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - ataraid.o - -Support Promise software RAID (Fasttrak(tm)) -CONFIG_BLK_DEV_ATARAID_PDC - Say Y or M if you have a Promise Fasttrak (tm) Raid controller - and want linux to use the softwareraid feature of this card. - This driver uses /dev/ataraid/dXpY (X and Y numbers) as device - names. - - If you choose to compile this as a module, the module will be called - pdcraid.o. - -Highpoint 370 software RAID -CONFIG_BLK_DEV_ATARAID_HPT - Say Y or M if you have a Highpoint HPT 370 Raid controller - and want linux to use the softwareraid feature of this card. - This driver uses /dev/ataraid/dXpY (X and Y numbers) as device - names. - - If you choose to compile this as a module, the module will be called - hptraid.o. - -CMD/Silicon Image Medley Software RAID -CONFIG_BLK_DEV_ATARAID_MEDLEY - Say Y or M if you have a Silicon Image 3112 SATA RAID controller, - a CMD680 based controller, or another IDE RAID controller that uses - CMD's Medley software RAID, and want Linux to use the software RAID - feature of this card. This driver uses /dev/ataraid/dXpY (X and Y - numbers) as device names. - - This driver currently only supports RAID0 (striped) mode, so if you - are using RAID1 (mirroring) this will not work for you. In that - case, you may want to try the Silicon Image Medley Software RAID - driver (below). - - Support for mirroring is planned in the future. - - If you choose to compile this as a module, the module will be called - medley.o. - -Silicon Image Medley Software RAID (old driver) -CONFIG_BLK_DEV_ATARAID_SII - Say Y or M if you have a Silicon Image SATARaid controller - and want Linux to use the softwareraid feature of this card. - This driver uses /dev/ataraid/dXpY (X and Y numbers) as device - names. - - This driver does not reliably detect all Medley RAID sets, and could - be dangerous if you have a striped set with disks of different size. - - You should use the new Medley RAID driver (above), unless you use - RAID1 (mirroring), which the new driver does not yet support. - - If you choose to compile this as a module, the module will be called - silraid.o. - -Support for Acer PICA 1 chipset -CONFIG_ACER_PICA_61 - This is a machine with a R4400 133/150 MHz CPU. To compile a Linux - kernel that runs on these, say Y here. For details about Linux on - the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at - . - -Support for Algorithmics P4032 (EXPERIMENTAL) -CONFIG_ALGOR_P4032 - This is an evaluation board of the British company Algorithmics. - The board uses the R4300 and a R5230 CPUs. For more information - about this board see . - -SGI SN2 L1 serial port support -CONFIG_SGI_L1_SERIAL - If you have an SGI SN2 and you want to use the serial port connected - to the system controller (you want this!), say Y. Otherwise, say N. - -SGI SN2 L1 serial console support -CONFIG_SGI_L1_SERIAL_CONSOLE - If you have an SGI SN2 and you would like to use the system - controller serial port as your console (you want this!), say Y. - Otherwise, say N. - -Support for BAGET MIPS series -CONFIG_BAGET_MIPS - This enables support for the Baget, a Russian embedded system. For - more details about the Baget see the Linux/MIPS FAQ on - . - -Baget AMD LANCE support -CONFIG_BAGETLANCE - Say Y to enable kernel support for AMD Lance Ethernet cards on the - MIPS-32-based Baget embedded system. This chipset is better known - via the NE2100 cards. - -Support for DECstations -CONFIG_DECSTATION - This enables support for DEC's MIPS based workstations. For details - see the Linux/MIPS FAQ on and the - DECstation porting pages on . - - If you have one of the following DECstation Models you definitely - want to choose R4xx0 for the CPU Type: - - DECstation 5000/50 - DECstation 5000/150 - DECstation 5000/260 - DECsystem 5900/260 - - otherwise choose R3000. - -Support for Cobalt Micro Server -CONFIG_COBALT_MICRO_SERVER - Support for MIPS-based Cobalt boxes (they have been bought by Sun - and are now the "Server Appliance Business Unit") including the 2700 - series -- versions 1 of the Qube and Raq. To compile a Linux kernel - for this hardware, say Y here. - -Support for Cobalt 2800 -CONFIG_COBALT_28 - Support for the second generation of MIPS-based Cobalt boxes (they - have been bought by Sun and are now the "Server Appliance Business - Unit") including the 2800 series -- versions 2 of the Qube and Raq. - To compile a Linux kernel for this hardware, say Y here. - -Support for the Momentum Computer Ocelot SBC -CONFIG_MOMENCO_OCELOT - The Ocelot is a MIPS-based Single Board Computer (SBC) made by - Momentum Computer . - -Support for NEC DDB Vrc-5074 -CONFIG_DDB5074 - This enables support for the VR5000-based NEC DDB Vrc-5074 - evaluation board. - -Support for NEC DDB Vrc-5476 -CONFIG_DDB5476 - This enables support for the R5432-based NEC DDB Vrc-5476 - evaluation board. - - Features : kernel debugging, serial terminal, NFS root fs, on-board - ether port (Need an additional patch at ), - USB, AC97, PCI, PCI VGA card & framebuffer console, IDE controller, - PS2 keyboard, PS2 mouse, etc. - -Support for NEC DDB Vrc-5477 -CONFIG_DDB5477 - This enables support for the R5432-based NEC DDB Vrc-5477 - evaluation board. - - Features : kernel debugging, serial terminal, NFS root fs, on-board - ether port (Need an additional patch at ), - USB, AC97, PCI, etc. - -Support for MIPS Atlas board -CONFIG_MIPS_ATLAS - This enables support for the QED R5231-based MIPS Atlas evaluation - board. - -Support for MIPS Malta board -CONFIG_MIPS_MALTA - This enables support for the VR5000-based MIPS Malta evaluation - board. - -# Choice: bcmboard -Support for Broadcom SiByte boards -CONFIG_SIBYTE_SWARM - Enable support for boards based on the Broadcom SiByte family: - - BCM91250A-SWARM BCM1250 ATX size Eval Board (BCM91250A-SWARM) - - BCM91250E-Sentosa BCM1250 PCI card Eval Board (BCM91250E-Sentosa) - - BCM91125E-Rhone BCM1125 PCI card Eval Board (BCM91125E-Rhone) - - Other Non-Broadcom SiByte-based platform - -# Choice: bcmsoc -Support for Broadcom BCM1xxx SOCs -CONFIG_SIBYTE_SB1250 - - BCM1250 Dual-CPU SB1 with PCI and HyperTransport. - - BCM1120 Uniprocessor SB1. - - BCM1125 Uniprocessor SB1 with PCI (and HyperTransport for 1125H). - -BCM1250 Stepping -CONFIG_CPU_SB1_PASS_1 - Which pass of the SOC is supported (see the "system_revision" - register in the User Manual for more discussion of revisions): - - Pass1 1250 "Pass 1" - - An 1250 "Pass 2" - - Bn 1250 "Pass 2.2" - - Cn 1250 "Pass 3" - -BCM112x Stepping -CONFIG_CPU_SB1_PASS_2 - Which pass of the SOC is supported (see the "system_revision" - register in the User Manual for more discussion of revisions): - - Hybrid 1250 "Pass 2" - - An 112x "Pass 1" - -Booting from CFE -CONFIG_SIBYTE_CFE - Make use of the CFE API for enumerating available memory, - controlling secondary CPUs, and possibly console output. - -Use firmware console -CONFIG_SIBYTE_CFE_CONSOLE - Use the CFE API's console write routines during boot. Other console - options (VT console, sb1250 duart console, etc.) should not be - configured. - -Support for Bus Watcher statistics -CONFIG_SIBYTE_BUS_WATCHER - Handle and keep statistics on the bus error interrupts (COR_ECC, - BAD_ECC, IO_BUS). - -Bus trace dump on bus error -CONFIG_SIBYTE_BW_TRACE - Run a continuous bus trace, dumping the raw data as soon as a ZBbus - error is detected. Cannot work if ZBbus profiling is turned on, and - also will interfere with JTAG-based trace buffer activity. Raw - buffer data is dumped to console, and must be processed off-line. - -Corelis Debugger -CONFIG_SB1XXX_CORELIS - Select compile flags that produce code that can be processed by the - Corelis mksym utility and UDB Emulator. - -DMA for page clear and copy -CONFIG_SIBYTE_DMA_PAGEOPS - Instead of using the CPU to zero and copy pages, use a Data Mover - channel. These DMA channels are otherwise unused by the standard - SiByte Linux port. Seems to give a small performance benefit. - -Support for Galileo Evaluation board or CoSine Orion -CONFIG_ORION - Say Y if configuring for the Galileo evaluation board - or CoSine Orion. More information is available at - . - - Otherwise, say N. - -Support for Mips Magnum 4000 -CONFIG_MIPS_MAGNUM_4000 - This is a machine with a R4000 100 MHz CPU. To compile a Linux - kernel that runs on these, say Y here. For details about Linux on - the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at - . - -Enable Qtronix 990P Keyboard Support -CONFIG_QTRONIX_KEYBOARD - Images of Qtronix keyboards are at - . - -Support for Olivetti M700 -CONFIG_OLIVETTI_M700 - This is a machine with a R4000 100 MHz CPU. To compile a Linux - kernel that runs on these, say Y here. For details about Linux on - the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at - . - -Support for SNI RM200 PCI -CONFIG_SNI_RM200_PCI - The SNI RM200 PCI was a MIPS-based platform manufactured by Siemens - Nixdorf Informationssysteme (SNI), parent company of Pyramid - Technology and now in turn merged with Fujitsu. Say Y here to - support this machine type. - -Support for SGI-IP22 (Indy/Indigo2) -CONFIG_SGI_IP22 - This are the SGI Indy, Challenge S and Indigo2, as well as certain - OEM variants like the Tandem CMN B006S. To compile a Linux kernel - that runs on these, say Y here. - -Support for SGI IP27 (Origin200/2000) -CONFIG_SGI_IP27 - This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics - workstations. To compile a Linux kernel that runs on these, say Y - here. - -IP27 N-Mode -CONFIG_SGI_SN0_N_MODE - The nodes of Origin 200, Origin 2000 and Onyx 2 systems can be - configured in either N-Modes which allows for more nodes or M-Mode - which allows for more memory. Your system is most probably - running in M-Mode, so you should say N here. - -Lasi Ethernet -CONFIG_LASI_82596 - Say Y here to support the on-board Intel 82596 ethernet controller - built into Hewlett-Packard PA-RISC machines. - -MIPS JAZZ onboard SONIC Ethernet support -CONFIG_MIPS_JAZZ_SONIC - This is the driver for the onboard card of MIPS Magnum 4000, - Acer PICA, Olivetti M700-10 and a few other identical OEM systems. - -MIPS JAZZ FAS216 SCSI support -CONFIG_JAZZ_ESP - This is the driver for the onboard SCSI host adapter of MIPS Magnum - 4000, Acer PICA, Olivetti M700-10 and a few other identical OEM - systems. - -MIPS GT96100 Ethernet support -CONFIG_MIPS_GT96100ETH - Say Y here to support the Ethernet subsystem on your GT96100 card. - -Zalon SCSI support -CONFIG_SCSI_ZALON - The Zalon is an interface chip that sits between the PA-RISC - processor and the NCR 53c720 SCSI controller on K-series PA-RISC - boards (these are used, among other places, on some HP 780 - workstations). Say Y here to make sure it gets initialized - correctly before the Linux kernel tries to talk to the controller. - -SGI PROM Console Support -CONFIG_SGI_PROM_CONSOLE - Say Y here to set up the boot console on serial port 0. - -DECstation serial support -CONFIG_SERIAL_DEC - This selects whether you want to be asked about drivers for - DECstation serial ports. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about DECstation serial ports. - - If unsure, say Y. - -Support for console on a DECstation serial port -CONFIG_SERIAL_DEC_CONSOLE - If you say Y here, it will be possible to use a serial port as the - system console (the system console is the device which receives all - kernel messages and warnings and which allows logins in single user - mode). Note that the firmware uses ttyS0 as the serial console on - the Maxine and ttyS2 on the others. - - If unsure, say Y. - -DZ11 Serial Support -CONFIG_DZ - DZ11-family serial controllers for VAXstations, including the - DC7085, M7814, and M7819. - -TURBOchannel support -CONFIG_TC - TurboChannel is a DEC (now Compaq) bus for Alpha and MIPS processors. - Documentation on writing device drivers for TurboChannel is available at: - . - -# Choice: galileo_clock -75 -CONFIG_SYSCLK_75 - Configure the kernel for clock speed of your Galileo board. - The choices are 75MHz, 83.3MHz, and 100MHz. - -83.3 -CONFIG_SYSCLK_83 - Configure the Galileo kernel for a clock speed of 83.3 MHz. - -100 -CONFIG_SYSCLK_100 - Configure the Galileo kernel for a clock speed of 100 MHz. - -Z85C30 Serial Support -CONFIG_ZS - Documentation on the Zilog 85C350 serial communications controller - is downloadable at . - -PCMCIA SCSI adapter support -CONFIG_SCSI_PCMCIA - Say Y here if you intend to attach a PCMCIA or CardBus card to your - computer which acts as a SCSI host adapter. These are credit card - size devices often used with laptops. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions PCMCIA SCSI host adapters. - -Adaptec APA1480 CardBus support -CONFIG_PCMCIA_APA1480 - Say Y here if you intend to attach this type of CardBus SCSI host - adapter to your computer. - - This driver is also available as a module called apa1480_cb.o ( = - code which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support -CONFIG_PCMCIA_NINJA_SCSI - If you intend to attach this type of PCMCIA SCSI host adapter to - your computer, say Y here and read - . - - This driver is also available as a module called nsp_cs.o ( = - code which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Adaptec AHA152X PCMCIA support -CONFIG_PCMCIA_AHA152X - Say Y here if you intend to attach this type of PCMCIA SCSI host - adapter to your computer. - - This driver is also available as a module called aha152x_cs.o ( = - code which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Qlogic PCMCIA support -CONFIG_PCMCIA_QLOGIC - Say Y here if you intend to attach this type of PCMCIA SCSI host - adapter to your computer. - - This driver is also available as a module called qlogic_cs.o ( = - code which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Future Domain PCMCIA support -CONFIG_PCMCIA_FDOMAIN - Say Y here if you intend to attach this type of PCMCIA SCSI host - adapter to your computer. - - This driver is also available as a module called fdomain_cs.o ( = - code which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -# Choice: mipstype -CPU type -CONFIG_CPU_R3000 - Please make sure to pick the right CPU type. Linux/MIPS is not - designed to be generic, i.e. Kernels compiled for R3000 CPUs will - *not* work on R4000 machines and vice versa. However, since most - of the supported machines have an R4000 (or similar) CPU, R4x00 - might be a safe bet. If the resulting kernel does not work, - try to recompile with R3000. - - R3000 MIPS Technologies R3000-series processors, - including the 3041, 3051, and 3081. - - R6000 MIPS Technologies R6000-series processors, - including the 64474, 64475, 64574 and 64575. - - R4300 MIPS Technologies R4300-series processors. - - R4x00 MIPS Technologies R4000-series processors other than 4300, - including the 4640, 4650, and 4700. - - R5000 MIPS Technologies R5000-series processors other than the - Nevada. - - R52xx MIPS Technologies R52xx-series ("Nevada") processors. - - R10000 MIPS Technologies R10000-series processors. - - SB1 Broadcom SiByte SB1 processor. - -R6000 -CONFIG_CPU_R6000 - MIPS Technologies R6000-series processors, including the 64474, - 64475, 64574 and 64575. - -R4300 -CONFIG_CPU_R4300 - MIPS Technologies R4300-series processors. - -R4x00 -CONFIG_CPU_R4X00 - MIPS Technologies R4000-series processors other than 4300, including - the 4640, 4650, and 4700. - -R5000 -CONFIG_CPU_R5000 - MIPS Technologies R5000-series processors other than the Nevada. - -R52x0 -CONFIG_CPU_NEVADA - MIPS Technologies R52x0-series ("Nevada") processors. - -R8000 -CONFIG_CPU_R8000 - MIPS Technologies R8000-series processors. - -R10000 -CONFIG_CPU_R10000 - MIPS Technologies R10000-series processors. - -SB1 -CONFIG_CPU_SB1 - Broadcom SiByte SB1 processor. - -Discontiguous Memory Support -CONFIG_DISCONTIGMEM - Say Y to support efficient handling of discontiguous physical memory, - for architectures which are either NUMA (Non-Uniform Memory Access) - or have huge holes in the physical address space for other reasons. - See for more. - -Mapped kernel support -CONFIG_MAPPED_KERNEL - Change the way a Linux kernel is loaded unto memory on a MIPS64 - machine. This is required in order to support text replication and - NUMA. If you need to understand it, read the source code. - -Kernel text replication support -CONFIG_REPLICATE_KTEXT - Say Y here to enable replicating the kernel text across multiple - nodes in a NUMA cluster. This trades memory for speed. - -Exception handler replication support -CONFIG_REPLICATE_EXHANDLERS - Say Y here to enable replicating the kernel exception handlers - across multiple nodes in a NUMA cluster. This trades memory for - speed. - -NUMA support? -CONFIG_NUMA - Say Y to compile the kernel to support NUMA (Non-Uniform Memory - Access). This option is for configuring high-end multiprocessor - server machines. If in doubt, say N. - -R41xx -CONFIG_CPU_VR41XX - The options selects support for the NEC VR41xx series of processors. - Only choose this option if you have one of these processors as a - kernel built with this option will not run on any other type of - processor or vice versa. - -CPU feature configuration -CONFIG_CPU_ADVANCED - Saying yes here allows you to select support for various features - your CPU may or may not have. Most people should say N here. - -ll and sc instructions available -CONFIG_CPU_HAS_LLSC - MIPS R4000 series and later provide the Load Linked (ll) - and Store Conditional (sc) instructions. More information is - available at . - - Say Y here if your CPU has the ll and sc instructions. Say Y here - for better performance, N if you don't know. You must say Y here - for multiprocessor machines. - -lld and scd instructions available -CONFIG_CPU_HAS_LLDSCD - Say Y here if your CPU has the lld and scd instructions, the 64-bit - equivalents of ll and sc. Say Y here for better performance, N if - you don't know. You must say Y here for multiprocessor machines. - -Writeback Buffer available -CONFIG_CPU_HAS_WB - Say N here for slightly better performance. You must say Y here for - machines which require flushing of write buffers in software. Saying - Y is the safe option; N may result in kernel malfunction and crashes. - -Support for large 64-bit configurations -CONFIG_MIPS_INSANE_LARGE - MIPS R10000 does support a 44 bit / 16TB address space as opposed to - previous 64-bit processors which only supported 40 bit / 1TB. If you - need processes of more than 1TB virtual address space, say Y here. - This will result in additional memory usage, so it is not - recommended for normal users. - -Generate little endian code -CONFIG_CPU_LITTLE_ENDIAN - Some MIPS machines can be configured for either little or big endian - byte order. These modes require different kernels. Say Y if your - machine is little endian, N if it's a big endian machine. - -Use power LED as a heartbeat -CONFIG_HEARTBEAT - Use the power-on LED on your machine as a load meter. The exact - behaviour is platform-dependent, but normally the flash frequency is - a hyperbolic function of the 5-minute load average. - -Networking support -CONFIG_NET - Unless you really know what you are doing, you should say Y here. - The reason is that some programs need kernel networking support even - when running on a stand-alone machine that isn't connected to any - other computer. If you are upgrading from an older kernel, you - should consider updating your networking tools too because changes - in the kernel and the tools often go hand in hand. The tools are - contained in the package net-tools, the location and version number - of which are given in . - - For a general introduction to Linux networking, it is highly - recommended to read the NET-HOWTO, available from - . - -Socket filtering -CONFIG_FILTER - The Linux Socket Filter is derived from the Berkeley Packet Filter. - If you say Y here, user-space programs can attach a filter to any - socket and thereby tell the kernel that it should allow or disallow - certain types of data to get through the socket. Linux Socket - Filtering works on all socket types except TCP for now. See the - text file for more - information. - - You need to say Y here if you want to use PPP packet filtering - (see the CONFIG_PPP_FILTER option below). - - If unsure, say N. - -Network packet filtering (replaces ipchains) -CONFIG_NETFILTER - Netfilter is a framework for filtering and mangling network packets - that pass through your Linux box. - - The most common use of packet filtering is to run your Linux box as - a firewall protecting a local network from the Internet. The type of - firewall provided by this kernel support is called a "packet - filter", which means that it can reject individual network packets - based on type, source, destination etc. The other kind of firewall, - a "proxy-based" one, is more secure but more intrusive and more - bothersome to set up; it inspects the network traffic much more - closely, modifies it and has knowledge about the higher level - protocols, which a packet filter lacks. Moreover, proxy-based - firewalls often require changes to the programs running on the local - clients. Proxy-based firewalls don't need support by the kernel, but - they are often combined with a packet filter, which only works if - you say Y here. - - You should also say Y here if you intend to use your Linux box as - the gateway to the Internet for a local network of machines without - globally valid IP addresses. This is called "masquerading": if one - of the computers on your local network wants to send something to - the outside, your box can "masquerade" as that computer, i.e. it - forwards the traffic to the intended outside destination, but - modifies the packets to make it look like they came from the - firewall box itself. It works both ways: if the outside host - replies, the Linux box will silently forward the traffic to the - correct local computer. This way, the computers on your local net - are completely invisible to the outside world, even though they can - reach the outside and can receive replies. It is even possible to - run globally visible servers from within a masqueraded local network - using a mechanism called portforwarding. Masquerading is also often - called NAT (Network Address Translation). - - Another use of Netfilter is in transparent proxying: if a machine on - the local network tries to connect to an outside host, your Linux - box can transparently forward the traffic to a local server, - typically a caching proxy server. - - Various modules exist for netfilter which replace the previous - masquerading (ipmasqadm), packet filtering (ipchains), transparent - proxying, and portforwarding mechanisms. Please see - under "iptables" for the location of - these packages. - - Make sure to say N to "Fast switching" below if you intend to say Y - here, as Fast switching currently bypasses netfilter. - - Chances are that you should say Y here if you compile a kernel which - will run as a router and N for regular hosts. If unsure, say N. - -Network packet filtering debugging -CONFIG_NETFILTER_DEBUG - You can say Y here if you want to get additional messages useful in - debugging the netfilter code. - -Connection tracking (required for masq/NAT) -CONFIG_IP_NF_CONNTRACK - Connection tracking keeps a record of what packets have passed - through your machine, in order to figure out how they are related - into connections. - - This is required to do Masquerading or other kinds of Network - Address Translation (except for Fast NAT). It can also be used to - enhance packet filtering (see `Connection state match support' - below). - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -Amanda protocol support -CONFIG_IP_NF_AMANDA - If you are running the Amanda backup package (http://www.amanda.org/) - on this machine or machines that will be MASQUERADED through this - machine, then you may want to enable this feature. This allows the - connection tracking and natting code to allow the sub-channels that - Amanda requires for communication of the backup data, messages and - index. - - If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `N'. - - -IRC Send/Chat protocol support -CONFIG_IP_NF_IRC - There is a commonly-used extension to IRC called - Direct Client-to-Client Protocol (DCC). This enables users to send - files to each other, and also chat to each other without the need - of a server. DCC Sending is used anywhere you send files over IRC, - and DCC Chat is most commonly used by Eggdrop bots. If you are - using NAT, this extension will enable you to send files and initiate - chats. Note that you do NOT need this extension to get files or - have others initiate chats, or everything else in IRC. - - If you want to compile it as a module, say 'M' here and read - Documentation/modules.txt. If unsure, say 'N'. - -TFTP protocol support -CONFIG_IP_NF_TFTP - TFTP connection tracking helper, this is required depending - on how restrictive your ruleset is. - If you are using a tftp client behind -j SNAT or -j MASQUERADING - you will need this. - - If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `Y'. - -FTP protocol support -CONFIG_IP_NF_FTP - Tracking FTP connections is problematic: special helpers are - required for tracking them, and doing masquerading and other forms - of Network Address Translation on them. - - If you want to compile it as a module, say M here and read - . If unsure, say `Y'. - -User space queueing via NETLINK -CONFIG_IP_NF_QUEUE - Netfilter has the ability to queue packets to user space: the - netlink device can be used to access them using this driver. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -IP tables support (required for filtering/masq/NAT) -CONFIG_IP_NF_IPTABLES - iptables is a general, extensible packet identification framework. - The packet filtering and full NAT (masquerading, port forwarding, - etc) subsystems now use this: say `Y' or `M' here if you want to use - either of those. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -recent match support -CONFIG_IP_NF_MATCH_RECENT - This match is used for creating one or many lists of recently - used addresses and then matching against that/those list(s). - - Short options are available by using 'iptables -m recent -h' - Official Website: - - If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `N'. - -limit match support -CONFIG_IP_NF_MATCH_LIMIT - limit matching allows you to control the rate at which a rule can be - matched: mainly useful in combination with the LOG target ("LOG - target support", below) and to avoid some Denial of Service attacks. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -skb->pkt_type packet match support -CONFIG_IP_NF_MATCH_PKTTYPE - This patch allows you to match packet in accrodance - to its "class", eg. BROADCAST, MULTICAST, ... - - Typical usage: - iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG - - If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `N'. - -MAC address match support -CONFIG_IP_NF_MATCH_MAC - MAC matching allows you to match packets based on the source - Ethernet address of the packet. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -Netfilter MARK match support -CONFIG_IP_NF_MATCH_MARK - Netfilter mark matching allows you to match packets based on the - `nfmark' value in the packet. This can be set by the MARK target - (see below). - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -Multiple port match support -CONFIG_IP_NF_MATCH_MULTIPORT - Multiport matching allows you to match TCP or UDP packets based on - a series of source or destination ports: normally a rule can only - match a single range of ports. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -TTL match support -CONFIG_IP_NF_MATCH_TTL - This adds CONFIG_IP_NF_MATCH_TTL option, which enabled the user - to match packets by their TTL value. - - If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `N'. - -LENGTH match support -CONFIG_IP_NF_MATCH_LENGTH - This option allows you to match the length of a packet against a - specific value or range of values. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -AH/ESP match support -CONFIG_IP_NF_MATCH_AH_ESP - These two match extensions (`ah' and `esp') allow you to match a - range of SPIs inside AH or ESP headers of IPSec packets. - - If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `N'. - -DSCP match support -CONFIG_IP_NF_MATCH_DSCP - This option adds a `DSCP' match, which allows you to match against - the IPv4 header DSCP field (DSCP codepoint). - - The DSCP codepoint can have any value between 0x0 and 0x4f. - - If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `N'. - - - -ECN match support -CONFIG_IP_NF_MATCH_ECN - This option adds a `ECN' match, which allows you to match against - the IPv4 and TCP header ECN fields. - - If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `N'. - - - -TOS match support -CONFIG_IP_NF_MATCH_TOS - TOS matching allows you to match packets based on the Type Of - Service fields of the IP packet. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -conntrack match support -CONFIG_IP_NF_MATCH_CONNTRACK - This is a general conntrack match module, a superset of the state match. - - It allows matching on additional conntrack information, which is - useful in complex configurations, such as NAT gateways with multiple - internet links or tunnels. - - If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `N'. - - -Connection state match support -CONFIG_IP_NF_MATCH_STATE - Connection state matching allows you to match packets based on their - relationship to a tracked connection (ie. previous packets). This - is a powerful tool for packet classification. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -Unclean match support -CONFIG_IP_NF_MATCH_UNCLEAN - Unclean packet matching matches any strange or invalid packets, by - looking at a series of fields in the IP, TCP, UDP and ICMP headers. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -Owner match support -CONFIG_IP_NF_MATCH_OWNER - Packet owner matching allows you to match locally-generated packets - based on who created them: the user, group, process or session. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -Packet filtering -CONFIG_IP_NF_FILTER - Packet filtering defines a table `filter', which has a series of - rules for simple packet filtering at local input, forwarding and - local output. See the man page for iptables(8). - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -REJECT target support -CONFIG_IP_NF_TARGET_REJECT - The REJECT target allows a filtering rule to specify that an ICMP - error should be issued in response to an incoming packet, rather - than silently being dropped. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -MIRROR target support -CONFIG_IP_NF_TARGET_MIRROR - The MIRROR target allows a filtering rule to specify that an - incoming packet should be bounced back to the sender. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -Local NAT support -CONFIG_IP_NF_NAT_LOCAL - This option enables support for NAT of locally originated connections. - Enable this if you need to use destination NAT on connections - originating from local processes on the nat box itself. - - Please note that you will need a recent version (>= 1.2.6a) - of the iptables userspace program in order to use this feature. - See for download instructions. - - If unsure, say 'N'. - - -Full NAT (Network Address Translation) -CONFIG_IP_NF_NAT - The Full NAT option allows masquerading, port forwarding and other - forms of full Network Address Port Translation. It is controlled by - the `nat' table in iptables: see the man page for iptables(8). - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -MASQUERADE target support -CONFIG_IP_NF_TARGET_MASQUERADE - Masquerading is a special case of NAT: all outgoing connections are - changed to seem to come from a particular interface's address, and - if the interface goes down, those connections are lost. This is - only useful for dialup accounts with dynamic IP address (ie. your IP - address will be different on next dialup). - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -Basic SNMP-ALG support -CONFIG_IP_NF_NAT_SNMP_BASIC - - This module implements an Application Layer Gateway (ALG) for - SNMP payloads. In conjunction with NAT, it allows a network - management system to access multiple private networks with - conflicting addresses. It works by modifying IP addresses - inside SNMP payloads to match IP-layer NAT mapping. - - This is the "basic" form of SNMP-ALG, as described in RFC 2962 - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -REDIRECT target support -CONFIG_IP_NF_TARGET_REDIRECT - REDIRECT is a special case of NAT: all incoming connections are - mapped onto the incoming interface's address, causing the packets to - come to the local machine instead of passing through. This is - useful for transparent proxies. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -Packet mangling -CONFIG_IP_NF_MANGLE - This option adds a `mangle' table to iptables: see the man page for - iptables(8). This table is used for various packet alterations - which can effect how the packet is routed. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -DSCP target support -CONFIG_IP_NF_TARGET_DSCP - This option adds a `DSCP' target, which allows you to create rules in - the iptables mangle table. The selected packet has the DSCP field set - to the hex value provided on the command line; unlike the TOS target - which will only set the legal values within ip.h. - - The DSCP field can be set to any value between 0x0 and 0x4f. It does - take into account that bits 6 and 7 are used by ECN. - - If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `N'. - - - -ECN target support -CONFIG_IP_NF_TARGET_ECN - This option adds a `ECN' target, which can be used in the iptables mangle - table. - - You can use this target to remove the ECN bits from the IPv4 header of - an IP packet. This is particularly useful, if you need to work around - existing ECN blackholes on the internet, but don't want to disable - ECN support in general. - - If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `N'. - - - -TOS target support -CONFIG_IP_NF_TARGET_TOS - This option adds a `TOS' target, which allows you to create rules in - the `mangle' table which alter the Type Of Service field of an IP - packet prior to routing. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -MARK target support -CONFIG_IP_NF_TARGET_MARK - This option adds a `MARK' target, which allows you to create rules - in the `mangle' table which alter the netfilter mark (nfmark) field - associated with the packet prior to routing. This can change - the routing method (see `Use netfilter MARK value as routing - key') and can also be used by other subsystems to change their - behaviour. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -TCPMSS target support -CONFIG_IP_NF_TARGET_TCPMSS - This option adds a `TCPMSS' target, which allows you to alter the - MSS value of TCP SYN packets, to control the maximum size for that - connection (usually limiting it to your outgoing interface's MTU - minus 40). - - This is used to overcome criminally braindead ISPs or servers which - block ICMP Fragmentation Needed packets. The symptoms of this - problem are that everything works fine from your Linux - firewall/router, but machines behind it can never exchange large - packets: - 1) Web browsers connect, then hang with no data received. - 2) Small mail works fine, but large emails hang. - 3) ssh works fine, but scp hangs after initial handshaking. - - Workaround: activate this option and add a rule to your firewall - configuration like: - - iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN \ - -j TCPMSS --clamp-mss-to-pmtu - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -Helper match support -CONFIG_IP_NF_MATCH_HELPER - Helper matching allows you to match packets in dynamic connections - tracked by a conntrack-helper, ie. ip_conntrack_ftp - - If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `Y'. - -TCPMSS match support -CONFIG_IP_NF_MATCH_TCPMSS - This option adds a `tcpmss' match, which allows you to examine the - MSS value of TCP SYN packets, which control the maximum packet size - for that connection. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -ULOG target support -CONFIG_IP_NF_TARGET_ULOG - This option adds a `ULOG' target, which allows you to create rules in - any iptables table. The packet is passed to a userspace logging - daemon using netlink multicast sockets; unlike the LOG target - which can only be viewed through syslog. - - The appropriate userspace logging daemon (ulogd) may be obtained from - - - If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `N'. - -LOG target support -CONFIG_IP_NF_TARGET_LOG - This option adds a `LOG' target, which allows you to create rules in - any iptables table which records the packet header to the syslog. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -ipchains (2.2-style) support -CONFIG_IP_NF_COMPAT_IPCHAINS - This option places ipchains (with masquerading and redirection - support) back into the kernel, using the new netfilter - infrastructure. It is not recommended for new installations (see - `Packet filtering'). With this enabled, you should be able to use - the ipchains tool exactly as in 2.2 kernels. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -ipfwadm (2.0-style) support -CONFIG_IP_NF_COMPAT_IPFWADM - This option places ipfwadm (with masquerading and redirection - support) back into the kernel, using the new netfilter - infrastructure. It is not recommended for new installations (see - `Packet filtering'). With this enabled, you should be able to use - the ipfwadm tool exactly as in 2.0 kernels. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -EUI64 address check (EXPERIMENTAL) -CONFIG_IP6_NF_MATCH_EUI64 - This module performs checking on the IPv6 source address - Compares the last 64 bits with the EUI64 (delivered - from the MAC address) address - - If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `N'. - -MAC address match support -CONFIG_IP6_NF_MATCH_MAC - mac matching allows you to match packets based on the source - Ethernet address of the packet. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -length match support -CONFIG_IP6_NF_MATCH_LENGTH - This option allows you to match the length of a packet against a - specific value or range of values. - - If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `N'. - -Netfilter MARK match support -CONFIG_IP6_NF_MATCH_MARK - Netfilter mark matching allows you to match packets based on the - `nfmark' value in the packet. This can be set by the MARK target - (see below). - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -Multiple port match support -CONFIG_IP6_NF_MATCH_MULTIPORT - Multiport matching allows you to match TCP or UDP packets based on - a series of source or destination ports: normally a rule can only - match a single range of ports. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -IPV6 queue handler (EXPERIMENTAL) -CONFIG_IP6_NF_QUEUE - - This option adds a queue handler to the kernel for IPv6 - packets which lets us to receive the filtered packets - with QUEUE target using libiptc as we can do with - the IPv4 now. - - (C) Fernando Anton 2001 - IPv64 Project - Work based in IPv64 draft by Arturo Azcorra. - Universidad Carlos III de Madrid - Universidad Politecnica de Alcala de Henares - email: fanton@it.uc3m.es - - If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `N'. - -Owner match support -CONFIG_IP6_NF_MATCH_OWNER - Packet owner matching allows you to match locally-generated packets - based on who created them: the user, group, process or session. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -Packet filtering -CONFIG_IP6_NF_FILTER - Packet filtering defines a table `filter', which has a series of - rules for simple packet filtering at local input, forwarding and - local output. See the man page for iptables(8). - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -Packet mangling -CONFIG_IP6_NF_MANGLE - This option adds a `mangle' table to iptables: see the man page for - iptables(8). This table is used for various packet alterations - which can effect how the packet is routed. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -MARK target support -CONFIG_IP6_NF_TARGET_MARK - This option adds a `MARK' target, which allows you to create rules - in the `mangle' table which alter the netfilter mark (nfmark) field - associated with the packet packet prior to routing. This can change - the routing method (see `Use netfilter MARK value as routing - key') and can also be used by other subsystems to change their - behaviour. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -ARP tables support -CONFIG_IP_NF_ARPTABLES - arptables is a general, extensible packet identification framework. - The ARP packet filtering and mangling (manipulation)subsystems - use this: say Y or M here if you want to use either of those. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -ARP packet filtering -CONFIG_IP_NF_ARPFILTER - ARP packet filtering defines a table `filter', which has a series of - rules for simple ARP packet filtering at local input and - local output. See the man page for arptables(8). - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -ARP payload mangling -CONFIG_IP_NF_ARP_MANGLE - Allows altering the ARP packet payload: source and destination - hardware and network addresses. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -TCP Explicit Congestion Notification support -CONFIG_INET_ECN - Explicit Congestion Notification (ECN) allows routers to notify - clients about network congestion, resulting in fewer dropped packets - and increased network performance. This option adds ECN support to - the Linux kernel, as well as a sysctl (/proc/sys/net/ipv4/tcp_ecn) - which allows ECN support to be disabled at runtime. - - Note that, on the Internet, there are many broken firewalls which - refuse connections from ECN-enabled machines, and it may be a while - before these firewalls are fixed. Until then, to access a site - behind such a firewall (some of which are major sites, at the time - of this writing) you will have to disable this option, either by - saying N now or by using the sysctl. - - If in doubt, say N. - -IPv6 tables support (required for filtering/masq/NAT) -CONFIG_IP6_NF_IPTABLES - ip6tables is a general, extensible packet identification framework. - Currently only the packet filtering and packet mangling subsystem - for IPv6 use this, but connection tracking is going to follow. - Say 'Y' or 'M' here if you want to use either of those. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -IPv6 limit match support -CONFIG_IP6_NF_MATCH_LIMIT - limit matching allows you to control the rate at which a rule can be - matched: mainly useful in combination with the LOG target ("LOG - target support", below) and to avoid some Denial of Service attacks. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -LOG target support -CONFIG_IP6_NF_TARGET_LOG - This option adds a `LOG' target, which allows you to create rules in - any iptables table which records the packet header to the syslog. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -IP: virtual server support -CONFIG_IP_VS - IP Virtual Server support will let you build a high-performance - virtual server based on cluster of two or more real servers. This - option must be enabled for at least one of the clustered computers - that will take care of intercepting incomming connections to a - single IP address and scheduling them to real servers. - - Three request dispatching techniques are implemented, they are - virtual server via NAT, virtual server via tunneling and virtual - server via direct routing. The several scheduling algorithms can - be used to choose which server the connection is directed to, - thus load balancing can be achieved among the servers. For more - information and its administration program, please visit the - following URL: - http://www.linuxvirtualserver.org/ - - If you want to compile it in kernel, say Y. If you want to compile - it as a module, say M here and read Documentation/modules.txt. If - unsure, say N. - -IP virtual server debugging -CONFIG_IP_VS_DEBUG - Say Y here if you want to get additional messages useful in - debugging the IP virtual server code. You can change the debug - level in /proc/sys/net/ipv4/vs/debug_level - -IPVS connection hash table size (the Nth power of 2) -CONFIG_IP_VS_TAB_BITS - The IPVS connection hash table uses the chaining scheme to handle - hash collisions. Using a big IPVS connection hash table will greatly - reduce conflicts when there are hundreds of thousands of connections - in the hash table. - - Note the table size must be power of 2. The table size will be the - value of 2 to the your input number power. The number to choose is - from 8 to 20, the default number is 12, which means the table size - is 4096. Don't input the number too small, otherwise you will lose - performance on it. You can adapt the table size yourself, according - to your virtual server application. It is good to set the table size - not far less than the number of connections per second multiplying - average lasting time of connection in the table. For example, your - virtual server gets 200 connections per second, the connection lasts - for 200 seconds in average in the connection table, the table size - should be not far less than 200x200, it is good to set the table - size 32768 (2**15). - - Another note that each connection occupies 128 bytes effectively and - each hash entry uses 8 bytes, so you can estimate how much memory is - needed for your box. - -IPVS: round-robin scheduling -CONFIG_IP_VS_RR - The robin-robin scheduling algorithm simply directs network - connections to different real servers in a round-robin manner. - - If you want to compile it in kernel, say Y. If you want to compile - it as a module, say M here and read Documentation/modules.txt. If - unsure, say N. - -IPVS: weighted round-robin scheduling -CONFIG_IP_VS_WRR - The weighted robin-robin scheduling algorithm directs network - connections to different real servers based on server weights - in a round-robin manner. Servers with higher weights receive - new connections first than those with less weights, and servers - with higher weights get more connections than those with less - weights and servers with equal weights get equal connections. - - If you want to compile it in kernel, say Y. If you want to compile - it as a module, say M here and read Documentation/modules.txt. If - unsure, say N. - -IPVS: least-connection scheduling -CONFIG_IP_VS_LC - The least-connection scheduling algorithm directs network - connections to the server with the least number of active - connections. - - If you want to compile it in kernel, say Y. If you want to compile - it as a module, say M here and read Documentation/modules.txt. If - unsure, say N. - -IPVS: weighted least-connection scheduling -CONFIG_IP_VS_WLC - The weighted least-connection scheduling algorithm directs network - connections to the server with the least active connections - normalized by the server weight. - - If you want to compile it in kernel, say Y. If you want to compile - it as a module, say M here and read Documentation/modules.txt. If - unsure, say N. - -IPVS: locality-based least-connection scheduling -CONFIG_IP_VS_LBLC - The locality-based least-connection scheduling algorithm is for - destination IP load balancing. It is usually used in cache cluster. - This algorithm usually directs packet destined for an IP address to - its server if the server is alive and under load. If the server is - overloaded (its active connection numbers is larger than its weight) - and there is a server in its half load, then allocate the weighted - least-connection server to this IP address. - - If you want to compile it in kernel, say Y. If you want to compile - it as a module, say M here and read Documentation/modules.txt. If - unsure, say N. - -IPVS: locality-based least-connection with replication scheduling -CONFIG_IP_VS_LBLCR - The locality-based least-connection with replication scheduling - algorithm is also for destination IP load balancing. It is - usually used in cache cluster. It differs from the LBLC scheduling - as follows: the load balancer maintains mappings from a target - to a set of server nodes that can serve the target. Requests for - a target are assigned to the least-connection node in the target's - server set. If all the node in the server set are over loaded, - it picks up a least-connection node in the cluster and adds it - in the sever set for the target. If the server set has not been - modified for the specified time, the most loaded node is removed - from the server set, in order to avoid high degree of replication. - - If you want to compile it in kernel, say Y. If you want to compile - it as a module, say M here and read Documentation/modules.txt. If - unsure, say N. - -IPVS: destination hashing scheduling -CONFIG_IP_VS_DH - The destination hashing scheduling algorithm assigns network - connections to the servers through looking up a statically assigned - hash table by their destination IP addresses. - - If you want to compile it in kernel, say Y. If you want to compile - it as a module, say M here and read Documentation/modules.txt. If - unsure, say N. - -IPVS: source hashing scheduling -CONFIG_IP_VS_SH - The source hashing scheduling algorithm assigns network - connections to the servers through looking up a statically assigned - hash table by their source IP addresses. - - If you want to compile it in kernel, say Y. If you want to compile - it as a module, say M here and read Documentation/modules.txt. If - unsure, say N. - -IPVS: shortest expected delay scheduling -CONFIG_IP_VS_SED - The shortest expected delay scheduling algorithm assigns network - connections to the server with the shortest expected delay. The - expected delay that the job will experience is (Ci + 1) / Ui if - sent to the ith server, in which Ci is the number of connections - on the the ith server and Ui is the fixed service rate (weight) - of the ith server. - - If you want to compile it in kernel, say Y. If you want to compile - it as a module, say M here and read Documentation/modules.txt. If - unsure, say N. - -IPVS: never queue scheduling -CONFIG_IP_VS_NQ - The never queue scheduling algorithm adopts a two-speed model. - When there is an idle server available, the job will be sent to - the idle server, instead of waiting for a fast one. When there - is no idle server available, the job will be sent to the server - that minimize its expected delay (The Shortest Expected Delay - scheduling algorithm). - - If you want to compile it in kernel, say Y. If you want to compile - it as a module, say M here and read Documentation/modules.txt. If - unsure, say N. - -IPVS: FTP protocol helper -CONFIG_IP_VS_FTP - FTP is a protocol that transfers IP address and/or port number in - the payload. In the virtual server via Network Address Translation, - the IP address and port number of real servers cannot be sent to - clients in ftp connections directly, so FTP protocol helper is - required for tracking the connection and mangling it back to that of - virtual service. - - If you want to compile it in kernel, say Y. If you want to compile - it as a module, say M here and read Documentation/modules.txt. If - unsure, say N. - -AH/ESP match support (EXPERIMENTAL) -CONFIG_IP6_NF_MATCH_AHESP - This module allows one to match AH and ESP packets. - - If you want to compile it as a module, say M here and read - . The modules will be called - ip6t_ah.o and ip6t_esp.o. - - If unsure, say 'N'. - -Routing header match support -CONFIG_IP6_NF_MATCH_RT - rt matching allows you to match packets based on the routing - header of the packet. - - If you want to compile it as a module, say M here and read - . The module will be called - ip6t_rt.o. - - If unsure, say 'N'. - -Hop-by-hop and Dst opts header match support -CONFIG_IP6_NF_MATCH_OPTS - This allows one to match packets based on the hop-by-hop - and destination options headers of a packet. - - If you want to compile it as a module, say M here and read - . The modules will be called - ip6t_hbh.o and ip6t_dst.o. - - If unsure, say 'N'. - -Fragmentation header match support -CONFIG_IP6_NF_MATCH_FRAG - frag matching allows you to match packets based on the fragmentation - header of the packet. - - If you want to compile it as a module, say M here and read - . The module will be called - ip6t_frag.o. - - If unsure, say 'N'. - -HL match support -CONFIG_IP6_NF_MATCH_HL - HL matching allows you to match packets based on the hop - limit of the packet. - - If you want to compile it as a module, say M here and read - . The module will be called - ip6t_hl.o. - - If unsure, say 'N'. - -IPv6 Extension Headers Match (EXPERIMENTAL) -CONFIG_IP6_NF_MATCH_IPV6HEADER - This module allows one to match packets based upon - the ipv6 extension headers. - - If you want to compile it as a module, say M here and read - . The module will be called - ip6t_ipv6header.o. - - If unsure, say 'N'. - -SYN flood protection -CONFIG_SYN_COOKIES - Normal TCP/IP networking is open to an attack known as "SYN - flooding". This denial-of-service attack prevents legitimate remote - users from being able to connect to your computer during an ongoing - attack and requires very little work from the attacker, who can - operate from anywhere on the Internet. - - SYN cookies provide protection against this type of attack. If you - say Y here, the TCP/IP stack will use a cryptographic challenge - protocol known as "SYN cookies" to enable legitimate users to - continue to connect, even when your machine is under attack. There - is no need for the legitimate users to change their TCP/IP software; - SYN cookies work transparently to them. For technical information - about SYN cookies, check out . - - If you are SYN flooded, the source address reported by the kernel is - likely to have been forged by the attacker; it is only reported as - an aid in tracing the packets to their actual source and should not - be taken as absolute truth. - - SYN cookies may prevent correct error reporting on clients when the - server is really overloaded. If this happens frequently better turn - them off. - - If you say Y here, note that SYN cookies aren't enabled by default; - you can enable them by saying Y to "/proc file system support" and - "Sysctl support" below and executing the command - - echo 1 >/proc/sys/net/ipv4/tcp_syncookies - - at boot time after the /proc file system has been mounted. - - If unsure, say N. - -# Choice: alphatype -Alpha system type -CONFIG_ALPHA_GENERIC - This is the system type of your hardware. A "generic" kernel will - run on any supported Alpha system. However, if you configure a - kernel for your specific system, it will be faster and smaller. - - To find out what type of Alpha system you have, you may want to - check out the Linux/Alpha FAQ, accessible on the WWW from - . In summary: - - Alcor/Alpha-XLT AS 600 - Alpha-XL XL-233, XL-266 - AlphaBook1 Alpha laptop - Avanti AS 200, AS 205, AS 250, AS 255, AS 300, AS 400 - Cabriolet AlphaPC64, AlphaPCI64 - DP264 DP264 - EB164 EB164 21164 evaluation board - EB64+ EB64+ 21064 evaluation board - EB66 EB66 21066 evaluation board - EB66+ EB66+ 21066 evaluation board - Jensen DECpc 150, DEC 2000 model 300, - DEC 2000 model 500 - LX164 AlphaPC164-LX - Miata Personal Workstation 433a, 433au, 500a, - 500au, 600a, or 600au - Mikasa AS 1000 - Noname AXPpci33, UDB (Multia) - Noritake AS 1000A, AS 600A, AS 800 - PC164 AlphaPC164 - Rawhide AS 1200, AS 4000, AS 4100 - Ruffian RPX164-2, AlphaPC164-UX, AlphaPC164-BX - SX164 AlphaPC164-SX - Sable AS 2000, AS 2100 - Shark DS 20L - Takara Takara - Titan Privateer - Wildfire AlphaServer GS 40/80/160/320 - - If you don't know what to do, choose "generic". - -# Most of the information on these variants is from -# -Alcor/Alpha-XLT -CONFIG_ALPHA_ALCOR - For systems using the Digital ALCOR chipset: 5 chips (4, 64-bit data - slices (Data Switch, DSW) - 208-pin PQFP and 1 control (Control, I/O - Address, CIA) - a 383 pin plastic PGA). It provides a DRAM - controller (256-bit memory bus) and a PCI interface. It also does - all the work required to support an external Bcache and to maintain - memory coherence when a PCI device DMAs into (or out of) memory. - -Alpha-XL -CONFIG_ALPHA_XL - XL-233 and XL-266-based Alpha systems. - -AlphaBook1 -CONFIG_ALPHA_BOOK1 - Dec AlphaBook1/Burns Alpha-based laptops. - -Avanti -CONFIG_ALPHA_AVANTI - Avanti AS 200, AS 205, AS 250, AS 255, AS 300, and AS 400-based - Alphas. Info at - . - -Cabriolet -CONFIG_ALPHA_CABRIOLET - Cabriolet AlphaPC64, AlphaPCI64 systems. Derived from EB64+ but now - baby-AT with Flash boot ROM, no on-board SCSI or Ethernet. 3 ISA - slots, 4 PCI slots (one pair are on a shared slot), uses plug-in - Bcache SIMMs. Requires power supply with 3.3V output. - -DP264 -CONFIG_ALPHA_DP264 - Various 21264 systems with the tsunami core logic chipset. - API Networks: 264DP, UP2000(+), CS20; - Compaq: DS10(E,L), XP900, XP1000, DS20(E), ES40. - -EB164 -CONFIG_ALPHA_EB164 - EB164 21164 evaluation board from DEC. Uses 21164 and ALCOR. Has - ISA and PCI expansion (3 ISA slots, 2 64-bit PCI slots (one is - shared with an ISA slot) and 2 32-bit PCI slots. Uses plus-in - Bcache SIMMs. I/O sub-system provides SuperI/O (2S, 1P, FD), KBD, - MOUSE (PS2 style), RTC/NVRAM. Boot ROM is Flash. PC-AT-sized - motherboard. Requires power supply with 3.3V output. - -EB64+ -CONFIG_ALPHA_EB64P - Uses 21064 or 21064A and APECs. Has ISA and PCI expansion (3 ISA, - 2 PCI, one pair are on a shared slot). Supports 36-bit DRAM SIMs. - ISA bus generated by Intel SaturnI/O PCI-ISA bridge. On-board SCSI - (NCR 810 on PCI) Ethernet (Digital 21040), KBD, MOUSE (PS2 style), - SuperI/O (2S, 1P, FD), RTC/NVRAM. Boot ROM is EPROM. PC-AT size. - Runs from standard PC power supply. - -EB66 -CONFIG_ALPHA_EB66 - A Digital DS group board. Uses 21066 or 21066A. I/O sub-system is - identical to EB64+. Baby PC-AT size. Runs from standard PC power - supply. The EB66 schematic was published as a marketing poster - advertising the 21066 as "the first microprocessor in the world with - embedded PCI". - -EB66+ -CONFIG_ALPHA_EB66P - Later variant of the EB66 board. - -Eiger -CONFIG_ALPHA_EIGER - Apparently an obscure OEM single-board computer based on the - Typhoon/Tsunami chipset family. Information on it is scanty. - -Jensen -CONFIG_ALPHA_JENSEN - DEC PC 150 AXP (aka Jensen): This is a very old Digital system - one - of the first-generation Alpha systems. A number of these systems - seem to be available on the second- hand market. The Jensen is a - floor-standing tower system which originally used a 150MHz 21064 It - used programmable logic to interface a 486 EISA I/O bridge to the - CPU. - -LX164 -CONFIG_ALPHA_LX164 - A technical overview of this board is available at - . - -Miata -CONFIG_ALPHA_MIATA - The Digital PersonalWorkStation (PWS 433a, 433au, 500a, 500au, 600a, - or 600au). There is an Installation HOWTO for this hardware at - . - -Mikasa -CONFIG_ALPHA_MIKASA - AlphaServer 1000-based Alpha systems. - -Nautilus -CONFIG_ALPHA_NAUTILUS - Alpha systems based on the AMD 751 & ALI 1543C chipsets. - -Noname -CONFIG_ALPHA_NONAME - The AXPpci33 (aka NoName), is based on the EB66 (includes the Multia - UDB). This design was produced by Digital's Technical OEM (TOEM) - group. It uses the 21066 processor running at 166MHz or 233MHz. It - is a baby-AT size, and runs from a standard PC power supply. It has - 5 ISA slots and 3 PCI slots (one pair are a shared slot). There are - 2 versions, with either PS/2 or large DIN connectors for the - keyboard. - -Noritake -CONFIG_ALPHA_NORITAKE - AlphaServer 1000A, AlphaServer 600A, and AlphaServer 800-based - systems. - -Rawhide -CONFIG_ALPHA_RAWHIDE - AlphaServer 1200, AlphaServer 4000 and AlphaServer 4100 machines. - See HOWTO at - . - -Ruffian -CONFIG_ALPHA_RUFFIAN - Samsung APC164UX. There is a page on known problems and workarounds - at . - -Sable -CONFIG_ALPHA_SABLE - Digital AlphaServer 2000 and 2100-based systems. - -Takara -CONFIG_ALPHA_TAKARA - Alpha 11164-based OEM single-board computer. - -Wildfire -CONFIG_ALPHA_WILDFIRE - AlphaServer GS 40/80/160/320 SMP based on the EV67 core. - -EV5 CPU daughtercard (model 5/xxx) -CONFIG_ALPHA_PRIMO - Say Y if you have an AS 1000 5/xxx or an AS 1000A 5/xxx. - -EV5 CPU(s) (model 5/xxx) -CONFIG_ALPHA_GAMMA - Say Y if you have an AS 2000 5/xxx or an AS 2100 5/xxx. - -EV67 (or later) CPU (speed > 600MHz)? -CONFIG_ALPHA_EV67 - Is this a machine based on the EV67 core? If in doubt, select N here - and the machine will be treated as an EV6. - -Use SRM as bootloader -CONFIG_ALPHA_SRM - There are two different types of booting firmware on Alphas: SRM, - which is command line driven, and ARC, which uses menus and arrow - keys. Details about the Linux/Alpha booting process are contained in - the Linux/Alpha FAQ, accessible on the WWW from - . - - The usual way to load Linux on an Alpha machine is to use MILO - (a bootloader that lets you pass command line parameters to the - kernel just like lilo does for the x86 architecture) which can be - loaded either from ARC or can be installed directly as a permanent - firmware replacement from floppy (which requires changing a certain - jumper on the motherboard). If you want to do either of these, say N - here. If MILO doesn't work on your system (true for Jensen - motherboards), you can bypass it altogether and boot Linux directly - from an SRM console; say Y here in order to do that. Note that you - won't be able to boot from an IDE disk using old versions of SRM. - - If unsure, say N. - -Legacy kernel start address -CONFIG_ALPHA_LEGACY_START_ADDRESS - The 2.4 kernel changed the kernel start address from 0x310000 - to 0x810000 to make room for the Wildfire's larger SRM console. - - If you're using aboot 0.7 or later, the bootloader will examine the - ELF headers to determine where to transfer control. Unfortunately, - most older bootloaders -- APB or MILO -- hardcoded the kernel start - address rather than examining the ELF headers, and the result is a - hard lockup. - - Say Y if you have a broken bootloader. Say N if you do not, or if - you wish to run on Wildfire. - -Large VMALLOC support -CONFIG_ALPHA_LARGE_VMALLOC - Process creation and other aspects of virtual memory management can - be streamlined if we restrict the kernel to one PGD for all vmalloc - allocations. This equates to about 8GB. - - Under normal circumstances, this is so far and above what is needed - as to be laughable. However, there are certain applications (such - as benchmark-grade in-kernel web serving) that can make use of as - much vmalloc space as is available. - - Say N unless you know you need gobs and gobs of vmalloc space. - -Non-standard serial port support -CONFIG_SERIAL_NONSTANDARD - Say Y here if you have any non-standard serial boards -- boards - which aren't supported using the standard "dumb" serial driver. - This includes intelligent serial boards such as Cyclades, - Digiboards, etc. These are usually used for systems that need many - serial ports because they serve many terminals or dial-in - connections. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about non-standard serial boards. - - Most people can say N here. - -Extended dumb serial driver options -CONFIG_SERIAL_EXTENDED - If you wish to use any non-standard features of the standard "dumb" - driver, say Y here. This includes HUB6 support, shared serial - interrupts, special multiport support, support for more than the - four COM 1/2/3/4 boards, etc. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about serial driver options. If unsure, say N. - -Support more than 4 serial ports -CONFIG_SERIAL_MANY_PORTS - Say Y here if you have dumb serial boards other than the four - standard COM 1/2/3/4 ports. This may happen if you have an AST - FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available - from ), or other custom - serial port hardware which acts similar to standard serial port - hardware. If you only use the standard COM 1/2/3/4 ports, you can - say N here to save some memory. You can also say Y if you have an - "intelligent" multiport card such as Cyclades, Digiboards, etc. - -Support for sharing serial interrupts -CONFIG_SERIAL_SHARE_IRQ - Some serial boards have hardware support which allows multiple dumb - serial ports on the same board to share a single IRQ. To enable - support for this in the serial driver, say Y here. - -Auto-detect IRQ on standard ports (unsafe) -CONFIG_SERIAL_DETECT_IRQ - Say Y here if you want the kernel to try to guess which IRQ - to use for your serial port. - - This is considered unsafe; it is far better to configure the IRQ in - a boot script using the setserial command. - - If unsure, say N. - -Support special multiport boards -CONFIG_SERIAL_MULTIPORT - Some multiport serial ports have special ports which are used to - signal when there are any serial ports on the board which need - servicing. Say Y here to enable the serial driver to take advantage - of those special I/O ports. - -SGI IP22 Zilog85C30 serial support -CONFIG_IP22_SERIAL - If you want to use your IP22's built-in serial ports under Linux, - answer Y. - -SGI Newport Console support -CONFIG_SGI_NEWPORT_CONSOLE - Say Y here if you want the console on the Newport aka XL graphics - card of your Indy. Most people say Y here. - -SGI DS1286 RTC support -CONFIG_SGI_DS1286 - If you say Y here and create a character special file /dev/rtc with - major number 10 and minor number 135 using mknod ("man mknod"), you - will get access to the real time clock built into your computer. - Every SGI has such a clock built in. It reports status information - via the file /proc/rtc and its behaviour is set by various ioctls on - /dev/rtc. - -Dallas DS1742 RTC Support -CONFIG_DS1742 - If you say Y here and create a character special file /dev/rtc with - major number 10 and minor number 135 using mknod ("man mknod"), you - will get access to the real time clock present on various Toshiba - MIPS-based boards. It reports status information via the file - /proc/driver/rtc and its behaviour is set by various ioctls on - /dev/rtc or /dev/misc/rtc if using devfs. - - For technical information and application notes, please see the - Dallas Semiconductor website: - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called ds1742.o. If you want to compile it as a module, - say M here and read . - -Indy/I2 Hardware Watchdog -CONFIG_INDYDOG - Hardwaredriver for the Indy's/I2's watchdog. This is a - watchdog timer that will reboot the machine after a 60 second - timer expired and no process has written to /dev/watchdog during - that time. - -Support the Bell Technologies HUB6 card -CONFIG_HUB6 - Say Y here to enable support in the dumb serial driver to support - the HUB6 card. - -PCMCIA serial device support -CONFIG_PCMCIA_SERIAL_CS - Say Y here to enable support for 16-bit PCMCIA serial devices, - including serial port cards, modems, and the modem functions of - multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are - credit-card size devices often used with laptops.) - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called serial_cs.o. If you want to compile it as - a module, say M here and read . - If unsure, say N. - -CONFIG_SYNCLINK_CS - Enable support for the SyncLink PC Card serial adapter, running - asynchronous and HDLC communications up to 512Kbps. The port is - selectable for RS-232, V.35, RS-449, RS-530, and X.21 - - This driver may be built as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called synclinkmp.o. If you want to do that, say M - here. - -ACP Modem (Mwave) support -CONFIG_MWAVE - The ACP modem (Mwave) for Linux is a WinModem. It is composed of a - kernel driver and a user level application. Together these components - support direct attachment to public switched telephone networks (PSTNs) - and support selected world wide countries. - - This version of the ACP Modem driver supports the IBM Thinkpad 600E, - 600, and 770 that include on board ACP modem hardware. - - The modem also supports the standard communications port interface - (ttySx) and is compatible with the Hayes AT Command Set. - - The user level application needed to use this driver can be found at - the IBM Linux Technology Center (LTC) web site: - . - - If you own one of the above IBM Thinkpads which has the Mwave chipset - in it, say Y. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called mwave.o. If you want to compile it as - a module, say M here and read Documentation/modules.txt. - -/dev/agpgart (AGP Support) -CONFIG_AGP - AGP (Accelerated Graphics Port) is a bus system mainly used to - connect graphics cards to the rest of the system. - - If you have an AGP system and you say Y here, it will be possible to - use the AGP features of your 3D rendering video card. This code acts - as a sort of "AGP driver" for the motherboard's chipset. - - If you need more texture memory than you can get with the AGP GART - (theoretically up to 256 MB, but in practice usually 64 or 128 MB - due to kernel allocation issues), you could use PCI accesses - and have up to a couple gigs of texture space. - - Note that this is the only means to have XFree4/GLX use - write-combining with MTRR support on the AGP bus. Without it, OpenGL - direct rendering will be a lot slower but still faster than PIO. - - You should say Y here if you use XFree86 3.3.6 or 4.x and want to - use GLX or DRI. If unsure, say N. - - This driver is available as a module. If you want to compile it as - a module, say M here and read . The - module will be called agpgart.o. - -Intel 440LX/BX/GX/815/820/830/840/845/850/860 support -CONFIG_AGP_INTEL - This option gives you AGP support for the GLX component of the - XFree86 4.x on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850 and 860 chipsets. - - You should say Y here if you use XFree86 3.3.6 or 4.x and want to - use GLX or DRI. If unsure, say N. - -Intel 460GX support -CONFIG_AGP_I460 - This option gives you AGP support for the Intel 460GX chipset. This - chipset, the first to support Intel Itanium processors, is new and - this option is correspondingly a little experimental. - - If you don't have a 460GX based machine (such as BigSur) with an AGP - slot then this option isn't going to do you much good. If you're - dying to do Direct Rendering on IA-64, this is what you're looking for. - -Intel I810/I815 DC100/I810e support -CONFIG_AGP_I810 - This option gives you AGP support for the Xserver on the Intel 810 - 815 and 830m chipset boards for their on-board integrated graphics. This - is required to do any useful video modes with these boards. - -VIA chipset support -CONFIG_AGP_VIA - This option gives you AGP support for the GLX component of the - XFree86 4.x on VIA MPV3/Apollo Pro chipsets. - - You should say Y here if you use XFree86 3.3.6 or 4.x and want to - use GLX or DRI. If unsure, say N. - -AMD Irongate, 761, and 762 support -CONFIG_AGP_AMD - This option gives you AGP support for the GLX component of the - XFree86 4.x on AMD Irongate, 761, and 762 chipsets. - - You should say Y here if you use XFree86 3.3.6 or 4.x and want to - use GLX or DRI. If unsure, say N. - -CONFIG_AGP_AMD_K8 - This option gives you AGP support for the GLX component of - XFree86 on an AMD Opteron/Athlon64 using the on-CPU GART. - - You should say Y here if you use XFree86 3.3.6 or 4.x and want to - use GLX or DRI. If unsure, say N. - -Generic SiS support -CONFIG_AGP_SIS - This option gives you AGP support for the GLX component of - XFree86 4.x on Silicon Integrated Systems [SiS] chipsets. - - Note that 5591/5592 AGP chipsets are NOT specifically supported; - However, the driver works well on these, too. - - You should say Y here if you use XFree86 3.3.6 or 4.x and want to - use GLX or DRI. If unsure, say N. - -Serverworks LE/HE support -CONFIG_AGP_SWORKS - Say Y here to support the Serverworks AGP card. See - for product descriptions and images. - -NVIDIA chipset support -CONFIG_AGP_NVIDIA - This option gives you AGP support for the GLX component of the - XFree86 4.x on NVIDIA nForce/nForce2 chipsets. - - You should say Y here if you use XFree86 3.3.6 or 4.x and want to - use GLX or DRI. If unsure, say N. - -ALI chipset support -CONFIG_AGP_ALI - This option gives you AGP support for the GLX component of the - XFree86 4.x on the following ALi chipsets. The supported chipsets - include M1541, M1621, M1631, M1632, M1641,M1647,and M1651. - For the ALi-chipset question, ALi suggests you refer to - . - - The M1541 chipset can do AGP 1x and 2x, but note that there is an - acknowledged incompatibility with Matrox G200 cards. Due to - timing issues, this chipset cannot do AGP 2x with the G200. - This is a hardware limitation. AGP 1x seems to be fine, though. - - You should say Y here if you use XFree86 3.3.6 or 4.x and want to - use GLX or DRI. If unsure, say N. - -CONFIG_AGP_HP_ZX1 - This option gives you AGP GART support for the HP ZX1 chipset - for IA64 processors. - -CONFIG_AGP_ATI - This option gives you AGP support for the GLX component of - XFree86 4.x on the ATI RadeonIGP family of chipsets. - - You should say Y here if you use XFree86 3.3.6 or 4.x and want to - use GLX or DRI. If unsure, say N. - -Support for ISA-bus hardware -CONFIG_ISA - Find out whether you have ISA slots on your motherboard. ISA is the - name of a bus system, i.e. the way the CPU talks to the other stuff - inside your box. Other bus systems are PCI, EISA, MicroChannel - (MCA) or VESA. ISA is an older system, now being displaced by PCI; - newer boards don't support it. If you have ISA, say Y, otherwise N. - -Support for PCI bus hardware -CONFIG_PCI - Find out whether you have a PCI motherboard. PCI is the name of a - bus system, i.e. the way the CPU talks to the other stuff inside - your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or - VESA. If you have PCI, say Y, otherwise N. - - The PCI-HOWTO, available from - , contains valuable - information about which PCI hardware does work under Linux and which - doesn't. - -PCI support -CONFIG_PCI_INTEGRATOR - Find out whether you have a PCI motherboard. PCI is the name of a - bus system, i.e. the way the CPU talks to the other stuff inside - your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or - VESA. If you have PCI, say Y, otherwise N. - - The PCI-HOWTO, available from - , contains valuable - information about which PCI hardware does work under Linux and which - doesn't. - -QSpan PCI -CONFIG_PCI_QSPAN - Find out whether you have a PCI motherboard. PCI is the name of a - bus system, i.e. the way the CPU talks to the other stuff inside - your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or - VESA. If you have PCI, say Y, otherwise N. - - The PCI-HOWTO, available from - , contains valuable - information about which PCI hardware does work under Linux and which - doesn't. - -# Choice: pci_access -PCI access mode -CONFIG_PCI_GOBIOS - On PCI systems, the BIOS can be used to detect the PCI devices and - determine their configuration. However, some old PCI motherboards - have BIOS bugs and may crash if this is done. Also, some embedded - PCI-based systems don't have any BIOS at all. Linux can also try to - detect the PCI hardware directly without using the BIOS. - - With this option, you can specify how Linux should detect the PCI - devices. If you choose "BIOS", the BIOS will be used, if you choose - "Direct", the BIOS won't be used, and if you choose "Any", the - kernel will try the direct access method and falls back to the BIOS - if that doesn't work. If unsure, go with the default, which is - "Any". - -PCI device name database -CONFIG_PCI_NAMES - By default, the kernel contains a database of all known PCI device - names to make the information in /proc/pci, /proc/ioports and - similar files comprehensible to the user. This database increases - size of the kernel image by about 80KB, but it gets freed after the - system boots up, so it doesn't take up kernel memory. Anyway, if you - are building an installation floppy or kernel for an embedded system - where kernel image size really matters, you can disable this feature - and you'll get device ID numbers instead of names. - - When in doubt, say Y. - -Generic PCI hotplug support -CONFIG_HOTPLUG_PCI - Say Y here if you have a motherboard with a PCI Hotplug controller. - This allows you to add and remove PCI cards while the machine is - powered up and running. The file system pcihpfs must be mounted - in order to interact with any PCI Hotplug controllers. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called pci_hotplug.o. If you want to compile it - as a module, say M here and read . - - When in doubt, say N. - -Compaq PCI Hotplug driver -CONFIG_HOTPLUG_PCI_COMPAQ - Say Y here if you have a motherboard with a Compaq PCI Hotplug - controller. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cpqphp.o. If you want to compile it - as a module, say M here and read . - - When in doubt, say N. - -PCI Compaq Hotplug controller NVRAM support -CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM - Say Y here if you have a Compaq server that has a PCI Hotplug - controller. This will allow the PCI Hotplug driver to store the PCI - system configuration options in NVRAM. - - When in doubt, say N. - -ACPI PCI Hotplug driver -CONFIG_HOTPLUG_PCI_ACPI - Say Y here if you have a system that supports PCI Hotplug using - ACPI. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called acpiphp.o. If you want to compile it - as a module, say M here and read . - -MCA support -CONFIG_MCA - MicroChannel Architecture is found in some IBM PS/2 machines and - laptops. It is a bus system similar to PCI or ISA. See - (and especially the web page given - there) before attempting to build an MCA bus kernel. - -Support for EISA-bus hardware -CONFIG_EISA - The Extended Industry Standard Architecture (EISA) bus was - developed as an open alternative to the IBM MicroChannel bus. - - The EISA bus provided some of the features of the IBM MicroChannel - bus while maintaining backward compatibility with cards made for - the older ISA bus. The EISA bus saw limited use between 1988 and - 1995 when it was made obsolete by the PCI bus. - - Say Y here if you are building a kernel for an EISA-based machine. - - Otherwise, say N. - -SGI Visual Workstation support -CONFIG_VISWS - The SGI Visual Workstation series is an IA32-based workstation - based on SGI systems chips with some legacy PC hardware attached. - Say Y here to create a kernel to run on the SGI 320 or 540. - A kernel compiled for the Visual Workstation will not run on other - PC boards and vice versa. - See for more. - -SGI Visual Workstation framebuffer support -CONFIG_FB_SGIVW - SGI Visual Workstation support for framebuffer graphics. - -I2O support -CONFIG_I2O - The Intelligent Input/Output (I2O) architecture allows hardware - drivers to be split into two parts: an operating system specific - module called the OSM and an hardware specific module called the - HDM. The OSM can talk to a whole range of HDM's, and ideally the - HDM's are not OS dependent. This allows for the same HDM driver to - be used under different operating systems if the relevant OSM is in - place. In order for this to work, you need to have an I2O interface - adapter card in your computer. This card contains a special I/O - processor (IOP), thus allowing high speeds since the CPU does not - have to deal with I/O. - - If you say Y here, you will get a choice of interface adapter - drivers and OSM's with the following questions. - - This support is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . You will get modules called - i2o_core.o and i2o_config.o. - - If unsure, say N. - -I2O PCI support -CONFIG_I2O_PCI - Say Y for support of PCI bus I2O interface adapters. Currently this - is the only variety supported, so you should say Y. - - This support is also available as a module called i2o_pci.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -I2O Block OSM -CONFIG_I2O_BLOCK - Include support for the I2O Block OSM. The Block OSM presents disk - and other structured block devices to the operating system. - - This support is also available as a module called i2o_block.o ( = - code which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -I2O LAN OSM -CONFIG_I2O_LAN - Include support for the LAN OSM. You will also need to include - support for token ring or FDDI if you wish to use token ring or FDDI - I2O cards with this driver. - - This support is also available as a module called i2o_lan.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -I2O SCSI OSM -CONFIG_I2O_SCSI - Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel - I2O controller. You can use both the SCSI and Block OSM together if - you wish. - - This support is also available as a module called i2o_scsi.o ( = - code which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -I2O /proc support -CONFIG_I2O_PROC - If you say Y here and to "/proc file system support", you will be - able to read I2O related information from the virtual directory - /proc/i2o. - - This support is also available as a module called i2o_proc.o ( = - code which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Plug and Play support -CONFIG_PNP - Plug and Play (PnP) is a standard for peripherals which allows those - peripherals to be configured by software, e.g. assign IRQ's or other - parameters. No jumpers on the cards are needed, instead the values - are provided to the cards from the BIOS, from the operating system, - or using a user-space utility. - - Say Y here if you would like Linux to configure your Plug and Play - devices. You should then also say Y to "ISA Plug and Play support", - below. Alternatively, you can say N here and configure your PnP - devices using the user space utilities contained in the isapnptools - package. - - This support is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . - -ISA Plug and Play support -CONFIG_ISAPNP - Say Y here if you would like support for ISA Plug and Play devices. - Some information is in . - - This support is also available as a module called isapnp.o ( = - code which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - - If unsure, say Y. - -PNPBIOS support -CONFIG_PNPBIOS - Linux uses the PNPBIOS as defined in "Plug and Play BIOS - Specification Version 1.0A May 5, 1994" to autodetect built-in - mainboard resources (e.g. parallel port resources). - - Other features (e.g. change resources, ESCD, event notification, - Docking station information, ISAPNP services) are not used. - - Note: ACPI is expected to supersede PNPBIOS some day, currently it - co-exists nicely. - - See latest pcmcia-cs (stand-alone package) for a nice "lspnp" tools, - or have a look at /proc/bus/pnp. - - If unsure, say Y. - -Support for hot-pluggable devices -CONFIG_HOTPLUG - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. - -PCMCIA/CardBus support -CONFIG_PCMCIA - Say Y here if you want to attach PCMCIA- or PC-cards to your Linux - computer. These are credit-card size devices such as network cards, - modems or hard drives often used with laptops computers. There are - actually two varieties of these cards: the older 16 bit PCMCIA cards - and the newer 32 bit CardBus cards. If you want to use CardBus - cards, you need to say Y here and also to "CardBus support" below. - - To use your PC-cards, you will need supporting software from David - Hinds' pcmcia-cs package (see the file - for location). Please also read the PCMCIA-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - When compiled this way, there will be modules called pcmcia_core.o - and ds.o. If you want to compile it as a module, say M here and - read . - -CardBus card and (Yenta) bridge support -CONFIG_CARDBUS - CardBus is a bus mastering architecture for PC-cards, which allows - for 32 bit PC-cards (the original PCMCIA standard specifies only - a 16 bit wide bus). Many newer PC-cards are actually CardBus cards. - - This option enables support for CardBus PC Cards, as well as support - for CardBus host bridges. Virtually all modern PCMCIA bridges are - CardBus compatible. A "bridge" is the hardware inside your computer - that PCMCIA cards are plugged into. - - To use your PC-cards, you will need supporting software from David - Hinds' pcmcia-cs package (see the file - for location). - - If unsure, say Y. - -i82092 compatible bridge support -CONFIG_I82092 - This provides support for the Intel I82092AA PCI-to-PCMCIA bridge device, - found in some older laptops and more commonly in evaluation boards for the - chip. - -i82365 compatible host bridge support -CONFIG_I82365 - Say Y here to include support for ISA-bus PCMCIA host bridges that - are register compatible with the Intel i82365. These are found on - older laptops and ISA-bus card readers for desktop systems. A - "bridge" is the hardware inside your computer that PCMCIA cards are - plugged into. If unsure, say N. - -Databook TCIC host bridge support -CONFIG_TCIC - Say Y here to include support for the Databook TCIC family of PCMCIA - host bridges. These are only found on a handful of old systems. - "Bridge" is the name used for the hardware inside your computer that - PCMCIA cards are plugged into. If unsure, say N. - -CONFIG_PCMCIA_SIBYTE - Say Y here to include support for the SiByte SOC's built-in PCMCIA - interface. Only ATA cards and CompactFlash are currently - supported. - -System V IPC -CONFIG_SYSVIPC - Inter Process Communication is a suite of library functions and - system calls which let processes (running programs) synchronize and - exchange information. It is generally considered to be a good thing, - and some programs won't run unless you say Y here. In particular, if - you want to run the DOS emulator dosemu under Linux (read the - DOSEMU-HOWTO, available from - ), you'll need to say Y - here. - - You can find documentation about IPC with "info ipc" and also in - section 6.4 of the Linux Programmer's Guide, available from - . - -BSD Process Accounting -CONFIG_BSD_PROCESS_ACCT - If you say Y here, a user level program will be able to instruct the - kernel (via a special system call) to write process accounting - information to a file: whenever a process exits, information about - that process will be appended to the file by the kernel. The - information includes things such as creation time, owning user, - command name, memory usage, controlling terminal etc. (the complete - list is in the struct acct in ). It is - up to the user level program to do useful things with this - information. This is generally a good idea, so say Y. - -Sysctl support -CONFIG_SYSCTL - The sysctl interface provides a means of dynamically changing - certain kernel parameters and variables on the fly without requiring - a recompile of the kernel or reboot of the system. The primary - interface consists of a system call, but if you say Y to "/proc - file system support", a tree of modifiable sysctl entries will be - generated beneath the /proc/sys directory. They are explained in the - files in . Note that enabling this - option will enlarge the kernel by at least 8 KB. - - As it is generally a good thing, you should say Y here unless - building a kernel for install/rescue disks or your system is very - limited in memory. - -# Choice: kcore -Kernel core (/proc/kcore) format -CONFIG_KCORE_ELF - If you enabled support for /proc file system then the file - /proc/kcore will contain the kernel core image. This can be used - in gdb: - - $ cd /usr/src/linux ; gdb vmlinux /proc/kcore - - You have two choices here: ELF and A.OUT. Selecting ELF will make - /proc/kcore appear in ELF core format as defined by the Executable - and Linking Format specification. Selecting A.OUT will choose the - old "a.out" format which may be necessary for some old versions - of binutils or on some architectures. - - This is especially useful if you have compiled the kernel with the - "-g" option to preserve debugging information. It is mainly used - for examining kernel data structures on the live kernel so if you - don't understand what this means or are not a kernel hacker, just - leave it at its default value ELF. - -Select a.out format for /proc/kcore -CONFIG_KCORE_AOUT - Not necessary unless you're using a very out-of-date binutils - version. You probably want KCORE_ELF. - -Kernel support for ELF binaries -CONFIG_BINFMT_ELF - ELF (Executable and Linkable Format) is a format for libraries and - executables used across different architectures and operating - systems. Saying Y here will enable your kernel to run ELF binaries - and enlarge it by about 13 KB. ELF support under Linux has now all - but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC) - because it is portable (this does *not* mean that you will be able - to run executables from different architectures or operating systems - however) and makes building run-time libraries very easy. Many new - executables are distributed solely in ELF format. You definitely - want to say Y here. - - Information about ELF is contained in the ELF HOWTO available from - . - - If you find that after upgrading from Linux kernel 1.2 and saying Y - here, you still can't run any ELF binaries (they just crash), then - you'll have to install the newest ELF runtime libraries, including - ld.so (check the file for location and - latest version). - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called binfmt_elf.o. Saying M or N here is dangerous because - some crucial programs on your system might be in ELF format. - -Kernel support for a.out binaries -CONFIG_BINFMT_AOUT - A.out (Assembler.OUTput) is a set of formats for libraries and - executables used in the earliest versions of UNIX. Linux used the - a.out formats QMAGIC and ZMAGIC until they were replaced with the - ELF format. - - As more and more programs are converted to ELF, the use for a.out - will gradually diminish. If you disable this option it will reduce - your kernel by one page. This is not much and by itself does not - warrant removing support. However its removal is a good idea if you - wish to ensure that absolutely none of your programs will use this - older executable format. If you don't know what to answer at this - point then answer Y. If someone told you "You need a kernel with - QMAGIC support" then you'll have to say Y here. You may answer M to - compile a.out support as a module and later load the module when you - want to use a program or library in a.out format. The module will be - called binfmt_aout.o. Saying M or N here is dangerous though, - because some crucial programs on your system might still be in A.OUT - format. - -OSF/1 v4 readv/writev compatibility -CONFIG_OSF4_COMPAT - Say Y if you are using OSF/1 binaries (like Netscape and Acrobat) - with v4 shared libraries freely available from Compaq. If you're - going to use shared libraries from Tru64 version 5.0 or later, say N. - -Kernel support for Linux/Intel ELF binaries -CONFIG_BINFMT_EM86 - Say Y here if you want to be able to execute Linux/Intel ELF - binaries just like native Alpha binaries on your Alpha machine. For - this to work, you need to have the emulator /usr/bin/em86 in place. - - You can get the same functionality by saying N here and saying Y to - "Kernel support for MISC binaries". - - You may answer M to compile the emulation support as a module and - later load the module when you want to use a Linux/Intel binary. The - module will be called binfmt_em86.o. If unsure, say Y. - -Kernel support for SOM binaries -CONFIG_BINFMT_SOM - SOM is a binary executable format inherited from HP/UX. Say Y here - to be able to load and execute SOM binaries directly. - -Kernel support for MISC binaries -CONFIG_BINFMT_MISC - If you say Y here, it will be possible to plug wrapper-driven binary - formats into the kernel. You will like this especially when you use - programs that need an interpreter to run like Java, Python or - Emacs-Lisp. It's also useful if you often run DOS executables under - the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from - ). Once you have - registered such a binary class with the kernel, you can start one of - those programs simply by typing in its name at a shell prompt; Linux - will automatically feed it to the correct interpreter. - - You can do other nice things, too. Read the file - to learn how to use this - feature, and for information about how - to include Java support. - - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this part of the kernel. - - You may say M here for module support and later load the module when - you have use for it; the module is called binfmt_misc.o. If you - don't know what to answer at this point, say Y. - -Kernel support for JAVA binaries -CONFIG_BINFMT_JAVA - If you say Y here, the kernel will load and execute Java J-code - binaries directly. Note: this option is obsolete and scheduled for - removal, use CONFIG_BINFMT_MISC instead. - -Solaris binary emulation -CONFIG_SOLARIS_EMUL - This is experimental code which will enable you to run (many) - Solaris binaries on your SPARC Linux machine. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called solaris.o. If you want to compile it as a - module, say M here and read . - -SUN SME environment monitoring -CONFIG_ENVCTRL - Kernel support for temperature and fan monitoring on Sun SME - machines. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called envctrl.o. If you want to compile it as a - module, say M here and read . - -# Choice: x86type -Processor family -CONFIG_M386 - This is the processor type of your CPU. This information is used for - optimizing purposes. In order to compile a kernel that can run on - all x86 CPU types (albeit not optimally fast), you can specify - "386" here. - - The kernel will not necessarily run on earlier architectures than - the one you have chosen, e.g. a Pentium optimized kernel will run on - a PPro, but not necessarily on a i486. - - Here are the settings recommended for greatest speed: - - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI - 486DLC/DLC2, UMC 486SX-S and NexGen Nx586. Only "386" kernels - will run on a 386 class machine. - - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or - SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S. - - "586" for generic Pentium CPUs, possibly lacking the TSC - (time stamp counter) register. - - "Pentium-Classic" for the Intel Pentium. - - "Pentium-MMX" for the Intel Pentium MMX. - - "Pentium-Pro" for the Intel Pentium Pro/Celeron/Pentium II. - - "Pentium-III" for the Intel Pentium III - and Celerons based on the Coppermine core. - - "Pentium-4" for the Intel Pentium 4. - - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D). - - "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird). - - "Elan" for the AMD Elan family (Elan SC400/SC410). - - "Crusoe" for the Transmeta Crusoe series. - - "Winchip-C6" for original IDT Winchip. - - "Winchip-2" for IDT Winchip 2. - - "Winchip-2A" for IDT Winchips with 3dNow! capabilities. - - "CyrixIII" for VIA Cyrix III or VIA C3. - - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above). - - If you don't know what to do, choose "386". - -486 -CONFIG_M486 - Select this for a x486 processor, ether Intel or one of the - compatible processors from AMD, Cyrix, IBM, or Intel. Includes DX, - DX2, and DX4 variants; also SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or - U5S. - -586/K5/5x86/6x86/6x86MX -CONFIG_M586 - Select this for an x586 or x686 processor such as the AMD K5, the - Intel 5x86 or 6x86, or the Intel 6x86MX. This choice does not - assume the RDTSC instruction. - -Pentium Classic -CONFIG_M586TSC - Select this for a Pentium Classic processor with the RDTSC (Read - Time Stamp Counter) instruction for benchmarking. - -VIA C3-2 (Nehemiah) -CONFIG_MVIAC3_2 - Select this for a VIA C3 "Nehemiah". Selecting this enables usage of SSE - and tells gcc to treat the CPU as a 686. - - Note, this kernel will not boot on older (pre model 9) C3s. - -32-bit PDC -CONFIG_PDC_NARROW - Saying Y here will allow developers with a C180, C200, C240, C360, - J200, J210, and/or a J2240 to test 64-bit kernels by providing a - wrapper for the 32-bit PDC calls. Since the machines which require - this option do not support over 4G of RAM, this option is targeted - for developers of these machines wishing to test changes on both - 32-bit and 64-bit configurations. - - If unsure, say N. - -VGA text console -CONFIG_VGA_CONSOLE - Saying Y here will allow you to use Linux in text mode through a - display that complies with the generic VGA standard. Virtually - everyone wants that. - - The program SVGATextMode can be used to utilize SVGA video cards to - their full potential in text mode. Download it from - . - - Say Y. - -Distribute interrupts on all CPUs by default -CONFIG_IRQ_ALL_CPUS - This option gives the kernel permission to distribute IRQs across - multiple CPUs. Saying N here will route all IRQs to the first - CPU. Generally SMP PowerMacs can answer Y. SMP IBM CHRP boxes or - Power3 boxes should say N for now. - -Video mode selection support -CONFIG_VIDEO_SELECT - This enables support for text mode selection on kernel startup. If - you want to take advantage of some high-resolution text mode your - card's BIOS offers, but the traditional Linux utilities like - SVGATextMode don't, you can say Y here and set the mode using the - "vga=" option from your boot loader (lilo or loadlin) or set - "vga=ask" which brings up a video mode menu on kernel startup. (Try - "man bootparam" or see the documentation of your boot loader about - how to pass options to the kernel.) - - Read the file for more information - about the Video mode selection support. If unsure, say N. - -Support for frame buffer devices -CONFIG_FB - The frame buffer device provides an abstraction for the graphics - hardware. It represents the frame buffer of some video hardware and - allows application software to access the graphics hardware through - a well-defined interface, so the software doesn't need to know - anything about the low-level (hardware register) stuff. - - Frame buffer devices work identically across the different - architectures supported by Linux and make the implementation of - application programs easier and more portable; at this point, an X - server exists which uses the frame buffer device exclusively. - On several non-X86 architectures, the frame buffer device is the - only way to use the graphics hardware. - - The device is accessed through special device nodes, usually located - in the /dev directory, i.e. /dev/fb*. - - You need an utility program called fbset to make full use of frame - buffer devices. Please read - and the Framebuffer-HOWTO at - for more - information. - - Say Y here and to the driver for your graphics board below if you - are compiling a kernel for a non-x86 architecture. - - If you are compiling for the x86 architecture, you can say Y if you - want to play with it, but it is not essential. Please note that - running graphical applications that directly touch the hardware - (e.g. an accelerated X server) and that are not frame buffer - device-aware may cause unexpected results. If unsure, say N. - -Acorn VIDC support -CONFIG_FB_ACORN - This is the frame buffer device driver for the Acorn VIDC graphics - hardware found in Acorn RISC PCs and other ARM-based machines. If - unsure, say N. - -Permedia2 support -CONFIG_FB_PM2 - This is the frame buffer device driver for the Permedia2 AGP frame - buffer card from ASK, aka `Graphic Blaster Exxtreme'. There is a - product page at - . - -Enable FIFO disconnect feature -CONFIG_FB_PM2_FIFO_DISCONNECT - Support the Permedia2 FIFOI disconnect feature (see CONFIG_FB_PM2). - -Generic Permedia2 PCI board support -CONFIG_FB_PM2_PCI - Say Y to enable support for Permedia2 AGP frame buffer card from - 3Dlabs (aka `Graphic Blaster Exxtreme') on the PCI bus. - -Phase5 CVisionPPC/BVisionPPC support -CONFIG_FB_PM2_CVPPC - Say Y to enable support for the Amiga Phase 5 CVisionPPC BVisionPPC - framebuffer cards. Phase 5 is no longer with us, alas. - -Amiga native chipset support -CONFIG_FB_AMIGA - This is the frame buffer device driver for the builtin graphics - chipset found in Amigas. - - The driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). The - module will be called amifb.o. If you want to compile it as a - module, say M here and read . - -Amiga OCS chipset support -CONFIG_FB_AMIGA_OCS - This enables support for the original Agnus and Denise video chips, - found in the Amiga 1000 and most A500's and A2000's. If you intend - to run Linux on any of these systems, say Y; otherwise say N. - -Amiga ECS chipset support -CONFIG_FB_AMIGA_ECS - This enables support for the Enhanced Chip Set, found in later - A500's, later A2000's, the A600, the A3000, the A3000T and CDTV. If - you intend to run Linux on any of these systems, say Y; otherwise - say N. - -Amiga AGA chipset support -CONFIG_FB_AMIGA_AGA - This enables support for the Advanced Graphics Architecture (also - known as the AGA or AA) Chip Set, found in the A1200, A4000, A4000T - and CD32. If you intend to run Linux on any of these systems, say Y; - otherwise say N. - -Amiga CyberVision support -CONFIG_FB_CYBER - This enables support for the Cybervision 64 graphics card from - Phase5. Please note that its use is not all that intuitive (i.e. if - you have any questions, be sure to ask!). Say N unless you have a - Cybervision 64 or plan to get one before you next recompile the - kernel. Please note that this driver DOES NOT support the - Cybervision 64 3D card, as they use incompatible video chips. - -CyberPro 20x0 support -CONFIG_FB_CYBER2000 - This enables support for the Integraphics CyberPro 20x0 and 5000 - VGA chips used in the Rebel.com Netwinder and other machines. - Say Y if you have a NetWinder or a graphics card containing this - device, otherwise say N. - -Amiga CyberVision3D support -CONFIG_FB_VIRGE - This enables support for the Cybervision 64/3D graphics card from - Phase5. Please note that its use is not all that intuitive (i.e. if - you have any questions, be sure to ask!). Say N unless you have a - Cybervision 64/3D or plan to get one before you next recompile the - kernel. Please note that this driver DOES NOT support the older - Cybervision 64 card, as they use incompatible video chips. - -Amiga RetinaZ3 support -CONFIG_FB_RETINAZ3 - This enables support for the Retina Z3 graphics card. Say N unless - you have a Retina Z3 or plan to get one before you next recompile - the kernel. - -Cirrus Logic generic driver -CONFIG_FB_CLGEN - This enables support for Cirrus Logic GD542x/543x based boards on - Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum. - - If you have a PCI-based system, this enables support for these - chips: GD-543x, GD-544x, GD-5480. - - Please read the file . - - Say N unless you have such a graphics board or plan to get one - before you next recompile the kernel. - -Apollo support -CONFIG_APOLLO - Say Y here if you want to run Linux on an MC680x0-based Apollo - Domain workstation such as the DN3500. - -Apollo 3c505 "EtherLink Plus" support -CONFIG_APOLLO_ELPLUS - Say Y or M here if your Apollo has a 3Com 3c505 ISA Ethernet card. - If you don't have one made for Apollos, you can use one from a PC, - except that your Apollo won't be able to boot from it (because the - code in the ROM will be for a PC). - -Atari native chipset support -CONFIG_FB_ATARI - This is the frame buffer device driver for the builtin graphics - chipset found in Ataris. - -Amiga FrameMaster II/Rainbow II support -CONFIG_FB_FM2 - This is the frame buffer device driver for the Amiga FrameMaster - card from BSC (exhibited 1992 but not shipped as a CBM product). - -Open Firmware frame buffer device support -CONFIG_FB_OF - Say Y if you want support with Open Firmware for your graphics - board. - -S3 Trio frame buffer device support -CONFIG_FB_S3TRIO - If you have a S3 Trio say Y. Say N for S3 Virge. - -3Dfx Banshee/Voodoo3 display support -CONFIG_FB_3DFX - This driver supports graphics boards with the 3Dfx Banshee/Voodoo3 - chips. Say Y if you have such a graphics board. - - The driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). The - module will be called tdfxfb.o. If you want to compile it as a - module, say M here and read . - -nVidia Riva support -CONFIG_FB_RIVA - This driver supports graphics boards with the nVidia Riva/Geforce - chips. - Say Y if you have such a graphics board. - - The driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). The - module will be called rivafb.o. If you want to compile it as a - module, say M here and read . - -Trident Blade/Image support -CONFIG_FB_TRIDENT - This driver is supposed to support graphics boards with the - Trident CyberXXXX/Image/CyberBlade chips mostly found in laptops - but also on some motherboards.Read - - Say Y if you have such a graphics board. - - The driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). The - module will be called tridentfb.o. If you want to compile it as a - module, say M here and read . - -ATI Mach64 display support -CONFIG_FB_ATY - This driver supports graphics boards with the ATI Mach64 chips. - Say Y if you have such a graphics board. - - The driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). The - module will be called atyfb.o. If you want to compile it as a - module, say M here and read . - -ATI Rage128 display support -CONFIG_FB_ATY128 - This driver supports graphics boards with the ATI Rage128 chips. - Say Y if you have such a graphics board and read - . - - The driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). The - module will be called aty128fb.o. If you want to compile it as a - module, say M here and read . - -Maxine (Personal DECstation) onboard framebuffer support -CONFIG_FB_MAXINE - Support for the onboard framebuffer (1024x768x8) in the Personal - DECstation series (Personal DECstation 5000/20, /25, /33, /50, - Codename "Maxine"). - -PMAG-AA TURBOchannel framebuffer support -CONFIG_FB_PMAG_AA - Support for the PMAG-AA TURBOchannel framebuffer card (1280x1024x1) - used mainly in the MIPS-based DECstation series. - -PMAG-BA TURBOchannel framebuffer support -CONFIG_FB_PMAG_BA - Support for the PMAG-BA TURBOchannel framebuffer card (1024x864x8) - used mainly in the MIPS-based DECstation series. - -PMAGB-B TURBOchannel framebuffer support -CONFIG_FB_PMAGB_B - Support for the PMAGB-B TURBOchannel framebuffer card used mainly - in the MIPS-based DECstation series. The card is currently only - supported in 1280x1024x8 mode. - -FutureTV PCI card -CONFIG_ARCH_FTVPCI - Say Y here if you intend to run this kernel on a FutureTV (nee Nexus - Electronics) StrongARM PCI card. - -ANAKIN Vehicle Telematics Platform -CONFIG_ARCH_ANAKIN - The Anakin is a StrongArm based SA110 - 2 DIN Vehicle Telematics Platform. - 64MB SDRAM - 4 Mb Flash - Compact Flash Interface - 1 MB VRAM - - On board peripherals: - * Front display: 400x234 16 bit TFT touchscreen - * External independent second screen interface - * CAN controller SJA1000 - * USB host controller - * 6 channel video codec with hardware overlay - * Smartcard reader - * IrDa - - Modules interfaced over the Multi Media Extension slots: - * A communication card - Wavecom GPRS modem - uBlock GPS - Bosch DAB module - * An audio card ( 4 * 40W, AC97 Codec, I2S) - -Altera Excalibur XA10 Dev Board -ARCH_CAMELOT - This enables support for Altera's Excalibur XA10 development board. - If you would like to build your kernel to run on one of these boards - then you must say 'Y' here. Otherwise say 'N' - -Link-Up Systems LCD support -CONFIG_FB_L7200 - This driver supports the L7200 Color LCD. - Say Y if you want graphics support. - -NeoMagic display support (EXPERIMENTAL) -CONFIG_FB_NEOMAGIC - This driver supports notebooks with NeoMagic PCI chips. - Say Y if you have such a graphics card. - - The driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). The - module will be called neofb.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. - -PowerMac "control" frame buffer device support -CONFIG_FB_CONTROL - This driver supports a frame buffer for the graphics adapter in the - Power Macintosh 7300 and others. - -PowerMac "platinum" frame buffer device support -CONFIG_FB_PLATINUM - This driver supports a frame buffer for the "platinum" graphics - adapter in some Power Macintoshes. - -PowerMac "valkyrie" frame buffer device support -CONFIG_FB_VALKYRIE - This driver supports a frame buffer for the "valkyrie" graphics - adapter in some Power Macintoshes. - -Chips 65550 display support -CONFIG_FB_CT65550 - This is the frame buffer device driver for the Chips & Technologies - 65550 graphics chip in PowerBooks. - -TGA frame buffer support -CONFIG_FB_TGA - This is the frame buffer device driver for generic TGA graphic - cards. Say Y if you have one of those. - -VESA VGA graphics console -CONFIG_FB_VESA - This is the frame buffer device driver for generic VESA 2.0 - compliant graphic cards. The older VESA 1.2 cards are not supported. - You will get a boot time penguin logo at no additional cost. Please - read . If unsure, say Y. - -VGA 16-color planar support -CONFIG_FBCON_VGA_PLANES - This low level frame buffer console driver enable the kernel to use - the 16-color planar modes of the old VGA cards where the bits of - each pixel are separated into 4 planes. - - Only answer Y here if you have a (very old) VGA card that isn't VESA - 2 compatible. - -VGA 16-color graphics console -CONFIG_FB_VGA16 - This is the frame buffer device driver for VGA 16 color graphic - cards. Say Y if you have such a card. - - This code is also available as a module. If you want to compile it - as a module ( = code which can be inserted in and removed from the - running kernel whenever you want), say M here and read - . The module will be called - vga16fb.o. - -Generic STI frame buffer device support -CONFIG_FB_STI - STI refers to the HP "Standard Text Interface" which is a set of - BIOS routines contained in a ROM chip in HP PA-RISC based machines. - Enabling this option will implement the linux framebuffer device and - an fbcon color text console using calls to the STI BIOS routines. - The HP framebuffer device is sometimes planar, using a strange memory - layout, and changing the plane mask to create colored pixels - can require a call to the STI routines, so /dev/fb may not actually - be useful. However, on some systems packed pixel formats are supported. - It is sufficient for basic text console functions, including fonts. - - You should probably enable this option, unless you are having - trouble getting video when booting the kernel (make sure it isn't - just that you are running the console on the serial port, though). - Really old HP boxes may not have STI, and must use the PDC BIOS - console or the IODC BIOS. - -Select other compiled-in fonts -CONFIG_FBCON_FONTS - Say Y here if you would like to use fonts other than the default - your frame buffer console usually use. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about foreign fonts. - - If unsure, say N (the default choices are safe). - -VGA 8x16 font -CONFIG_FONT_8x16 - This is the "high resolution" font for the VGA frame buffer (the one - provided by the VGA text console 80x25 mode. - - If unsure, say Y. - -Support only 8 pixels wide fonts -CONFIG_FBCON_FONTWIDTH8_ONLY - Answer Y here will make the kernel provide only the 8x8 fonts (these - are the less readable). - - If unsure, say N. - -Sparc console 8x16 font -CONFIG_FONT_SUN8x16 - This is the high resolution console font for Sun machines. Say Y. - -Sparc console 12x22 font (not supported by all drivers) -CONFIG_FONT_SUN12x22 - This is the high resolution console font for Sun machines with very - big letters (like the letters used in the SPARC PROM). If the - standard font is unreadable for you, say Y, otherwise say N. - -VGA 8x8 font -CONFIG_FONT_8x8 - This is the "high resolution" font for the VGA frame buffer (the one - provided by the text console 80x50 (and higher) modes). - - Note that this is a poor quality font. The VGA 8x16 font is quite a - lot more readable. - - Given the resolution provided by the frame buffer device, answer N - here is safe. - -Mac console 6x11 font (not supported by all drivers) -CONFIG_FONT_6x11 - Small console font with Macintosh-style high-half glyphs. Some Mac - framebuffer drivers don't support this one at all. - -Pearl (old m68k) console 8x8 font -CONFIG_FONT_PEARL_8x8 - Small console font with PC-style control-character and high-half - glyphs. - -Acorn console 8x8 font -CONFIG_FONT_ACORN_8x8 - Small console font with PC-style control characters and high-half - glyphs. - -Backward compatibility mode for Xpmac -CONFIG_FB_COMPAT_XPMAC - If you use the Xpmac X server (common with mklinux), you'll need to - say Y here to use X. You should consider changing to XFree86 which - includes a server that supports the frame buffer device directly - (XF68_FBDev). - -Hercules (HGA) mono graphics support -CONFIG_FB_HGA - Say Y here if you have a Hercules mono graphics card. - - This driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). - The module will be called hgafb.o. If you want to compile it as - a module, say M here and read . - - As this card technology is 15 years old, most people will answer N - here. - -Epson 1355 framebuffer support -CONFIG_FB_E1355 - Build in support for the SED1355 Epson Research Embedded RAMDAC - LCD/CRT Controller (since redesignated as the S1D13505) as a - framebuffer. Product specs at - . - -Dreamcast Frame Buffer support -CONFIG_FB_DC - Say Y here to enable support for the framebuffer on the Sega - Dreamcast. This driver is also available as a module, dcfb.o. - -Register Base Address -CONFIG_E1355_REG_BASE - Epson SED1355/S1D13505 LCD/CRT controller register base address. - See the manuals at - for - discussion. - -Framebuffer Base Address -CONFIG_E1355_FB_BASE - Epson SED1355/S1D13505 LCD/CRT controller memory base address. See - the manuals at - for - discussion. - -NEC PowerVR 2 display support -CONFIG_FB_PVR2 - Say Y here if you have a PowerVR 2 card in your box. If you plan to - run linux on your Dreamcast, you will have to say Y here. - This driver may or may not work on other PowerVR 2 cards, but is - totally untested. Use at your own risk. If unsure, say N. - - This driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). - The module will be called pvr2fb.o. If you want to compile it as - a module, say M here and read . - - You can pass several parameters to the driver at boot time or at - module load time. The parameters look like "video=pvr2:XXX", where - the meaning of XXX can be found at the end of the main source file - (). Please see the file - . - -Debug pvr2fb -CONFIG_FB_PVR2_DEBUG - Say Y here if you wish for the pvr2fb driver to print out debugging - messages. Most people will want to say N here. If unsure, you will - also want to say N. - -Matrox unified accelerated driver -CONFIG_FB_MATROX - Say Y here if you have a Matrox Millennium, Millennium II, Mystique, - Mystique 220, Productiva G100, Mystique G200, Millennium G200, - Matrox G400, G450 or G550 card in your box. At this time, support for - the G-series digital output is almost non-existant. - - This driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). - The module will be called matroxfb.o. If you want to compile it as - a module, say M here and read . - - You can pass several parameters to the driver at boot time or at - module load time. The parameters look like "video=matrox:XXX", and - are described in . - -Matrox Millennium I/II support -CONFIG_FB_MATROX_MILLENIUM - Say Y here if you have a Matrox Millennium or Matrox Millennium II - video card. If you select "Advanced lowlevel driver options" below, - you should check 4 bpp packed pixel, 8 bpp packed pixel, 16 bpp - packed pixel, 24 bpp packed pixel and 32 bpp packed pixel. You can - also use font widths different from 8. - -Matrox Mystique support -CONFIG_FB_MATROX_MYSTIQUE - Say Y here if you have a Matrox Mystique or Matrox Mystique 220 - video card. If you select "Advanced lowlevel driver options" below, - you should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp - packed pixel and 32 bpp packed pixel. You can also use font widths - different from 8. - -CONFIG_FB_MATROX_G450 - Say Y here if you have a Matrox G100, G200, G400, G450 or G550 based - video card. If you select "Advanced lowlevel driver options", you - should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed - pixel and 32 bpp packed pixel. You can also use font widths - different from 8. - - If you need support for G400 secondary head, you must first say Y to - "I2C support" and "I2C bit-banging support" in the character devices - section, and then to "Matrox I2C support" and "G400 second head - support" here in the framebuffer section. G450/G550 secondary head - and digital output are supported without additional modules. - - The driver starts in monitor mode. You must use the matroxset tool - (available at ) to - swap primary and secondary head outputs, or to change output mode. - Secondary head driver always start in 640x480 resolution and you - must use fbset to change it. - - Do not forget that second head supports only 16 and 32 bpp - packed pixels, so it is a good idea to compile them into the kernel - too. You can use only some font widths, as the driver uses generic - painting procedures (the secondary head does not use acceleration - engine). - - G450/G550 hardware can display TV picture only from secondary CRTC, - and it performs no scaling, so picture must have 525 or 625 lines. - -CONFIG_FB_MATROX_G100A - Say Y here if you have a Matrox G100, G200 or G400 based - video card. If you select "Advanced lowlevel driver options", you - should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed - pixel and 32 bpp packed pixel. You can also use font widths - different from 8. - - If you need support for G400 secondary head, you must first say Y to - "I2C support" and "I2C bit-banging support" in the character devices - section, and then to "Matrox I2C support" and "G400 second head - support" here in the framebuffer section. - -CONFIG_FB_MATROX_I2C - This drivers creates I2C buses which are needed for accessing the - DDC (I2C) bus present on all Matroxes, an I2C bus which - interconnects Matrox optional devices, like MGA-TVO on G200 and - G400, and the secondary head DDC bus, present on G400 only. - - You can say Y or M here if you want to experiment with monitor - detection code. You must say Y or M here if you want to use either - second head of G400 or MGA-TVO on G200 or G400. - - If you compile it as module, it will create a module named - i2c-matroxfb.o. - -Matrox G400 second head support -CONFIG_FB_MATROX_MAVEN - WARNING !!! This support does not work with G450 !!! - - Say Y or M here if you want to use a secondary head (meaning two - monitors in parallel) on G400 or MGA-TVO add-on on G200. Secondary - head is not compatible with accelerated XFree 3.3.x SVGA servers - - secondary head output is blanked while you are in X. With XFree - 3.9.17 preview you can use both heads if you use SVGA over fbdev or - the fbdev driver on first head and the fbdev driver on second head. - - If you compile it as module, two modules are created, - matroxfb_crtc2.o and matroxfb_maven.o. Matroxfb_maven is needed for - both G200 and G400, matroxfb_crtc2 is needed only by G400. You must - also load i2c-matroxfb to get it to run. - - The driver starts in monitor mode and you must use the matroxset - tool (available at - ) to switch it to - PAL or NTSC or to swap primary and secondary head outputs. - Secondary head driver also always start in 640x480 resolution, you - must use fbset to change it. - - Also do not forget that second head supports only 16 and 32 bpp - packed pixels, so it is a good idea to compile them into the kernel - too. You can use only some font widths, as the driver uses generic - painting procedures (the secondary head does not use acceleration - engine). - -CONFIG_FB_MATROX_PROC - Say Y or M here if you want to access some informations about driver - state through /proc interface. - - You should download matrox_pins tool (available at - ) to get human - readable output. - -CONFIG_FB_MATROX_MULTIHEAD - Say Y here if you have more than one (supported) Matrox device in - your computer and you want to use all of them for different monitors - ("multihead"). If you have only one device, you should say N because - the driver compiled with Y is larger and a bit slower, especially on - ia32 (ix86). - - If you said M to "Matrox unified accelerated driver" and N here, you - will still be able to use several Matrox devices simultaneously: - insert several instances of the module matroxfb.o into the kernel - with insmod, supplying the parameter "dev=N" where N is 0, 1, etc. - for the different Matrox devices. This method is slightly faster but - uses 40 KB of kernel memory per Matrox card. - - There is no need for enabling 'Matrox multihead support' if you have - only one Matrox card in the box. - -3Dfx Voodoo Graphics / Voodoo2 frame buffer support -CONFIG_FB_VOODOO1 - Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or - Voodoo2 (cvg) based graphics card. - - This driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). - The module will be called sstfb.o. If you want to compile it as - a module, say M here and read Documentation/modules.txt. - - WARNING: Do not use any application that uses the 3D engine - (namely glide) while using this driver. - Please read the file Documentation/fb/README-sstfb.txt for supported - options and other important info support. - -MDA text console (dual-headed) -CONFIG_MDA_CONSOLE - Say Y here if you have an old MDA or monochrome Hercules graphics - adapter in your system acting as a second head ( = video card). You - will then be able to use two monitors with your Linux system. Do not - say Y here if your MDA card is the primary card in your system; the - normal VGA driver will handle it. - - This driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). - The module will be called mdacon.o. If you want to compile it as - a module, say M here and read . - - If unsure, say N. - -SBUS and UPA framebuffers -CONFIG_FB_SBUS - Say Y if you want support for SBUS or UPA based frame buffer device. - -Creator/Creator3D support -CONFIG_FB_CREATOR - This is the frame buffer device driver for the Creator and Creator3D - graphics boards. - -CGsix (GX,TurboGX) support -CONFIG_FB_CGSIX - This is the frame buffer device driver for the CGsix (GX, TurboGX) - frame buffer. - -BWtwo support -CONFIG_FB_BWTWO - This is the frame buffer device driver for the BWtwo frame buffer. - -CGthree support -CONFIG_FB_CGTHREE - This is the frame buffer device driver for the CGthree frame buffer. - -CGfourteen (SX) support -CONFIG_FB_CGFOURTEEN - This is the frame buffer device driver for the CGfourteen frame - buffer on Desktop SPARCsystems with the SX graphics option. - -P9100 (Sparcbook 3 only) support -CONFIG_FB_P9100 - This is the frame buffer device driver for the P9100 card - supported on Sparcbook 3 machines. - -Leo (ZX) support -CONFIG_FB_LEO - This is the frame buffer device driver for the SBUS-based Sun ZX - (leo) frame buffer cards. - -IGA 168x display support -CONFIG_FB_IGA - This is the framebuffer device for the INTERGRAPHICS 1680 and - successor frame buffer cards. - -TCX (SS4/SS5 only) support -CONFIG_FB_TCX - This is the frame buffer device driver for the TCX 24/8bit frame - buffer. - -HD64461 Frame Buffer support -CONFIG_FB_HIT - This is the frame buffer device driver for the Hitachi HD64461 LCD - frame buffer card. - -SIS display support -CONFIG_FB_SIS - This is the frame buffer device driver for the SiS 300, 315 and 330 - series chipsets. Documentation available at the maintainer's site - at . - -SIS 300 series support -CONFIG_FB_SIS_300 - This enables support for SiS 300 series chipsets (300/305, 540, 630, - 730). Documentation available at the maintainer's website at - . - -SIS 315/330 series support -CONFIG_FB_SIS_315 - This enables support for SiS 315/330 series chipsets (315, 550, 650, - M650, 651, 661FX, M661FX, 740, 741, 330). Documentation available at - the maintainer's site . - -IMS Twin Turbo display support -CONFIG_FB_IMSTT - The IMS Twin Turbo is a PCI-based frame buffer card bundled with - many Macintosh and compatible computers. - -CONFIG_FB_TX3912 - The TX3912 is a Toshiba RISC processor based on the MIPS 3900 core; - see . - - Say Y here to enable kernel support for the on-board framebuffer. - -Virtual Frame Buffer support (ONLY FOR TESTING!) -CONFIG_FB_VIRTUAL - This is a `virtual' frame buffer device. It operates on a chunk of - unswappable kernel memory instead of on the memory of a graphics - board. This means you cannot see any output sent to this frame - buffer device, while it does consume precious memory. The main use - of this frame buffer device is testing and debugging the frame - buffer subsystem. Do NOT enable it for normal systems! To protect - the innocent, it has to be enabled explicitly at boot time using the - kernel option `video=vfb:'. - - This driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). The - module will be called vfb.o. If you want to compile it as a module, - say M here and read . - - If unsure, say N. - -Mach64 CT/VT/GT/LT (incl. 3D RAGE) support -CONFIG_FB_ATY_CT - Say Y here to support use of ATI's 64-bit Rage boards (or other - boards based on the Mach64 CT, VT, GT, and LT chipsets) as a - framebuffer device. The ATI product support page for these boards - is at . - -Sony Vaio Picturebook laptop LCD panel support -CONFIG_FB_ATY_CT_VAIO_LCD - Say Y here if you want to use the full width of the Sony Vaio - Picturebook laptops LCD panels (you will get a 128x30 console). - - Note that you need to activate this mode using the 'vga=0x301' - option from your boot loader (lilo or loadlin). See the - documentation of your boot loader about how to pass options to the - kernel. - -Mach64 GX support -CONFIG_FB_ATY_GX - Say Y here to support use of the ATI Mach64 Graphics Expression - board (or other boards based on the Mach64 GX chipset) as a - framebuffer device. The ATI product support page for these boards - is at - . - -Mach64 Generic LCD support -CONFIG_FB_ATY_GENERIC_LCD - Enabling this option enables the Atyfb driver to drive LCD panels. It - will autodetect the resulution and format of your display and emulate - other resolutions using the hardware stretcher on the chip. - Say Y here if you have computer with a Rage LT Pro, Rage Mobility M1, - Rage XC or Rage XL chip and a laptop LCD display or any other LCD display - that needs to be digitally driven. It is not necessary to enable this - option if you are using an LCD display with a normal VGA connector, - but it won't hurt if you do. - -ATI Radeon display support -CONFIG_FB_RADEON - Choose this option if you want to use an ATI Radeon graphics card as - a framebuffer device. There are both PCI and AGP versions. You - don't need to choose this to run the Radeon in plain VGA mode. - There is a product page at - . - -SA-1100 LCD support -CONFIG_FB_SA1100 - This is a framebuffer device for the SA-1100 LCD Controller. - See for information on framebuffer - devices. - - If you plan to use the LCD display with your SA-1100 system, say - Y here. - -Advanced low level driver options -CONFIG_FBCON_ADVANCED - The frame buffer console uses character drawing routines that are - tailored to the specific organization of pixels in the memory of - your graphics hardware. These are called the low level frame buffer - console drivers. Note that they are used for text console output - only; they are NOT needed for graphical applications. - - If you say N here, the needed low level drivers are automatically - enabled, depending on what frame buffer devices you selected above. - This is recommended for most users. - - If you say Y here, you have more fine-grained control over which low - level drivers are enabled. You can e.g. leave out low level drivers - for color depths you do not intend to use for text consoles. - - Low level frame buffer console drivers can be modules ( = code which - can be inserted and removed from the running kernel whenever you - want). The modules will be called fbcon-*.o. If you want to compile - (some of) them as modules, read . - - If unsure, say N. - -Monochrome support -CONFIG_FBCON_MFB - This is the low level frame buffer console driver for monochrome - (2 colors) packed pixels. - -2 bpp packed pixels support -CONFIG_FBCON_CFB2 - This is the low level frame buffer console driver for 2 bits per - pixel (4 colors) packed pixels. - -4 bpp packed pixels support -CONFIG_FBCON_CFB4 - This is the low level frame buffer console driver for 4 bits per - pixel (16 colors) packed pixels. - -8 bpp packed pixels support -CONFIG_FBCON_CFB8 - This is the low level frame buffer console driver for 8 bits per - pixel (256 colors) packed pixels. - -16 bpp packed pixels support -CONFIG_FBCON_CFB16 - This is the low level frame buffer console driver for 15 or 16 bits - per pixel (32K or 64K colors, also known as `hicolor') packed - pixels. - -24 bpp packed pixels support -CONFIG_FBCON_CFB24 - This is the low level frame buffer console driver for 24 bits per - pixel (16M colors, also known as `truecolor') packed pixels. It is - NOT for `sparse' 32 bits per pixel mode. - -32 bpp packed pixels support -CONFIG_FBCON_CFB32 - This is the low level frame buffer console driver for 32 bits per - pixel (16M colors, also known as `truecolor') sparse packed pixels. - -Amiga bitplanes support -CONFIG_FBCON_AFB - This is the low level frame buffer console driver for 1 to 8 - bitplanes (2 to 256 colors) on Amiga. - -Amiga interleaved bitplanes support -CONFIG_FBCON_ILBM - This is the low level frame buffer console driver for 1 to 8 - interleaved bitplanes (2 to 256 colors) on Amiga. - -Atari interleaved bitplanes (2 planes) support -CONFIG_FBCON_IPLAN2P2 - This is the low level frame buffer console driver for 2 interleaved - bitplanes (4 colors) on Atari. - -Atari interleaved bitplanes (4 planes) support -CONFIG_FBCON_IPLAN2P4 - This is the low level frame buffer console driver for 4 interleaved - bitplanes (16 colors) on Atari. - -Atari interleaved bitplanes (8 planes) support -CONFIG_FBCON_IPLAN2P8 - This is the low level frame buffer console driver for 8 interleaved - bitplanes (256 colors) on Atari. - -Mac variable bpp packed pixels support -CONFIG_FBCON_MAC - This is the low level frame buffer console driver for 1/2/4/8/16/32 - bits per pixel packed pixels on Mac. It supports variable font - widths for low resolution screens. - -Permedia3 support (EXPERIMENTAL) -CONFIG_FB_PM3 - This is the frame buffer device driver for the 3DLabs Permedia3 - chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 & - similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000 - and maybe other boards. - -HGA monochrome support -CONFIG_FBCON_HGA - This is the low level frame buffer console driver for Hercules mono - graphics cards. - -VGA characters/attributes support -CONFIG_FBCON_VGA - This is the low level frame buffer console driver for VGA text mode; - it is used by frame buffer device drivers that support VGA text - mode. - -Parallel-port support -CONFIG_PARPORT - If you want to use devices connected to your machine's parallel port - (the connector at the computer with 25 holes), e.g. printer, ZIP - drive, PLIP link (Parallel Line Internet Protocol is mainly used to - create a mini network by connecting the parallel ports of two local - machines) etc., then you need to say Y here; please read - and - . - - For extensive information about drivers for many devices attaching - to the parallel port see on - the WWW. - - It is possible to share a single parallel port among several devices - and it is safe to compile all the corresponding drivers into the - kernel. If you want to compile parallel port support as a module - ( = code which can be inserted in and removed from the running - kernel whenever you want), say M here and read - . The module will be called - parport.o. If you have more than one parallel port and want to - specify which port and IRQ to be used by this driver at module load - time, take a look at . - - If unsure, say Y. - -PC-style hardware -CONFIG_PARPORT_PC - You should say Y here if you have a PC-style parallel port. All IBM - PC compatible computers and some Alphas have PC-style parallel - ports. - - This code is also available as a module. If you want to compile it - as a module ( = code which can be inserted in and removed from the - running kernel whenever you want), say M here and read - . The module will be called - parport_pc.o. - - If unsure, say Y. - -Parallel+serial PCI multi-IO card support -CONFIG_PARPORT_SERIAL - This adds support for multi-IO PCI cards that have parallel and - serial ports. You should say Y or M here. If you say M, the module - will be called parport_serial.o. - -Use FIFO/DMA if available -CONFIG_PARPORT_PC_FIFO - Many parallel port chipsets provide hardware that can speed up - printing. Say Y here if you want to take advantage of that. - - As well as actually having a FIFO, or DMA capability, the kernel - will need to know which IRQ the parallel port has. By default, - parallel port interrupts will not be used, and so neither will the - FIFO. See to find out how to - specify which IRQ/DMA to use. - -SuperIO chipset support -CONFIG_PARPORT_PC_SUPERIO - Saying Y here enables some probes for Super-IO chipsets in order to - find out things like base addresses, IRQ lines and DMA channels. It - is safe to say N. - -Support for PCMCIA management for PC-style ports -CONFIG_PARPORT_PC_PCMCIA - Say Y here if you need PCMCIA support for your PC-style parallel - ports. If unsure, say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - parport_cs.o - -Support foreign hardware -CONFIG_PARPORT_OTHER - Say Y here if you want to be able to load driver modules to support - other non-standard types of parallel ports. This causes a - performance loss, so most people say N. - -Amiga built-in parallel port support -CONFIG_PARPORT_AMIGA - Say Y here if you need support for the parallel port hardware on - Amiga machines. This code is also available as a module (say M), - called parport_amiga.o. If in doubt, saying N is the safe plan. - -Atari built-in parallel port support -CONFIG_PARPORT_ATARI - Say Y here if you need support for the parallel port hardware on - Atari machines. This code is also available as a module (say M), - called parport_atari.o. If in doubt, saying N is the safe plan. - -Multiface III parallel port support -CONFIG_PARPORT_MFC3 - Say Y here if you need parallel port support for the MFC3 card. - This code is also available as a module (say M), called - parport_mfc3.o. If in doubt, saying N is the safe plan. - -Support IEEE 1284 status readback -CONFIG_PRINTER_READBACK - If you have a device on your parallel port that support this - protocol, this option will allow the device to report its status. It - is safe to say Y. - -IEEE 1284 transfer modes -CONFIG_PARPORT_1284 - If you have a printer that supports status readback or device ID, or - want to use a device that uses enhanced parallel port transfer modes - such as EPP and ECP, say Y here to enable advanced IEEE 1284 - transfer modes. Also say Y if you want device ID information to - appear in /proc/sys/dev/parport/*/autoprobe*. It is safe to say N. - -Enable loadable module support -CONFIG_MODULES - Kernel modules are small pieces of compiled code which can be - inserted in or removed from the running kernel, using the programs - insmod and rmmod. This is described in the file - , including the fact that you have - to say "make modules" in order to compile the modules that you chose - during kernel configuration. Modules can be device drivers, file - systems, binary executable formats, and so on. If you think that you - may want to make use of modules with this kernel in the future, then - say Y here. If unsure, say Y. - -Set version information on all symbols for modules -CONFIG_MODVERSIONS - Usually, modules have to be recompiled whenever you switch to a new - kernel. Saying Y here makes it possible, and safe, to use the - same modules even after compiling a new kernel; this requires the - program modprobe. All the software needed for module support is in - the modutils package (check the file - for location and latest version). NOTE: if you say Y here but don't - have the program genksyms (which is also contained in the above - mentioned modutils package), then the building of your kernel will - fail. If you are going to use modules that are generated from - non-kernel sources, you would benefit from this option. Otherwise - it's not that important. So, N ought to be a safe bet. - -Kernel module loader support -CONFIG_KMOD - Normally when you have selected some drivers and/or file systems to - be created as loadable modules, you also have the responsibility to - load the corresponding modules (using the programs insmod or - modprobe) before you can use them. If you say Y here however, the - kernel will be able to load modules for itself: when a part of the - kernel needs a module, it runs modprobe with the appropriate - arguments, thereby loading the module if it is available. (This is a - replacement for kerneld.) Say Y here and read about configuring it - in . - -ARP daemon support -CONFIG_ARPD - Normally, the kernel maintains an internal cache which maps IP - addresses to hardware addresses on the local network, so that - Ethernet/Token Ring/ etc. frames are sent to the proper address on - the physical networking layer. For small networks having a few - hundred directly connected hosts or less, keeping this address - resolution (ARP) cache inside the kernel works well. However, - maintaining an internal ARP cache does not work well for very large - switched networks, and will use a lot of kernel memory if TCP/IP - connections are made to many machines on the network. - - If you say Y here, the kernel's internal ARP cache will never grow - to more than 256 entries (the oldest entries are expired in a LIFO - manner) and communication will be attempted with the user space ARP - daemon arpd. Arpd then answers the address resolution request either - from its own cache or by asking the net. - - This code is experimental and also obsolete. If you want to use it, - you need to find a version of the daemon arpd on the net somewhere, - and you should also say Y to "Kernel/User network link driver", - below. If unsure, say N. - -TCP/IP networking -CONFIG_INET - These are the protocols used on the Internet and on most local - Ethernets. It is highly recommended to say Y here (this will enlarge - your kernel by about 144 KB), since some programs (e.g. the X window - system) use TCP/IP even if your machine is not connected to any - other computer. You will get the so-called loopback device which - allows you to ping yourself (great fun, that!). - - For an excellent introduction to Linux networking, please read the - NET-3-HOWTO, available from - . - - This option is also necessary if you want to use the full power of - term (term is a program which gives you almost full Internet - connectivity if you have a regular dial up shell account on some - Internet connected Unix computer; for more information, read - ). - - If you say Y here and also to "/proc file system support" and - "Sysctl support" below, you can change various aspects of the - behaviour of the TCP/IP code by writing to the (virtual) files in - /proc/sys/net/ipv4/*; the options are explained in the file - . - - Short answer: say Y. - -IP multicasting -CONFIG_IP_MULTICAST - This is code for addressing several networked computers at once, - enlarging your kernel by about 2 KB. You need multicasting if you - intend to participate in the MBONE, a high bandwidth network on top - of the Internet which carries audio and video broadcasts. More - information about the MBONE is on the WWW at - . Information about the multicast - capabilities of the various network cards is contained in - . For most people, it's - safe to say N. - -Advanced router -CONFIG_IP_ADVANCED_ROUTER - If you intend to run your Linux box mostly as a router, i.e. as a - computer that forwards and redistributes network packets, say Y; you - will then be presented with several options that allow more precise - control about the routing process. - - The answer to this question won't directly affect the kernel: - answering N will just cause the configurator to skip all the - questions about advanced routing. - - Note that your box can only act as a router if you enable IP - forwarding in your kernel; you can do that by saying Y to "/proc - file system support" and "Sysctl support" below and executing the - line - - echo "1" > /proc/sys/net/ipv4/ip_forward - - at boot time after the /proc file system has been mounted. - - If you turn on IP forwarding, you will also get the rp_filter, which - automatically rejects incoming packets if the routing table entry - for their source address doesn't match the network interface they're - arriving on. This has security advantages because it prevents the - so-called IP spoofing, however it can pose problems if you use - asymmetric routing (packets from you to a host take a different path - than packets from that host to you) or if you operate a non-routing - host which has several IP addresses on different interfaces. To turn - rp_filter off use: - - echo 0 > /proc/sys/net/ipv4/conf//rp_filter - or - echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter - - If unsure, say N here. - -Policy routing -CONFIG_IP_MULTIPLE_TABLES - Normally, a router decides what to do with a received packet based - solely on the packet's final destination address. If you say Y here, - the Linux router will also be able to take the packet's source - address into account. Furthermore, if you also say Y to "Use TOS - value as routing key" below, the TOS (Type-Of-Service) field of the - packet can be used for routing decisions as well. In addition, if - you say Y here and to "Fast network address translation" below, - the router will also be able to modify source and destination - addresses of forwarded packets. - - If you are interested in this, please see the preliminary - documentation at - and . - You will need supporting software from - . - - If unsure, say N. - -Equal cost multipath -CONFIG_IP_ROUTE_MULTIPATH - Normally, the routing tables specify a single action to be taken in - a deterministic manner for a given packet. If you say Y here - however, it becomes possible to attach several actions to a packet - pattern, in effect specifying several alternative paths to travel - for those packets. The router considers all these paths to be of - equal "cost" and chooses one of them in a non-deterministic fashion - if a matching packet arrives. - -Use TOS value as routing key -CONFIG_IP_ROUTE_TOS - The header of every IP packet carries a TOS (Type Of Service) value - with which the packet requests a certain treatment, e.g. low - latency (for interactive traffic), high throughput, or high - reliability. If you say Y here, you will be able to specify - different routes for packets with different TOS values. - -Use netfilter MARK value as routing key -CONFIG_IP_ROUTE_FWMARK - If you say Y here, you will be able to specify different routes for - packets with different mark values (see iptables(8), MARK target). - -Verbose route monitoring -CONFIG_IP_ROUTE_VERBOSE - If you say Y here, which is recommended, then the kernel will print - verbose messages regarding the routing, for example warnings about - received packets which look strange and could be evidence of an - attack or a misconfigured system somewhere. The information is - handled by the klogd daemon which is responsible for kernel messages - ("man klogd"). - -Fast network address translation -CONFIG_IP_ROUTE_NAT - If you say Y here, your router will be able to modify source and - destination addresses of packets that pass through it, in a manner - you specify. General information about Network Address Translation - can be gotten from the document - . - -Kernel level IP autoconfiguration -CONFIG_IP_PNP - This enables automatic configuration of IP addresses of devices and - of the routing table during kernel boot, based on either information - supplied on the kernel command line or by BOOTP or RARP protocols. - You need to say Y only for diskless machines requiring network - access to boot (in which case you want to say Y to "Root file system - on NFS" as well), because all other machines configure the network - in their startup scripts. - -BOOTP support -CONFIG_IP_PNP_BOOTP - If you want your Linux box to mount its whole root file system (the - one containing the directory /) from some other computer over the - net via NFS and you want the IP address of your computer to be - discovered automatically at boot time using the BOOTP protocol (a - special protocol designed for doing this job), say Y here. In case - the boot ROM of your network card was designed for booting Linux and - does BOOTP itself, providing all necessary information on the kernel - command line, you can say N here. If unsure, say Y. Note that if you - want to use BOOTP, a BOOTP server must be operating on your network. - Read for details. - -DHCP support -CONFIG_IP_PNP_DHCP - If you want your Linux box to mount its whole root file system (the - one containing the directory /) from some other computer over the - net via NFS and you want the IP address of your computer to be - discovered automatically at boot time using the DHCP protocol (a - special protocol designed for doing this job), say Y here. In case - the boot ROM of your network card was designed for booting Linux and - does DHCP itself, providing all necessary information on the kernel - command line, you can say N here. - - If unsure, say Y. Note that if you want to use DHCP, a DHCP server - must be operating on your network. Read - for details. - -RARP support -CONFIG_IP_PNP_RARP - If you want your Linux box to mount its whole root file system (the - one containing the directory /) from some other computer over the - net via NFS and you want the IP address of your computer to be - discovered automatically at boot time using the RARP protocol (an - older protocol which is being obsoleted by BOOTP and DHCP), say Y - here. Note that if you want to use RARP, a RARP server must be - operating on your network. Read for - details. - -IP tunneling -CONFIG_NET_IPIP - Tunneling means encapsulating data of one protocol type within - another protocol and sending it over a channel that understands the - encapsulating protocol. This particular tunneling driver implements - encapsulation of IP within IP, which sounds kind of pointless, but - can be useful if you want to make your (or some other) machine - appear on a different network than it physically is, or to use - mobile-IP facilities (allowing laptops to seamlessly move between - networks without changing their IP addresses; check out - ). - - Saying Y to this option will produce two modules ( = code which can - be inserted in and removed from the running kernel whenever you - want). Most people won't need this and can say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - ipip.o - -GRE tunnels over IP -CONFIG_NET_IPGRE - Tunneling means encapsulating data of one protocol type within - another protocol and sending it over a channel that understands the - encapsulating protocol. This particular tunneling driver implements - GRE (Generic Routing Encapsulation) and at this time allows - encapsulating of IPv4 or IPv6 over existing IPv4 infrastructure. - This driver is useful if the other endpoint is a Cisco router: Cisco - likes GRE much better than the other Linux tunneling driver ("IP - tunneling" above). In addition, GRE allows multicast redistribution - through the tunnel. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - ip_gre.o - -Broadcast GRE over IP -CONFIG_NET_IPGRE_BROADCAST - One application of GRE/IP is to construct a broadcast WAN (Wide Area - Network), which looks like a normal Ethernet LAN (Local Area - Network), but can be distributed all over the Internet. If you want - to do that, say Y here and to "IP multicast routing" below. - -IP multicast routing -CONFIG_IP_MROUTE - This is used if you want your machine to act as a router for IP - packets that have several destination addresses. It is needed on the - MBONE, a high bandwidth network on top of the Internet which carries - audio and video broadcasts. In order to do that, you would most - likely run the program mrouted. Information about the multicast - capabilities of the various network cards is contained in - . If you haven't heard - about it, you don't need it. - -PIM-SM version 1 support -CONFIG_IP_PIMSM_V1 - Kernel side support for Sparse Mode PIM (Protocol Independent - Multicast) version 1. This multicast routing protocol is used widely - because Cisco supports it. You need special software to use it - (pimd-v1). Please see for more - information about PIM. - - Say Y if you want to use PIM-SM v1. Note that you can say N here if - you just want to use Dense Mode PIM. - -PIM-SM version 2 support -CONFIG_IP_PIMSM_V2 - Kernel side support for Sparse Mode PIM version 2. In order to use - this, you need an experimental routing daemon supporting it (pimd or - gated-5). This routing protocol is not used widely, so say N unless - you want to play with it. - -Unix domain sockets -CONFIG_UNIX - If you say Y here, you will include support for Unix domain sockets; - sockets are the standard Unix mechanism for establishing and - accessing network connections. Many commonly used programs such as - the X Window system and syslog use these sockets even if your - machine is not connected to any network. Unless you are working on - an embedded system or something similar, you therefore definitely - want to say Y here. - - However, the socket support is also available as a module ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . The module will be - called unix.o. If you try building this as a module and you have - said Y to "Kernel module loader support" above, be sure to add - 'alias net-pf-1 unix' to your /etc/modules.conf file. Note that - several important services won't work correctly if you say M here - and then neglect to load the module. - - Say Y unless you know what you are doing. - -The IPv6 protocol -CONFIG_IPV6 - This is experimental support for the next version of the Internet - Protocol: IP version 6 (also called IPng "IP next generation"). - Features of this new protocol include: expanded address space, - authentication and privacy, and seamless interoperability with the - current version of IP (IP version 4). For general information about - IPv6, see ; - for specific information about IPv6 under Linux read the HOWTO at - and the file net/ipv6/README - in the kernel source. - - If you want to use IPv6, please upgrade to the newest net-tools as - given in . You will still be able to do - regular IPv4 networking as well. - - This protocol support is also available as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). The module will be called ipv6.o. If you want to compile it - as a module, say M here and read . - - It is safe to say N here for now. - -The SCTP Protocol (EXPERIMENTAL) -CONFIG_IP_SCTP - Stream Control Transmission Protocol - - From RFC 2960 (http://www.ietf.org/rfc/rfc2960.txt) - - "SCTP is a reliable transport protocol operating on top of a - connectionless packet network such as IP. It offers the following - services to its users: - - -- acknowledged error-free non-duplicated transfer of user data, - -- data fragmentation to conform to discovered path MTU size, - -- sequenced delivery of user messages within multiple streams, - with an option for order-of-arrival delivery of individual user - messages, - -- optional bundling of multiple user messages into a single SCTP - packet, and - -- network-level fault tolerance through supporting of multi- - homing at either or both ends of an association." - - This protocol support is also available as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). The module will be called sctp. If you want to compile it - as a module, say M here and read . - - If in doubt, say N. - -SCTP: Debug messages -CONFIG_SCTP_DBG_MSG - If you say Y, this will enable verbose debugging messages. - - If unsure, say N. However, if you are running into problems, use - this option to gather detailed trace information - -SCTP: Debug object counts -CONFIG_SCTP_DBG_OBJCNT - If you say Y, this will enable debugging support for counting the - type of objects that are currently allocated. This is useful for - identifying memory leaks. If the /proc filesystem is enabled this - debug information can be viewed by - 'cat /proc/net/sctp/sctp_dbg_objcnt' - - If unsure, say N - -#choice -SCTP: HMAC algorithm -CONFIG_SCTP_HMAC_NONE - Choose an HMAC algorithm to be used during association establishment. - It can be one of SHA1, MD5 or NONE. It is advised to use either HMAC-MD5 - or HMAC-SHA1. - See configuration for Cryptographic API and enable these algorithms - to make usable by SCTP. - -SCTP: SHA1 HMAC algorithm -CONFIG_SCTP_HMAC_SHA1 - Enable the use of HMAC-SHA1 during association establishment. It - is advised to use either HMAC-MD5 or HMAC-SHA1. - See configuration for Cryptographic API and enable these algorithms - to make usable by SCTP. - -SCTP: MD5 HMAC algorithm -config SCTP_HMAC_MD5 - Enable the use of HMAC-MD5 during association establishment. It is - advised to use either HMAC-MD5 or HMAC-SHA1. - See configuration for Cryptographic API and enable these algorithms - to make usable by SCTP. - -Kernel httpd acceleration -CONFIG_KHTTPD - The kernel httpd acceleration daemon (kHTTPd) is a (limited) web - server built into the kernel. It is limited since it can only serve - files from the file system and cannot deal with executable content - such as CGI scripts. Serving files is sped up if you use kHTTPd. - If kHTTPd is not able to fulfill a request, it can transparently - pass it through to a user space web server such as apache. - - Saying "M" here builds the kHTTPd module; this is NOT enough to have - a working kHTTPd. For safety reasons, the module has to be activated - by doing a "echo 1 > /proc/sys/net/khttpd/start" after inserting the - module. - - Before using this, read the README in net/khttpd ! - - The kHTTPd is experimental. Be careful when using it on a production - machine. Also note that kHTTPd doesn't support virtual servers yet. - -The IPX protocol -CONFIG_IPX - This is support for the Novell networking protocol, IPX, commonly - used for local networks of Windows machines. You need it if you - want to access Novell NetWare file or print servers using the Linux - Novell client ncpfs (available from - ) or from - within the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, - available from ). In order - to do the former, you'll also have to say Y to "NCP file system - support", below. - - IPX is similar in scope to IP, while SPX, which runs on top of IPX, - is similar to TCP. There is also experimental support for SPX in - Linux (see "SPX networking", below). - - To turn your Linux box into a fully featured NetWare file server and - IPX router, say Y here and fetch either lwared from - or - mars_nwe from . For more - information, read the IPX-HOWTO available from - . - - General information about how to connect Linux, Windows machines and - Macs is on the WWW at . - - The IPX driver would enlarge your kernel by about 16 KB. This driver - is also available as a module ( = code which can be inserted in and - removed from the running kernel whenever you want). The module will - be called ipx.o. If you want to compile it as a module, say M here - and read . Unless you want to - integrate your Linux box with a local Novell network, say N. - -Full internal IPX network -CONFIG_IPX_INTERN - Every IPX network has an address that identifies it. Sometimes it is - useful to give an IPX "network" address to your Linux box as well - (for example if your box is acting as a file server for different - IPX networks: it will then be accessible from everywhere using the - same address). The way this is done is to create a virtual internal - "network" inside your box and to assign an IPX address to this - network. Say Y here if you want to do this; read the IPX-HOWTO at - for details. - - The full internal IPX network enables you to allocate sockets on - different virtual nodes of the internal network. This is done by - evaluating the field sipx_node of the socket address given to the - bind call. So applications should always initialize the node field - to 0 when binding a socket on the primary network. In this case the - socket is assigned the default node that has been given to the - kernel when the internal network was created. By enabling the full - internal IPX network the cross-forwarding of packets targeted at - 'special' sockets to sockets listening on the primary network is - disabled. This might break existing applications, especially RIP/SAP - daemons. A RIP/SAP daemon that works well with the full internal net - can be found on . - - If you don't know what you are doing, say N. - -#(We're told this will come back someday) - -SPX networking -CONFIG_SPX - * Orphaned entry retained 20 April 2001 by Petr Vandrovec * - * If you read this note from the configurator, please contact * - * the Configure.help maintainers. * - The Sequenced Packet eXchange protocol is a transport layer protocol - built on top of IPX. It is used in Novell NetWare systems for - client-server applications and is similar to TCP (which runs on top - of IP). - - Note that Novell NetWare file sharing does not use SPX; it uses a - protocol called NCP, for which separate Linux support is available - ("NCP file system support" below for the client side, and the user - space programs lwared or mars_nwe for the server side). - - Say Y here if you have use for SPX; read the IPX-HOWTO at - for details. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called af_spx.o. If you want to compile it as a - module, say M here and read . - -DECnet networking -CONFIG_DECNET - The DECnet networking protocol was used in many products made by - Digital (now Compaq). It provides reliable stream and sequenced - packet communications over which run a variety of services similar - to those which run over TCP/IP. - - To find some tools to use with the kernel layer support, please - look at Patrick Caulfield's web site: - . - - More detailed documentation is available in - . - - Be sure to say Y to "/proc file system support" and "Sysctl support" - below when using DECnet, since you will need sysctl support to aid - in configuration at run time. - - The DECnet code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called decnet.o. - -DECnet SIOCFIGCONF support -CONFIG_DECNET_SIOCGIFCONF - This option should only be turned on if you are really sure that - you know what you are doing. It can break other applications which - use this system call and the proper way to get the information - provided by this call is to use rtnetlink. - - If unsure, say N. - -DECnet router support -CONFIG_DECNET_ROUTER - Add support for turning your DECnet Endnode into a level 1 or 2 - router. This is an unfinished option for developers only. If you - do say Y here, then make sure that you also say Y to "Kernel/User - network link driver", "Routing messages" and "Network packet - filtering". The first two are required to allow configuration via - rtnetlink (currently you need Alexey Kuznetsov's iproute2 package - from ). The "Network packet filtering" option - will be required for the forthcoming routing daemon to work. - - See for more information. - -Use FWMARK value as DECnet routing key -CONFIG_DECNET_ROUTE_FWMARK - If you say Y here, you will be able to specify different routes for - packets with different FWMARK ("firewalling mark") values - (see ipchains(8), "-m" argument). - -AppleTalk interfaces support -CONFIG_DEV_APPLETALK - AppleTalk is the protocol that Apple computers can use to communicate - on a network. If your Linux box is connected to such a network, and wish - to do IP over it, or you have a LocalTalk card and wish to use it to - connect to the AppleTalk network, say Y. - -AppleTalk protocol support -CONFIG_ATALK - AppleTalk is the protocol that Apple computers can use to communicate - on a network. If your Linux box is connected to such a network and you - wish to connect to it, say Y. You will need to use the netatalk package - so that your Linux box can act as a print and file server for Macs as - well as access AppleTalk printers. Check out - on the WWW for details. - EtherTalk is the name used for AppleTalk over Ethernet and the - cheaper and slower LocalTalk is AppleTalk over a proprietary Apple - network using serial links. EtherTalk and LocalTalk are fully - supported by Linux. - - General information about how to connect Linux, Windows machines and - Macs is on the WWW at . The - NET-3-HOWTO, available from - , contains valuable - information as well. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called appletalk.o. If you want to compile it as a - module, say M here and read . You - almost certainly want to compile it as a module so you can restart - your AppleTalk stack without rebooting your machine. I hear that - the GNU boycott of Apple is over, so even politically correct people - are allowed to say Y here. - -AppleTalk-IP driver support -CONFIG_IPDDP - This allows IP networking for users who only have AppleTalk - networking available. This feature is experimental. With this - driver, you can encapsulate IP inside AppleTalk (e.g. if your Linux - box is stuck on an AppleTalk only network) or decapsulate (e.g. if - you want your Linux box to act as an Internet gateway for a zoo of - AppleTalk connected Macs). Please see the file - for more information. - - If you say Y here, the AppleTalk-IP support will be compiled into - the kernel. In this case, you can either use encapsulation or - decapsulation, but not both. With the following two questions, you - decide which one you want. - - If you say M here, the AppleTalk-IP support will be compiled as a - module ( = code which can be inserted in and removed from the - running kernel whenever you want, read - ). The module is called ipddp.o. - In this case, you will be able to use both encapsulation and - decapsulation simultaneously, by loading two copies of the module - and specifying different values for the module option ipddp_mode. - -IP to AppleTalk-IP Encapsulation support -CONFIG_IPDDP_ENCAP - If you say Y here, the AppleTalk-IP code will be able to encapsulate - IP packets inside AppleTalk frames; this is useful if your Linux box - is stuck on an AppleTalk network (which hopefully contains a - decapsulator somewhere). Please see - for more information. If - you said Y to "AppleTalk-IP driver support" above and you say Y - here, then you cannot say Y to "AppleTalk-IP to IP Decapsulation - support", below. - -AppleTalk-IP to IP Decapsulation support -CONFIG_IPDDP_DECAP - If you say Y here, the AppleTalk-IP code will be able to decapsulate - AppleTalk-IP frames to IP packets; this is useful if you want your - Linux box to act as an Internet gateway for an AppleTalk network. - Please see for more - information. If you said Y to "AppleTalk-IP driver support" above - and you say Y here, then you cannot say Y to "IP to AppleTalk-IP - Encapsulation support", above. - -Apple/Farallon LocalTalk PC card support -CONFIG_LTPC - This allows you to use the AppleTalk PC card to connect to LocalTalk - networks. The card is also known as the Farallon PhoneNet PC card. - If you are in doubt, this card is the one with the 65C02 chip on it. - You also need version 1.3.3 or later of the netatalk package. - This driver is experimental, which means that it may not work. - See the file . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - ltpc.o - -COPS LocalTalk PC card support -CONFIG_COPS - This allows you to use COPS AppleTalk cards to connect to LocalTalk - networks. You also need version 1.3.3 or later of the netatalk - package. This driver is experimental, which means that it may not - work. This driver will only work if you choose "AppleTalk DDP" - networking support, above. - Please read the file . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - cops.o - -Dayna firmware support -CONFIG_COPS_DAYNA - Support COPS compatible cards with Dayna style firmware (Dayna - DL2000/ Daynatalk/PC (half length), COPS LT-95, Farallon PhoneNET PC - III, Farallon PhoneNET PC II). - -Tangent firmware support -CONFIG_COPS_TANGENT - Support COPS compatible cards with Tangent style firmware (Tangent - ATB_II, Novell NL-1000, Daystar Digital LT-200. - -Amateur Radio support -CONFIG_HAMRADIO - If you want to connect your Linux box to an amateur radio, answer Y - here. You want to read and - the AX25-HOWTO, available from . - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about amateur radio. - -Amateur Radio AX.25 Level 2 protocol -CONFIG_AX25 - This is the protocol used for computer communication over amateur - radio. It is either used by itself for point-to-point links, or to - carry other protocols such as tcp/ip. To use it, you need a device - that connects your Linux box to your amateur radio. You can either - use a low speed TNC (a Terminal Node Controller acts as a kind of - modem connecting your computer's serial port to your radio's - microphone input and speaker output) supporting the KISS protocol or - one of the various SCC cards that are supported by the generic Z8530 - or the DMA SCC driver. Another option are the Baycom modem serial - and parallel port hacks or the sound card modem (supported by their - own drivers). If you say Y here, you also have to say Y to one of - those drivers. - - Information about where to get supporting software for Linux amateur - radio as well as information about how to configure an AX.25 port is - contained in the AX25-HOWTO, available from - . You might also want to - check out the file in the - kernel source. More information about digital amateur radio in - general is on the WWW at - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ax25.o. If you want to compile it as a - module, say M here and read . - -AX.25 DAMA Slave support -CONFIG_AX25_DAMA_SLAVE - DAMA is a mechanism to prevent collisions when doing AX.25 - networking. A DAMA server (called "master") accepts incoming traffic - from clients (called "slaves") and redistributes it to other slaves. - If you say Y here, your Linux box will act as a DAMA slave; this is - transparent in that you don't have to do any special DAMA - configuration. (Linux cannot yet act as a DAMA server.) If unsure, - say N. - -AX.25 DAMA Master support -CONFIG_AX25_DAMA_MASTER - DAMA is a mechanism to prevent collisions when doing AX.25 - networking. A DAMA server (called "master") accepts incoming traffic - from clients (called "slaves") and redistributes it to other - slaves. If you say Y here, your Linux box will act as a DAMA server. - If unsure, say N. - -Amateur Radio NET/ROM support -CONFIG_NETROM - NET/ROM is a network layer protocol on top of AX.25 useful for - routing. - - A comprehensive listing of all the software for Linux amateur radio - users as well as information about how to configure an AX.25 port is - contained in the AX25-HOWTO, available from - . You also might want to - check out the file . More - information about digital amateur radio in general is on the WWW at - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called netrom.o. If you want to compile it as a - module, say M here and read . - -Amateur Radio X.25 PLP (Rose) -CONFIG_ROSE - The Packet Layer Protocol (PLP) is a way to route packets over X.25 - connections in general and amateur radio AX.25 connections in - particular, essentially an alternative to NET/ROM. - - A comprehensive listing of all the software for Linux amateur radio - users as well as information about how to configure an AX.25 port is - contained in the AX25-HOWTO, available from - . You also might want to - check out the file . More - information about digital amateur radio in general is on the WWW at - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called rose.o. If you want to compile it as a - module, say M here and read . - -Serial port KISS driver for AX.25 -CONFIG_MKISS - KISS is a protocol used for the exchange of data between a computer - and a Terminal Node Controller (a small embedded system commonly - used for networking over AX.25 amateur radio connections; it - connects the computer's serial port with the radio's microphone - input and speaker output). - - Although KISS is less advanced than the 6pack protocol, it has - the advantage that it is already supported by most modern TNCs - without the need for a firmware upgrade. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called mkiss.o. - -Serial port 6PACK driver for AX.25 -CONFIG_6PACK - 6pack is a transmission protocol for the data exchange between your - PC and your TNC (the Terminal Node Controller acts as a kind of - modem connecting your computer's serial port to your radio's - microphone input and speaker output). This protocol can be used as - an alternative to KISS for networking over AX.25 amateur radio - connections, but it has some extended functionality. - - Note that this driver is still experimental and might cause - problems. For details about the features and the usage of the - driver, read . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called 6pack.o. - -BPQ Ethernet driver -CONFIG_BPQETHER - AX.25 is the protocol used for computer communication over amateur - radio. If you say Y here, you will be able to send and receive AX.25 - traffic over Ethernet (also called "BPQ AX.25"), which could be - useful if some other computer on your local network has a direct - amateur radio connection. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called bpqether.o. - -High-speed (DMA) SCC driver for AX.25 -CONFIG_DMASCC - This is a driver for high-speed SCC boards, i.e. those supporting - DMA on one port. You usually use those boards to connect your - computer to an amateur radio modem (such as the WA4DSY 56kbps - modem), in order to send and receive AX.25 packet radio network - traffic. - - Currently, this driver supports Ottawa PI/PI2, Paccomm/Gracilis - PackeTwin, and S5SCC/DMA boards. They are detected automatically. - If you have one of these cards, say Y here and read the AX25-HOWTO, - available from . - - This driver can operate multiple boards simultaneously. If you - compile it as a module (by saying M instead of Y), it will be called - dmascc.o. If you don't pass any parameter to the driver, all - possible I/O addresses are probed. This could irritate other devices - that are currently not in use. You may specify the list of addresses - to be probed by "dmascc=addr1,addr2,..." (when compiled into the - kernel image) or "io=addr1,addr2,..." (when loaded as a module). The - network interfaces will be called dmascc0 and dmascc1 for the board - detected first, dmascc2 and dmascc3 for the second one, and so on. - - Before you configure each interface with ifconfig, you MUST set - certain parameters, such as channel access timing, clock mode, and - DMA channel. This is accomplished with a small utility program, - dmascc_cfg, available at - . Please be sure to get - at least version 1.27 of dmascc_cfg, as older versions will not - work with the current driver. - -Z8530 SCC driver for AX.25 -CONFIG_SCC - These cards are used to connect your Linux box to an amateur radio - in order to communicate with other computers. If you want to use - this, read and the - AX25-HOWTO, available from - . Also make sure to say Y - to "Amateur Radio AX.25 Level 2" support. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called scc.o. - -Support for TRX that feedback the tx signal to rx -CONFIG_SCC_TRXECHO - Some transmitters feed the transmitted signal back to the receive - line. Say Y here to foil this by explicitly disabling the receiver - during data transmission. If in doubt, say Y. - -Additional delay for PA0HZP OptoSCC compatible boards -CONFIG_SCC_DELAY - Say Y here if you experience problems with the SCC driver not - working properly; please read - for details. If unsure, - say N. - -YAM driver for AX.25 -CONFIG_YAM - The YAM is a modem for packet radio which connects to the serial - port and includes some of the functions of a Terminal Node - Controller. If you have one of those, say Y here. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called yam.o. - -BAYCOM picpar and par96 driver for AX.25 -CONFIG_BAYCOM_PAR - This is a driver for Baycom style simple amateur radio modems that - connect to a parallel interface. The driver supports the picpar and - par96 designs. To configure the driver, use the sethdlc utility - available in the standard ax25 utilities package. For information on - the modems, see and the file - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called baycom_par.o. - -BAYCOM EPP driver for AX.25 -CONFIG_BAYCOM_EPP - This is a driver for Baycom style simple amateur radio modems that - connect to a parallel interface. The driver supports the EPP - designs. To configure the driver, use the sethdlc utility available - in the standard ax25 utilities package. For information on the - modems, see and the file - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called baycom_par.o. - -BAYCOM ser12 full-duplex driver for AX.25 -CONFIG_BAYCOM_SER_FDX - This is one of two drivers for Baycom style simple amateur radio - modems that connect to a serial interface. The driver supports the - ser12 design in full-duplex mode. In addition, it allows the - baudrate to be set between 300 and 4800 baud (however not all modems - support all baudrates). This is the preferred driver. The next - driver, "BAYCOM ser12 half-duplex driver for AX.25" is the old - driver and still provided in case this driver does not work with - your serial interface chip. To configure the driver, use the sethdlc - utility available in the standard ax25 utilities package. For - information on the modems, see and - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called baycom_ser_fdx.o. - -BAYCOM ser12 half-duplex driver for AX.25 -CONFIG_BAYCOM_SER_HDX - This is one of two drivers for Baycom style simple amateur radio - modems that connect to a serial interface. The driver supports the - ser12 design in full-duplex mode. This is the old driver. It is - still provided in case your serial interface chip does not work with - the full-duplex driver. This driver is depreciated. To configure - the driver, use the sethdlc utility available in the standard ax25 - utilities package. For information on the modems, see - and - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called baycom_ser_hdx.o. - -Sound card modem driver for AX.25 -CONFIG_SOUNDMODEM - This experimental driver allows a standard Sound Blaster or - WindowsSoundSystem compatible sound card to be used as a packet - radio modem (NOT as a telephone modem!), to send digital traffic - over amateur radio. - - To configure the driver, use the sethdlc, smdiag and smmixer - utilities available in the standard ax25 utilities package. For - information on how to key the transmitter, see - and - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called soundmodem.o. - -Sound card modem support for Sound Blaster and compatible cards -CONFIG_SOUNDMODEM_SBC - This option enables the soundmodem driver to use Sound Blaster and - compatible cards. If you have a dual mode card (i.e. a WSS cards - with a Sound Blaster emulation) you should say N here and Y to - "Sound card modem support for WSS and Crystal cards", below, because - this usually results in better performance. This option also - supports SB16/32/64 in full-duplex mode. - -Sound card modem support for WSS and Crystal cards -CONFIG_SOUNDMODEM_WSS - This option enables the soundmodem driver to use WindowsSoundSystem - compatible cards. These cards feature a codec chip from either - Analog Devices (such as AD1848, AD1845, AD1812) or Crystal - Semiconductors (such as CS4248, CS423x). This option also supports - the WSS full-duplex operation which currently works with Crystal - CS423x chips. If you don't need full-duplex operation, do not enable - it to save performance. - -Sound card modem support for 1200 baud AFSK modulation -CONFIG_SOUNDMODEM_AFSK1200 - This option enables the soundmodem driver 1200 baud AFSK modem, - compatible to popular modems using TCM3105 or AM7911. The - demodulator requires about 12% of the CPU power of a Pentium 75 CPU - per channel. - -Sound card modem support for 2400 baud AFSK modulation (7.3728MHz crystal) -CONFIG_SOUNDMODEM_AFSK2400_7 - This option enables the soundmodem driver 2400 baud AFSK modem, - compatible to TCM3105 modems (over-)clocked with a 7.3728MHz - crystal. Note that the availability of this driver does _not_ imply - that I recommend building such links. It is only here since users - especially in eastern Europe have asked me to do so. In fact this - modulation scheme has many disadvantages, mainly its incompatibility - with many transceiver designs and the fact that the TCM3105 (if - used) is operated widely outside its specifications. - -Sound card modem support for 2400 baud AFSK modulation (8MHz crystal) -CONFIG_SOUNDMODEM_AFSK2400_8 - This option enables the soundmodem driver 2400 baud AFSK modem, - compatible to TCM3105 modems (over-)clocked with an 8MHz crystal. - Note that the availability of this driver does _not_ imply that I - recommend building such links. It is only here since users - especially in eastern Europe have asked me to do so. In fact this - modulation scheme has many disadvantages, mainly its incompatibility - with many transceiver designs and the fact that the TCM3105 (if - used) is operated widely outside its specifications. - -Sound card modem support for 2666 baud AFSK modulation -CONFIG_SOUNDMODEM_AFSK2666 - This option enables the soundmodem driver 2666 baud AFSK modem. - This modem is experimental, and not compatible to anything - else I know of. - -Sound card modem support for 4800 baud 8PSK modulation -CONFIG_SOUNDMODEM_PSK4800 - This option enables the soundmodem driver 4800 baud 8PSK modem. - This modem is experimental, and not compatible to anything - else I know of. - -Sound card modem support for 4800 baud HAPN-1 modulation -CONFIG_SOUNDMODEM_HAPN4800 - This option enables the soundmodem driver 4800 baud HAPN-1 - compatible modem. This modulation seems to be widely used 'down - under' and in the Netherlands. Here, nobody uses it, so I could not - test if it works. It is compatible to itself, however :-) - -Sound card modem support for 9600 baud FSK G3RUH modulation -CONFIG_SOUNDMODEM_FSK9600 - This option enables the soundmodem driver 9600 baud FSK modem, - compatible to the G3RUH standard. The demodulator requires about 4% - of the CPU power of a Pentium 75 CPU per channel. You can say Y to - both 1200 baud AFSK and 9600 baud FSK if you want (but obviously you - can only use one protocol at a time, depending on what the other end - can understand). - -CCITT X.25 Packet Layer -CONFIG_X25 - X.25 is a set of standardized network protocols, similar in scope to - frame relay; the one physical line from your box to the X.25 network - entry point can carry several logical point-to-point connections - (called "virtual circuits") to other computers connected to the X.25 - network. Governments, banks, and other organizations tend to use it - to connect to each other or to form Wide Area Networks (WANs). Many - countries have public X.25 networks. X.25 consists of two - protocols: the higher level Packet Layer Protocol (PLP) (say Y here - if you want that) and the lower level data link layer protocol LAPB - (say Y to "LAPB Data Link Driver" below if you want that). - - You can read more about X.25 at and - . - Information about X.25 for Linux is contained in the files - and - . - - One connects to an X.25 network either with a dedicated network card - using the X.21 protocol (not yet supported by Linux) or one can do - X.25 over a standard telephone line using an ordinary modem (say Y - to "X.25 async driver" below) or over Ethernet using an ordinary - Ethernet card and either the 802.2 LLC protocol (say Y to "802.2 - LLC" below) or LAPB over Ethernet (say Y to "LAPB Data Link Driver" - and "LAPB over Ethernet driver" below). - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called x25.o. If unsure, say N. - -LAPB Data Link Driver -CONFIG_LAPB - Link Access Procedure, Balanced (LAPB) is the data link layer (i.e. - the lower) part of the X.25 protocol. It offers a reliable - connection service to exchange data frames with one other host, and - it is used to transport higher level protocols (mostly X.25 Packet - Layer, the higher part of X.25, but others are possible as well). - Usually, LAPB is used with specialized X.21 network cards, but Linux - currently supports LAPB only over Ethernet connections. If you want - to use LAPB connections over Ethernet, say Y here and to "LAPB over - Ethernet driver" below. Read - for technical - details. - - If you want to compile this driver as a module though ( = code which - can be inserted in and removed from the running kernel whenever you - want), say M here and read . The - module will be called lapb.o. If unsure, say N. - -802.2 LLC -CONFIG_LLC - This is a Logical Link Layer protocol used for X.25 connections over - Ethernet, using ordinary Ethernet cards. - -Frame Diverter -CONFIG_NET_DIVERT - The Frame Diverter allows you to divert packets from the - network, that are not aimed at the interface receiving it (in - promisc. mode). Typically, a Linux box setup as an Ethernet bridge - with the Frames Diverter on, can do some *really* transparent www - caching using a Squid proxy for example. - - This is very useful when you don't want to change your router's - config (or if you simply don't have access to it). - - The other possible usages of diverting Ethernet Frames are - numberous: - - reroute smtp traffic to another interface - - traffic-shape certain network streams - - transparently proxy smtp connections - - etc... - - For more informations, please refer to: - - - - If unsure, say N. - -802.1d Ethernet Bridging -CONFIG_BRIDGE - If you say Y here, then your Linux box will be able to act as an - Ethernet bridge, which means that the different Ethernet segments it - is connected to will appear as one Ethernet to the participants. - Several such bridges can work together to create even larger - networks of Ethernets using the IEEE 802.1 spanning tree algorithm. - As this is a standard, Linux bridges will cooperate properly with - other third party bridge products. - - In order to use the Ethernet bridge, you'll need the bridge - configuration tools; see - for location. Please read the Bridge mini-HOWTO for more - information. - - Note that if your box acts as a bridge, it probably contains several - Ethernet devices, but the kernel is not able to recognize more than - one at boot time without help; for details read the Ethernet-HOWTO, - available from in . - - If you want to compile this code as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called bridge.o. - - If unsure, say N. - -Packet socket -CONFIG_PACKET - The Packet protocol is used by applications which communicate - directly with network devices without an intermediate network - protocol implemented in the kernel, e.g. tcpdump. If you want them - to work, choose Y. - - This driver is also available as a module called af_packet.o ( = - code which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read ; if you use modprobe - or kmod, you may also want to add "alias net-pf-17 af_packet" to - /etc/modules.conf. - - If unsure, say Y. - -Packet socket: mmapped IO -CONFIG_PACKET_MMAP - If you say Y here, the Packet protocol driver can use a faster and - more efficient capture method. This feature also allows bigger - receive buffers. To take advantage of this method who have to use - a libpcap library that supports it. For more info see - . - - If unsure, say N. - -Netlink device emulation -CONFIG_NETLINK_DEV - This option will be removed soon. Any programs that want to use - character special nodes like /dev/tap0 or /dev/route (all with major - number 36) need this option, and need to be rewritten soon to use - the real netlink socket. - This is a backward compatibility option, choose Y for now. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - netlink_dev.o - -Asynchronous Transfer Mode (ATM) -CONFIG_ATM - ATM is a high-speed networking technology for Local Area Networks - and Wide Area Networks. It uses a fixed packet size and is - connection oriented, allowing for the negotiation of minimum - bandwidth requirements. - - In order to participate in an ATM network, your Linux box needs an - ATM networking card. If you have that, say Y here and to the driver - of your ATM card below. - - Note that you need a set of user-space programs to actually make use - of ATM. See the file for - further details. - -Classical IP over ATM -CONFIG_ATM_CLIP - Classical IP over ATM for PVCs and SVCs, supporting InARP and - ATMARP. If you want to communication with other IP hosts on your ATM - network, you will typically either say Y here or to "LAN Emulation - (LANE)" below. - -Do NOT send ICMP if no neighbour -CONFIG_ATM_CLIP_NO_ICMP - Normally, an "ICMP host unreachable" message is sent if a neighbour - cannot be reached because there is no VC to it in the kernel's - ATMARP table. This may cause problems when ATMARP table entries are - briefly removed during revalidation. If you say Y here, packets to - such neighbours are silently discarded instead. - -RFC1483/2684 Bridged protocols -CONFIG_ATM_BR2684 - ATM PVCs can carry ethernet PDUs according to rfc2684 (formerly 1483) - This device will act like an ethernet from the kernels point of view, - with the traffic being carried by ATM PVCs (currently 1 PVC/device). - This is sometimes used over DSL lines. If in doubt, say N. - -Per-VC IP filter kludge -CONFIG_ATM_BR2684_IPFILTER - This is an experimental mechanism for users who need to terminating a - large number of IP-only vcc's. Do not enable this unless you are sure - you know what you are doing. - -LAN Emulation (LANE) support -CONFIG_ATM_LANE - LAN Emulation emulates services of existing LANs across an ATM - network. Besides operating as a normal ATM end station client, Linux - LANE client can also act as an proxy client bridging packets between - ELAN and Ethernet segments. You need LANE if you want to try MPOA. - -Multi-Protocol Over ATM (MPOA) support -CONFIG_ATM_MPOA - Multi-Protocol Over ATM allows ATM edge devices such as routers, - bridges and ATM attached hosts establish direct ATM VCs across - subnetwork boundaries. These shortcut connections bypass routers - enhancing overall network performance. - -ATM over TCP -CONFIG_ATM_TCP - ATM over TCP driver. Useful mainly for development and for - experiments. If unsure, say N. - -Efficient Networks ENI155P -CONFIG_ATM_ENI - Driver for the Efficient Networks ENI155p series and SMC ATM - Power155 155 Mbps ATM adapters. Both, the versions with 512KB and - 2MB on-board RAM (Efficient calls them "C" and "S", respectively), - and the FPGA and the ASIC Tonga versions of the board are supported. - The driver works with MMF (-MF or ...F) and UTP-5 (-U5 or ...D) - adapters. - - This driver is also available as a module. If you want to compile - it as a module, say M here and read - . The module will be called eni.o. - -Enable extended debugging -CONFIG_ATM_ENI_DEBUG - Extended debugging records various events and displays that list - when an inconsistency is detected. This mechanism is faster than - generally using printks, but still has some impact on performance. - Note that extended debugging may create certain race conditions - itself. Enable this ONLY if you suspect problems with the driver. - -Fine-tune burst settings -CONFIG_ATM_ENI_TUNE_BURST - In order to obtain good throughput, the ENI NIC can transfer - multiple words of data per PCI bus access cycle. Such a multi-word - transfer is called a burst. - - The default settings for the burst sizes are suitable for most PCI - chipsets. However, in some cases, large bursts may overrun buffers - in the PCI chipset and cause data corruption. In such cases, large - bursts must be disabled and only (slower) small bursts can be used. - The burst sizes can be set independently in the send (TX) and - receive (RX) direction. - - Note that enabling many different burst sizes in the same direction - may increase the cost of setting up a transfer such that the - resulting throughput is lower than when using only the largest - available burst size. - - Also, sometimes larger bursts lead to lower throughput, e.g. on an - Intel 440FX board, a drop from 135 Mbps to 103 Mbps was observed - when going from 8W to 16W bursts. - -Enable 16W TX bursts (discouraged) -CONFIG_ATM_ENI_BURST_TX_16W - Burst sixteen words at once in the send direction. This may work - with recent PCI chipsets, but is known to fail with older chipsets. - -Enable 8W TX bursts (recommended) -CONFIG_ATM_ENI_BURST_TX_8W - Burst eight words at once in the send direction. This is the default - setting. - -Enable 4W TX bursts (optional) -CONFIG_ATM_ENI_BURST_TX_4W - Burst four words at once in the send direction. You may want to try - this if you have disabled 8W bursts. Enabling 4W if 8W is also set - may or may not improve throughput. - -Enable 2W TX bursts (optional) -CONFIG_ATM_ENI_BURST_TX_2W - Burst two words at once in the send direction. You may want to try - this if you have disabled 4W and 8W bursts. Enabling 2W if 4W or 8W - are also set may or may not improve throughput. - -Enable 16W RX bursts (discouraged) -CONFIG_ATM_ENI_BURST_RX_16W - Burst sixteen words at once in the receive direction. This may work - with recent PCI chipsets, but is known to fail with older chipsets. - -Enable 8W RX bursts (discouraged) -CONFIG_ATM_ENI_BURST_RX_8W - Burst eight words at once in the receive direction. This may work - with recent PCI chipsets, but is known to fail with older chipsets, - such as the Intel Neptune series. - -Enable 4W RX bursts (recommended) -CONFIG_ATM_ENI_BURST_RX_4W - Burst four words at once in the receive direction. This is the - default setting. Enabling 4W if 8W is also set may or may not - improve throughput. - -Enable 2W RX bursts (optional) -CONFIG_ATM_ENI_BURST_RX_2W - Burst two words at once in the receive direction. You may want to - try this if you have disabled 4W and 8W bursts. Enabling 2W if 4W or - 8W are also set may or may not improve throughput. - -ZeitNet ZN1221/ZN1225 -CONFIG_ATM_ZATM - Driver for the ZeitNet ZN1221 (MMF) and ZN1225 (UTP-5) 155 Mbps ATM - adapters. - - This driver is also available as a module. If you want to compile - it as a module, say M here and read - . The module will be called zatm.o. - -Enable extended debugging -CONFIG_ATM_ZATM_DEBUG - Extended debugging records various events and displays that list - when an inconsistency is detected. This mechanism is faster than - generally using printks, but still has some impact on performance. - Note that extended debugging may create certain race conditions - itself. Enable this ONLY if you suspect problems with the driver. - -Fujitsu FireStream (FS50/FS155) -CONFIG_ATM_FIRESTREAM - Driver for the Fujitsu FireStream 155 (MB86697) and - FireStream 50 (MB86695) ATM PCI chips. - - This driver is also available as a module. If you want to compile - it as a module, say M here and read - . The module will be called - firestream.o. - -Enable usec resolution timestamps -CONFIG_ATM_ZATM_EXACT_TS - The uPD98401 SAR chip supports a high-resolution timer (approx. 30 - MHz) that is used for very accurate reception timestamps. Because - that timer overflows after 140 seconds, and also to avoid timer - drift, time measurements need to be periodically synchronized with - the normal system time. Enabling this feature will add some general - overhead for timer synchronization and also per-packet overhead for - time conversion. - -IDT 77201/11 (NICStAR) (ForeRunnerLE) -CONFIG_ATM_NICSTAR - The NICStAR chipset family is used in a large number of ATM NICs for - 25 and for 155 Mbps, including IDT cards and the Fore ForeRunnerLE - series. Say Y if you have one of those. - - This driver is also available as a module. If you want to compile - it as a module, say M here and read - . The module will be called - nicstar.o. - -Use suni PHY driver (155Mbps) -CONFIG_ATM_NICSTAR_USE_SUNI - Support for the S-UNI and compatible PHYsical layer chips. These are - found in most 155Mbps NICStAR based ATM cards, namely in the - ForeRunner LE155 cards. This driver provides detection of cable~ - removal and reinsertion and provides some statistics. This driver - doesn't have removal capability when compiled as a module, so if you - need that capability don't include S-UNI support (it's not needed to - make the card work). - -Use IDT77015 PHY driver (25Mbps) -CONFIG_ATM_NICSTAR_USE_IDT77105 - Support for the PHYsical layer chip in ForeRunner LE25 cards. In - addition to cable removal/reinsertion detection, this driver allows - you to control the loopback mode of the chip via a dedicated IOCTL. - This driver is required for proper handling of temporary carrier - loss, so if you have a 25Mbps NICStAR based ATM card you must say Y. - -IDT 77252 (NICStAR II) -CONFIG_ATM_IDT77252 - Driver for the IDT 77252 ATM PCI chips. - - This driver is also available as a module. If you want to compile - it as a module, say M here and read - . The module will be called idt77252.o - -Enable debugging messages -CONFIG_ATM_IDT77252_DEBUG - Somewhat useful debugging messages are available. The choice of - messages is controlled by a bitmap. This may be specified as a - module argument. See the file for - the meanings of the bits in the mask. - - When active, these messages can have a significant impact on the - speed of the driver, and the size of your syslog files! When - inactive, they will have only a modest impact on performance. - -Receive ALL cells in raw queue -CONFIG_ATM_IDT77252_RCV_ALL - Enable receiving of all cells on the ATM link, that do not match - an open connection in the raw cell queue of the driver. Useful - for debugging or special applications only, so the safe answer is N. - -Madge Ambassador (Collage PCI 155 Server) -CONFIG_ATM_AMBASSADOR - This is a driver for ATMizer based ATM card produced by Madge - Networks Ltd. Say Y (or M to compile as a module named ambassador.o) - here if you have one of these cards. - -Enable debugging messages -CONFIG_ATM_AMBASSADOR_DEBUG - Somewhat useful debugging messages are available. The choice of - messages is controlled by a bitmap. This may be specified as a - module argument (kernel command line argument as well?), changed - dynamically using an ioctl (not yet) or changed by sending the - string "Dxxxx" to VCI 1023 (where x is a hex digit). See the file - for the meanings of the bits in the - mask. - - When active, these messages can have a significant impact on the - speed of the driver, and the size of your syslog files! When - inactive, they will have only a modest impact on performance. - -Madge Horizon [Ultra] (Collage PCI 25 and Collage PCI 155 Client) -CONFIG_ATM_HORIZON - This is a driver for the Horizon chipset ATM adapter cards once - produced by Madge Networks Ltd. Say Y (or M to compile as a module - named horizon.o) here if you have one of these cards. - -Enable debugging messages -CONFIG_ATM_HORIZON_DEBUG - Somewhat useful debugging messages are available. The choice of - messages is controlled by a bitmap. This may be specified as a - module argument (kernel command line argument as well?), changed - dynamically using an ioctl (not yet) or changed by sending the - string "Dxxxx" to VCI 1023 (where x is a hex digit). See the file - for the meanings of the bits in the - mask. - - When active, these messages can have a significant impact on the - speed of the driver, and the size of your syslog files! When - inactive, they will have only a modest impact on performance. - -Interphase ATM PCI x575/x525/x531 -CONFIG_ATM_IA - This is a driver for the Interphase (i)ChipSAR adapter cards - which include a variety of variants in term of the size of the - control memory (128K-1KVC, 512K-4KVC), the size of the packet - memory (128K, 512K, 1M), and the PHY type (Single/Multi mode OC3, - UTP155, UTP25, DS3 and E3). Go to: - - for more info about the cards. Say Y (or M to compile as a module - named iphase.o) here if you have one of these cards. - - See the file for further - details. - -Enable debugging messages -CONFIG_ATM_IA_DEBUG - Somewhat useful debugging messages are available. The choice of - messages is controlled by a bitmap. This may be specified as a - module argument (kernel command line argument as well?), changed - dynamically using an ioctl (Get the debug utility, iadbg, from - ). - - See the file for the meanings of the - bits in the mask. - - When active, these messages can have a significant impact on the - speed of the driver, and the size of your syslog files! When - inactive, they will have only a modest impact on performance. - -Efficient Networks Speedstream 3010 -CONFIG_ATM_LANAI - Supports ATM cards based on the Efficient Networks "Lanai" - chipset such as the Speedstream 3010 and the ENI-25p. The - Speedstream 3060 is currently not supported since we don't - have the code to drive the on-board Alcatel DSL chipset (yet). - -Linux telephony support -CONFIG_PHONE - Say Y here if you have a telephony card, which for example allows - you to use a regular phone for voice-over-IP applications. - - Note: this has nothing to do with modems. You do not need to say Y - here in order to be able to use a modem under Linux. - - This support is also available as a module. If you want to compile - it as a module, say M here and read - . The module will be called - phonedev.o. - -Compaq Smart Array support -CONFIG_BLK_CPQ_CISS_DA - This is the driver for Compaq Smart Array 5xxx controllers. - Everyone using these boards should say Y here. - See for the current list of - boards supported by this driver, and for further information - on the use of this driver. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - cciss.o - -SCSI tape drive support for Smart Array 5xxx -CONFIG_CISS_SCSI_TAPE - When enabled (Y), this option allows SCSI tape drives and SCSI medium - changers (tape robots) to be accessed via a Compaq 5xxx array - controller. (See for more details.) - - "SCSI support" and "SCSI tape support" must also be enabled for this - option to work. - - When this option is disabled (N), the SCSI portion of the driver - is not compiled. - -Enable monitor thread -CONFIG_CISS_MONITOR_THREAD - Intended for use with multipath configurations (see the md driver). - This option allows a per-adapter monitoring thread to periodically - poll the adapter to detect failure modes in which the processor - is unable to receive interrupts from the adapter, thus enabling - fail-over to an alternate adapter in such situations. See - for more details. - -QuickNet Internet LineJack/PhoneJack support -CONFIG_PHONE_IXJ - Say M if you have a telephony card manufactured by Quicknet - Technologies, Inc. These include the Internet PhoneJACK and - Internet LineJACK Telephony Cards. You will get a module called - ixj.o. - - For the ISA versions of these products, you can configure the - cards using the isapnp tools (pnpdump/isapnp) or you can use the - isapnp support. Please read . - - For more information on these cards, see Quicknet's web site at: - . - - If you do not have any Quicknet telephony cards, you can safely - say N here. - -QuickNet Internet LineJack/PhoneJack PCMCIA support -CONFIG_PHONE_IXJ_PCMCIA - Say Y here to configure in PCMCIA service support for the Quicknet - cards manufactured by Quicknet Technologies, Inc. This builds an - additional support module for the PCMCIA version of the card. - -FORE Systems 200E-series -CONFIG_ATM_FORE200E_MAYBE - This is a driver for the FORE Systems 200E-series ATM adapter - cards. It simultaneously supports PCA-200E and SBA-200E models - on PCI and SBUS hosts. Say Y (or M to compile as a module - named fore_200e.o) here if you have one of these ATM adapters. - - Note that the driver will actually be compiled only if you - additionally enable the support for PCA-200E and/or SBA-200E - cards. - - See the file for - further details. - -Enable PCA-200E card support on PCI-based hosts -CONFIG_ATM_FORE200E_PCA - Say Y here if you want your PCA-200E cards to be probed. - -Use default PCA-200E firmware -CONFIG_ATM_FORE200E_PCA_DEFAULT_FW - Use the default PCA-200E firmware data shipped with the driver. - - Normal users do not have to deal with the firmware stuff, so - they should say Y here. - -Pathname of user-supplied binary firmware -CONFIG_ATM_FORE200E_PCA_FW - This defines the pathname of an alternative PCA-200E binary - firmware image supplied by the user. This pathname may be - absolute or relative to the drivers/atm directory. - - The driver comes with an adequate firmware image, so normal users do - not have to supply an alternative one. They just say Y to "Use - default PCA-200E firmware" instead. - -Enable SBA-200E card support on SBUS-based hosts -CONFIG_ATM_FORE200E_SBA - Say Y here if you want your SBA-200E cards to be probed. - -Use default SBA-200E firmware -CONFIG_ATM_FORE200E_SBA_DEFAULT_FW - Use the default SBA-200E firmware data shipped with the driver. - - Normal users do not have to deal with the firmware stuff, so - they should say Y here. - -Pathname of user-supplied binary firmware -CONFIG_ATM_FORE200E_SBA_FW - This defines the pathname of an alternative SBA-200E binary - firmware image supplied by the user. This pathname may be - absolute or relative to the drivers/atm directory. - - The driver comes with an adequate firmware image, so normal users do - not have to supply an alternative one. They just say Y to "Use - default SBA-200E firmware", above. - -Maximum number of tx retries -CONFIG_ATM_FORE200E_TX_RETRY - Specifies the number of times the driver attempts to transmit - a message before giving up, if the transmit queue of the ATM card - is transiently saturated. - - Saturation of the transmit queue may occur only under extreme - conditions, e.g. when a fast host continuously submits very small - frames (<64 bytes) or raw AAL0 cells (48 bytes) to the ATM adapter. - - Note that under common conditions, it is unlikely that you encounter - a saturation of the transmit queue, so the retry mechanism never - comes into play. - -Debugging level (0-3) -CONFIG_ATM_FORE200E_DEBUG - Specifies the level of debugging messages issued by the driver. - The verbosity of the driver increases with the value of this - parameter. - - When active, these messages can have a significant impact on - the performances of the driver, and the size of your syslog files! - Keep the debugging level to 0 during normal operations. - -ForeRunner HE Series -CONFIG_ATM_HE - This is a driver for the Marconi ForeRunner HE-series ATM adapter - cards. It simultaneously supports the 155 and 622 versions. - -Use S/UNI PHY driver - Support for the S/UNI-Ultra and S/UNI-622 found in the ForeRunner - HE cards. This driver provides carrier detection some statistics. - -PPP over ATM -CONFIG_PPPOATM - Support PPP (Point to Point Protocol) encapsulated in ATM frames. - This implementation does not yet comply with section 8 of RFC2364, - which can lead to bad results idf the ATM peer loses state and - changes its encapsulation unilaterally. - -Fusion MPT device support -CONFIG_FUSION - LSI Logic Fusion(TM) Message Passing Technology (MPT) device support - provides high performance SCSI host initiator, and LAN [1] interface - services to a host system. The Fusion architecture is capable of - duplexing these protocols on high-speed Fibre Channel - (up to 2 GHz x 2 ports = 4 GHz) and parallel SCSI (up to Ultra-320) - physical medium. - - [1] LAN is not supported on parallel SCSI medium. - - These drivers require a Fusion MPT compatible PCI adapter installed - in the host system. MPT adapters contain specialized I/O processors - to handle I/O workload, and more importantly to offload this work - from the host CPU(s). - - If you have Fusion MPT hardware and want to use it, you can say - Y or M here to add MPT (base + ScsiHost) drivers. - = build lib (fusion.o), and link [static] into the kernel [2] - proper - = compiled as [dynamic] modules [3] named: (mptbase.o, - mptscsih.o) - - [2] In order enable capability to boot the linux kernel - natively from a Fusion MPT target device, you MUST - answer Y here! (currently requires CONFIG_BLK_DEV_SD) - [3] This support is also available as a module ( = code - which can be inserted in and removed from the running - kernel whenever you want). If you want to compile as - modules, say M here and read - . - - If unsure, say N. - - If you say Y or M here you will get a choice of these - additional protocol and support module options: Module Name: - Enhanced SCSI error reporting (isense.o) - Fusion MPT misc device (ioctl) driver (mptctl.o) - Fusion MPT LAN driver (mptlan.o) - - --- - Fusion MPT is trademark of LSI Logic Corporation, and its - architecture is based on LSI Logic's Message Passing Interface (MPI) - specification. - -Maximum number of scatter gather entries -CONFIG_FUSION_MAX_SGE - This option allows you to specify the maximum number of scatter- - gather entries per I/O. The driver defaults to 40, a reasonable number - for most systems. However, the user may increase this up to 128. - Increasing this parameter will require significantly more memory - on a per controller instance. Increasing the parameter is not - necessary (or recommended) unless the user will be running - large I/O's via the raw interface. - -Fusion MPT enhanced SCSI error reporting [optional] module -CONFIG_FUSION_ISENSE - The isense module (roughly stands for Interpret SENSE data) is - completely optional. It simply provides extra English readable - strings in SCSI Error Report(s) that might be generated from the - Fusion MPT SCSI Host driver, for example when a target device - returns a SCSI check condition on a I/O. Without this module - loaded you might see: - - SCSI Error Report =-=-= (ioc0,scsi5:0) - SCSI_Status=02h (CHECK_CONDITION) - Original_CDB[]: 2A 00 00 00 00 41 00 00 02 00 - SenseData[12h]: 70 00 02 00 00 00 00 0A 00 00 00 00 04 02 02 00 00 00 - SenseKey=2h (NOT READY); FRU=02h - ASC/ASCQ=29h/00h - - Where otherwise, if this module had been loaded, you would see: - - SCSI Error Report =-=-= (ioc0,scsi5:0) - SCSI_Status=02h (CHECK_CONDITION) - Original_CDB[]: 2A 00 00 00 00 41 00 00 02 00 - "WRITE(10)" - SenseData[12h]: 70 00 02 00 00 00 00 0A 00 00 00 00 04 02 02 00 00 00 - SenseKey=2h (NOT READY); FRU=02h - ASC/ASCQ=29h/00h "LOGICAL UNIT NOT READY, INITIALIZING CMD. REQUIRED" - - Say M for "Enhanced SCSI error reporting" to compile this optional module, - creating a driver named: isense.o. - - NOTE: Support for building this feature into the kernel is not - available, due to kernel size considerations. - -Fusion MPT misc device (ioctl) driver [optional] module -CONFIG_FUSION_CTL - The Fusion MPT misc device driver provides specialized control - of MPT adapters via system ioctl calls. Use of ioctl calls to - the MPT driver requires that you create and use a misc device - node ala: - mknod /dev/mptctl c 10 240 - - One use of this ioctl interface is to perform an upgrade (reflash) - of the MPT adapter firmware. Refer to readme file(s) distributed - with the Fusion MPT linux driver for additional details. - - If enabled by saying M to this, a driver named: mptctl.o - will be compiled. - - If unsure whether you really want or need this, say N. - -Fusion MPT LAN driver [optional] -CONFIG_FUSION_LAN - This module supports LAN IP traffic over Fibre Channel port(s) - on Fusion MPT compatible hardware (LSIFC9xx chips). - The physical interface used is defined in RFC 2625. - Please refer to that document for details. - - Installing this driver requires the knowledge to configure and - activate a new network interface, "fc0", using standard Linux tools. - - If enabled by saying M to this, a driver named: mptlan.o - will be compiled. - - If unsure whether you really want or need this, say N. - - NOTES: This feature is NOT available nor supported for linux-2.2.x - kernels. You must be building a linux-2.3.x or linux-2.4.x kernel - in order to configure this option. - Support for building this feature into the linux kernel is not - yet available. - -SCSI support -CONFIG_SCSI - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - - You also need to say Y here if you want support for the parallel - port version of the 100 MB IOMEGA ZIP drive. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scsi_mod.o. If you want to compile it as - a module, say M here and read and - . However, do not compile this as a - module if your root file system (the one containing the directory /) - is located on a SCSI device. - -SCSI disk support -CONFIG_BLK_DEV_SD - If you want to use a SCSI hard disk or the SCSI or parallel port - version of the IOMEGA ZIP drive under Linux, say Y and read the - SCSI-HOWTO, the Disk-HOWTO and the Multi-Disk-HOWTO, available from - . This is NOT for SCSI - CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called sd_mod.o. If you want to compile it as a - module, say M here and read and - . Do not compile this driver as a - module if your root file system (the one containing the directory /) - is located on a SCSI disk. In this case, do not compile the driver - for your SCSI host adapter (below) as a module either. - -Maximum number of SCSI disks that can be loaded as modules -CONFIG_SD_EXTRA_DEVS - This controls the amount of additional space allocated in tables for - drivers that are loaded as modules after the kernel is booted. In - the event that the SCSI core itself was loaded as a module, this - value is the number of additional disks that can be loaded after the - first host driver is loaded. - - Admittedly this isn't pretty, but there are tons of race conditions - involved with resizing the internal arrays on the fly. Someday this - flag will go away, and everything will work automatically. - - If you don't understand what's going on, go with the default. - -Maximum number of SCSI tapes that can be loaded as modules -CONFIG_ST_EXTRA_DEVS - This controls the amount of additional space allocated in tables for - drivers that are loaded as modules after the kernel is booted. In - the event that the SCSI core itself was loaded as a module, this - value is the number of additional tapes that can be loaded after the - first host driver is loaded. - - Admittedly this isn't pretty, but there are tons of race conditions - involved with resizing the internal arrays on the fly. Someday this - flag will go away, and everything will work automatically. - - If you don't understand what's going on, go with the default. - -SCSI tape support -CONFIG_CHR_DEV_ST - If you want to use a SCSI tape drive under Linux, say Y and read the - SCSI-HOWTO, available from - , and - in the kernel source. This is NOT for - SCSI CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called st.o. If you want to compile it as a - module, say M here and read and - . - -OnStream SC-x0 SCSI tape support -CONFIG_CHR_DEV_OSST - The OnStream SC-x0 SCSI tape drives can not be driven by the - standard st driver, but instead need this special osst driver and - use the /dev/osstX char device nodes (major 206). Via usb-storage - and ide-scsi, you may be able to drive the USB-x0 and DI-x0 drives - as well. Note that there is also a second generation of OnStream - tape drives (ADR-x0) that supports the standard SCSI-2 commands for - tapes (QIC-157) and can be driven by the standard driver st. - For more information, you may have a look at the SCSI-HOWTO - and - in the kernel source. - More info on the OnStream driver may be found on - - Please also have a look at the standard st docu, as most of it - applies to osst as well. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called osst.o. If you want to compile it as a - module, say M here and read and - . - -SCSI CD-ROM support -CONFIG_BLK_DEV_SR - If you want to use a SCSI CD-ROM under Linux, say Y and read the - SCSI-HOWTO and the CD-ROM-HOWTO at - . Also make sure to say Y - or M to "ISO 9660 CD-ROM file system support" later. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called sr_mod.o. If you want to compile it as a - module, say M here and read and - . - -Maximum number of CD-ROM devices that can be loaded as modules -CONFIG_SR_EXTRA_DEVS - This controls the amount of additional space allocated in tables for - drivers that are loaded as modules after the kernel is booted. In - the event that the SCSI core itself was loaded as a module, this - value is the number of additional CD-ROMs that can be loaded after - the first host driver is loaded. - - Admittedly this isn't pretty, but there are tons of race conditions - involved with resizing the internal arrays on the fly. Someday this - flag will go away, and everything will work automatically. - - If you don't understand what's going on, go with the default. - -Enable vendor-specific extensions (for SCSI CD-ROM) -CONFIG_BLK_DEV_SR_VENDOR - This enables the usage of vendor specific SCSI commands. This is - required to support multisession CDs with old NEC/TOSHIBA cdrom - drives (and HP Writers). If you have such a drive and get the first - session only, try saying Y here; everybody else says N. - -SCSI generic support -CONFIG_CHR_DEV_SG - If you want to use SCSI scanners, synthesizers or CD-writers or just - about anything having "SCSI" in its name other than hard disks, - CD-ROMs or tapes, say Y here. These won't be supported by the kernel - directly, so you need some additional software which knows how to - talk to these devices using the SCSI protocol: - - For scanners, look at SANE (). For CD - writer software look at Cdrtools - () - and for burning a "disk at once": CDRDAO - (). Cdparanoia is a high - quality digital reader of audio CDs (). - For other devices, it's possible that you'll have to write the - driver software yourself. Please read the file - for more information. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read and - . The module will be called sg.o. If unsure, - say N. - -Probe all LUNs on each SCSI device -CONFIG_SCSI_MULTI_LUN - If you have a SCSI device that supports more than one LUN (Logical - Unit Number), e.g. a CD jukebox, and only one LUN is detected, you - can say Y here to force the SCSI driver to probe for multiple LUNs. - A SCSI device with multiple LUNs acts logically like multiple SCSI - devices. The vast majority of SCSI devices have only one LUN, and - so most people can say N here and should in fact do so, because it - is safer. - -Verbose SCSI error reporting (kernel size +=12K) -CONFIG_SCSI_CONSTANTS - The error messages regarding your SCSI hardware will be easier to - understand if you say Y here; it will enlarge your kernel by about - 12 KB. If in doubt, say Y. - -SCSI logging facility -CONFIG_SCSI_LOGGING - This turns on a logging facility that can be used to debug a number - of SCSI related problems. - - If you say Y here, no logging output will appear by default, but you - can enable logging by saying Y to "/proc file system support" and - "Sysctl support" below and executing the command - - echo "scsi log token [level]" > /proc/scsi/scsi - - at boot time after the /proc file system has been mounted. - - There are a number of things that can be used for 'token' (you can - find them in the source: ), and this - allows you to select the types of information you want, and the - level allows you to select the level of verbosity. - - If you say N here, it may be harder to track down some types of SCSI - problems. If you say Y here your kernel will be somewhat larger, but - there should be no noticeable performance impact as long as you have - logging turned off. - -QDIO base support for IBM S/390 and zSeries -CONFIG_QDIO - This driver provides the Queued Direct I/O base support for the - IBM S/390 (G5 and G6) and eServer zSeries (z800 and z900). - - For details please refer to the documentation provided by IBM at - - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called qdio.o. If you want to compile it as a - module, say M here and read . - - If unsure, say Y. - -Performance statistics for QDIO base support -CONFIG_QDIO_PERF_STATS - Say Y here to get performance statistics in /proc/qdio_perf - - If unsure, say N. - -SGI WD93C93 SCSI Driver -CONFIG_SCSI_SGIWD93 - Say Y here to support the on-board WD93C93 SCSI controller found (a) - on the Indigo2 and other MIPS-based SGI machines, and (b) on ARCS - ARM-based machines. - -DEC NCR53C94 SCSI Driver -CONFIG_SCSI_DECNCR - Say Y here to support the NCR53C94 SCSI controller chips on IOASIC - based TURBOchannel DECstations and TURBOchannel PMAZ-A cards. - -AdvanSys SCSI support -CONFIG_SCSI_ADVANSYS - This is a driver for all SCSI host adapters manufactured by - AdvanSys. It is documented in the kernel source in - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - advansys.o. - -Adaptec AHA152X/2825 support -CONFIG_SCSI_AHA152X - This is a driver for the AHA-1510, AHA-1520, AHA-1522, and AHA-2825 - SCSI host adapters. It also works for the AVA-1505, but the IRQ etc. - must be manually specified in this case. - - It is explained in section 3.3 of the SCSI-HOWTO, available from - . You might also want to - read the file . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called aha152x.o. If you want to compile it as a - module, say M here and read . - -Adaptec AHA1542 support -CONFIG_SCSI_AHA1542 - This is support for a SCSI host adapter. It is explained in section - 3.4 of the SCSI-HOWTO, available from - . Note that Trantor was - purchased by Adaptec, and some former Trantor products are being - sold under the Adaptec name. If it doesn't work out of the box, you - may have to change some settings in . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called aha1542.o. - -Adaptec AHA1740 support -CONFIG_SCSI_AHA1740 - This is support for a SCSI host adapter. It is explained in section - 3.5 of the SCSI-HOWTO, available from - . If it doesn't work out - of the box, you may have to change some settings in - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called aha1740.o. If you want to compile it as a - module, say M here and read . - -Adaptec AIC7xxx support -CONFIG_SCSI_AIC7XXX - This driver supports all of Adaptec's Fast through Ultra 160 PCI - based SCSI controllers as well as the aic7770 based EISA and VLB - SCSI controllers (the 274x and 284x series). For AAA and ARO based - configurations, only SCSI functionality is provided. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called aic7xxx.o. - -Maximum number of TCQ commands per device -CONFIG_AIC7XXX_CMDS_PER_DEVICE - Specify the number of commands you would like to allocate per SCSI - device when Tagged Command Queueing (TCQ) is enabled on that device. - - This is an upper bound value for the number of tagged transactions - to be used for any device. The aic7xxx driver will automatically - vary this number based on device behavior. For devices with a - fixed maximum, the driver will eventually lock to this maximum - and display a console message indicating this value. - - Due to resource allocation issues in the Linux SCSI mid-layer, using - a high number of commands per device may result in memory allocation - failures when many devices are attached to the system. For this reason, - the default is set to 32. Higher values may result in higer performance - on some devices. The upper bound is 253. 0 disables tagged queueing. - - Per device tag depth can be controlled via the kernel command line - "tag_info" option. See drivers/scsi/aic7xxx/README.aic7xxx - for details. - - Default: 32 - -Initial bus reset delay in milli-seconds -CONFIG_AIC7XXX_RESET_DELAY_MS - The number of milliseconds to delay after an initial bus reset. - The bus settle delay following all error recovery actions is - dictated by the SCSI layer and is not affected by this value. - - Default: 15000 (15 seconds) - -Probe for EISA and VL AIC7XXX Adapters -CONFIG_AIC7XXX_PROBE_EISA_VL - Probe for EISA and VLB Aic7xxx controllers. In many newer systems, - the invasive probes necessary to detect these controllers can cause - other devices to fail. For this reason, the non-PCI probe code is - disabled by default. The current value of this option can be "toggled" - via the no_probe kernel command line option. - -CONFIG_AIC7XXX_BUILD_FIRMWARE - This option should only be enabled if you are modifying the firmware - source to the aic7xxx driver and wish to have the generated firmware - include files updated during a normal kernel build. The assembler - for the firmware requires lex and yacc or their equivalents, as well - as the db v1 library. You may have to install additional packages - or modify the assembler Makefile or the files it includes if your - build environment is different than that of the author. - -Compile in Debugging Code -CONFIG_AIC7XXX_DEBUG_ENABLE - Compile in aic7xxx debugging code that can be useful in diagnosing - driver errors. - -Debug code enable mask (2048 for all debugging) -CONFIG_AIC7XXX_DEBUG_MASK - Bit mask of debug options that is only valid if the - CONFIG_AIC7XXX_DEBUG_ENBLE option is enabled. The bits in this mask - are defined in the drivers/scsi/aic7xxx/aic7xxx.h - search for the - variable ahc_debug in that file to find them. - - Default: 0 - -Decode registers during diagnostics -CONFIG_AIC7XXX_REG_PRETTY_PRINT - Compile in register value tables for the output of expanded register - contents in diagnostics. This make it much easier to understand debug - output without having to refer to a data book and/or the aic7xxx.reg file. - -Old Adaptec AIC7xxx support -CONFIG_SCSI_AIC7XXX_OLD - WARNING This driver is an older aic7xxx driver and is no longer - under active development. Adaptec, Inc. is writing a new driver to - take the place of this one, and it is recommended that whenever - possible, people should use the new Adaptec written driver instead - of this one. This driver will eventually be phased out entirely. - - This is support for the various aic7xxx based Adaptec SCSI - controllers. These include the 274x EISA cards; 284x VLB cards; - 2902, 2910, 293x, 294x, 394x, 3985 and several other PCI and - motherboard based SCSI controllers from Adaptec. It does not support - the AAA-13x RAID controllers from Adaptec, nor will it likely ever - support them. It does not support the 2920 cards from Adaptec that - use the Future Domain SCSI controller chip. For those cards, you - need the "Future Domain 16xx SCSI support" driver. - - In general, if the controller is based on an Adaptec SCSI controller - chip from the aic777x series or the aic78xx series, this driver - should work. The only exception is the 7810 which is specifically - not supported (that's the RAID controller chip on the AAA-13x - cards). - - Note that the AHA2920 SCSI host adapter is *not* supported by this - driver; choose "Future Domain 16xx SCSI support" instead if you have - one of those. - - Information on the configuration options for this controller can be - found by checking the help file for each of the available - configuration options. You should read - at a minimum before - contacting the maintainer with any questions. The SCSI-HOWTO, - available from , can also - be of great help. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called aic7xxx_old.o. - -Enable tagged command queueing (TCQ) by default -CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT - This option causes the aic7xxx driver to attempt to use Tagged - Command Queueing (TCQ) on all devices that claim to support it. - - TCQ is a feature of SCSI-2 which improves performance: the host - adapter can send several SCSI commands to a device's queue even if - previous commands haven't finished yet. Because the device is - intelligent, it can optimize its operations (like head positioning) - based on its own request queue. Not all devices implement this - correctly. - - If you say Y here, you can still turn off TCQ on troublesome devices - with the use of the tag_info boot parameter. See the file - for more information on that and - other aic7xxx setup commands. If this option is turned off, you may - still enable TCQ on known good devices by use of the tag_info boot - parameter. - - If you are unsure about your devices then it is safest to say N - here. - - However, TCQ can increase performance on some hard drives by as much - as 50% or more, so it is recommended that if you say N here, you - should at least read the file so - you will know how to enable this option manually should your drives - prove to be safe in regards to TCQ. - - Conversely, certain drives are known to lock up or cause bus resets - when TCQ is enabled on them. If you have a Western Digital - Enterprise SCSI drive for instance, then don't even bother to enable - TCQ on it as the drive will become unreliable, and it will actually - reduce performance. - -Default number of TCQ commands per device -CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE - Specify the number of commands you would like to allocate per SCSI - device when Tagged Command Queueing (TCQ) is enabled on that device. - - Reasonable figures are in the range of 8 to 24 commands per device, - but depending on hardware could be increased or decreased from that - figure. If the number is too high for any particular device, the - driver will automatically compensate usually after only 10 minutes - of uptime. It will not hinder performance if some of your devices - eventually have their command depth reduced, but is a waste of - memory if all of your devices end up reducing this number down to a - more reasonable figure. - - NOTE: Certain very broken drives are known to lock up when given - more commands than they like to deal with. Quantum Fireball drives - are the most common in this category. For the Quantum Fireball - drives it is suggested to use no more than 8 commands per device. - - Default: 8 - -Collect statistics to report in /proc -CONFIG_AIC7XXX_OLD_PROC_STATS - This option tells the driver to keep track of how many commands have - been sent to each particular device and report that information to - the user via the /proc/scsi/aic7xxx/n file, where n is the number of - the aic7xxx controller you want the information on. This adds a - small amount of overhead to each and every SCSI command the aic7xxx - driver handles, so if you aren't really interested in this - information, it is best to leave it disabled. This will only work if - you also say Y to "/proc file system support", below. - - If unsure, say N. - -CONFIG_SCSI_AIC79XX - This driver supports all of Adaptec's Ultra 320 PCI-X based SCSI controllers. - -CONFIG_AIC79XX_CMDS_PER_DEVICE 32 - Specify the number of commands you would like to allocate per SCSI - device when Tagged Command Queueing (TCQ) is enabled on that device. - - This is an upper bound value for the number of tagged transactions - to be used for any device. The aic7xxx driver will automatically - vary this number based on device behavior. For devices with a - fixed maximum, the driver will eventually lock to this maximum - and display a console message indicating this value. - - Due to resource allocation issues in the Linux SCSI mid-layer, using - a high number of commands per device may result in memory allocation - failures when many devices are attached to the system. For this reason, - the default is set to 32. Higher values may result in higer performance - on some devices. The upper bound is 253. - - Per device tag depth can be controlled via the kernel command line - "tag_info" option. See drivers/scsi/aic7xxx/README.aic79xx - for details. - - Default: 32 - -CONFIG_AIC79XX_RESET_DELAY_MS 15000 - The number of milliseconds to delay after an initial bus reset. - The bus settle delay following all error recovery actions is - dictated by the SCSI layer and is not affected by this value. - - Default: 15000 (15 seconds) - -CONFIG_AIC79XX_BUILD_FIRMWARE - This option should only be enabled if you are modifying the firmware - source to the aic7xxx driver and wish to have the generated firmware - include files updated during a normal kernel build. The assembler - for the firmware requires lex and yacc or their equivalents, as well - as the db v1 library. You may have to install additional packages - or modify the assembler Makefile or the files it includes if your - build environment is different than that of the author. - -CONFIG_AIC79XX_ENABLE_RD_STRM - Read Streaming is a U320 protocol option that should enhance performance. - Early U320 drive firmware actually performs slower with read streaming - enabled so it is disabled by default. Read Streaming can be configured - in much the same way as tagged queueing using the "rd_strm" command line - option. See drivers/scsi/aic7xxx/README.aic79xx for details. - -CONFIG_AIC79XX_DEBUG_ENABLE - Compile in aic79xx debugging code that can be useful in diagnosing - driver errors. - -CONFIG_AIC79XX_DEBUG_MASK - Bit mask of debug options that is only valid if the - CONFIG_AIC79XX_DEBUG_ENBLE option is enabled. The bits in this mask - are defined in the drivers/scsi/aic7xxx/aic79xx.h - search for the - variable ahd_debug in that file to find them. - - Default: 0 - -CONFIG_AIC79XX_REG_PRETTY_PRINT - Compile in register value tables for the output of expanded register - contents in diagnostics. This make it much easier to understand debug - output without having to refer to a data book and/or the aic7xxx.reg file. - -Adaptec I2O RAID support -CONFIG_SCSI_DPT_I2O - This driver supports all of Adaptec's I2O based RAID controllers as - well as the DPT SmartRaid V cards. This is an Adaptec maintained - driver by Deanna Bonds. See . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - dpt_i2o.o. - -IBM ServeRAID support -CONFIG_SCSI_IPS - This is support for the IBM ServeRAID hardware RAID controllers. - See - for more information. If this driver does not work correctly - without modification please contact the author by email at - ipslinux@us.ibm.com. - - You can build this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - but only a single instance may be loaded. If you want to compile it - as a module, say M here and read . - The module will be called ips.o. - -BusLogic SCSI support -CONFIG_SCSI_BUSLOGIC - This is support for BusLogic MultiMaster and FlashPoint SCSI Host - Adapters. Consult the SCSI-HOWTO, available from - , and the files - and - for more information. If this - driver does not work correctly without modification, please contact - the author, Leonard N. Zubkoff, by email to lnz@dandelion.com. - - You can also build this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - but only a single instance may be loaded. If you want to compile it - as a module, say M here and read . - The module will be called BusLogic.o. - -Omit BusLogic SCSI FlashPoint support -CONFIG_SCSI_OMIT_FLASHPOINT - This option allows you to omit the FlashPoint support from the - BusLogic SCSI driver. The FlashPoint SCCB Manager code is - substantial, so users of MultiMaster Host Adapters may wish to omit - it. - -Compaq Fibre Channel 64-bit/66Mhz HBA support -CONFIG_SCSI_CPQFCTS - Say Y here to compile in support for the Compaq StorageWorks Fibre - Channel 64-bit/66Mhz Host Bus Adapter. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called cpqfc.o. - -DMX3191D SCSI support -CONFIG_SCSI_DMX3191D - This is support for Domex DMX3191D SCSI Host Adapters. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called dmx3191d.o. If you want to compile it as - a module, say M here and read . - -DTC3180/3280 SCSI support -CONFIG_SCSI_DTC3280 - This is support for DTC 3180/3280 SCSI Host Adapters. Please read - the SCSI-HOWTO, available from - , and the file - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called dtc.o. If you want to compile it as a - module, say M here and read . - -EATA-DMA [Obsolete] (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support -CONFIG_SCSI_EATA_DMA - This is support for the EATA-DMA protocol compliant SCSI Host - Adapters like the SmartCache III/IV, SmartRAID controller families - and the DPT PM2011B and PM2012B controllers. - - Note that this driver is obsolete; if you have one of the above - SCSI Host Adapters, you should normally say N here and Y to "EATA - ISA/EISA/PCI support", below. Please read the SCSI-HOWTO, available - from . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called eata_dma.o. If you want to compile it as - a module, say M here and read . - -EATA-PIO (old DPT PM2001, PM2012A) support -CONFIG_SCSI_EATA_PIO - This driver supports all EATA-PIO protocol compliant SCSI Host - Adapters like the DPT PM2001 and the PM2012A. EATA-DMA compliant - host adapters could also use this driver but are discouraged from - doing so, since this driver only supports hard disks and lacks - numerous features. You might want to have a look at the SCSI-HOWTO, - available from . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called eata_pio.o. - -UltraStor 14F/34F support -CONFIG_SCSI_U14_34F - This is support for the UltraStor 14F and 34F SCSI-2 host adapters. - The source at contains some - information about this hardware. If the driver doesn't work out of - the box, you may have to change some settings in - . Read the SCSI-HOWTO, available from - . Note that there is also - another driver for the same hardware: "UltraStor SCSI support", - below. You should say Y to both only if you want 24F support as - well. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called u14-34f.o. If you want to compile it as a - module, say M here and read . - -enable elevator sorting -CONFIG_SCSI_U14_34F_LINKED_COMMANDS - This option enables elevator sorting for all probed SCSI disks and - CD-ROMs. It definitely reduces the average seek distance when doing - random seeks, but this does not necessarily result in a noticeable - performance improvement: your mileage may vary... - - The safe answer is N. - -maximum number of queued commands -CONFIG_SCSI_U14_34F_MAX_TAGS - This specifies how many SCSI commands can be maximally queued for - each probed SCSI device. You should reduce the default value of 8 - only if you have disks with buggy or limited tagged command support. - Minimum is 2 and maximum is 14. This value is also the window size - used by the elevator sorting option above. The effective value used - by the driver for each probed SCSI device is reported at boot time. - -Future Domain 16xx SCSI/AHA-2920A support -CONFIG_SCSI_FUTURE_DOMAIN - This is support for Future Domain's 16-bit SCSI host adapters - (TMC-1660/1680, TMC-1650/1670, TMC-3260, TMC-1610M/MER/MEX) and - other adapters based on the Future Domain chipsets (Quantum - ISA-200S, ISA-250MG; Adaptec AHA-2920A; and at least one IBM board). - It is explained in section 3.7 of the SCSI-HOWTO, available from - . - - NOTE: Newer Adaptec AHA-2920C boards use the Adaptec AIC-7850 chip - and should use the aic7xxx driver ("Adaptec AIC7xxx chipset SCSI - controller support"). This Future Domain driver works with the older - Adaptec AHA-2920A boards with a Future Domain chip on them. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called fdomain.o. If you want to compile it as a - module, say M here and read . - -Future Domain MCS-600/700 SCSI support -CONFIG_SCSI_FD_MCS - This is support for Future Domain MCS 600/700 MCA SCSI adapters. - Some PS/2 computers are equipped with IBM Fast SCSI Adapter/A which - is identical to the MCS 700 and hence also supported by this driver. - This driver also supports the Reply SB16/SCSI card (the SCSI part). - It supports multiple adapters in the same system. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called fd_mcs.o. If you want to compile it as a - module, say M here and read . - -Generic NCR5380/53c400 SCSI support -CONFIG_SCSI_GENERIC_NCR5380 - This is the generic NCR family of SCSI controllers, not to be - confused with the NCR 53c7 or 8xx controllers. It is explained in - section 3.8 of the SCSI-HOWTO, available from - . If it doesn't work out - of the box, you may have to change some settings in - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called g_NCR5380.o. If you want to compile it as - a module, say M here and read . - -Enable NCR53c400 extensions -CONFIG_SCSI_GENERIC_NCR53C400 - This enables certain optimizations for the NCR53c400 SCSI cards. - You might as well try it out. Note that this driver will only probe - for the Trantor T130B in its default configuration; you might have - to pass a command line option to the kernel at boot time if it does - not detect your card. See the file - for details. - -# Choice: ncr5380 -NCR5380/53c400 mapping method (use Port for T130B) -CONFIG_SCSI_G_NCR5380_PORT - The NCR5380 and NCR53c400 SCSI controllers come in two varieties: - port or memory mapped. You should know what you have. The most - common card, Trantor T130B, uses port mapped mode. - -NCR Dual 700 MCA SCSI support -CONFIG_SCSI_NCR_D700 - This is a driver for the MicroChannel Dual 700 card produced by - NCR and commonly used in 345x/35xx/4100 class machines. It always - tries to negotiate sync and uses tag command queueing. - - Unless you have an NCR manufactured machine, the chances are that - you do not have this SCSI card, so say N. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called NCR_D700.o. - -HP LASI SCSI support for 53c700/710 -CONFIG_SCSI_LASI700 - This is a driver for the lasi baseboard in some parisc machines - which is based on the 53c700 chip. Will also support LASI subsystems - based on the 710 chip using 700 emulation mode. - - Unless you know you have a 53c700 or 53c710 based lasi, say N here - -NCR53c7,8xx SCSI support -CONFIG_SCSI_NCR53C7xx - This is a driver for the 53c7 and 8xx NCR family of SCSI - controllers, not to be confused with the NCR 5380 controllers. It - is explained in section 3.8 of the SCSI-HOWTO, available from - . If it doesn't work out - of the box, you may have to change some settings in - . Please read - for the available boot time - command line options. - - Note: there is another driver for the 53c8xx family of controllers - ("NCR53C8XX SCSI support" below). If you want to use them both, you - need to say M to both and build them as modules, but only one may be - active at a time. If you have a 53c8xx board, it's better to use the - other driver. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called 53c7,8xx.o. If you want to compile it as - a module, say M here and read . - -Always negotiate synchronous transfers -CONFIG_SCSI_NCR53C7xx_sync - In general, this is good; however, it is a bit dangerous since there - are some broken SCSI devices out there. Take your chances. Safe bet - is N. - -Allow FAST-SCSI [10MHz] -CONFIG_SCSI_NCR53C7xx_FAST - This will enable 10MHz FAST-SCSI transfers with your host - adapter. Some systems have problems with that speed, so it's safest - to say N here. - -Allow DISCONNECT -CONFIG_SCSI_NCR53C7xx_DISCONNECT - This enables the disconnect/reconnect feature of the NCR SCSI - controller. When you say Y here, a slow SCSI device will not lock - the SCSI bus while processing a request, allowing simultaneous use - of e.g. a SCSI hard disk and SCSI tape or CD-ROM drive, and - providing much better performance when using slow and fast SCSI - devices at the same time. Some devices, however, do not operate - properly with this option enabled, and will cause your SCSI system - to hang, which might cause a system crash. The safe answer - therefore is to say N. - -SYM53C8XX Version 2 SCSI support -CONFIG_SCSI_SYM53C8XX_2 - This driver supports the whole NCR53C8XX/SYM53C8XX family of - PCI-SCSI controllers. It also supports the subset of LSI53C10XX - Ultra-160 controllers that are based on the SYM53C8XX SCRIPTS - language. It does not support LSI53C10XX Ultra-320 PCI-X SCSI - controllers. - - If your system has problems using this new major version of the - SYM53C8XX driver, you may switch back to driver version 1. - - Please read for more - information. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called sym53c8xx_2.o. - -PCI DMA addressing mode -CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE - This option only applies to PCI-SCSI chip that are PCI DAC capable - (875A, 895A, 896, 1010-33, 1010-66, 1000). - - When set to 0, only PCI 32 bit DMA addressing (SAC) will be performed. - When set to 1, 40 bit DMA addressing (with upper 24 bits of address - set to zero) is supported. The addressable range is here 1 TB. - When set to 2, full 64 bits of address for DMA are supported, but only - 16 segments of 4 GB can be addressed. The addressable range is so - limited to 64 GB. - - The safest value is 0 (32 bit DMA addressing) that is guessed to still - fit most of real machines. - - The preferred value 1 (40 bit DMA addressing) should make happy - properly engineered PCI DAC capable host bridges. You may configure - this option for Intel platforms with more than 4 GB of memory. - - The still experimental value 2 (64 bit DMA addressing with 16 x 4GB - segments limitation) can be used on systems that require PCI address - bits past bit 39 to be set for the addressing of memory using PCI - DAC cycles. - -use normal IO -CONFIG_SCSI_SYM53C8XX_IOMAPPED - If you say Y here, the driver will preferently use normal IO rather than - memory mapped IO. - -maximum number of queued commands -CONFIG_SCSI_SYM53C8XX_MAX_TAGS - This option allows you to specify the maximum number of commands - that can be queued to any device, when tagged command queuing is - possible. The driver supports up to 256 queued commands per device. - This value is used as a compiled-in hard limit. - -default tagged command queue depth -CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS - This is the default value of the command queue depth the driver will - announce to the generic SCSI layer for devices that support tagged - command queueing. This value can be changed from the boot command line. - This is a soft limit that cannot exceed CONFIG_SCSI_SYM53C8XX_MAX_TAGS. - -NCR53C8XX SCSI support -CONFIG_SCSI_NCR53C8XX - This is the BSD ncr driver adapted to Linux for the NCR53C8XX family - of PCI-SCSI controllers. This driver supports parity checking, - tagged command queuing and fast synchronous data transfers up to 80 - MB/s with wide FAST-40 LVD devices and controllers. - - Recent versions of the 53C8XX chips are better supported by the - option "SYM53C8XX SCSI support", below. - - Note: there is yet another driver for the 53c8xx family of - controllers ("NCR53c7,8xx SCSI support" above). If you want to use - them both, you need to say M to both and build them as modules, but - only one may be active at a time. If you have a 53c8xx board, you - probably do not want to use the "NCR53c7,8xx SCSI support". - - Please read for more - information. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ncr53c8xx.o. - -SYM53C8XX Version 1 SCSI support -CONFIG_SCSI_SYM53C8XX - This driver supports all the features of recent 53C8XX chips (used - in PCI SCSI controllers), notably the hardware phase mismatch - feature of the SYM53C896. - - Older versions of the 53C8XX chips are not supported by this - driver. If your system uses either a 810 rev. < 16, a 815, or a 825 - rev. < 16 PCI SCSI processor, you must use the generic NCR53C8XX - driver ("NCR53C8XX SCSI support" above) or configure both the - NCR53C8XX and this SYM53C8XX drivers either as module or linked to - the kernel image. - - When both drivers are linked into the kernel, the SYM53C8XX driver - is called first at initialization and you can use the 'excl=ioaddr' - driver boot option to exclude attachment of adapters by the - SYM53C8XX driver. For example, entering - 'sym53c8xx=excl:0xb400,excl=0xc000' at the lilo prompt prevents - adapters at io address 0xb400 and 0xc000 from being attached by the - SYM53C8XX driver, thus allowing the NCR53C8XX driver to attach them. - The 'excl' option is also supported by the NCR53C8XX driver. - - Please read for more - information. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called sym53c8xx.o. - -Synchronous transfer frequency in MHz -CONFIG_SCSI_NCR53C8XX_SYNC - The SCSI Parallel Interface-2 Standard defines 5 classes of transfer - rates: FAST-5, FAST-10, FAST-20, FAST-40 and FAST-80. The numbers - are respectively the maximum data transfer rates in mega-transfers - per second for each class. For example, a FAST-20 Wide 16 device is - able to transfer data at 20 million 16 bit packets per second for a - total rate of 40 MB/s. - - You may specify 0 if you want to only use asynchronous data - transfers. This is the safest and slowest option. Otherwise, specify - a value between 5 and 80, depending on the capability of your SCSI - controller. The higher the number, the faster the data transfer. - Note that 80 should normally be ok since the driver decreases the - value automatically according to the controller's capabilities. - - Your answer to this question is ignored for controllers with NVRAM, - since the driver will get this information from the user set-up. It - also can be overridden using a boot setup option, as follows - (example): 'ncr53c8xx=sync:12' will allow the driver to negotiate - for FAST-20 synchronous data transfer (20 mega-transfers per - second). - - The normal answer therefore is not to go with the default but to - select the maximum value 80 allowing the driver to use the maximum - value supported by each controller. If this causes problems with - your SCSI devices, you should come back and decrease the value. - - There is no safe option other than using good cabling, right - terminations and SCSI conformant devices. - -Use normal IO -CONFIG_SCSI_NCR53C8XX_IOMAPPED - If you say Y here, the driver will use normal IO, as opposed to - memory mapped IO. Memory mapped IO has less latency than normal IO - and works for most Intel-based hardware. Under Linux/Alpha only - normal IO is currently supported by the driver and so, this option - has no effect on those systems. - - The normal answer therefore is N; try Y only if you encounter SCSI - related problems. - -Not allow targets to disconnect -CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT - This option is only provided for safety if you suspect some SCSI - device of yours to not support properly the target-disconnect - feature. In that case, you would say Y here. In general however, to - not allow targets to disconnect is not reasonable if there is more - than 1 device on a SCSI bus. The normal answer therefore is N. - -Default tagged command queue depth -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS - "Tagged command queuing" is a feature of SCSI-2 which improves - performance: the host adapter can send several SCSI commands to a - device's queue even if previous commands haven't finished yet. - Because the device is intelligent, it can optimize its operations - (like head positioning) based on its own request queue. Some SCSI - devices don't implement this properly; if you want to disable this - feature, enter 0 or 1 here (it doesn't matter which). - - The default value is 8 and should be supported by most hard disks. - This value can be overridden from the boot command line using the - 'tags' option as follows (example): - 'ncr53c8xx=tags:4/t2t3q16/t0u2q10' will set default queue depth to - 4, set queue depth to 16 for target 2 and target 3 on controller 0 - and set queue depth to 10 for target 0 / lun 2 on controller 1. - - The normal answer therefore is to go with the default 8 and to use - a boot command line option for devices that need to use a different - command queue depth. - - There is no safe option other than using good SCSI devices. - -Maximum number of queued commands -CONFIG_SCSI_NCR53C8XX_MAX_TAGS - This option allows you to specify the maximum number of commands - that can be queued to any device, when tagged command queuing is - possible. The default value is 32. Minimum is 2, maximum is 64. - Modern hard disks are able to support 64 tags and even more, but - do not seem to be faster when more than 32 tags are being used. - - So, the normal answer here is to go with the default value 32 unless - you are using very large hard disks with large cache (>= 1 MB) that - are able to take advantage of more than 32 tagged commands. - - There is no safe option and the default answer is recommended. - -Assume boards are SYMBIOS compatible -CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT - This option allows you to enable some features depending on GPIO - wiring. These General Purpose Input/Output pins can be used for - vendor specific features or implementation of the standard SYMBIOS - features. Genuine SYMBIOS controllers use GPIO0 in output for - controller LED and GPIO3 bit as a flag indicating - singled-ended/differential interface. The Tekram DC-390U/F boards - uses a different GPIO wiring. - - Your answer to this question is ignored if all your controllers have - NVRAM, since the driver is able to detect the board type from the - NVRAM format. - - If all the controllers in your system are genuine SYMBIOS boards or - use BIOS and drivers from SYMBIOS, you would want to say Y here, - otherwise N. N is the safe answer. - -Enable traffic profiling -CONFIG_SCSI_NCR53C8XX_PROFILE - This option allows you to enable profiling information gathering. - These statistics are not very accurate due to the low frequency - of the kernel clock (100 Hz on i386) and have performance impact - on systems that use very fast devices. - - The normal answer therefore is N. - -Include support for the NCR PQS/PDS SCSI card -CONFIG_SCSI_NCR53C8XX_PQS_PDS - Say Y here if you have a special SCSI adapter produced by NCR - corporation called a PCI Quad SCSI or PCI Dual SCSI. You do not need - this if you do not have one of these adapters. However, since this - device is detected as a specific PCI device, this option is quite - safe. - - The common answer here is N, but answering Y is safe. - -Workbit NinjaSCSI-32Bi/UDE support -CONFIG_SCSI_NSP32 - This is support for the Workbit NinjaSCSI-32Bi/UDE PCI/Cardbus - SCSI host adapter. Please read the SCSI-HOWTO, available from - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called nsp32.o. - -IBMMCA SCSI support -CONFIG_SCSI_IBMMCA - This is support for the IBM SCSI adapter found in many of the PS/2 - series computers. These machines have an MCA bus, so you need to - answer Y to "MCA support" as well and read - . - - If the adapter isn't found during boot (a common problem for models - 56, 57, 76, and 77) you'll need to use the 'ibmmcascsi=' kernel - option, where is the id of the SCSI subsystem (usually 7, but - if that doesn't work check your reference diskette). Owners of - model 95 with a LED-matrix-display can in addition activate some - activity info like under OS/2, but more informative, by setting - 'ibmmcascsi=display' as an additional kernel parameter. Try "man - bootparam" or see the documentation of your boot loader about how to - pass options to the kernel. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ibmmca.o. - -Standard SCSI-order -CONFIG_IBMMCA_SCSI_ORDER_STANDARD - In the PC-world and in most modern SCSI-BIOS-setups, SCSI-hard disks - are assigned to the drive letters, starting with the lowest SCSI-id - (physical number -- pun) to be drive C:, as seen from DOS and - similar operating systems. When looking into papers describing the - ANSI-SCSI-standard, this assignment of drives appears to be wrong. - The SCSI-standard follows a hardware-hierarchy which says that id 7 - has the highest priority and id 0 the lowest. Therefore, the host - adapters are still today everywhere placed as SCSI-id 7 by default. - In the SCSI-standard, the drive letters express the priority of the - disk. C: should be the hard disk, or a partition on it, with the - highest priority. This must therefore be the disk with the highest - SCSI-id (e.g. 6) and not the one with the lowest! IBM-BIOS kept the - original definition of the SCSI-standard as also industrial- and - process-control-machines, like VME-CPUs running under realtime-OSes - (e.g. LynxOS, OS9) do. - - If you like to run Linux on your MCA-machine with the same - assignment of hard disks as seen from e.g. DOS or OS/2 on your - machine, which is in addition conformant to the SCSI-standard, you - must say Y here. This is also necessary for MCA-Linux users who want - to keep downward compatibility to older releases of the - IBM-MCA-SCSI-driver (older than driver-release 2.00 and older than - June 1997). - - If you like to have the lowest SCSI-id assigned as drive C:, as - modern SCSI-BIOSes do, which does not conform to the standard, but - is widespread and common in the PC-world of today, you must say N - here. If unsure, say Y. - -Reset SCSI-devices at boot time -CONFIG_IBMMCA_SCSI_DEV_RESET - By default, SCSI-devices are reset when the machine is powered on. - However, some devices exist, like special-control-devices, - SCSI-CNC-machines, SCSI-printer or scanners of older type, that do - not reset when switched on. If you say Y here, each device connected - to your SCSI-bus will be issued a reset-command after it has been - probed, while the kernel is booting. This may cause problems with - more modern devices, like hard disks, which do not appreciate these - reset commands, and can cause your system to hang. So say Y only if - you know that one of your older devices needs it; N is the safe - answer. - -NCR MCA 53C9x SCSI support -CONFIG_SCSI_MCA_53C9X - Some MicroChannel machines, notably the NCR 35xx line, use a SCSI - controller based on the NCR 53C94. This driver will allow use of - the controller on the 3550, and very possibly others. - - If you want to compile this as a module (= code which can be - inserted and removed from the running kernel whenever you want), say - M here and read . The module will - be called mca_53c9x.o. - -Always IN2000 SCSI support -CONFIG_SCSI_IN2000 - This is support for an ISA bus SCSI host adapter. You'll find more - information in . If it doesn't work - out of the box, you may have to change the jumpers for IRQ or - address selection. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called in2000.o. - -Initio 91XXU(W) SCSI support -CONFIG_SCSI_INITIO - This is support for the Initio 91XXU(W) SCSI host adapter. Please - read the SCSI-HOWTO, available from - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called initio.o. - -PAS16 SCSI support -CONFIG_SCSI_PAS16 - This is support for a SCSI host adapter. It is explained in section - 3.10 of the SCSI-HOWTO, available from - . If it doesn't work out - of the box, you may have to change some settings in - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called pas16.o. If you want to compile it as a - module, say M here and read . - -Initio INI-A100U2W SCSI support -CONFIG_SCSI_INIA100 - This is support for the Initio INI-A100U2W SCSI host adapter. - Please read the SCSI-HOWTO, available from - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called a100u2w.o. - -PCI2000 support -CONFIG_SCSI_PCI2000 - This is support for the PCI2000I EIDE interface card which acts as a - SCSI host adapter. Please read the SCSI-HOWTO, available from - . - - This driver is also available as a module called pci2000.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -PCI2220i support -CONFIG_SCSI_PCI2220I - This is support for the PCI2220i EIDE interface card which acts as a - SCSI host adapter. Please read the SCSI-HOWTO, available from - . - - This driver is also available as a module called pci2220i.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -PSI240i support -CONFIG_SCSI_PSI240I - This is support for the PSI240i EIDE interface card which acts as a - SCSI host adapter. Please read the SCSI-HOWTO, available from - . - - This driver is also available as a module called psi240i.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Qlogic FAS SCSI support -CONFIG_SCSI_QLOGIC_FAS - This is a driver for the ISA, VLB, and PCMCIA versions of the Qlogic - FastSCSI! cards as well as any other card based on the FASXX chip - (including the Control Concepts SCSI/IDE/SIO/PIO/FDC cards). - - This driver does NOT support the PCI versions of these cards. The - PCI versions are supported by the Qlogic ISP driver ("Qlogic ISP - SCSI support"), below. - - Information about this driver is contained in - . You should also read the - SCSI-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called qlogicfas.o. If you want to compile it as - a module, say M here and read . - -Qlogic ISP SCSI support -CONFIG_SCSI_QLOGIC_ISP - This driver works for all QLogic PCI SCSI host adapters (IQ-PCI, - IQ-PCI-10, IQ_PCI-D) except for the PCI-basic card. (This latter - card is supported by the "AM53/79C974 PCI SCSI" driver.) - - If you say Y here, make sure to choose "BIOS" at the question "PCI - access mode". - - Please read the file . You - should also read the SCSI-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called qlogicisp.o. If you want to compile it as - a module, say M here and read . - -Qlogic ISP FC SCSI support -CONFIG_SCSI_QLOGIC_FC - This is a driver for the QLogic ISP2100 SCSI-FCP host adapter. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called qlogicfc.o. If you want to compile it as - a module, say M here and read . - -Include loadable firmware in driver -CONFIG_SCSI_QLOGIC_FC_FIRMWARE - Say Y to include ISP2100 Fabric Initiator/Target Firmware, with - expanded LUN addressing and FcTape (FCP-2) support, in the - Qlogic QLA 1280 driver. This is required on some platforms. - -Qlogic QLA 1280 SCSI support -CONFIG_SCSI_QLOGIC_1280 - Say Y if you have a QLogic ISP1x80/1x160 SCSI host adapter. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called qla1280.o. If you want to compile it as - a module, say M here and read . - -Seagate ST-02 and Future Domain TMC-8xx SCSI support -CONFIG_SCSI_SEAGATE - These are 8-bit SCSI controllers; the ST-01 is also supported by - this driver. It is explained in section 3.9 of the SCSI-HOWTO, - available from . If it - doesn't work out of the box, you may have to change some settings in - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called seagate.o. If you want to compile it as a - module, say M here and read . - -Trantor T128/T128F/T228 SCSI support -CONFIG_SCSI_T128 - This is support for a SCSI host adapter. It is explained in section - 3.11 of the SCSI-HOWTO, available from - . If it doesn't work out - of the box, you may have to change some settings in - . Note that Trantor was purchased by - Adaptec, and some former Trantor products are being sold under the - Adaptec name. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called t128.o. If you want to compile it as a - module, say M here and read . - -UltraStor SCSI support -CONFIG_SCSI_ULTRASTOR - This is support for the UltraStor 14F, 24F and 34F SCSI-2 host - adapter family. This driver is explained in section 3.12 of the - SCSI-HOWTO, available from - . If it doesn't work out - of the box, you may have to change some settings in - . - - Note that there is also another driver for the same hardware: - "UltraStor 14F/34F support", above. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ultrastor.o. - -7000FASST SCSI support -CONFIG_SCSI_7000FASST - This driver supports the Western Digital 7000 SCSI host adapter - family. Some information is in the source: - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called wd7000.o. If you want to compile it as a - module, say M here and read . - -ACARD SCSI support -CONFIG_SCSI_ACARD - This driver supports the ACARD 870U/W SCSI host adapter. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called atp870u.o. If you want to compile it as a - module, say M here and read . - -EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support -CONFIG_SCSI_EATA - This driver supports all EATA/DMA-compliant SCSI host adapters. DPT - ISA and all EISA I/O addresses are probed looking for the "EATA" - signature. If you chose "BIOS" at the question "PCI access mode", - the addresses of all the PCI SCSI controllers reported by the PCI - subsystem are probed as well. - - You want to read the start of and the - SCSI-HOWTO, available from - . - - Note that there is also another driver for the same hardware - available: "EATA-DMA [Obsolete] (DPT, NEC, AT&T, SNI, AST, Olivetti, - Alphatronix) support". You should say Y to only one of them. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called eata.o. - -enable tagged command queueing -CONFIG_SCSI_EATA_TAGGED_QUEUE - This is a feature of SCSI-2 which improves performance: the host - adapter can send several SCSI commands to a device's queue even if - previous commands haven't finished yet. Most EATA adapters negotiate - this feature automatically with the device, even if your answer is - N. The safe answer is N. - -enable elevator sorting -CONFIG_SCSI_EATA_LINKED_COMMANDS - This option enables elevator sorting for all probed SCSI disks and - CD-ROMs. It definitely reduces the average seek distance when doing - random seeks, but this does not necessarily result in a noticeable - performance improvement: your mileage may vary... - The safe answer is N. - -maximum number of queued commands -CONFIG_SCSI_EATA_MAX_TAGS - This specifies how many SCSI commands can be maximally queued for - each probed SCSI device. You should reduce the default value of 16 - only if you have disks with buggy or limited tagged command support. - Minimum is 2 and maximum is 62. This value is also the window size - used by the elevator sorting option above. The effective value used - by the driver for each probed SCSI device is reported at boot time. - -NCR53c406a SCSI support -CONFIG_SCSI_NCR53C406A - This is support for the NCR53c406a SCSI host adapter. For user - configurable parameters, check out - in the kernel source. Also read the SCSI-HOWTO, available from - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called NCR53c406.o. - -Symbios 53c416 SCSI support -CONFIG_SCSI_SYM53C416 - This is support for the sym53c416 SCSI host adapter, the SCSI - adapter that comes with some HP scanners. This driver requires that - the sym53c416 is configured first using some sort of PnP - configuration program (e.g. isapnp) or by a PnP aware BIOS. If you - are using isapnp then you need to compile this driver as a module - and then load it using insmod after isapnp has run. The parameters - of the configured card(s) should be passed to the driver. The format - is: - - insmod sym53c416 sym53c416=, [sym53c416_1=,] - - There is support for up to four adapters. If you want to compile - this driver as a module ( = code which can be inserted in and - removed from the running kernel whenever you want), say M here and - read . The module will be called - sym53c416.o. - -Simple 53c710 SCSI support (Compaq, NCR machines) -CONFIG_SCSI_SIM710 - This is a simple driver for NCR53c710 based SCSI host adapters. - - More complex drivers for this chip are available ("NCR53c7,8xx SCSI - support", above), but they require that the scsi chip be able to do - DMA block moves between memory and on-chip registers, which can - cause problems under certain conditions. This driver is designed to - avoid these problems and is intended to work with any Intel machines - using 53c710 chips, including various Compaq and NCR machines. - - Please read the comments at the top of the file - for more information. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called sim710.o. - -Tekram DC390(T) and Am53/79C974 SCSI support -CONFIG_SCSI_DC390T - This driver supports PCI SCSI host adapters based on the Am53C974A - chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard - PCscsi/PCnet (Am53/79C974) solutions. - - Documentation can be found in . - - Note that this driver does NOT support Tekram DC390W/U/F, which are - based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those. - Also note that there is another generic Am53C974 driver, - "AM53/79C974 PCI SCSI support" below. You can pick either one. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called tmscsim.o. - -Omit support for other Am53/79C974 based SCSI adapters -CONFIG_SCSI_DC390T_NOGENSUPP - If you say N here, the DC390(T) SCSI driver relies on the DC390 - EEPROM to get initial values for its settings, such as speed, - termination, etc. If it can't find this EEPROM, it will use - defaults or the user supplied boot/module parameters. For details - on driver configuration see . - - If you say Y here and if no EEPROM is found, the driver gives up and - thus only supports Tekram DC390(T) adapters. This can be useful if - you have a DC390(T) and another Am53C974 based adapter, which, for - some reason, you want to drive with the other AM53C974 driver. - - If unsure, say N. - -AM53/79C974 PCI SCSI support -CONFIG_SCSI_AM53C974 - This is support for the AM53/79C974 SCSI host adapters. Please read - for details. Also, the - SCSI-HOWTO, available from - , is for you. - - Note that there is another driver for AM53C974 based adapters: - "Tekram DC390(T) and Am53/79C974 (PCscsi) SCSI support", above. You - can pick either one. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called AM53C974.o. - -AMI MegaRAID support (old driver) -CONFIG_SCSI_MEGARAID - This driver supports the AMI MegaRAID 418, 428, 438, 466, 762, 490, - 467, 471 and 493 SCSI host adapters. - - This is the old and very heavily tested driver but lacks features - like clustering. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called megaraid.o. - -AMI MegaRAID support (new driver) -CONFIG_SCSI_MEGARAID2 - This driver supports the AMI MegaRAID 418, 428, 438, 466, 762, 490, - 467, 471, 493 and new Ultra320(518, 520, 531, 532) SCSI host adapters. - - This is the newer less tested but more featureful driver. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called megaraid2.o. - -Intel/ICP (former GDT SCSI Disk Array) RAID Controller support -CONFIG_SCSI_GDTH - Formerly called GDT SCSI Disk Array Controller Support. - - This is a driver for RAID/SCSI Disk Array Controllers (EISA/ISA/PCI) - manufactured by Intel/ICP vortex (an Intel Company). It is documented - in the kernel source in and - - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called gdth.o. - -IOMEGA parallel port (ppa - older drives) -CONFIG_SCSI_PPA - This driver supports older versions of IOMEGA's parallel port ZIP - drive (a 100 MB removable media device). - - Note that you can say N here if you have the SCSI version of the ZIP - drive: it will be supported automatically if you said Y to the - generic "SCSI disk support", above. - - If you have the ZIP Plus drive or a more recent parallel port ZIP - drive (if the supplied cable with the drive is labeled "AutoDetect") - then you should say N here and Y to "IOMEGA parallel port (imm - - newer drives)", below. - - For more information about this driver and how to use it you should - read the file . You should also read - the SCSI-HOWTO, which is available from - . If you use this driver, - you will still be able to use the parallel port for other tasks, - such as a printer; it is safe to compile both drivers into the - kernel. - - This driver is also available as a module which can be inserted in - and removed from the running kernel whenever you want. To compile - this driver as a module, say M here and read - . The module will be called ppa.o. - -IOMEGA parallel port (imm - newer drives) -CONFIG_SCSI_IMM - This driver supports newer versions of IOMEGA's parallel port ZIP - drive (a 100 MB removable media device). - - Note that you can say N here if you have the SCSI version of the ZIP - drive: it will be supported automatically if you said Y to the - generic "SCSI disk support", above. - - If you have the ZIP Plus drive or a more recent parallel port ZIP - drive (if the supplied cable with the drive is labeled "AutoDetect") - then you should say Y here; if you have an older ZIP drive, say N - here and Y to "IOMEGA Parallel Port (ppa - older drives)", above. - - For more information about this driver and how to use it you should - read the file . You should also read - the SCSI-HOWTO, which is available from - . If you use this driver, - you will still be able to use the parallel port for other tasks, - such as a printer; it is safe to compile both drivers into the - kernel. - - This driver is also available as a module which can be inserted in - and removed from the running kernel whenever you want. To compile - this driver as a module, say M here and read - . The module will be called imm.o. - -Force the Iomega ZIP drivers to use EPP-16 -CONFIG_SCSI_IZIP_EPP16 - EPP (Enhanced Parallel Port) is a standard for parallel ports which - allows them to act as expansion buses that can handle up to 64 - peripheral devices. - - Some parallel port chipsets are slower than their motherboard, and - so we have to control the state of the chipset's FIFO queue every - now and then to avoid data loss. This will be done if you say Y - here. - - Generally, saying Y is the safe option and slows things down a bit. - -Assume slow parallel port control register -CONFIG_SCSI_IZIP_SLOW_CTR - Some parallel ports are known to have excessive delays between - changing the parallel port control register and good data being - available on the parallel port data/status register. This option - forces a small delay (1.0 usec to be exact) after changing the - control register to let things settle out. Enabling this option may - result in a big drop in performance but some very old parallel ports - (found in 386 vintage machines) will not work properly. - - Generally, saying N is fine. - -SCSI debugging host simulator -CONFIG_SCSI_DEBUG - This is a host adapter simulator that can be programmed to simulate - a large number of conditions that could occur on a real bus. The - advantage is that many hard to reproduce problems can be tested in a - controlled environment where there is reduced risk of losing - important data. This is primarily of use to people trying to debug - the middle and upper layers of the SCSI subsystem. If unsure, say N. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called scsi_debug.o. - -Fibre Channel and FC4 SCSI support -CONFIG_FC4 - Fibre Channel is a high speed serial protocol mainly used to - connect large storage devices to the computer; it is compatible with - and intended to replace SCSI. - - This is an experimental support for storage arrays connected to your - computer using optical fibre cables and the "X3.269-199X Fibre - Channel Protocol for SCSI" specification. If you want to use this, - you need to say Y here and to "SCSI support" as well as to the - drivers for the storage array itself and for the interface adapter - such as SOC or SOC+. This subsystem could even serve for IP - networking, with some code extensions. - - If unsure, say N. - -Sun SOC/Sbus -CONFIG_FC4_SOC - Serial Optical Channel is an interface card with one or two Fibre - Optic ports, each of which can be connected to a disk array. Note - that if you have older firmware in the card, you'll need the - microcode from the Solaris driver to make it work. - - This support is also available as a module called soc.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Sun SOC+ (aka SOCAL) -CONFIG_FC4_SOCAL - Serial Optical Channel Plus is an interface card with up to two - Fibre Optic ports. This card supports FC Arbitrated Loop (usually - A5000 or internal FC disks in E[3-6]000 machines through the - Interface Board). You'll probably need the microcode from the - Solaris driver to make it work. - - This support is also available as a module called socal.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -SparcSTORAGE Array 100 and 200 series -CONFIG_SCSI_PLUTO - If you never bought a disk array made by Sun, go with N. - - This support is also available as a module called pluto.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Sun Enterprise Network Array (A5000 and EX500) -CONFIG_SCSI_FCAL - This driver drives FC-AL disks connected through a Fibre Channel - card using the drivers/fc4 layer (currently only SOCAL). The most - common is either A5000 array or internal disks in E[3-6]000 - machines. - - This support is also available as a module called fcal.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . If unsure, say N. - -Acorn SCSI card (aka30) support -CONFIG_SCSI_ACORNSCSI_3 - This enables support for the Acorn SCSI card (aka30). If you have an - Acorn system with one of these, say Y. If unsure, say N. - -Support SCSI 2 Tagged queueing -CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE - Say Y here to enable tagged queuing support on the Acorn SCSI card. - - This is a feature of SCSI-2 which improves performance: the host - adapter can send several SCSI commands to a device's queue even if - previous commands haven't finished yet. Some SCSI devices don't - implement this properly, so the safe answer is N. - -Support SCSI 2 Synchronous Transfers -CONFIG_SCSI_ACORNSCSI_SYNC - Say Y here to enable synchronous transfer negotiation with all - targets on the Acorn SCSI card. - - In general, this improves performance; however some SCSI devices - don't implement it properly, so the safe answer is N. - -ARXE SCSI support -CONFIG_SCSI_ARXESCSI - Around 1991, Arxe Systems Limited released a high density floppy - disc interface for the Acorn Archimedes range, to allow the use of - HD discs from the then new A5000 on earlier models. This interface - was either sold on its own or with an integral SCSI controller. - Technical details on this NCR53c94-based device are available at - - Say Y here to compile in support for the SCSI controller. - -Oak SCSI support -CONFIG_SCSI_OAK1 - This enables support for the Oak SCSI card. If you have an Acorn - system with one of these, say Y. If unsure, say N. - -Cumana SCSI I support -CONFIG_SCSI_CUMANA_1 - This enables support for the Cumana SCSI I card. If you have an - Acorn system with one of these, say Y. If unsure, say N. - -Cumana SCSI II support -CONFIG_SCSI_CUMANA_2 - This enables support for the Cumana SCSI II card. If you have an - Acorn system with one of these, say Y. If unsure, say N. - -EcoSCSI support -CONFIG_SCSI_ECOSCSI - This enables support for the EcoSCSI card -- a small card that sits - in the Econet socket. If you have an Acorn system with one of these, - say Y. If unsure, say N. - -EESOX SCSI support -CONFIG_SCSI_EESOXSCSI - This enables support for the EESOX SCSI card. If you have an Acorn - system with one of these, say Y, otherwise say N. - -PowerTec SCSI support -CONFIG_SCSI_POWERTECSCSI - This enables support for the Powertec SCSI card on Acorn systems. If - you have one of these, say Y. If unsure, say N. - -IEEE 1394 (FireWire) support -CONFIG_IEEE1394 - IEEE 1394 describes a high performance serial bus, which is also - known as FireWire(tm) or i.Link(tm) and is used for connecting all - sorts of devices (most notably digital video cameras) to your - computer. - - If you have FireWire hardware and want to use it, say Y here. This - is the core support only, you will also need to select a driver for - your IEEE 1394 adapter. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ieee1394.o. - -Texas Instruments PCILynx support -CONFIG_IEEE1394_PCILYNX - Say Y here if you have an IEEE-1394 controller with the Texas - Instruments PCILynx chip. Note: this driver is written for revision - 2 of this chip and may not work with revision 0. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called pcilynx.o. - -Use local RAM on PCILynx board -CONFIG_IEEE1394_PCILYNX_LOCALRAM - This option makes the PCILynx driver use local RAM available on some - PCILynx setups for Packet Control Lists. Local RAM is random access - memory which resides on the PCILynx board as opposed to on your - computer's motherboard. Local RAM may speed up command processing - because no PCI transfers are necessary during use of the Packet - Control Lists. - - Note that there are no known PCILynx systems providing local RAM - except for the evaluation boards by Texas Instruments and that the - PCILynx does not reliably report missing RAM. This means that it is - dangerous to say Y here if you are not absolutely sure that your - board provides 64KB of local RAM. - - If unsure, say N. - -Support for non-IEEE1394 local ports -CONFIG_IEEE1394_PCILYNX_PORTS - This option enables driver code to access the RAM, ROM and AUX ports - of the PCILynx through character devices in /dev. If you don't know - what this is about then you won't need it. - - If unsure, say N. - -#Adaptec AIC-5800 IEEE 1394 support -#CONFIG_IEEE1394_AIC5800 -# Say Y here if you have a IEEE 1394 controller using the Adaptec -# AIC-5800 chip. All Adaptec host adapters (89xx series) use this -# chip, as well as miro's DV boards. -# -# If you want to compile this as a module ( = code which can be -# inserted in and removed from the running kernel whenever you want), -# say M here and read . The module -# will be called aic5800.o. -# -OHCI-1394 (Open Host Controller Interface) support -CONFIG_IEEE1394_OHCI1394 - Enable this driver if you have an IEEE 1394 controller based on the - OHCI-1394 specification. The current driver is only tested with OHCI - chipsets made by Texas Instruments and NEC. Most third-party vendors - use one of these chipsets. It should work with any OHCI-1394 - compliant card, however. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ohci1394.o. - -OHCI-1394 Video support -CONFIG_IEEE1394_VIDEO1394 - This option enables video device usage for OHCI-1394 cards. Enable - this option only if you have an IEEE 1394 video device connected to - an OHCI-1394 card. - -SBP-2 support (Harddisks etc.) -CONFIG_IEEE1394_SBP2 - This option enables you to use SBP-2 devices connected to your IEEE - 1394 bus. SBP-2 devices include harddrives and DVD devices. - -Raw IEEE 1394 I/O support -CONFIG_IEEE1394_RAWIO - Say Y here if you want support for the raw device. This is generally - a good idea, so you should say Y here. The raw device enables - direct communication of user programs with the IEEE 1394 bus and - thus with the attached peripherals. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called raw1394.o. - -Excessive debugging output -CONFIG_IEEE1394_VERBOSEDEBUG - If you say Y here, you will get very verbose debugging logs from the - subsystem which includes a dump of the header of every sent and - received packet. This can amount to a high amount of data collected - in a very short time which is usually also saved to disk by the - system logging daemons. - - Say Y if you really want or need the debugging output, everyone else - says N. - -CONFIG_IEEE1394_OUI_DB - If you say Y here, then an OUI list (vendor unique ID's) will be - compiled into the ieee1394 module. This doesn't really do much - except being able to display the vendor of a hardware node. The - downside is that it adds about 300k to the size of the module, - or kernel (depending on whether you compile ieee1394 as a - module, or static in the kernel). - - This option is not needed for userspace programs like gscanbus - to show this information. - -Network device support -CONFIG_NETDEVICES - You can say N here if you don't intend to connect your Linux box to - any other computer at all or if all your connections will be over a - telephone line with a modem either via UUCP (UUCP is a protocol to - forward mail and news between unix hosts over telephone lines; read - the UUCP-HOWTO, available from - ) or dialing up a shell - account or a BBS, even using term (term is a program which gives you - almost full Internet connectivity if you have a regular dial up - shell account on some Internet connected Unix computer. Read - ). - - You'll have to say Y if your computer contains a network card that - you want to use under Linux (make sure you know its name because you - will be asked for it and read the Ethernet-HOWTO (especially if you - plan to use more than one network card under Linux)) or if you want - to use SLIP (Serial Line Internet Protocol is the protocol used to - send Internet traffic over telephone lines or null modem cables) or - CSLIP (compressed SLIP) or PPP (Point to Point Protocol, a better - and newer replacement for SLIP) or PLIP (Parallel Line Internet - Protocol is mainly used to create a mini network by connecting the - parallel ports of two local machines) or AX.25/KISS (protocol for - sending Internet traffic over amateur radio links). - - Make sure to read the NET-3-HOWTO. Eventually, you will have to read - Olaf Kirch's excellent and free book "Network Administrator's - Guide", to be found in . If - unsure, say Y. - -Dummy net driver support -CONFIG_DUMMY - This is essentially a bit-bucket device (i.e. traffic you send to - this device is consigned into oblivion) with a configurable IP - address. It is most commonly used in order to make your currently - inactive SLIP address seem like a real address for local programs. - If you use SLIP or PPP, you might want to say Y here. Since this - thing often comes in handy, the default is Y. It won't enlarge your - kernel either. What a deal. Read about it in the Network - Administrator's Guide, available from - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called dummy.o. If you want to use more than one dummy - device at a time, you need to compile this driver as a module. - Instead of 'dummy', the devices will then be called 'dummy0', - 'dummy1' etc. - -Bonding driver support -CONFIG_BONDING - Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet - Channels together. This is called 'Etherchannel' by Cisco, - 'Trunking' by Sun, and 'Bonding' in Linux. - - If you have two Ethernet connections to some other computer, you can - make them behave like one double speed connection using this driver. - Naturally, this has to be supported at the other end as well, either - with a similar Bonding Linux driver, a Cisco 5500 switch or a - SunTrunking SunSoft driver. - - This is similar to the EQL driver, but it merges Ethernet segments - instead of serial lines. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called bonding.o. - -SLIP (serial line) support -CONFIG_SLIP - Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to - connect to your Internet service provider or to connect to some - other local Unix box or if you want to configure your Linux box as a - Slip/CSlip server for other people to dial in. SLIP (Serial Line - Internet Protocol) is a protocol used to send Internet traffic over - serial connections such as telephone lines or null modem cables; - nowadays, the protocol PPP is more commonly used for this same - purpose. - - Normally, your access provider has to support SLIP in order for you - to be able to use it, but there is now a SLIP emulator called SLiRP - around (available from - ) which - allows you to use SLIP over a regular dial up shell connection. If - you plan to use SLiRP, make sure to say Y to CSLIP, below. The - NET-3-HOWTO, available from - , explains how to - configure SLIP. Note that you don't need this option if you just - want to run term (term is a program which gives you almost full - Internet connectivity if you have a regular dial up shell account on - some Internet connected Unix computer. Read - ). SLIP - support will enlarge your kernel by about 4 KB. If unsure, say N. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read as well as - . The module will be - called slip.o. - -CSLIP compressed headers -CONFIG_SLIP_COMPRESSED - This protocol is faster than SLIP because it uses compression on the - TCP/IP headers (not on the data itself), but it has to be supported - on both ends. Ask your access provider if you are not sure and - answer Y, just in case. You will still be able to use plain SLIP. If - you plan to use SLiRP, the SLIP emulator (available from - ) which - allows you to use SLIP over a regular dial up shell connection, you - definitely want to say Y here. The NET-3-HOWTO, available from - , explains how to configure - CSLIP. This won't enlarge your kernel. - -Keepalive and linefill -CONFIG_SLIP_SMART - Adds additional capabilities to the SLIP driver to support the - RELCOM line fill and keepalive monitoring. Ideal on poor quality - analogue lines. - -Six bit SLIP encapsulation -CONFIG_SLIP_MODE_SLIP6 - Just occasionally you may need to run IP over hostile serial - networks that don't pass all control characters or are only seven - bit. Saying Y here adds an extra mode you can use with SLIP: - "slip6". In this mode, SLIP will only send normal ASCII symbols over - the serial device. Naturally, this has to be supported at the other - end of the link as well. It's good enough, for example, to run IP - over the async ports of a Camtec JNT Pad. If unsure, say N. - -PPP (point-to-point protocol) support -CONFIG_PPP - PPP (Point to Point Protocol) is a newer and better SLIP. It serves - the same purpose: sending Internet traffic over telephone (and other - serial) lines. Ask your access provider if they support it, because - otherwise you can't use it; most Internet access providers these - days support PPP rather than SLIP. - - To use PPP, you need an additional program called pppd as described - in the PPP-HOWTO, available at - . Make sure that you have - the version of pppd recommended in . - The PPP option enlarges your kernel by about 16 KB. - - There are actually two versions of PPP: the traditional PPP for - asynchronous lines, such as regular analog phone lines, and - synchronous PPP which can be used over digital ISDN lines for - example. If you want to use PPP over phone lines or other - asynchronous serial lines, you need to say Y (or M) here and also to - the next option, "PPP support for async serial ports". For PPP over - synchronous lines, you should say Y (or M) here and to "Support - synchronous PPP", below. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you said Y to "Version information on all symbols" above, then - you cannot compile the PPP driver into the kernel; you can then only - compile it as a module. The module will be called ppp_generic.o. - If you want to compile it as a module, say M here and read - as well as - . - -PPP multilink support -CONFIG_PPP_MULTILINK - PPP multilink is a protocol (defined in RFC 1990) which allows you - to combine several (logical or physical) lines into one logical PPP - connection, so that you can utilize your full bandwidth. - - This has to be supported at the other end as well and you need a - version of the pppd daemon which understands the multilink protocol. - - If unsure, say N. - -PPP filtering -CONFIG_PPP_FILTER - Say Y here if you want to be able to filter the packets passing over - PPP interfaces. This allows you to control which packets count as - activity (i.e. which packets will reset the idle timer or bring up - a demand-dialled link) and which packets are to be dropped entirely. - You need to say Y here if you wish to use the pass-filter and - active-filter options to pppd. - - If unsure, say N. - -PPP support for async serial ports -CONFIG_PPP_ASYNC - Say Y (or M) here if you want to be able to use PPP over standard - asynchronous serial ports, such as COM1 or COM2 on a PC. If you use - a modem (not a synchronous or ISDN modem) to contact your ISP, you - need this option. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ppp_async.o. - - If unsure, say Y. - -PPP support for sync tty ports -CONFIG_PPP_SYNC_TTY - Say Y (or M) here if you want to be able to use PPP over synchronous - (HDLC) tty devices, such as the SyncLink adapter. These devices - are often used for high-speed leased lines like T1/E1. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ppp_synctty.o. - -PPP Deflate compression -CONFIG_PPP_DEFLATE - Support for the Deflate compression method for PPP, which uses the - Deflate algorithm (the same algorithm that gzip uses) to compress - each PPP packet before it is sent over the wire. The machine at the - other end of the PPP link (usually your ISP) has to support the - Deflate compression method as well for this to be useful. Even if - they don't support it, it is safe to say Y here. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ppp_deflate.o. - -PPP BSD-Compress compression -CONFIG_PPP_BSDCOMP - Support for the BSD-Compress compression method for PPP, which uses - the LZW compression method to compress each PPP packet before it is - sent over the wire. The machine at the other end of the PPP link - (usually your ISP) has to support the BSD-Compress compression - method as well for this to be useful. Even if they don't support it, - it is safe to say Y here. - - The PPP Deflate compression method ("PPP Deflate compression", - above) is preferable to BSD-Compress, because it compresses better - and is patent-free. - - Note that the BSD compression code will always be compiled as a - module; it is called bsd_comp.o and will show up in the directory - modules once you have said "make modules". If unsure, say N. - -PPP over Ethernet -CONFIG_PPPOE - Support for PPP over Ethernet. - - This driver requires the current pppd from the "ppp" CVS repository - on cvs.samba.org. The required support will be present in the next - ppp release (2.4.2). - -Wireless LAN (non-hamradio) -CONFIG_NET_RADIO - Support for wireless LANs and everything having to do with radio, - but not with amateur radio or FM broadcasting. - - Saying Y here also enables the Wireless Extensions (creates - /proc/net/wireless and enables ifconfig access). The Wireless - Extension is a generic API allowing a driver to expose to the user - space configuration and statistics specific to common Wireless LANs. - The beauty of it is that a single set of tool can support all the - variations of Wireless LANs, regardless of their type (as long as - the driver supports Wireless Extension). Another advantage is that - these parameters may be changed on the fly without restarting the - driver (or Linux). If you wish to use Wireless Extensions with - wireless PCMCIA (PC-) cards, you need to say Y here; you can fetch - the tools from - . - - Some user-level drivers for scarab devices which don't require - special kernel support are available from - . - -STRIP (Metricom Starmode radio IP) -CONFIG_STRIP - Say Y if you have a Metricom radio and intend to use Starmode Radio - IP. STRIP is a radio protocol developed for the MosquitoNet project - (on the WWW at ) to send Internet - traffic using Metricom radios. Metricom radios are small, battery - powered, 100kbit/sec packet radio transceivers, about the size and - weight of a cellular telephone. (You may also have heard them called - "Metricom modems" but we avoid the term "modem" because it misleads - many people into thinking that you can plug a Metricom modem into a - phone line and use it as a modem.) - - You can use STRIP on any Linux machine with a serial port, although - it is obviously most useful for people with laptop computers. If you - think you might get a Metricom radio in the future, there is no harm - in saying Y to STRIP now, except that it makes the kernel a bit - bigger. - - You can also compile this as a module ( = code which can be inserted - in and removed from the running kernel whenever you want), say M - here and read . The module will be - called strip.o. - -AT&T WaveLAN & DEC RoamAbout DS support -CONFIG_WAVELAN - The Lucent WaveLAN (formerly NCR and AT&T; or DEC RoamAbout DS) is - a Radio LAN (wireless Ethernet-like Local Area Network) using the - radio frequencies 900 MHz and 2.4 GHz. - - This driver support the ISA version of the WaveLAN card. A separate - driver for the PCMCIA (PC-card) hardware is available in David - Hinds' pcmcia-cs package (see the file - for location). - - If you want to use an ISA WaveLAN card under Linux, say Y and read - the Ethernet-HOWTO, available from - . Some more specific - information is contained in - and in the source code - . - - You will also need the wireless tools package available from - . - Please read the man pages contained therein. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called wavelan.o. If you want to compile it as a - module, say M here and read as well - as . - -Aironet Arlan 655 & IC2200 DS support -CONFIG_ARLAN - Aironet makes Arlan, a class of wireless LAN adapters. These use the - www.Telxon.com chip, which is also used on several similar cards. - This driver is tested on the 655 and IC2200 series cards. Look at - for the latest information. - - The driver is built as two modules, arlan and arlan-proc. The latter - is the /proc interface and is not needed most of time. - - On some computers the card ends up in non-valid state after some - time. Use a ping-reset script to clear it. - -Aironet 4500/4800 series adapters -CONFIG_AIRONET4500 - www.aironet.com (recently bought by Cisco) makes these 802.11 DS - adapters. Driver by Elmer Joandi (elmer@ylenurme.ee). - - Say Y here if you have such an adapter, and then say Y below to - the option that applies to your particular type of card (PCI, ISA, - or PCMCIA). - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called aironet4500_core.o. If you want to - compile it as a module, say M here and read - as well as - . - - quick config parameters: - SSID=tsunami - "The Password" - adhoc=1 there are no Access Points around - master=1 Adhoc master (the one who creates network - sync) - slave=1 Adhoc slave (btw, it is still forming own net - sometimes, and has problems with firmware... - change IbssJoinNetTimeout from /proc...) - channel=1..? meaningful in adhoc mode - - If you have problems with screwing up card, both_bap_lock=1 is a - conservative value (performance hit 15%). - - All other parameters can be set via the proc interface. - -Aironet 4500/4800 ISA/PCI/PNP/365 support -CONFIG_AIRONET4500_NONCS - If you have an ISA, PCI or PCMCIA Aironet 4500/4800 wireless LAN - card, say Y here, and then also to the options below that apply - to you. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called aironet4500_card.o. If you want to - compile it as a module, say M here and read - . - -Aironet 4500/4800 PNP support -CONFIG_AIRONET4500_PNP - If you have an ISA Aironet 4500/4800 card which you want to use in - PnP (Plug and Play) mode, say Y here. This is the recommended mode - for ISA cards. Remember however to enable the PnP jumper on the - board if you say Y here. - -Aironet 4500/4800 PCI support -CONFIG_AIRONET4500_PCI - If you have an PCI Aironet 4500/4800 card, say Y here. - -Aironet 4500/4800 ISA broken support -CONFIG_AIRONET4500_ISA - If you have an ISA Aironet 4500/4800 card which you want to run in - non-PnP mode, say Y here. This is not recommended and does not work - correctly at this point. Say N. - -Aironet 4500/4800 I365 broken support -CONFIG_AIRONET4500_I365 - If you have a PCMCIA Aironet 4500/4800 card which you want to use - without the standard PCMCIA cardservices provided by the pcmcia-cs - package, say Y here. This is not recommended, so say N. - -Aironet 4500/4800 PCMCIA support -CONFIG_AIRONET4500_CS - Say Y here if you have a PCMCIA Aironet 4500/4800 card which you - want to use with the standard PCMCIA cardservices provided by the - pcmcia-cs package. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called aironet4500_cs.o. If you want to - compile it as a module, say M here and read - . - -Aironet 4500/4800 PROC interface -CONFIG_AIRONET4500_PROC - If you say Y here (and to the "/proc file system" below), you will - be able to configure your Aironet card via the - /proc/sys/aironet4500 interface. - - Additional info: look in . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called aironet4500_proc.o. If you want to - compile it as a module, say M here and read - . - - NOTE: the proc interface uses a lot of memory, so it is recommended - to compile it as a module and remove the module after - configuration. - -LAPB over Ethernet driver -CONFIG_LAPBETHER - This is a driver for a pseudo device (typically called /dev/lapb0) - which allows you to open an LAPB point-to-point connection to some - other computer on your Ethernet network. In order to do this, you - need to say Y or M to the driver for your Ethernet card as well as - to "LAPB Data Link Driver". - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called lapbether.o. If unsure, say N. - -X.25 async driver -CONFIG_X25_ASY - This is a driver for sending and receiving X.25 frames over regular - asynchronous serial lines such as telephone lines equipped with - ordinary modems. Experts should note that this driver doesn't - currently comply with the asynchronous HDLS framing protocols in - CCITT recommendation X.25. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called x25_asy.o. If unsure, say N. - -PCMCIA network device support -CONFIG_NET_PCMCIA - Say Y if you would like to include support for any PCMCIA or CardBus - network adapters, then say Y to the driver for your particular card - below. PCMCIA- or PC-cards are credit-card size devices often used - with laptops computers; CardBus is the newer and faster version of - PCMCIA. - - To use your PC-cards, you will need supporting software from David - Hinds' pcmcia-cs package (see the file - for location). You also want to check out the PCMCIA-HOWTO, - available from . - - If unsure, say N. - -3Com 3c589 PCMCIA support -CONFIG_PCMCIA_3C589 - Say Y here if you intend to attach a 3Com 3c589 or compatible PCMCIA - (PC-card) Ethernet card to your computer. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called 3c589_cs.o. If you want to compile it as - a module, say M here and read . If - unsure, say N. - -3Com 3c574 PCMCIA support -CONFIG_PCMCIA_3C574 - Say Y here if you intend to attach a 3Com 3c574 or compatible PCMCIA - (PC-card) Fast Ethernet card to your computer. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called 3c574_cs.o. If you want to compile it as - a module, say M here and read . If - unsure, say N. - -Fujitsu FMV-J18x PCMCIA support -CONFIG_PCMCIA_FMVJ18X - Say Y here if you intend to attach a Fujitsu FMV-J18x or compatible - PCMCIA (PC-card) Ethernet card to your computer. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called fmvj18x_cs.o. If you want to compile it - as a module, say M here and read . - If unsure, say N. - -NE2000 compatible PCMCIA support -CONFIG_PCMCIA_PCNET - Say Y here if you intend to attach an NE2000 compatible PCMCIA - (PC-card) Ethernet or Fast Ethernet card to your computer. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called pcnet_cs.o. If you want to compile it as - a module, say M here and read . If - unsure, say N. - -Asix AX88190 PCMCIA support -CONFIG_PCMCIA_AXNET - Say Y here if you intend to attach an Asix AX88190-based PCMCIA - (PC-card) Fast Ethernet card to your computer. These cards are - nearly NE2000 compatible but need a separate driver due to a few - misfeatures. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called axnet_cs.o. If you want to compile it as - a module, say M here and read . If - unsure, say N. - -New Media PCMCIA support -CONFIG_PCMCIA_NMCLAN - Say Y here if you intend to attach a New Media Ethernet or LiveWire - PCMCIA (PC-card) Ethernet card to your computer. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called nmclan_cs.o. If you want to compile it as - a module, say M here and read . If - unsure, say N. - -SMC 91Cxx PCMCIA support -CONFIG_PCMCIA_SMC91C92 - Say Y here if you intend to attach an SMC 91Cxx compatible PCMCIA - (PC-card) Ethernet or Fast Ethernet card to your computer. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called smc91c92_cs.o. If you want to compile it - as a module, say M here and read . - If unsure, say N. - -Xircom 16-bit PCMCIA support -CONFIG_PCMCIA_XIRC2PS - Say Y here if you intend to attach a Xircom 16-bit PCMCIA (PC-card) - Ethernet or Fast Ethernet card to your computer. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called xirc2ps_cs.o. If you want to compile it - as a module, say M here and read . - If unsure, say N. - -COM20020 ARCnet PCMCIA support -CONFIG_ARCNET_COM20020_CS - Say Y here if you intend to attach this type of ARCnet PCMCIA card - to your computer. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called com20020_cs.o. If you want to compile it - as a module, say M here and read . - If unsure, say N. - -IBM PCMCIA Token Ring adapter support -CONFIG_PCMCIA_IBMTR - Say Y here if you intend to attach this type of Token Ring PCMCIA - card to your computer. You then also need to say Y to "Token Ring - driver support". - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ibmtr_cs.o. If you want to compile it as - a module, say M here and read . - -Xircom Tulip-like CardBus support (old driver) -CONFIG_PCMCIA_XIRTULIP - This driver is for the Digital "Tulip" Ethernet CardBus adapters. - It should work with most DEC 21*4*-based chips/ethercards, as well - as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and - ASIX. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called xircom_tulip_cb.o. If you want to compile - it as a module, say M here and read - . If unsure, say N. - -Xircom CardBus support (new driver) -CONFIG_PCMCIA_XIRCOM - This driver is for the Digital "Tulip" Ethernet CardBus adapters. - It should work with most DEC 21*4*-based chips/ethercards, as well - as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and - ASIX. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called xircom_cb.o. If you want to compile - it as a module, say M here and read - . If unsure, say N. - -PCMCIA Wireless LAN -CONFIG_NET_PCMCIA_RADIO - Say Y here if you would like to use a PCMCIA (PC-card) device to - connect to a wireless local area network. Then say Y to the driver - for your particular card below. - - To use your PC-cards, you will need supporting software from David - Hinds' pcmcia-cs package (see the file - for location). You also want to check out the PCMCIA-HOWTO, - available from . - -Hermes chipset 802.11b support (Orinoco/Prism2/Symbol cards) -CONFIG_HERMES - A driver for 802.11b wireless cards based based on the "Hermes" or - Intersil HFA384x (Prism 2) MAC controller. This includes the vast - majority of the PCMCIA 802.11b cards (which are nearly all rebadges) - - except for the Cisco/Aironet cards. Cards supported include the - Apple Airport (not a PCMCIA card), WavelanIEEE/Orinoco, - Cabletron/EnteraSys Roamabout, ELSA AirLancer, MELCO Buffalo, Avaya, - IBM High Rate Wireless, Farralon Syyline, Samsung MagicLAN, Netgear - MA401, LinkSys WPC-11, D-Link DWL-650, 3Com AirConnect, Intel - PRO/Wireless, and Symbol Spectrum24 High Rate amongst others. - - This option includes the guts of the driver, but in order to - actually use a card you will also need to enable support for PCMCIA - Hermes cards, PLX9052 based PCI adaptors or the Apple Airport below. - - You will also very likely also need the Wireless Tools in order to - configure your card and that /etc/pcmcia/wireless.opts works : - - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called hermes.o. - -Hermes 802.11b in PLX9052 based PCI adaptor support -CONFIG_PLX_HERMES - Enable support for PCMCIA cards supported by the "Hermes" (aka - orinoco_cs) driver when used in PLX9052 based PCI adaptors. These - adaptors are not a full PCMCIA controller but act as a more limited - PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that - 802.11b PCMCIA cards can be used in desktop machines. The Netgear - MA301 is such an adaptor. - - Support for these adaptors is so far still incomplete and buggy. - You have been warned. - -Hermes 802.11b in TMD7160/NCP130 based PCI adaptor support -CONFIG_TMD_HERMES - Enable support for PCMCIA cards supported by the "Hermes" (aka - orinoco) driver when used in TMD7160 based PCI adaptors. These - adaptors are not a full PCMCIA controller but act as a more limited - PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that - 802.11b PCMCIA cards can be used in desktop machines. - - Support for these adaptors is so far still incomplete and buggy. - You have been warned. - -Prism 2.5 PCI 802.11b adaptor support -CONFIG_PCI_HERMES - Enable support for PCI and mini-PCI 802.11b wireless NICs based on - the Prism 2.5 chipset. These are true PCI cards, not the 802.11b - PCMCIA cards bundled with PCI<->PCMCIA adaptors which are also - common. Some of the built-in wireless adaptors in laptops are of - this variety. - -Hermes support (Orinoco/WavelanIEEE/PrismII/Symbol 802.11b cards) -CONFIG_PCMCIA_HERMES - A driver for "Hermes" chipset based PCMCIA wireless adaptors, such - as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/ - EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and - others). It should also be usable on various Prism II based cards - such as the Linksys, D-Link and Farallon Skyline. It should also - work on Symbol cards such as the 3Com AirConnect and Ericsson WLAN. - - To use your PC-cards, you will need supporting software from David - Hinds' pcmcia-cs package (see the file - for location). You also want to check out the PCMCIA-HOWTO, - available from . - - You will also very likely also need the Wireless Tools in order to - configure your card and that /etc/pcmcia/wireless.opts works: - . - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called orinoco_cs.o. - -Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards -CONFIG_AIRO - This is the standard Linux driver to support Cisco/Aironet ISA and - PCI 802.11 wireless cards. - It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X - - with or without encryption) as well as card before the Cisco - acquisition (Aironet 4500, Aironet 4800, Aironet 4800B). - - This driver support both the standard Linux Wireless Extensions - and Cisco proprietary API, so both the Linux Wireless Tools and the - Cisco Linux utilities can be used to configure the card. - - The driver can be compiled as a module and will be named "airo.o". - -Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards -CONFIG_AIRO_CS - This is the standard Linux driver to support Cisco/Aironet PCMCIA - 802.11 wireless cards. This driver is the same as the Aironet - driver part of the Linux Pcmcia package. - It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X - - with or without encryption) as well as card before the Cisco - acquisition (Aironet 4500, Aironet 4800, Aironet 4800B). It also - supports OEM of Cisco such as the DELL TrueMobile 4800 and Xircom - 802.11b cards. - - This driver support both the standard Linux Wireless Extensions - and Cisco proprietary API, so both the Linux Wireless Tools and the - Cisco Linux utilities can be used to configure the card. - - To use your PC-cards, you will need supporting software from David - Hinds' pcmcia-cs package (see the file - for location). You also want to check out the PCMCIA-HOWTO, - available from . - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called airo_cs.o. - -Atmel at76c502/at76c504 PCMCIA cards -CONFIG_PCMCIA_ATMEL - A driver for PCMCIA 802.11 wireless cards based on the - Atmel fast-vnet chips. This driver supports standard - Linux wireless extensions. - - Many cards based on this chipset do not have flash memory - and need their firmware loaded at start-up. If yours is - one of these, you will need to provide a firmware image - to be loaded into the card by the driver. The Atmel - firmware package can be downloaded from - http://www.thekelleys.org.uk/atmel/atmel_firmware.tar.gz - -Aviator/Raytheon 2.4MHz wireless support -CONFIG_PCMCIA_RAYCS - Say Y here if you intend to attach an Aviator/Raytheon PCMCIA - (PC-card) wireless Ethernet networking card to your computer. - Please read the file for - details. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ray_cs.o. If you want to compile it as a - module, say M here and read . If - unsure, say N. - -Apple Airport support (built-in) -CONFIG_APPLE_AIRPORT - Say Y here to support the Airport 802.11b wireless Ethernet hardware - built into the Macintosh iBook and other recent PowerPC-based - Macintosh machines. This is essentially a Lucent Orinoco card with - a non-standard interface - -Xircom Netwave AirSurfer wireless support -CONFIG_PCMCIA_NETWAVE - Say Y here if you intend to attach this type of PCMCIA (PC-card) - wireless Ethernet networking card to your computer. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called netwave_cs.o. If you want to compile it - as a module, say M here and read . - If unsure, say N. - -AT&T/Lucent Wavelan wireless support -CONFIG_PCMCIA_WAVELAN - Say Y here if you intend to attach an AT&T/Lucent Wavelan PCMCIA - (PC-card) wireless Ethernet networking card to your computer. This - driver is for the non-IEEE-802.11 Wavelan cards. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called wavelan_cs.o. If you want to compile it - as a module, say M here and read . - If unsure, say N. - -PLIP (parallel port) support -CONFIG_PLIP - PLIP (Parallel Line Internet Protocol) is used to create a - reasonably fast mini network consisting of two (or, rarely, more) - local machines. A PLIP link from a Linux box is a popular means to - install a Linux distribution on a machine which doesn't have a - CD-ROM drive (a minimal system has to be transferred with floppies - first). The kernels on both machines need to have this PLIP option - enabled for this to work. - - The PLIP driver has two modes, mode 0 and mode 1. The parallel - ports (the connectors at the computers with 25 holes) are connected - with "null printer" or "Turbo Laplink" cables which can transmit 4 - bits at a time (mode 0) or with special PLIP cables, to be used on - bidirectional parallel ports only, which can transmit 8 bits at a - time (mode 1); you can find the wiring of these cables in - . The cables can be up to - 15m long. Mode 0 works also if one of the machines runs DOS/Windows - and has some PLIP software installed, e.g. the Crynwr PLIP packet - driver () - and winsock or NCSA's telnet. - - If you want to use PLIP, say Y and read the PLIP mini-HOWTO as well - as the NET-3-HOWTO, both available from - . Note that the PLIP - protocol has been changed and this PLIP driver won't work together - with the PLIP support in Linux versions 1.0.x. This option enlarges - your kernel by about 8 KB. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read as well as - . The module will be - called plip.o. If unsure, say Y or M, in case you buy a laptop - later. - -EQL (serial line load balancing) support -CONFIG_EQUALIZER - If you have two serial connections to some other computer (this - usually requires two modems and two telephone lines) and you use - SLIP (the protocol for sending Internet traffic over telephone - lines) or PPP (a better SLIP) on them, you can make them behave like - one double speed connection using this driver. Naturally, this has - to be supported at the other end as well, either with a similar EQL - Linux driver or with a Livingston Portmaster 2e. - - Say Y if you want this and read - . You may also want to read - section 6.2 of the NET-3-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called eql.o. If you want to compile it as a - module, say M here and read . If - unsure, say N. - -Universal TUN/TAP device driver support -CONFIG_TUN - TUN/TAP provides packet reception and transmission for user space - programs. It can be viewed as a simple Point-to-Point or Ethernet - device, which instead of receiving packets from a physical media, - receives them from user space program and instead of sending packets - via physical media writes them to the user space program. - - When a program opens /dev/net/tun, driver creates and registers - corresponding net device tunX or tapX. After a program closed above - devices, driver will automatically delete tunXX or tapXX device and - all routes corresponding to it. - - Please read for more - information. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called tun.o. If you want to compile it as a - module, say M here and read . - - If you don't know what to use this for, you don't need it. - -Ethertap network tap (OBSOLETE) -CONFIG_ETHERTAP - If you say Y here (and have said Y to "Kernel/User network link - driver", above) and create a character special file /dev/tap0 with - major number 36 and minor number 16 using mknod ("man mknod"), you - will be able to have a user space program read and write raw - Ethernet frames from/to that special file. tap0 can be configured - with ifconfig and route like any other Ethernet device but it is not - connected to any physical LAN; everything written by the user to - /dev/tap0 is treated by the kernel as if it had come in from a LAN - to the device tap0; everything the kernel wants to send out over the - device tap0 can instead be read by the user from /dev/tap0: the user - mode program replaces the LAN that would be attached to an ordinary - Ethernet device. Please read the file - for more information. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ethertap.o. If you want to compile it as a - module, say M here and read . - - If you don't know what to use this for, you don't need it. - -Sealevel Systems 4021 support -CONFIG_SEALEVEL_4021 - This is a driver for the Sealevel Systems ACB 56 serial I/O adapter. - - This driver can only be compiled as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to do that, say M here. The module will be called - sealevel.o. - -TMPTX3912/PR31700 serial port support -CONFIG_SERIAL_TX3912 - The TX3912 is a Toshiba RISC processor based o the MIPS 3900 core; - see . - Say Y here to enable kernel support for the on-board serial port. - -Console on TMPTX3912/PR31700 serial port -CONFIG_SERIAL_TX3912_CONSOLE - The TX3912 is a Toshiba RISC processor based o the MIPS 3900 core; - see . - Say Y here to direct console I/O to the on-board serial port. - -Enable Au1000 serial console -CONFIG_AU1000_SERIAL_CONSOLE - If you have an Alchemy AU1000 processor (MIPS based) and you want - to use a console on a serial port, say Y. Otherwise, say N. - -Enable Au1000 UART Support -CONFIG_AU1000_UART - If you have an Alchemy AU1000 processor (MIPS based) and you want - to use serial ports, say Y. Otherwise, say N. - -SyncLink HDLC/SYNCPPP support -CONFIG_SYNCLINK_SYNCPPP - Enables HDLC/SYNCPPP support for the SyncLink WAN driver. - Normally the SyncLink WAN driver works with the main PPP - driver (ppp.c) and pppd program. HDLC/SYNCPPP support allows use - of the Cisco HDLC/PPP driver (syncppp.c). - The SyncLink WAN driver (in character devices) must also be enabled. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called syncppp.o. - -FarSync T-Series X.21 (and V.35/V.24) cards -CONFIG_FARSYNC - This driver supports the FarSync T-Series X.21 (and V.35/V.24) cards - from FarSite Communications Ltd. - Synchronous communication is supported on all ports at speeds up to - 8Mb/s (128K on V.24) using synchronous PPP, Cisco HDLC, raw HDLC, - Frame Relay or X.25/LAPB. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want) - say M here and read . - The module will be called farsync.o and if you want the module to be - automatically loaded when the interface is referenced then you - should add "alias hdlcX farsync" to /etc/modules.conf for each - interface, where X is 0, 1, 2, ... - -Frame Relay (DLCI) support -CONFIG_DLCI - This is support for the frame relay protocol; frame relay is a fast - low-cost way to connect to a remote Internet access provider or to - form a private wide area network. The one physical line from your - box to the local "switch" (i.e. the entry point to the frame relay - network, usually at the phone company) can carry several logical - point-to-point connections to other computers connected to the frame - relay network. For a general explanation of the protocol, check out - on the WWW. To use frame relay, you need - supporting hardware (called FRAD) and certain programs from the - net-tools package as explained in - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called dlci.o. If you want to compile it as a - module, say M here and read . - -Max open DLCI -CONFIG_DLCI_COUNT - This is the maximal number of logical point-to-point frame relay - connections (the identifiers of which are called DCLIs) that - the driver can handle. The default is probably fine. - -Max DLCI per device -CONFIG_DLCI_MAX - You can specify here how many logical point-to-point frame relay - connections (the identifiers of which are called DCLIs) should be - handled by each of your hardware frame relay access devices. Go with - the default. - -SDLA (Sangoma S502/S508) support -CONFIG_SDLA - Say Y here if you need a driver for the Sangoma S502A, S502E, and - S508 Frame Relay Access Devices. These are multi-protocol cards, but - only frame relay is supported by the driver at this time. Please - read . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called sdla.o. If you want to compile it as a - module, say M here and read . - -Acorn Econet/AUN protocols -CONFIG_ECONET - Econet is a fairly old and slow networking protocol mainly used by - Acorn computers to access file and print servers. It uses native - Econet network cards. AUN is an implementation of the higher level - parts of Econet that runs over ordinary Ethernet connections, on - top of the UDP packet protocol, which in turn runs on top of the - Internet protocol IP. - - If you say Y here, you can choose with the next two options whether - to send Econet/AUN traffic over a UDP Ethernet connection or over - a native Econet network card. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called econet.o. If you want to compile it as a - module, say M here and read . - -AUN over UDP -CONFIG_ECONET_AUNUDP - Say Y here if you want to send Econet/AUN traffic over a UDP - connection (UDP is a packet based protocol that runs on top of the - Internet protocol IP) using an ordinary Ethernet network card. - -Native Econet -CONFIG_ECONET_NATIVE - Say Y here if you have a native Econet network card installed in - your computer. - -WAN router -CONFIG_WAN_ROUTER - Wide Area Networks (WANs), such as X.25, frame relay and leased - lines, are used to interconnect Local Area Networks (LANs) over vast - distances with data transfer rates significantly higher than those - achievable with commonly used asynchronous modem connections. - Usually, a quite expensive external device called a `WAN router' is - needed to connect to a WAN. - - As an alternative, WAN routing can be built into the Linux kernel. - With relatively inexpensive WAN interface cards available on the - market, a perfectly usable router can be built for less than half - the price of an external router. If you have one of those cards and - wish to use your Linux box as a WAN router, say Y here and also to - the WAN driver for your card, below. You will then need the - wan-tools package which is available from . - Read for more - information. - - The WAN routing support is also available as a module called - wanrouter.o ( = code which can be inserted in and removed from the - running kernel whenever you want). If you want to compile it as a - module, say M here and read . - - If unsure, say N. - -Fast switching (read help!) -CONFIG_NET_FASTROUTE - Saying Y here enables direct NIC-to-NIC (NIC = Network Interface - Card) data transfers on the local network, which is fast. - - IMPORTANT NOTE: This option is NOT COMPATIBLE with "Network packet - filtering" (CONFIG_NETFILTER). Say N here if you say Y there. - - However, it will work with all options in the "Advanced router" - section (except for "Use TOS value as routing key" and - "Use FWMARK value as routing key"). - - At the moment, few devices support fast switching (tulip is one of - them, a modified 8390 driver can be found at - ). - - If unsure, say N. - -Forwarding between high speed interfaces -CONFIG_NET_HW_FLOWCONTROL - This option enables NIC (Network Interface Card) hardware throttling - during periods of extremal congestion. At the moment only a couple - of device drivers support it (really only one -- tulip, a modified - 8390 driver can be found at - ). - - Really, this option is applicable to any machine attached to a fast - enough network, and even a 10 Mb NIC is able to kill a not very slow - box, such as a 120MHz Pentium. - - However, do not say Y here if you did not experience any serious - problems. - -QoS and/or fair queueing -CONFIG_NET_SCHED - When the kernel has several packets to send out over a network - device, it has to decide which ones to send first, which ones to - delay, and which ones to drop. This is the job of the packet - scheduler, and several different algorithms for how to do this - "fairly" have been proposed. - - If you say N here, you will get the standard packet scheduler, which - is a FIFO (first come, first served). If you say Y here, you will be - able to choose from among several alternative algorithms which can - then be attached to different network devices. This is useful for - example if some of your network devices are real time devices that - need a certain minimum data flow rate, or if you need to limit the - maximum data flow rate for traffic which matches specified criteria. - This code is considered to be experimental. - - To administer these schedulers, you'll need the user-level utilities - from the package iproute2+tc at . - That package also contains some documentation; for more, check out - . - - This Quality of Service (QoS) support will enable you to use - Differentiated Services (diffserv) and Resource Reservation Protocol - (RSVP) on your Linux router if you also say Y to "QoS support", - "Packet classifier API" and to some classifiers below. Documentation - and software is at . - - If you say Y here and to "/proc file system" below, you will be able - to read status information about packet schedulers from the file - /proc/net/psched. - - The available schedulers are listed in the following questions; you - can say Y to as many as you like. If unsure, say N now. - -CBQ packet scheduler -CONFIG_NET_SCH_CBQ - Say Y here if you want to use the Class-Based Queueing (CBQ) packet - scheduling algorithm for some of your network devices. This - algorithm classifies the waiting packets into a tree-like hierarchy - of classes; the leaves of this tree are in turn scheduled by - separate algorithms (called "disciplines" in this context). - - See the top of for references about the - CBQ algorithm. - - CBQ is a commonly used scheduler, so if you're unsure, you should - say Y here. Then say Y to all the queueing algorithms below that you - want to use as CBQ disciplines. Then say Y to "Packet classifier - API" and say Y to all the classifiers you want to use; a classifier - is a routine that allows you to sort your outgoing traffic into - classes based on a certain criterion. - - This code is also available as a module called sch_cbq.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -CONFIG_NET_SCH_HTB - Say Y here if you want to use the Hierarchical Token Buckets (HTB) - packet scheduling algorithm for some of your network devices. See - URL for complete manual and - in-depth articles. - - HTB is very similar to the CBQ regarding its goals however is has - different properties and different algorithm. - - This code is also available as a module called sch_htb.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -CONFIG_NET_SCH_HFSC - Say Y here if you want to use the Hierarchical Fair Service Curve - (HFSC) packet scheduling algorithm for some of your network devices. - - This code is also available as a module called sch_hfsc.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -CSZ packet scheduler -CONFIG_NET_SCH_CSZ - Say Y here if you want to use the Clark-Shenker-Zhang (CSZ) packet - scheduling algorithm for some of your network devices. At the - moment, this is the only algorithm that can guarantee service for - real-time applications (see the top of - for details and references about the algorithm). - - Note: this scheduler is currently broken. - - This code is also available as a module called sch_csz.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -ATM pseudo-scheduler -CONFIG_NET_SCH_ATM - Say Y here if you want to use the ATM pseudo-scheduler. This - provides a framework for invoking classifiers (aka "filters"), which - in turn select classes of this queuing discipline. Each class maps - the flow(s) it is handling to a given virtual circuit (see the top of - ). - - This code is also available as a module called sch_atm.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -The simplest PRIO pseudo-scheduler -CONFIG_NET_SCH_PRIO - Say Y here if you want to use an n-band priority queue packet - "scheduler" for some of your network devices or as a leaf discipline - for the CBQ scheduling algorithm. If unsure, say Y. - - This code is also available as a module called sch_prio.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Diffserv field marker -CONFIG_NET_SCH_DSMARK - Say Y if you want to schedule packets according to the - Differentiated Services architecture proposed in RFC 2475. - Technical information on this method, with pointers to associated - RFCs, is available at . - - This code is also available as a module called sch_dsmark.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -GRED queue -CONFIG_NET_SCH_GRED - Say Y here if you want to use the Generic Random Early Detection - (RED) packet scheduling algorithm for some of your network devices - (see the top of for details and - references about the algorithm). - - This code is also available as a module called sch_gred.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -RED queue -CONFIG_NET_SCH_RED - Say Y here if you want to use the Random Early Detection (RED) - packet scheduling algorithm for some of your network devices (see - the top of for details and references - about the algorithm). - - This code is also available as a module called sch_red.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -SFQ queue -CONFIG_NET_SCH_SFQ - Say Y here if you want to use the Stochastic Fairness Queueing (SFQ) - packet scheduling algorithm for some of your network devices or as a - leaf discipline for the CBQ scheduling algorithm (see the top of - for details and references about the SFQ - algorithm). - - This code is also available as a module called sch_sfq.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -TEQL queue -CONFIG_NET_SCH_TEQL - Say Y here if you want to use the True Link Equalizer (TLE) packet - scheduling algorithm for some of your network devices or as a leaf - discipline for the CBQ scheduling algorithm. This queueing - discipline allows the combination of several physical devices into - one virtual device. (see the top of for - details). - - This code is also available as a module called sch_teql.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -TBF queue -CONFIG_NET_SCH_TBF - Say Y here if you want to use the Simple Token Bucket Filter (TBF) - packet scheduling algorithm for some of your network devices or as a - leaf discipline for the CBQ scheduling algorithm (see the top of - for a description of the TBF algorithm). - - This code is also available as a module called sch_tbf.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Network delay simualtor -CONFIG_NET_SCH_DELAY - Say Y if you want to delay packets by a fixed amount of - time. This is often useful to simulate network delay when - testing applications or protocols. - - This code is also available as a module called sch_delay.o - -Ingress Qdisc -CONFIG_NET_SCH_INGRESS - If you say Y here, you will be able to police incoming bandwidth - and drop packets when this bandwidth exceeds your desired rate. - If unsure, say Y. - - This code is also available as a module called cls_ingress.o - ( = code which can be inserted in and removed from the running - kernel whenever you want). If you want to compile it as a module, - say M here and read . - -QoS support -CONFIG_NET_QOS - Say Y here if you want to include Quality Of Service scheduling - features, which means that you will be able to request certain - rate-of-flow limits for your network devices. - - This Quality of Service (QoS) support will enable you to use - Differentiated Services (diffserv) and Resource Reservation Protocol - (RSVP) on your Linux router if you also say Y to "Packet classifier - API" and to some classifiers below. Documentation and software is at - . - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about QoS support. - -Rate estimator -CONFIG_NET_ESTIMATOR - In order for Quality of Service scheduling to work, the current - rate-of-flow for a network device has to be estimated; if you say Y - here, the kernel will do just that. - -Packet classifier API -CONFIG_NET_CLS - The CBQ scheduling algorithm requires that network packets which are - scheduled to be sent out over a network device be classified - according to some criterion. If you say Y here, you will get a - choice of several different packet classifiers with the following - questions. - - This will enable you to use Differentiated Services (diffserv) and - Resource Reservation Protocol (RSVP) on your Linux router. - Documentation and software is at - . - -Traffic policing (needed for in/egress) -CONFIG_NET_CLS_POLICE - Say Y to support traffic policing (bandwidth limits). Needed for - ingress and egress rate limiting. - -TC index classifier -CONFIG_NET_CLS_TCINDEX - If you say Y here, you will be able to classify outgoing packets - according to the tc_index field of the skb. You will want this - feature if you want to implement Differentiated Services using - sch_dsmark. If unsure, say Y. - - This code is also available as a module called cls_tcindex.o - ( = code which can be inserted in and removed from the running - kernel whenever you want). If you want to compile it as a module, - say M here and read . - -Routing tables based classifier -CONFIG_NET_CLS_ROUTE4 - If you say Y here, you will be able to classify outgoing packets - according to the route table entry they matched. If unsure, say Y. - - This code is also available as a module called cls_route.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Firewall based classifier -CONFIG_NET_CLS_FW - If you say Y here, you will be able to classify outgoing packets - according to firewall criteria you specified. - - This code is also available as a module called cls_fw.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -U32 classifier -CONFIG_NET_CLS_U32 - If you say Y here, you will be able to classify outgoing packets - according to their destination address. If unsure, say Y. - - This code is also available as a module called cls_u32.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Special RSVP classifier -CONFIG_NET_CLS_RSVP - The Resource Reservation Protocol (RSVP) permits end systems to - request a minimum and maximum data flow rate for a connection; this - is important for real time data such as streaming sound or video. - - Say Y here if you want to be able to classify outgoing packets based - on their RSVP requests. - - This code is also available as a module called cls_rsvp.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Special RSVP classifier for IPv6 -CONFIG_NET_CLS_RSVP6 - The Resource Reservation Protocol (RSVP) permits end systems to - request a minimum and maximum data flow rate for a connection; this - is important for real time data such as streaming sound or video. - - Say Y here if you want to be able to classify outgoing packets based - on their RSVP requests and you are using the new Internet Protocol - IPv6 as opposed to the older and more common IPv4. - - This code is also available as a module called cls_rsvp6.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Network code profiler -CONFIG_NET_PROFILE - If you say Y here and to "/proc file system support" below, some - obscure and undocumented information about the network code's - performance will be written to /proc/net/profile. If you don't know - what it is about, you don't need it: say N. - -Network packet generator -CONFIG_NET_PKTGEN - This module will inject preconfigured packets, at a configurable - rate, out of a given interface. It is used for network interface - stress testing and performance analysis. If you don't understand - what was just said, you don't need it: say N. - - Documentation on how to use the packet generator can be found - at . - - This code is also available as a module called pktgen.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Wan interfaces support -CONFIG_WAN - Wide Area Networks (WANs), such as X.25, frame relay and leased - lines, are used to interconnect Local Area Networks (LANs) over vast - distances with data transfer rates significantly higher than those - achievable with commonly used asynchronous modem connections. - Usually, a quite expensive external device called a `WAN router' is - needed to connect to a WAN. - - As an alternative, a relatively inexpensive WAN interface card can - allow your Linux box to directly connect to a WAN. If you have one - of those cards and wish to use it under Linux, say Y here and also - to the WAN driver for your card, below. - - If unsure, say N. - -Comtrol Hostess SV-11 support -CONFIG_HOSTESS_SV11 - This is a network card for low speed synchronous serial links, at - up to 256Kbps. It supports both PPP and Cisco HDLC. - - At this point, the driver can only be compiled as a module. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called hostess_sv11.o. - -COSA/SRP sync serial board support -CONFIG_COSA - This is a driver for COSA and SRP synchronous serial boards. These - boards allow to connect synchronous serial devices (for example - base-band modems, or any other device with the X.21, V.24, V.35 or - V.36 interface) to your Linux box. The cards can work as the - character device, synchronous PPP network device, or the Cisco HDLC - network device. - - To actually use the COSA or SRP board, you will need user-space - utilities for downloading the firmware to the cards and to set them - up. Look at the for more - information about the cards (including the pointer to the user-space - utilities). You can also read the comment at the top of the - for details about the cards and the driver - itself. - - The driver will be compiled as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cosa.o. For general information about - modules read . - -Etinc PCISYNC serial board support -CONFIG_DSCC4 - This is a driver for Etinc PCISYNC boards based on the Infineon - (ex. Siemens) DSCC4 chipset. It is supposed to work with the four - ports card. Take a look at - for further informations about the driver and his configuration. - - The driver will be compiled as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called dscc4.o. For general information about - modules read . - -PCISYNC feature -CONFIG_DSCC4_PCISYNC - Due to Etinc's design choice for its PCISYNC cards, some operations - are only allowed on specific ports of the DSCC4. This option is the - only way for the driver to know that it shouldn't return a success - code for these operations. - - Please say Y if your card is an Etinc's PCISYNC. - -Hard reset support -CONFIG_DSCC4_PCI_RST - Various DSCC4 bug forbid any reliable software reset of the asic. - As a replacement, some vendors provide a way to assert the PCI #RST - pin of DSCC4 through the GPIO port of the card. If you choose Y, the - driver will make use of this feature before module removal (i.e. rmmod). - This feature is known to exist on Commtech's cards. - Contact your manufacturer for details. - - Say Y if yout card supports this feature. - -LanMedia Corp. serial boards (SSI/V.35, T1/E1, HSSI, T3) -CONFIG_LANMEDIA - This is a driver for the following Lan Media family of serial - boards. - - LMC 1000 board allows you to connect synchronous serial devices (for - example base-band modems, or any other device with the X.21, V.24, - V.35 or V.36 interface) to your Linux box. - - LMC 1200 with on board DSU board allows you to connect your Linux - box directly to a T1 or E1 circuit. - - LMC 5200 board provides a HSSI interface capable of running up to - 52 mbits per second. - - LMC 5245 board connects directly to a T3 circuit saving the - additional external hardware. - - To change setting such as syncPPP vs cisco HDLC or clock source you - will need lmcctl. It is available at . - - This code is also available as a module called lmc.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Fibre Channel driver support -CONFIG_NET_FC - Fibre Channel is a high speed serial protocol mainly used to connect - large storage devices to the computer; it is compatible with and - intended to replace SCSI. - - If you intend to use Fibre Channel, you need to have a Fibre channel - adaptor card in your computer; say Y here and to the driver for your - adaptor below. You also should have said Y to "SCSI support" and - "SCSI generic support". - -Interphase 5526 Tachyon chipset based adaptor support -CONFIG_IPHASE5526 - Say Y here if you have a Fibre Channel adaptor of this kind. - - The driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called iph5526.o. For general information about - modules read . - -Red Creek Hardware VPN -CONFIG_RCPCI - This is a driver for hardware which provides a Virtual Private - Network (VPN). Say Y if you have it. - - This code is also available as a module called rcpci.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Granch SBNI12 Leased Line adapter driver -CONFIG_SBNI - This is a driver for ISA SBNI12-xx cards which are low cost - alternatives to leased line modems. Say Y if you want to insert - the driver into the kernel or say M to compile it as a module (the - module will be called sbni.o). - - You can find more information and last versions of drivers and - utilities at . If you have any question you - can send email to sbni@granch.ru. - - Say N if unsure. - -SBNI multiple-line feature support -CONFIG_SBNI_MULTILINE - Schedule traffic for some parallel lines, via SBNI12 adapters. - If you have two computers connected with two parallel lines it's - possible to increase transfer rate nearly twice. You should have - a program named 'sbniconfig' to configure adapters. - - Say N if unsure. - -WAN router drivers -CONFIG_WAN_ROUTER_DRIVERS - If you have a WAN interface card and you want your Linux box to act - as a WAN router, thereby connecting you Local Area Network to the - outside world over the WAN connection, say Y here and then to the - driver for your card below. In addition, you need to say Y to "Wan - Router". - - You will need the wan-tools package which is available from - . Read - for more information. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about WAN router drivers. If unsure, say N. - -Sangoma WANPIPE(tm) multiprotocol cards -CONFIG_VENDOR_SANGOMA - WANPIPE from Sangoma Technologies Inc. () - is a family of intelligent multiprotocol WAN adapters with data - transfer rates up to 4Mbps. They are also known as Synchronous - Data Link Adapters (SDLA) and are designated as S514-PCI or - S508-ISA. These cards support - - - X.25, Frame Relay, PPP, Cisco HDLC protocols. - - - API support for protocols like HDLC (LAPB), - HDLC Streaming, X.25, Frame Relay and BiSync. - - - Ethernet Bridging over Frame Relay protocol. - - - MULTILINK PPP - - - Async PPP (Modem Dialup) - - If you have one or more of these cards, say M to this option; you - may then also want to read the file - . The next questions - will ask you about the protocols you want the driver to support. - - The driver will be compiled as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called wanpipe.o. For general information about - modules read . - -WANPIPE X.25 support -CONFIG_WANPIPE_X25 - Say Y to this option if you are planning to connect a WANPIPE card - to an X.25 network. Note, this feature also includes the X.25 API - support used to develop custom applications over the X.25 protocol. - If you say N, the X.25 support will not be included in the driver. - The X.25 option is supported on S514-PCI and S508-ISA cards. - -WANPIPE Frame Relay support -CONFIG_WANPIPE_FR - Say Y to this option if you are planning to connect a WANPIPE card - to a frame relay network, or use frame relay API to develop - custom applications over the Frame Relay protocol. - This feature also contains the Ethernet Bridging over Frame Relay, - where a WANPIPE frame relay link can be directly connected to the - Linux kernel bridge. If you say N, the frame relay support will - not be included in the driver. The Frame Relay option is - supported on S514-PCI and S508-ISA cards. - -WANPIPE PPP support -CONFIG_WANPIPE_PPP - Say Y to this option if you are planning to connect a WANPIPE card - to a leased line using Point-to-Point protocol (PPP). If you say N, - the PPP support will not be included in the driver. The PPP option - is supported on S514-PCI/S508-ISA cards. - -WANPIPE Multi-Port PPP support -CONFIG_WANPIPE_MULTPPP - Say Y to this option if you are planning to connect a WANPIPE card - to a leased line using Point-to-Point protocol (PPP). Note, the - MultiPort PPP uses the Linux Kernel SyncPPP protocol over the - Sangoma HDLC Streaming adapter. In this case each Sangoma adapter - port can support an independent PPP connection. For example, a - single Quad-Port PCI adapter can support up to four independent - PPP links. If you say N,the PPP support will not be included in the - driver. The PPP option is supported on S514-PCI/S508-ISA cards. - -WANPIPE Cisco HDLC support -CONFIG_WANPIPE_CHDLC - Say Y to this option if you are planning to connect a WANPIPE card - to a leased line using the Cisco HDLC protocol. This now supports - Dual Port Cisco HDLC on the S514-PCI/S508-ISA cards. - This support also allows user to build applications using the - HDLC streaming API. - - CHDLC Streaming driver also supports MULTILINK PPP - support that can bind multiple WANPIPE T1 cards into - a single logical channel. - - If you say N, the Cisco HDLC support and - HDLC streaming API and MULTILINK PPP will not be - included in the driver. - -MultiGate (COMX) synchronous serial board support -CONFIG_COMX - Say Y if you want to use any board from the MultiGate (COMX) family. - These boards are synchronous serial adapters for the PC, - manufactured by ITConsult-Pro Co, Hungary. - - Read for help on - configuring and using COMX interfaces. Further info on these cards - can be found at or . - - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this driver. - -Support for COMX/CMX/HiCOMX boards -CONFIG_COMX_HW_COMX - Hardware driver for the 'CMX', 'COMX' and 'HiCOMX' boards from the - MultiGate family. Say Y if you have one of these. - - You will need additional firmware to use these cards, which are - downloadable from . - - If you want to compile this as a module, say M and read - . The module will be called - comx-hw-comx.o. - -Support for LoCOMX board -CONFIG_COMX_HW_LOCOMX - Hardware driver for the 'LoCOMX' board from the MultiGate family. - Say Y if you have a board like this. - - If you want to compile this as a module, say M and read - . The module will be called - comx-hw-locomx.o. - -Support for MixCOM board -CONFIG_COMX_HW_MIXCOM - Hardware driver for the 'MixCOM' board from the MultiGate family. - Say Y if you have a board like this. - - If you want to use the watchdog device on this card, you should - select it in the Watchdog Cards section of the Character Devices - configuration. The ISDN interface of this card is Teles 16.3 - compatible, you should enable it in the ISDN configuration menu. The - driver for the flash ROM of this card is available separately on - . - - If you want to compile this as a module, say M and read - . The module will be called - comx-hw-mixcom.o. - -i810 TCO timer/watchdog support -CONFIG_I810_TCO - Hardware driver for the TCO timer built into the Intel i810 and i815 - chipset family. The TCO (Total Cost of Ownership) timer is a - watchdog timer that will reboot the machine after its second - expiration. The expiration time can be configured by command - argument "i810_margin=" where is the counter initial value. - It is decremented every 0.6 secs, the default is 50 which gives a - timeout of 30 seconds and one minute until reset. - - On some motherboards the driver may fail to reset the chipset's - NO_REBOOT flag which prevents the watchdog from rebooting the - machine. If this is the case you will get a kernel message like - "i810tco init: failed to reset NO_REBOOT flag". - - If you want to compile this as a module, say M and read - . The module will be called - i810-tco.o. - -SliceCOM/PciCOM board support -CONFIG_COMX_HW_MUNICH - Hardware driver for the 'SliceCOM' (channelized E1) and 'PciCOM' - boards (X21) from the MultiGate family. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called comx-hw-munich.o. If you want to compile it - as a module, say M here and read . - - Read linux/Documentation/networking/slicecom.txt for help on - configuring and using SliceCOM interfaces. Further info on these cards - can be found at or . - -Support for HDLC and syncPPP protocols on MultiGate boards -CONFIG_COMX_PROTO_PPP - Cisco-HDLC and synchronous PPP protocol driver for all MultiGate - boards. Say Y if you want to use either protocol on your MultiGate - boards. - - If you want to compile this as a module, say M and read - . The module will be called - comx-proto-ppp.o. - -Support for LAPB protocol on MultiGate boards -CONFIG_COMX_PROTO_LAPB - LAPB protocol driver for all MultiGate boards. Say Y if you - want to use this protocol on your MultiGate boards. - - If you want to compile this as a module, say M and read - . The module will be called - comx-proto-lapb.o. - -Support for Frame Relay on MultiGate boards -CONFIG_COMX_PROTO_FR - Frame Relay protocol driver for all MultiGate boards. Say Y if you - want to use this protocol on your MultiGate boards. - - If you want to compile this as a module, say M and read - . The module will be called - comx-proto-fr.o. - -Cyclom 2X(tm) multiprotocol cards -CONFIG_CYCLADES_SYNC - Cyclom 2X from Cyclades Corporation ( and - ) is an intelligent multiprotocol WAN - adapter with data transfer rates up to 512 Kbps. These cards support - the X.25 and SNA related protocols. If you have one or more of these - cards, say Y to this option. The next questions will ask you about - the protocols you want the driver to support (for now only X.25 is - supported). - - While no documentation is available at this time please grab the - wanconfig tarball in - (with minor changes - to make it compile with the current wanrouter include files; efforts - are being made to use the original package available at - ). - - Feel free to contact me or the cycsyn-devel mailing list at - acme@conectiva.com.br and cycsyn-devel@bazar.conectiva.com.br for - additional details, I hope to have documentation available as soon - as possible. (Cyclades Brazil is writing the Documentation). - - The driver will be compiled as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cyclomx.o. For general information about - modules read . - -Cyclom 2X X.25 support -CONFIG_CYCLOMX_X25 - Say Y to this option if you are planning to connect a Cyclom 2X card - to an X.25 network. - - If you say N, the X.25 support will not be included in the driver - (saves about 11 KB of kernel memory). - -Generic HDLC driver -CONFIG_HDLC - Say Y to this option if your Linux box contains a WAN card supported - by this driver and you are planning to connect the box to a WAN - ( = Wide Area Network). You will need supporting software from - . - Generic HDLC driver currently supports raw HDLC, Cisco HDLC, Frame - Relay, synchronous Point-to-Point Protocol (PPP) and X.25. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called hdlc.o. - - If unsure, say N here. - -Raw HDLC support -CONFIG_HDLC_RAW - Say Y to this option if you want generic HDLC driver to support - raw HDLC over WAN (Wide Area Network) connections. - - If unsure, say N here. - -Raw HDLC Ethernet device support -CONFIG_HDLC_RAW_ETH - Say Y to this option if you want generic HDLC driver to support - raw HDLC Ethernet device emulation over WAN (Wide Area Network) - connections. - You will need it for Ethernet over HDLC bridges. - - If unsure, say N here. - -Cisco HDLC support -CONFIG_HDLC_CISCO - Say Y to this option if you want generic HDLC driver to support - Cisco HDLC over WAN (Wide Area Network) connections. - - If unsure, say N here. - -Frame-Relay HDLC support -CONFIG_HDLC_FR - Say Y to this option if you want generic HDLC driver to support - Frame-Relay protocol over WAN (Wide Area Network) connections. - - If unsure, say N here. - -Synchronous Point-to-Point Protocol (PPP) support -CONFIG_HDLC_PPP - Say Y to this option if you want generic HDLC driver to support - PPP over WAN (Wide Area Network) connections. - - If unsure, say N here. - -CCITT X.25 over HDLC support -CONFIG_HDLC_X25 - Say Y to this option if you want generic HDLC driver to support - X.25 protocol over WAN (Wide Area Network) connections. - - If unsure, say N here. - -Cyclades-PC300 support -CONFIG_PC300 - This is a driver for the Cyclades-PC300 synchronous communication - boards. These boards provide synchronous serial interfaces to your - Linux box (interfaces currently available are RS-232/V.35, X.21 and - T1/E1). If you wish to support Multilink PPP, please select the - option below this one and read the file README.mlppp provided by PC300 - package. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called pc300.o. - - If you haven't heard about it, it's safe to say N. - -Cyclades-PC300 Sync TTY (to MLPPP) support -CONFIG_PC300_MLPPP - Say 'Y' to this option if you are planning to use Multilink PPP over the - PC300 synchronous communication boards. - -CONFIG_PCI200SYN - This driver is for PCI200SYN cards made by Goramo sp. j. - If you have such a card, say Y or M here and see - - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called pci200syn.o. - - If unsure, say N here. - -SDL RISCom/N2 support -CONFIG_N2 - This driver is for RISCom/N2 single or dual channel ISA cards - made by SDL Communications Inc. If you have such a card, - say Y here and see . - - Note that N2csu and N2dds cards are not supported by this driver. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called n2.o. - - If unsure, say N here. - -Moxa C101 support -CONFIG_C101 - This driver is for C101 SuperSync ISA cards made by Moxa - Technologies Co., Ltd. If you have such a card, - say Y here and see - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called c101.o. - - If unsure, say N here. - -Ethernet (10 or 100Mbit) -CONFIG_NET_ETHERNET - Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common - type of Local Area Network (LAN) in universities and companies. - - Common varieties of Ethernet are: 10BASE-2 or Thinnet (10 Mbps over - coaxial cable, linking computers in a chain), 10BASE-T or twisted - pair (10 Mbps over twisted pair cable, linking computers to central - hubs), 10BASE-F (10 Mbps over optical fiber links, using hubs), - 100BASE-TX (100 Mbps over two twisted pair cables, using hubs), - 100BASE-T4 (100 Mbps over 4 standard voice-grade twisted pair - cables, using hubs), 100BASE-FX (100 Mbps over optical fiber links) - [the 100BASE varieties are also known as Fast Ethernet], and Gigabit - Ethernet (1 Gbps over optical fiber or short copper links). - - If your Linux machine will be connected to an Ethernet and you have - an Ethernet network interface card (NIC) installed in your computer, - say Y here and read the Ethernet-HOWTO, available from - . You will then also have - to say Y to the driver for your particular NIC. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about Ethernet network cards. If unsure, say N. - -Western Digital/SMC cards -CONFIG_NET_VENDOR_SMC - If you have a network (Ethernet) card belonging to this class, say Y - and read the Ethernet-HOWTO, available from - . - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about Western Digital cards. If you say Y, you will be - asked for your specific card in the following questions. - -WD80*3 support -CONFIG_WD80x3 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called wd.o. If you want to compile it as a - module, say M here and read as well - as . - -SMC Ultra MCA support -CONFIG_ULTRAMCA - If you have a network (Ethernet) card of this type and are running - an MCA based system (PS/2), say Y and read the Ethernet-HOWTO, - available from . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called smc-mca.o. If you want to compile it as a - module, say M here and read as well - as . - -SMC Ultra support -CONFIG_ULTRA - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - Important: There have been many reports that, with some motherboards - mixing an SMC Ultra and an Adaptec AHA154x SCSI card (or compatible, - such as some BusLogic models) causes corruption problems with many - operating systems. The Linux smc-ultra driver has a work-around for - this but keep it in mind if you have such a SCSI card and have - problems. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called smc-ultra.o. If you want to compile it as - a module, say M here and read as - well as . - -SMC Ultra32 EISA support -CONFIG_ULTRA32 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called smc-ultra32.o. If you want to compile it - as a module, say M here and read as - well as . - -SMC 9194 support -CONFIG_SMC9194 - This is support for the SMC9xxx based Ethernet cards. Choose this - option if you have a DELL laptop with the docking station, or - another SMC9192/9194 based chipset. Say Y if you want it compiled - into the kernel, and read the file - and the Ethernet-HOWTO, - available from . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called smc9194.o. If you want to compile it as a - module, say M here and read as well - as . - -PCI NE2000 and clones support -CONFIG_NE2K_PCI - This driver is for NE2000 compatible PCI cards. It will not work - with ISA NE2000 cards (they have their own driver, "NE2000/NE1000 - support" below). If you have a PCI NE2000 network (Ethernet) card, - say Y and read the Ethernet-HOWTO, available from - . - - This driver also works for the following NE2000 clone cards: - RealTek RTL-8029 Winbond 89C940 Compex RL2000 KTI ET32P2 - NetVin NV5000SC Via 86C926 SureCom NE34 Winbond - Holtek HT80232 Holtek HT80229 - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ne2k-pci.o. If you want to compile it as - a module, say M here and read as - well as . - -Racal-Interlan (Micom) NI cards -CONFIG_NET_VENDOR_RACAL - If you have a network (Ethernet) card belonging to this class, such - as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO, - available from . - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about NI cards. If you say Y, you will be asked for - your specific card in the following questions. - -NI5010 support -CONFIG_NI5010 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . Note that this is still - experimental code. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ni5010.o. If you want to compile it as a - module, say M here and read as well - as . - -NI5210 support -CONFIG_NI52 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ni52.o. If you want to compile it as a - module, say M here and read as well - as . - -NI6510 support -CONFIG_NI65 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ni65.o. If you want to compile it as a - module, say M here and read as well - as . - -RealTek RTL-8139C+ 10/100 PCI Fast Ethernet Adapter support -CONFIG_8139CP - This is a driver for the Fast Ethernet PCI network cards based on - the RTL8139C+ chips. If you have one of those, say Y and read - the Ethernet-HOWTO, available from - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. This is recommended. - The module will be called 8139cp.o. - -RealTek RTL-8139 PCI Fast Ethernet Adapter support -CONFIG_8139TOO - This is a driver for the Fast Ethernet PCI network cards based on - the RTL8139 chips. If you have one of those, say Y and read - as well as the - Ethernet-HOWTO, available from - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called 8139too.o. - -Use PIO instead of MMIO -CONFIG_8139TOO_PIO - This instructs the driver to use programmed I/O ports (PIO) instead - of PCI shared memory (MMIO). This can possibly solve some problems - in case your mainboard has memory consistency issues. If unsure, - say N. - -Support for uncommon RTL-8139 rev. K (automatic channel equalization) -CONFIG_8139TOO_TUNE_TWISTER - This implements a function which might come in handy in case you - are using low quality on long cabling. It is required for RealTek - RTL-8139 revision K boards, and totally unused otherwise. It tries - to match the transceiver to the cable characteristics. This is - experimental since hardly documented by the manufacturer. - If unsure, say Y. - -Support for older RTL-8129/8130 boards -CONFIG_8139TOO_8129 - This enables support for the older and uncommon RTL-8129 and - RTL-8130 chips, which support MII via an external transceiver, - instead of an internal one. Disabling this option will save some - memory by making the code size smaller. If unsure, say Y. - -Use older RX-reset method -CONFIG_8139_OLD_RX_RESET - The 8139too driver was recently updated to contain a more rapid - reset sequence, in the face of severe receive errors. This "new" - RX-reset method should be adequate for all boards. But if you - experience problems, you can enable this option to restore the - old RX-reset behavior. If unsure, say N. - -SiS 900/7016 PCI Fast Ethernet Adapter support -CONFIG_SIS900 - This is a driver for the Fast Ethernet PCI network cards based on - the SiS 900 and SiS 7016 chips. The SiS 900 core is also embedded in - SiS 630 and SiS 540 chipsets. If you have one of those, say Y and - read the Ethernet-HOWTO, available at - . Please read - and comments at the - beginning of for more information. - - This driver also supports AMD 79C901 HomePNA so that you can use - your phone line as a network cable. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called sis900.o. - -Packet Engines Yellowfin Gigabit-NIC / Symbios 53c885 support -CONFIG_YELLOWFIN - Say Y here if you have a Packet Engines G-NIC PCI Gigabit Ethernet - adapter or the SYM53C885 Ethernet controller. The Gigabit adapter is - used by the Beowulf Linux cluster project. See - for more - information about this driver in particular and Beowulf in general. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called yellowfin.o. - -Realtek 8169 Gigabit Ethernet support -CONFIG_R8169 - Say Y here if you have a Realtek 8169 PCI Gigabit Ethernet adapter. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called r8169.o. - -General Instruments Surfboard 1000 -CONFIG_NET_SB1000 - This is a driver for the General Instrument (also known as - NextLevel) SURFboard 1000 internal - cable modem. This is an ISA card which is used by a number of cable - TV companies to provide cable modem access. It's a one-way - downstream-only cable modem, meaning that your upstream net link is - provided by your regular phone modem. - - At present this driver only compiles as a module, so say M here if - you have this card. The module will be called sb1000.o. Then read - for information on how - to use this module, as it needs special ppp scripts for establishing - a connection. Further documentation and the necessary scripts can be - found at: - - - - - - If you don't have this card, of course say N. - -Adaptec Starfire support -CONFIG_ADAPTEC_STARFIRE - Say Y here if you have an Adaptec Starfire (or DuraLAN) PCI network - adapter. The DuraLAN chip is used on the 64 bit PCI boards from - Adaptec e.g. the ANA-6922A. The older 32 bit boards use the tulip - driver. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called starfire.o. - -Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support -CONFIG_ACENIC - Say Y here if you have an Alteon AceNIC, 3Com 3C985(B), NetGear - GA620, SGI Gigabit or Farallon PN9000-SX PCI Gigabit Ethernet - adapter. The driver allows for using the Jumbo Frame option (9000 - bytes/frame) however it requires that your switches can handle this - as well. To enable Jumbo Frames, add `mtu 9000' to your ifconfig - line. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called acenic.o. - -Omit support for old Tigon I based AceNICs -CONFIG_ACENIC_OMIT_TIGON_I - Say Y here if you only have Tigon II based AceNICs and want to leave - out support for the older Tigon I based cards which are no longer - being sold (ie. the original Alteon AceNIC and 3Com 3C985 (non B - version)). This will reduce the size of the driver object by - app. 100KB. If you are not sure whether your card is a Tigon I or a - Tigon II, say N here. - - The safe and default value for this is N. - -Marvell Yukon / SysKonnect SK-98xx and SK-95xx Gigabit Ethernet Adapter family support -CONFIG_SK98LIN - Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx - compliant Gigabit Ethernet Adapter. The following adapters are supported - by this driver: - - 3Com 3C940 Gigabit LOM Ethernet Adapter - - 3Com 3C941 Gigabit LOM Ethernet Adapter - - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter - - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter - - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter - - Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter - - Allied Telesyn AT-2970TX Gigabit Ethernet Adapter - - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter - - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter - - Allied Telesyn AT-2971T Gigabit Ethernet Adapter - - DGE-530T Gigabit Ethernet Adapter - - EG1032 v2 Instant Gigabit Network Adapter - - EG1064 v2 Instant Gigabit Network Adapter - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Albatron) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Asus) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (ECS) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Epox) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Foxconn) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill) - - Marvell RDK-8001 Adapter - - Marvell RDK-8002 Adapter - - Marvell RDK-8003 Adapter - - Marvell RDK-8004 Adapter - - Marvell RDK-8006 Adapter - - Marvell RDK-8007 Adapter - - Marvell RDK-8008 Adapter - - Marvell RDK-8009 Adapter - - Marvell RDK-8010 Adapter - - Marvell RDK-8011 Adapter - - Marvell RDK-8012 Adapter - - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit) - - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit) - - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L) - - SK-9521 10/100/1000Base-T Adapter - - SK-9521 V2.0 10/100/1000Base-T Adapter - - SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T) - - SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter - - SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link) - - SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX) - - SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter - - SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link) - - SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX) - - SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link) - - SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition) - - SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link) - - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX) - - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter - - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) - - SMC EZ Card 1000 (SMC9452TXV.2) - - The adapters support Jumbo Frames. - The dual link adapters support link-failover and dual port features. - Both Marvell Yukon and SysKonnect SK-98xx/SK-95xx adapters support - the scatter-gather functionality with sendfile(). Please refer to - Documentation/networking/sk98lin.txt for more information about - optional driver parameters. - Questions concerning this driver may be addressed to: - linux@syskonnect.de - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. This is recommended. - The module will be called sk98lin.o. - - -Sun GEM support -CONFIG_SUNGEM - Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0. See also - . - - This chip is also used by Apple under the name GMAC in all their recent - machines starting with the first iBook. This includes all AGP capable - Apple machines except some early G4s and iMacs that still used a - Tulip chip. This driver obsoletes the GMAC driver for these machines. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called sungem.o. - -Broadcom Tigon3 support -CONFIG_TIGON3 - This driver supports Broadcom Tigon3 based gigabit Ethernet cards. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called tg3.o. - -MV-64340 Ethernet support -CONFIG_MV64340_ETH - This driver supports the Marvell Discovery II MV64340 device - as an Ethernet controller. Say Y here and select Port 0,1,2 - as needed. Otherwise, say N. - -MV-64340 Port 0 -CONFIG_MV64340_ETH_0 - Enable port 0 on the MV64340 Ethernet controller. - -MV-64340 Port 1 -CONFIG_MV64340_ETH_1 - Enable port 1 on the MV64340 Ethernet controller. - -MV-64340 Port 2 -CONFIG_MV64340_ETH_2 - Enable port 2 on the MV64340 Ethernet controller. - -MyriCOM Gigabit Ethernet support -CONFIG_MYRI_SBUS - This driver supports MyriCOM Sbus gigabit Ethernet cards. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called myri_sbus.o. - -D-Link 2000-based Gigabit Ethernet support -CONFIG_DL2K - This driver supports D-Link 2000-based gigabit ethernet cards, which - includes - D-Link DGE-550T Gigabit Ethernet Adapter. - D-Link DL2000-based Gigabit Ethernet Adapter. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called dl2k.o. - -EtherExpress Pro/100 support (e100, Alternate Intel driver) -CONFIG_E100 - This driver supports Intel(R) PRO/100 family of adapters, which - includes: - - Controller Adapter Name Board IDs - ---------- ------------ --------- - - 82558 PRO/100+ PCI Adapter 668081-xxx, - 689661-xxx - 82558 PRO/100+ Management Adapter 691334-xxx, - 701738-xxx, - 721383-xxx - 82558 PRO/100+ Dual Port Server Adapter 714303-xxx, - 711269-xxx, - A28276-xxx - 82558 PRO/100+ PCI Server Adapter 710550-xxx - 82550 PRO/100 S Server Adapter 752438-xxx - 82559 A56831-xxx, - A10563-xxx, - A12171-xxx, - A12321-xxx, - A12320-xxx, - A12170-xxx - 748568-xxx - 748565-xxx - 82550 PRO/100 S Desktop Adapter 751767-xxx - 82559 748592-xxx, - A12167-xxx, - A12318-xxx, - A12317-xxx, - A12165-xxx, - 748569-xxx - 82559 PRO/100+ Server Adapter 729757-xxx - 82559 PRO/100 S Management Adapter 748566-xxx, - 748564-xxx - 82550 PRO/100 S Dual Port Server Adapter A56831-xxx - 82551 PRO/100 M Desktop Adapter A80897-xxx - PRO/100 S Advanced Management Adapter - 747842-xxx, - 745171-xxx - CNR PRO/100 VE Desktop Adapter A10386-xxx, - A10725-xxx, - A23801-xxx, - A19716-xxx - PRO/100 VM Desktop Adapter A14323-xxx, - A19725-xxx, - A23801-xxx, - A22220-xxx, - A23796-xxx - - - To verify that your adapter is supported, find the board ID number - on the adapter. Look for a label that has a barcode and a number - in the format 123456-001 (six digits hyphen three digits). Match - this to the list of numbers above. - - For more information on how to identify your adapter, go to the - Adapter & Driver ID Guide at: - - http://support.intel.com/support/network/adapter/pro100/21397.htm - - For the latest Intel PRO/100 network driver for Linux, see: - - http://appsr.intel.com/scripts-df/support_intel.asp - - More specific information on configuring the driver is in - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called e100.o. If you want to compile it as a - module, say M here and read as well - as . - -Intel(R) PRO/1000 Gigabit Ethernet support -CONFIG_E1000 - This driver supports Intel(R) PRO/1000 gigabit ethernet family of - adapters, which includes: - - Controller Adapter Name Board IDs - ---------- ------------ --------- - 82542 PRO/1000 Gigabit Server Adapter 700262-xxx, - 717037-xxx - 82543 PRO/1000 F Server Adapter 738640-xxx, - A38888-xxx - 82543 PRO/1000 T Server Adapter A19845-xxx, - A33948-xxx - 82544 PRO/1000 XT Server Adapter A51580-xxx - 82544 PRO/1000 XF Server Adapter A50484-xxx - 82544 PRO/1000 T Desktop Adapter A62947-xxx - 82540 PRO/1000 MT Desktop Adapter A78408-xxx - 82541 PRO/1000 MT Desktop Adapter C91016-xxx - 82545 PRO/1000 MT Server Adapter A92165-xxx - 82546 PRO/1000 MT Dual Port Server Adapter A92111-xxx - 82545 PRO/1000 MF Server Adapter A91622-xxx - 82545 PRO/1000 MF Server Adapter(LX) A91624-xxx - 82546 PRO/1000 MF Dual Port Server Adapter A91620-xxx - - For more information on how to identify your adapter, go to the - Adapter & Driver ID Guide at: - - - - For general information and support, go to the Intel support - website at: - - - - More specific information on configuring the driver is in - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called e1000.o. If you want to compile it as a - module, say M here and read as well - as . - -AMD LANCE and PCnet (AT1500 and NE2100) support -CONFIG_LANCE - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . Some LinkSys cards are - of this type. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called lance.o. - -SGI IOC3 Ethernet -CONFIG_SGI_IOC3_ETH - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - -National Semiconductor DP83902AV support -CONFIG_STNIC - Support for cards based on the National Semiconductor DP83902AV - ST-NIC Serial Network Interface Controller for Twisted Pair. This - is a 10Mbit/sec Ethernet controller. Product overview and specs at - . - - If unsure, say N. - -3COM cards -CONFIG_NET_VENDOR_3COM - If you have a network (Ethernet) card belonging to this class, say Y - and read the Ethernet-HOWTO, available from - . - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about 3COM cards. If you say Y, you will be asked for - your specific card in the following questions. - -3c501 "EtherLink" support -CONFIG_EL1 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . Also, consider buying a - new card, since the 3c501 is slow, broken, and obsolete: you will - have problems. Some people suggest to ping ("man ping") a nearby - machine every minute ("man cron") when using this card. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called 3c501.o. If you want to compile it as a - module, say M here and read as well - as . - -3c503 "EtherLink II" support -CONFIG_EL2 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called 3c503.o. If you want to compile it as a - module, say M here and read as well - as . - -3c505 "EtherLink Plus" support -CONFIG_ELPLUS - Information about this network (Ethernet) card can be found in - . If you have a card of - this type, say Y and read the Ethernet-HOWTO, available from - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read as well as - . The module will be - called 3c505.o. - -3c507 (EtherLink 16) support -CONFIG_EL16 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called 3c507.o. If you want to compile it as a - module, say M here and read as well - as . - -3c523 "EtherlinkMC" support -CONFIG_ELMC - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called 3c523.o. If you want to compile it as a - module, say M here and read as well - as . - -3c527 "EtherLink/MC 32" support -CONFIG_ELMC_II - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called 3c527.o. If you want to compile it as a - module, say M here and read as well - as . - -3c509/3c529 (MCA)/3c579 "EtherLink III" support -CONFIG_EL3 - If you have a network (Ethernet) card belonging to the 3Com - EtherLinkIII series, say Y and read the Ethernet-HOWTO, available - from . - - If your card is not working you may need to use the DOS - setup disk to disable Plug & Play mode, and to select the default - media type. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read as well as - . The module will be - called 3c509.o. - -3c515 ISA Fast EtherLink -CONFIG_3C515 - If you have a 3Com ISA EtherLink XL "Corkscrew" 3c515 Fast Ethernet - network card, say Y and read the Ethernet-HOWTO, available from - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read as well as - . The module will be - called 3c515.o. - -3c590/3c900 series (592/595/597) "Vortex/Boomerang/Cyclone" support -CONFIG_VORTEX - This option enables driver support for a large number of 10mbps and - 10/100mbps EISA, PCI and PCMCIA 3Com network cards: - - "Vortex" (Fast EtherLink 3c590/3c592/3c595/3c597) EISA and PCI - "Boomerang" (EtherLink XL 3c900 or 3c905) PCI - "Cyclone" (3c540/3c900/3c905/3c980/3c575/3c656) PCI and Cardbus - "Tornado" (3c905) PCI - "Hurricane" (3c555/3cSOHO) PCI - - If you have such a card, say Y and read the Ethernet-HOWTO, - available from . More - specific information is in - and in the comments at - the beginning of . - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called 3c59x.o. - -3cr990 series "Typhoon" support -CONFIG_TYPHOON - This option enables driver support for the 3cr990 series of cards: - - 3C990-TX, 3CR990-TX-95, 3CR990-TX-97, 3CR990-FX-95, 3CR990-FX-97, - 3CR990SVR, 3CR990SVR95, 3CR990SVR97, 3CR990-FX-95 Server, - 3CR990-FX-97 Server, 3C990B-TX-M, 3C990BSVR - - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called typhoon.o. If you want to compile it as a - module, say M here and read as well - as . - -Other ISA cards -CONFIG_NET_ISA - If your network (Ethernet) card hasn't been mentioned yet and its - bus system (that's the way the cards talks to the other components - of your computer) is ISA (as opposed to EISA, VLB or PCI), say Y. - Make sure you know the name of your card. Read the Ethernet-HOWTO, - available from . - - If unsure, say Y. - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the remaining ISA network card questions. If you say Y, you will be - asked for your specific card in the following questions. - -Generic ARCnet support -CONFIG_ARCNET - If you have a network card of this type, say Y and check out the - (arguably) beautiful poetry in - . - - You need both this driver, and the driver for the particular ARCnet - chipset of your card. If you don't know, then it's probably a - COM90xx type card, so say Y (or M) to "ARCnet COM90xx chipset - support" below. - - You might also want to have a look at the Ethernet-HOWTO, available - from (even though ARCnet - is not really Ethernet). - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called arcnet.o. If you want to compile it as a - module, say M here and read as well - as . - -Enable old ARCNet packet format (RFC 1051) -CONFIG_ARCNET_1051 - This allows you to use RFC1051 with your ARCnet card via the virtual - arc0s device. You only need arc0s if you want to talk to ARCnet - software complying with the "old" standard, specifically, the DOS - arcnet.com packet driver, Amigas running AmiTCP, and some variants - of NetBSD. You do not need to say Y here to communicate with - industry-standard RFC1201 implementations, like the arcether.com - packet driver or most DOS/Windows ODI drivers. RFC1201 is included - automatically as the arc0 device. Please read the ARCnet - documentation in for more - information about using arc0e and arc0s. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called rfc1051.o. - -Enable standard ARCNet packet format (RFC 1201) -CONFIG_ARCNET_1201 - This allows you to use RFC1201 with your ARCnet card via the virtual - arc0 device. You need to say Y here to communicate with - industry-standard RFC1201 implementations, like the arcether.com - packet driver or most DOS/Windows ODI drivers. Please read the - ARCnet documentation in - for more information about using arc0. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called rfc1201.o. - -Enable raw mode packet interface -CONFIG_ARCNET_RAW - ARCnet "raw mode" packet encapsulation, no soft headers. Unlikely - to work unless talking to a copy of the same Linux arcnet driver, - but perhaps marginally faster in that case. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called arc-rawmode.o. - -ARCnet COM90xx (normal) chipset driver -CONFIG_ARCNET_COM90xx - This is the chipset driver for the standard COM90xx cards. If you - have always used the old ARCnet driver without knowing what type of - card you had, this is probably the one for you. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called com90xx.o. If you want to compile it as a - module, say M here and read as well - as . - -ARCnet COM90xx (IO mapped) chipset driver -CONFIG_ARCNET_COM90xxIO - This is the chipset driver for the COM90xx cards, using them in - IO-mapped mode instead of memory-mapped mode. This is slower than - the normal driver. Only use it if your card doesn't support shared - memory. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called com90io.o. If you want to compile it as a - module, say M here and read as well - as . - -ARCnet COM90xx (RIM I) chipset driver -CONFIG_ARCNET_RIM_I - This is yet another chipset driver for the COM90xx cards, but this - time only using memory-mapped mode, and no IO ports at all. This - driver is completely untested, so if you have one of these cards, - please mail dwmw2@infradead.org, especially if it works! - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you - want). The module will be called arc-rimi.o. If you want to compile - it as a module, say M here and read - as well as . - -ARCnet COM20020 chipset driver -CONFIG_ARCNET_COM20020 - This is the driver for the new COM20020 chipset. It supports such - things as promiscuous mode, so packet sniffing is possible, and - extra diagnostic information. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called com20020.o. If you want to compile it as - a module, say M here and read as - well as . - -Cabletron E21xx support -CONFIG_E2100 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called e2100.o. If you want to compile it as a - module, say M here and read as well - as . - -Broadcom 4400 ethernet support (EXPERIMENTAL) -CONFIG_B44 - If you have a network (Ethernet) controller of this type, say Y and - read the Ethernet-HOWTO, available from - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read as well as - . The module will be - called b44. - -nForce Ethernet support (EXPERIMENTAL) -CONFIG_FORCEDETH - If you have a network (Ethernet) controller of this type, say Y and - read the Ethernet-HOWTO, available from - . - - To compile this driver as a module, choose M here and read - . The module will be - called forcedeth.o. - -CS89x0 support (Daynaport CS and LC cards) -CONFIG_CS89x0 - Support for CS89x0 chipset based Ethernet cards. If you have a - network (Ethernet) card of this type, say Y and read the - Ethernet-HOWTO, available from - as well as - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read as well as - . The module will be - called cs89x.o. - -DEPCA, DE10x, DE200, DE201, DE202, DE422 support -CONFIG_DEPCA - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - as well as - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read as well as - . The module will be - called - depca.o. - -EtherWORKS 3 (DE203, DE204, DE205) support -CONFIG_EWRK3 - This driver supports the DE203, DE204 and DE205 network (Ethernet) - cards. If this is for you, say Y and read - in the kernel source as - well as the Ethernet-HOWTO, available from - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read as well as - . The module will be - called ewrk3.o. - -SEEQ8005 support -CONFIG_SEEQ8005 - This is a driver for the SEEQ 8005 network (Ethernet) card. If this - is for you, read the Ethernet-HOWTO, available from - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read as well as - . The module will be - called ewrk3.o. - -AT1700/1720 support -CONFIG_AT1700 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - as well as - . The module will be - called at1700.o. - -FMV-181/182/183/184 support -CONFIG_FMV18X - If you have a Fujitsu FMV-181/182/183/184 network (Ethernet) card, - say Y and read the Ethernet-HOWTO, available from - . - - If you use an FMV-183 or FMV-184 and it is not working, you may need - to disable Plug & Play mode of the card. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called fmv18x.o. If you want to compile it as a - module, say M here and read as well - as . - -EtherExpressPro and EtherExpress 10 (i82595) support -CONFIG_EEXPRESS_PRO - If you have a network (Ethernet) card of this type, say Y. This - driver supports intel i82595{FX,TX} based boards. Note however - that the EtherExpress PRO/100 Ethernet card has its own separate - driver. Please read the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called eepro.o. If you want to compile it as a - module, say M here and read as well - as . - -EtherExpress 16 support -CONFIG_EEXPRESS - If you have an EtherExpress16 network (Ethernet) card, say Y and - read the Ethernet-HOWTO, available from - . Note that the Intel - EtherExpress16 card used to be regarded as a very poor choice - because the driver was very unreliable. We now have a new driver - that should do better. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read as well as - . The module will be - called eexpress.o. - -Packet Engines Hamachi GNIC-II support -CONFIG_HAMACHI - If you have a Gigabit Ethernet card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read as well as - . The module will be - called hamachi.o. - -HP PCLAN+ (27247B and 27252A) support -CONFIG_HPLAN_PLUS - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called hp-plus.o. If you want to compile it as a - module, say M here and read as well - as . - -HP PCLAN (27245 and other 27xxx series) support -CONFIG_HPLAN - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called hp.o. If you want to compile it as a - module, say M here and read as well - as . - -HP 10/100VG PCLAN (ISA, EISA, PCI) support -CONFIG_HP100 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read as well as - . The module will be - called hp100.o. - -NE2000/NE1000 support -CONFIG_NE2000 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . Many Ethernet cards - without a specific driver are compatible with NE2000. - - If you have a PCI NE2000 card however, say N here and Y to "PCI - NE2000 support", above. If you have a NE2000 card and are running on - an MCA system (a bus system used on some IBM PS/2 computers and - laptops), say N here and Y to "NE/2 (ne2000 MCA version) support", - below. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ne.o. If you want to compile it as a - module, say M here and read as well - as . - -National Semiconductor DP8381x series PCI Ethernet support -CONFIG_NATSEMI - This driver is for the National Semiconductor DP83810 series, - which is used in cards from PureData, NetGear, Linksys - and others, including the 83815 chip. - More specific information and updates are available from - . - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called natsemi.o. - -NatSemi workaround for high errors -CONFIG_NATSEMI_CABLE_MAGIC - Some systems see lots of errors with NatSemi ethernet controllers - on certain cables. If you are seeing lots of errors, try turning - this option on. Some boards have incorrect values for supporting - resistors that can cause this change to break. If you turn this - option on and your network suddenly stops working, turn this - option off. - -SK_G16 support -CONFIG_SK_G16 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - -NE/2 (ne2000 MCA version) support -CONFIG_NE2_MCA - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ne2.o. If you want to compile it as a - module, say M here and read as well - as . - -SKnet MCA support -CONFIG_SKMC - These are Micro Channel Ethernet adapters. You need to say Y to "MCA - support" in order to use this driver. Supported cards are the SKnet - Junior MC2 and the SKnet MC2(+). The driver automatically - distinguishes between the two cards. Note that using multiple boards - of different type hasn't been tested with this driver. Say Y if you - have one of these Ethernet adapters. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called sk_mca.o. If you want to compile it as a - module, say M here and read as well - as . - -IBM LAN Adapter/A support -CONFIG_IBMLANA - This is a Micro Channel Ethernet adapter. You need to set - CONFIG_MCA to use this driver. It is both available as an in-kernel - driver and as a module ( = code which can be inserted in and removed - from the running kernel whenever you want). If you want to compile - it as a module, say M here and read - as well as . The only - currently supported card is the IBM LAN Adapter/A for Ethernet. It - will both support 16K and 32K memory windows, however a 32K window - gives a better security against packet losses. Usage of multiple - boards with this driver should be possible, but has not been tested - up to now due to lack of hardware. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ibmlana.o. - -EISA, VLB, PCI and on board controllers -CONFIG_NET_PCI - This is another class of network cards which attach directly to the - bus. If you have one of those, say Y and read the Ethernet-HOWTO, - available from . - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about this class of network cards. If you say Y, you - will be asked for your specific card in the following questions. If - you are unsure, say Y. - -AMD PCnet32 (VLB and PCI) support -CONFIG_PCNET32 - If you have a PCnet32 or PCnetPCI based network (Ethernet) card, - answer Y here and read the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called pcnet32.o. If you want to compile it as a - module, say M here and read as well - as . - -AMD 8111 (new PCI lance) support -CONFIG_AMD8111_ETH - If you have an AMD 8111-based PCI lance ethernet card, - answer Y here and read the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called amd8111e.o. If you want to compile it as a - module, say M here and read as well - as . - -Ansel Communications EISA 3200 support -CONFIG_AC3200 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ac3200.o. If you want to compile it as a - module, say M here and read as well - as . - -Mylex EISA LNE390A/LNE390B support -CONFIG_LNE390 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called lne390.o. If you want to compile it as a - module, say M here and read as well - as . - -Novell/Eagle/Microdyne NE3210 EISA support -CONFIG_NE3210 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . Note that this driver - will NOT WORK for NE3200 cards as they are completely different. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ne3210.o. If you want to compile it as a - module, say M here and read as well - as . - -Apricot Xen-II on board Ethernet -CONFIG_APRICOT - If you have a network (Ethernet) controller of this type, say Y and - read the Ethernet-HOWTO, available from - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read as well as - . The module will be - called apricot.o. - -Generic DECchip & DIGITAL EtherWORKS PCI/EISA -CONFIG_DE4X5 - This is support for the DIGITAL series of PCI/EISA Ethernet cards. - These include the DE425, DE434, DE435, DE450 and DE500 models. If - you have a network card of this type, say Y and read the - Ethernet-HOWTO, available from - . More specific - information is contained in - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called de4x5.o. If you want to compile it as a - module, say M here and read as well - as . - -DECchip Tulip (dc21x4x) PCI support -CONFIG_TULIP - This driver is developed for the SMC EtherPower series Ethernet - cards and also works with cards based on the DECchip - 21040/21041/21140 (Tulip series) chips. Some LinkSys PCI cards are - of this type. (If your card is NOT SMC EtherPower 10/100 PCI - (smc9332dst), you can also try the driver for "Generic DECchip" - cards, above. However, most people with a network card of this type - will say Y here.) Do read the Ethernet-HOWTO, available from - . More specific - information is contained in - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called tulip.o. If you want to compile it as a - module, say M here and read as well - as . - -Use PCI shared memory for NIC registers -CONFIG_TULIP_MMIO - Use PCI shared memory for the NIC registers, rather than going through - the Tulip's PIO (programmed I/O ports). Faster, but could produce - obscure bugs if your mainboard has memory controller timing issues. - If in doubt, say N. - -Digi Intl. RightSwitch SE-X support -CONFIG_DGRS - This is support for the Digi International RightSwitch series of - PCI/EISA Ethernet switch cards. These include the SE-4 and the SE-6 - models. If you have a network card of this type, say Y and read the - Ethernet-HOWTO, available from - . More specific - information is contained in . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called dgrs.o. If you want to compile it as a - module, say M here and read as well - as . - -EtherExpress Pro/100 support -CONFIG_EEPRO100 - If you have an Intel EtherExpress PRO/100 PCI network (Ethernet) - card, say Y and read the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called eepro100.o. If you want to compile it as - a module, say M here and read as - well as . - -Use PIO instead of MMIO -CONFIG_EEPRO100_PIO - This instructs the driver to use programmed I/O ports (PIO) instead - of PCI shared memory (MMIO). This can possibly solve some problems - in case your mainboard has memory consistency issues. If unsure, - say N. - -Enable Power Management -CONFIG_EEPRO100_PM - Many Intel EtherExpress PRO/100 PCI network cards are capable - of providing power management capabilities. To make use of these - capabilities, say Y. - - WARNING: This option is intended for kernel developers and testers. - It is still very experimental, with some people reporting complete - lockups. - - It is recommended to say N here. - -Myson MTD-8xx PCI Ethernet support -CONFIG_FEALNX - Say Y here to support the Mysom MTD-800 family of PCI-based Ethernet - cards. Specifications and data at - . - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called fealnx.o. - -LP486E on board Ethernet -CONFIG_LP486E - Say Y here to support the 82596-based on-board Ethernet controller - for the Panther motherboard, which is one of the two shipped in the - Intel Professional Workstation. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called lp486e.o. - -ICL EtherTeam 16i/32 support -CONFIG_ETH16I - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called eth16i.o. If you want to compile it as a - module, say M here and read as well - as . - -TI ThunderLAN support -CONFIG_TLAN - If you have a PCI Ethernet network card based on the ThunderLAN chip - which is supported by this driver, say Y and read the - Ethernet-HOWTO, available from - . - - Devices currently supported by this driver are Compaq Netelligent, - Compaq NetFlex and Olicom cards. Please read the file - for more details. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called tlan.o. If you want to compile it as a - module, say M here and read as well - as . - - Please email feedback to torben.mathiasen@compaq.com. - -VIA Rhine support -CONFIG_VIA_RHINE - If you have a VIA "rhine" based network card (Rhine-I (3043) or - Rhine-2 (VT86c100A)), say Y here. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called via-rhine.o. If you want to compile it as - a module, say M here and read as - well as . - -VIA Rhine MMIO support (EXPERIMENTAL) -CONFIG_VIA_RHINE_MMIO - This instructs the driver to use PCI shared memory (MMIO) instead of - programmed I/O ports (PIO). Enabling this gives an improvement in - processing time in parts of the driver. - - It is not known if this works reliably on all "rhine" based cards, - but it has been tested successfully on some DFE-530TX adapters. - - If unsure, say N. - -Davicom DM910x/DM980x support -CONFIG_DM9102 - This driver is for DM9102(A)/DM9132/DM9801 compatible PCI cards from - Davicom (). If you have such a network - (Ethernet) card, say Y. Some information is contained in the file - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called dmfe.o. If you want to compile it as a - module, say M here and read as well - as . - -Racal-Interlan EISA ES3210 support -CONFIG_ES3210 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called es3210.o. If you want to compile it as a - module, say M here and read as well - as . - -SMC EtherPower II -CONFIG_EPIC100 - This driver is for the SMC EtherPower II 9432 PCI Ethernet NIC, - which is based on the SMC83c17x (EPIC/100). - More specific information and updates are available from - . - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called epic100.o. - -DEC LANCE Ethernet controller support -CONFIG_DECLANCE - This driver is for the series of Ethernet controllers produced by - DEC (now Compaq) based on the AMD Lance chipset, including the - DEPCA series. (This chipset is better known via the NE2100 cards.) - -SGI Seeq Ethernet controller support -CONFIG_SGISEEQ - Say Y here if you have an Seeq based Ethernet network card. This is - used in many Silicon Graphics machines. - -Sundance Alta PCI Ethernet support -CONFIG_SUNDANCE - This driver is for the Sundance "Alta" chip. - More specific information and updates are available from - . - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called sundance.o. - -Sundance Alta memory-mapped I/O support -CONFIG_SUNDANCE_MMIO - Enable memory-mapped I/O for interaction with Sundance NIC registers. - Do NOT enable this by default, PIO (enabled when MMIO is disabled) - is known to solve bugs on certain chips. - - If unsure, say N. - -Sun3/Sun3x on-board LANCE support -CONFIG_SUN3LANCE - Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80) - featured an AMD Lance 10Mbit Ethernet controller on board; say Y - here to compile in the Linux driver for this and enable Ethernet. - General Linux information on the Sun 3 and 3x series (now - discontinued) is at - . - - If you're not building a kernel for a Sun 3, say N. - -Sun3 on-board Intel 82586 support -CONFIG_SUN3_82586 - This driver enables support for the on-board Intel 82586 based - Ethernet adapter found on Sun 3/1xx and 3/2xx motherboards. Note - that this driver does not support 82586-based adapters on additional - VME boards. - -Winbond W89c840 PCI Ethernet support -CONFIG_WINBOND_840 - This driver is for the Winbond W89c840 chip. It also works with - the TX9882 chip on the Compex RL100-ATX board. - More specific information and updates are available from - . - -Zenith Z-Note support -CONFIG_ZNET - The Zenith Z-Note notebook computer has a built-in network - (Ethernet) card, and this is the Linux driver for it. Note that the - IBM Thinkpad 300 is compatible with the Z-Note and is also supported - by this driver. Read the Ethernet-HOWTO, available from - . - -Philips SAA9730 Ethernet support -CONFIG_LAN_SAA9730 - The SAA9730 is a combined multimedia and peripheral controller used - in thin clients, Internet access terminals, and diskless - workstations. - See . - -Pocket and portable adapters -CONFIG_NET_POCKET - Cute little network (Ethernet) devices which attach to the parallel - port ("pocket adapters"), commonly used with laptops. If you have - one of those, say Y and read the Ethernet-HOWTO, available from - . - - If you want to plug a network (or some other) card into the PCMCIA - (or PC-card) slot of your laptop instead (PCMCIA is the standard for - credit card size extension cards used by all modern laptops), you - need the pcmcia-cs package (location contained in the file - ) and you can say N here. - - Laptop users should read the Linux Laptop home page at - . - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about this class of network devices. If you say Y, you - will be asked for your specific device in the following questions. - -AT-LAN-TEC/RealTek pocket adapter support -CONFIG_ATP - This is a network (Ethernet) device which attaches to your parallel - port. Read as well as the Ethernet-HOWTO, - available from , if you - want to use this. If you intend to use this driver, you should have - said N to the "Parallel printer support", because the two drivers - don't like each other. - - If you want to compile this driver as a module however ( = code - which can be inserted in and removed from the running kernel - whenever you want), say M here and read - . The module will be called atp.o. - -D-Link DE600 pocket adapter support -CONFIG_DE600 - This is a network (Ethernet) device which attaches to your parallel - port. Read as well as the - Ethernet-HOWTO, available from - , if you want to use - this. It is possible to have several devices share a single parallel - port and it is safe to compile the corresponding drivers into the - kernel. - - If you want to compile this driver as a module however ( = code - which can be inserted in and removed from the running kernel - whenever you want), say M here and read - . - The module will be called de600.o. - -D-Link DE620 pocket adapter support -CONFIG_DE620 - This is a network (Ethernet) device which attaches to your parallel - port. Read as well as the - Ethernet-HOWTO, available from - , if you want to use - this. It is possible to have several devices share a single parallel - port and it is safe to compile the corresponding drivers into the - kernel. - - If you want to compile this driver as a module however ( = code - which can be inserted in and removed from the running kernel - whenever you want), say M here and read - . - The module will be called de620.o. - -Token Ring driver support -CONFIG_TR - Token Ring is IBM's way of communication on a local network; the - rest of the world uses Ethernet. To participate on a Token Ring - network, you need a special Token ring network card. If you are - connected to such a Token Ring network and want to use your Token - Ring card under Linux, say Y here and to the driver for your - particular card below and read the Token-Ring mini-HOWTO, available - from . Most people can - say N here. - -IBM Tropic chipset based adapter support -CONFIG_IBMTR - This is support for all IBM Token Ring cards that don't use DMA. If - you have such a beast, say Y and read the Token-Ring mini-HOWTO, - available from . - - Warning: this driver will almost definitely fail if more than one - active Token Ring card is present. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ibmtr.o. If you want to compile it as a - module, say M here and read . - -IBM Olympic chipset PCI adapter support -CONFIG_IBMOL - This is support for all non-Lanstreamer IBM PCI Token Ring Cards. - Specifically this is all IBM PCI, PCI Wake On Lan, PCI II, PCI II - Wake On Lan, and PCI 100/16/4 adapters. - - If you have such an adapter, say Y and read the Token-Ring - mini-HOWTO, available from . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called olympic.o. If you want to compile it - as a module, say M here and read . - - Also read or check the - Linux Token Ring Project site for the latest information at - . - -IBM Lanstreamer chipset PCI adapter support -CONFIG_IBMLS - This is support for IBM Lanstreamer PCI Token Ring Cards. - - If you have such an adapter, say Y and read the Token-Ring - mini-HOWTO, available from . - - This driver is also available as a modules ( = code which can be - inserted in and removed from the running kernel whenever you want). - The modules will be called lanstreamer.o. If you want to compile it - as a module, say M here and read . - -Generic TMS380 Token Ring ISA/PCI/MCA/EISA adapter support -CONFIG_TMS380TR - This driver provides generic support for token ring adapters - based on the Texas Instruments TMS380 series chipsets. This - includes the SysKonnect TR4/16(+) ISA (SK-4190), SysKonnect - TR4/16(+) PCI (SK-4590), SysKonnect TR4/16 PCI (SK-4591), - Compaq 4/16 PCI, Thomas-Conrad TC4048 4/16 PCI, and several - Madge adapters. If you say Y here, you will be asked to select - which cards to support below. If you're using modules, each - class of card will be supported by a separate module. - - If you have such an adapter and would like to use it, say Y and - read the Token-Ring mini-HOWTO, available from - . - - Also read the file or - check . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called tms380tr.o. If you want to compile it - as a module, say M here and read . - -Generic TMS380 PCI support -CONFIG_TMSPCI - This tms380 module supports generic TMS380-based PCI cards. - - These cards are known to work: - - Compaq 4/16 TR PCI - - SysKonnect TR4/16 PCI (SK-4590/SK-4591) - - Thomas-Conrad TC4048 PCI 4/16 - - 3Com Token Link Velocity - - This driver is available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called tmspci.o. If you want to compile it - as a module, say M here and read . - -Generic TMS380 ISA support -CONFIG_TMSISA - This tms380 module supports generic TMS380-based ISA cards. - - These cards are known to work: - - SysKonnect TR4/16 ISA (SK-4190) - - This driver is available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called tmsisa.o. If you want to compile it - as a module, say M here and read . - -Madge Smart 16/4 PCI Mk2 support -CONFIG_ABYSS - This tms380 module supports the Madge Smart 16/4 PCI Mk2 - cards (51-02). - - This driver is available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called abyss.o. If you want to compile it - as a module, say M here and read . - -Madge Smart 16/4 Ringnode MicroChannel -CONFIG_MADGEMC - This tms380 module supports the Madge Smart 16/4 MC16 and MC32 - MicroChannel adapters. - - This driver is available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called madgemc.o. If you want to compile it - as a module, say M here and read . - -SMC ISA/MCA Token Ring adapter support -CONFIG_SMCTR - This is support for the ISA and MCA SMC Token Ring cards, - specifically SMC TokenCard Elite (8115T) and SMC TokenCard Elite/A - (8115T/A) adapters. - - If you have such an adapter and would like to use it, say Y or M and - read the Token-Ring mini-HOWTO, available from - and the file - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called smctr.o. If you want to compile it - as a module, say M here and read . - -3COM 3C359 Token Link Velocity XL PCI adapter support -CONFIG_3C359 - This is support for the 3Com PCI Velocity XL cards, specifically - the 3Com 3C359, please note this is not for the 3C339 cards, you - should use the tms380 driver instead. - - If you have such an adapter, say Y and read the Token-Ring - mini-HOWTO, available from . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will will be called 3c359.o. If you want to compile it - as a module, say M here and read Documentation/modules.txt. - - Also read the file or check the - Linux Token Ring Project site for the latest information at - - -Sun Happy Meal 10/100baseT support -CONFIG_HAPPYMEAL - This driver supports the "hme" interface present on most Ultra - systems and as an option on older Sbus systems. This driver supports - both PCI and Sbus devices. This driver also supports the "qfe" quad - 100baseT device available in both PCI and Sbus configurations. - - This support is also available as a module called sunhme.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Sun Lance support -CONFIG_SUNLANCE - This driver supports the "le" interface present on all 32-bit Sparc - systems, on some older Ultra systems and as an Sbus option. These - cards are based on the AMD Lance chipset, which is better known - via the NE2100 cards. - - This support is also available as a module called sunlance.o ( = - code which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Sun BigMAC 10/100baseT support -CONFIG_SUNBMAC - This driver supports the "be" interface available as an Sbus option. - This is Sun's older 100baseT Ethernet device. - - This support is also available as a module called sunbmac.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Sun QuadEthernet support -CONFIG_SUNQE - This driver supports the "qe" 10baseT Ethernet device, available as - an Sbus option. Note that this is not the same as Quad FastEthernet - "qfe" which is supported by the Happy Meal driver instead. - - This support is also available as a module called sunqe.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Traffic Shaper -CONFIG_SHAPER - The traffic shaper is a virtual network device that allows you to - limit the rate of outgoing data flow over some other network device. - The traffic that you want to slow down can then be routed through - these virtual devices. See - for more information. - - An alternative to this traffic shaper is the experimental - Class-Based Queueing (CBQ) scheduling support which you get if you - say Y to "QoS and/or fair queueing" above. - - To set up and configure shaper devices, you need the shapecfg - program, available from in the - shaper package. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called shaper.o. If you want to compile it as a - module, say M here and read . If - unsure, say N. - -FDDI driver support -CONFIG_FDDI - Fiber Distributed Data Interface is a high speed local area network - design; essentially a replacement for high speed Ethernet. FDDI can - run over copper or fiber. If you are connected to such a network and - want a driver for the FDDI card in your computer, say Y here (and - then also Y to the driver for your FDDI card, below). Most people - will say N. - -Digital DEFEA and DEFPA adapter support -CONFIG_DEFXX - This is support for the DIGITAL series of EISA (DEFEA) and PCI - (DEFPA) controllers which can connect you to a local FDDI network. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called defxx.o. - -SysKonnect FDDI PCI support -CONFIG_SKFP - Say Y here if you have a SysKonnect FDDI PCI adapter. - The following adapters are supported by this driver: - - SK-5521 (SK-NET FDDI-UP) - - SK-5522 (SK-NET FDDI-UP DAS) - - SK-5541 (SK-NET FDDI-FP) - - SK-5543 (SK-NET FDDI-LP) - - SK-5544 (SK-NET FDDI-LP DAS) - - SK-5821 (SK-NET FDDI-UP64) - - SK-5822 (SK-NET FDDI-UP64 DAS) - - SK-5841 (SK-NET FDDI-FP64) - - SK-5843 (SK-NET FDDI-LP64) - - SK-5844 (SK-NET FDDI-LP64 DAS) - - Netelligent 100 FDDI DAS Fibre SC - - Netelligent 100 FDDI SAS Fibre SC - - Netelligent 100 FDDI DAS UTP - - Netelligent 100 FDDI SAS UTP - - Netelligent 100 FDDI SAS Fibre MIC - - Read for information about - the driver. - - Questions concerning this driver can be addressed to: - linux@syskonnect.de - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called skfp.o. - -HIgh Performance Parallel Interface (HIPPI) support -CONFIG_HIPPI - HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and - 1600Mbit/sec dual-simplex switched or point-to-point network. HIPPI - can run over copper (25m) or fiber (300m on multi-mode or 10km on - single-mode). HIPPI networks are commonly used for clusters and to - connect to super computers. If you are connected to a HIPPI network - and have a HIPPI network card in your computer that you want to use - under Linux, say Y here (you must also remember to enable the driver - for your HIPPI card below). Most people will say N here. - -Essential RoadRunner HIPPI PCI adapter support -CONFIG_ROADRUNNER - Say Y here if this is your PCI HIPPI network card. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called rrunner.o. If you want to compile it as a - module, say M here and read . If - unsure, say N. - -Use large TX/RX rings -CONFIG_ROADRUNNER_LARGE_RINGS - If you say Y here, the RoadRunner driver will preallocate up to 2 MB - of additional memory to allow for fastest operation, both for - transmitting and receiving. This memory cannot be used by any other - kernel code or by user space programs. Say Y here only if you have - the memory. - -Acorn Ether1 support -CONFIG_ARM_ETHER1 - If you have an Acorn system with one of these (AKA25) network cards, - you should say Y to this option if you wish to use it with Linux. - -Acorn/ANT Ether3 support -CONFIG_ARM_ETHER3 - If you have an Acorn system with one of these network cards, you - should say Y to this option if you wish to use it with Linux. - -I-Cubed EtherH support -CONFIG_ARM_ETHERH - If you have an Acorn system with one of these network cards, you - should say Y to this option if you wish to use it with Linux. - -EBSA-110 Ethernet interface (AM79C961A) -CONFIG_ARM_AM79C961A - If you wish to compile a kernel for the EBSA-110, then you should - always answer Y to this. - -Support Thumb instructions -CONFIG_ARM_THUMB - Say Y if you want to have kernel support for ARM Thumb instructions, - fault handlers, and system calls. - - The Thumb instruction set is a compressed form of the standard ARM - instruction set resulting in smaller binaries at the expense of - slightly less efficient code. - - If you don't know what this all is, saying Y is a safe choice. - -Support CD-ROM drives that are not SCSI or IDE/ATAPI -CONFIG_CD_NO_IDESCSI - If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y - here, otherwise N. Read the CD-ROM-HOWTO, available from - . - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about these CD-ROM drives. If you are unsure what you - have, say Y and find out whether you have one of the following - drives. - - For each of these drivers, a file Documentation/cdrom/{driver_name} - exists. Especially in cases where you do not know exactly which kind - of drive you have you should read there. Most of these drivers use a - file drivers/cdrom/{driver_name}.h where you can define your - interface parameters and switch some internal goodies. - - All these CD-ROM drivers are also usable as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). If you want to compile them as module, say M instead of Y and - read . - - If you want to use any of these CD-ROM drivers, you also have to - answer Y or M to "ISO 9660 CD-ROM file system support" below (this - answer will get "defaulted" for you if you enable any of the Linux - CD-ROM drivers). - -Sony CDU31A/CDU33A CD-ROM support -CONFIG_CDU31A - These CD-ROM drives have a spring-pop-out caddyless drawer, and a - rectangular green LED centered beneath it. NOTE: these CD-ROM - drives will not be auto detected by the kernel at boot time; you - have to provide the interface address as an option to the kernel at - boot time as described in or fill - in your parameters into . Try "man - bootparam" or see the documentation of your boot loader (lilo or - loadlin) about how to pass options to the kernel. - - If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM - file system support" below, because that's the file system used on - CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cdu31a.o. If you want to compile it as a - module, say M here and read . - -Standard Mitsumi [no XA/Multisession] CD-ROM support -CONFIG_MCD - This is the older of the two drivers for the older Mitsumi models - LU-005, FX-001 and FX-001D. This is not the right driver for the - FX-001DE and the triple or quad speed models (all these are - IDE/ATAPI models). Please also the file - . - - With the old LU-005 model, the whole drive chassis slides out for cd - insertion. The FX-xxx models use a motorized tray type mechanism. - Note that this driver does not support XA or MultiSession CDs - (PhotoCDs). There is a new driver (next question) which can do - this. If you want that one, say N here. - - If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM - file system support" below, because that's the file system used on - CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called mcd.o. If you want to compile it as a - module, say M here and read . - -IRQ channel for Mitsumi CD-ROM -CONFIG_MCD_IRQ - This allows you to specify the default value of the IRQ used by the - driver. This setting can be overridden by passing the "mcd=" - parameter to the kernel at boot time (or at module load time if you - said M to "Standard Mitsumi CD-ROM support"). - -I/O base address for Mitsumi CD-ROM -CONFIG_MCD_BASE - This allows you to specify the default value of the I/O base address - used by the driver. This setting can be overridden by passing the - "mcd=" parameter to the kernel at boot time (or at module load time - if you said M to "Standard Mitsumi CD-ROM support"). - -Mitsumi [XA/MultiSession] CD-ROM support -CONFIG_MCDX - Use this driver if you want to be able to read XA or MultiSession - CDs (PhotoCDs) as well as ordinary CDs with your Mitsumi LU-005, - FX-001 or FX-001D CD-ROM drive. In addition, this driver uses much - less kernel memory than the old one, if that is a concern. This - driver is able to support more than one drive, but each drive needs - a separate interface card. Please read the file - . - - If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM - file system support" below, because that's the file system used on - CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called mcdx.o. If you want to compile it as a - module, say M here and read . - -Matsushita/Panasonic/Creative, Longshine, TEAC CD-ROM support -CONFIG_SBPCD - This driver supports most of the drives which use the Panasonic or - Sound Blaster interface. Please read the file - . - - The Matsushita CR-521, CR-522, CR-523, CR-562, CR-563 drives - (sometimes labeled "Creative"), the Creative Labs CD200, the - Longshine LCS-7260, the "IBM External ISA CD-ROM" (in fact a CR-56x - model), the TEAC CD-55A fall under this category. Some other - "electrically compatible" drives (Vertos, Genoa, some Funai models) - are currently not supported; for the Sanyo H94A drive currently a - separate driver (asked later) is responsible. Most drives have a - uniquely shaped faceplate, with a caddyless motorized drawer, but - without external brand markings. The older CR-52x drives have a - caddy and manual loading/eject, but still no external markings. The - driver is able to do an extended auto-probing for interface - addresses and drive types; this can help to find facts in cases you - are not sure, but can consume some time during the boot process if - none of the supported drives gets found. Once your drive got found, - you should enter the reported parameters into - and set "DISTRIBUTION 0" there. - - This driver can support up to four CD-ROM controller cards, and each - card can support up to four CD-ROM drives; if you say Y here, you - will be asked how many controller cards you have. If compiled as a - module, only one controller card (but with up to four drives) is - usable. - - If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM - file system support" below, because that's the file system used on - CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called sbpcd.o. If you want to compile it as a - module, say M here and read . - -Matsushita/Panasonic, ... second CD-ROM controller support -CONFIG_SBPCD2 - Say Y here only if you have two CD-ROM controller cards of this type - (usually only if you have more than four drives). You should enter - the parameters for the second, third and fourth interface card into - before compiling the new kernel. Read - the file . - -Matsushita/Panasonic, ... third CD-ROM controller support -CONFIG_SBPCD3 - Say Y here only if you have three CD-ROM controller cards of this - type (usually only if you have more than six drives). You should - enter the parameters for the second, third and fourth interface card - into before compiling the new kernel. - Read the file . - -Matsushita/Panasonic, ... fourth CD-ROM controller support -CONFIG_SBPCD4 - Say Y here only if you have four CD-ROM controller cards of this - type (usually only if you have more than eight drives). You should - enter the parameters for the second, third and fourth interface card - into before compiling the new kernel. - Read the file . - -Aztech/Orchid/Okano/Wearnes/TXC/CyDROM CD-ROM support -CONFIG_AZTCD - This is your driver if you have an Aztech CDA268-01A, Orchid - CD-3110, Okano or Wearnes CDD110, Conrad TXC, or CyCD-ROM CR520 or - CR540 CD-ROM drive. This driver -- just like all these CD-ROM - drivers -- is NOT for CD-ROM drives with IDE/ATAPI interfaces, such - as Aztech CDA269-031SE. Please read the file - . - - If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM - file system support" below, because that's the file system used on - CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called aztcd.o. If you want to compile it as a - module, say M here and read . - -Sony CDU535 CD-ROM support -CONFIG_CDU535 - This is the driver for the older Sony CDU-535 and CDU-531 CD-ROM - drives. Please read the file . - - If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM - file system support" below, because that's the file system used on - CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called sonycd535.o. If you want to compile it as - a module, say M here and read . - -Goldstar R420 CD-ROM support -CONFIG_GSCD - If this is your CD-ROM drive, say Y here. As described in the file - , you might have to change a setting - in the file before compiling the - kernel. Please read the file . - - If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM - file system support" below, because that's the file system used on - CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called gscd.o. If you want to compile it as a - module, say M here and read . - -Philips/LMS CM206 CD-ROM support -CONFIG_CM206 - If you have a Philips/LMS CD-ROM drive cm206 in combination with a - cm260 host adapter card, say Y here. Please also read the file - . - - If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM - file system support" below, because that's the file system used on - CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cm206.o. If you want to compile it as a - module, say M here and read . - -Optics Storage DOLPHIN 8000AT CD-ROM support -CONFIG_OPTCD - This is the driver for the 'DOLPHIN' drive with a 34-pin Sony - compatible interface. It also works with the Lasermate CR328A. If - you have one of those, say Y. This driver does not work for the - Optics Storage 8001 drive; use the IDE-ATAPI CD-ROM driver for that - one. Please read the file . - - If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM - file system support" below, because that's the file system used on - CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called optcd.o. If you want to compile it as a - module, say M here and read . - -Sanyo CDR-H94A CD-ROM support -CONFIG_SJCD - If this is your CD-ROM drive, say Y here and read the file - . You should then also say Y or M to - "ISO 9660 CD-ROM file system support" below, because that's the - file system used on CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called sjcd.o. If you want to compile it as a - module, say M here and read . - -ISP16/MAD16/Mozart soft configurable cdrom interface support -CONFIG_ISP16_CDI - These are sound cards with built-in cdrom interfaces using the OPTi - 82C928 or 82C929 chips. Say Y here to have them detected and - possibly configured at boot time. In addition, You'll have to say Y - to a driver for the particular cdrom drive you have attached to the - card. Read for details. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called isp16.o. If you want to compile it as a - module, say M here and read . - -iSeries Virtual I/O CD Support -CONFIG_VIOCD - If you are running Linux on an IBM iSeries system and you want to - read a CD drive owned by OS/400, say Y here. - -Quota support -CONFIG_QUOTA - If you say Y here, you will be able to set per user limits for disk - usage (also called disk quotas). Currently, it works only for the - ext2 file system. You need additional software in order to use quota - support (you can download sources from - ). For further details, read - the Quota mini-HOWTO, available from - . Probably the quota - support is only useful for multi user systems. If unsure, say N. - -VFS v0 quota format support -CONFIG_QFMT_V2 - This quota format allows using quotas with 32-bit UIDs/GIDs. If you - need this functionality say Y here. Note that you will need latest - quota utilities for new quota format with this kernel. - -Memory Technology Device (MTD) support -CONFIG_MTD - Memory Technology Devices are flash, RAM and similar chips, often - used for solid state file systems on embedded devices. This option - will provide the generic support for MTD drivers to register - themselves with the kernel and for potential users of MTD devices - to enumerate the devices which are present and obtain a handle on - them. It will also allow you to select individual drivers for - particular hardware and users of MTD devices. If unsure, say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - mtdcore.o - -MTD debugging support -CONFIG_MTD_DEBUG - This turns on low-level debugging for the entire MTD sub-system. - Normally, you should say 'N'. - -MTD partitioning support -CONFIG_MTD_PARTITIONS - If you have a device which needs to divide its flash chip(s) up - into multiple 'partitions', each of which appears to the user as - a separate MTD device, you require this option to be enabled. If - unsure, say 'Y'. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - mtdpart.o - - Note, however, that you don't need this option for the DiskOnChip - devices. Partitioning on NFTL 'devices' is a different - that's the - 'normal' form of partitioning used on a block device. - -RedBoot partition table parsing -CONFIG_MTD_REDBOOT_PARTS - RedBoot is a ROM monitor and bootloader which deals with multiple - 'images' in flash devices by putting a table in the last erase block - of the device, similar to a partition table, which gives the - offsets, lengths and names of all the images stored in the flash. - - If you need code which can detect and parse this table, and register - MTD 'partitions' corresponding to each image in the table, enable - this option. - - You will still need the parsing functions to be called by the driver - for your particular device. It won't happen automatically. The - SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for - example. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - redboot.o - -CONFIG_MTD_CMDLINE_PARTS - Allow generic configuration of the MTD paritition tables via the kernel - command line. Multiple flash resources are supported for hardware where - different kinds of flash memory are available. - - You will still need the parsing functions to be called by the driver - for your particular device. It won't happen automatically. The - SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for - example. - - The format for the command line is as follows: - - mtdparts=[; := :[,] - := [@offset][][ro] - := unique id used in mapping driver/device - := standard linux memsize OR "-" to denote all - remaining space - := (NAME) - - Due to the way Linux handles the command line, no spaces are - allowed in the partition definition, including mtd id's and partition - names. - - Examples: - - 1 flash resource (mtd-id "sa1100"), with 1 single writable partition: - mtdparts=sa1100:- - - Same flash, but 2 named partitions, the first one being read-only: - mtdparts=sa1100:256k(ARMboot)ro,-(root) - - If unsure, say 'N'. - -MTD concatenating support -CONFIG_MTD_CONCAT - Support for concatenating several MTD devices into a single - (virtual) one. This allows you to have -for example- a JFFS(2) - file system spanning multiple physical flash chips. If unsure, - say 'Y'. - - If compiled as a module, it will be called mtdconcat.o. - -ARM Firmware Suite flash layout / partition parsing -CONFIG_MTD_AFS_PARTS - The ARM Firmware Suite allows the user to divide flash devices into - multiple 'images'. Each such image has a header containing its name - and offset/size etc. - - If you need code which can detect and parse these tables, and - register MTD 'partitions' corresponding to each image detected, - enable this option. - - You will still need the parsing functions to be called by the driver - for your particular device. It won't happen automatically. The - 'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example. - -MTD debugging verbosity (0 = quiet, 3 = noisy) -CONFIG_MTD_DEBUG_VERBOSE - Determines the verbosity level of the MTD debugging messages. - -Direct chardevice access to MTD devices -CONFIG_MTD_CHAR - This provides a character device for each MTD device present in - the system, allowing the user to read and write directly to the - memory chips, and also use ioctl() to obtain information about - the device, or to erase parts of it. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - mtdchar.o - -Caching block device access to MTD devices -CONFIG_MTD_BLOCK - Although most flash chips have an erase size too large to be useful - as block devices, it is possible to use MTD devices which are based - on RAM chips in this manner. This block device is a user of MTD - devices performing that function. - - At the moment, it is also required for the Journalling Flash File - System(s) to obtain a handle on the MTD device when it's mounted - (although JFFS and JFFS2 don't actually use any of the functionality - of the mtdblock device). - - Later, it may be extended to perform read/erase/modify/write cycles - on flash chips to emulate a smaller block size. Needless to say, - this is very unsafe, but could be useful for file systems which are - almost never written to. - - You do not need this option for use with the DiskOnChip devices. For - those, enable NFTL support (CONFIG_NFTL) instead. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - mtdblock.o - -Readonly block device access to MTD devices -CONFIG_MTD_BLOCK_RO - This allows you to mount read-only file systems (such as cramfs) - from an MTD device, without the overhead (and danger) of the caching - driver. - - You do not need this option for use with the DiskOnChip devices. For - those, enable NFTL support (CONFIG_NFTL) instead. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - mtdblock_ro.o - -FTL (Flash Translation Layer) support -CONFIG_FTL - This provides support for the original Flash Translation Layer which - is part of the PCMCIA specification. It uses a kind of pseudo- - file system on a flash device to emulate a block device with - 512-byte sectors, on top of which you put a 'normal' file system. - - You may find that the algorithms used in this code are patented - unless you live in the Free World where software patents aren't - legal - in the USA you are only permitted to use this on PCMCIA - hardware, although under the terms of the GPL you're obviously - permitted to copy, modify and distribute the code as you wish. Just - not use it. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - ftl.o - -NFTL (NAND Flash Translation Layer) support -CONFIG_NFTL - This provides support for the NAND Flash Translation Layer which is - used on M-Systems' DiskOnChip devices. It uses a kind of pseudo- - file system on a flash device to emulate a block device with - 512-byte sectors, on top of which you put a 'normal' file system. - - You may find that the algorithms used in this code are patented - unless you live in the Free World where software patents aren't - legal - in the USA you are only permitted to use this on DiskOnChip - hardware, although under the terms of the GPL you're obviously - permitted to copy, modify and distribute the code as you wish. Just - not use it. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - nftl.o - -Write support for NFTL (EXPERIMENTAL) -CONFIG_NFTL_RW - If you're lucky, this will actually work. Don't whinge if it - doesn't. Send mail to the MTD mailing list - if you want to help to make it more - reliable. - -Detect flash chips by Common Flash Interface (CFI) probe -CONFIG_MTD_CFI - The Common Flash Interface specification was developed by Intel, - AMD and other flash manufactures that provides a universal method - for probing the capabilities of flash devices. If you wish to - support any device that is CFI-compliant, you need to enable this - option. Visit - for more information on CFI. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - cfi_probe.o - -CFI Advanced configuration options -CONFIG_MTD_CFI_ADV_OPTIONS - If you need to specify a specific endianness for access to flash - chips, or if you wish to reduce the size of the kernel by including - support for only specific arrangements of flash chips, say 'Y'. This - option does not directly affect the code, but will enable other - configuration options which allow you to do so. - - If unsure, say 'N'. - -Specific CFI Flash geometry selection -CONFIG_MTD_CFI_GEOMETRY - This option does not affect the code directly, but will enable - some other configuration options which would allow you to reduce - the size of the kernel by including support for only certain - arrangements of CFI chips. If unsure, say 'N' and all options - which are supported by the current code will be enabled. - -Support 8-bit buswidth -CONFIG_MTD_CFI_B1 - If you wish to support CFI devices on a physical bus which is - 8 bits wide, say 'Y'. - -Support 16-bit buswidth -CONFIG_MTD_CFI_B2 - If you wish to support CFI devices on a physical bus which is - 16 bits wide, say 'Y'. - -Support 32-bit buswidth -CONFIG_MTD_CFI_B4 - If you wish to support CFI devices on a physical bus which is - 32 bits wide, say 'Y'. - -CONFIG_MTD_CFI_B8 - If you wish to support CFI devices on a physical bus which is - 64 bits wide, say 'Y'. - -Support 1-chip flash interleave -CONFIG_MTD_CFI_I1 - If your flash chips are not interleaved - i.e. you only have one - flash chip addressed by each bus cycle, then say 'Y'. - -Support 2-chip flash interleave -CONFIG_MTD_CFI_I2 - If your flash chips are interleaved in pairs - i.e. you have two - flash chips addressed by each bus cycle, then say 'Y'. - -Support 4-chip flash interleave -CONFIG_MTD_CFI_I4 - If your flash chips are interleaved in fours - i.e. you have four - flash chips addressed by each bus cycle, then say 'Y'. - -CONFIG_MTD_CFI_I8 - If your flash chips are interleaved in eights - i.e. you have eight - flash chips addressed by each bus cycle, then say 'Y'. - -# Choice: mtd_data_swap -Flash cmd/query data swapping -CONFIG_MTD_CFI_NOSWAP - This option defines the way in which the CPU attempts to arrange - data bits when writing the 'magic' commands to the chips. Saying - 'NO', which is the default when CONFIG_MTD_CFI_ADV_OPTIONS isn't - enabled, means that the CPU will not do any swapping; the chips - are expected to be wired to the CPU in 'host-endian' form. - Specific arrangements are possible with the BIG_ENDIAN_BYTE and - LITTLE_ENDIAN_BYTE, if the bytes are reversed. - - If you have a LART, on which the data (and address) lines were - connected in a fashion which ensured that the nets were as short - as possible, resulting in a bit-shuffling which seems utterly - random to the untrained eye, you need the LART_ENDIAN_BYTE option. - - Yes, there really exists something sicker than PDP-endian :) - -CFI support for Intel/Sharp Extended Command Set chips -CONFIG_MTD_CFI_INTELEXT - The Common Flash Interface defines a number of different command - sets which a CFI-compliant chip may claim to implement. This code - provides support for one of those command sets, used on Intel - StrataFlash and other parts. - -CFI support for AMD/Fujitsu Standard Command Set chips -CONFIG_MTD_CFI_AMDSTD - The Common Flash Interface defines a number of different command - sets which a CFI-compliant chip may claim to implement. This code - provides support for one of those command sets, used on chips - chips including the AMD Am29LV320. - -CFI support for Intel/Sharp Standard Commands -CONFIG_MTD_CFI_INTELSTD - The Common Flash Interface defines a number of different command - sets which a CFI-compliant chip may claim to implement. This code - provides support for one of those command sets. - -pre-CFI Sharp chip support -CONFIG_MTD_SHARP - This option enables support for flash chips using Sharp-compatible - commands, including some which are not CFI-compatible and hence - cannot be used with the CONFIG_MTD_CFI_INTELxxx options. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - sharp.o - -AMD compatible flash chip support (non-CFI) -CONFIG_MTD_AMDSTD - This option enables support for flash chips using AMD-compatible - commands, including some which are not CFI-compatible and hence - cannot be used with the CONFIG_MTD_CFI_AMDSTD option. - - It also works on AMD compatible chips that do conform to CFI. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - amd_flash.o - -CONFIG_MTD_CFI_STAA - The Common Flash Interface defines a number of different command - sets which a CFI-compliant chip may claim to implement. This code - provides support for one of those command sets. - -Support for RAM chips in bus mapping -CONFIG_MTD_RAM - This option enables basic support for RAM chips accessed through - a bus mapping driver. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - map_ram.o - -Support for ROM chips in bus mapping -CONFIG_MTD_ROM - This option enables basic support for ROM chips accessed through - a bus mapping driver. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - map_rom.o - -JEDEC device support -CONFIG_MTD_JEDEC - Enable older older JEDEC flash interface devices for self - programming flash. It is commonly used in older AMD chips. It is - only called JEDEC because the JEDEC association - distributes the identification codes for the - chips. WARNING!!!! This code does not compile and is incomplete as - are the specific JEDEC devices drivers. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - jedec.o - -CFI Flash device mapped on StrongARM SA11x0 -CONFIG_MTD_SA1100 - This enables access to the flash chips on most platforms based on - the SA1100 and SA1110, including the Assabet and the Compaq iPAQ. - If you have such a board, say 'Y'. - -Support for Compaq bootldr partition tables on SA11x0 -CONFIG_MTD_SA1100_REDBOOT_PARTITIONS - Enabling this option will cause the kernel to look for a RedBoot - FIS (Flash Image System) table in the last erase block of the flash - chips detected. If you are using RedBoot on your SA11x0-based board - and want Linux to present 'partitions' matching the images which - RedBoot has listed, say 'Y'. - -Support for Compaq bootldr partition tables on SA11x0 -CONFIG_MTD_SA1100_BOOTLDR_PARTITIONS - Enabling this option will cause the kernel to look for a Compaq - bootldr partition table on the flash chips detected. If you are - using the Compaq bootldr on your SA11x0-based board and want Linux - to present 'partitions' matching the images which the bootldr has - listed, say 'Y'. - -Flash chip mapping in physical memory -CONFIG_MTD_PHYSMAP - This provides a 'mapping' driver which allows the CFI probe and - command set driver code to communicate with flash chips which - are mapped physically into the CPU's memory. You will need to - configure the physical address and size of the flash chips on - your particular board as well as the bus width. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - physmap.o - -Physical start location of flash chip mapping -CONFIG_MTD_PHYSMAP_START - This is the physical memory location at which the flash chips - are mapped on your particular target board. Refer to the - memory map which should hopefully be in the documentation for - your board. - -Physical length of flash chip mapping -CONFIG_MTD_PHYSMAP_LEN - This is the total length of the mapping of the flash chips on - your particular board. If there is space, or aliases, in the - physical memory map between the chips, this could be larger - than the total amount of flash present. Refer to the memory - map which should hopefully be in the documentation for your - board. - -Buswidth of flash in bytes -CONFIG_MTD_PHYSMAP_BUSWIDTH - This is the total width of the data bus of the flash devices - in octets. For example, if you have a data bus width of 32 - bits, you would set the bus width octet value to 4. This is - used internally by the CFI drivers. - -Flash chip mapping on Sun Microsystems boardsets -CONFIG_MTD_SUN_UFLASH - This provides a 'mapping' driver which supports the way in - which user-programmable flash chips are connected on various - Sun Microsystems boardsets. This driver will require CFI support - in the kernel, so if you did not enable CFI previously, do that now. - -Flash chip mapping on Nora -CONFIG_MTD_NORA - If you had to ask, you don't have one. Say 'N'. - -Flash chip mapping on Photron PNC-2000 -CONFIG_MTD_PNC2000 - PNC-2000 is the name of Network Camera product from PHOTRON - Ltd. in Japan. It uses CFI-compliant flash. - -Flash chip mapping on RPXlite or CLLF PPC board -CONFIG_MTD_RPXLITE - The RPXLite PowerPC board has CFI-compliant chips mapped in - a strange sparse mapping. This 'mapping' driver supports that - arrangement, allowing the CFI probe and command set driver code - to communicate with the chips on the RPXLite board. More at - . - -Flash chip mapping on AMD SC520 CDP board -CONFIG_MTD_SC520CDP - The SC520 CDP board has two banks of CFI-compliant chips and one - Dual-in-line JEDEC chip. This 'mapping' driver supports that - arrangement, implementing three MTD devices. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - sc520cdp.o - -Flash chip mapping on Arcom Control Systems SBC-MediaGX -CONFIG_MTD_SBC_GXX - This provides a driver for the on-board flash of Arcom Control - Systems' SBC-GXn family of boards, formerly known as SBC-MediaGX. - By default the flash is split into 3 partitions which are accessed - as separate MTD devices. This board utilizes Intel StrataFlash. - More info at - . - -CFI Flash device mapped on D-Box2 -CONFIG_MTD_DBOX2 - This enables access routines for the flash chips on the Nokia/Sagem - D-Box 2 board. If you have one of these boards and would like to use - the flash chips on it, say 'Y'. - -CFI Flash devices mapped on IBM Redwood -CONFIG_MTD_REDWOOD - This enables access routines for the flash chips on the IBM - Redwood board. If you have one of these boards and would like to - use the flash chips on it, say 'Y'. - - If compiled as a module, it will be called redwood.o. - -CFI Flash device mapped on the XScale IQ80310 board -CONFIG_MTD_IQ80310 - This enables access routines for the flash chips on the Intel XScale - IQ80310 evaluation board. If you have one of these boards and would - like to use the flash chips on it, say 'Y'. - -CFI Flash device mapped on AMD NetSc520 -CONFIG_MTD_NETSC520 - This enables access routines for the flash chips on the AMD NetSc520 - demonstration board. If you have one of these boards and would like - to use the flash chips on it, say 'Y'. - -Flash chip mapping on Arcom Control Systems ELAN-104NC -CONFIG_MTD_ELAN_104NC - This provides a driver for the on-board flash of the Arcom Control - System's ELAN-104NC development board. By default the flash - is split into 3 partitions which are accessed as separate MTD - devices. This board utilizes Intel StrataFlash. More info at - . - -Flash chip mapping on Compaq iPAQ/Bitsy -CONFIG_MTD_BITSY - This provides a driver for the on-board flash found in Compaq's - iPAQ Palm PC and their research prototype the Itsy. iPAQ info at - and the - Itsy . - -Flash chip mapping on Compaq iPAQ/Bitsy -CONFIG_MTD_DC21285 - This provides a driver for the flash accessed using Intel's - 21285 bridge used with Intel's StrongARM processors. More info at - . - -Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board -CONFIG_MTD_CSTM_MIPS_IXX - This provides a mapping driver for the Integrated Tecnology Express, - Inc (ITE) QED-4N-S01B eval board and the Globespan IVR Reference - Board. It provides the necessary addressing, length, buswidth, vpp - code and addition setup of the flash device for these boards. In - addition, this mapping driver can be used for other boards via - setting of the CONFIG_MTD_CSTM_MIPS_IXX_START/LEN/BUSWIDTH - parameters. This mapping will provide one mtd device using one - partition. The start address can be offset from the beginning of - flash and the len can be less than the total flash device size to - allow a window into the flash. Both CFI and JEDEC probes are - called. - -Physical start location of flash chip mapping -CONFIG_MTD_CSTM_MIPS_IXX_START - This is the physical memory location that the MTD driver will - use for the flash chips on your particular target board. - Refer to the memory map which should hopefully be in the - documentation for your board. - -Physical length of flash chip mapping -CONFIG_MTD_CSTM_MIPS_IXX_LEN - This is the total length that the MTD driver will use for the - flash chips on your particular board. Refer to the memory - map which should hopefully be in the documentation for your - board. - -Physical bus width of flash mapping in bytes -CONFIG_MTD_CSTM_MIPS_IXX_BUSWIDTH - This is the total bus width of the mapping of the flash chips - on your particular board. - -JEDEC Flash device mapped on Mixcom piggyback card -CONFIG_MTD_MIXMEM - This supports the paging arrangement for access to flash chips - on the MixCOM piggyback card, allowing the flash chip drivers - to get on with their job of driving the flash chips without - having to know about the paging. If you have one of these boards, - you probably want to enable this mapping driver. More info is at - . - -JEDEC Flash device mapped on Octagon 5066 SBC -CONFIG_MTD_OCTAGON - This provides a 'mapping' driver which supports the way in which - the flash chips are connected in the Octagon-5066 Single Board - Computer. More information on the board is available at - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - octagon-5066.o - -JEDEC Flash device mapped on Tempustech VMAX SBC301 -CONFIG_MTD_VMAX - This provides a 'mapping' driver which supports the way in which - the flash chips are connected in the Tempustech VMAX SBC301 Single - Board Computer. More information on the board is available at - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - vmax301.o - -Support for NAND flash devices -CONFIG_MTD_NAND - This enables support for accessing all type of NAND flash - devices. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - nand.o - -Support for software ECC algorithm -CONFIG_MTD_NAND_ECC - This enables software-based ECC for use with NAND flash chips. It - can detect and correct 1 bit errors per 256 byte blocks. This - should be used to increase the reliability of the data stored and - read on the device. - -Support for verify read after write -CONFIG_MTD_NAND_VERIFY_WRITE - This adds an extra check when data is written to the flash. The - NAND flash device internally checks only bits transitioning - from 1 to 0. There is a rare possibility that even though the - device thinks the write was successful, a bit could have been - flipped accidentally due to device wear, gamma rays, whatever. - Enable this if you are really paranoid. - -Support for the SPIA board -CONFIG_MTD_NAND_SPIA - If you had to ask, you don't have one. Say 'N'. - -SmartMediaCard on autronix autcpu12 board -CONFIG_MTD_NAND_AUTCPU12 - This enables the driver for the autronix autcpu12 board to - access the SmartMediaCard. - - If compiled as a module, it will be called autcpu12.o. - -Support for Cirrus Logic EBD7312 evaluation board -CONFIG_MTD_NAND_EDB7312 - This enables the driver for the Cirrus Logic EBD7312 evaluation - board to access the onboard NAND Flash. - - If compiled as a module, it will be called edb7312.o. - -M-Systems Disk-On-Chip 1000 support -CONFIG_MTD_DOC1000 - This provides an MTD device driver for the M-Systems DiskOnChip - 1000 devices, which are obsolete so you probably want to say 'N'. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - doc1000.o - -M-Systems Disk-On-Chip 2000 and Millennium support -CONFIG_MTD_DOC2000 - This provides an MTD device driver for the M-Systems DiskOnChip - 2000 and Millennium devices. Originally designed for the DiskOnChip - 2000, it also now includes support for the DiskOnChip Millennium. - If you have problems with this driver and the DiskOnChip Millennium, - you may wish to try the alternative Millennium driver below. To use - the alternative driver, you will need to undefine DOC_SINGLE_DRIVER - in the source code. - - If you use this device, you probably also want to enable the NFTL - 'NAND Flash Translation Layer' option below, which is used to - emulate a block device by using a kind of file system on the flash - chips. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - doc2000.o - -Alternative Disk-On-Chip Millennium support -CONFIG_MTD_DOC2001 - This provides an alternative MTD device driver for the M-Systems - DiskOnChip Millennium devices. Use this if you have problems with - the combined DiskOnChip 2000 and Millennium driver above. To get - the DiskOnChip probe code to load and use this driver instead of - the other one, you will need to undefine DOC_SINGLE_DRIVER near - the beginning of . - - If you use this device, you probably also want to enable the NFTL - 'NAND Flash Translation Layer' option below, which is used to - emulate a block device by using a kind of file system on the flash - chips. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - doc2001.o - -Probe for DiskOnChip devices -CONFIG_MTD_DOCPROBE - This isn't a real config option, it's derived. - -Advanced detection options for DiskOnChip -CONFIG_MTD_DOCPROBE_ADVANCED - This option allows you to specify nonstandard address at which to - probe for a DiskOnChip, or to change the detection options. You - are unlikely to need any of this unless you are using LinuxBIOS. - Say 'N'. - -Probe for 0x55 0xAA BIOS Extension Signature -CONFIG_MTD_DOCPROBE_55AA - Check for the 0x55 0xAA signature of a DiskOnChip, and do not - continue with probing if it is absent. The signature will always be - present for a DiskOnChip 2000 or a normal DiskOnChip Millennium. - Only if you have overwritten the first block of a DiskOnChip - Millennium will it be absent. Enable this option if you are using - LinuxBIOS or if you need to recover a DiskOnChip Millennium on which - you have managed to wipe the first block. - -Physical address of DiskOnChip -CONFIG_MTD_DOCPROBE_ADDRESS - By default, the probe for DiskOnChip devices will look for a - DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000. - This option allows you to specify a single address at which to probe - for the device, which is useful if you have other devices in that - range which get upset when they are probed. - - (Note that on PowerPC, the normal probe will only check at - 0xE4000000.) - - Normally, you should leave this set to zero, to allow the probe at - the normal addresses. - -Probe high addresses -CONFIG_MTD_DOCPROBE_HIGH - By default, the probe for DiskOnChip devices will look for a - DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000. - This option changes to make it probe between 0xFFFC8000 and - 0xFFFEE000. Unless you are using LinuxBIOS, this is unlikely to be - useful to you. Say 'N'. - -Ramix PMC551 PCI Mezzanine ram card support -CONFIG_MTD_PMC551 - This provides a MTD device driver for the Ramix PMC551 RAM PCI card - from Ramix Inc. . - These devices come in memory configurations from 32M - 1G. If you - have one, you probably want to enable this. - - If this driver is compiled as a module you get the ability to select - the size of the aperture window pointing into the devices memory. - What this means is that if you have a 1G card, normally the kernel - will use a 1G memory map as its view of the device. As a module, - you can select a 1M window into the memory and the driver will - "slide" the window around the PMC551's memory. This was - particularly useful on the 2.2 kernels on PPC architectures as there - was limited kernel space to deal with. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - pmc551.o - -PMC551 256M DRAM Bugfix -CONFIG_MTD_PMC551_BUGFIX - Some of Ramix's PMC551 boards with 256M configurations have invalid - column and row mux values. This option will fix them, but will - break other memory configurations. If unsure say N. - -PMC551 Debugging -CONFIG_MTD_PMC551_DEBUG - This option makes the PMC551 more verbose during its operation and - is only really useful if you are developing on this driver or - suspect a possible hardware or driver bug. If unsure say N. - -Use extra onboard system memory as MTD device -CONFIG_MTD_SLRAM - If your CPU cannot cache all of the physical memory in your machine, - you can still use it for storage or swap by using this driver to - present it to the system as a Memory Technology Device. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - slram.o - -DEC MS02-NV NVRAM module support -CONFIG_MTD_MS02NV - This is an MTD driver for the DEC's MS02-NV (54-20948-01) battery - backed-up NVRAM module. The module was originally meant as an NFS - accelerator. Say Y here if you have a DECstation 5000/2x0 or a - DECsystem 5900 equipped with such a module. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module will - be called ms02-nv.o. - -Debugging RAM test driver -CONFIG_MTD_MTDRAM - This enables a test MTD device driver which uses vmalloc() to - provide storage. You probably want to say 'N' unless you're - testing stuff. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - mtdram.o - -MTDRAM erase block size in KB -CONFIG_MTDRAM_ERASE_SIZE - This allows you to configure the size of the erase blocks in the - device emulated by the MTDRAM driver. If the MTDRAM driver is built - as a module, it is also possible to specify this as a parameter when - loading the module. - -MTDRAM device size in KB -CONFIG_MTDRAM_TOTAL_SIZE - This allows you to configure the total size of the MTD device - emulated by the MTDRAM driver. If the MTDRAM driver is built - as a module, it is also possible to specify this as a parameter when - loading the module. - -SRAM Hexadecimal Absolute position or 0 -CONFIG_MTDRAM_ABS_POS - If you have system RAM accessible by the CPU but not used by Linux - in normal operation, you can give the physical address at which the - available RAM starts, and the MTDRAM driver will use it instead of - allocating space from Linux's available memory. Otherwise, leave - this set to zero. Most people will want to leave this as zero. - -CFI Flash device mapping on the Flaga Digital Module -CONFIG_MTD_CFI_FLAGADM - Mapping for the Flaga digital module. If you don´t have one, ignore - this setting. - -Momenco Ocelot boot flash device -CONFIG_MTD_OCELOT - This enables access routines for the boot flash device and for the - NVRAM on the Momenco Ocelot board. If you have one of these boards - and would like access to either of these, say 'Y'. - -Support for absent chips in bus mapping -CONFIG_MTD_ABSENT - This option enables support for a dummy probing driver used to - allocated placeholder MTD devices on systems that have socketed - or removable media. Use of this driver as a fallback chip probe - preserves the expected registration order of MTD device nodes on - the system regardless of media presence. Device nodes created - with this driver will return -ENODEV upon access. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - map_absent.o - -MTD emulation using block device -CONFIG_MTD_BLKMTD - This driver allows a block device to appear as an MTD. It would - generally be used in the following cases: - - Using Compact Flash as an MTD, these usually present themselves to - the system as an ATA drive. - Testing MTD users (eg JFFS2) on large media and media that might - be removed during a write (using the floppy drive). - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - blkmtd.o - -Cirrus CDB89712 evaluation board mappings -CONFIG_MTD_CDB89712 - This enables access to the flash or ROM chips on the CDB89712 board. - (This board has 8 MB of Intel Strataflash, a 128 byte boot ROM, and 48 KB of - internal SRAM. This driver provides MTD devices for all three components.) - If you have such a board, say 'Y'. - -Detect non-CFI AMD/JEDEC-compatible flash chips -CONFIG_MTD_JEDECPROBE - This option enables JEDEC-style probing of flash chips which are not - compatible with the Common Flash Interface, but will use the common - CFI-targetted flash drivers for any chips which are identified which - are in fact compatible in all but the probe method. This actually - covers most AMD/Fujitsu-compatible chips, and will shortly cover also - non-CFI Intel chips (that code is in MTD CVS and should shortly be sent - for inclusion in Linus' tree) - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - jedec_probe.o - -BIOS flash chip on Intel L440GX boards -CONFIG_MTD_L440GX - Support for treating the BIOS flash chip on Intel L440GX motherboards - as an MTD device - with this you can reprogram your BIOS. - - BE VERY CAREFUL. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - l440gx.o - -28F160xx flash driver for LART -CONFIG_MTD_LART - This enables the flash driver for LART. Please note that you do - not need any mapping/chip driver for LART. This one does it all - for you, so go disable all of those if you enabled some of them (: - -Older (theoretically obsoleted now) drivers for non-CFI chips -CONFIG_MTD_OBSOLETE_CHIPS - This option does not enable any code directly, but will allow you to - select some other chip drivers which are now considered obsolete, - because the generic CONFIG_JEDEC_PROBE code above should now detect - the chips which are supported by these drivers, and allow the generic - CFI-compatible drivers to drive the chips. Say 'N' here unless you have - already tried the CONFIG_JEDEC_PROBE method and reported its failure - to the MTD mailing list at - -CFI Flash device mapped on Hitachi SolutionEngine -CONFIG_MTD_SOLUTIONENGINE - This enables access to the flash chips on the Hitachi SolutionEngine and - similar boards. Say 'Y' if you are building a kernel for such a board. - -CFI Flash device mapped on TQM8XXL PPC board -CONFIG_MTD_TQM8XXL - The TQM8xxL PowerPC board has up to two banks of CFI-compliant - chips, currently uses AMD one. This 'mapping' driver supports - that arrangement, allowing the CFI probe and command set driver - code to communicate with the chips on the TQM8xxL board. More at - . - -Darkness -CONFIG_MEMORY_SET - This is an option about which you will never be asked a question. - Therefore, I conclude that you do not exist - go away. - - There is a grue here. - -Physical memory size -CONFIG_MEMORY_SIZE - This sets the default memory size assumed by your SH kernel. It can - be overridden as normal by the 'mem=' argument on the kernel command - line. If unsure, consult your board specifications or just leave it - as 0x00400000 which was the default value before this became - configurable. - -Cache and PCI noncoherent -CONFIG_SH_PCIDMA_NONCOHERENT - Enable this option if your platform does not have a CPU cache which - remains coherent with PCI DMA. It is safest to say 'Y', although you - will see better performance if you can say 'N', because the PCI DMA - code will not have to flush the CPU's caches. If you have a PCI host - bridge integrated with your SH CPU, refer carefully to the chip specs - to see if you can say 'N' here. Otherwise, leave it as 'Y'. - -USB (Universal Serial Bus) support -CONFIG_USB - Universal Serial Bus (USB) is a specification for a serial bus - subsystem which offers higher speeds and more features than the - traditional PC serial port. The bus supplies power to peripherals - and allows for hot swapping. Up to 127 USB peripherals can be - connected to a single USB port in a tree structure. The USB port is - the root of the tree, the peripherals are the leaves and the inner - nodes are special USB devices called hubs. Many newer PC's have USB - ports and newer peripherals such as scanners, keyboards, mice, - modems, and printers support the USB protocol and can be connected - to the PC via those ports. - - Say Y here if your computer has a USB port and you want to use USB - devices. You then need to say Y to at least one of "UHCI support" - or "OHCI support" below (the type of interface that the USB hardware - in your computer provides to the operating system) and then choose - from among the drivers for USB peripherals. You may want to check - out the information provided in and - especially the links given in . - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called usbcore.o. If you want to compile it as a - module, say M here and read . - -USB verbose debug messages -CONFIG_USB_DEBUG - Say Y here if you want the USB core & hub drivers to produce a bunch - of debug messages to the system log. Select this if you are having a - problem with USB support and want to see more of what is going on. - -USB long timeout for slow-responding devices (some MGE Ellipse UPSes) -CONFIG_USB_LONG_TIMEOUT - This option makes the standard time out a bit longer. Basically, - some devices are just slow to respond, so this makes usb more - patient. There should be no harm in selecting this, but it is - needed for some MGE Ellipse UPSes. - - If you have an MGE Ellipse UPS, or you see timeouts in HID - transactions, say Y; otherwise say N. - -EHCI (USB 2.0) support -CONFIG_USB_EHCI_HCD - The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 - "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. - If your USB host controller supports USB 2.0, you will likely want to - configure this Host Controller Driver. At this writing, the primary - implementation of EHCI is a chip from NEC, widely available in add-on - PCI cards, but implementations are in the works from other vendors - including Intel and Philips. Motherboard support is appearing. - - EHCI controllers are packaged with "companion" host controllers (OHCI - or UHCI) to handle USB 1.1 devices connected to root hub ports. Ports - will connect to EHCI if it the device is high speed, otherwise they - connect to a companion controller. If you configure EHCI, you should - probably configure the OHCI (for NEC and some other vendors) USB Host - Controller Driver too. - - You may want to read . - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ehci-hcd.o. If you want to compile it as a - module, say M here and read . - -UHCI (Intel PIIX4, VIA, ...) support -CONFIG_USB_UHCI - The Universal Host Controller Interface is a standard by Intel for - accessing the USB hardware in the PC (which is also called the USB - host controller). If your USB host controller conforms to this - standard, you may want to say Y, but see below. All recent boards - with Intel PCI chipsets (like intel 430TX, 440FX, 440LX, 440BX, - i810, i820) conform to this standard. Also all VIA PCI chipsets - (like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro - 133). - - Currently there exist two drivers for UHCI host controllers: this - one and the so-called JE driver, which you can get from - "UHCI alternate (JE) support", below. You need only one. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called usb-uhci.o. If you want to compile it as a - module, say M here and read . - -UHCI (Intel PIIX4, VIA, ...) alternate (JE) support -CONFIG_USB_UHCI_ALT - The Universal Host Controller Interface is a standard by Intel for - accessing the USB hardware in the PC (which is also called the USB - host controller). If your USB host controller conforms to this - standard, you may want to say Y, but see below. All recent boards - with Intel PCI chipsets (like intel 430TX, 440FX, 440LX, 440BX, - i810, i820) conform to this standard. Also all VIA PCI chipsets - (like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro - 133). If unsure, say Y. - - Currently there exist two drivers for UHCI host controllers: this - so-called JE driver, and the one you get from "UHCI support", above. - You need only one. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called uhci.o. If you want to compile it as a - module, say M here and read . - -OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support -CONFIG_USB_OHCI - The Open Host Controller Interface is a standard by - Compaq/Microsoft/National for accessing the USB PC hardware (also - called USB host controller). If your USB host controller conforms to - this standard, say Y. The USB host controllers on most non-Intel - architectures and on several x86 compatibles with non-Intel chipsets - -- like SiS (aktual 610, 610 and so on) or ALi (ALi IV, ALi V, - Aladdin Pro..) -- conform to this standard. - - You may want to read . - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called usb-ohci.o. If you want to compile it - as a module, say M here and read . - -SL811HS (x86, StrongARM) support -CONFIG_USB_SL811HS - Embedded Open Host Controller SL811HS from CYPRESS SEMICONDUCTOR INC. - - - Board USB1104 in i386 architecture with PC/104-bus. - - - - StrongARM is currently not testet and not for PC/104-bus! - StrongARM need a special hardware with Chip Select directly from CPU. - See also SL811HS_ALT. - -SL811HS_ALT (x86, StrongARM) support -CONFIG_USB_SL811HS_ALT - Embedded Open Host Controller SL811HS from CYPRESS SEMICONDUCTOR INC. - Alternate with isochornous mode and better interrupt handling. - See also SL811HS. - -USB Human Interface Device (full HID) support -CONFIG_USB_HID - Say Y here if you want full HID support to connect keyboards, - mice, joysticks, graphic tablets, or any other HID based devices - to your computer via USB. You also need to select HID Input layer - support (below) if you want to use keyboards, mice, joysticks and - the like. - - You can't use this driver and the HIDBP (Boot Protocol) keyboard - and mouse drivers at the same time. More information is available: - . - - If unsure, say Y. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called hid.o. If you want to compile it as a - module, say M here and read . - -USB HID Input layer support -CONFIG_USB_HIDINPUT - Say Y here if you want to use a USB keyboard, mouse or joystick, - or any other HID input device. You also need Input layer support, - (CONFIG_INPUT) which you select under "Input core support". - - If unsure, say Y. - -/dev/usb/hiddev raw HID device support -CONFIG_USB_HIDDEV - Say Y here if you want to support HID devices (from the USB - specification standpoint) that aren't strictly user interface - devices, like monitor controls and Uninterruptable Power Supplies. - - This module supports these devices separately using a separate - event interface on /dev/usb/hiddevX (char 180:96 to 180:111). - This driver requires CONFIG_USB_HID. - - If unsure, say Y. - -USB HIDBP Keyboard (basic) support -CONFIG_USB_KBD - Say Y here only if you are absolutely sure that you don't want - to use the generic HID driver for your USB keyboard and prefer - to use the keyboard in its limited Boot Protocol mode instead. - - This is almost certainly not what you want. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called usbkbd.o. If you want to compile it as a - module, say M here and read . - - If even remotely unsure, say N. - -USB HIDBP Mouse (basic) support -CONFIG_USB_MOUSE - Say Y here only if you are absolutely sure that you don't want - to use the generic HID driver for your USB mouse and prefer - to use the mouse in its limited Boot Protocol mode instead. - - This is almost certainly not what you want. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called usbmouse.o. If you want to compile it as - a module, say M here and read . - - If even remotely unsure, say N. - -Wacom Intuos/Graphire tablet support -CONFIG_USB_WACOM - Say Y here if you want to use the USB version of the Wacom Intuos - or Graphire tablet. Make sure to say Y to "Mouse support" - (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" - (CONFIG_INPUT_EVDEV) as well. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called wacom.o. If you want to compile it as a - module, say M here and read . - -Griffin Technology PowerMate support -CONFIG_USB_POWERMATE - Say Y here if you want to use the Griffin Technology, Inc. USB - PowerMate device. This device is an aluminum dial which can - measure clockwise and anticlockwise rotation. The dial also - acts as a pushbutton. The base contains an LED which can be - instructed to pulse or to switch to a particular intensity. - - You can download userspace tools from http://sowerbutts.com/powermate/ - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called powermate.o. If you want to compile it as a - module, say M here and read . - -Aiptek HyperPen tablet support -CONFIG_USB_AIPTEK - Say Y here if you want to use the USB version of the Aiptek HyperPen - Digital Tablet (models 4000U, 5000U, 6000U, 8000U, and 12000U.) - Make sure to say Y to "Mouse support" (CONFIG_INPUT_MOUSEDEV) and/or - "Event interface support" (CONFIG_INPUT_EVDEV) as well. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called aiptek.o. If you want to compile it as a - module, say M here and read . - -Use input layer for ADB devices -CONFIG_INPUT_ADBHID - Say Y here if you want to have ADB (Apple Desktop Bus) HID devices - such as keyboards, mice, joysticks, or graphic tablets handled by - the input layer. If you say Y here, make sure to say Y to the - corresponding drivers "Keyboard support" (CONFIG_INPUT_KEYBDEV), - "Mouse Support" (CONFIG_INPUT_MOUSEDEV) and "Event interface - support" (CONFIG_INPUT_EVDEV) as well. - - If you say N here, you still have the option of using the old ADB - keyboard and mouse drivers. - - If unsure, say Y. - -HP OB600 C/CT Pop-Up Mouse -CONFIG_OBMOUSE - Only add this driver if you have an Omnibook 600C or 600CT laptop. - This driver has no probe routine and must assume ports 0x238-23b - belong to the Pop-Up mouse. Depends on CONFIG_INPUT_MOUSEDEV. - - Best is to use a module and load the obmouse driver at runtime. - Say M here and read . - - -Input core support -CONFIG_INPUT - Say Y here if you want to enable any of the following options for - USB Human Interface Device (HID) support. - - Say Y here if you want to enable any of the USB HID options in the - USB support section which require Input core support. - - Otherwise, say N. - -Keyboard support -CONFIG_INPUT_KEYBDEV - Say Y here if you want your USB HID keyboard (or an ADB keyboard - handled by the input layer) to be able to serve as a system - keyboard. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called keybdev.o. If you want to compile it as a - module, say M here and read . - -Mouse support -CONFIG_INPUT_MOUSEDEV - Say Y here if you want your USB HID mouse (or ADB mouse handled by - the input layer) to be accessible as char devices 13:32+ - - /dev/input/mouseX and 13:63 - /dev/input/mice as an emulated ImPS/2 - mouse. That way, all user space programs will be able to use your - mouse. - - If unsure, say Y. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called mousedev.o. If you want to compile it as - a module, say M here and read . - -Horizontal screen resolution -CONFIG_INPUT_MOUSEDEV_SCREEN_X - If you're using a digitizer, or a graphic tablet, and want to use - it as a mouse then the mousedev driver needs to know the X window - screen resolution you are using to correctly scale the data. If - you're not using a digitizer, this value is ignored. - -Vertical screen resolution -CONFIG_INPUT_MOUSEDEV_SCREEN_Y - If you're using a digitizer, or a graphic tablet, and want to use - it as a mouse then the mousedev driver needs to know the X window - screen resolution you are using to correctly scale the data. If - you're not using a digitizer, this value is ignored. - -Joystick support -CONFIG_INPUT_JOYDEV - Say Y here if you want your USB HID joystick or gamepad to be - accessible as char device 13:0+ - /dev/input/jsX device. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called joydev.o. If you want to compile it as a - module, say M here and read . - -Event interface support -CONFIG_INPUT_EVDEV - Say Y here if you want your USB or ADB HID device events be - accessible under char device 13:64+ - /dev/input/eventX in a generic - way. This is the future ... - -CONFIG_INPUT_UINPUT - Say Y here if you want to support user level drivers for input - subsystem accessible under char device 10:223 - /dev/input/uinput. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called uinput.o. If you want to compile it as a - module, say M here and read . - -USB Scanner support -CONFIG_USB_SCANNER - Say Y here if you want to connect a USB scanner to your computer's - USB port. Please read for more - information. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scanner.o. If you want to compile it as - a module, say M here and read . - -HP 5300C scanner support -CONFIG_USB_HP5300 - Say Y here if you want to connect a HP5300C scanner to your - computer's USB port. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called hp5300.o. If you want to compile it as - a module, say M here and read . - -USB Audio support -CONFIG_USB_AUDIO - Say Y here if you want to connect USB audio equipment such as - speakers to your computer's USB port. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called audio.o. If you want to compile it as a - module, say M here and read . - -EMI 2|6 USB Audio interface support -CONFIG_USB_EMI26 - This driver loads firmware to Emagic EMI 2|6 low latency USB - Audio interface. - - After firmware load the device is handled with standard linux - USB Audio driver. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called audio.o. If you want to compile it as a - module, say M here and read . - -USB Modem (CDC ACM) support -CONFIG_USB_ACM - This driver supports USB modems and ISDN adapters which support the - Communication Device Class Abstract Control Model interface. - Please read for details. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called acm.o. If you want to compile it as a - module, say M here and read . - -USB serial converter support -CONFIG_USB_SERIAL - Say Y here if you have a USB device that provides normal serial - ports, or acts like a serial device, and you want to connect it to - your USB bus. - - Please read for more - information on the specifics of the different devices that are - supported, and on how to use them. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called usbserial.o. If you want to compile it - as a module, say M here and read . - -USB Generic Serial Driver -CONFIG_USB_SERIAL_GENERIC - Say Y here if you want to use the generic USB serial driver. Please - read for more information on - using this driver. It is recommended that the "USB Serial converter - support" be compiled as a module for this driver to be used - properly. - -USB ConnectTech WhiteHEAT Serial Driver -CONFIG_USB_SERIAL_WHITEHEAT - Say Y here if you want to use a ConnectTech WhiteHEAT 4 port - USB to serial converter device. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called whiteheat.o. If you want to compile it as - a module, say M here and read . - -USB Handspring Visor Driver -CONFIG_USB_SERIAL_VISOR - Say Y here if you want to connect to your HandSpring Visor, Palm - m500 or m505 through its USB docking station. See - for more information on using this - driver. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called visor.o. If you want to compile it as a - module, say M here and read . - -USB PocketPC PDA Driver -CONFIG_USB_SERIAL_IPAQ - Say Y here if you want to connect to your Compaq iPAQ, HP Jornada, - or any other PDA running Windows CE 3.0 or PocketPC 2002 using a USB - cradle/cable. For information on using the driver, - read . - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ipaq.o. If you want to compile it as a - module, say M here and read . - -USB IR Dongle Serial Driver -CONFIG_USB_SERIAL_IR - Say Y here if you want to enable simple serial support for USB IrDA - devices. This is useful if you do not want to use the full IrDA - stack. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ir-usb.o. If you want to compile it as a - module, say M here and read . - -USB Belkin and Paracom Single Port Serial Driver -CONFIG_USB_SERIAL_BELKIN - Say Y here if you want to use a Belkin USB Serial single port - adaptor (F5U103 is one of the model numbers) or the Peracom single - port USB to serial adapter. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called belkin_sa.o. If you want to compile it as - a module, say M here and read . - -USB FTDI Single Port Serial Driver -CONFIG_USB_SERIAL_FTDI_SIO - Say Y here if you want to use a FTDI SIO single port USB to serial - converter device. The implementation I have is called the USC-1000. - This driver has also be tested with the 245 and 232 devices. - - See for more - information on this driver and the device. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ftdi_sio.o. If you want to compile it as - a module, say M here and read . - -USB Keyspan PDA Single Port Serial Driver -CONFIG_USB_SERIAL_KEYSPAN_PDA - Say Y here if you want to use a Keyspan PDA single port USB to - serial converter device. This driver makes use of firmware - developed from scratch by Brian Warner. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called keyspan_pda.o. If you want to compile it - as a module, say M here and read . - -USB Xircom / Entregra Single Port Serial Driver -CONFIG_USB_SERIAL_XIRCOM - Say Y here if you want to use a Xircom or Entregra single port USB to - serial converter device. This driver makes use of firmware - developed from scratch by Brian Warner. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called keyspan_pda.o. If you want to compile it - as a module, say M here and read . - -USB Keyspan USA-xxx Serial Driver -CONFIG_USB_SERIAL_KEYSPAN - Say Y here if you want to use Keyspan USB to serial converter - devices. This driver makes use of Keyspan's official firmware - and was developed with their support. You must also include - firmware to support your particular device(s). - - See for more information. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called keyspan.o. If you want to compile it as a - module, say M here and read . - -USB Keyspan USA-28 Firmware -CONFIG_USB_SERIAL_KEYSPAN_USA28 - Say Y here to include firmware for the USA-28 converter. - -USB Keyspan USA-28X Firmware -CONFIG_USB_SERIAL_KEYSPAN_USA28X - Say Y here to include firmware for the USA-28X converter. - Be sure you have a USA-28X, there are also 28XA and 28XB - models, the label underneath has the actual part number. - -USB Keyspan USA-28XA Firmware -CONFIG_USB_SERIAL_KEYSPAN_USA28XA - Say Y here to include firmware for the USA-28XA converter. - Be sure you have a USA-28XA, there are also 28X and 28XB - models, the label underneath has the actual part number. - -USB Keyspan USA-28XB Firmware -CONFIG_USB_SERIAL_KEYSPAN_USA28XB - Say Y here to include firmware for the USA-28XB converter. - Be sure you have a USA-28XB, there are also 28X and 28XA - models, the label underneath has the actual part number. - -USB Keyspan USA-19 Firmware -CONFIG_USB_SERIAL_KEYSPAN_USA19 - Say Y here to include firmware for the USA-19 converter. - -USB Keyspan USA-18X Firmware -CONFIG_USB_SERIAL_KEYSPAN_USA18X - Say Y here to include firmware for the USA-18X converter. - -USB Keyspan USA-19W Firmware -CONFIG_USB_SERIAL_KEYSPAN_USA19W - Say Y here to include firmware for the USA-19W converter. - -USB Keyspan USA-19QW Firmware -CONFIG_USB_SERIAL_KEYSPAN_USA19QW - Say Y here to include firmware for the USA-19QW converter. - -USB Keyspan USA-19QI Firmware -CONFIG_USB_SERIAL_KEYSPAN_USA19QI - Say Y here to include firmware for the USA-19QI converter. - -USB Keyspan USA-49W Firmware -CONFIG_USB_SERIAL_KEYSPAN_USA49W - Say Y here to include firmware for the USA-49W converter. - -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC - Say Y here to include firmware for the USA-49WLC converter. - -USB ZyXEL omni.net LCD Plus Driver -CONFIG_USB_SERIAL_OMNINET - Say Y here if you want to use a ZyXEL omni.net LCD ISDN TA. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called omninet.o. If you want to compile it as a - module, say M here and read . - -USB Digi International AccelePort USB Serial Driver -CONFIG_USB_SERIAL_DIGI_ACCELEPORT - Say Y here if you want to use Digi AccelePort USB 2 or 4 devices, - 2 port (plus parallel port) and 4 port USB serial converters. The - parallel port on the USB 2 appears as a third serial port on Linux. - The Digi Acceleport USB 8 is not yet supported by this driver. - - This driver works under SMP with the usb-uhci driver. It does not - work under SMP with the uhci driver. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called digi_acceleport.o. If you want to compile - it as a module, say M here and read - . - -USB Empeg empeg-car Mark I/II Driver -CONFIG_USB_SERIAL_EMPEG - Say Y here if you want to connect to your Empeg empeg-car Mark I/II - mp3 player via USB. The driver uses a single ttyUSB{0,1,2,...} - device node. See for more - tidbits of information. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called empeg.o. If you want to compile it as a - module, say M here and read . - -USB MCT Single Port Serial Driver -CONFIG_USB_SERIAL_MCT_U232 - Say Y here if you want to use a USB Serial single port adapter from - Magic Control Technology Corp. (U232 is one of the model numbers). - - This driver also works with Sitecom U232-P25 and D-Link DU-H3SP USB - BAY devices. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called mct_u232.o. If you want to compile it as - a module, say M here and read . - -USB Prolific 2303 Single Port Serial Driver -CONFIG_USB_SERIAL_PL2303 - Say Y here if you want to use the PL2303 USB Serial single port - adapter from Prolific. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called pl2303.o. If you want to compile it as - a module, say M here and read . - -USB KOBIL chipcard reader -CONFIG_USB_SERIAL_KOBIL_SCT - Say Y here if you want to use one of the following KOBIL USB chipcard - readers: TWIN, KAAN Standard Plus, SecOVID Reader Plus, B1 PRO, KAAN PRO - - Note that you need a current CT-API. - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called kobil_sct.o. If you want to compile it as - a module, say M here and read . - -USB REINER SCT cyberJack pinpad/e-com chipcard reader -CONFIG_USB_SERIAL_CYBERJACK - Say Y here if you want to use a cyberJack pinpad/e-com USB chipcard - reader. This is an interface to ISO 7816 compatible contactbased - chipcards, e.g. GSM SIMs. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cyberjack.o. If you want to compile it as - a module, say M here and read . - - If unsure, say N. - -USB Edgeport Serial Driver -CONFIG_USB_SERIAL_EDGEPORT - Say Y here if you want to use any of the following devices from - Inside Out Networks (Digi): - Edgeport/4 - Rapidport/4 - Edgeport/4t - Edgeport/2 - Edgeport/4i - Edgeport/2i - Edgeport/421 - Edgeport/21 - Edgeport/8 - Edgeport/8 Dual - Edgeport/2D8 - Edgeport/4D8 - Edgeport/8i - Edgeport/2 DIN - Edgeport/4 DIN - Edgeport/16 Dual - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called io_edgeport.o. If you want to compile it - as a module, say M here and read . - -USB PalmConnect (and other KL5KUSB105-based) Single Port Serial Driver -CONFIG_USB_SERIAL_KLSI - Say Y here if you want to use a KL5KUSB105 - based single port - serial adapter. The most widely known -- and currently the only - tested -- device in this category is the PalmConnect USB Serial - adapter sold by Palm Inc. for use with their Palm III and Palm V - series PDAs. - - Please read for more - information. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called kl5kusb105.o. If you want to compile it as - a module, say M here and read . - -USB Serial Converter verbose debug -CONFIG_USB_SERIAL_DEBUG - Say Y here if you want verbose debug messages from the USB Serial - Drivers sent to the kernel debug log. - -USB Printer support -CONFIG_USB_PRINTER - Say Y here if you want to connect a USB printer to your computer's - USB port. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called printer.o. If you want to compile it as a - module, say M here and read . - -USB IBM (Xirlink) C-It Camera support -CONFIG_USB_IBMCAM - Say Y here if you want to connect a IBM "C-It" camera, also known as - "Xirlink PC Camera" to your computer's USB port. For more - information, read . - - This driver uses the Video For Linux API. You must enable - (Y or M in config) Video For Linux (under Character Devices) - to use this driver. Information on this API and pointers to - "v4l" programs may be found on the WWW at - . - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ibmcam.o. If you want to compile it as a - module, say M here and read . This - camera has several configuration options which can be specified when - you load the module. Read to - learn more. - -CONFIG_USB_KONICAWC - Say Y here if you want support for webcams based on a Konica - chipset. This is known to work with the Intel YC76 webcam. - - This driver uses the Video For Linux API. You must enable - (Y or M in config) Video For Linux (under Character Devices) - to use this driver. Information on this API and pointers to - "v4l" programs may be found on the WWW at - . - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called konicawc.o. If you want to compile it as - a module, say M here and read . - -USB OV511 Camera support -CONFIG_USB_OV511 - Say Y here if you want to connect this type of camera to your - computer's USB port. See for more - information and for a list of supported cameras. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" (under Character Devices) to use this driver. - Information on this API and pointers to "v4l" programs may be found - on the WWW at . - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ov511.o. If you want to compile it as a - module, say M here and read . - -USB W996[87]CF Camera support -CONFIG_USB_W9968CF - Say Y here if you want support for cameras based on - Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. - - This driver has an optional plugin, which is distributed as a - separate module only (released under GPL). It contains code that - allows you to use higher resolutions and framerates, and cannot - be included in the official Linux kernel for performance purposes. - At the moment the driver needs a third-party module for the CMOS - sensors, which is available on internet: it is recommended to read - for more informations and for - a list of supported cameras. - - This driver uses the Video For Linux and the I2C APIs. - You must say Y or M to both "Video For Linux" and "I2C Support" - to use this driver. Information on this API and pointers to "v4l" - programs may be found on the WWW at - . - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called w9968cf.o. If you want to compile it as a - module, say M here and read . - -USB Communication Class Ethernet device support -CONFIG_USB_CDCETHER - This driver supports devices conforming to the Communication Device - Class Ethernet Control Model. This is used in some cable modems. - For more details on the specification, get the Communication Device - Class specification from . - - This driver should work with the following devices: - * Ericsson PipeRider (all variants) - * Motorola (DM100 and SB4100) - * Broadcom Cable Modem (reference design) - * Toshiba PCX1100U and possibly other cable modems - * Sharp Zaurus SL-5000D - - The device creates a network device (ethX, where X depends on what - other networking devices you have in use), as for a normal PCI - or ISA based ethernet network card. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called CDCEther.o. If you want to compile it as - a module, say M here and read . - -NetChip 1080-based USB Host-to-Host Link -CONFIG_USB_NET1080 - The NetChip 1080 is a USB 1.1 host controller. NetChip has a web - site with technical information at . - -Philips webcam support -CONFIG_USB_PWC - Say Y or M here if you want to use one of these Philips USB webcams: - PCA645, PCA646, PCVC675, PCVC680, PCVC690, PCVC730, PCVC740, or - the Askey VC010. The PCA635, PCVC665 and PCVC720 are not supported - by this driver and never will be. - - This driver has an optional plugin, which is distributed as a binary - module only. It contains code that allow you to use higher - resolutions and framerates but may not be distributed as source. - But even without this plugin you can these cams for most - applications. - - See for more information and - installation instructions. - - The built-in microphone is enabled by selecting USB Audio support. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" (under Character Devices) to use this driver. - Information on this API and pointers to "v4l" programs may be found - on the WWW at . - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called pwc.o. If you want to compile it as a - module, say M here and read . - -USB SE401 Camera support -CONFIG_USB_SE401 - Say Y here if you want to connect this type of camera to your - computer's USB port. See for more - information and for a list of supported cameras. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" (under Multimedia Devices) to use this driver. - Information on this API and pointers to "v4l" programs may be found - on the WWW at . - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called se401.o. If you want to compile it as a - module, say M here and read . - -USB STV680 (Pencam) Camera support -CONFIG_USB_STV680 - Say Y here if you want to connect this type of camera to your - computer's USB port. This includes the Pencam line of cameras. - See for more information and for - a list of supported cameras. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" (under Multimedia Devices) to use this driver. - Information on this API and pointers to "v4l" programs may be found - on the WWW at . - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called stv680.o. If you want to compile it as a - module, say M here and read . - -Vicam -CONFIG_USB_VICAM - Say Y here if you have 3com homeconnect camera (vicam). - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" (under Multimedia Devices) to use this driver. - Information on this API and pointers to "v4l" programs may be found - on the WWW at . - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called vicam.o. If you want to compile it as a - module, say M here and read . - - -Pegasus/Pegasus II based USB-Ethernet device support -CONFIG_USB_PEGASUS - Say Y here if you know you have Pegasus or Pegasus-II based adapter. - If in doubt then look at linux/drivers/usb/pegasus.h for the complete - list of supported devices. - If your particular adapter is not in the list and you are _sure_ it - is Pegasus or Pegasus-II based then send me (petkan@users.sourceforge.net) - vendor and device IDs. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called pegasus.o. If you want to compile it as a - module, say M here and read . - -Realtek RTL8150 based USB-Ethernet device support -CONFIG_USB_RTL8150 - Say Y here if you have RTL8150 based usb-ethernet adapter. - Send me (petkan@users.sourceforge.net) any comments you may have. - You can also check for updates at - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called rtl8150.o. If you want to compile it as a - module, say M here and read . - -USB KLSI KL5USB101-based Ethernet device support -CONFIG_USB_KAWETH - Say Y here if you want to use one of the following 10Mbps only - USB Ethernet adapters based on the KLSI KL5KUSB101B chipset: - 3Com 3C19250 - ADS USB-10BT - ATEN USB Ethernet - ASANTE USB To Ethernet Adapter - AOX Endpoints USB Ethernet - Correga K.K. - D-Link DSB-650C and DU-E10 - Entrega / Portgear E45 - I-O DATA USB-ET/T - Jaton USB Ethernet Device Adapter - Kingston Technology USB Ethernet Adapter - Linksys USB10T - Mobility USB-Ethernet Adapter - NetGear EA-101 - Peracom Enet and Enet2 - Portsmith Express Ethernet Adapter - Shark Pocket Adapter - SMC 2202USB - Sony Vaio port extender - - This driver is likely to work with most 10Mbps only USB Ethernet - adapters, including some "no brand" devices. It does NOT work on - SmartBridges smartNIC or on Belkin F5U111 devices - you should use - the CATC NetMate driver for those. If you are not sure which one - you need, select both, and the correct one should be selected for - you. - - This driver makes the adapter appear as a normal Ethernet interface, - typically on eth0, if it is the only ethernet device, or perhaps on - eth1, if you have a PCI or ISA ethernet card installed. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called kaweth.o. If you want to compile it as a - module, say M here and read . - -USB CATC NetMate-based Ethernet device support -CONFIG_USB_CATC - Say Y if you want to use one of the following 10Mbps USB Ethernet - device based on the EL1210A chip. Supported devices are: - Belkin F5U011 - Belkin F5U111 - CATC NetMate - CATC NetMate II - smartBridges smartNIC - - This driver makes the adapter appear as a normal Ethernet interface, - typically on eth0, if it is the only ethernet device, or perhaps on - eth1, if you have a PCI or ISA ethernet card installed. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called catc.o. If you want to compile it as a - module, say M here and read . - -USB Kodak DC-2xx Camera support -CONFIG_USB_DC2XX - Say Y here if you want to connect this type of still camera to your - computer's USB port. See for - more information; some non-Kodak cameras may also work with this - driver, given application support (such as ). - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called dc2xx.o. If you want to compile it as a - module, say M here and read . - -USB Mustek MDC800 Digital Camera support -CONFIG_USB_MDC800 - Say Y here if you want to connect this type of still camera to - your computer's USB port. This driver can be used with gphoto 0.4.3 - and higher (look at ). - To use it create a device node with "mknod /dev/mustek c 180 32" and - configure it in your software. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called mdc800.o. If you want to compile it as a - module, say M here and read . - -USB Mass Storage support -CONFIG_USB_STORAGE - Say Y here if you want to connect USB mass storage devices to your - computer's USB port. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called usb-storage.o. If you want to compile it - as a module, say M here and read . - -USB Mass Storage verbose debug -CONFIG_USB_STORAGE_DEBUG - Say Y here in order to have the USB Mass Storage code generate - verbose debugging messages. - -ISD-200 USB/ATA Bridge support -CONFIG_USB_STORAGE_ISD200 - Say Y here if you want to use USB Mass Store devices based - on the In-Systems Design ISD-200 USB/ATA bridge. - - Some of the products that use this chip are: - - - Archos Jukebox 6000 - - ISD SmartCable for Storage - - Taiwan Skymaster CD530U/DEL-0241 IDE bridge - - Sony CRX10U CD-R/RW drive - - CyQ've CQ8060A CDRW drive - - Planex eXtreme Drive RX-25HU USB-IDE cable (not model RX-25U) - -USS720 parport driver -CONFIG_USB_USS720 - This driver is for USB parallel port adapters that use the Lucent - Technologies USS-720 chip. These cables are plugged into your USB - port and provide USB compatibility to peripherals designed with - parallel port interfaces. - - The chip has two modes: automatic mode and manual mode. In automatic - mode, it looks to the computer like a standard USB printer. Only - printers may be connected to the USS-720 in this mode. The generic - USB printer driver ("USB Printer support", above) may be used in - that mode, and you can say N here if you want to use the chip only - in this mode. - - Manual mode is not limited to printers, any parallel port - device should work. This driver utilizes manual mode. - Note however that some operations are three orders of magnitude - slower than on a PCI/ISA Parallel Port, so timing critical - applications might not work. - - Say Y here if you own an USS-720 USB->Parport cable and intend to - connect anything other than a printer to it. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called uss720.o. If you want to compile it as a - module, say M here and read . - -USB device file system -CONFIG_USB_DEVICEFS - If you say Y here (and to "/proc file system support" in the "File - systems section, above), you will get a file /proc/bus/usb/devices - which lists the devices currently connected to your USB bus or - busses, a file /proc/bus/usb/drivers which lists the USB kernel - client drivers currently loaded, and for every connected device a - file named "/proc/bus/usb/xxx/yyy", where xxx is the bus number and - yyy the device number; the latter files can be used by user space - programs to talk directly to the device. These files are "virtual", - meaning they are generated on the fly and not stored on the hard - drive. - - You may need to mount the usbdevfs file system to see the files, use - mount -t usbdevfs none /proc/bus/usb - - For the format of the various /proc/bus/usb/ files, please read - . - - Please note that this code is completely unrelated to devfs, the - "/dev file system support". - - Most users want to say Y here. - -Enforce USB bandwidth allocation -CONFIG_USB_BANDWIDTH - If you say Y here, the USB subsystem enforces USB bandwidth - allocation and will prevent some device opens from succeeding - if they would cause USB bandwidth usage to go above 90% of - the bus bandwidth. - - If you say N here, these conditions will cause warning messages - about USB bandwidth usage to be logged and some devices or - drivers may not work correctly. - -DABUSB driver -CONFIG_USB_DABUSB - A Digital Audio Broadcasting (DAB) Receiver for USB and Linux - brought to you by the DAB-Team (). This - driver can be taken as an example for URB-based bulk, control, and - isochronous transactions. URB's are explained in - . - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called dabusb.o. If you want to compile it as a - module, say M here and read . - -Host-to-Host USB networking -CONFIG_USB_USBNET - This driver supports network links over USB with USB "Network" - or "data transfer" cables, often used to network laptops to PCs. - Such cables have chips from suppliers such as Belkin/eTEK, GeneSys - (GeneLink), NetChip and Prolific. Intelligent USB devices could also - use this approach to provide Internet access, using standard USB - cabling. You can find these chips also on some motherboards with - USB PC2PC support. - - These links will have names like "usb0", "usb1", etc. They act - like two-node Ethernets, so you can use 802.1d Ethernet Bridging - (CONFIG_BRIDGE) to simplify your network routing. - - This code is also available as a kernel module (code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called usbnet.o. If you want to compile it as a - module, say M here and read . - -Freecom USB/ATAPI Bridge support -CONFIG_USB_STORAGE_FREECOM - Support for the Freecom USB to IDE/ATAPI adaptor. - Freecom has a web page at . - -Microtech CompactFlash/SmartMedia reader -CONFIG_USB_STORAGE_DPCM - Say Y here to support the Microtech ZiO! CompactFlash/SmartMedia - reader, details at . - This driver treats the flash card as a removable storage device. - -SanDisk SDDR-09 (and other SmartMedia) support -CONFIG_USB_STORAGE_SDDR09 - Say Y here to include additional code to support the Sandisk SDDR-09 - SmartMedia reader in the USB Mass Storage driver. - -SanDisk SDDR-55 SmartMedia support -CONFIG_USB_STORAGE_SDDR55 - Say Y here to include additional code to support the Sandisk SDDR-55 - SmartMedia reader in the USB Mass Storage driver. - -USB Diamond Rio500 support -CONFIG_USB_RIO500 - Say Y here if you want to connect a USB Rio500 mp3 player to your - computer's USB port. Please read - for more information. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called rio500.o. If you want to compile it as - a module, say M here and read . - -Auerswald device support -CONFIG_USB_AUERSWALD - Say Y here if you want to connect an Auerswald USB ISDN Device - to your computer's USB port. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called auerswald.o. If you want to compile it as - a module, say M here and read - -USB Auerswald ISDN modem support -CONFIG_USB_AUERISDN - Say Y here if you want to enable the ISDN modem option - of your Auerswald ISDN devices. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called auerswald.o. If you want to compile it as - a module, say M here and read - -CONFIG_USB_TIGL - If you own a Texas Instruments graphing calculator and use a - TI-GRAPH LINK USB cable (aka SilverLink), then you might be - interested in this driver. - - If you enable this driver, you will be able to communicate with - your calculator through a set of device nodes under /dev. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called tiglusb.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. - - If you don't know what the SilverLink cable is or what a Texas - Instruments graphing calculator is, then you probably don't need this - driver. - - If unsure, say N. - -Texas Instruments parallel link cable support -CONFIG_TIPAR - If you own a Texas Instruments graphing calculator and use a - parallel link cable, then you might be interested in this driver. - - If you enable this driver, you will be able to communicate with - your calculator through a set of device nodes under /dev. The - main advantage of this driver is that you don't have to be root - to use this precise link cable (depending on the permissions on - the device nodes, though). - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called tipar.o. If you want to compile it as a - module, say M here and read - - If you don't know what a parallel link cable is or what a Texas - Instruments graphing calculator is, then you probably don't need this - driver. - - If unsure, say N. - -Tieman Voyager USB Braille display support -CONFIG_USB_BRLVOYAGER - Say Y here if you want to use the Voyager USB Braille display from - Tieman. See for more - information. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called brlvger.o. If you want to compile it as - a module, say M here and read . - -USBLCD support -CONFIG_USB_LCD - Say Y here if you want to connect an USBLCD to your computer's - USB port. The USBLCD is a small USB interface board for - alphanumeric LCD modules. See for more - information. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called usblcd.o. If you want to compile it as - a module, say M here and read . - -D-Link DSB-R100 FM radio support -CONFIG_USB_DSBR - Say Y here if you want to connect this type of radio to your - computer's USB port. Note that the audio is not digital, and - you must connect the line out connector to a sound card or a - set of speakers. - - This driver uses the Video For Linux API. You must enable - (Y or M in config) Video For Linux (under Character Devices) - to use this driver. Information on this API and pointers to - "v4l" programs may be found on the WWW at - . - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called dsbr100.o. If you want to compile it as a - module, say M here and read . - -Alcatel Speedtouch USB support -CONFIG_USB_SPEEDTOUCH - Say Y here if you have an Alcatel SpeedTouch USB or SpeedTouch 330 - modem. In order to use your modem you will need to install some user - space tools, see for details. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called speedtch.o. If you want to compile it as - a module, say M here and read . - -CONFIG_USB_GADGET - USB is a master/slave protocol, organized with one master - host (such as a PC) controlling up to 127 peripheral devices. - The USB hardware is asymmetric, which makes it easier to set up: - you can't connect two "to-the-host" connectors to each other. - - Linux can run in the host, or in the peripheral. In both cases - you need a low level bus controller driver, and some software - talking to it. Peripheral controllers are often discrete silicon, - or are integrated with the CPU in a microcontroller. The more - familiar host side controllers have names like like "EHCI", "OHCI", - or "UHCI", and are usually integrated into southbridges on PC - motherboards. - - Enable this configuration option if you want to run Linux inside - a USB peripheral device. Configure one hardware driver for your - peripheral/device side bus controller, and a "gadget driver" for - your peripheral protocol. (If you use modular gadget drivers, - you may configure more than one.) - - If in doubt, say "N" and don't enable these drivers; most people - don't have this kind of hardware (except maybe inside Linux PDAs). - -CONFIG_USB_NET2280 - NetChip 2280 is a PCI based USB peripheral controller which - supports both full and high speed USB 2.0 data transfers. - - It has six configurable endpoints, as well as endpoint zero - (for control transfers) and several endpoints with dedicated - functions. - - Say "y" to link the driver statically, or "m" to build a - dynamically linked module called "net2280" and force all - gadget drivers to also be dynamically linked. - -CONFIG_USB_ZERO - Gadget Zero is a two-configuration device. It either sinks and - sources bulk data; or it loops back a configurable number of - transfers. It also implements control requests, for "chapter 9" - conformance. The driver needs only two bulk-capable endpoints, so - it can work on top of most device-side usb controllers. It's - useful for testing, and is also a working example showing how - USB "gadget drivers" can be written. - - Make this be the first driver you try using on top of any new - USB peripheral controller driver. Then you can use host-side - test software, like the "usbtest" driver, to put your hardware - and its driver through a basic set of functional tests. - - Gadget Zero also works with the host-side "usb-skeleton" driver, - and with many kinds of host-side test software. You may need - to tweak product and vendor IDs before host software knows about - this device, and arrange to select an appropriate configuration. - - Say "y" to link the driver statically, or "m" to build a - dynamically linked module called "g_zero". - -CONFIG_USB_ETH - This driver implements Ethernet style communication, in either - of two ways: - - - The "Communication Device Class" (CDC) Ethernet Control Model. - That protocol is often avoided with pure Ethernet adapters, in - favor of simpler vendor-specific hardware, but is widely - supported by firmware for smart network devices. - - - On hardware can't implement that protocol, a simpler approach - is used, placing fewer demands on USB. - - Within the USB device, this gadget driver exposes a network device - "usbX", where X depends on what other networking devices you have. - Treat it like a two-node Ethernet link: host, and gadget. - - The Linux-USB host-side "usbnet" driver interoperates with this - driver, so that deep I/O queues can be supported. On 2.4 kernels, - use "CDCEther" instead, if you're using the CDC option. That CDC - mode should also interoperate with standard CDC Ethernet class - drivers on other host operating systems. - - Say "y" to link the driver statically, or "m" to build a - dynamically linked module called "g_ether". - -Always do synchronous disk IO for UBD -CONFIG_BLK_DEV_UBD_SYNC - The User-Mode Linux port includes a driver called UBD which will let - you access arbitrary files on the host computer as block devices. - Writes to such a block device are not immediately written to the - host's disk; this may cause problems if, for example, the User-Mode - Linux 'Virtual Machine' uses a journalling file system and the host - computer crashes. - - Synchronous operation (i.e. always writing data to the host's disk - immediately) is configurable on a per-UBD basis by using a special - kernel command line option. Alternatively, you can say Y here to - turn on synchronous operation by default for all block. - - If you're running a journalling file system (like reiserfs, for - example) in your virtual machine, you will want to say Y here. If - you care for the safety of the data in your virtual machine, Y is a - wise choice too. In all other cases (for example, if you're just - playing around with User-Mode Linux) you can choose N. - -Enable ptrace proxy -CONFIG_PT_PROXY - This option enables a debugging interface which allows gdb to debug - the kernel without needing to actually attach to kernel threads. - If you want to do kernel debugging, say Y here; otherwise say N. - -Management console -CONFIG_MCONSOLE - The user mode linux management console is a low-level interface to - the kernel, somewhat like the i386 SysRq interface. Since there is - a full-blown operating system running under every user mode linux - instance, there is much greater flexibility possible than with the - SysRq mechanism. - - If you answer 'Y' to this option, to use this feature, you need the - mconsole client (called uml_mconsole) which is present in CVS in - 2.4.5-9um and later (path /tools/mconsole), and is also in the - distribution RPM package in 2.4.6 and later. - - It is safe to say 'Y' here. - -Enable kernel debugging symbols -CONFIG_DEBUGSYM - When this is enabled, the User-Mode Linux binary will include - debugging symbols. This enlarges the binary by a few megabytes, - but aids in tracking down kernel problems in UML. It is required - if you intend to do any kernel development. - - If you're truly short on disk space or don't expect to report any - bugs back to the UML developers, say N, otherwise say Y. - -Enable gcov support -CONFIG_GCOV - This option allows developers to retrieve coverage data from a UML - session. - - See for more - details. - - If you're involved in UML kernel development and want to use gcov, - say Y. If you're unsure, say N. - -Enable gprof support -CONFIG_GPROF - This allows profiling of a User-Mode Linux kernel with the gprof - utility. - - See for more - details. - - If you're involved in UML kernel development and want to use gprof, - say Y. If you're unsure, say N. - -Host filesystem -CONFIG_HOSTFS - While the User-Mode Linux port uses its own root file system for - booting and normal file access, this module lets the UML user - access files stored on the host. It does not require any - network connection between the Host and UML. An example use of - this might be: - - mount none /tmp/fromhost -t hostfs -o /tmp/umlshare - - where /tmp/fromhost is an empty directory inside UML and - /tmp/umlshare is a directory on the host with files the UML user - wishes to access. - - For more information, see - . - - If you'd like to be able to work with files stored on the host, - say Y or M here; otherwise say N. - -Example IO Memory driver -CONFIG_MMAPPER - The User-Mode Linux port can provide support for IO Memory - emulation with this option. This allows a host file to be - specified as an I/O region on the kernel command line. That file - will be mapped into UML's kernel address space where a driver can - locate it and do whatever it wants with the memory, including - providing an interface to it for UML processes to use. - - For more information, see - . - - If you'd like to be able to provide a simulated IO port space for - User-Mode Linux processes, say Y. If unsure, say N. - -Virtual Serial Line -CONFIG_SSL - The User-Mode Linux environment allows you to create virtual serial - lines on the UML that are usually made to show up on the host as - ttys or ptys. - - See for more - information and command line examples of how to use this facility. - - Unless you have a specific reason for disabling this, say Y. - -Virtual network device -CONFIG_UML_NET - While the User-Mode port cannot directly talk to any physical - hardware devices, this choice and the following transport options - provide one or more virtual network devices through which the UML - kernels can talk to each other, the host, and with the host's help, - machines on the outside world. - - For more information, including explanations of the networking and - sample configurations, see - . - - If you'd like to be able to enable networking in the User-Mode - linux environment, say Y; otherwise say N. Note that you must - enable at least one of the following transport options to actually - make use of UML networking. - -Daemon transport -CONFIG_UML_NET_DAEMON - This User-Mode Linux network transport allows one or more running - UMLs on a single host to communicate with each other, but not to - the host. - - To use this form of networking, you'll need to run the UML - networking daemon on the host. - - For more information, see - That site - has examples of the UML command line to use to enable Daemon - networking. - - If you'd like to set up a network with other UMLs on a single host, - say Y. If you need a network between UMLs on multiple physical - hosts, choose the Multicast Transport. To set up a network with - the host and/or other IP machines, say Y to the Ethertap or Slip - transports. You'll need at least one of them, but may choose - more than one without conflict. If you don't need UML networking, - say N. - -Ethertap transport -CONFIG_UML_NET_ETHERTAP - The Ethertap User-Mode Linux network transport allows a single - running UML to exchange packets with its host over one of the - host's Ethertap devices, such as /dev/tap0. Additional running - UMLs can use additional Ethertap devices, one per running UML. - While the UML believes it's on a (multi-device, broadcast) virtual - Ethernet network, it's in fact communicating over a point-to-point - link with the host. - - To use this, your host kernel must have support for Ethertap - devices. Also, if your host kernel is 2.4.x, it must have - CONFIG_NETLINK_DEV configured as Y or M. - - For more information, see - That site - has examples of the UML command line to use to enable Ethertap - networking. - - If you'd like to set up an IP network with the host and/or the - outside world, say Y to this, the Daemon Transport and/or the - Slip Transport. You'll need at least one of them, but may choose - more than one without conflict. If you don't need UML networking, - say N. - -TUN/TAP transport -CONFIG_UML_NET_TUNTAP - The UML TUN/TAP network transport allows a UML instance to exchange - packets with the host over a TUN/TAP device. This option will only - work with a 2.4 host, unless you've applied the TUN/TAP patch to - your 2.2 host kernel. - - To use this transport, your host kernel must have support for TUN/TAP - devices, either built-in or as a module. - -Multicast transport -CONFIG_UML_NET_MCAST - This Multicast User-Mode Linux network transport allows multiple - UMLs (even ones running on different host machines!) to talk to - each other over a virtual ethernet network. However, it requires - at least one UML with one of the other transports to act as a - bridge if any of them need to be able to talk to their hosts or any - other IP machines. - - To use this, your host kernel(s) must support IP Multicasting. - - For more information, see - That site - has examples of the UML command line to use to enable Multicast - networking, and notes about the security of this approach. - - If you need UMLs on multiple physical hosts to communicate as if - they shared an Ethernet network, say Y. If you need to communicate - with other IP machines, make sure you select one of the other - transports (possibly in addition to Multicast; they're not - exclusive). If you don't need to network UMLs say N to each of - the transports. - -SLIP transport -CONFIG_UML_NET_SLIP - The Slip User-Mode Linux network transport allows a running UML to - network with its host over a point-to-point link. Unlike Ethertap, - which can carry any Ethernet frame (and hence even non-IP packets), - the Slip transport can only carry IP packets. - - To use this, your host must support Slip devices. - - For more information, see - . That site - has examples of the UML command line to use to enable Slip - networking, and details of a few quirks with it. - - The Ethertap Transport is preferred over Slip because of its - limitation. If you prefer Slip, however, say Y here. Otherwise - choose the Multicast transport (to network multiple UMLs on - multiple hosts), Ethertap (to network with the host and the - outside world), and/or the Daemon transport (to network multiple - UMLs on a single host). You may choose more than one without - conflict. If you don't need UML networking, say N. - -Microtek USB scanner support -CONFIG_USB_MICROTEK - Say Y here if you want support for the Microtek X6USB and - possibly the Phantom 336CX, Phantom C6 and ScanMaker V6U(S)L. - Support for anything but the X6 is experimental. - Please report failures and successes. - The scanner will appear as a scsi generic device to the rest - of the system. Scsi support is required for this driver to compile - and work. SANE 1.0.4 or newer is needed to make use of your scanner. - This driver can be compiled as a module. - -HP53xx and Minolta Dual Scanner support -CONFIG_USB_HPUSBSCSI - Say Y here if you want support for the HP 53xx series of scanners - and the Minolta Scan Dual. This driver is experimental. - The scanner will be accessible as a SCSI device. - -USB Bluetooth support -CONFIG_USB_BLUETOOTH - Say Y here if you want to connect a USB Bluetooth device to your - computer's USB port. You will need the Bluetooth stack (available - at ) to fully use the device. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called bluetooth.o. If you want to compile it as - a module, say M here and read . - -USB MIDI support -CONFIG_USB_MIDI - Say Y here if you want to connect a USB MIDI device to your - computer's USB port. This driver is for devices that comply with - 'Universal Serial Bus Device Class Definition for MIDI Device'. - - The following devices are known to work: - * Steinberg USB2MIDI - * Roland MPU64 - * Roland PC-300 - * Roland SC8850 - * Roland UM-1 - * Roland UM-2 - * Roland UA-100 - * Yamaha MU1000 - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called usb-midi.o. If you want to compile it as a - module, say M here and read . - -Minix fs support -CONFIG_MINIX_FS - Minix is a simple operating system used in many classes about OS's. - The minix file system (method to organize files on a hard disk - partition or a floppy disk) was the original file system for Linux, - but has been superseded by the second extended file system ext2fs. - You don't want to use the minix file system on your hard disk - because of certain built-in restrictions, but it is sometimes found - on older Linux floppy disks. This option will enlarge your kernel - by about 28 KB. If unsure, say N. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called minix.o. Note that the file system of your root - partition (the one containing the directory /) cannot be compiled as - a module. - -Reiserfs support -CONFIG_REISERFS_FS - Stores not just filenames but the files themselves in a balanced - tree. Uses journalling. - - Balanced trees are more efficient than traditional file system - architectural foundations. - - In general, ReiserFS is as fast as ext2, but is very efficient with - large directories and small files. It is much faster for writes, - and slightly slower for reads than ext2. It is much faster than - ext3. It will be obsoleted by Reiser4 in not too long, so keep - an eye on our website for when Reiser4 ships. - - Mount with the notail option if performance matters more to you than - saving space (the design flaw underlying this is fixed in reiser4). - - Read to learn more about reiserfs. - -Enable extra Reiserfs consistency checks -CONFIG_REISERFS_CHECK - If you set this to Y, then ReiserFS will perform every check it can - possibly imagine of its internal consistency throughout its - operation. It will also go substantially slower. More than once we - have forgotten that this was on, and then gone despondent over the - latest benchmarks.:-) Use of this option allows our team to go all - out in checking for consistency when debugging without fear of its - effect on end users. If you are on the verge of sending in a bug - report, say Y and you might get a useful error message. Almost - everyone should say N. - -Publish some reiserfs-specific info under /proc/fs/reiserfs -CONFIG_REISERFS_PROC_INFO - Create under /proc/fs/reiserfs a hierarchy of files, displaying - various ReiserFS statistics and internal data at the expense of making - your kernel or module slightly larger (+8 KB). This also increases the - amount of kernel memory required for each mount by 440 bytes. - It isn't useful to average persons, and you probably can't measure the - performance cost of it. If you are fine-tuning reiserfs, say Y, - otherwise say N. - -Second extended fs support -CONFIG_EXT2_FS - This is the de facto standard Linux file system (method to organize - files on a storage device) for hard disks. - - You want to say Y here, unless you intend to use Linux exclusively - from inside a DOS partition using the UMSDOS file system. The - advantage of the latter is that you can get away without - repartitioning your hard drive (which often implies backing - everything up and restoring afterwards); the disadvantage is that - Linux becomes susceptible to DOS viruses and that UMSDOS is somewhat - slower than ext2fs. Even if you want to run Linux in this fashion, - it might be a good idea to have ext2fs around: it enables you to - read more floppy disks and facilitates the transition to a *real* - Linux partition later. Another (rare) case which doesn't require - ext2fs is a diskless Linux box which mounts all files over the - network using NFS (in this case it's sufficient to say Y to "NFS - file system support" below). Saying Y here will enlarge your kernel - by about 44 KB. - - The Ext2fs-Undeletion mini-HOWTO, available from - , gives information about - how to retrieve deleted files on ext2fs file systems. - - To change the behaviour of ext2 file systems, you can use the tune2fs - utility ("man tune2fs"). To modify attributes of files and - directories on ext2 file systems, use chattr ("man chattr"). - - Ext2fs partitions can be read from within DOS using the ext2tool - command line tool package (available from - ) and from - within Windows NT using the ext2nt command line tool package from - . Explore2fs is a - graphical explorer for ext2fs partitions which runs on Windows 95 - and Windows NT and includes experimental write support; it is - available from - . - - If you want to compile this file system as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want), say M here and read . The - module will be called ext2.o. Be aware however that the file system - of your root partition (the one containing the directory /) cannot - be compiled as a module, and so this could be dangerous. Most - everyone wants to say Y here. - -Ext3 journalling file system support (EXPERIMENTAL) -CONFIG_EXT3_FS - This is the journalling version of the Second extended file system - (often called ext3), the de facto standard Linux file system - (method to organize files on a storage device) for hard disks. - - The journalling code included in this driver means you do not have - to run e2fsck (file system checker) on your file systems after a - crash. The journal keeps track of any changes that were being made - at the time the system crashed, and can ensure that your file system - is consistent without the need for a lengthy check. - - Other than adding the journal to the file system, the on-disk format - of ext3 is identical to ext2. It is possible to freely switch - between using the ext3 driver and the ext2 driver, as long as the - file system has been cleanly unmounted, or e2fsck is run on the file - system. - - To add a journal on an existing ext2 file system or change the - behaviour of ext3 file systems, you can use the tune2fs utility ("man - tune2fs"). To modify attributes of files and directories on ext3 - file systems, use chattr ("man chattr"). You need to be using - e2fsprogs version 1.20 or later in order to create ext3 journals - (available at ). - - If you want to compile this file system as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want), say M here and read . The - module will be called ext3.o. Be aware however that the file system - of your root partition (the one containing the directory /) cannot - be compiled as a module, and so this may be dangerous. - -Journal Block Device support (JBD for ext3) (EXPERIMENTAL) -CONFIG_JBD - This is a generic journalling layer for block devices. It is - currently used by the ext3 file system, but it could also be used to - add journal support to other file systems or block devices such as - RAID or LVM. - - If you are using the ext3 file system, you need to say Y here. If - you are not using ext3 then you will probably want to say N. - - If you want to compile this device as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called jbd.o. If you are compiling ext3 into the kernel, - you cannot compile this code as a module. - -JBD (ext3) debugging support -CONFIG_JBD_DEBUG - If you are using the ext3 journalling file system (or potentially any - other file system/device using JBD), this option allows you to - enable debugging output while the system is running, in order to - help track down any problems you are having. By default the - debugging output will be turned off. - - If you select Y here, then you will be able to turn on debugging - with "echo N > /proc/sys/fs/jbd-debug", where N is a number between - 1 and 5, the higher the number, the more debugging output is - generated. To turn debugging off again, do - "echo 0 > /proc/sys/fs/jbd-debug". - -Buffer Head tracing (DEBUG) -CONFIG_BUFFER_DEBUG - If you are a kernel developer working with file systems or in the - block device layer, this buffer head tracing may help you to track - down bugs in your code. This enables some debugging macros - (BUFFER_TRACE, etc.) which allow you to track the state of a buffer - through various layers of code. The debugging code is used - primarily by ext3 and JBD code. - - Because this option adds considerably to the size of each buffer, - most people will want to say N here. - -BeOS filesystem support (BeFS) (read only) -CONFIG_BEFS_FS - The BeOS File System (BeFS) is the native file system of Be, Inc's - BeOS. Notable features include support for arbitrary attributes - on files and directories, and database-like indices on selected - attributes. (Also note that this driver doesn't make those features - available at this time). It is a 64 bit filesystem, so it supports - extremely large volumes and files. - - If you use this filesystem, you should also say Y to at least one - of the NLS (native language support) options below. - - If you don't know what this is about, say N. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called befs.o. - -Debug BeFS -CONFIG_BEFS_DEBUG - If you say Y here, you can use the 'debug' mount option to enable - debugging output from the driver. This is unlike previous versions - of the driver, where enabling this option would turn on debugging - output automatically. - - Example: - mount -t befs /dev/hda2 /mnt -o debug - -BFS file system support -CONFIG_BFS_FS - Boot File System (BFS) is a file system used under SCO UnixWare to - allow the bootloader access to the kernel image and other important - files during the boot process. It is usually mounted under /stand - and corresponds to the slice marked as "STAND" in the UnixWare - partition. You should say Y if you want to read or write the files - on your /stand slice from within Linux. You then also need to say Y - to "UnixWare slices support", below. More information about the BFS - file system is contained in the file - . - - If you don't know what this is about, say N. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called bfs.o. Note that the file system of your root - partition (the one containing the directory /) cannot be compiled as - a module. - -Compressed ROM file system support -CONFIG_CRAMFS - Saying Y here includes support for CramFs (Compressed ROM File - System). CramFs is designed to be a simple, small, and compressed - file system for ROM based embedded systems. CramFs is read-only, - limited to 256MB file systems (with 16MB files), and doesn't support - 16/32 bits uid/gid, hard links and timestamps. - - See and - for further information. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called cramfs.o. Note that the root file system (the one - containing the directory /) cannot be compiled as a module. - - If unsure, say N. - -CMS file system support -CONFIG_CMS_FS - Read only support for CMS minidisk file systems found on IBM - mainframe systems. Only the basic format is supported so far. If - you don't know what CMS is you probably don't want to know any more. - -# When the 2.5 version of configure.help goes away, the part of this that -# duplicates Documentation/filesystems/tmpfs.txt can drop out. -Virtual memory file system support -CONFIG_TMPFS - Tmpfs is a file system which keeps all files in virtual memory. - Everything in tmpfs is temporary in the sense that no files will be - created on your hard drive. If you reboot, everything in tmpfs will - be lost. - - In contrast to RAM disks, which get allocated a fixed amount of - physical RAM, tmpfs grows and shrinks to accommodate the files it - contains and is able to swap unneeded pages out to swap space. - - Everything is "virtual" in the sense that no files will be created - on your hard drive; if you reboot, everything in tmpfs will be - lost. - - You should mount the file system somewhere to be able to use - POSIX shared memory. Adding the following line to /etc/fstab should - take care of things: - - tmpfs /dev/shm tmpfs defaults 0 0 - - Remember to create the directory that you intend to mount tmpfs on - if necessary (/dev/shm is automagically created if you use devfs). - - You can set limits for the number of blocks and inodes used by the - file system with the mount options "size", "nr_blocks" and - "nr_inodes". These parameters accept a suffix k, m or g for kilo, - mega and giga and can be changed on remount. - - The initial permissions of the root directory can be set with the - mount option "mode". - - See for details. - -Simple RAM-based file system support -CONFIG_RAMFS - Ramfs is a file system which keeps all files in RAM. It allows - read and write access. - - It is more of an programming example than a usable file system. If - you need a file system which lives in RAM with limit checking use - tmpfs. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ramfs.o. - -ISO 9660 CD-ROM file system support -CONFIG_ISO9660_FS - This is the standard file system used on CD-ROMs. It was previously - known as "High Sierra File System" and is called "hsfs" on other - Unix systems. The so-called Rock-Ridge extensions which allow for - long Unix filenames and symbolic links are also supported by this - driver. If you have a CD-ROM drive and want to do more with it than - just listen to audio CDs and watch its LEDs, say Y (and read - and the CD-ROM-HOWTO, - available from ), thereby - enlarging your kernel by about 27 KB; otherwise say N. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called isofs.o. - -Microsoft Joliet CD-ROM extensions -CONFIG_JOLIET - Joliet is a Microsoft extension for the ISO 9660 CD-ROM file system - which allows for long filenames in unicode format (unicode is the - new 16 bit character code, successor to ASCII, which encodes the - characters of almost all languages of the world; see - for more information). Say Y here if you - want to be able to read Joliet CD-ROMs under Linux. - -Transparent decompression extension -CONFIG_ZISOFS - This is a Linux-specific extension to RockRidge which lets you store - data in compressed form on a CD-ROM and have it transparently - decompressed when the CD-ROM is accessed. See - for the tools - necessary to create such a filesystem. Say Y here if you want to be - able to read such compressed CD-ROMs. - -UDF file system support (read-only) -CONFIG_UDF_FS - This is the new file system used on some CD-ROMs and DVDs. Say Y if - you intend to mount DVD discs or CDRW's written in packet mode, or - if written to by other UDF utilities, such as DirectCD. This UDF - file system support is read-only. If you want to write to UDF - file systems on some media, you need to say Y to "UDF read-write - support" below in addition. Please read - . - - This file system support is also available as a module ( = code - which can be inserted in and removed from the running kernel - whenever you want). The module is called udf.o. If you want to - compile it as a module, say M here and read - . - - If unsure, say N. - -UDF write support (DANGEROUS) -CONFIG_UDF_RW - Say Y if you want to test write support for UDF file systems. - Due to lack of support for writing to CDR/CDRW's, this option - is only supported for hard discs, DVD-RAM, and loopback files. - -DOS FAT fs support -CONFIG_FAT_FS - If you want to use one of the FAT-based file systems (the MS-DOS, - VFAT (Windows 95) and UMSDOS (used to run Linux on top of an - ordinary DOS partition) file systems), then you must say Y or M here - to include FAT support. You will then be able to mount partitions or - diskettes with FAT-based file systems and transparently access the - files on them, i.e. MSDOS files will look and behave just like all - other Unix files. - - This FAT support is not a file system in itself, it only provides - the foundation for the other file systems. You will have to say Y or - M to at least one of "MSDOS fs support" or "VFAT fs support" in - order to make use of it. - - Another way to read and write MSDOS floppies and hard drive - partitions from within Linux (but not transparently) is with the - mtools ("man mtools") program suite. You don't need to say Y here in - order to do that. - - If you need to move large files on floppies between a DOS and a - Linux box, say Y here, mount the floppy under Linux with an MSDOS - file system and use GNU tar's M option. GNU tar is a program - available for Unix and DOS ("man tar" or "info tar"). - - It is now also becoming possible to read and write compressed FAT - file systems; read for - details. - - The FAT support will enlarge your kernel by about 37 KB. If unsure, - say Y. - - If you want to compile this as a module however ( = code which can - be inserted in and removed from the running kernel whenever you - want), say M here and read . The - module will be called fat.o. Note that if you compile the FAT - support as a module, you cannot compile any of the FAT-based file - systems into the kernel -- they will have to be modules as well. - The file system of your root partition (the one containing the - directory /) cannot be a module, so don't say M here if you intend - to use UMSDOS as your root file system. - -MSDOS fs support -CONFIG_MSDOS_FS - This allows you to mount MSDOS partitions of your hard drive (unless - they are compressed; to access compressed MSDOS partitions under - Linux, you can either use the DOS emulator DOSEMU, described in the - DOSEMU-HOWTO, available from - , or try dmsdosfs in - . If you - intend to use dosemu with a non-compressed MSDOS partition, say Y - here) and MSDOS floppies. This means that file access becomes - transparent, i.e. the MSDOS files look and behave just like all - other Unix files. - - If you want to use UMSDOS, the Unix-like file system on top of a - DOS file system, which allows you to run Linux from within a DOS - partition without repartitioning, you'll have to say Y or M here. - - If you have Windows 95 or Windows NT installed on your MSDOS - partitions, you should use the VFAT file system (say Y to "VFAT fs - support" below), or you will not be able to see the long filenames - generated by Windows 95 / Windows NT. - - This option will enlarge your kernel by about 7 KB. If unsure, - answer Y. This will only work if you said Y to "DOS FAT fs support" - as well. If you want to compile this as a module however ( = code - which can be inserted in and removed from the running kernel - whenever you want), say M here and read - . - The module will be called msdos.o. - -VFAT (Windows-95) fs support -CONFIG_VFAT_FS - This option provides support for normal Windows file systems with - long filenames. That includes non-compressed FAT-based file systems - used by Windows 95, Windows 98, Windows NT 4.0, and the Unix - programs from the mtools package. - - You cannot use the VFAT file system for your Linux root partition - (the one containing the directory /); use UMSDOS instead if you - want to run Linux from within a DOS partition (i.e. say Y to - "Unix like fs on top of std MSDOS fs", below). - - The VFAT support enlarges your kernel by about 10 KB and it only - works if you said Y to the "DOS FAT fs support" above. Please read - the file for details. If - unsure, say Y. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called vfat.o. - -Unix-like file system on top of standard MSDOS fs -CONFIG_UMSDOS_FS - Say Y here if you want to run Linux from within an existing DOS - partition of your hard drive. The advantage of this is that you can - get away without repartitioning your hard drive (which often implies - backing everything up and restoring afterwards) and hence you're - able to quickly try out Linux or show it to your friends; the - disadvantage is that Linux becomes susceptible to DOS viruses and - that UMSDOS is somewhat slower than ext2fs. Another use of UMSDOS - is to write files with long unix filenames to MSDOS floppies; it - also allows Unix-style soft-links and owner/permissions of files on - MSDOS floppies. You will need a program called umssync in order to - make use of UMSDOS; read - . - - To get utilities for initializing/checking UMSDOS file system, or - latest patches and/or information, visit the UMSDOS home page at - . - - This option enlarges your kernel by about 28 KB and it only works if - you said Y to both "DOS FAT fs support" and "MSDOS fs support" - above. If you want to compile this as a module ( = code which can - be inserted in and removed from the running kernel whenever you - want), say M here and read . The - module will be called umsdos.o. Note that the file system of your - root partition (the one containing the directory /) cannot be a - module, so saying M could be dangerous. If unsure, say N. - -/proc file system support -CONFIG_PROC_FS - This is a virtual file system providing information about the status - of the system. "Virtual" means that it doesn't take up any space on - your hard disk: the files are created on the fly by the kernel when - you try to access them. Also, you cannot read the files with older - version of the program less: you need to use more or cat. - - It's totally cool; for example, "cat /proc/interrupts" gives - information about what the different IRQs are used for at the moment - (there is a small number of Interrupt ReQuest lines in your computer - that are used by the attached devices to gain the CPU's attention -- - often a source of trouble if two devices are mistakenly configured - to use the same IRQ). The program procinfo to display some - information about your system gathered from the /proc file system. - - Before you can use the /proc file system, it has to be mounted, - meaning it has to be given a location in the directory hierarchy. - That location should be /proc. A command such as "mount -t proc proc - /proc" or the equivalent line in /etc/fstab does the job. - - The /proc file system is explained in the file - and on the proc(5) manpage - ("man 5 proc"). - - This option will enlarge your kernel by about 67 KB. Several - programs depend on this, so everyone should say Y here. - -Support for PReP Residual Data -CONFIG_PREP_RESIDUAL - Some PReP systems have residual data passed to the kernel by the - firmware. This allows detection of memory size, devices present and - other useful pieces of information. Sometimes this information is - not present or incorrect. - - Unless you expect to boot on a PReP system, there is no need to - select Y. - -PReP residual data available in /proc/residual -CONFIG_PROC_PREPRESIDUAL - Enabling this option will create a /proc/residual file which allows - you to get at the residual data on PReP systems. You will need a tool - (lsresidual) to parse it. If you aren't on a PReP system, you don't - want this. - -/dev file system support -CONFIG_DEVFS_FS - This is support for devfs, a virtual file system (like /proc) which - provides the file system interface to device drivers, normally found - in /dev. Devfs does not depend on major and minor number - allocations. Device drivers register entries in /dev which then - appear automatically, which means that the system administrator does - not have to create character and block special device files in the - /dev directory using the mknod command (or MAKEDEV script) anymore. - - This is work in progress. If you want to use this, you *must* read - the material in , especially - the file README there. - - If unsure, say N. - -Automatically mount devfs at boot time -CONFIG_DEVFS_MOUNT - This option appears if you have CONFIG_DEVFS_FS enabled. Setting - this to 'Y' will make the kernel automatically mount devfs onto /dev - when the system is booted, before the init thread is started. - You can override this with the "devfs=nomount" boot option. - - If unsure, say N. - -Debug devfs -CONFIG_DEVFS_DEBUG - If you say Y here, then the /dev file system code will generate - debugging messages. See the file - for more - details. - - If unsure, say N. - -NFS file system support -CONFIG_NFS_FS - If you are connected to some other (usually local) Unix computer - (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing - on that computer (the NFS server) using the Network File Sharing - protocol, say Y. "Mounting files" means that the client can access - the files with usual UNIX commands as if they were sitting on the - client's hard disk. For this to work, the server must run the - programs nfsd and mountd (but does not need to have NFS file system - support enabled in its kernel). NFS is explained in the Network - Administrator's Guide, available from - , on its man page: "man - nfs", and in the NFS-HOWTO. - - A superior but less widely used alternative to NFS is provided by - the Coda file system; see "Coda file system support" below. - - If you say Y here, you should have said Y to TCP/IP networking also. - This option would enlarge your kernel by about 27 KB. - - This file system is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called nfs.o. If you want to compile it as a module, - say M here and read . - - If you are configuring a diskless machine which will mount its root - file system over NFS at boot time, say Y here and to "Kernel - level IP autoconfiguration" above and to "Root file system on NFS" - below. You cannot compile this driver as a module in this case. - There are two packages designed for booting diskless machines over - the net: netboot, available from - , and Etherboot, - available from . - - If you don't know what all this is about, say N. - -Provide NFSv3 client support -CONFIG_NFS_V3 - Say Y here if you want your NFS client to be able to speak the newer - version 3 of the NFS protocol. - - If unsure, say N. - -Allow direct I/O on files in NFS -CONFIG_NFS_DIRECTIO - There are important applications whose performance or correctness - depends on uncached access to file data. Database clusters (multiple - copies of the same instance running on separate hosts) implement their - own cache coherency protocol that subsumes the NFS cache protocols. - Applications that process datasets considerably larger than the client's - memory do not always benefit from a local cache. A streaming video - server, for instance, has no need to cache the contents of a file. - - This option enables applications to perform direct I/O on files in NFS - file systems using the O_DIRECT open() flag. When O_DIRECT is set for - files, their data is not cached in the system's page cache. Direct - read and write operations are aligned to block boundaries. Data is - moved to and from user-level application buffers directly. - - Unless your program is designed to use O_DIRECT properly, you are much - better off allowing the NFS client to manage caching for you. Misusing - O_DIRECT can cause poor server performance or network storms. This - kernel build option defaults OFF to avoid exposing system administrators - unwittingly to a potentially hazardous feature. - - If unsure, say N. - -Root file system on NFS -CONFIG_ROOT_NFS - If you want your Linux box to mount its whole root file system (the - one containing the directory /) from some other computer over the - net via NFS (presumably because your box doesn't have a hard disk), - say Y. Read for details. It is - likely that in this case, you also want to say Y to "Kernel level IP - autoconfiguration" so that your box can discover its network address - at boot time. - - Most people say N here. - -NFS server support -CONFIG_NFSD - If you want your Linux box to act as an NFS *server*, so that other - computers on your local network which support NFS can access certain - directories on your box transparently, you have two options: you can - use the self-contained user space program nfsd, in which case you - should say N here, or you can say Y and use the kernel based NFS - server. The advantage of the kernel based solution is that it is - faster. - - In either case, you will need support software; the respective - locations are given in the file in the - NFS section. - - If you say Y here, you will get support for version 2 of the NFS - protocol (NFSv2). If you also want NFSv3, say Y to the next question - as well. - - Please read the NFS-HOWTO, available from - . - - The NFS server is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called nfsd.o. If you want to compile it as a module, - say M here and read . If unsure, - say N. - -Provide NFSv3 server support -CONFIG_NFSD_V3 - If you would like to include the NFSv3 server as well as the NFSv2 - server, say Y here. If unsure, say Y. - -Provide NFS over TCP server support EXPERIMENTAL -CONFIG_NFSD_TCP - Enable NFS service over TCP connections. This the officially - still experimental, but seems to work well. - -OS/2 HPFS file system support -CONFIG_HPFS_FS - OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS - is the file system used for organizing files on OS/2 hard disk - partitions. Say Y if you want to be able to read files from and - write files to an OS/2 HPFS partition on your hard drive. OS/2 - floppies however are in regular MSDOS format, so you don't need this - option in order to be able to read them. Read - . - - This file system is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called hpfs.o. If you want to compile it as a module, - say M here and read . If unsure, - say N. - -NTFS file system support (read-only) -CONFIG_NTFS_FS - NTFS is the file system of Microsoft Windows NT. Say Y if you want - to get read access to files on NTFS partitions of your hard drive. - The Linux NTFS driver supports most of the mount options of the VFAT - driver, see . Saying Y here - will give you read-only access to NTFS partitions. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ntfs.o. If you want to compile it as a - module, say M here and read . - -NTFS write support (DANGEROUS) -CONFIG_NTFS_RW - If you say Y here, you will (maybe) be able to write to NTFS file - systems as well as read from them. The read-write support in NTFS - is far from being complete and is not well tested. If you say Y - here, back up your NTFS volume first, since it will probably get - damaged. Also, download the Linux-NTFS project distribution from - Sourceforge at and always run the - included ntfsfix utility after writing to an NTFS partition from - Linux to fix some of the damage done by the driver. You should run - ntfsfix _after_ unmounting the partition in Linux but _before_ - rebooting into Windows. When Windows next boots, chkdsk will be - run automatically to fix the remaining damage. - Please note that write support is limited to Windows NT4 and - earlier versions. - - If unsure, say N. - -System V/Xenix/V7/Coherent file system support -CONFIG_SYSV_FS - SCO, Xenix and Coherent are commercial Unix systems for Intel - machines, and Version 7 was used on the DEC PDP-11. Saying Y - here would allow you to read from their floppies and hard disk - partitions. - - If you have floppies or hard disk partitions like that, it is likely - that they contain binaries from those other Unix systems; in order - to run these binaries, you will want to install linux-abi which is a - a set of kernel modules that lets you run SCO, Xenix, Wyse, - UnixWare, Dell Unix and System V programs under Linux. It is - available via FTP (user: ftp) from - ). - NOTE: that will work only for binaries from Intel-based systems; - PDP ones will have to wait until somebody ports Linux to -11 ;-) - - If you only intend to mount files from some other Unix over the - network using NFS, you don't need the System V file system support - (but you need NFS file system support obviously). - - Note that this option is generally not needed for floppies, since a - good portable way to transport files and directories between unixes - (and even other operating systems) is given by the tar program ("man - tar" or preferably "info tar"). Note also that this option has - nothing whatsoever to do with the option "System V IPC". Read about - the System V file system in - . - Saying Y here will enlarge your kernel by about 27 KB. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called sysv.o. - - If you haven't heard about all of this before, it's safe to say N. - -Amiga FFS file system support -CONFIG_AFFS_FS - The Fast File System (FFS) is the common file system used on hard - disks by Amiga(tm) systems since AmigaOS Version 1.3 (34.20). Say Y - if you want to be able to read and write files from and to an Amiga - FFS partition on your hard drive. Amiga floppies however cannot be - read with this driver due to an incompatibility of the floppy - controller used in an Amiga and the standard floppy controller in - PCs and workstations. Read - and . - - With this driver you can also mount disk files used by Bernd - Schmidt's Un*X Amiga Emulator - (). - If you want to do this, you will also need to say Y or M to "Loop - device support", above. - - This file system is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called affs.o. If you want to compile it as a module, - say M here and read . If unsure, - say N. - -Apple HFS file system support -CONFIG_HFS_FS - If you say Y here, you will be able to mount Macintosh-formatted - floppy disks and hard drive partitions with full read-write access. - Please read to learn about the available mount - options. - - This file system support is also available as a module ( = code - which can be inserted in and removed from the running kernel - whenever you want). The module is called hfs.o. If you want to - compile it as a module, say M here and read - . - -Apple HFS+ (Extended HFS) file system support -CONFIG_HFSPLUS_FS - If you say Y here, you will be able to mount extended format - Macintosh-formatted hard drive partitions with full read-write access. - - This file system is often called HFS+ and was introduced with - MacOS 8. It includes all Mac specific filesystem data such as - data forks and creator codes, but it also has several UNIX - style features such as file ownership and permissions. - - This file system is also available as a module ( = code which can - be inserted in and removed from the running kernel whenever you - want). The module is called hfsplus.o. If you want to compile it - as a module, say M here and read Documentation/modules.txt. - -ROM file system support -CONFIG_ROMFS_FS - This is a very small read-only file system mainly intended for - initial ram disks of installation disks, but it could be used for - other read-only media as well. Read - for details. - - This file system support is also available as a module ( = code - which can be inserted in and removed from the running kernel - whenever you want). The module is called romfs.o. If you want to - compile it as a module, say M here and read - . Note that the file system of your - root partition (the one containing the directory /) cannot be a - module. - - If you don't know whether you need it, then you don't need it: - answer N. - -QNX4 file system support (read only) -CONFIG_QNX4FS_FS - This is the file system used by the real-time operating systems - QNX 4 and QNX 6 (the latter is also called QNX RTP). - Further information is available at . - Say Y if you intend to mount QNX hard disks or floppies. - Unless you say Y to "QNX4FS read-write support" below, you will - only be able to read these file systems. - - This file system support is also available as a module ( = code - which can be inserted in and removed from the running kernel - whenever you want). The module is called qnx4.o. If you want to - compile it as a module, say M here and read - . - - If you don't know whether you need it, then you don't need it: - answer N. - -QNX4FS write support (DANGEROUS) -CONFIG_QNX4FS_RW - Say Y if you want to test write support for QNX4 file systems. - - It's currently broken, so for now: - answer N. - -Kernel automounter support -CONFIG_AUTOFS_FS - The automounter is a tool to automatically mount remote file systems - on demand. This implementation is partially kernel-based to reduce - overhead in the already-mounted case; this is unlike the BSD - automounter (amd), which is a pure user space daemon. - - To use the automounter you need the user-space tools from the autofs - package; you can find the location in . - You also want to answer Y to "NFS file system support", below. - - If you want to use the newer version of the automounter with more - features, say N here and say Y to "Kernel automounter v4 support", - below. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called autofs.o. - - If you are not a part of a fairly large, distributed network, you - probably do not need an automounter, and can say N here. - -Kernel automounter version 4 support (also supports v3) -CONFIG_AUTOFS4_FS - The automounter is a tool to automatically mount remote file systems - on demand. This implementation is partially kernel-based to reduce - overhead in the already-mounted case; this is unlike the BSD - automounter (amd), which is a pure user space daemon. - - To use the automounter you need the user-space tools from - ; you also - want to answer Y to "NFS file system support", below. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called autofs4.o. You will need to add "alias autofs - autofs4" to your modules configuration file. - - If you are not a part of a fairly large, distributed network or - don't have a laptop which needs to dynamically reconfigure to the - local network, you probably do not need an automounter, and can say - N here. - -EFS file system support (read-only) -CONFIG_EFS_FS - EFS is an older file system used for non-ISO9660 CD-ROMs and hard - disk partitions by SGI's IRIX operating system (IRIX 6.0 and newer - uses the XFS file system for hard disk partitions however). - - This implementation only offers read-only access. If you don't know - what all this is about, it's safe to say N. For more information - about EFS see its home page at . - - If you want to compile the EFS file system support as a module ( = - code which can be inserted in and removed from the running kernel - whenever you want), say M here and read - . The module will be called efs.o. - -Journalling Flash File System (JFFS) support -CONFIG_JFFS_FS - JFFS is the Journalling Flash File System developed by Axis - Communications in Sweden, aimed at providing a crash/powerdown-safe - file system for disk-less embedded devices. Further information is - available at (). - -JFFS debugging verbosity (0 = quiet, 3 = noisy) -CONFIG_JFFS_FS_VERBOSE - Determines the verbosity level of the JFFS debugging messages. - -Journalling Flash File System v2 (JFFS2) support -CONFIG_JFFS2_FS - JFFS2 is the second generation of the Journalling Flash File System - for use on diskless embedded devices. It provides improved wear - levelling, compression and support for hard links. You cannot use - this on normal block devices, only on 'MTD' devices. - - Further information should be made available soon at - . - -JFFS2 debugging verbosity (0 = quiet, 2 = noisy) -CONFIG_JFFS2_FS_DEBUG - This controls the amount of debugging messages produced by the JFFS2 - code. Set it to zero for use in production systems. For evaluation, - testing and debugging, it's advisable to set it to one. This will - enable a few assertions and will print debugging messages at the - KERN_DEBUG loglevel, where they won't normally be visible. Level 2 - is unlikely to be useful - it enables extra debugging in certain - areas which at one point needed debugging, but when the bugs were - located and fixed, the detailed messages were relegated to level 2. - - If reporting bugs, please try to have available a full dump of the - messages at debug level 1 while the misbehaviour was occurring. - -JFFS stats available in /proc filesystem -CONFIG_JFFS_PROC_FS - Enabling this option will cause statistics from mounted JFFS file systems - to be made available to the user in the /proc/fs/jffs/ directory. - -UFS file system support (read-only) -CONFIG_UFS_FS - BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD, - OpenBSD and NeXTstep) use a file system called UFS. Some System V - Unixes can create and mount hard disk partitions and diskettes using - this file system as well. Saying Y here will allow you to read from - these partitions; if you also want to write to them, say Y to the - experimental "UFS file system write support", below. Please read the - file for more information. - - If you only intend to mount files from some other Unix over the - network using NFS, you don't need the UFS file system support (but - you need NFS file system support obviously). - - Note that this option is generally not needed for floppies, since a - good portable way to transport files and directories between unixes - (and even other operating systems) is given by the tar program ("man - tar" or preferably "info tar"). - - When accessing NeXTstep files, you may need to convert them from the - NeXT character set to the Latin1 character set; use the program - recode ("info recode") for this purpose. - - If you want to compile the UFS file system support as a module ( = - code which can be inserted in and removed from the running kernel - whenever you want), say M here and read - . The module will be called ufs.o. - - If you haven't heard about all of this before, it's safe to say N. - -UFS file system write support (DANGEROUS) -CONFIG_UFS_FS_WRITE - Say Y here if you want to try writing to UFS partitions. This is - experimental, so you should back up your UFS partitions beforehand. - -XFS filesystem support -CONFIG_XFS_FS - XFS is a high performance journaling filesystem which originated - on the SGI IRIX platform. It is completely multi-threaded, can - support large files and large filesystems, extended attributes, - variable block sizes, is extent based, and makes extensive use of - Btrees (directories, extents, free space) to aid both performance - and scalability. - - Refer to the documentation at - for complete details. This implementation is on-disk compatible - with the IRIX version of XFS. - - If you want to compile this file system as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want), say M here and read . The - module will be called xfs.o. Be aware, however, that if the file - system of your root partition is compiled as a module, you'll need - to use an initial ramdisk (initrd) to boot. - -Quota support -CONFIG_XFS_QUOTA - If you say Y here, you will be able to set limits for disk usage on - a per user and/or per group basis under XFS. XFS considers quota - information as filesystem metadata and uses journaling to provide a - higher level guarantee of consistency. The on-disk data format for - quota is also compatible with the IRIX version of XFS, allowing a - filesystem to be migrated between Linux and IRIX without any need - for conversion. - - If unsure, say N. More comprehensive documentation can be found in - README.quota in the xfsprogs package. XFS quota can be used either - with or without the generic quota support enabled (CONFIG_QUOTA) - - they are completely independent subsystems. - -Realtime support (EXPERIMENTAL) -CONFIG_XFS_RT - If you say Y here you will be able to mount and use XFS filesystems - which contain a realtime subvolume. The realtime subvolume is a - separate area of disk space where only file data is stored. The - realtime subvolume is designed to provide very deterministic - data rates suitable for media streaming applications. - - See the xfs man page in section 5 for a bit more information. - - This feature is unsupported at this time, is not yet fully - functional, and may cause serious problems. - - If unsure, say N. - -Tracing support (EXPERIMENTAL) -CONFIG_XFS_TRACE - Say Y here to get an XFS build with activity tracing enabled. - Enabling this option will attach historical information to XFS - inodes, pagebufs, certain locks, the log, the IO path, and a - few other key areas within XFS. These traces can be examined - using a kernel debugger. - - Note that for the pagebuf traces, you will also have to enable - the sysctl in /proc/sys/vm/pagebuf/debug for this to work. - - Say N unless you are an XFS developer. - -Debugging support (EXPERIMENTAL) -CONFIG_XFS_DEBUG - Say Y here to get an XFS build with many debugging features, - including ASSERT checks, function wrappers around macros, - and extra sanity-checking functions in various code paths. - - Note that the resulting code will be HUGE and SLOW, and probably - not useful unless you are debugging a particular problem. - - Say N unless you are an XFS developer, or play one on TV. - -Advanced partition selection -CONFIG_PARTITION_ADVANCED - Say Y here if you would like to use hard disks under Linux which - were partitioned under an operating system running on a different - architecture than your Linux system. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about foreign partitioning schemes. - - If unsure, say N. - -Acorn partition support -CONFIG_ACORN_PARTITION - Support hard disks partitioned under Acorn operating systems. - -Xen virtual-partition support -CONFIG_XEN_VBD_PARTITION - Support partition-level virtual block devices. The Xen - hypervisor can export partitions on a physical disk to clients, - but access to the partition table requires special trickery. - This will be used if this option is enabled; otherwise, - it will be possible to access exported partitions by sector - number but not with useful names e.g. /dev/hda4. - - If unsure, say Y. - -Native filecore partition support -CONFIG_ACORN_PARTITION_ADFS - The Acorn Disc Filing System is the standard file system of the - RiscOS operating system which runs on Acorn's ARM-based Risc PC - systems and the Acorn Archimedes range of machines. If you say - `Y' here, Linux will support disk partitions created under ADFS. - -PowerTec partition support -CONFIG_ACORN_PARTITION_POWERTEC - Support reading partition tables created on Acorn machines using - the PowerTec SCSI drive. - -RISCiX partition support -CONFIG_ACORN_PARTITION_RISCIX - Once upon a time, there was a native Unix port for the Acorn series - of machines called RISCiX. If you say 'Y' here, Linux will be able - to read disks partitioned under RISCiX. - -ICS partition support -CONFIG_ACORN_PARTITION_ICS - Say Y here if you would like to use hard disks under Linux which - were partitioned using the ICS interface on Acorn machines. - -Alpha OSF partition support -CONFIG_OSF_PARTITION - Say Y here if you would like to use hard disks under Linux which - were partitioned on an Alpha machine. - -Macintosh partition map support -CONFIG_MAC_PARTITION - Say Y here if you would like to use hard disks under Linux which - were partitioned on a Macintosh. - -Windows Logical Disk Manager (Dynamic Disk) support (EXPERIMENTAL) -CONFIG_LDM_PARTITION - Say Y here if you would like to use hard disks under Linux which - were partitioned using Windows 2000's or XP's Logical Disk Manager. - They are also known as "Dynamic Disks". - - Windows 2000 introduced the concept of Dynamic Disks to get around - the limitations of the PC's partitioning scheme. The Logical Disk - Manager allows the user to repartition a disk and create spanned, - mirrored, striped or RAID volumes, all without the need for - rebooting. - - Normal partitions are now called Basic Disks under Windows 2000 and - XP. - - Technical documentation to accompany this driver is available from: - . - - If unsure, say N. - -Windows LDM extra logging -CONFIG_LDM_DEBUG - Say Y here if you would like LDM to log verbosely. This could be - helpful if the driver doesn't work as expected and you'd like to - report a bug. - - If unsure, say N. - -PC BIOS (MSDOS partition tables) support -CONFIG_MSDOS_PARTITION - Say Y here if you would like to use hard disks under Linux which - were partitioned on an x86 PC (not necessarily by DOS). - -Amiga partition table support -CONFIG_AMIGA_PARTITION - Say Y here if you would like to use hard disks under Linux which - were partitioned under AmigaOS. - -Atari partition table support -CONFIG_ATARI_PARTITION - Say Y here if you would like to use hard disks under Linux which - were partitioned under the Atari OS. - -BSD disklabel (FreeBSD partition tables) support -CONFIG_BSD_DISKLABEL - FreeBSD uses its own hard disk partition scheme on your PC. It - requires only one entry in the primary partition table of your disk - and manages it similarly to DOS extended partitions, putting in its - first sector a new partition table in BSD disklabel format. Saying Y - here allows you to read these disklabels and further mount FreeBSD - partitions from within Linux if you have also said Y to "UFS - file system support", above. If you don't know what all this is - about, say N. - -Minix subpartition support -CONFIG_MINIX_SUBPARTITION - Minix 2.0.0/2.0.2 subpartition table support for Linux. - Say Y here if you want to mount and use Minix 2.0.0/2.0.2 - subpartitions. - -Sun partition table support -CONFIG_SUN_PARTITION - Like most systems, SunOS uses its own hard disk partition table - format, incompatible with all others. Saying Y here allows you to - read these partition tables and further mount SunOS partitions from - within Linux if you have also said Y to "UFS file system support", - above. This is mainly used to carry data from a SPARC under SunOS to - your Linux box via a removable medium like magneto-optical or ZIP - drives; note however that a good portable way to transport files and - directories between unixes (and even other operating systems) is - given by the tar program ("man tar" or preferably "info tar"). If - you don't know what all this is about, say N. - -Solaris (x86) partition table support -CONFIG_SOLARIS_X86_PARTITION - Like most systems, Solaris x86 uses its own hard disk partition - table format, incompatible with all others. Saying Y here allows you - to read these partition tables and further mount Solaris x86 - partitions from within Linux if you have also said Y to "UFS - file system support", above. - -SGI partition support -CONFIG_SGI_PARTITION - Say Y here if you would like to be able to read the hard disk - partition table format used by SGI machines. - -Intel EFI GUID partition support -CONFIG_EFI_PARTITION - Say Y here if you would like to use hard disks under Linux which - were partitioned using EFI GPT. Presently only useful on the - IA-64 platform. - -Ultrix partition table support -CONFIG_ULTRIX_PARTITION - Say Y here if you would like to be able to read the hard disk - partition table format used by DEC (now Compaq) Ultrix machines. - Otherwise, say N. - -IBM disk label and partition support -CONFIG_IBM_PARTITION - You have to say Y here if you would like to be able to read volume - labels of IBM DASD disks. These can be ECKD DASD disks with - compatible disk layout (cdl) and standard Linux disk layout (ldl), - FBA DASD disks and CMS reserved minidisks. - Otherwise, say N and you will not be able to access these disks. - -ADFS file system support -CONFIG_ADFS_FS - The Acorn Disc Filing System is the standard file system of the - RiscOS operating system which runs on Acorn's ARM-based Risc PC - systems and the Acorn Archimedes range of machines. If you say Y - here, Linux will be able to read from ADFS partitions on hard drives - and from ADFS-formatted floppy discs. If you also want to be able to - write to those devices, say Y to "ADFS write support" below. - - The ADFS partition should be the first partition (i.e., - /dev/[hs]d?1) on each of your drives. Please read the file - for further details. - - This code is also available as a module called adfs.o ( = code which - can be inserted in and removed from the running kernel whenever you - want). If you want to compile it as a module, say M here and read - . - - If unsure, say N. - -ADFS write support (DANGEROUS) -CONFIG_ADFS_FS_RW - If you say Y here, you will be able to write to ADFS partitions on - hard drives and ADFS-formatted floppy disks. This is experimental - codes, so if you're unsure, say N. - -JFS filesystem support -CONFIG_JFS_FS - This is a port of IBM's Journalling Filesystem . More information is - available in the file Documentation/filesystems/jfs.txt. - - If you do not intend to use the JFS filesystem, say N. - -JFS Debugging -CONFIG_JFS_DEBUG - If you are experiencing any problems with the JFS filesystem, say - Y here. This will result in additional debugging messages to be - written to the system log. Under normal circumstances, this - results in very little overhead. - -JFS Statistics -CONFIG_JFS_STATISTICS - Enabling this option will cause statistics from the JFS file system - to be made available to the user in the /proc/fs/jfs/ directory. - -/dev/pts file system for Unix98 PTYs -CONFIG_DEVPTS_FS - You should say Y here if you said Y to "Unix98 PTY support" above. - You'll then get a virtual file system which can be mounted on - /dev/pts with "mount -t devpts". This, together with the pseudo - terminal master multiplexer /dev/ptmx, is used for pseudo terminal - support as described in The Open Group's Unix98 standard: in order - to acquire a pseudo terminal, a process opens /dev/ptmx; the number - of the pseudo terminal is then made available to the process and the - pseudo terminal slave can be accessed as /dev/pts/. What was - traditionally /dev/ttyp2 will then be /dev/pts/2, for example. - - The GNU C library glibc 2.1 contains the requisite support for this - mode of operation; you also need client programs that use the Unix98 - API. Please read for more information - about the Unix98 pty devices. - - Note that the experimental "/dev file system support" - (CONFIG_DEVFS_FS) is a more general facility. - -FreeVxFS file system support (VERITAS VxFS(TM) compatible) -CONFIG_VXFS_FS - FreeVxFS is a file system driver that support the VERITAS VxFS(TM) - file system format. VERITAS VxFS(TM) is the standard file system - of SCO UnixWare (and possibly others) and optionally available - for Sunsoft Solaris, HP-UX and many other operating systems. - Currently only readonly access is supported. - - NOTE: the file system type as used by mount(1), mount(2) and - fstab(5) is 'vxfs' as it describes the file system format, not - the actual driver. - - This file system is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called freevxfs.o. If you want to compile it as a - module, say M here and read . If - unsure, say N. - -UnixWare slices support -CONFIG_UNIXWARE_DISKLABEL - Like some systems, UnixWare uses its own slice table inside a - partition (VTOC - Virtual Table of Contents). Its format is - incompatible with all other OSes. Saying Y here allows you to read - VTOC and further mount UnixWare partitions read-only from within - Linux if you have also said Y to "UFS file system support" or - "System V and Coherent file system support", above. - - This is mainly used to carry data from a UnixWare box to your - Linux box via a removable medium like magneto-optical, ZIP or - removable IDE drives. Note, however, that a good portable way to - transport files and directories between unixes (and even other - operating systems) is given by the tar program ("man tar" or - preferably "info tar"). - - If you don't know what all this is about, say N. - -SMB file system support (to mount Windows shares etc.) -CONFIG_SMB_FS - SMB (Server Message Block) is the protocol Windows for Workgroups - (WfW), Windows 95/98, Windows NT and OS/2 Lan Manager use to share - files and printers over local networks. Saying Y here allows you to - mount their file systems (often called "shares" in this context) and - access them just like any other Unix directory. Currently, this - works only if the Windows machines use TCP/IP as the underlying - transport protocol, and not NetBEUI. For details, read - and the SMB-HOWTO, - available from . - - Note: if you just want your box to act as an SMB *server* and make - files and printing services available to Windows clients (which need - to have a TCP/IP stack), you don't need to say Y here; you can use - the program SAMBA (available from ) - for that. - - General information about how to connect Linux, Windows machines and - Macs is on the WWW at . - - If you want to compile the SMB support as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want), say M here and read . The - module will be called smbfs.o. Most people say N, however. - -Use a default NLS -CONFIG_SMB_NLS_DEFAULT - Enabling this will make smbfs use nls translations by default. You - need to specify the local charset (CONFIG_NLS_DEFAULT) in the nls - settings and you need to give the default nls for the SMB server as - CONFIG_SMB_NLS_REMOTE. - - The nls settings can be changed at mount time, if your smbmount - supports that, using the codepage and iocharset parameters. - - smbmount from samba 2.2.0 or later supports this. - -Default Remote NLS Option -CONFIG_SMB_NLS_REMOTE - This setting allows you to specify a default value for which - codepage the server uses. If this field is left blank no - translations will be done by default. The local codepage/charset - default to CONFIG_NLS_DEFAULT. - - The nls settings can be changed at mount time, if your smbmount - supports that, using the codepage and iocharset parameters. - - smbmount from samba 2.2.0 or later supports this. - -Enable Unix Extensions -CONFIG_SMB_UNIX - Enabling this will make smbfs use the CIFS Unix Extensions if - supported by the server. These extensions allows use of unix user - ids, permissions, file modes, symlinks, etc that normally do not - work on smbfs. - - Samba 3.0 servers supports these extensions. - - If you don't know what all this is about, it is safe to say Y. - -Coda file system support (advanced network fs) -CONFIG_CODA_FS - Coda is an advanced network file system, similar to NFS in that it - enables you to mount file systems of a remote server and access them - with regular Unix commands as if they were sitting on your hard - disk. Coda has several advantages over NFS: support for - disconnected operation (e.g. for laptops), read/write server - replication, security model for authentication and encryption, - persistent client caches and write back caching. - - If you say Y here, your Linux box will be able to act as a Coda - *client*. You will need user level code as well, both for the - client and server. Servers are currently user level, i.e. they need - no kernel support. Please read - and check out the Coda - home page . - - If you want to compile the coda client support as a module ( = code - which can be inserted in and removed from the running kernel - whenever you want), say M here and read - . The module will be called coda.o. - -InterMezzo file system support (replicating fs) -CONFIG_INTERMEZZO_FS - InterMezzo is a networked file system with disconnected operation - and kernel level write back caching. It is most often used for - replicating potentially large trees or keeping laptop/desktop copies - in sync. - - If you say Y or M your kernel or module will provide InterMezzo - support. You will also need a file server daemon, which you can get - from . - -NCP file system support (to mount NetWare volumes) -CONFIG_NCP_FS - NCP (NetWare Core Protocol) is a protocol that runs over IPX and is - used by Novell NetWare clients to talk to file servers. It is to - IPX what NFS is to TCP/IP, if that helps. Saying Y here allows you - to mount NetWare file server volumes and to access them just like - any other Unix directory. For details, please read the file - in the kernel source and - the IPX-HOWTO from . - - You do not have to say Y here if you want your Linux box to act as a - file *server* for Novell NetWare clients. - - General information about how to connect Linux, Windows machines and - Macs is on the WWW at . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ncpfs.o. Say N unless you are connected to a Novell - network. - -Packet signatures -CONFIG_NCPFS_PACKET_SIGNING - NCP allows packets to be signed for stronger security. If you want - security, say Y. Normal users can leave it off. To be able to use - packet signing you must use ncpfs > 2.0.12. - -Proprietary file locking -CONFIG_NCPFS_IOCTL_LOCKING - Allows locking of records on remote volumes. Say N unless you have - special applications which are able to utilize this locking scheme. - -Clear remove/delete inhibit when needed -CONFIG_NCPFS_STRONG - Allows manipulation of files flagged as Delete or Rename Inhibit. - To use this feature you must mount volumes with the ncpmount - parameter "-s" (ncpfs-2.0.12 and newer). Say Y unless you are not - mounting volumes with -f 444. - -Use NFS namespace if available -CONFIG_NCPFS_NFS_NS - Allows you to utilize NFS namespace on NetWare servers. It brings - you case sensitive filenames. Say Y. You can disable it at - mount-time with the `-N nfs' parameter of ncpmount. - -Use LONG (OS/2) namespace if available -CONFIG_NCPFS_OS2_NS - Allows you to utilize OS2/LONG namespace on NetWare servers. - Filenames in this namespace are limited to 255 characters, they are - case insensitive, and case in names is preserved. Say Y. You can - disable it at mount time with the -N os2 parameter of ncpmount. - -Lowercase DOS filenames on LONG namespace volume -CONFIG_NCPFS_SMALLDOS - If you say Y here, every filename on a NetWare server volume using - the OS2/LONG namespace and created under DOS or on a volume using - DOS namespace will be converted to lowercase characters. - Saying N here will give you these filenames in uppercase. - - This is only a cosmetic option since the OS2/LONG namespace is case - insensitive. The only major reason for this option is backward - compatibility when moving from DOS to OS2/LONG namespace support. - Long filenames (created by Win95) will not be affected. - - This option does not solve the problem that filenames appear - differently under Linux and under Windows, since Windows does an - additional conversions on the client side. You can achieve similar - effects by saying Y to "Allow using of Native Language Support" - below. - -Use Native Language Support -CONFIG_NCPFS_NLS - Allows you to use codepages and I/O charsets for file name - translation between the server file system and input/output. This - may be useful, if you want to access the server with other operating - systems, e.g. Windows 95. See also NLS for more Information. - - To select codepages and I/O charsets use ncpfs-2.2.0.13 or newer. - -Symbolic links and mode permission bits -CONFIG_NCPFS_EXTRAS - This enables the use of symbolic links and an execute permission - bit on NCPFS. The file server need not have long name space or NFS - name space loaded for these to work. - - To use the new attributes, it is recommended to use the flags - '-f 600 -d 755' on the ncpmount command line. - -Default NLS Option -CONFIG_NLS_DEFAULT - The default NLS used when mounting file system. Note, that this is - the NLS used by your console, not the NLS used by a specific file - system (if different) to store data (filenames) on a disk. - Currently, the valid values are: - big5, cp437, cp737, cp775, cp850, cp852, cp855, cp857, cp860, cp861, - cp862, cp863, cp864, cp865, cp866, cp869, cp874, cp932, cp936, - cp949, cp950, cp1250, cp1251, cp1255, euc-jp, euc-kr, gb2312, iso8859-1, - iso8859-2, iso8859-3, iso8859-4, iso8859-5, iso8859-6, iso8859-7, - iso8859-8, iso8859-9, iso8859-13, iso8859-14, iso8859-15, - koi8-r, koi8-ru, koi8-u, sjis, tis-620, utf8. - If you specify a wrong value, it will use the built-in NLS; - compatible with iso8859-1. - - If unsure, specify it as "iso8859-1". - -Codepage 437 (United States, Canada) -CONFIG_NLS_CODEPAGE_437 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored - in so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage that is used in - the United States and parts of Canada. This is recommended. - -Codepage 737 (Greek) -CONFIG_NLS_CODEPAGE_737 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored - in so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage that is used for - Greek. If unsure, say N. - -Codepage 775 (Baltic Rim) -CONFIG_NLS_CODEPAGE_775 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored - in so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage that is used - for the Baltic Rim Languages (Latvian and Lithuanian). If unsure, - say N. - -Codepage 850 (Europe) -CONFIG_NLS_CODEPAGE_850 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage that is used for - much of Europe -- United Kingdom, Germany, Spain, Italy, and [add - more countries here]. It has some characters useful to many European - languages that are not part of the US codepage 437. - - If unsure, say Y. - -Codepage 852 (Central/Eastern Europe) -CONFIG_NLS_CODEPAGE_852 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the Latin 2 codepage used by DOS - for much of Central and Eastern Europe. It has all the required - characters for these languages: Albanian, Croatian, Czech, English, - Finnish, Hungarian, Irish, German, Polish, Rumanian, Serbian (Latin - transcription), Slovak, Slovenian, and Serbian. - -Codepage 855 (Cyrillic) -CONFIG_NLS_CODEPAGE_855 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage for Cyrillic. - -Codepage 857 (Turkish) -CONFIG_NLS_CODEPAGE_857 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage for Turkish. - -Codepage 860 (Portuguese) -CONFIG_NLS_CODEPAGE_860 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage for Portuguese. - -Codepage 861 (Icelandic) -CONFIG_NLS_CODEPAGE_861 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage for Icelandic. - -Codepage 862 (Hebrew) -CONFIG_NLS_CODEPAGE_862 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage for Hebrew. - -Codepage 863 (Canadian French) -CONFIG_NLS_CODEPAGE_863 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage for Canadian - French. - -Codepage 864 (Arabic) -CONFIG_NLS_CODEPAGE_864 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage for Arabic. - -Codepage 865 (Norwegian, Danish) -CONFIG_NLS_CODEPAGE_865 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage for the Nordic - European countries. - -Codepage 866 (Cyrillic/Russian) -CONFIG_NLS_CODEPAGE_866 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage for - Cyrillic/Russian. - -Codepage 869 (Greek) -CONFIG_NLS_CODEPAGE_869 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage for Greek. - -Thai charset (CP874, TIS-620) -CONFIG_NLS_CODEPAGE_874 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage for Thai. - -Windows CP1251 (Bulgarian, Belarusian) -CONFIG_NLS_CODEPAGE_1251 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage for Russian and - Bulgarian and Belarusian. - -Japanese charsets (Shift-JIS, EUC-JP) -CONFIG_NLS_CODEPAGE_932 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage for Shift-JIS - or EUC-JP. To use EUC-JP, you can use 'euc-jp' as mount option or - NLS Default value during kernel configuration, instead of 'cp932'. - -Simplified Chinese charset (CP936, GB2312) -CONFIG_NLS_CODEPAGE_936 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage for Simplified - Chinese(GBK). - -Korean charset (CP949, EUC-KR) -CONFIG_NLS_CODEPAGE_949 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage for UHC. - -Traditional Chinese charset (Big5) -CONFIG_NLS_CODEPAGE_950 - The Microsoft FAT file system family can deal with filenames in - native language character sets. These character sets are stored in - so-called DOS codepages. You need to include the appropriate - codepage if you want to be able to read/write these filenames on - DOS/Windows partitions correctly. This does apply to the filenames - only, not to the file contents. You can include several codepages; - say Y here if you want to include the DOS codepage for Traditional - Chinese(Big5). - -Central European (Codepage 1250) -CONFIG_NLS_CODEPAGE_1250 - If you want to display filenames with native language characters - from the Microsoft FAT file system family or from JOLIET CDROMs - correctly on the screen, you need to include the appropriate - input/output character sets. Say Y here for the Windows CP-1250 - character set, which works for most Latin-written Slavic and Central - European languages: Czech, German, Hungarian, Polish, Rumanian, Croatian, - Slovak, Slovene. - -NLS ISO 8859-1 (Latin 1; Western European Languages) -CONFIG_NLS_ISO8859_1 - If you want to display filenames with native language characters - from the Microsoft FAT file system family or from JOLIET CD-ROMs - correctly on the screen, you need to include the appropriate - input/output character sets. Say Y here for the Latin 1 character - set, which covers most West European languages such as Albanian, - Catalan, Danish, Dutch, English, Faeroese, Finnish, French, German, - Galician, Irish, Icelandic, Italian, Norwegian, Portuguese, Spanish, - and Swedish. It is also the default for the US. If unsure, say Y. - -NLS ISO 8859-2 (Latin 2; Slavic/Central European Languages) -CONFIG_NLS_ISO8859_2 - If you want to display filenames with native language characters - from the Microsoft FAT file system family or from JOLIET CD-ROMs - correctly on the screen, you need to include the appropriate - input/output character sets. Say Y here for the Latin 2 character - set, which works for most Latin-written Slavic and Central European - languages: Czech, German, Hungarian, Polish, Rumanian, Croatian, - Slovak, Slovene. - -NLS ISO 8859-3 (Latin 3; Esperanto, Galician, Maltese, Turkish) -CONFIG_NLS_ISO8859_3 - If you want to display filenames with native language characters - from the Microsoft FAT file system family or from JOLIET CD-ROMs - correctly on the screen, you need to include the appropriate - input/output character sets. Say Y here for the Latin 3 character - set, which is popular with authors of Esperanto, Galician, Maltese, - and Turkish. - -NLS ISO 8859-4 (Latin 4; old Baltic charset) -CONFIG_NLS_ISO8859_4 - If you want to display filenames with native language characters - from the Microsoft FAT file system family or from JOLIET CD-ROMs - correctly on the screen, you need to include the appropriate - input/output character sets. Say Y here for the Latin 4 character - set which introduces letters for Estonian, Latvian, and - Lithuanian. It is an incomplete predecessor of Latin 7. - -NLS ISO 8859-5 (Cyrillic) -CONFIG_NLS_ISO8859_5 - If you want to display filenames with native language characters - from the Microsoft FAT file system family or from JOLIET CD-ROMs - correctly on the screen, you need to include the appropriate - input/output character sets. Say Y here for ISO8859-5, a Cyrillic - character set with which you can type Bulgarian, Belarusian, - Macedonian, Russian, Serbian, and Ukrainian. Note that the charset - KOI8-R is preferred in Russia. - -NLS ISO 8859-6 (Arabic) -CONFIG_NLS_ISO8859_6 - If you want to display filenames with native language characters - from the Microsoft FAT file system family or from JOLIET CD-ROMs - correctly on the screen, you need to include the appropriate - input/output character sets. Say Y here for ISO8859-6, the Arabic - character set. - -NLS ISO 8859-7 (Modern Greek) -CONFIG_NLS_ISO8859_7 - If you want to display filenames with native language characters - from the Microsoft FAT file system family or from JOLIET CD-ROMs - correctly on the screen, you need to include the appropriate - input/output character sets. Say Y here for ISO8859-7, the Modern - Greek character set. - -Hebrew charsets (ISO-8859-8, CP1255) -CONFIG_NLS_ISO8859_8 - If you want to display filenames with native language characters - from the Microsoft FAT file system family or from JOLIET CD-ROMs - correctly on the screen, you need to include the appropriate - input/output character sets. Say Y here for ISO8859-8, the Hebrew - character set. - -NLS ISO 8859-9 (Latin 5; Turkish) -CONFIG_NLS_ISO8859_9 - If you want to display filenames with native language characters - from the Microsoft FAT file system family or from JOLIET CD-ROMs - correctly on the screen, you need to include the appropriate - input/output character sets. Say Y here for the Latin 5 character - set, and it replaces the rarely needed Icelandic letters in Latin 1 - with the Turkish ones. Useful in Turkey. - -NLS ISO 8859-10 (Latin 6; Nordic) -CONFIG_NLS_ISO8859_10 - If you want to display filenames with native language characters - from the Microsoft FAT file system family or from JOLIET CD-ROMs - correctly on the screen, you need to include the appropriate - input/output character sets. Say Y here for the Latin 6 character - set, which adds the last Inuit (Greenlandic) and Sami (Lappish) - letters that were missing in Latin 4 to cover the entire Nordic - area. - -NLS ISO 8859-13 (Latin 7; Baltic) -CONFIG_NLS_ISO8859_13 - If you want to display filenames with native language characters - from the Microsoft FAT file system family or from JOLIET CD-ROMs - correctly on the screen, you need to include the appropriate - input/output character sets. Say Y here for the Latin 7 character - set, which supports modern Baltic languages including Latvian - and Lithuanian. - -NLS ISO 8859-14 (Latin 8; Celtic) -CONFIG_NLS_ISO8859_14 - If you want to display filenames with native language characters - from the Microsoft FAT file system family or from JOLIET CD-ROMs - correctly on the screen, you need to include the appropriate - input/output character sets. Say Y here for the Latin 8 character - set, which adds the last accented vowels for Welsh (aka Cymraeg) - (and Manx Gaelic) that were missing in Latin 1. - has further information. - -NLS ISO 8859-15 (Latin 9; Western European languages with Euro) -CONFIG_NLS_ISO8859_15 - If you want to display filenames with native language characters - from the Microsoft FAT file system family or from JOLIET CD-ROMs - correctly on the screen, you need to include the appropriate - input/output character sets. Say Y here for the Latin 9 character - set, which covers most West European languages such as Albanian, - Catalan, Danish, Dutch, English, Estonian, Faeroese, Finnish, - French, German, Galician, Irish, Icelandic, Italian, Norwegian, - Portuguese, Spanish, and Swedish. Latin 9 is an update to - Latin 1 (ISO 8859-1) that removes a handful of rarely used - characters and instead adds support for Estonian, corrects the - support for French and Finnish, and adds the new Euro character. - If unsure, say Y. - -NLS KOI8-R (Russian) -CONFIG_NLS_KOI8_R - If you want to display filenames with native language characters - from the Microsoft FAT file system family or from JOLIET CD-ROMs - correctly on the screen, you need to include the appropriate - input/output character sets. Say Y here for the preferred Russian - character set. - -NLS KOI8-U/RU (Ukrainian, Belarusian) -CONFIG_NLS_KOI8_U - If you want to display filenames with native language characters - from the Microsoft FAT file system family or from JOLIET CD-ROMs - correctly on the screen, you need to include the appropriate - input/output character sets. Say Y here for the preferred Ukrainian - (koi8-u) and Belarusian (koi8-ru) character sets. - -NLS UTF8 -CONFIG_NLS_UTF8 - If you want to display filenames with native language characters - from the Microsoft FAT file system family or from JOLIET CD-ROMs - correctly on the screen, you need to include the appropriate - input/output character sets. Say Y here for the UTF-8 encoding of - the Unicode/ISO9646 universal character set. - -Virtual terminal -CONFIG_VT - If you say Y here, you will get support for terminal devices with - display and keyboard devices. These are called "virtual" because you - can run several virtual terminals (also called virtual consoles) on - one physical terminal. This is rather useful, for example one - virtual terminal can collect system messages and warnings, another - one can be used for a text-mode user session, and a third could run - an X session, all in parallel. Switching between virtual terminals - is done with certain key combinations, usually Alt-. - - The setterm command ("man setterm") can be used to change the - properties (such as colors or beeping) of a virtual terminal. The - man page console_codes(4) ("man console_codes") contains the special - character sequences that can be used to change those properties - directly. The fonts used on virtual terminals can be changed with - the setfont ("man setfont") command and the key bindings are defined - with the loadkeys ("man loadkeys") command. - - You need at least one virtual terminal device in order to make use - of your keyboard and monitor. Therefore, only people configuring an - embedded system would want to say N here in order to save some - memory; the only way to log into such a system is then via a serial - or network connection. - - If unsure, say Y, or else you won't be able to do much with your new - shiny Linux system :-) - -Support for console on virtual terminal -CONFIG_VT_CONSOLE - The system console is the device which receives all kernel messages - and warnings and which allows logins in single user mode. If you - answer Y here, a virtual terminal (the device used to interact with - a physical terminal) can be used as system console. This is the most - common mode of operations, so you should say Y here unless you want - the kernel messages be output only to a serial port (in which case - you should say Y to "Console on serial port", below). - - If you do say Y here, by default the currently visible virtual - terminal (/dev/tty0) will be used as system console. You can change - that with a kernel command line option such as "console=tty3" which - would use the third virtual terminal as system console. (Try "man - bootparam" or see the documentation of your boot loader (lilo or - loadlin) about how to pass options to the kernel at boot time.) - - If unsure, say Y. - -STI console -CONFIG_STI_CONSOLE - The STI console is the builtin display/keyboard on HP-PARISC - machines. Say Y here to build support for it into your kernel. - The alternative is to use your primary serial port as a console. - -Use MDIO for PHY configuration -CONFIG_USE_MDIO - On some boards the hardware configuration of the ethernet PHY can be - used without any software interaction over the MDIO interface, so - all MII code can be omitted. Say N here if unsure or if you don't - need link status reports. - -860T FEC Ethernet -CONFIG_FEC_ENET - Enable Ethernet support via the Fast Ethernet Controller (FCC) on - the Motorola MPC8260. - -Ethernet on FCC1 -CONFIG_FCC1_ENET - Use MPC8260 fast Ethernet controller 1 to drive Ethernet (default). - -Ethernet on FCC2 -CONFIG_FCC2_ENET - Use MPC8260 fast Ethernet controller 2 to drive Ethernet. - -Ethernet on FCC3 -CONFIG_FCC3_ENET - Use MPC8260 fast Ethernet controller 3 to drive Ethernet. - -CPM SCC Ethernet -CONFIG_SCC_ENET - Enable Ethernet support via the Motorola MPC8xx serial - communications controller. - -# Choice: scc_ethernet -Ethernet on SCC1 -CONFIG_SCC1_ENET - Use MPC8xx serial communications controller 1 to drive Ethernet - (default). - -Ethernet on SCC2 -CONFIG_SCC2_ENET - Use MPC8xx serial communications controller 2 to drive Ethernet. - -Ethernet on SCC3 -CONFIG_SCC3_ENET - Use MPC8xx serial communications controller 3 to drive Ethernet. - -Use Big CPM Ethernet Buffers -CONFIG_ENET_BIG_BUFFERS - Allocate large buffers for MPC8xx Ethernet. Increases throughput - and decreases the likelihood of dropped packets, but costs memory. - -Apple Desktop Bus (ADB) support -CONFIG_ADB - Apple Desktop Bus (ADB) support is for support of devices which - are connected to an ADB port. ADB devices tend to have 4 pins. - If you have an Apple Macintosh prior to the iMac, or a - "Blue and White G3", you probably want to say Y here. Otherwise - say N. - -Support for CUDA based PowerMacs -CONFIG_ADB_CUDA - This provides support for CUDA based Power Macintosh systems. This - includes most OldWorld PowerMacs, the first generation iMacs, the - Blue&White G3 and the Yikes G4 (PCI Graphics). All later models - should use CONFIG_ADB_PMU instead. - - If unsure say Y. - -Support for PMU-based PowerMacs -CONFIG_ADB_PMU - This provides support for PMU based Power Macintosh systems. This - includes all PowerBooks and all AGP-based machines. - - If unsure say Y. - -Include MacIO ADB driver -CONFIG_ADB_MACIO - Say Y here to include direct support for the ADB controller in the - Hydra chip used on PowerPC Macintoshes of the CHRP type. (The Hydra - also includes a MESH II SCSI controller, DBDMA controller, VIA chip, - OpenPIC controller and two RS422/Geoports.) - -Support for ADB keyboard (old driver) -CONFIG_ADB_KEYBOARD - This option allows you to use an ADB keyboard attached to your - machine. Note that this disables any other (ie. PS/2) keyboard - support, even if your machine is physically capable of using both at - the same time. - - If you use an ADB keyboard (4 pin connector), say Y here. - If you use a PS/2 keyboard (6 pin connector), say N here. - -HIL keyboard support -CONFIG_HIL - The "Human Interface Loop" is a older, 8-channel USB-like controller - used in Hewlett Packard PA-RISC based machines. There are a few - cases where it is seen on PC/MAC architectures as well, usually also - manufactured by HP. This driver is based off MACH and BSD drivers, - and implements support for a keyboard attached to the HIL port. - Full support for the USB-like functions and non-keyboard channels of - the HIL is not provided for in this driver. There are vestiges of - mouse support in the driver, but it is probably not working. The - necessary hardware documentation to fully support the HIL controller - and interface it to the linux-input API is lacking. - - Enable this option if you intend to use a HIL keyboard. - -HP System Device Controller support -CONFIG_HP_SDC - This option enables supports for the the "System Device Controller", - an i8042 carrying microcode to manage a few miscellanous devices - on some Hewlett Packard systems. The SDC itself contains a 10ms - resolution timer/clock capable of delivering interrupts on periodic - and one-shot basis. The SDC may also be connected to a battery-backed - real-time clock, a basic audio waveform generator, and an HP-HIL - Master Link Controller serving up to seven input devices. - - By itself this option is rather useless, but enabling it will - enable selection of drivers for the abovementioned devices. - It is, however, incompatible with the old, reliable HIL keyboard - driver, and the new HIL driver is experimental, so if you plan to - use a HIL keyboard as your primary keyboard, you may wish to - keep using that driver until the new HIL drivers have had more - testing. - -Include IOP (IIfx/Quadra 9x0) ADB driver -CONFIG_ADB_IOP - The I/O Processor (IOP) is an Apple custom IC designed to provide - intelligent support for I/O controllers. It is described at - to enable direct - support for it, say 'Y' here. - -Mac II style Apple Desktop Bus support -CONFIG_ADB_MACII - Say Y here if want your kernel to support Macintosh systems that use - the Mac II style ADB. This includes the II, IIx, IIcx, SE/30, IIci, - Quadra 610, Quadra 650, Quadra 700, Quadra 800, Centris 610 and - Centris 650. - -Mac IIsi style Apple Desktop Bus support -CONFIG_ADB_MACIISI - Say Y here if want your kernel to support Macintosh systems that use - the Mac IIsi style ADB. This includes the IIsi, IIvi, IIvx, Classic - II, LC, LC II, LC III, Performa 460, and the Performa 600. - -Apple 68K PowerBook Power Management and Desktop Bus support -CONFIG_ADB_PMU68K - Say Y here if want your kernel to support the m68k based Powerbooks. - This includes the PowerBook 140, PowerBook 145, PowerBook 150, - PowerBook 160, PowerBook 165, PowerBook 165c, PowerBook 170, - PowerBook 180, PowerBook, 180c, PowerBook 190cs, PowerBook 520, - PowerBook Duo 210, PowerBook Duo 230, PowerBook Duo 250, - PowerBook Duo 270c, PowerBook Duo 280 and PowerBook Duo 280c. - -Macintosh IIfx/Quadra 900/Quadra 950 floppy support -CONFIG_BLK_DEV_SWIM_IOP - Say Y here to support the SWIM (Super Woz Integrated Machine) IOP - floppy controller on the Macintosh IIfx and Quadra 900/950. - -Macintosh NS8390 based Ethernet support -CONFIG_MAC8390 - If you want to include a driver to support Nubus or LC-PDS - Ethernet cards using an NS8390 chipset or its equivalent, say Y - and read the Ethernet-HOWTO, available from - . - -Macintosh CS89x0 based Ethernet support -CONFIG_MAC89x0 - Support for CS89x0 chipset based Ethernet cards. If you have a - Nubus or LC-PDS network (Ethernet) card of this type, say Y and - read the Ethernet-HOWTO, available from - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read as well as - . This module will - be called mac89x0.o. - -Macintosh onboard AMD 79C940 MACE based Ethernet support -CONFIG_MACMACE - Support for the onboard AMD 79C940 MACE Ethernet controller used in - the 660AV and 840AV Macintosh. If you have one of these Macintoshes - say Y and read the Ethernet-HOWTO, available from - . - -Macintosh SONIC based Ethernet support (onboard, NuBus, LC, CS) -CONFIG_MACSONIC - Support for NatSemi SONIC based Ethernet devices. This includes - the onboard Ethernet in many Quadras as well as some LC-PDS, - a few Nubus and all known Comm Slot Ethernet cards. If you have - one of these say Y and read the Ethernet-HOWTO, available from - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read as well as - . This module will - be called macsonic.o. - -Macintosh NCR5380 SCSI support -CONFIG_MAC_SCSI - This is the NCR 5380 SCSI controller included on most of the 68030 - based Macintoshes. If you have one of these say Y and read the - SCSI-HOWTO, available from - . - -Macintosh NCR53c9[46] SCSI support -CONFIG_SCSI_MAC_ESP - This is the NCR 53c9x SCSI controller found on most of the 68040 - based Macintoshes. If you have one of these say Y and read the - SCSI-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called mac_esp.o. If you want to compile it as - a module, say M here and read . - -Standard/generic (8250/16550 and compatible UARTs) serial support -CONFIG_SERIAL - This selects whether you want to include the driver for the standard - serial ports. The standard answer is Y. People who might say N - here are those that are setting up dedicated Ethernet WWW/FTP - servers, or users that have one of the various bus mice instead of a - serial mouse and don't intend to use their machine's standard serial - port for anything. (Note that the Cyclades and Stallion multi - serial port drivers do not need this driver built in for them to - work.) - - If you want to compile this driver as a module, say M here and read - . The module will be called - serial.o. - [WARNING: Do not compile this driver as a module if you are using - non-standard serial ports, since the configuration information will - be lost when the driver is unloaded. This limitation may be lifted - in the future.] - - BTW1: If you have a mouseman serial mouse which is not recognized by - the X window system, try running gpm first. - - BTW2: If you intend to use a software modem (also called Winmodem) - under Linux, forget it. These modems are crippled and require - proprietary drivers which are only available under Windows. - - Most people will say Y or M here, so that they can use serial mice, - modems and similar devices connecting to the standard serial ports. - -Support for console on serial port -CONFIG_SERIAL_CONSOLE - If you say Y here, it will be possible to use a serial port as the - system console (the system console is the device which receives all - kernel messages and warnings and which allows logins in single user - mode). This could be useful if some terminal or printer is connected - to that serial port. - - Even if you say Y here, the currently visible virtual console - (/dev/tty0) will still be used as the system console by default, but - you can alter that using a kernel command line option such as - "console=ttyS1". (Try "man bootparam" or see the documentation of - your boot loader (lilo or loadlin) about how to pass options to the - kernel at boot time.) - - If you don't have a VGA card installed and you say Y here, the - kernel will automatically use the first serial line, /dev/ttyS0, as - system console. - - If unsure, say N. - -Support for serial port described by EFI HCDP table -CONFIG_SERIAL_HCDP - If you wish to make the serial console port described by the EFI - HCDP table available for use as serial console or general - purpose port, say Y here. See - . - -Support for PowerMac serial ports -CONFIG_MAC_SERIAL - If you have Macintosh style serial ports (8 pin mini-DIN), say Y - here. If you also have regular serial ports and enable the driver - for them, you can't currently use the serial console feature. - -Comtrol Rocketport support -CONFIG_ROCKETPORT - This is a driver for the Comtrol Rocketport cards which provide - multiple serial ports. You would need something like this to connect - more than two modems to your Linux box, for instance in order to - become a dial-in server. - - If you want to compile this driver as a module, say M here and read - . The module will be called - rocket.o. - -Digiboard Intelligent async support -CONFIG_DIGIEPCA - This is a driver for Digi International's Xx, Xeve, and Xem series - of cards which provide multiple serial ports. You would need - something like this to connect more than two modems to your Linux - box, for instance in order to become a dial-in server. This driver - supports the original PC (ISA) boards as well as PCI, and EISA. If - you have a card like this, say Y here and read the file - . - - NOTE: There is another, separate driver for the Digiboard PC boards: - "Digiboard PC/Xx Support" below. You should (and can) only select - one of the two drivers. - - If you want to compile this driver as a module, say M here and read - . The module will be called epca.o. - -Digiboard PC/Xx Support -CONFIG_DIGI - This is a driver for the Digiboard PC/Xe, PC/Xi, and PC/Xeve cards - that give you many serial ports. You would need something like this - to connect more than two modems to your Linux box, for instance in - order to become a dial-in server. If you have a card like that, say - Y here and read the file . - - If you want to compile this driver as a module, say M here and read - . The module will be called pcxx.o. - -SDL RISCom/8 card support -CONFIG_RISCOM8 - This is a driver for the SDL Communications RISCom/8 multiport card, - which gives you many serial ports. You would need something like - this to connect more than two modems to your Linux box, for instance - in order to become a dial-in server. If you have a card like that, - say Y here and read the file . - - Also it's possible to say M here and compile this driver as kernel - loadable module; the module will be called riscom8.o. - -Computone IntelliPort Plus serial support -CONFIG_COMPUTONE - This driver supports the entire family of Intelliport II/Plus - controllers with the exception of the MicroChannel controllers and - products previous to the Intelliport II. These are multiport cards, - which give you many serial ports. You would need something like this - to connect more than two modems to your Linux box, for instance in - order to become a dial-in server. If you have a card like that, say - Y here and read . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . You will get - two modules called ip2.o and ip2main.o. - -Specialix IO8+ card support -CONFIG_SPECIALIX - This is a driver for the Specialix IO8+ multiport card (both the - ISA and the PCI version) which gives you many serial ports. You - would need something like this to connect more than two modems to - your Linux box, for instance in order to become a dial-in server. - - If you have a card like that, say Y here and read the file - . Also it's possible to say M here - and compile this driver as kernel loadable module which will be - called specialix.o. - -Specialix DTR/RTS pin is RTS -CONFIG_SPECIALIX_RTSCTS - The Specialix IO8+ card can only support either RTS or DTR. If you - say N here, the driver will use the pin as "DTR" when the tty is in - software handshake mode. If you say Y here or hardware handshake is - on, it will always be RTS. Read the file - for more information. - -Specialix RIO system support -CONFIG_RIO - This is a driver for the Specialix RIO, a smart serial card which - drives an outboard box that can support up to 128 ports. Product - information is at . - There are both ISA and PCI versions. - -Support really old RIO/PCI cards -CONFIG_RIO_OLDPCI - Older RIO PCI cards need some initialization-time configuration to - determine the IRQ and some control addresses. If you have a RIO and - this doesn't seem to work, try setting this to Y. - -Cyclades async mux support -CONFIG_CYCLADES - This is a driver for a card that gives you many serial ports. You - would need something like this to connect more than two modems to - your Linux box, for instance in order to become a dial-in server. - For information about the Cyclades-Z card, read - . - - As of 1.3.9x kernels, this driver's minor numbers start at 0 instead - of 32. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called cyclades.o. - - If you haven't heard about it, it's safe to say N. - -Cyclades-Z interrupt mode operation -CONFIG_CYZ_INTR - The Cyclades-Z family of multiport cards allows 2 (two) driver op - modes: polling and interrupt. In polling mode, the driver will check - the status of the Cyclades-Z ports every certain amount of time - (which is called polling cycle and is configurable). In interrupt - mode, it will use an interrupt line (IRQ) in order to check the - status of the Cyclades-Z ports. The default op mode is polling. If - unsure, say N. - -Stallion multiport serial support -CONFIG_STALDRV - Stallion cards give you many serial ports. You would need something - like this to connect more than two modems to your Linux box, for - instance in order to become a dial-in server. If you say Y here, - you will be asked for your specific card model in the next - questions. Make sure to read in - this case. If you have never heard about all this, it's safe to - say N. - -Stallion EasyIO or EC8/32 support -CONFIG_STALLION - If you have an EasyIO or EasyConnection 8/32 multiport Stallion - card, then this is for you; say Y. Make sure to read - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called stallion.o. - -Stallion EC8/64, ONboard, Brumby support -CONFIG_ISTALLION - If you have an EasyConnection 8/64, ONboard, Brumby or Stallion - serial multiport card, say Y here. Make sure to read - . - - To compile it as a module ( = code which can be inserted in and - removed from the running kernel whenever you want), say M here and - read . The module will be called - istallion.o. - -PDC software console support -CONFIG_PDC_CONSOLE - Saying Y here will enable the software based PDC console to be - used as the system console. This is useful for machines in - which the hardware based console has not been written yet. The - following steps must be competed to use the PDC console: - - 1. create the device entry (mknod /dev/ttyB0 c 60 0) - 2. Edit the /etc/inittab to start a getty listening on /dev/ttyB0 - 3. Add device ttyB0 to /etc/securetty (if you want to log on as - root on this console.) - 4. Change the kernel command console parameter to: console=ttyB0 - -Microgate SyncLink adapter support -CONFIG_SYNCLINK - Provides support for the SyncLink ISA and PCI multiprotocol serial - adapters. These adapters support asynchronous and HDLC bit - synchronous communication up to 10Mbps (PCI adapter). - - This driver can only be built as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called synclink.o. If you want to do that, say M - here. - -CONFIG_SYNCLINKMP - Enable support for the SyncLink Multiport (2 or 4 ports) - serial adapter, running asynchronous and HDLC communications up - to 2.048Mbps. Each ports is independently selectable for - RS-232, V.35, RS-449, RS-530, and X.21 - - This driver may be built as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called synclinkmp.o. If you want to do that, say M - here. - -Synchronous HDLC line discipline support -CONFIG_N_HDLC - Allows synchronous HDLC communications with tty device drivers that - support synchronous HDLC such as the Microgate SyncLink adapter. - - This driver can only be built as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called n_hdlc.o. If you want to do that, say M - here. - -Specialix SX (and SI) card support -CONFIG_SX - This is a driver for the SX and SI multiport serial cards. - Please read the file for details. - - This driver can only be built as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called sx.o. If you want to do that, say M here. - -Hayes ESP serial port support -CONFIG_ESPSERIAL - This is a driver which supports Hayes ESP serial ports. Both single - port cards and multiport cards are supported. Make sure to read - . - - To compile this driver as a module ( = code which can be inserted in - and removed from the running kernel whenever you want), say M here - and read . The module will be - called esp.o. If unsure, say N. - -Moxa Intellio support -CONFIG_MOXA_INTELLIO - Say Y here if you have a Moxa Intellio multiport serial card. - - This driver can also be built as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called moxa.o. If you want to do that, say M - here. - -Moxa SmartIO support -CONFIG_MOXA_SMARTIO - Say Y here if you have a Moxa SmartIO multiport serial card. - - This driver can also be built as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called mxser.o. If you want to do that, say M - here. - -Multi-Tech multiport card support -CONFIG_ISI - This is a driver for the Multi-Tech cards which provide several - serial ports. The driver is experimental and can currently only be - built as a module ( = code which can be inserted in and removed from - the running kernel whenever you want). Please read - . The module will be called - isicom.o. - -Unix98 PTY support -CONFIG_UNIX98_PTYS - A pseudo terminal (PTY) is a software device consisting of two - halves: a master and a slave. The slave device behaves identical to - a physical terminal; the master device is used by a process to - read data from and write data to the slave, thereby emulating a - terminal. Typical programs for the master side are telnet servers - and xterms. - - Linux has traditionally used the BSD-like names /dev/ptyxx for - masters and /dev/ttyxx for slaves of pseudo terminals. This scheme - has a number of problems. The GNU C library glibc 2.1 and later, - however, supports the Unix98 naming standard: in order to acquire a - pseudo terminal, a process opens /dev/ptmx; the number of the pseudo - terminal is then made available to the process and the pseudo - terminal slave can be accessed as /dev/pts/. What was - traditionally /dev/ttyp2 will then be /dev/pts/2, for example. - - The entries in /dev/pts/ are created on the fly by a virtual - file system; therefore, if you say Y here you should say Y to - "/dev/pts file system for Unix98 PTYs" as well. - - If you want to say Y here, you need to have the C library glibc 2.1 - or later (equal to libc-6.1, check with "ls -l /lib/libc.so.*"). - Read the instructions in pertaining to - pseudo terminals. It's safe to say N. - -Maximum number of Unix98 PTYs in use (0-2048) -CONFIG_UNIX98_PTY_COUNT - The maximum number of Unix98 PTYs that can be used at any one time. - The default is 256, and should be enough for desktop systems. Server - machines which support incoming telnet/rlogin/ssh connections and/or - serve several X terminals may want to increase this: every incoming - connection and every xterm uses up one PTY. - - When not in use, each additional set of 256 PTYs occupy - approximately 8 KB of kernel memory on 32-bit architectures. - -Parallel printer support -CONFIG_PRINTER - If you intend to attach a printer to the parallel port of your Linux - box (as opposed to using a serial printer; if the connector at the - printer has 9 or 25 holes ["female"], then it's serial), say Y. - Also read the Printing-HOWTO, available from - . - - It is possible to share one parallel port among several devices - (e.g. printer and ZIP drive) and it is safe to compile the - corresponding drivers into the kernel. If you want to compile this - driver as a module however ( = code which can be inserted in and - removed from the running kernel whenever you want), say M here and - read and - . The module will be called lp.o. - - If you have several parallel ports, you can specify which ports to - use with the "lp" kernel command line option. (Try "man bootparam" - or see the documentation of your boot loader (lilo or loadlin) about - how to pass options to the kernel at boot time.) The syntax of the - "lp" command line option can be found in . - - If you have more than 8 printers, you need to increase the LP_NO - macro in lp.c and the PARPORT_MAX macro in parport.h. - -Support for console on line printer -CONFIG_LP_CONSOLE - If you want kernel messages to be printed out as they occur, you - can have a console on the printer. This option adds support for - doing that; to actually get it to happen you need to pass the - option "console=lp0" to the kernel at boot time. - - If the printer is out of paper (or off, or unplugged, or too - busy..) the kernel will stall until the printer is ready again. - By defining CONSOLE_LP_STRICT to 0 (at your own risk) you - can make the kernel continue when this happens, - but it'll lose the kernel messages. - - If unsure, say N. - -Support for user-space parallel port device drivers -CONFIG_PPDEV - Saying Y to this adds support for /dev/parport device nodes. This - is needed for programs that want portable access to the parallel - port, for instance deviceid (which displays Plug-and-Play device - IDs). - - This is the parallel port equivalent of SCSI generic support (sg). - It is safe to say N to this -- it is not needed for normal printing - or parallel port CD-ROM/disk support. - - This support is also available as a module. If you want to compile - it as a module, say M here and read - . The module will be called - ppdev.o. - - If unsure, say N. - -Cobalt Networks support -CONFIG_COBALT - Support for Cobalt Networks x86-based servers. - -Gen III (3000 series) system support -CONFIG_COBALT_GEN_III - This option enables support for the 3000 series of Cobalt Networks - systems. This includes the RaQ 3, RaQ 4, and Qube 3 product lines. - - This platform uses an AMD K6-2 processor, an ALI M1541/1533 chipset, - an optional NCR 53c875 SCSI controller, and two Intel 82559ER or - National Semiconductor DP83815 NICs. - - Getting this option wrong will likely result in a kernel that does - not boot. Selecting support for more than 1 system series will add - bloat to your kernel, but will not cause anything bad to happen. - - If you have a Cobalt Networks System, but aren't sure what kind, - say Y here. - -Gen V (5000 series) system support -CONFIG_COBALT_GEN_V - This option enables support for the 5000 series of Cobalt Networks - systems. This includes the RaQ XTR product line. - - This platform uses Intel Pentium III Coppermine FCPGA CPUs, the - ServerWorks LE chipset (with registered ECC DIMMs only!), two - HighPoint HPT370 IDE controllers, and two National Semiconductor - DP83815 NICs. - - Getting this option wrong will likely result in a kernel that does - not boot. Selecting support for more than 1 system series will add - bloat to your kernel, but will not cause anything bad to happen. - - If you have a Cobalt Networks System, but aren't sure what kind, - say Y here. - -Create legacy /proc files -CONFIG_COBALT_OLDPROC - This option forces some Cobalt Networks drivers to support legacy - files in /proc. Older versions of these drivers exported files - directly in /proc, as opposed to the newer /proc/cobalt. If you say - N to this option, the old filenames will no longer be exported. - Regardless of your selection here, files in /proc/cobalt will be - exported. Of course, you have to include support for /proc fs, too. - - It is safe to say Y here. - -Front panel LCD support -CONFIG_COBALT_LCD - This enables support for the Cobalt Networks front panel. This is - for the LCD panel and buttons. The primary method for connection is - via the parallel port (IO base 0x370), but newer systems use an - I2C bus. - - If you have a Cobalt Networks system, you should say Y here. - -Software controlled LED support -CONFIG_COBALT_LED - This enables support for the software-controlled LEDs on Cobalt - Networks systems. This includes the fault light and front panel - LEDs on the RaQ XTR, the lightbar on the Qube 3, and others. - - If you have a Cobalt Networks system, you should say Y here. - -Silicon serial number support -CONFIG_COBALT_SERNUM - This enables support for the on-board serial number on Cobalt - Networks systems. This is a universally-unique 64-bit serial - number. Some systems use a Dallas DS2401 chip, others have an I2C - based EEPROM. - - If you select Y here, the files /proc/cobalt/hostid and - /proc/cobalt/serialnumber will be created. The hostid file contains - a 32 bit integer generated from the serial number, in binary form. - The serialnumber file contains the hexadecimal representation of the - serial number, in ASCII. - - If you have a Cobalt Networks system, you should say Y here. - -Chipset watchdog timer support -CONFIG_COBALT_WDT - This enables support for the watchdog timer built into Cobalt - chipsets. The timer wakes up periodically, to make find out if - system has hung, or disabled interrupts too long. The result of - detecting a hang is a hard reboot. - - If you have a Cobalt Networks system, you should say Y here. - -Thermal sensor support -CONFIG_COBALT_THERMAL - This enables support for the thermal sensor(s) built into Cobalt - Networks systems. This driver exports /proc/cobalt/thermal_sensors. - - If you have a Cobalt Networks system, you should say Y here. - -Fan tachometer support -CONFIG_COBALT_FANS - This enables support for the fan tachometers built into some Cobalt - Networks systems. This driver exports /proc/cobalt/faninfo. Some - Cobalt software depends on this feature, and enabling it does not - cause any risks. - - If you have a Cobalt Networks system, you should say Y here, unless - you are absolutely sure. - -Disk drive ruler support -CONFIG_COBALT_RULER - This enables support for the cobalt hard drive ruler, found on some - Cobalt systems, including the RaQ XTR. This is the device that - enables swapping of drives. It is not needed for basic disk - operation. Enabling this on a system with no ruler will have no - adverse effects. - - If you have a Cobalt Networks system, you should say Y here, - unless you are absolutely sure. - -IT8172G Sound -CONFIG_SOUND_IT8172 - Say Y here to support the on-board sound generator on the Integrated - Technology Express, Inc. ITE8172 SBC. Vendor page at - ; picture of the - board at . - -I2C support -CONFIG_I2C - I2C (pronounce: I-square-C) is a slow serial bus protocol used in - many micro controller applications and developed by Philips. SMBus, - or System Management Bus is a subset of the I2C protocol. More - information is contained in the directory , - especially in the file called "summary" there. - - Both I2C and SMBus are supported here. You will need this for - hardware sensors support, and also for Video For Linux support. - Specifically, if you want to use a BT848 based frame grabber/overlay - boards under Linux, say Y here and also to "I2C bit-banging - interfaces", below. - - If you want I2C support, you should say Y here and also to the - specific driver for your bus adapter(s) below. If you say Y to - "/proc file system" below, you will then get a /proc interface which - is documented in . - - This I2C support is also available as a module. If you want to - compile it as a module, say M here and read - . - The module will be called i2c-core.o. - -UltraSPARC-III bootbus i2c controller driver -CONFIG_BBC_I2C - The BBC devices on the UltraSPARC III have two I2C controllers. The - first I2C controller connects mainly to configuration PROMs (NVRAM, - CPU configuration, DIMM types, etc.). The second I2C controller - connects to environmental control devices such as fans and - temperature sensors. The second controller also connects to the - smartcard reader, if present. Say Y to enable support for these. - -I2C bit-banging interfaces -CONFIG_I2C_ALGOBIT - This allows you to use a range of I2C adapters called bit-banging - adapters. Say Y if you own an I2C adapter belonging to this class - and then say Y to the specific driver for you adapter below. - - This support is also available as a module. If you want to compile - it as a module, say M here and read - . - The module will be called i2c-algo-bit.o. - -Philips style parallel port adapter -CONFIG_I2C_PHILIPSPAR - This supports parallel-port I2C adapters made by Philips. Say Y if - you own such an adapter. - - This driver is also available as a module. If you want to compile - it as a module, say M here and read - . - The module will be called i2c-philips-par.o. - - Note that if you want support for different parallel port devices, - life will be much easier if you compile them all as modules. - -ELV adapter -CONFIG_I2C_ELV - This supports parallel-port I2C adapters called ELV. Say Y if you - own such an adapter. - - This driver is also available as a module. If you want to compile - it as a module, say M here and read - . - The module will be called i2c-elv.o. - -Velleman K8000 adapter -CONFIG_I2C_VELLEMAN - This supports the Velleman K8000 parallel-port I2C adapter. Say Y - if you own such an adapter. - - This driver is also available as a module. If you want to compile - it as a module, say M here and read - . - The module will be called i2c-velleman.o. - -I2C PCF 8584 interfaces -CONFIG_I2C_ALGOPCF - This allows you to use a range of I2C adapters called PCF adapters. - Say Y if you own an I2C adapter belonging to this class and then say - Y to the specific driver for you adapter below. - - This support is also available as a module. If you want to compile - it as a module, say M here and read - . - The module will be called i2c-algo-pcf.o. - -Elektor ISA card -CONFIG_I2C_ELEKTOR - This supports the PCF8584 ISA bus I2C adapter. Say Y if you own - such an adapter. - - This driver is also available as a module. If you want to compile - it as a module, say M here and read - . - The module will be called i2c-elektor.o. - -ITE I2C Algorithm -CONFIG_ITE_I2C_ALGO - This supports the use the ITE8172 I2C interface found on some MIPS - systems. Say Y if you have one of these. You should also say Y for - the ITE I2C peripheral driver support below. - - This support is also available as a module. If you want to compile - it as a modules, say M here and read - . - The module will be called i2c-algo-ite.o. - -ITE I2C Adapter -CONFIG_ITE_I2C_ADAP - This supports the ITE8172 I2C peripheral found on some MIPS - systems. Say Y if you have one of these. You should also say Y for - the ITE I2C driver algorithm support above. - - This support is also available as a module. If you want to compile - it as a module, say M here and read - . - The module will be called i2c-adap-ite.o. - -SiByte I2C Algorithm -CONFIG_I2C_ALGO_SIBYTE - Supports the SiByte SOC on-chip I2C interfaces (2 channels). - -MAX1617 Temperature Sensor -CONFIG_I2C_MAX1617 - This builds a simple polling driver for the Maxim 1617 temperature - sensor. Currently the device is only supported on a SiByte I2C - adapter, and the driver prints status updates to the system log. - -SGI I2C Algorithm -CONFIG_I2C_ALGO_SGI - Supports the SGI interfaces like the ones found on SGI Indy VINO - or SGI O2 MACE. - -I2C device interface -CONFIG_I2C_CHARDEV - Say Y here to use i2c-* device files, usually found in the /dev - directory on your system. They make it possible to have user-space - programs use the I2C bus. Information on how to do this is - contained in the file . - - This code is also available as a module. If you want to compile - it as a module, say M here and read - . - The module will be called i2c-dev.o. - -I2C /proc interface (required for hardware sensors) -CONFIG_I2C_PROC - This provides support for i2c device entries in the /proc filesystem. - The entries will be found in /proc/sys/dev/sensors. - - This code is also available as a module. If you want to compile - it as a module, say M here and read . - The module will be called i2c-proc.o. - -Powermac Keywest I2C interface -CONFIG_I2C_KEYWEST - This supports the use of the I2C interface in the combo-I/O - chip on recent Apple machines. Say Y if you have such a machine. - - This driver is also available as a module. If you want to compile - it as a module, say M here and read Documentation/modules.txt. - The module will be called i2c-keywest.o. - -Bus Mouse Support -CONFIG_BUSMOUSE - Say Y here if your machine has a bus mouse as opposed to a serial - mouse. Most people have a regular serial MouseSystem or - Microsoft mouse (made by Logitech) that plugs into a COM port - (rectangular with 9 or 25 pins). These people say N here. - - If you have a laptop, you either have to check the documentation or - experiment a bit to find out whether the trackball is a serial mouse - or not; it's best to say Y here for you. - - This is the generic bus mouse driver code. If you have a bus mouse, - you will have to say Y here and also to the specific driver for your - mouse below. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called busmouse.o. If you want to compile it as a - module, say M here and read . - -Mouse Support (not serial and bus mice) -CONFIG_MOUSE - This is for machines with a mouse which is neither a serial nor a - bus mouse. Examples are PS/2 mice (such as the track balls on some - laptops) and some digitizer pads. Most people have a regular serial - MouseSystem or Microsoft mouse (made by Logitech) that plugs into a - COM port (rectangular with 9 or 25 pins). These people say N here. - If you have something else, read the Busmouse-HOWTO, available from - . This HOWTO contains - information about all non-serial mice, not just bus mice. - - If you have a laptop, you either have to check the documentation or - experiment a bit to find out whether the trackball is a serial mouse - or not; it's best to say Y here for you. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about non-serial mice. If unsure, say Y. - -Logitech busmouse support -CONFIG_LOGIBUSMOUSE - Logitech mouse connected to a proprietary interface card. It's - generally a round connector with 9 pins. Note that the newer mice - made by Logitech don't use the Logitech protocol anymore; for those, - you don't need this option. You want to read the Busmouse-HOWTO, - available from . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called busmouse.o. If you are unsure, say N and read the - HOWTO nevertheless: it will tell you what you have. - -PS/2 mouse (aka "auxiliary device") support -CONFIG_PSMOUSE - The PS/2 mouse connects to a special mouse port that looks much like - the keyboard port (small circular connector with 6 pins). This way, - the mouse does not use any serial ports. This port can also be used - for other input devices like light pens, tablets, keypads. Compaq, - AST and IBM all use this as their mouse port on currently shipping - machines. The trackballs of some laptops are PS/2 mice also. In - particular, the C&T 82C710 mouse on TI Travelmates is a PS/2 mouse. - - Although PS/2 mice are not technically bus mice, they are explained - in detail in the Busmouse-HOWTO, available from - . - - When using a PS/2 mouse, you can get problems if you want to use the - mouse both on the Linux console and under X. Using the "-R" option - of the Linux mouse managing program gpm (available from - ) solves this problem, or you can get - the "mconv2" utility from . - -C&T 82C710 mouse port support (as on TI Travelmate) -CONFIG_82C710_MOUSE - This is a certain kind of PS/2 mouse used on the TI Travelmate. If - you are unsure, try first to say N here and come back if the mouse - doesn't work. Read the Busmouse-HOWTO, available from - . - -PC110 digitizer pad support -CONFIG_PC110_PAD - This drives the digitizer pad on the IBM PC110 palmtop. It can turn - the digitizer pad into a PS/2 mouse emulation with tap gestures or - into an absolute pad. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called pc110pad.o. - -Microsoft busmouse support -CONFIG_MS_BUSMOUSE - These animals (also called Inport mice) are connected to an - expansion board using a round connector with 9 pins. If this is what - you have, say Y and read the Busmouse-HOWTO, available from - . - - If you are unsure, say N and read the HOWTO nevertheless: it will - tell you what you have. Also be aware that several vendors talk - about 'Microsoft busmouse' and actually mean PS/2 busmouse -- so - count the pins on the connector. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called msbusmouse.o. - -Apple Desktop Bus mouse support -CONFIG_ADBMOUSE - Say Y here if you have this type of bus mouse (4 pin connector) as - is common on Macintoshes. You may want to read the Busmouse-HOWTO, - available from . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called adbmouse.o. - -ATIXL busmouse support -CONFIG_ATIXL_BUSMOUSE - This is a rare type of busmouse that is connected to the back of an - ATI video card. Say Y if you have one of those. Note however that - most mice by ATI are actually Microsoft busmice; you should say Y to - "Microsoft busmouse support" above if you have one of those. Read - the Busmouse-HOWTO, available from - . - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called atixlmouse.o. - - If you are unsure, say N and read the HOWTO nevertheless: it will - tell you what you have. - -QIC-02 tape support -CONFIG_QIC02_TAPE - If you have a non-SCSI tape drive like that, say Y. Or, if you want - to compile this driver as a module ( = code which can be inserted in - and removed from the running kernel whenever you want), say M here - and read . The module will be called - tpqic02.o. - -iSeries Virtual Tape Support -CONFIG_VIOTAPE - If you are running Linux on an iSeries system and you want Linux - to read and/or write a tape drive owned by OS/400, say Y here. - -Do you want runtime configuration for QIC-02 -CONFIG_QIC02_DYNCONF - You can either configure this driver once and for all by editing a - header file (), in which case you - should say N, or you can fetch a program via anonymous FTP which is - able to configure this driver during runtime. The program to do - this is called 'qic02conf' and it is part of the - tpqic02-support-X.Y.tar.gz support package. - - If you want to use the qic02conf program, say Y. - -Floppy tape drive (QIC-80/40/3010/3020/TR-1/TR-2/TR-3) support -CONFIG_FTAPE - If you have a tape drive that is connected to your floppy - controller, say Y here. - - Some tape drives (like the Seagate "Tape Store 3200" or the Iomega - "Ditto 3200" or the Exabyte "Eagle TR-3") come with a "high speed" - controller of their own. These drives (and their companion - controllers) are also supported if you say Y here. - - If you have a special controller (such as the CMS FC-10, FC-20, - Mountain Mach-II, or any controller that is based on the Intel 82078 - FDC like the high speed controllers by Seagate and Exabyte and - Iomega's "Ditto Dash") you must configure it by selecting the - appropriate entries from the "Floppy tape controllers" sub-menu - below and possibly modify the default values for the IRQ and DMA - channel and the IO base in ftape's configuration menu. - - If you want to use your floppy tape drive on a PCI-bus based system, - please read the file . - - The ftape kernel driver is also available as a runtime loadable - module ( = code which can be inserted in and removed from the - running kernel whenever you want). If you want to compile it as a - module, say M here and read . The - module will be called ftape.o. - - Note that the Ftape-HOWTO is out of date (sorry) and documents the - older version 2.08 of this software but still contains useful - information. There is a web page with more recent documentation at - . This page - always contains the latest release of the ftape driver and useful - information (backup software, ftape related patches and - documentation, FAQ). Note that the file system interface has - changed quite a bit compared to previous versions of ftape. Please - read . - -VFS interface for ftape -CONFIG_ZFTAPE - Normally, you want to say Y or M. DON'T say N here or you - WON'T BE ABLE TO USE YOUR FLOPPY TAPE DRIVE. - - The ftape module itself no longer contains the routines necessary - to interface with the kernel VFS layer (i.e. to actually write data - to and read data from the tape drive). Instead the file system - interface (i.e. the hardware independent part of the driver) has - been moved to a separate module. - - If you say M zftape will be compiled as a runtime loadable - module ( = code which can be inserted in and removed from the - running kernel whenever you want). In this case you should read - . The module will be called - zftape.o. - - Regardless of whether you say Y or M here, an additional runtime - loadable module called `zft-compressor.o' which contains code to - support user transparent on-the-fly compression based on Ross - William's lzrw3 algorithm will be produced. If you have enabled the - kernel module loader (i.e. have said Y to "Kernel module loader - support", above) then `zft-compressor.o' will be loaded - automatically by zftape when needed. - - Despite its name, zftape does NOT use compression by default. The - file contains a short description of - the most important changes in the file system interface compared to - previous versions of ftape. The ftape home page - contains - further information. - - IMPORTANT NOTE: zftape can read archives created by previous - versions of ftape and provide file mark support (i.e. fast skipping - between tape archives) but previous version of ftape will lack file - mark support when reading archives produced by zftape. - -Default block size for zftape -CONFIG_ZFT_DFLT_BLK_SZ - If unsure leave this at its default value, i.e. 10240. Note that - you specify only the default block size here. The block size can be - changed at run time using the MTSETBLK tape operation with the - MTIOCTOP ioctl (i.e. with "mt -f /dev/qft0 setblk #BLKSZ" from the - shell command line). - - The probably most striking difference between zftape and previous - versions of ftape is the fact that all data must be written or read - in multiples of a fixed block size. The block size defaults to - 10240 which is what GNU tar uses. The values for the block size - should be either 1 or multiples of 1024 up to a maximum value of - 63488 (i.e. 62 K). If you specify `1' then zftape's builtin - compression will be disabled. - - Reasonable values are `10240' (GNU tar's default block size), - `5120' (afio's default block size), `32768' (default block size some - backup programs assume for SCSI tape drives) or `1' (no restriction - on block size, but disables builtin compression). - -Number of DMA buffers -CONFIG_FT_NR_BUFFERS - Please leave this at `3' unless you REALLY know what you are doing. - It is not necessary to change this value. Values below 3 make the - proper use of ftape impossible, values greater than 3 are a waste of - memory. You can change the amount of DMA memory used by ftape at - runtime with "mt -f /dev/qft0 setdrvbuffer #NUMBUFFERS". Each buffer - wastes 32 KB of memory. Please note that this memory cannot be - swapped out. - -Enable procfs status report (+2kb) -CONFIG_FT_PROC_FS - Optional. Saying Y will result in creation of a directory - `/proc/ftape' under the /proc file system. The files can be viewed - with your favorite pager (i.e. use "more /proc/ftape/history" or - "less /proc/ftape/history" or simply "cat /proc/ftape/history"). The - file will contain some status information about the inserted - cartridge, the kernel driver, your tape drive, the floppy disk - controller and the error history for the most recent use of the - kernel driver. Saying Y will enlarge the size of the ftape driver - by approximately 2 KB. - - WARNING: When compiling ftape as a module (i.e. saying M to "Floppy - tape drive") it is dangerous to use ftape's /proc file system - interface. Accessing `/proc/ftape' while the module is unloaded will - result in a kernel Oops. This cannot be fixed from inside ftape. - -# Choice: ftdebug -Controlling the amount of debugging output of ftape -CONFIG_FT_NORMAL_DEBUG - This option controls the amount of debugging output the ftape driver - is ABLE to produce; it does not increase or diminish the debugging - level itself. If unsure, leave this at its default setting, - i.e. choose "Normal". - - Ftape can print lots of debugging messages to the system console - resp. kernel log files. Reducing the amount of possible debugging - output reduces the size of the kernel module by some KB, so it might - be a good idea to use "None" for emergency boot floppies. - - If you want to save memory then the following strategy is - recommended: leave this option at its default setting "Normal" until - you know that the driver works as expected, afterwards reconfigure - the kernel, this time specifying "Reduced" or "None" and recompile - and install the kernel as usual. Note that choosing "Excessive" - debugging output does not increase the amount of debugging output - printed to the console but only makes it possible to produce - "Excessive" debugging output. - - Please read for a short description - how to control the amount of debugging output. - -Excessive -CONFIG_FT_FULL_DEBUG - Extremely verbose output for driver debugging purposes. - -Reduced -CONFIG_FT_NO_TRACE - Reduced tape driver debugging output. - -None -CONFIG_FT_NO_TRACE_AT_ALL - Suppress all debugging output from the tape drive. - -# Choice: ftcontroller -The floppy drive controller for ftape -CONFIG_FT_STD_FDC - Only change this setting if you have a special controller. If you - didn't plug any add-on card into your computer system but just - plugged the floppy tape cable into the already existing floppy drive - controller then you don't want to change the default setting, - i.e. choose "Standard". - - Choose "MACH-2" if you have a Mountain Mach-2 controller. - Choose "FC-10/FC-20" if you have a Colorado FC-10 or FC-20 - controller. - Choose "Alt/82078" if you have another controller that is located at - an IO base address different from the standard floppy drive - controller's base address of `0x3f0', or uses an IRQ (interrupt) - channel different from `6', or a DMA channel different from - `2'. This is necessary for any controller card that is based on - Intel's 82078 FDC such as Seagate's, Exabyte's and Iomega's "high - speed" controllers. - - If you choose something other than "Standard" then please make - sure that the settings for the IO base address and the IRQ and DMA - channel in the configuration menus below are correct. Use the manual - of your tape drive to determine the correct settings! - - If you are already successfully using your tape drive with another - operating system then you definitely should use the same settings - for the IO base, the IRQ and DMA channel that have proven to work - with that other OS. - - Note that this menu lets you specify only the default setting for - the hardware setup. The hardware configuration can be changed at - boot time (when ftape is compiled into the kernel, i.e. if you - have said Y to "Floppy tape drive") or module load time (i.e. if you - have said M to "Floppy tape drive"). - - Please read also the file which - contains a short description of the parameters that can be set at - boot or load time. If you want to use your floppy tape drive on a - PCI-bus based system, please read the file - . - -IO base for the floppy disk controller used with Ftape -CONFIG_FT_FDC_BASE - You don't need to specify a value if the following default - settings for the base IO address are correct: - <<< MACH-2 : 0x1E0 >>> - <<< FC-10/FC-20: 0x180 >>> - <<< Secondary : 0x370 >>> - Secondary refers to a secondary FDC controller like the "high speed" - controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash. - Please make sure that the setting for the IO base address - specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR - CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already - successfully using the tape drive with another operating system then - you definitely should use the same settings for the IO base that has - proven to work with that other OS. - - Note that this menu lets you specify only the default setting for - the IO base. The hardware configuration can be changed at boot time - (when ftape is compiled into the kernel, i.e. if you specified Y to - "Floppy tape drive") or module load time (i.e. if you have said M to - "Floppy tape drive"). - - Please read also the file which - contains a short description of the parameters that can be set at - boot or load time. - -IRQ channel for the floppy disk controller used with Ftape -CONFIG_FT_FDC_IRQ - You don't need to specify a value if the following default - settings for the interrupt channel are correct: - <<< MACH-2 : 6 >>> - <<< FC-10/FC-20: 9 >>> - <<< Secondary : 6 >>> - Secondary refers to secondary a FDC controller like the "high speed" - controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash. - Please make sure that the setting for the IO base address - specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR - CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already - successfully using the tape drive with another operating system then - you definitely should use the same settings for the IO base that has - proven to work with that other OS. - - Note that this menu lets you specify only the default setting for - the IRQ channel. The hardware configuration can be changed at boot - time (when ftape is compiled into the kernel, i.e. if you said Y to - "Floppy tape drive") or module load time (i.e. if you said M to - "Floppy tape drive"). - - Please read also the file which - contains a short description of the parameters that can be set at - boot or load time. - -DMA channel for the floppy disk controller used with Ftape -CONFIG_FT_FDC_DMA - You don't need to specify a value if the following default - settings for the DMA channel are correct: - <<< MACH-2 : 2 >>> - <<< FC-10/FC-20: 3 >>> - <<< Secondary : 2 >>> - Secondary refers to a secondary FDC controller like the "high speed" - controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash. - Please make sure that the setting for the IO base address - specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR - CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already - successfully using the tape drive with another operating system then - you definitely should use the same settings for the IO base that has - proven to work with that other OS. - - Note that this menu lets you specify only the default setting for - the DMA channel. The hardware configuration can be changed at boot - time (when ftape is compiled into the kernel, i.e. if you said Y to - "Floppy tape drive") or module load time (i.e. if you said M to - "Floppy tape drive"). - - Please read also the file which - contains a short description of the parameters that can be set at - boot or load time. - -FDC FIFO Threshold before requesting DMA service -CONFIG_FT_FDC_THR - Set the FIFO threshold of the FDC. If this is higher the DMA - controller may serve the FDC after a higher latency time. If this is - lower, fewer DMA transfers occur leading to less bus contention. - You may try to tune this if ftape annoys you with "reduced data - rate because of excessive overrun errors" messages. However, this - doesn't seem to have too much effect. - - If unsure, don't touch the initial value, i.e. leave it at "8". - -FDC maximum data rate -CONFIG_FT_FDC_MAX_RATE - With some motherboard/FDC combinations ftape will not be able to - run your FDC/tape drive combination at the highest available - speed. If this is the case you'll encounter "reduced data rate - because of excessive overrun errors" messages and lots of retries - before ftape finally decides to reduce the data rate. - - In this case it might be desirable to tell ftape beforehand that - it need not try to run the tape drive at the highest available - speed. If unsure, leave this disabled, i.e. leave it at 2000 - bits/sec. - -Direct Rendering Manager (XFree86 DRI support) -CONFIG_DRM - Kernel-level support for the Direct Rendering Infrastructure (DRI) - introduced in XFree86 4.0. If you say Y here, you need to select - the module that's right for your graphics card from the list below. - These modules provide support for synchronization, security, and - DMA transfers. Please see for more - details. You should also select and configure AGP - (/dev/agpgart) support. - -Build drivers for new (XFree 4.1) DRM -CONFIG_DRM_NEW - If you set this option, the new DRM version needed by XFree86 4.1 - will be used. Otherwise, the old DRM version will be used, - appropriate for XFree86 4.0. - -3dfx Banshee/Voodoo3+ -CONFIG_DRM_TDFX - Choose this option if you have a 3dfx Banshee or Voodoo3 (or later), - graphics card. If M is selected, the module will be called tdfx.o. - -3dlabs GMX 2000 -CONFIG_DRM_GAMMA - Choose this option if you have a 3dlabs GMX 2000 graphics card. - If M is selected, the module will be called gamma.o. - -ATI Rage 128 -CONFIG_DRM_R128 - Choose this option if you have an ATI Rage 128 graphics card. If M - is selected, the module will be called r128.o. AGP support for - this card is strongly suggested (unless you have a PCI version). - -ATI Radeon -CONFIG_DRM_RADEON - Choose this option if you have an ATI Radeon graphics card. There - are both PCI and AGP versions. You don't need to choose this to - run the Radeon in plain VGA mode. There is a product page at - . - If M is selected, the module will be called radeon.o. - -Intel I810 -CONFIG_DRM_I810 - Choose this option if you have an Intel I810 graphics card. If M is - selected, the module will be called i810.o. AGP support is required - for this driver to work. - -Intel 830M, 845G, 852GM, 855GM, 865G -CONFIG_DRM_I830 - Choose this option if you have a system that has Intel 830M, 845G, - 852GM, 855GM or 865G integrated graphics. If M is selected, the - module will be called i830.o. AGP support is required for this driver - to work. - -Matrox G200/G400/G450 -CONFIG_DRM_MGA - Choose this option if you have a Matrox G200, G400 or G450 graphics - card. If M is selected, the module will be called mga.o. AGP - support is required for this driver to work. - -3dfx Banshee/Voodoo3+ -CONFIG_DRM40_TDFX - Choose this option if you have a 3dfx Banshee or Voodoo3 (or later), - graphics card. If M is selected, the module will be called tdfx.o. - -3dlabs GMX 2000 -CONFIG_DRM40_GAMMA - Choose this option if you have a 3dlabs GMX 2000 graphics card. - If M is selected, the module will be called gamma.o. - -ATI Rage 128 -CONFIG_DRM40_R128 - Choose this option if you have an ATI Rage 128 graphics card. If M - is selected, the module will be called r128.o. AGP support for - this card is strongly suggested (unless you have a PCI version). - -ATI Radeon -CONFIG_DRM40_RADEON - Choose this option if you have an ATI Radeon graphics card. There - are both PCI and AGP versions. You don't need to choose this to - run the Radeon in plain VGA mode. There is a product page at - . - If M is selected, the module will be called radeon.o. - -Intel I810 -CONFIG_DRM40_I810 - Choose this option if you have an Intel I810 graphics card. If M is - selected, the module will be called i810.o. AGP support is required - for this driver to work. - -Matrox G200/G400/G450 -CONFIG_DRM40_MGA - Choose this option if you have a Matrox G200, G400 or G450 graphics - card. If M is selected, the module will be called mga.o. AGP - support is required for this driver to work. - -Creator/Creator3D/Elite3D -CONFIG_DRM_FFB - Choose this option if you have one of Sun's Creator3D-based graphics - and frame buffer cards. Product page at - . - -MTRR (Memory Type Range Register) support -CONFIG_MTRR - On Intel P6 family processors (Pentium Pro, Pentium II and later) - the Memory Type Range Registers (MTRRs) may be used to control - processor access to memory ranges. This is most useful if you have - a video (VGA) card on a PCI or AGP bus. Enabling write-combining - allows bus write transfers to be combined into a larger transfer - before bursting over the PCI/AGP bus. This can increase performance - of image write operations 2.5 times or more. Saying Y here creates a - /proc/mtrr file which may be used to manipulate your processor's - MTRRs. Typically the X server should use this. - - This code has a reasonably generic interface so that similar - control registers on other processors can be easily supported - as well: - - The Cyrix 6x86, 6x86MX and M II processors have Address Range - Registers (ARRs) which provide a similar functionality to MTRRs. For - these, the ARRs are used to emulate the MTRRs. - The AMD K6-2 (stepping 8 and above) and K6-3 processors have two - MTRRs. The Centaur C6 (WinChip) has 8 MCRs, allowing - write-combining. All of these processors are supported by this code - and it makes sense to say Y here if you have one of them. - - Saying Y here also fixes a problem with buggy SMP BIOSes which only - set the MTRRs for the boot CPU and not for the secondary CPUs. This - can lead to all sorts of problems, so it's good to say Y here. - - You can safely say Y even if your machine doesn't have MTRRs, you'll - just add about 9 KB to your kernel. - - See for more information. - -CPU clock frequency of your DEC Alpha -CONFIG_FT_ALPHA_CLOCK - On some DEC Alpha machines the CPU clock frequency cannot be - determined automatically, so you need to specify it here ONLY if - running a DEC Alpha, otherwise this setting has no effect. - -Double Talk PC internal speech card support -CONFIG_DTLK - This driver is for the DoubleTalk PC, a speech synthesizer - manufactured by RC Systems (). It is also - called the `internal DoubleTalk'. If you want to compile this as a - module ( = code which can be inserted in and removed from the - running kernel whenever you want), say M here and read - . The module will be called dtlk.o. - -Siemens R3964 serial protocol support -CONFIG_R3964 - This driver allows synchronous communication with devices using the - Siemens R3964 packet protocol. Unless you are dealing with special - hardware like PLCs, you are unlikely to need this. - - To compile this driver as a module ( = code which can be inserted in - and removed from the running kernel whenever you want), say M here - and read . The module will be called - n_r3964.o. - - If unsure, say N. - -Applicom intelligent fieldbus card support -CONFIG_APPLICOM - This driver provides the kernel-side support for the intelligent - fieldbus cards made by Applicom International. More information - about these cards can be found on the WWW at the address - , or by email from David Woodhouse - . - - To compile this driver as a module ( = code which can be inserted in - and removed from the running kernel whenever you want), say M here - and read . The module will be called - applicom.o. - - If unsure, say N. - -Sony Vaio Programmable I/O Control Device support -CONFIG_SONYPI - This driver enables access to the Sony Programmable I/O Control - Device which can be found in many (all ?) Sony Vaio laptops. - - If you have one of those laptops, read - , and say Y or M here. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called sonypi.o. - -Intel Random Number Generator support -CONFIG_INTEL_RNG - This driver provides kernel-side support for the Random Number - Generator hardware found on Intel i8xx-based motherboards. - - Both a character driver, used to read() entropy data, and a timer - function which automatically adds entropy directly into the - kernel pool, are exported by this driver. - - To compile this driver as a module ( = code which can be inserted in - and removed from the running kernel whenever you want), say M here - and read . The module will be called - i810_rng.o. - - If unsure, say N. - -Intel/AMD/VIA HW Random Number Generator support -CONFIG_HW_RANDOM - This driver provides kernel-side support for the - Random Number Generator hardware found on Intel i8xx-based motherboards, - AMD 76x-based motherboards, and Via Nehemiah CPUs. - - Provides a character driver, used to read() entropy data. - - To compile this driver as a module ( = code which can be inserted in - and removed from the running kernel whenever you want), say M here - and read . The module will be called - hw_random. - - If unsure, say N. - -Power Management support -CONFIG_PM - "Power Management" means that parts of your computer are shut - off or put into a power conserving "sleep" mode if they are not - being used. There are two competing standards for doing this: APM - and ACPI. If you want to use either one, say Y here and then also - to the requisite support below. - - Power Management is most important for battery powered laptop - computers; if you have a laptop, check out the Linux Laptop home - page on the WWW at - and the - Battery Powered Linux mini-HOWTO, available from - . - - Note that, even if you say N here, Linux on the x86 architecture - will issue the hlt instruction if nothing is to be done, thereby - sending the processor to sleep and saving power. - -ACPI support -CONFIG_ACPI - ACPI/OSPM support for Linux is currently under development. As such, - this support is preliminary and EXPERIMENTAL. Configuring ACPI - support enables kernel interfaces that allow higher level software - (OSPM) to manipulate ACPI defined hardware and software interfaces, - including the evaluation of ACPI control methods. If unsure, choose - N here. Note, this option will enlarge your kernel by about 120K. - - This support requires an ACPI compliant platform (hardware/firmware). - If both ACPI and Advanced Power Management (APM) support are - configured, whichever is loaded first shall be used. - - This code DOES NOT currently provide a complete OSPM implementation - -- it has not yet reached APM's level of functionality. When fully - implemented, Linux ACPI/OSPM will provide a more robust functional - replacement for legacy configuration and power management - interfaces, including the Plug-and-Play BIOS specification (PnP - BIOS), the Multi-Processor Specification (MPS), and the Advanced - Power Management specification (APM). - - Linux support for ACPI/OSPM is based on Intel Corporation's ACPI - Component Architecture (ACPI CA). The latest ACPI CA source code, - documentation, debug builds, and implementation status information - can be downloaded from: - . - - The ACPI Sourceforge project may also be of interest: - - - Note that "acpi=off" can be used to disable all ACPI code in the kernel. - -ACPI kernel configuration manager -CONFIG_ACPI_KERNEL_CONFIG - If you say `Y' here, Linux's ACPI support will use the - hardware-level system descriptions found on IA64 machines. - -ACPI Debug Statements -CONFIG_ACPI_DEBUG - The ACPI driver can optionally report errors with a great deal - of verbosity. Saying Y enables these statements. This will increase - your kernel size by around 50K. - -ACPI Button -CONFIG_ACPI_BUTTON - This driver registers for events based on buttons, such as the - power, sleep, and lid switch. In the future, a daemon will read - /proc/acpi/event and perform user-defined actions such as shutting - down the system. Until then, you can cat it, and see output when - a button is pressed. - -CONFIG_ACPI_BATTERY - This driver adds support for battery information through - /proc/acpi/battery. If you have a mobile system with a battery, - say Y. - -CONFIG_ACPI_FAN - This driver adds support for ACPI fan devices, allowing user-mode - applications to perform basic fan control (on, off, status). - -CONFIG_ACPI_PROCESSOR - This driver installs ACPI as the idle handler for Linux, and uses - ACPI C2 and C3 processor states to save power, on systems that - support it. - -ACPI AC Adapter -CONFIG_ACPI_AC - This driver adds support for the AC Adapter object, which indicates - whether a system is on AC, or not. Typically, only laptops have - this object, since desktops are always on AC. - -ACPI Embedded Controller -CONFIG_ACPI_EC - This driver is required on some systems for the proper operation of - the battery and thermal drivers. If you are compiling for a laptop, - say Y. - -ACPI Thermal -CONFIG_ACPI_THERMAL - This driver handles overheating conditions on laptops. It is HIGHLY - recommended, as your laptop CPU may be damaged without it. - -ACPI ASUS/Medion Laptop Extras -CONFIG_ACPI_ASUS - This driver provides support for extra features of ACPI-compatible - ASUS laptops. As some of Medion laptops are made by ASUS, it may also - support some Medion laptops (such as 9675 for example). It makes all - the extra buttons generate standard ACPI events that go through - /proc/acpi/events, and (on some models) adds support for changing the - display brightness and output, switching the LCD backlight on and off, - and most importantly, allows you to blink those fancy LEDs intended - for reporting mail and wireless status. - - Note: the display switching code is currently considered EXPERIMENTAL, - toying with these values may even lock your machine. - - All settings are changed via /proc/acpi/asus directory entries. Owner - and group for these entries can be set with asus_uid and asus_gid - parameters. - - More information and a userspace daemon for handling the extra buttons - at . - - If you have an ACPI-compatible ASUS laptop, say Y or M here. This - driver is still under development, so if your laptop is unsupported or - something works not quite as expected, please use the mailing list - available on the above page (acpi4asus-user@lists.sourceforge.net) - -ACPI Toshiba Laptop Extras -CONFIG_ACPI_TOSHIBA - This driver adds support for access to certain system settings - on "legacy free" Toshiba laptops. These laptops can be recognized by - their lack of a BIOS setup menu and APM support. - - On these machines, all system configuration is handled through the - ACPI. This driver is required for access to controls not covered - by the general ACPI drivers, such as LCD brightness, video output, - etc. - - This driver differs from the non-ACPI Toshiba laptop driver (located - under "Processor type and features") in several aspects. - Configuration is accessed by reading and writing text files in the - /proc tree instead of by program interface to /dev. Furthermore, no - power management functions are exposed, as those are handled by the - general ACPI drivers. - - More information about this driver is available at - . - - If you have a legacy free Toshiba laptop (such as the Libretto L1 - series), say Y. - -Advanced Power Management BIOS support -CONFIG_APM - APM is a BIOS specification for saving power using several different - techniques. This is mostly useful for battery powered laptops with - APM compliant BIOSes. If you say Y here, the system time will be - reset after a RESUME operation, the /proc/apm device will provide - battery status information, and user-space programs will receive - notification of APM "events" (e.g. battery status change). - - If you select "Y" here, you can disable actual use of the APM - BIOS by passing the "apm=off" option to the kernel at boot time. - - Note that the APM support is almost completely disabled for - machines with more than one CPU. - - In order to use APM, you will need supporting software. For location - and more information, read and the - Battery Powered Linux mini-HOWTO, available from - . - - This driver does not spin down disk drives (see the hdparm(8) - manpage ("man 8 hdparm") for that), and it doesn't turn off - VESA-compliant "green" monitors. - - This driver does not support the TI 4000M TravelMate and the ACER - 486/DX4/75 because they don't have compliant BIOSes. Many "green" - desktop machines also don't have compliant BIOSes, and this driver - may cause those machines to panic during the boot phase. - - Generally, if you don't have a battery in your machine, there isn't - much point in using this driver and you should say N. If you get - random kernel OOPSes or reboots that don't seem to be related to - anything, try disabling/enabling this option (or disabling/enabling - APM in your BIOS). - - Some other things you should try when experiencing seemingly random, - "weird" problems: - - 1) make sure that you have enough swap space and that it is - enabled. - 2) pass the "no-hlt" option to the kernel - 3) switch on floating point emulation in the kernel and pass - the "no387" option to the kernel - 4) pass the "floppy=nodma" option to the kernel - 5) pass the "mem=4M" option to the kernel (thereby disabling - all but the first 4 MB of RAM) - 6) make sure that the CPU is not over clocked. - 7) read the sig11 FAQ at - 8) disable the cache from your BIOS settings - 9) install a fan for the video card or exchange video RAM - 10) install a better fan for the CPU - 11) exchange RAM chips - 12) exchange the motherboard. - - To compile this driver as a module ( = code which can be inserted in - and removed from the running kernel whenever you want), say M here - and read . The module will be called - apm.o. - -Ignore USER SUSPEND -CONFIG_APM_IGNORE_USER_SUSPEND - This option will ignore USER SUSPEND requests. On machines with a - compliant APM BIOS, you want to say N. However, on the NEC Versa M - series notebooks, it is necessary to say Y because of a BIOS bug. - -Enable APM at boot time -CONFIG_APM_DO_ENABLE - Enable APM features at boot time. From page 36 of the APM BIOS - specification: "When disabled, the APM BIOS does not automatically - power manage devices, enter the Standby State, enter the Suspend - State, or take power saving steps in response to CPU Idle calls." - This driver will make CPU Idle calls when Linux is idle (unless this - feature is turned off -- see "Do CPU IDLE calls", below). This - should always save battery power, but more complicated APM features - will be dependent on your BIOS implementation. You may need to turn - this option off if your computer hangs at boot time when using APM - support, or if it beeps continuously instead of suspending. Turn - this off if you have a NEC UltraLite Versa 33/C or a Toshiba - T400CDT. This is off by default since most machines do fine without - this feature. - -Make CPU Idle calls when idle -CONFIG_APM_CPU_IDLE - Enable calls to APM CPU Idle/CPU Busy inside the kernel's idle loop. - On some machines, this can activate improved power savings, such as - a slowed CPU clock rate, when the machine is idle. These idle calls - are made after the idle loop has run for some length of time (e.g., - 333 mS). On some machines, this will cause a hang at boot time or - whenever the CPU becomes idle. (On machines with more than one CPU, - this option does nothing.) - -Enable console blanking using APM -CONFIG_APM_DISPLAY_BLANK - Enable console blanking using the APM. Some laptops can use this to - turn off the LCD backlight when the screen blanker of the Linux - virtual console blanks the screen. Note that this is only used by - the virtual console screen blanker, and won't turn off the backlight - when using the X Window system. This also doesn't have anything to - do with your VESA-compliant power-saving monitor. Further, this - option doesn't work for all laptops -- it might not turn off your - backlight at all, or it might print a lot of errors to the console, - especially if you are using gpm. - -RTC stores time in GMT -CONFIG_APM_RTC_IS_GMT - Say Y here if your RTC (Real Time Clock a.k.a. hardware clock) - stores the time in GMT (Greenwich Mean Time). Say N if your RTC - stores localtime. - - It is in fact recommended to store GMT in your RTC, because then you - don't have to worry about daylight savings time changes. The only - reason not to use GMT in your RTC is if you also run a broken OS - that doesn't understand GMT. - -Allow interrupts during APM BIOS calls -CONFIG_APM_ALLOW_INTS - Normally we disable external interrupts while we are making calls to - the APM BIOS as a measure to lessen the effects of a badly behaving - BIOS implementation. The BIOS should reenable interrupts if it - needs to. Unfortunately, some BIOSes do not -- especially those in - many of the newer IBM Thinkpads. If you experience hangs when you - suspend, try setting this to Y. Otherwise, say N. - -Use real mode APM BIOS call to power off -CONFIG_APM_REAL_MODE_POWER_OFF - Use real mode APM BIOS calls to switch off the computer. This is - a work-around for a number of buggy BIOSes. Switch this option on if - your computer crashes instead of powering off properly. - -Watchdog Timer Support -CONFIG_WATCHDOG - If you say Y here (and to one of the following options) and create a - character special file /dev/watchdog with major number 10 and minor - number 130 using mknod ("man mknod"), you will get a watchdog, i.e.: - subsequently opening the file and then failing to write to it for - longer than 1 minute will result in rebooting the machine. This - could be useful for a networked machine that needs to come back - online as fast as possible after a lock-up. There's both a watchdog - implementation entirely in software (which can sometimes fail to - reboot the machine) and a driver for hardware watchdog boards, which - are more robust and can also keep track of the temperature inside - your computer. For details, read - in the kernel source. - - The watchdog is usually used together with the watchdog daemon - which is available from - . This daemon can - also monitor NFS connections and can reboot the machine when the process - table is full. - - If unsure, say N. - -Disable watchdog shutdown on close -CONFIG_WATCHDOG_NOWAYOUT - The default watchdog behaviour (which you get if you say N here) is - to stop the timer if the process managing it closes the file - /dev/watchdog. It's always remotely possible that this process might - get killed. If you say Y here, the watchdog cannot be stopped once - it has been started. - -WDT Watchdog timer -CONFIG_WDT - If you have a WDT500P or WDT501P watchdog board, say Y here, - otherwise N. It is not possible to probe for this board, which means - that you have to inform the kernel about the IO port and IRQ using - the "wdt=" kernel option (try "man bootparam" or see the - documentation of your boot loader (lilo or loadlin) about how to - pass options to the kernel at boot time). - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called wdt.o. - -WDT PCI Watchdog timer -CONFIG_WDTPCI - If you have a PCI WDT500/501 watchdog board, say Y here, otherwise - N. It is not possible to probe for this board, which means that you - have to inform the kernel about the IO port and IRQ using the "wdt=" - kernel option (try "man bootparam" or see the documentation of your - boot loader (lilo or loadlin) about how to pass options to the - kernel at boot time). - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called wdt_pci.o. - -WDT501 features -CONFIG_WDT_501 - Saying Y here and creating a character special file /dev/temperature - with major number 10 and minor number 131 ("man mknod") will give - you a thermometer inside your computer: reading from - /dev/temperature yields one byte, the temperature in degrees - Fahrenheit. This works only if you have a WDT501P watchdog board - installed. - -Fan Tachometer -CONFIG_WDT_501_FAN - Enable the Fan Tachometer on the WDT501. Only do this if you have a - fan tachometer actually set up. - -Software Watchdog -CONFIG_SOFT_WATCHDOG - A software monitoring watchdog. This will fail to reboot your system - from some situations that the hardware watchdog will recover - from. Equally it's a lot cheaper to install. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - softdog.o. - -Berkshire Products PC Watchdog -CONFIG_PCWATCHDOG - This is the driver for the Berkshire Products PC Watchdog card. - This card simply watches your kernel to make sure it doesn't freeze, - and if it does, it reboots your computer after a certain amount of - time. This driver is like the WDT501 driver but for different - hardware. Please read . The PC - watchdog cards can be ordered from . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called pcwd.o. If you want to compile it as a module, - say M here and read . - - Most people will say N. - -Acquire SBC Watchdog Timer -CONFIG_ACQUIRE_WDT - This is the driver for the hardware watchdog on the PSC-6x86 Single - Board Computer produced by Acquire Inc (and others). This watchdog - simply watches your kernel to make sure it doesn't freeze, and if - it does, it reboots your computer after a certain amount of time. - - This driver is like the WDT501 driver but for different hardware. - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called pscwdt.o. If you want to compile it as a - module, say M here and read . Most - people will say N. - -Advantech SBC Watchdog Timer -CONFIG_ADVANTECH_WDT - If you are configuring a Linux kernel for the Advantech single-board - computer, say `Y' here to support its built-in watchdog timer - feature. See the help for CONFIG_WATCHDOG for discussion. - -ALi M7101 Watchdog Timer -CONFIG_ALIM7101_WDT - This is the driver for the hardware watchdog on the ALi M7101 PMU - as used in the x86 Cobalt servers. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called alim7101_wdt.o. If you want to compile it as a - module, say M here and read . Most - people will say N. - -IB700 SBC Watchdog Timer -CONFIG_IB700_WDT - This is the driver for the hardware watchdog on the IB700 Single - Board Computer produced by TMC Technology (www.tmc-uk.com). This watchdog - simply watches your kernel to make sure it doesn't freeze, and if - it does, it reboots your computer after a certain amount of time. - - This driver is like the WDT501 driver but for slightly different hardware. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called ib700wdt.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. Most people - will say N. - -Mixcom Watchdog -CONFIG_MIXCOMWD - This is a driver for the Mixcom hardware watchdog cards. This - watchdog simply watches your kernel to make sure it doesn't freeze, - and if it does, it reboots your computer after a certain amount of - time. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called mixcomwd.o. If you want to compile it as a - module, say M here and read . Most - people will say N. - -ZF MachZ Watchdog -CONFIG_MACHZ_WDT - If you are using a ZF Micro MachZ processor, say Y here, otherwise - N. This is the driver for the watchdog timer builtin on that - processor using ZF-Logic interface. This watchdog simply watches - your kernel to make sure it doesn't freeze, and if it does, it - reboots your computer after a certain amount of time. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called machzwd.o. If you want to compile it as a - module, say M here and read . - -CONFIG_SC1200_WDT - This is a driver for National Semiconductor PC87307/PC97307 hardware - watchdog cards as found on the SC1200. This watchdog is mainly used - for power management purposes and can be used to power down the device - during inactivity periods (includes interrupt activity monitoring). - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called sc1200wdt.o. If you want to compile it as a - module, say M here and read . Most - people will say N. - -SuperH Watchdog -CONFIG_SH_WDT - This driver adds watchdog support for the integrated watchdog in the - SuperH 3, 4 and 5 processors. If you have one of these processors, say - Y, otherwise say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called shwdt.o. If you want to compile it as a module, - say M here and read Documentation/modules.txt. - -Wafer 5823 Watchdog -CONFIG_WAFER_WDT - This is a driver for the hardware watchdog on the ICP Wafer 5823 - Single Board Computer (and probably other similar models). - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - wafer5823wdt.o - -Machine Check Exception -CONFIG_X86_MCE - Machine Check Exception support allows the processor to notify the - kernel if it detects a problem (e.g. overheating, component failure). - The action the kernel takes depends on the severity of the problem, - ranging from a warning message on the console, to halting the machine. - You can safely select this on machines that do not support this feature. - - For pentium machines the mce support defaults to off as the mainboard - support is not always present. You must activate it as a boot option. - -Toshiba Laptop support -CONFIG_TOSHIBA - This adds a driver to safely access the System Management Mode of - the CPU on Toshiba portables with a genuine Toshiba BIOS. It does - not work on models with a Phoenix BIOS. The System Management Mode - is used to set the BIOS and power saving options on Toshiba portables. - - For information on utilities to make use of this driver see the - Toshiba Linux utilities web site at: - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - toshiba.o - - Say Y if you intend to run this kernel on a Toshiba portable. - Say N otherwise. - -Dell laptop support -CONFIG_I8K - This adds a driver to safely access the System Management Mode - of the CPU on the Dell Inspiron and Latitude laptops. The System - Management Mode is used to read cpu temperature, cooling fan - status and Fn-keys status on Dell laptops. It can also be used - to switch the fans on and off. - - The driver has been developed and tested on an Inspiron 8000 - but it should work on any Dell Inspiron or Latitude laptop. - You can force loading on unsupported models by passing the - parameter `force=1' to the module. Use at your own risk. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - i8k.o - - For more information on this driver and for utilities that make - use of the module see the I8K Linux Utilities web site at: - . - - Say Y if you intend to run this kernel on a Dell laptop. - Say N otherwise. - -/dev/cpu/microcode - Intel IA32 CPU microcode support -CONFIG_MICROCODE - If you say Y here and also to "/dev file system support" in the - 'File systems' section, you will be able to update the microcode on - Intel processors in the IA32 family, e.g. Pentium Pro, Pentium II, - Pentium III, Pentium 4, Xeon etc. You will obviously need the - actual microcode binary data itself which is not shipped with the - Linux kernel. - - For latest news and information on obtaining all the required - ingredients for this driver, check: - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called microcode.o. If you want to compile it as - a module, say M here and read . If - you use modprobe or kmod you may also want to add the line - 'alias char-major-10-184 microcode' to your /etc/modules.conf file. - -/dev/cpu/*/msr - Model-specific register support -CONFIG_X86_MSR - This device gives privileged processes access to the x86 - Model-Specific Registers (MSRs). It is a character device with - major 202 and minors 0 to 31 for /dev/cpu/0/msr to /dev/cpu/31/msr. - MSR accesses are directed to a specific CPU on multi-processor - systems. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - msr.o - -/dev/cpu/*/cpuid - CPU information support -CONFIG_X86_CPUID - This device gives processes access to the x86 CPUID instruction to - be executed on a specific processor. It is a character device - with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to - /dev/cpu/31/cpuid. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - cpuid.o - -x86 BIOS Enhanced Disk Drive support -CONFIG_EDD - Say Y or M here if you want to enable BIOS Enhanced Disk Drive - Services real mode BIOS calls to determine which disk - BIOS tries boot from. This information is then exported via /proc. - - This option is experimental, but believed to be safe, - and most disk controller BIOS vendors do not yet implement this feature. - -SBC-60XX Watchdog Timer -CONFIG_60XX_WDT - This driver can be used with the watchdog timer found on some - single board computers, namely the 6010 PII based computer. - It may well work with other cards. It reads port 0x443 to enable - and re-set the watchdog timer, and reads port 0x45 to disable - the watchdog. If you have a card that behave in similar ways, - you can probably make this driver work with your card as well. - - You can compile this driver directly into the kernel, or use - it as a module. The module will be called sbc60xxwdt.o. - -Eurotech CPU-1220/1410 Watchdog Timer -CONFIG_EUROTECH_WDT - Enable support for the watchdog timer on the Eurotech CPU-1220 and - CPU-1410 cards. These are PC/104 SBCs. Spec sheets and product - information are at . - -W83877F Watchdog Timer -CONFIG_W83877F_WDT - This is the driver for the hardware watchdog on the W83877F chipset - as used in EMACS PC-104 motherboards (and may work on others). This - watchdog simply watches your kernel to make sure it doesn't freeze, - and if it does, it reboots your computer after a certain amount of - time. - - You can compile this driver directly into the kernel, or use - it as a module. The module will be called w83877f_wdt.o. - -SC520 (AMD Elan) Watchdog Timer -CONFIG_SC520_WDT - This is the driver for the hardware watchdog built in to the - AMD "Elan" SC520 microcomputer commonly used in embedded systems. - This watchdog simply watches your kernel to make sure it doesn't - freeze, and if it does, it reboots your computer after a certain - amount of time. - - You can compile this driver directly into the kernel, or use - it as a module. The module will be called sc520_wdt.o. - -Enhanced Real Time Clock Support -CONFIG_RTC - If you say Y here and create a character special file /dev/rtc with - major number 10 and minor number 135 using mknod ("man mknod"), you - will get access to the real time clock (or hardware clock) built - into your computer. - - Every PC has such a clock built in. It can be used to generate - signals from as low as 1Hz up to 8192Hz, and can also be used - as a 24 hour alarm. It reports status information via the file - /proc/driver/rtc and its behaviour is set by various ioctls on - /dev/rtc. - - If you run Linux on a multiprocessor machine and said Y to - "Symmetric Multi Processing" above, you should say Y here to read - and set the RTC in an SMP compatible fashion. - - If you think you have a use for such a device (such as periodic data - sampling), then say Y here, and read - for details. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called rtc.o. If you want to compile it as a module, - say M here and read . - -Generic MIPS RTC Support -CONFIG_MIPS_RTC - - If your machine is a MIPS machine, this option provides a simple, - generic RTC driver for /dev/rtc device. It only implements two IOCTL - operations of the standard PC RTC driver: RTC_RD_TIME and RTC_SET_TIME. - It is sufficient to run hwclock program. - - You should say Y here if there is no machine-specific RTC driver for your - MIPS machine but you do want a simple RTC driver for your RTC device. - -Generic Real Time Clock Support -CONFIG_GEN_RTC - If you say Y here and create a character special file /dev/rtc with - major number 10 and minor number 135 using mknod ("man mknod"), you - will get access to the real time clock (or hardware clock) built - into your computer. - - In 2.4 and later kernels this is the only way to set and get rtc - time on m68k systems so it is highly recommended. - - It reports status information via the file /proc/driver/rtc and its - behaviour is set by various ioctls on /dev/rtc. If you enable the - "extended RTC operation" below it will also provide an emulation - for RTC_UIE which is required by some programs and may improve - precision in some cases. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called genrtc.o. If you want to compile it as a module, - say M here and read . To load the - module automatically add 'alias char-major-10-135 genrtc' to your - /etc/modules.conf - -Extended RTC operation -CONFIG_GEN_RTC_X - Provides an emulation for RTC_UIE which is required by some programs - and may improve precision of the generic RTC support in some cases. - -Tadpole ANA H8 Support -CONFIG_H8 - The Hitachi H8/337 is a microcontroller used to deal with the power - and thermal environment. If you say Y here, you will be able to - communicate with it via a character special device. - - If unsure, say N. - -/dev/nvram support -CONFIG_NVRAM - If you say Y here and create a character special file /dev/nvram - with major number 10 and minor number 144 using mknod ("man mknod"), - you get read and write access to the extra bytes of non-volatile - memory in the real time clock (RTC), which is contained in every PC - and most Ataris. The actual number of bytes varies, depending on the - nvram in the system, but is usually 114 (128-14 for the RTC). - - This memory is conventionally called "CMOS RAM" on PCs and "NVRAM" - on Ataris. /dev/nvram may be used to view settings there, or to - change them (with some utility). It could also be used to frequently - save a few bits of very important data that may not be lost over - power-off and for which writing to disk is too insecure. Note - however that most NVRAM space in a PC belongs to the BIOS and you - should NEVER idly tamper with it. See Ralf Brown's interrupt list - for a guide to the use of CMOS bytes by your BIOS. - - On Atari machines, /dev/nvram is always configured and does not need - to be selected. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called nvram.o. If you want to compile it as a - module, say M here and read . - -Joystick support -CONFIG_JOYSTICK - If you have a joystick, 6dof controller, gamepad, steering wheel, - weapon control system or something like that you can say Y here to - enable generic support for these controllers. You will also need to - say Y or M to at least one of the hardware specific drivers. This - will make the controllers available as /dev/input/jsX devices. - Please read the file which - contains more information and the location of the joystick package - that you'll need. - -Game port support -CONFIG_INPUT_GAMEPORT - Gameport support is for the standard 15-pin PC gameport. If you - have a joystick, gamepad, gameport card, a soundcard with a gameport - or anything else that uses the gameport, say Y or M here and also to - at least one of the hardware specific drivers. - Please read the file which - contains more information and the location of the joystick package - that you'll need if you use the gameport with a joystick. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called gameport.o. If you want to compile it as - a module, say M here and read . - -Classic ISA/PnP gameports -CONFIG_INPUT_NS558 - Say Y here if you have an ISA or PnP gameport. - For more information on how to use the driver please read - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ns558.o. If you want to compile it as a - module, say M here and read . - -PDPI Lightning 4 gamecard -CONFIG_INPUT_LIGHTNING - Say Y here if you have a PDPI Lightning 4 gamecard. For more - information on how to use the driver please read - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called lightning.o. If you want to compile it as - a module, say M here and read . - -Crystal SoundFusion gameports -CONFIG_INPUT_CS461X - Say Y here if you have a Cirrus CS461x aka "Crystal SoundFusion" - PCI audio accelerator. A product page for the CS4614 is at - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cs461x.o. If you want to compile it as a - module, say M here and read . - -Aureal Vortex, Trident 4DWave, and ALi 5451 gameports -CONFIG_INPUT_PCIGAME - Say Y here if you have a Trident 4DWave DX/NX or Aureal Vortex 1/2 - card or an ALi 5451 chip on your motherboard. For more information - on how to use the driver please read - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called pcigame.o. If you want to compile it as a - module, say M here and read . - -SoundBlaster Live! gameports -CONFIG_INPUT_EMU10K1 - Say Y here if you have a SoundBlaster Live! card and want to use - its gameport. For more information on how to use the driver - please read . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called emu10k1-gp.o. If you want to compile it as - a module, say M here and read . - -Classic PC analog joysticks and gamepads -CONFIG_INPUT_ANALOG - Say Y here if you have a controller that connects to the PC - gameport. This supports many different types, including joysticks - with throttle control, with rudders, or with extensions like - additional hats and buttons compatible with CH Flightstick Pro, - ThrustMaster FCS, 6 and 8 button gamepads, or Saitek Cyborg - joysticks. For more information on how to use the driver please - read . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called analog.o. If you want to compile it as a - module, say M here and read . - -Assassin 3D and MadCatz Panther devices -CONFIG_INPUT_A3D - Say Y here if you have an FPGaming or MadCatz controller using the - A3D protocol over the PC gameport. For more information on how to - use the driver please read . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called a3d.o. If you want to compile it as a - module, say M here and read . - -Logitech ADI digital joysticks and gamepads -CONFIG_INPUT_ADI - Say Y here if you have a Logitech controller using the ADI - protocol over the PC gameport. For more information on how to use - the driver please read . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called adi.o. If you want to compile it as a - module, say M here and read . - -Creative Labs Blaster Cobra gamepad -CONFIG_INPUT_COBRA - Say Y here if you have a Creative Labs Blaster Cobra gamepad. - For more information on how to use the driver please read - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cobra.o. If you want to compile it as a - module, say M here and read . - -Genius Flight2000 Digital joysticks and gamepads -CONFIG_INPUT_GF2K - Say Y here if you have a Genius Flight2000 or MaxFighter digitally - communicating joystick or gamepad. For more information on how to - use the driver please read . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called gf2k.o. If you want to compile it as a - module, say M here and read . - -Gravis GrIP joysticks and gamepads -CONFIG_INPUT_GRIP - Say Y here if you have a Gravis controller using the GrIP protocol - over the PC gameport. For more information on how to use the driver - please read . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called grip.o. If you want to compile it as a - module, say M here and read . - -InterAct digital joysticks and gamepads -CONFIG_INPUT_INTERACT - Say Y hereif you have an InterAct gameport or joystick - communicating digitally over the gameport. For more information on - how to use the driver please read . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called interact.o. If you want to compile it as - a module, say M here and read . - -ThrustMaster DirectConnect joysticks and gamepads -CONFIG_INPUT_TMDC - Say Y here if you have a ThrustMaster controller using the - DirectConnect (BSP) protocol over the PC gameport. For more - information on how to use the driver please read - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called tmdc.o. If you want to compile it as a - module, say M here and read . - -Microsoft SideWinder digital joysticks and gamepads -CONFIG_INPUT_SIDEWINDER - Say Y here if you have a Microsoft controller using the Digital - Overdrive protocol over PC gameport. For more information on how to - use the driver please read . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called sidewinder.o. If you want to compile it - as a module, say M here and read . - -Serial port device support -CONFIG_INPUT_SERIO - Say Y here and to the Serial port input line discipline option if - you plan to use a joystick that communicates over the serial (COM) - port. For more information on how to use the driver please read - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called sidewinder.o. If you want to compile it - as a module, say M here and read . - -Serial port input line discipline -CONFIG_INPUT_SERPORT - Say Y here if you plan to use a joystick that communicates over the - serial (COM) port. For more information on how to use the driver - please read . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called serport.o. If you want to compile it as a - module, say M here and read . - -Logitech WingMan Warrior joystick -CONFIG_INPUT_WARRIOR - Say Y here if you have a Logitech WingMan Warrior joystick connected - to your computer's serial port. For more information on how to use - the driver please read . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called warrior.o. If you want to compile it as a - module, say M here and read . - -LogiCad3d Magellan/SpaceMouse 6dof controller -CONFIG_INPUT_MAGELLAN - Say Y here if you have a Magellan or Space Mouse 6DOF controller - connected to your computer's serial port. For more information on - how to use the driver please read . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called magellan.o. If you want to compile it as - a module, say M here and read . - -SpaceTec SpaceOrb/Avenger 6dof controller -CONFIG_INPUT_SPACEORB - Say Y here if you have a SpaceOrb 360 or SpaceBall Avenger 6DOF - controller connected to your computer's serial port. For more - information on how to use the driver please read - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called spaceorb.o. If you want to compile it as - a module, say M here and read . - -SpaceTec SpaceBall 4000 FLX 6dof controller -CONFIG_INPUT_SPACEBALL - Say Y here if you have a SpaceTec SpaceBall 4000 FLX controller - connected to your computer's serial port. For more information on - how to use the driver please read . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called spaceball.o. If you want to compile it as - a module, say M here and read . - -Gravis Stinger gamepad -CONFIG_INPUT_STINGER - Say Y here if you have a Gravis Stinger connected to one of your - serial ports. For more information on how to use the driver please - read . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called stinger.o. If you want to compile it as a - module, say M here and read . - -I-Force joysticks/wheels -CONFIG_INPUT_IFORCE_232 - Say Y here if you have an I-Force joystick or steering wheel - connected to your serial (COM) port. For more information on how - to use the driver please read . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called iforce.o. If you want to compile it as a - module, say M here and read . - -I-Force joysticks/wheels -CONFIG_INPUT_IFORCE_USB - Say Y here if you have an I-Force joystick or steering wheel - connected to your USB port. For more information on how to use the - driver please read . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called iforce.o. If you want to compile it as a - module, say M here and read . - -Multisystem, Sega Genesis, Saturn joysticks and gamepads -CONFIG_INPUT_DB9 - Say Y here if you have a Sega Master System gamepad, Sega Genesis - gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga, - Commodore, Amstrad CPC joystick connected to your parallel port. - For more information on how to use the driver please read - and - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called db9.o. If you want to compile it as a - module, say M here and read . - -Multisystem, NES, SNES, N64, PSX joysticks and gamepads -CONFIG_INPUT_GAMECON - Say Y here if you have a Nintendo Entertainment System gamepad, - Super Nintendo Entertainment System gamepad, Nintendo 64 gamepad, - Sony PlayStation gamepad or a Multisystem -- Atari, Amiga, - Commodore, Amstrad CPC joystick connected to your parallel port. - For more information on how to use the driver please read - and - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called gamecon.o. If you want to compile it as a - module, say M here and read . - -Multisystem joysticks via TurboGraFX device -CONFIG_INPUT_TURBOGRAFX - Say Y here if you have the TurboGraFX interface by Steffen Schwenke, - and want to use it with Multisystem -- Atari, Amiga, Commodore, - Amstrad CPC joystick. For more information on how to use the driver - please read and - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called turbografx.o. If you want to compile it - as a module, say M here and read . - -Amiga joysticks -CONFIG_INPUT_AMIJOY - Say Y here if you have an Amiga with a digital joystick connected - to it. For more information on how to use the driver please read - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called joy-amiga.o. If you want to compile it as - a module, say M here and read . - -Atomwide serial port support -CONFIG_ATOMWIDE_SERIAL - If you have an Atomwide Serial card for an Acorn system, say Y to - this option. The driver can handle 1, 2, or 3 port cards. - If unsure, say N. - -Dual serial port support -CONFIG_DUALSP_SERIAL - If you have the Serial Port's dual serial card for an Acorn system, - say Y to this option. If unsure, say N. - -NetWinder Button -CONFIG_NWBUTTON - If you say Y here and create a character device node /dev/nwbutton - with major and minor numbers 10 and 158 ("man mknod"), then every - time the orange button is pressed a number of times, the number of - times the button was pressed will be written to that device. - - This is most useful for applications, as yet unwritten, which - perform actions based on how many times the button is pressed in a - row. - - Do not hold the button down for too long, as the driver does not - alter the behaviour of the hardware reset circuitry attached to the - button; it will still execute a hard reset if the button is held - down for longer than approximately five seconds. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - nwbutton.o. - - Most people will answer Y to this question and "Reboot Using Button" - below to be able to initiate a system shutdown from the button. - -Reboot Using Button -CONFIG_NWBUTTON_REBOOT - If you say Y here, then you will be able to initiate a system - shutdown and reboot by pressing the orange button a number of times. - The number of presses to initiate the shutdown is two by default, - but this can be altered by modifying the value of NUM_PRESSES_REBOOT - in nwbutton.h and recompiling the driver or, if you compile the - driver as a module, you can specify the number of presses at load - time with "insmod button reboot_count=". - -Sound card support -CONFIG_SOUND - If you have a sound card in your computer, i.e. if it can say more - than an occasional beep, say Y. Be sure to have all the information - about your sound card and its configuration down (I/O port, - interrupt and DMA channel), because you will be asked for it. - - You want to read the Sound-HOWTO, available from - . General information about - the modular sound system is contained in the files - . The file - contains some slightly - outdated but still useful information as well. - - If you have a PnP sound card and you want to configure it at boot - time using the ISA PnP tools (read - ), then you need to - compile the sound card support as a module ( = code which can be - inserted in and removed from the running kernel whenever you want) - and load that module after the PnP configuration is finished. To do - this, say M here and read as well - as ; the module will be - called soundcore.o. - - I'm told that even without a sound card, you can make your computer - say more than an occasional beep, by programming the PC speaker. - Kernel patches and supporting utilities to do that are in the pcsp - package, available at . - -OSS sound modules -CONFIG_SOUND_OSS - OSS is the Open Sound System suite of sound card drivers. They make - sound programming easier since they provide a common API. Say Y or - M here (the module will be called sound.o) if you haven't found a - driver for your sound card above, then pick your driver from the - list below. - -Persistent DMA buffers -CONFIG_SOUND_DMAP - Linux can often have problems allocating DMA buffers for ISA sound - cards on machines with more than 16MB of RAM. This is because ISA - DMA buffers must exist below the 16MB boundary and it is quite - possible that a large enough free block in this region cannot be - found after the machine has been running for a while. If you say Y - here the DMA buffers (64Kb) will be allocated at boot time and kept - until the shutdown. This option is only useful if you said Y to - "OSS sound modules", above. If you said M to "OSS sound modules" - then you can get the persistent DMA buffer functionality by passing - the command-line argument "dmabuf=1" to the sound.o module. - - Say Y unless you have 16MB or less RAM or a PCI sound card. - -Support for Aztech Sound Galaxy (non-PnP) cards -CONFIG_SOUND_SGALAXY - This module initializes the older non Plug and Play sound galaxy - cards from Aztech. It supports the Waverider Pro 32 - 3D and the - Galaxy Washington 16. - - If you compile the driver into the kernel, you have to add - "sgalaxy=,,,," to the kernel command - line. - -Support for AD1816(A) based cards -CONFIG_SOUND_AD1816 - Say M here if you have a sound card based on the Analog Devices - AD1816(A) chip. - - If you compile the driver into the kernel, you have to add - "ad1816=,,," to the kernel command line. - -Yamaha OPL3-SA1 audio controller -CONFIG_SOUND_OPL3SA1 - Say Y or M if you have a Yamaha OPL3-SA1 sound chip, which is - usually built into motherboards. Read - for details. - - If you compile the driver into the kernel, you have to add - "opl3sa=,,,,," to the kernel - command line. - -ProAudioSpectrum 16 support -CONFIG_SOUND_PAS - Answer Y only if you have a Pro Audio Spectrum 16, ProAudio Studio - 16 or Logitech SoundMan 16 sound card. Answer N if you have some - other card made by Media Vision or Logitech since those are not - PAS16 compatible. Please read . - It is not necessary to add Sound Blaster support separately; it - is included in PAS support. - - If you compile the driver into the kernel, you have to add - "pas2=,,,,,,, - to the kernel command line. - -Enable PAS16 joystick port -CONFIG_PAS_JOYSTICK - Say Y here to enable the Pro Audio Spectrum 16's auxiliary joystick - port. - -100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support -CONFIG_SOUND_SB - Answer Y if you have an original Sound Blaster card made by Creative - Labs or a 100% hardware compatible clone (like the Thunderboard or - SM Games). For an unknown card you may answer Y if the card claims - to be Sound Blaster-compatible. - - Please read the file . - - You should also say Y here for cards based on the Avance Logic - ALS-007 and ALS-1X0 chips (read ) and - for cards based on ESS chips (read - and - ). If you have an SB AWE 32 or SB AWE - 64, say Y here and also to "AWE32 synth" below and read - . If you have an IBM Mwave - card, say Y here and read . - - If you compile the driver into the kernel and don't want to use - isapnp, you have to add "sb=,,," to the kernel - command line. - - You can say M here to compile this driver as a module; the module is - called sb.o. - -Gravis Ultrasound support -CONFIG_SOUND_GUS - Say Y here for any type of Gravis Ultrasound card, including the GUS - or GUS MAX. See also for more - information on configuring this card with modules. - - If you compile the driver into the kernel, you have to add - "gus=,,," to the kernel command line. - -MPU-401 support (NOT for SB16) -CONFIG_SOUND_MPU401 - Be careful with this question. The MPU401 interface is supported by - all sound cards. However, some natively supported cards have their - own driver for MPU401. Enabling this MPU401 option with these cards - will cause a conflict. Also, enabling MPU401 on a system that - doesn't really have a MPU401 could cause some trouble. If your card - was in the list of supported cards, look at the card specific - instructions in the file. It - is safe to answer Y if you have a true MPU401 MIDI interface card. - - If you compile the driver into the kernel, you have to add - "mpu401=," to the kernel command line. - -6850 UART support -CONFIG_SOUND_UART6850 - This option enables support for MIDI interfaces based on the 6850 - UART chip. This interface is rarely found on sound cards. It's safe - to answer N to this question. - - If you compile the driver into the kernel, you have to add - "uart6850=," to the kernel command line. - -PSS (AD1848, ADSP-2115, ESC614) support -CONFIG_SOUND_PSS - Answer Y or M if you have an Orchid SW32, Cardinal DSP16, Beethoven - ADSP-16 or some other card based on the PSS chipset (AD1848 codec + - ADSP-2115 DSP chip + Echo ESC614 ASIC CHIP). For more information on - how to compile it into the kernel or as a module see the file - . - - If you compile the driver into the kernel, you have to add - "pss=,,,,," to the kernel - command line. - -Enable PSS mixer (Beethoven ADSP-16 and other compatible) -CONFIG_PSS_MIXER - Answer Y for Beethoven ADSP-16. You may try to say Y also for other - cards if they have master volume, bass, treble, and you can't - control it under Linux. If you answer N for Beethoven ADSP-16, you - can't control master volume, bass, treble and synth volume. - - If you said M to "PSS support" above, you may enable or disable this - PSS mixer with the module parameter pss_mixer. For more information - see the file . - -Have DSPxxx.LD firmware file -CONFIG_PSS_HAVE_BOOT - If you have the DSPxxx.LD file or SYNTH.LD file for you card, say Y - to include this file. Without this file the synth device (OPL) may - not work. - -Full pathname of DSPxxx.LD firmware file -CONFIG_PSS_BOOT_FILE - Enter the full pathname of your DSPxxx.LD file or SYNTH.LD file, - starting from /. - -Microsoft Sound System support -CONFIG_SOUND_MSS - Again think carefully before answering Y to this question. It's - safe to answer Y if you have the original Windows Sound System card - made by Microsoft or Aztech SG 16 Pro (or NX16 Pro). Also you may - say Y in case your card is NOT among these: - - ATI Stereo F/X, AdLib, Audio Excell DSP16, Cardinal DSP16, - Ensoniq SoundScape (and compatibles made by Reveal and Spea), - Gravis Ultrasound, Gravis Ultrasound ACE, Gravis Ultrasound Max, - Gravis Ultrasound with 16 bit option, Logitech Sound Man 16, - Logitech SoundMan Games, Logitech SoundMan Wave, MAD16 Pro (OPTi - 82C929), Media Vision Jazz16, MediaTriX AudioTriX Pro, Microsoft - Windows Sound System (MSS/WSS), Mozart (OAK OTI-601), Orchid - SW32, Personal Sound System (PSS), Pro Audio Spectrum 16, Pro - Audio Studio 16, Pro Sonic 16, Roland MPU-401 MIDI interface, - Sound Blaster 1.0, Sound Blaster 16, Sound Blaster 16ASP, Sound - Blaster 2.0, Sound Blaster AWE32, Sound Blaster Pro, TI TM4000M - notebook, ThunderBoard, Turtle Beach Tropez, Yamaha FM - synthesizers (OPL2, OPL3 and OPL4), 6850 UART MIDI Interface. - - For cards having native support in VoxWare, consult the card - specific instructions in . - Some drivers have their own MSS support and saying Y to this option - will cause a conflict. - - If you compile the driver into the kernel, you have to add - "ad1848=,,,[,]" to the kernel command - line. - -SGI Visual Workstation on-board audio -CONFIG_SOUND_VWSND - Say Y or M if you have an SGI Visual Workstation and you want to be - able to use its on-board audio. Read - for more info on this driver's - capabilities. - -NEC Vrc5477 AC97 sound -CONFIG_SOUND_VRC5477 - Say Y here to enable sound support for the NEC Vrc5477 chip, an - integrated, multi-function controller chip for MIPS CPUs. Works - with the AC97 codec. - -Ensoniq SoundScape support -CONFIG_SOUND_SSCAPE - Answer Y if you have a sound card based on the Ensoniq SoundScape - chipset. Such cards are being manufactured at least by Ensoniq, Spea - and Reveal (Reveal makes also other cards). - - If you compile the driver into the kernel, you have to add - "sscape=,,,," to the kernel command - line. - -MediaTriX AudioTriX Pro support -CONFIG_SOUND_TRIX - Answer Y if you have the AudioTriX Pro sound card manufactured - by MediaTrix. - -Have TRXPRO.HEX firmware file -CONFIG_TRIX_HAVE_BOOT - The MediaTrix AudioTrix Pro has an on-board microcontroller which - needs to be initialized by downloading the code from the file - TRXPRO.HEX in the DOS driver directory. If you don't have the - TRXPRO.HEX file handy you may skip this step. However, the SB and - MPU-401 modes of AudioTrix Pro will not work without this file! - -Full pathname of TRXPRO.HEX firmware file -CONFIG_TRIX_BOOT_FILE - Enter the full pathname of your TRXPRO.HEX file, starting from /. - -Support for OPTi MAD16 and/or Mozart based cards -CONFIG_SOUND_MAD16 - Answer Y if your card has a Mozart (OAK OTI-601) or MAD16 (OPTi - 82C928 or 82C929 or 82C931) audio interface chip. These chips are - quite common so it's possible that many no-name cards have one of - them. In addition the MAD16 chip is used in some cards made by known - manufacturers such as Turtle Beach (Tropez), Reveal (some models) - and Diamond (latest ones). Note however that the Tropez sound cards - have their own driver; if you have one of those, say N here and Y or - M to "Full support for Turtle Beach WaveFront", below. - - If you compile the driver into the kernel, you have to add - "mad16=,,,,," to the - kernel command line. - - See also and - for more information on setting - these cards up as modules. - -Full support for Turtle Beach WaveFront (Tropez Plus, Tropez, Maui) synth/sound cards -CONFIG_SOUND_WAVEFRONT - Answer Y or M if you have a Tropez Plus, Tropez or Maui sound card - and read the files and - . - -Support MIDI in older MAD16 based cards (requires SB) -CONFIG_MAD16_OLDCARD - Answer Y (or M) if you have an older card based on the C928 or - Mozart chipset and you want to have MIDI support. If you enable this - option you also need to enable support for Sound Blaster. - -Support for Crystal CS4232 based (PnP) cards -CONFIG_SOUND_CS4232 - Say Y here if you have a card based on the Crystal CS4232 chip set, - which uses its own Plug and Play protocol. - - If you compile the driver into the kernel, you have to add - "cs4232=,,,,," to the kernel - command line. - - See for more information on - configuring this card. - -Support for Crystal CS4297a on SiByte syncser -CONFIG_SOUND_BCM_CS4297A - The BCM91250A has a Crystal CS4297a on synchronous serial port B (in - addition to the DB-9 serial port). Say Y or M here to enable the - sound chip instead of the UART. Also note that CONFIG_KGDB should - not be enabled at the same time, since it also attempts to use this - UART port. - -Support for Yamaha OPL3-SA2 and SA3 based PnP cards -CONFIG_SOUND_OPL3SA2 - Say Y or M if you have a card based on one of these Yamaha sound - chipsets or the "SAx", which is actually a SA3. Read - for more information on - configuring these cards. - - If you compile the driver into the kernel and do not also - configure in the optional ISA PnP support, you will have to add - "opl3sa2=,,,,," to the kernel - command line. - -Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers -CONFIG_SOUND_MAUI - Say Y here if you have a Turtle Beach Wave Front, Maui, or Tropez - sound card. - - If you compile the driver into the kernel, you have to add - "maui=," to the kernel command line. - -Have OSWF.MOT firmware file -CONFIG_MAUI_HAVE_BOOT - Turtle Beach Maui and Tropez sound cards have a microcontroller - which needs to be initialized prior to use. OSWF.MOT is a file - distributed with the card's DOS/Windows drivers. Answer Y if you - have this file. - -Full pathname of OSWF.MOT firmware file -CONFIG_MAUI_BOOT_FILE - Enter the full pathname of your OSWF.MOT file, starting from /. - -Support for Turtle Beach MultiSound Classic, Tahiti, Monterey -CONFIG_SOUND_MSNDCLAS - Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or - Monterey (not for the Pinnacle or Fiji). - - See for important information - about this driver. Note that it has been discontinued, but the - Voyetra Turtle Beach knowledge base entry for it is still available - at . - -MSND Classic I/O -CONFIG_MSNDCLAS_IO - I/O port address for the MultiSound Classic and related cards. - -MSND Classic IRQ -CONFIG_MSNDCLAS_IRQ - Interrupt Request line for the MultiSound Classic and related cards. - -MSND Classic memory address -CONFIG_MSNDCLAS_MEM - Memory-mapped I/O base address for the MultiSound Classic and - related cards. - -Full pathname of MSNDINIT.BIN firmware file -CONFIG_MSNDCLAS_INIT_FILE - The MultiSound cards have two firmware files which are required for - operation, and are not currently included. These files can be - obtained from Turtle Beach. See - for information on how to - obtain this. - -Full pathname of MSNDPERM.BIN firmware file -CONFIG_MSNDCLAS_PERM_FILE - The MultiSound cards have two firmware files which are required for - operation, and are not currently included. These files can be - obtained from Turtle Beach. See - for information on how to - obtain this. - -Support for Turtle Beach MultiSound Pinnacle, Fiji -CONFIG_SOUND_MSNDPIN - Say M here if you have a Turtle Beach MultiSound Pinnacle or Fiji. - See for important information - about this driver. Note that it has been discontinued, but the - Voyetra Turtle Beach knowledge base entry for it is still available - at . - -MSND Pinnacle IDE I/O 0 -CONFIG_MSNDPIN_IDE_IO0 - CD-ROM drive 0 memory-mapped I/O base address for the MultiSound - Pinnacle and Fiji sound cards. - -MSND Pinnacle IDE I/O 1 -CONFIG_MSNDPIN_IDE_IO1 - CD-ROM drive 1 memory-mapped I/O base address for the MultiSound - Pinnacle and Fiji sound cards. - -MSND Pinnacle IDE IRQ -CONFIG_MSNDPIN_IDE_IRQ - Interrupt request number for the IDE CD-ROM interface on the - MultiSound Pinnacle and Fiji sound cards. - -MSND Pinnacle I/O -CONFIG_MSNDPIN_IO - Memory-mapped I/O base address for the primary synthesizer on - MultiSound Pinnacle and Fiji sound cards. - -MSND Pinnacle MPU I/O -CONFIG_MSNDPIN_MPU_IO - Memory-mapped I/O base address for the Kurzweil daughterboard - synthesizer on MultiSound Pinnacle and Fiji sound cards. - -MSND Pinnacle MPU IRQ -CONFIG_MSNDPIN_MPU_IRQ - Iinterrupt request number for the Kurzweil daughterboard - synthesizer on MultiSound Pinnacle and Fiji sound cards. - -MSND Pinnacle IRQ -CONFIG_MSNDPIN_IRQ - Interrupt request line for the primary synthesizer on MultiSound - Pinnacle and Fiji sound cards. - -MSND Pinnacle joystick I/O -CONFIG_MSNDPIN_JOYSTICK_IO - Memory-mapped I/O base address for the joystick port on MultiSound - Pinnacle and Fiji sound cards. - -MSND Pinnacle memory -CONFIG_MSNDPIN_MEM - Memory-mapped I/O base address for the primary synthesizer on - MultiSound Pinnacle and Fiji sound cards. - -Full pathname of PNDSPINI.BIN firmware file -CONFIG_MSNDPIN_INIT_FILE - The MultiSound cards have two firmware files which are required - for operation, and are not currently included. These files can be - obtained from Turtle Beach. See - for information on how to - obtain this. - -Full pathname of PNDSPERM.BIN firmware file -CONFIG_MSNDPIN_PERM_FILE - The MultiSound cards have two firmware files which are required for - operation, and are not currently included. These files can be - obtained from Turtle Beach. See - for information on how to - obtain this. - -MSND Pinnacle has S/PDIF I/O -CONFIG_MSNDPIN_DIGITAL - If you have the S/PDIF daughter board for the Pinnacle or Fiji, - answer Y here; otherwise, say N. If you have this, you will be able - to play and record from the S/PDIF port (digital signal). See - for information on how to make - use of this capability. - -MSND Pinnacle non-PnP Mode -CONFIG_MSNDPIN_NONPNP - The Pinnacle and Fiji card resources can be configured either with - PnP, or through a configuration port. Say Y here if your card is NOT - in PnP mode. For the Pinnacle, configuration in non-PnP mode allows - use of the IDE and joystick peripherals on the card as well; these - do not show up when the card is in PnP mode. Specifying zero for any - resource of a device will disable the device. If you are running the - card in PnP mode, you must say N here and use isapnptools to - configure the card's resources. - -MSND Pinnacle config port -CONFIG_MSNDPIN_CFG - This is the port which the Pinnacle and Fiji uses to configure the - card's resources when not in PnP mode. If your card is in PnP mode, - then be sure to say N to the previous option, "MSND Pinnacle Non-PnP - Mode". - -MSND buffer size (kB) -CONFIG_MSND_FIFOSIZE - Configures the size of each audio buffer, in kilobytes, for - recording and playing in the MultiSound drivers (both the Classic - and Pinnacle). Larger values reduce the chance of data overruns at - the expense of overall latency. If unsure, use the default. - -Yamaha FM synthesizer (YM3812/OPL-3) support -CONFIG_SOUND_YM3812 - Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4). - Answering Y is usually a safe and recommended choice, however some - cards may have software (TSR) FM emulation. Enabling FM support with - these cards may cause trouble (I don't currently know of any such - cards, however). Please read the file - if your card has an OPL3 chip. - - If you compile the driver into the kernel, you have to add - "opl3=" to the kernel command line. - - If unsure, say Y. - -ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20 radio) -CONFIG_SOUND_ACI_MIXER - ACI (Audio Command Interface) is a protocol used to communicate with - the microcontroller on some sound cards produced by miro and - Cardinal Technologies. The main function of the ACI is to control - the mixer and to get a product identification. - - This VoxWare ACI driver currently supports the ACI functions on the - miroSOUND PCM1-pro, PCM12 and PCM20 radio. On the PCM20 radio, ACI - also controls the radio tuner. This is supported in the video4linux - miropcm20 driver (say M or Y here and go back to "Multimedia - devices" -> "Radio Adapters"). - - This driver is also available as a module and will be called aci.o. - -SB32/AWE support -CONFIG_SOUND_AWE32_SYNTH - Say Y here if you have a Sound Blaster SB32, AWE32-PnP, SB AWE64 or - similar sound card. See , - and the Soundblaster-AWE - mini-HOWTO, available from - for more info. - -Gallant Audio Cards (SC-6000 and SC-6600 based) -CONFIG_SOUND_AEDSP16 - Answer Y if you have a Gallant's Audio Excel DSP 16 card. This - driver supports Audio Excel DSP 16 but not the III nor PnP versions - of this card. - - The Gallant's Audio Excel DSP 16 card can emulate either an SBPro or - a Microsoft Sound System card, so you should have said Y to either - "100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support" - or "Microsoft Sound System support", above, and you need to answer - the "MSS emulation" and "SBPro emulation" questions below - accordingly. You should say Y to one and only one of these two - questions. - - Read the file and the head of - as well as - to get more information - about this driver and its configuration. - -Audio Excel DSP 16 (SBPro emulation) -CONFIG_AEDSP16_SBPRO - Answer Y if you want your audio card to emulate Sound Blaster Pro. - You should then say Y to "100% Sound Blaster compatibles - (SB16/32/64, ESS, Jazz16) support" and N to "Audio Excel DSP 16 (MSS - emulation)". - - If you compile the driver into the kernel, you have to add - "aedsp16=,,,,," to the kernel - command line. - -Audio Excel DSP 16 (MSS emulation) -CONFIG_AEDSP16_MSS - Answer Y if you want your audio card to emulate Microsoft Sound - System. You should then say Y to "Microsoft Sound System support" - and say N to "Audio Excel DSP 16 (SBPro emulation)". - -SC-6600 based audio cards (new Audio Excel DSP 16) -CONFIG_SC6600 - The SC6600 is the new version of DSP mounted on the Audio Excel DSP - 16 cards. Find in the manual the FCC ID of your audio card and - answer Y if you have an SC6600 DSP. - -SC-6600 Joystick Interface -CONFIG_SC6600_JOY - Say Y here in order to use the joystick interface of the Audio Excel - DSP 16 card. - -SC-6600 CD-ROM Interface -CONFIG_SC6600_CDROM (4=None, 3=IDE, 1=Panasonic, 0=Sony) - This is used to activate the CD-ROM interface of the Audio Excel - DSP 16 card. Enter: 0 for Sony, 1 for Panasonic, 2 for IDE, 4 for no - CD-ROM present. - -SC-6600 CD-ROM Interface I/O Address -CONFIG_SC6600_CDROMBASE - Base I/O port address for the CD-ROM interface of the Audio Excel - DSP 16 card. - -Audio Excel DSP 16 (MPU401 emulation) -CONFIG_AEDSP16_MPU401 - Answer Y if you want your audio card to emulate the MPU-401 midi - interface. You should then also say Y to "MPU-401 support". - - Note that the I/O base for MPU-401 support of aedsp16 is the same - you have selected for "MPU-401 support". If you are using this - driver as a module you have to specify the MPU I/O base address with - the parameter 'mpu_base=0xNNN'. - -SC-6600 CDROM Interface (4=None, 3=IDE, 1=Panasonic, 0=?Sony?) -CONFIG_SC6600_CDROM - This is used to activate the CD-ROM interface of the Audio Excel - DSP 16 card. Enter: 0 for Sony, 1 for Panasonic, 2 for IDE, 4 for no - CD-ROM present. - -C-Media PCI (CMI8338/8738) -CONFIG_SOUND_CMPCI - Say Y or M if you have a PCI sound card using the CMI8338 - or the CMI8738 chipset. Data on these chips are available at - . - - A userspace utility to control some internal registers of these - chips is available at - . - -Support CMI8738 based audio cards -CONFIG_SOUND_CMPCI_CM8738 - Say Y or M if you have a PCI sound card using the CMI8338 - or the CMI8378 chipset. Data on this chip is available at - . - - A userspace utility to control some internal registers of these - chips is available at - . - -Enable joystick -CONFIG_SOUND_CMPCI_JOYSTICK - Say here in order to enable the joystick port on a sound crd using - the CMI8338 or the CMI8738 chipset. Data on these chips are - available at . - -Number of speakers (2, 4, 5, 6) -CONFIG_SOUND_CMPCI_SPEAKERS - Specify the number of speaker channels you want the card to drive, - as an integer. - -Enable S/PDIF loop for CMI8738 -CONFIG_SOUND_CMPCI_SPDIFLOOP - Enable loopback from SPDIF in to SPDIF out. For discussion, see - "The 8738 Audio SPDIF In/Out Technical Data" on the technical - support page at . - - A userspace utility to control even more internal registers of these - chips is available at - . - This package will among other things help you enable SPDIF - out/in/loop/monitor. - -Enable legacy FM -CONFIG_SOUND_CMPCI_FM - Say Y here to enable the legacy FM (frequency-modulation) synthesis - support on a card using the CMI8338 or CMI8378 chipset. - -FM I/O 388, 3C8, 3E0, 3E8 -CONFIG_SOUND_CMPCI_FMIO - Set the base I/O address for FM synthesis control on a card using - the CMI8338 or CMI8378 chipset. - -Enable legacy MPU-401 -CONFIG_SOUND_CMPCI_MIDI - Say Y here to enable the legacy MP401 MIDI synthesis support on a - card using the CMI8338 or CMI8378 chipset. - -MPU-401 I/O 330, 320, 310, 300 -CONFIG_SOUND_CMPCI_MPUIO - Set the base I/O address for MP401 MIDI synthesis control on a card - using the CMI8338 or CMI8378 chipset. - -Inverse S/PDIF in for CMI8738 -CONFIG_SOUND_CMPCI_SPDIFINVERSE - Say Y here to have the driver invert the signal presented on SPDIF IN - of a card using the CMI8338 or CMI8378 chipset. - -Use Line-in as Read-out -CONFIG_SOUND_CMPCI_LINE_REAR - Say Y here to enable using line-in jack as an output jack for a rear - speaker. - -Use Line-in as Bass -CONFIG_SOUND_CMPCI_LINE_BASS - Say Y here to enable using line-in jack as an output jack for a bass - speaker. - -Creative SBLive! (EMU10K1) based PCI sound cards -CONFIG_SOUND_EMU10K1 - Say Y or M if you have a PCI sound card using the EMU10K1 chipset, - such as the Creative SBLive!, SB PCI512 or Emu-APS. - - For more information on this driver and the degree of support for - the different card models please check: - - - - It is now possible to load dsp microcode patches into the EMU10K1 - chip. These patches are used to implement real time sound - processing effects which include for example: signal routing, - bass/treble control, AC3 passthrough, ... - Userspace tools to create new patches and load/unload them can be - found in the emu-tools package at the above URL. - -Creative SBLive! (EMU10K1) MIDI -CONFIG_MIDI_EMU10K1 - Say Y if you want to be able to use the OSS /dev/sequencer - interface. This code is still experimental. - -Crystal SoundFusion (CS4280/461x) -CONFIG_SOUND_FUSION - This module drives the Crystal SoundFusion devices (CS4280/46xx - series) when wired as native sound drivers with AC97 codecs. If - this driver does not work try the CS4232 driver. - -Ensoniq AudioPCI (ES1370) based PCI sound cards -CONFIG_SOUND_ES1370 - Say Y or M if you have a PCI sound card utilizing the Ensoniq - ES1370 chipset, such as Ensoniq's AudioPCI (non-97). To find - out if your sound card uses an ES1370 without removing your - computer's cover, use lspci -n and look for the PCI ID - 1274:5000. Since Ensoniq was bought by Creative Labs, - Sound Blaster 64/PCI models are either ES1370 or ES1371 based. - This driver differs slightly from OSS/Free, so PLEASE READ - . - -Ensoniq AudioPCI 97 (ES1371) based sound cards -CONFIG_SOUND_ES1371 - Say Y or M if you have a PCI sound card utilizing the Ensoniq - ES1371 chipset, such as Ensoniq's AudioPCI97. To find out if - your sound card uses an ES1371 without removing your computer's - cover, use lspci -n and look for the PCI ID 1274:1371. Since - Ensoniq was bought by Creative Labs, Sound Blaster 64/PCI - models are either ES1370 or ES1371 based. This driver differs - slightly from OSS/Free, so PLEASE READ - . - -ESS Solo1 based PCI sound cards (eg. SC1938) -CONFIG_SOUND_ESSSOLO1 - Say Y or M if you have a PCI sound card utilizing the ESS Technology - Solo1 chip. To find out if your sound card uses a - Solo1 chip without removing your computer's cover, use - lspci -n and look for the PCI ID 125D:1969. This driver - differs slightly from OSS/Free, so PLEASE READ - . - -S3 SonicVibes based PCI sound cards -CONFIG_SOUND_SONICVIBES - Say Y or M if you have a PCI sound card utilizing the S3 - SonicVibes chipset. To find out if your sound card uses a - SonicVibes chip without removing your computer's cover, use - lspci -n and look for the PCI ID 5333:CA00. This driver - differs slightly from OSS/Free, so PLEASE READ - . - -Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core -CONFIG_SOUND_TRIDENT - Say Y or M if you have a PCI sound card utilizing the Trident - 4DWave-DX/NX chipset or your mother board chipset has SiS 7018 - or ALi 5451 built-in. The SiS 7018 PCI Audio Core is embedded - in SiS960 Super South Bridge and SiS540/630 Single Chipset. - The ALi 5451 PCI Audio Core is embedded in ALi M1535, M1535D, - M1535+ or M1535D+ South Bridge. - - Use lspci -n to find out if your sound card or chipset uses - Trident 4DWave or SiS 7018. PCI ID 1023:2000 or 1023:2001 stands - for Trident 4Dwave. PCI ID 1039:7018 stands for SiS7018. PCI ID - 10B9:5451 stands for ALi5451. - - This driver supports S/PDIF in/out (record/playback) for ALi 5451 - embedded in ALi M1535+ and M1535D+. Note that they aren't all - enabled by default; you can enable them by saying Y to "/proc file - system support" and "Sysctl support", and after the /proc file - system has been mounted, executing the command - - command what is enabled - - echo 0>/proc/ALi5451 pcm out is also set to S/PDIF out. (Default). - - echo 1>/proc/ALi5451 use S/PDIF out to output pcm data. - - echo 2>/proc/ALi5451 use S/PDIF out to output non-pcm data. - (AC3...). - - echo 3>/proc/ALi5451 record from Ac97 in(MIC, Line in...). - (Default). - - echo 4>/proc/ALi5451 no matter Ac97 settings, record from S/PDIF - in. - - - This driver differs slightly from OSS/Free, so PLEASE READ the - comments at the top of . - -Rockwell WaveArtist -CONFIG_SOUND_WAVEARTIST - Say Y here to include support for the Rockwell WaveArtist sound - system. This driver is mainly for the NetWinder. - -VIA 82Cxxx Audio Codec -CONFIG_SOUND_VIA82CXXX - Say Y here to include support for the audio codec found on VIA - 82Cxxx-based chips. Typically these are built into a motherboard. - - DO NOT select Sound Blaster or Adlib with this driver, unless - you have a Sound Blaster or Adlib card in addition to your VIA - audio chip. - -VIA 82C686 MIDI -CONFIG_MIDI_VIA82CXXX - Answer Y to use the MIDI interface of the Via686. You may need to - enable this in the BIOS before it will work. This is for connection - to external MIDI hardware, and is not required for software playback - of MIDI files. - -NeoMagic 256AV/256ZX sound chipsets -CONFIG_SOUND_NM256 - Say M here to include audio support for the NeoMagic 256AV/256ZX - chipsets. These are the audio chipsets found in the Sony - Z505S/SX/DX, some Sony F-series, and the Dell Latitude CPi and CPt - laptops. It includes support for an AC97-compatible mixer and an - apparently proprietary sound engine. - - See for further information. - -ESS Maestro, Maestro2, Maestro2E driver -CONFIG_SOUND_MAESTRO - Say Y or M if you have a sound system driven by ESS's Maestro line - of PCI sound chips. These include the Maestro 1, Maestro 2, and - Maestro 2E. See for more - details. - -ESS Maestro3/Allegro driver -CONFIG_SOUND_MAESTRO3 - Say Y or M if you have a sound system driven by ESS's Maestro 3 - PCI sound chip. - -ForteMedia FM801 driver -CONFIG_SOUND_FORTE - Say Y or M if you want driver support for the ForteMedia FM801 PCI - audio controller (Abit AU10, Genius Sound Maker, HP Workstation - zx2000, and others). - -Adlib Cards -CONFIG_SOUND_ADLIB - Includes ASB 64 4D. Information on programming AdLib cards is - available at . - -Crystal Sound CS4281 -CONFIG_SOUND_CS4281 - Picture and feature list at - . - -16 bit sampling option of GUS (_NOT_ GUS MAX) -CONFIG_SOUND_GUS16 - Support for Gravis Ulstrasound (GUS) cards (other than the GUS), - sampling at 16-bit width. - -GUS MAX support -CONFIG_SOUND_GUSMAX - Support for Gravis Ulstrasound MAX. - -Intel ICH audio support -CONFIG_SOUND_ICH - Supports the following chipsets: - - Intel ICH 82801AA - Intel ICH 82901AB - Intel 440 MX - Intel ICH2 - Intel ICH3 - SiS 7012 - NVidia nForce - AMD 768 - - These are audio drivers for integral audio in chipsets of motherboards. - - Intel's I/O Controller Hub (ICH) is used on 810/815/820/840/845/845D/850 motherboards. - SiS 7012 is used on 645/735/745 motherboards. - -Verbose initialization -CONFIG_SOUND_TRACEINIT - Verbose soundcard initialization -- affects the format of autoprobe - and initialization messages at boot time. - -TV card (bt848) mixer support -CONFIG_SOUND_TVMIXER - Support for audio mixer facilities on the BT848 TV frame-grabber - card. - -VIDC 16-bit sound -CONFIG_SOUND_VIDC - 16-bit support for the VIDC onboard sound hardware found on Acorn - machines. - -Loopback MIDI device support -CONFIG_SOUND_VMIDI - Support for MIDI loopback on port 1 or 2. - -Yamaha YMF7xx PCI audio (native mode) -CONFIG_SOUND_YMFPCI - Support for Yamaha cards with the following chipsets: YMF724, - YMF724F, YMF740, YMF740C, YMF744, and YMF754. - - Two common cards that use this type of chip are Waveforce 192XG, - and Waveforce 192 Digital. - -Yamaha PCI legacy ports support -CONFIG_SOUND_YMFPCI_LEGACY - Support for YMF7xx PCI cards emulating an MP401. - -RME Hammerfall (RME96XX) support -CONFIG_SOUND_RME96XX - Say Y or M if you have a Hammerfall or Hammerfall light multichannel card - from RME. If you want to acess advanced features of the card, read - Documentation/sound/rme96xx. - -Are you using a crosscompiler -CONFIG_CROSSCOMPILE - Say Y here if you are compiling the kernel on a different - architecture than the one it is intended to run on. - -Kernel support for Linux/MIPS 32-bit binary compatibility -CONFIG_MIPS32_COMPAT - Select this option if you want Linux/MIPS 32-bit binary - compatibility. Since all software available for Linux/MIPS is - currently 32-bit you should say Y here. - -Kernel support for o32 binaries -CONFIG_MIPS32_O32 - Select this option if you want to run o32 binaries. These are pure - 32-bit binaries as used by the 32-bit Linux/MIPS port. Most of - existing binaries are in this format. - - If unsure, say Y. - -Kernel support for n32 binaries -CONFIG_MIPS32_N32 - Select this option if you want to run n32 binaries. These are - 64-bit binaries using 32-bit quantities for addressing and certain - data that would normally be 64-bit. They are used in special - cases. - - If unsure, say N. - -Build fp exception handler module -CONFIG_MIPS_FPE_MODULE - Build the floating point exception handler module. This option is - only useful for people working on the floating point exception - handler. If you don't, say N. - -Galileo EV64120 Evaluation board -CONFIG_MIPS_EV64120 - This is an evaluation board based on the Galileo GT-64120 - single-chip system controller that contains a MIPS R5000 compatible - core running at 75/100MHz. Their website is located at - . Say Y here if you wish to build a - kernel for this platform. - -Galileo EV96100 Evaluation board -CONFIG_MIPS_EV96100 - This is an evaluation board based on the Galielo GT-96100 LAN/WAN - communications controllers containing a MIPS R5000 compatible core - running at 83MHz. Their website is . Say Y - here if you wish to build a kernel for this platform. - -Support for ITE 8172G board -CONFIG_MIPS_ITE8172 - Ths is an evaluation board made by ITE - with ATX form factor that utilizes a MIPS R5000 to work with its - ITE8172G companion internet appliance chip. The MIPS core can be - either a NEC Vr5432 or QED RM5231. Say Y here if you wish to build - a kernel for this platform. - -Support for Globespan IVR board -CONFIG_MIPS_IVR - This is an evaluation board built by Globespan to showcase their - iVR (Internet Video Recorder) design. It utilizes a QED RM5231 - R5000 MIPS core. More information can be found out their website - located at . Say Y here if you wish to - build a kernel for this platform. - -Support for Alchemy Semi PB1000 board -CONFIG_MIPS_PB1000 - This is an evaluation board built by Alchemy Semiconductor to - showcase their Au1000 Internet Edge Processor. It is SOC design - containing a MIPS32 core running at 266/400/500MHz with many - integrated peripherals. Further information can be found at their - website, . Say Y here if you wish to - build a kernel for this platform. - -Support for Philips Nino -CONFIG_NINO - Say Y here to select a kernel for the Philips Nino Palm PC. The - website at - will have more information. - -# Choice: nino_model -CONFIG_NINO_4MB - Say Y here to build a kernel specifically for Nino Palm PCs with - 4MB of memory. These include models 300/301/302/319. - -Model-200/210/312/320/325/350/390 -CONFIG_NINO_8MB - Say Y here to build a kernel specifically for Nino Palm PCs with - 8MB of memory. These include models 200/210/312/320/325/350/390. - -Model-500/510 -CONFIG_NINO_16MB - Say Y here to build a kernel specifically for Nino 500/501 color - Palm PCs from Philips (INCOMPLETE). -Model-300/301/302/319 - -Enable run-time debugging -CONFIG_RUNTIME_DEBUG - If you say Y here, some debugging macros will do run-time checking. - If you say N here, those macros will mostly turn to no-ops. Currently - supported by MIPS arch. See include/asm-mips/debug.h for debuging macros. - If unsure, say N. - -Run uncached -CONFIG_MIPS_UNCACHED - If you say Y here there kernel will disable all CPU caches. This will - reduce the system's performance dramatically but can help finding - otherwise hard to track bugs. It can also useful if you're doing - hardware debugging with a logic analyzer and need to see all traffic - on the bus. - -AU1000 ethernet controller on SGI MIPS system -CONFIG_MIPS_AU1000_ENET - If you have an Alchemy Semi AU1000 ethernet controller - on an SGI MIPS system, say Y. Otherwise, say N. - -WD93 SCSI Controller on SGI MIPS system -CONFIG_SGIWD93_SCSI - If you have a Western Digital WD93 SCSI controller on - an SGI MIPS system, say Y. Otherwise, say N. - -Magic System Request Key support -CONFIG_MAGIC_SYSRQ - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -ISDN support -CONFIG_ISDN - ISDN ("Integrated Services Digital Networks", called RNIS in France) - is a special type of fully digital telephone service; it's mostly - used to connect to your Internet service provider (with SLIP or - PPP). The main advantage is that the speed is higher than ordinary - modem/telephone connections, and that you can have voice - conversations while downloading stuff. It only works if your - computer is equipped with an ISDN card and both you and your service - provider purchased an ISDN line from the phone company. For - details, read on the WWW. - - This driver allows you to use an ISDN-card for networking - connections and as dialin/out device. The isdn-tty's have a built - in AT-compatible modem emulator. Network devices support autodial, - channel-bundling, callback and caller-authentication without having - a daemon running. A reduced T.70 protocol is supported with tty's - suitable for German BTX. On D-Channel, the protocols EDSS1 - (Euro-ISDN) and 1TR6 (German style) are supported. See - for more information. - - If you want to compile the ISDN code as a module ( = code which can - be inserted in and removed from the running kernel whenever you - want), say M here and read . The - module will be called isdn.o. If unsure, say N. - -Support synchronous PPP -CONFIG_ISDN_PPP - Over digital connections such as ISDN, there is no need to - synchronize sender and recipient's clocks with start and stop bits - as is done over analog telephone lines. Instead, one can use - "synchronous PPP". Saying Y here will include this protocol. This - protocol is used by Cisco and Sun for example. So you want to say Y - here if the other end of your ISDN connection supports it. You will - need a special version of pppd (called ipppd) for using this - feature. See and - for more information. - -PPP filtering for ISDN -CONFIG_IPPP_FILTER - Say Y here if you want to be able to filter the packets passing over - IPPP interfaces. This allows you to control which packets count as - activity (i.e. which packets will reset the idle timer or bring up - a demand-dialled link) and which packets are to be dropped entirely. - You need to say Y here if you wish to use the pass-filter and - active-filter options to ipppd. - - If unsure, say N. - -Support generic MP (RFC 1717) -CONFIG_ISDN_MPP - With synchronous PPP enabled, it is possible to increase throughput - by bundling several ISDN-connections, using this protocol. See - for more information. - -Use VJ-compression with synchronous PPP -CONFIG_ISDN_PPP_VJ - This enables Van Jacobson header compression for synchronous PPP. - Say Y if the other end of the connection supports it. - -Support BSD compression -CONFIG_ISDN_PPP_BSDCOMP - Support for the BSD-Compress compression method for PPP, which uses - the LZW compression method to compress each PPP packet before it is - sent over the wire. The machine at the other end of the PPP link - (usually your ISP) has to support the BSD-Compress compression - method as well for this to be useful. Even if they don't support it, - it is safe to say Y here. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called isdn_bsdcomp.o. - -Support audio via ISDN -CONFIG_ISDN_AUDIO - If you say Y here, the modem-emulator will support a subset of the - EIA Class 8 Voice commands. Using a getty with voice-support - (mgetty+sendfax by gert@greenie.muc.de with an extension, available - with the ISDN utility package for example), you will be able to use - your Linux box as an ISDN-answering machine. Of course, this must be - supported by the lowlevel driver also. Currently, the HiSax driver - is the only voice-supporting driver. See - for more information. - -X.25 PLP on top of ISDN -CONFIG_ISDN_X25 - This feature provides the X.25 protocol over ISDN connections. - See for more information - if you are thinking about using this. - -ISDN diversion services support -CONFIG_ISDN_DIVERSION - This option allows you to use some supplementary diversion - services in conjunction with the HiSax driver on an EURO/DSS1 - line. - - Supported options are CD (call deflection), CFU (Call forward - unconditional), CFB (Call forward when busy) and CFNR (call forward - not reachable). Additionally the actual CFU, CFB and CFNR state may - be interrogated. - - The use of CFU, CFB, CFNR and interrogation may be limited to some - countries. The keypad protocol is still not implemented. CD should - work in all countries if the service has been subscribed to. - - Please read the file . - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called dss1_divert.o. - -ICN 2B and 4B support -CONFIG_ISDN_DRV_ICN - This enables support for two kinds of ISDN-cards made by a German - company called ICN. 2B is the standard version for a single ISDN - line with two B-channels, 4B supports two ISDN lines. For running - this card, additional firmware is necessary, which has to be - downloaded into the card using a utility which is distributed - separately. See and - for more - information. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called icn.o. - -isdnloop support -CONFIG_ISDN_DRV_LOOP - This driver provides a virtual ISDN card. Its primary purpose is - testing of linklevel features or configuration without getting - charged by your service-provider for lots of phone calls. - You need will need the loopctrl utility from the latest isdn4k-utils - package to set up this driver. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called isdnloop.o. - -HiSax SiemensChipSet driver support -CONFIG_ISDN_DRV_HISAX - This is a driver supporting the Siemens chipset on various - ISDN-cards (like AVM A1, Elsa ISDN cards, Teles S0-16.0, Teles - S0-16.3, Teles S0-8, Teles/Creatix PnP, ITK micro ix1 and many - compatibles). - - HiSax is just the name of this driver, not the name of any hardware. - - If you have a card with such a chipset, you should say Y here and - also to the configuration option of the driver for your particular - card, below. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called hisax.o. See - for more information on using this driver. - -HiSax Support for EURO/DSS1 -CONFIG_HISAX_EURO - Say Y or N according to the D-channel protocol which your local - telephone service company provides. - - The call control protocol E-DSS1 is used in most European countries. - If unsure, say Y. - -Support for German chargeinfo -CONFIG_DE_AOC - If you want that the HiSax hardware driver sends messages to the - upper level of the isdn code on each AOCD (Advice Of Charge, During - the call -- transmission of the fee information during a call) and - on each AOCE (Advice Of Charge, at the End of the call -- - transmission of fee information at the end of the call), say Y here. - This works only in Germany. - -Disable sending complete -CONFIG_HISAX_NO_SENDCOMPLETE - If you have trouble with some ugly exchanges or you live in - Australia select this option. - -Disable sending low layer compatibility -CONFIG_HISAX_NO_LLC - If you have trouble with some ugly exchanges try to select this - option. - -Disable keypad protocol option -CONFIG_HISAX_NO_KEYPAD - If you like to send special dial strings including * or # without - using the keypad protocol, select this option. - -HiSax Support for German 1TR6 -CONFIG_HISAX_1TR6 - Say Y or N according to the D-channel protocol which your local - telephone service company provides. - - 1TR6 is an old call control protocol which was used in Germany - before E-DSS1 was established. Nowadays, all new lines in Germany - use E-DSS1. - -HiSax Support for US NI1 -CONFIG_HISAX_NI1 - Enable this if you like to use ISDN in US on a NI1 basic rate - interface. - -Maximum number of cards supported by HiSax -CONFIG_HISAX_MAX_CARDS - This is used to allocate a driver-internal structure array with one - entry for each HiSax card on your system. - -Teles 16.0/8.0 -CONFIG_HISAX_16_0 - This enables HiSax support for the Teles ISDN-cards S0-16.0, S0-8 - and many compatibles. - - See on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port/shmem settings. - -Teles 16.3 or PNP or PCMCIA -CONFIG_HISAX_16_3 - This enables HiSax support for the Teles ISDN-cards S0-16.3 the - Teles/Creatix PnP and the Teles PCMCIA. - - See on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. - -Teles PCI -CONFIG_HISAX_TELESPCI - This enables HiSax support for the Teles PCI. - See on how to configure it. - -Teles S0Box -CONFIG_HISAX_S0BOX - This enables HiSax support for the Teles/Creatix parallel port - S0BOX. See on how to - configure it. - -AVM A1 (Fritz) -CONFIG_HISAX_AVM_A1 - This enables HiSax support for the AVM A1 (aka "Fritz"). - - See on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. - -AVM PnP/PCI (Fritz!PnP/PCI) -CONFIG_HISAX_FRITZPCI - This enables HiSax support for the AVM "Fritz!PnP" and "Fritz!PCI". - See on how to configure it. - -AVM A1 PCMCIA (Fritz) -CONFIG_HISAX_AVM_A1_PCMCIA - This enables HiSax support for the AVM A1 "Fritz!PCMCIA"). - See on how to configure it. - -Elsa cards -CONFIG_HISAX_ELSA - This enables HiSax support for the Elsa Mircolink ISA cards, for the - Elsa Quickstep series cards and Elsa PCMCIA. - - See on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. - -ITK ix1-micro Revision 2 -CONFIG_HISAX_IX1MICROR2 - This enables HiSax support for the ITK ix1-micro Revision 2 card. - - See on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. - -Eicon.Diehl Diva cards -CONFIG_HISAX_DIEHLDIVA - This enables HiSax support for the Eicon.Diehl Diva none PRO - versions passive ISDN cards. - - See on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. - -ASUSCOM ISA cards -CONFIG_HISAX_ASUSCOM - This enables HiSax support for the AsusCom and their OEM versions - passive ISDN ISA cards. - - See on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. - -TELEINT cards -CONFIG_HISAX_TELEINT - This enables HiSax support for the TELEINT SA1 semiactiv ISDN card. - - See on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. - -HFC-S based cards -CONFIG_HISAX_HFCS - This enables HiSax support for the HFC-S 2BDS0 based cards, like - teles 16.3c. - - See on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. - -Sedlbauer cards -CONFIG_HISAX_SEDLBAUER - This enables HiSax support for the Sedlbauer passive ISDN cards. - - See on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. - -USR Sportster internal TA -CONFIG_HISAX_SPORTSTER - This enables HiSax support for the USR Sportster internal TA card. - - See on how to configure it - using a different D-channel protocol, or non-standard IRQ/port - settings. - -MIC card -CONFIG_HISAX_MIC - This enables HiSax support for the ITH MIC card. - - See on how to configure it - using a different D-channel protocol, or non-standard IRQ/port - settings. - -NETjet card -CONFIG_HISAX_NETJET - This enables HiSax support for the NetJet from Traverse - Technologies. - - See on how to configure it - using a different D-channel protocol, or non-standard IRQ/port - settings. - -NETspider U card -CONFIG_HISAX_NETJET_U - This enables HiSax support for the Netspider U interface ISDN card - from Traverse Technologies. - See on how to configure it - using a different D-channel protocol, or non-standard IRQ/port - settings. - -Niccy PnP/PCI card -CONFIG_HISAX_NICCY - This enables HiSax support for the Dr. Neuhaus Niccy PnP or PCI. - - See on how to configure it - using a different D-channel protocol, or non-standard IRQ/port - settings. - -Siemens I-Surf card -CONFIG_HISAX_ISURF - This enables HiSax support for the Siemens I-Talk/I-Surf card with - ISAR chip. - See on how to configure it - using a different D-channel protocol, or non-standard IRQ/port - settings. - -HST Saphir card -CONFIG_HISAX_HSTSAPHIR - This enables HiSax support for the HST Saphir card. - - See on how to configure it - using a different D-channel protocol, or non-standard IRQ/port - settings. - -Telekom A4T card -CONFIG_HISAX_BKM_A4T - This enables HiSax support for the Telekom A4T card. - - See on how to configure it - using a different D-channel protocol, or non-standard IRQ/port - settings. - -Scitel Quadro card -CONFIG_HISAX_SCT_QUADRO - This enables HiSax support for the Scitel Quadro card. - - See on how to configure it - using a different D-channel protocol, or non-standard IRQ/port - settings. - -Gazel cards -CONFIG_HISAX_GAZEL - This enables HiSax support for the Gazel cards. - - See on how to configure it - using a different D-channel protocol, or non-standard IRQ/port - settings. - -HFC PCI-Bus cards -CONFIG_HISAX_HFC_PCI - This enables HiSax support for the HFC-S PCI 2BDS0 based cards. - - For more informations see under - . - -Winbond W6692 based cards -CONFIG_HISAX_W6692 - This enables HiSax support for Winbond W6692 based PCI ISDN cards. - - See on how to configure it - using a different D-channel protocol, or non-standard IRQ/port - settings. - -HFC-S+, HFC-SP, HFC-PCMCIA cards -CONFIG_HISAX_HFC_SX - This enables HiSax support for the HFC-S+, HFC-SP and HFC-PCMCIA - cards. This code is not finished yet. - -Formula-n enter:now PCI card (EXPERIMENTAL) -CONFIG_HISAX_ENTERNOW_PCI - This enables HiSax support for the Formula-n enter:now PCI - ISDN card. - -Am7930 -CONFIG_HISAX_AMD7930 - This enables HiSax support for the AMD7930 chips on some SPARCs. - This code is not finished yet. - -HiSax debugging -CONFIG_HISAX_DEBUG - This enables debugging code in the new-style HiSax drivers, i.e. - the ST5481 USB driver currently. - If in doubt, say yes. - -ELSA PCMCIA MicroLink cards -CONFIG_HISAX_ELSA_CS - This enables the PCMCIA client driver for the Elsa PCMCIA MicroLink - card. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called elsa_cs.o. - -Sedlbauer PCMCIA cards -CONFIG_HISAX_SEDLBAUER_CS - This enables the PCMCIA client driver for the Sedlbauer Speed Star - and Speed Star II cards. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called sedlbauer_cs.o. - -CONFIG_HISAX_AVM_A1_CS - This enables the PCMCIA client driver for the AVM A1 / Fritz!Card - PCMCIA cards. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called avma1_cs.o. - -ST5481 USB ISDN modem -CONFIG_HISAX_ST5481 - This enables the driver for ST5481 based USB ISDN adapters, - e.g. the BeWan Gazel 128 USB - -PCBIT-D support -CONFIG_ISDN_DRV_PCBIT - This enables support for the PCBIT ISDN-card. This card is - manufactured in Portugal by Octal. For running this card, - additional firmware is necessary, which has to be downloaded into - the card using a utility which is distributed separately. See - and - for more information. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called pcbit.o. - -Spellcaster support -CONFIG_ISDN_DRV_SC - This enables support for the Spellcaster BRI ISDN boards. This - driver currently builds only in a modularized version ( = code which - can be inserted in and removed from the running kernel whenever you - want, details in ); the module will - be called sc.o. See and - for more information. - -Eicon active card support -CONFIG_ISDN_DRV_EICON - Say Y here if you have an Eicon active ISDN card. In order to use - this card, additional firmware is necessary, which has to be loaded - into the card using the eiconctrl utility which is part of the - latest isdn4k-utils package. Please read the file - for more information. - -Legacy Eicon driver -CONFIG_ISDN_DRV_EICON_OLD - Say Y here to use your Eicon active ISDN card with ISDN4Linux - isdn module. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called eicon.o. - -Eicon PCI DIVA Server BRI/PRI/4BRI support -CONFIG_ISDN_DRV_EICON_PCI - Say Y here if you have an Eicon Diva Server (BRI/PRI/4BRI) ISDN - card. Please read for more - information. - -Eicon old-type (S,SX,SCOM,Quadro,S2M) card support -CONFIG_ISDN_DRV_EICON_ISA - Say Y here if you have an old-type Eicon active ISDN card. In order - to use this card, additional firmware is necessary, which has to be - loaded into the card using the eiconctrl utility which is part of - the latest isdn4k-utils package. Please read the file - for more information. - -Eicon driver type standalone -CONFIG_ISDN_DRV_EICON_DIVAS - Enable this option if you want the eicon driver as standalone - version with no interface to the ISDN4Linux isdn module. If you - say Y here, the eicon module only supports the Diva Server PCI - cards and will provide its own IDI interface. You should say N - here. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called divas.o. - -Support AT-Fax Class 1 and 2 commands -CONFIG_ISDN_TTY_FAX - If you say Y here, the modem-emulator will support a subset of the - Fax Class 1 and 2 commands. Using a getty with fax-support - (mgetty+sendfax, hylafax), you will be able to use your Linux box as - an ISDN-fax-machine. This must be supported by the lowlevel driver - also. See for more information. - -CAPI2.0 support -CONFIG_ISDN_CAPI - This provides the CAPI (Common ISDN Application Programming - Interface, a standard making it easy for programs to access ISDN - hardware, see . This is needed for AVM's set - of active ISDN controllers like B1, T1, M1. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The modules will be called capi.o and kernelcapi.o. If you want to - compile it as a module, say M here and read - . - -CAPI2.0 /dev/capi20 support -CONFIG_ISDN_CAPI_CAPI20 - This option will provide the CAPI 2.0 interface to userspace - applications via /dev/capi20. Applications should use the - standardized libcapi20 to access this functionality. You should say - Y/M here. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called capi.o. - -CAPI2.0 Middleware support -CONFIG_ISDN_CAPI_MIDDLEWARE - This option will enhance the capabilities of the /dev/capi20 - interface. It will provide a means of moving a data connection, - established via the usual /dev/capi20 interface to a special tty - device. If you want to use pppd with pppdcapiplugin to dial up to - your ISP, say Y here. - -CAPI2.0 filesystem support -CONFIG_ISDN_CAPI_CAPIFS - This option provides a special file system, similar to /dev/pts with - device nodes for the special ttys established by using the - middleware extension above. If you want to use pppd with - pppdcapiplugin to dial up to your ISP, say Y here. - -CAPI2.0 capidrv interface support -CONFIG_ISDN_CAPI_CAPIDRV - This option provides the glue code to hook up CAPI driven cards to - the legacy isdn4linux link layer. If you have a card which is - supported by a CAPI driver, but still want to use old features like - ippp interfaces or ttyI emulation, say Y/M here. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called capidrv.o. - -AVM B1 ISA support -CONFIG_ISDN_DRV_AVMB1_B1ISA - Enable support for the ISA version of the AVM B1 card. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called b1isa.o. - -AVM B1 PCI support -CONFIG_ISDN_DRV_AVMB1_B1CICI - Enable support for the PCI version of the AVM B1 card. - -AVM B1 PCI V4 support -CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - Enable support for the V4 version of AVM B1 PCI card. - -AVM T1/T1-B ISA support -CONFIG_ISDN_DRV_AVMB1_T1ISA - Enable support for the AVM T1 T1B card. - Note: This is a PRI card and handle 30 B-channels. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called t1isa.o. - -AVM B1/M1/M2 PCMCIA support -CONFIG_ISDN_DRV_AVMB1_B1PCMCIA - Enable support for the PCMCIA version of the AVM B1 card. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called b1pcmcia.o. - -AVM B1/M1/M2 PCMCIA cs module -CONFIG_ISDN_DRV_AVMB1_AVM_CS - Enable the PCMCIA client driver for the AVM B1/M1/M2 - PCMCIA cards. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called avm_cs.o. - -AVM T1/T1-B PCI support -CONFIG_ISDN_DRV_AVMB1_T1PCI - Enable support for the AVM T1 T1B card. - Note: This is a PRI card and handle 30 B-channels. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called t1pci.o. - -AVM C4/C2 support -CONFIG_ISDN_DRV_AVMB1_C4 - Enable support for the AVM C4/C2 PCI cards. - These cards handle 4/2 BRI ISDN lines (8/4 channels). - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called c4.o. - -Verbose reason code reporting (kernel size +=7K) -CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON - If you say Y here, the AVM B1 driver will give verbose reasons for - disconnecting. This will increase the size of the kernel by 7 KB. If - unsure, say Y. - -IBM Active 2000 support -CONFIG_ISDN_DRV_ACT2000 - Say Y here if you have an IBM Active 2000 ISDN card. In order to use - this card, additional firmware is necessary, which has to be loaded - into the card using a utility which is part of the latest - isdn4k-utils package. Please read the file - for more information. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called act2000.o. - -Auvertech TurboPAM support -CONFIG_ISDN_DRV_TPAM - This enables support for the Auvertech TurboPAM ISDN-card. - For running this card, additional firmware is necessary, which has - to be downloaded into the card using a utility which is distributed - separately from the Auvertech's web site: . - - Please redirect all support questions to support@auvertech.fr. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called tpam.o. - -Hypercope HYSDN cards (Champ, Ergo, Metro) support (module) -CONFIG_HYSDN - Say Y here if you have one of Hypercope's active PCI ISDN cards - Champ, Ergo and Metro. You will then get a module called hysdn.o. - Please read the file for more - information. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called hysdn.o. - -HYSDN CAPI 2.0 support -CONFIG_HYSDN_CAPI - Say Y here if you like to use Hypercope's CAPI 2.0 interface. - -Support for SUN4 machines (disables SUN4[CDM] support) -CONFIG_SUN4 - Say Y here if, and only if, your machine is a Sun4. Note that - a kernel compiled with this option will run only on Sun4. - (And the current version will probably work only on sun4/330.) - -SPARC ESP SCSI support -CONFIG_SCSI_SUNESP - This is the driver for the Sun ESP SCSI host adapter. The ESP - chipset is present in most SPARC SBUS-based computers. - - This support is also available as a module called esp.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -PTI Qlogic, ISP Driver -CONFIG_SCSI_QLOGICPTI - This driver supports SBUS SCSI controllers from PTI or QLogic. These - controllers are known under Solaris as qpti and in the openprom as - PTI,ptisp or QLGC,isp. Note that PCI QLogic SCSI controllers are - driven by a different driver. - - This support is also available as a module called qlogicpti.o ( = - code which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Sun PROM console -CONFIG_PROM_CONSOLE - Say Y to build a console driver for Sun machines that uses the - terminal emulation built into their console PROMS. - -/dev/openprom device support -CONFIG_SUN_OPENPROMIO - This driver provides user programs with an interface to the SPARC - PROM device tree. The driver implements a SunOS-compatible - interface and a NetBSD-compatible interface. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M and read . If unsure, say Y. - -Openprom tree appears in /proc/openprom -CONFIG_SUN_OPENPROMFS - If you say Y, the OpenPROM device tree will be available as a - virtual file system, which you can mount to /proc/openprom by "mount - -t openpromfs none /proc/openprom". - - If you want to compile the /proc/openprom support as a module ( = - code which can be inserted in and removed from the running kernel - whenever you want), say M here and read - . - The module will be called openpromfs.o. If unsure, say M. - -Kernel support for Linux/Sparc 32bit binary compatibility -CONFIG_SPARC32_COMPAT - This allows you to run 32-bit binaries on your Ultra. - Everybody wants this; say Y. - -Kernel support for 32-bit ELF binaries -CONFIG_BINFMT_ELF32 - This allows you to run 32-bit Linux/ELF binaries on your machine. - Everybody wants this; say Y. - -Kernel support for 32-bit (ie. SunOS) a.out binaries -CONFIG_BINFMT_AOUT32 - This allows you to run 32-bit a.out format binaries on your Ultra. - If you want to run SunOS binaries (see SunOS binary emulation below) - or other a.out binaries, say Y. If unsure, say N. - -SunOS binary emulation -CONFIG_SUNOS_EMUL - This allows you to run most SunOS binaries. If you want to do this, - say Y here and place appropriate files in /usr/gnemul/sunos. See - for more information. If you - want to run SunOS binaries on an Ultra you must also say Y to - "Kernel support for 32-bit a.out binaries" above. - -Mostek real time clock support -CONFIG_SUN_MOSTEK_RTC - The Mostek RTC chip is used on all known Sun computers except - some JavaStations. For a JavaStation you need to say Y both here - and to "Enhanced Real Time Clock Support". - - Say Y here unless you are building a special purpose kernel. - -OBP Flash Device support -CONFIG_OBP_FLASH - The OpenBoot PROM on Ultra systems is flashable. If you want to be - able to upgrade the OBP firmware, say Y here. - -JavaStation OS Flash SIMM -CONFIG_SUN_JSFLASH - If you say Y here, you will be able to boot from your JavaStation's - Flash memory. - -Siemens SAB82532 serial support -CONFIG_SAB82532 - This driver supports the serial ports on newer (PCI) Ultra systems. - Say Y if you want to be able to use your serial ports. - -Videopix Frame Grabber -CONFIG_SUN_VIDEOPIX - Say Y here to support the Videopix Frame Grabber from Sun - Microsystems, commonly found on SPARCstations. This card, which is - based on the Phillips SAA9051, can handle NTSC and PAL/SECAM and - SVIDEO signals. - -Sun bidirectional parallel port support -CONFIG_SUN_BPP - Say Y here to support Sun's obsolete variant of IEEE1284 - bidirectional parallel port protocol as /dev/bppX. Can be built on - x86 machines. - -Aurora Multiboard 1600se -CONFIG_SUN_AURORA - The Aurora Multiboard is a multi-port high-speed serial controller. - If you have one of these, say Y. - -Tadpole TS102 Microcontroller support -CONFIG_TADPOLE_TS102_UCTRL - Say Y here to directly support the TS102 Microcontroller interface - on the Tadpole Sparcbook 3. This device handles power-management - events, and can also notice the attachment/detachment of external - monitors and mice. - -Audio support -CONFIG_SPARCAUDIO - This driver provides support for the build-in sound devices on most - Sun machines. If you want to be able to use this, select this option - and one or more of the lowlevel drivers below. See - for more - information. - -AMD7930 Lowlevel Driver -CONFIG_SPARCAUDIO_AMD7930 - This driver supports the AMD 7930 chip found on sun4c, 4/6xx, and - SparcClassic systems. - -CS4231 Lowlevel Driver -CONFIG_SPARCAUDIO_CS4231 - This driver supports the Crystal Semiconductor CS4231 chip found on - the SS4, SS5, and Ultras. - -DBRI Lowlevel Driver -CONFIG_SPARCAUDIO_DBRI - This driver supports the DBRI audio interface found on the SS10, - SS20, LX, Sparcbook 3, and Voyager systems. - -Dummy Lowlevel Driver -CONFIG_SPARCAUDIO_DUMMY - This is a pseudo-driver used for debugging and testing the - sparcaudio subsystem. Say N unless you want to work on this - subsystem. - -Sparc hardware -CONFIG_PARPORT_SUNBPP - This driver provides support for the bidirectional parallel port - found on many Sun machines. Note that many of the newer Ultras - actually have pc style hardware instead. - -SPARC power management support -CONFIG_SUN_PM - Enable power management and CPU standby features on supported - SPARC platforms. - -/proc/hardware support -CONFIG_PROC_HARDWARE - Say Y here to support the /proc/hardware file, which gives you - access to information about the machine you're running on, - including the model, CPU, MMU, clock speed, BogoMIPS rating, - and memory size. - -Bluetooth subsystem support -CONFIG_BLUEZ - Bluetooth is low-cost, low-power, short-range wireless technology. - It was designed as a replacement for cables and other short-range - technologies like IrDA. Bluetooth operates in personal area range - that typically extends up to 10 meters. More information about - Bluetooth can be found at . - - Linux Bluetooth subsystem consist of several layers: - BlueZ Core (HCI device and connection manager, scheduler) - HCI Device drivers (interface to the hardware) - L2CAP Module (L2CAP protocol) - SCO Module (SCO links) - RFCOMM Module (RFCOMM protocol) - BNEP Module (BNEP protocol) - CMTP Module (CMTP protocol) - - Say Y here to enable Linux Bluetooth support and to build BlueZ Core - layer. - - To use Linux Bluetooth subsystem, you will need several user-space - utilities like hciconfig and hcid. These utilities and updates to - Bluetooth kernel modules are provided in the BlueZ package. - For more information, see . - - If you want to compile BlueZ Core as module (bluez.o) say M here. - -L2CAP protocol support -CONFIG_BLUEZ_L2CAP - L2CAP (Logical Link Control and Adaptation Protocol) provides - connection oriented and connection-less data transport. L2CAP - support is required for most Bluetooth applications. - - Say Y here to compile L2CAP support into the kernel or say M to - compile it as module (l2cap.o). - -SCO links support -CONFIG_BLUEZ_SCO - SCO link provides voice transport over Bluetooth. SCO support is - required for voice applications like Headset and Audio. - - Say Y here to compile SCO support into the kernel or say M to - compile it as module (sco.o). - -RFCOMM protocol support -CONFIG_BLUEZ_RFCOMM - RFCOMM provides connection oriented stream transport. RFCOMM - support is required for Dialup Networking, OBEX and other Bluetooth - applications. - - Say Y here to compile RFCOMM support into the kernel or say M to - compile it as module (rfcomm.o). - -RFCOMM TTY emulation support -CONFIG_BLUEZ_RFCOMM_TTY - This option enables TTY emulation support for RFCOMM channels. - -BNEP protocol support -CONFIG_BLUEZ_BNEP - BNEP (Bluetooth Network Encapsulation Protocol) is Ethernet - emulation layer on top of Bluetooth. BNEP is required for Bluetooth - PAN (Personal Area Network). - - To use BNEP, you will need user-space utilities provided in the - BlueZ-PAN package. - For more information, see . - - Say Y here to compile BNEP support into the kernel or say M to - compile it as module (bnep.o). - -CMTP protocol support -CONFIG_BLUEZ_CMTP - CMTP (CAPI Message Transport Protocol) is a transport layer - for CAPI messages. CMTP is required for the Bluetooth Common - ISDN Access Profile. - - Say Y here to compile CMTP support into the kernel or say M to - compile it as module (cmtp.o). - -BNEP multicast filter support -CONFIG_BLUEZ_BNEP_MC_FILTER - This option enables the multicast filter support for BNEP. - -BNEP protocol filter support -CONFIG_BLUEZ_BNEP_PROTO_FILTER - This option enables the protocol filter support for BNEP. - -HCI UART driver -CONFIG_BLUEZ_HCIUART - Bluetooth HCI UART driver. - This driver is required if you want to use Bluetooth devices with - serial port interface. You will also need this driver if you have - UART based Bluetooth PCMCIA and CF devices like Xircom Credit Card - adapter and BrainBoxes Bluetooth PC Card. - - Say Y here to compile support for Bluetooth UART devices into the - kernel or say M to compile it as module (hci_uart.o). - -HCI UART (H4) protocol support -CONFIG_BLUEZ_HCIUART_H4 - UART (H4) is serial protocol for communication between Bluetooth - device and host. This protocol is required for most Bluetooth devices - with UART interface, including PCMCIA and CF cards. - - Say Y here to compile support for HCI UART (H4) protocol. - -HCI BCSP protocol support -CONFIG_BLUEZ_HCIUART_BCSP - BCSP (BlueCore Serial Protocol) is serial protocol for communication - between Bluetooth device and host. This protocol is required for non - USB Bluetooth devices based on CSR BlueCore chip, including PCMCIA and - CF cards. - - Say Y here to compile support for HCI BCSP protocol. - -HCI BCSP transmit CRC with every BCSP packet -CONFIG_BLUEZ_HCIUART_BCSP_TXCRC - If you say Y here, a 16-bit CRC checksum will be transmitted along with - every BCSP (BlueCore Serial Protocol) packet sent to the Bluetooth chip. - This increases reliability, but slightly reduces efficiency. - -HCI USB driver -CONFIG_BLUEZ_HCIUSB - Bluetooth HCI USB driver. - This driver is required if you want to use Bluetooth devices with - USB interface. - - Say Y here to compile support for Bluetooth USB devices into the - kernel or say M to compile it as module (hci_usb.o). - -HCI USB SCO (voice) support -CONFIG_BLUEZ_HCIUSB_SCO - This option enables the SCO support in the HCI USB driver. You need this - to transmit voice data with your Bluetooth USB device. And your device - must also support sending SCO data over the HCI layer, because some of - them sends the SCO data to an internal PCM adapter. - - Say Y here to compile support for HCI SCO data. - -HCI VHCI Virtual HCI device driver -CONFIG_BLUEZ_HCIVHCI - Bluetooth Virtual HCI device driver. - This driver is required if you want to use HCI Emulation software. - - Say Y here to compile support for virtual HCI devices into the - kernel or say M to compile it as module (hci_vhci.o). - -HCI BFUSB device driver -CONFIG_BLUEZ_HCIBFUSB - Bluetooth HCI BlueFRITZ! USB driver. - This driver provides support for Bluetooth USB devices with AVM - interface: - AVM BlueFRITZ! USB - - Say Y here to compile support for HCI BFUSB devices into the - kernel or say M to compile it as module (bfusb.o). - -HCI DTL1 (PC Card) device driver -CONFIG_BLUEZ_HCIDTL1 - Bluetooth HCI DTL1 (PC Card) driver. - This driver provides support for Bluetooth PCMCIA devices with - Nokia DTL1 interface: - Nokia Bluetooth Card - Socket Bluetooth CF Card - - Say Y here to compile support for HCI DTL1 devices into the - kernel or say M to compile it as module (dtl1_cs.o). - -HCI BT3C (PC Card) device driver -CONFIG_BLUEZ_HCIBT3C - Bluetooth HCI BT3C (PC Card) driver. - This driver provides support for Bluetooth PCMCIA devices with - 3Com BT3C interface: - 3Com Bluetooth Card (3CRWB6096) - HP Bluetooth Card - - The HCI BT3C driver uses external firmware loader program provided in - the BlueFW package. For more information, see . - - Say Y here to compile support for HCI BT3C devices into the - kernel or say M to compile it as module (bt3c_cs.o). - -HCI BlueCard (PC Card) device driver -CONFIG_BLUEZ_HCIBLUECARD - Bluetooth HCI BlueCard (PC Card) driver. - This driver provides support for Bluetooth PCMCIA devices with - Anycom BlueCard interface: - Anycom Bluetooth PC Card - Anycom Bluetooth CF Card - - Say Y here to compile support for HCI BlueCard devices into the - kernel or say M to compile it as module (bluecard_cs.o). - -HCI UART (PC Card) device driver -CONFIG_BLUEZ_HCIBTUART - Bluetooth HCI UART (PC Card) driver. - This driver provides support for Bluetooth PCMCIA devices with - an UART interface: - Xircom CreditCard Bluetooth Adapter - Xircom RealPort2 Bluetooth Adapter - Sphinx PICO Card - H-Soft blue+Card - Cyber-blue Compact Flash Card - - Say Y here to compile support for HCI UART devices into the - kernel or say M to compile it as module (btuart_cs.o). - -# The following options are for Linux when running on the Hitachi -# SuperH family of RISC microprocessors. - -SuperH RTC support -CONFIG_SH_RTC - Selecting this option will allow the Linux kernel to emulate - PC's RTC. - - If unsure, say N. - -SuperH peripheral clock frequency -CONFIG_SH_PCLK_FREQ - Set this value or add "sh_pclk=" command line option to tell - peripheral clock frequency to kernel, if your system has no RTC. - Otherwise leave it 0, and kernel measures peripheral clock frequency - using TMU and RTC while system startup. - - If unsure, set 0. - -Wakeup UBC on startup -CONFIG_UBC_WAKEUP - Selecting this option will wakeup the User Break Controller (UBC) on - startup. Although the UBC is left in an awake state when the processor - comes up, some boot loaders misbehave by putting the UBC to sleep in a - power saving state, which causes issues with things like ptrace(). - - If unsure, say N. - -SuperH DMAC support -CONFIG_SH_DMA - Selecting this option will provide same API as PC's Direct Memory - Access Controller(8237A) for SuperH DMAC. - - If unsure, say N. - -# Choice: cf_area -CompactFlash Connection Area -CONFIG_CF_AREA5 - If your board has "Directly Connected" CompactFlash, You should - select the area where your CF is connected to. - - - "Area5" if CompactFlash is connected to Area 5 (0x14000000) - - "Area6" if it is connected to Area 6 (0x18000000) - - "Area6" will work for most boards. For ADX, select "Area5". - -Disable data cache -CONFIG_DCACHE_DISABLE - This option allows you to run the kernel with data cache disabled. - Say Y if you experience CPM lock-ups. - -# -# m68k-specific kernel options -# Documented by Chris Lawrence et al. -# -Amiga support -CONFIG_AMIGA - This option enables support for the Amiga series of computers. If - you plan to use this kernel on an Amiga, say Y here and browse the - material available in ; otherwise say N. - -Commodore A2232 serial support -CONFIG_A2232 - This option supports the 2232 7-port serial card shipped with the - Amiga 2000 and other Zorro-bus machines, dating from 1989. At - a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip - each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The - ports were connected with 8 pin DIN connectors on the card bracket, - for which 8 pin to DB25 adapters were supplied. The card also had - jumpers internally to toggle various pinning configurations. - - This driver can be built as a module; but then "generic_serial.o" - will also be built as a module. This has to be loaded before - "ser_a2232.o". If you want to do this, answer M here and read - "". - -Amiga NCR53c710 SCSI support -CONFIG_SCSI_AMIGA7XX - Support for various NCR53c710-based SCSI controllers on the Amiga. - This includes: - - the builtin SCSI controller on the Amiga 4000T, - - the Amiga 4091 Zorro III SCSI-2 controller, - - the MacroSystem Development's WarpEngine Amiga SCSI-2 controller - (info at - ), - - the SCSI controller on the Phase5 Blizzard PowerUP 603e+ - accelerator card for the Amiga 1200, - - the SCSI controller on the GVP Turbo 040/060 accelerator. - Note that all of the above SCSI controllers, except for the builtin - SCSI controller on the Amiga 4000T, reside on the Zorro expansion - bus, so you also have to enable Zorro bus support if you want to use - them. - -Atari support -CONFIG_ATARI - This option enables support for the 68000-based Atari series of - computers (including the TT, Falcon and Medusa). If you plan to use - this kernel on an Atari, say Y here and browse the material - available in ; otherwise say N. - -Hades support -CONFIG_HADES - This option enables support for the Hades Atari clone. If you plan - to use this kernel on a Hades, say Y here; otherwise say N. - -Macintosh support -CONFIG_MAC - This option enables support for the Apple Macintosh series of - computers (yes, there is experimental support now, at least for part - of the series). - - Say N unless you're willing to code the remaining necessary support. - ;) - -HP9000/300 support -CONFIG_HP300 - This option enables support for the HP9000/300 series of - workstations. Support for these machines is still very experimental. - If you plan to try to use the kernel on such a machine say Y here. - Everybody else says N. - -Q40/Q60 support -CONFIG_Q40 - The Q40 is a Motorola 68040-based successor to the Sinclair QL - manufactured in Germany. There is an official Q40 home page at - . This option enables support for the Q40 and - Q60. Select your CPU below. For 68LC060 don't forget to enable FPU - emulation. - -Q40/Q60 IDE interface support -CONFIG_BLK_DEV_Q40IDE - Enable the on-board IDE controller in the Q40/Q60. This should - normally be on; disable it only if you are running a custom hard - drive subsystem through an expansion card. - -Sun 3 support -CONFIG_SUN3 - This option enables support for the Sun 3 series of workstations. - Note that if this option is enabled, support for all other m68k - platforms above must be disabled in order to produce a working - kernel. - - Also, you will want to enable 68020 support below, and disable - all other CPU types. General Linux information on the Sun 3x series - (now discontinued) is at - . - - If you don't want to compile a kernel for a Sun 3, say N. - -Sun 3X support -CONFIG_SUN3X - This option enables support for the Sun 3x series of workstations. - Currently, only the Sun 3/80 is supported within the Sun 3x family. - You will also want to enable 68030 support below - General Linux information on the Sun 3x series (now discontinued) - is at . - - If you don't want to compile a kernel for a Sun 3x, say N. - -Sun3x builtin serial support -CONFIG_SUN3X_ZS - ZS refers to a type of asynchronous serial port built in to the Sun3 - and Sun3x workstations; if you have a Sun 3, you probably have - these. Say 'Y' to support ZS ports directly. This option must be - enabled in order to support the keyboard and mouse ports. - -Sun keyboard support -CONFIG_SUN_KEYBOARD - Say Y here to support the keyboard found on Sun 3 and 3x - workstations. It can also be used support Sun Type-5 keyboards - through an adaptor. See - and - for details on the - latter. - -68020 support -CONFIG_M68020 - If you anticipate running this kernel on a computer with a MC68020 - processor, say Y. Otherwise, say N. Note that the 68020 requires a - 68851 MMU (Memory Management Unit) to run Linux/m68k, except on the - Sun 3, which provides its own version. - -68030 support -CONFIG_M68030 - If you anticipate running this kernel on a computer with a MC68030 - processor, say Y. Otherwise, say N. Note that a MC68EC030 will not - work, as it does not include an MMU (Memory Management Unit). - -68040 support -CONFIG_M68040 - If you anticipate running this kernel on a computer with a MC68LC040 - or MC68040 processor, say Y. Otherwise, say N. Note that an - MC68EC040 will not work, as it does not include an MMU (Memory - Management Unit). - -68060 support -CONFIG_M68060 - If you anticipate running this kernel on a computer with a MC68060 - processor, say Y. Otherwise, say N. - -Math emulation support -CONFIG_M68KFPU_EMU - At some point in the future, this will cause floating-point math - instructions to be emulated by the kernel on machines that lack a - floating-point math coprocessor. Thrill-seekers and chronically - sleep-deprived psychotic hacker types can say Y now, everyone else - should probably wait a while. - -Math emulation only kernel -CONFIG_M68KFPU_EMU_ONLY - This option prevents any floating-point instructions from being - compiled into the kernel, thereby the kernel doesn't save any - floating point context anymore during task switches, so this - kernel will only be usable on machines without a floating-point - math coprocessor. This makes the kernel a bit faster as no tests - needs to be executed whether a floating-point instruction in the - kernel should be executed or not. - -Math emulation extra precision -CONFIG_M68KFPU_EMU_EXTRAPREC - The fpu uses normally a few bit more during calculations for - correct rounding, the emulator can (often) do the same but this - extra calculation can cost quite some time, so you can disable - it here. The emulator will then "only" calculate with a 64 bit - mantissa and round slightly incorrect, what is more then enough - for normal usage. - -Advanced configuration options -CONFIG_ADVANCED - This gives you access to some advanced options for the CPU. The - defaults should be fine for most users, but these options may make - it possible for you to improve performance somewhat if you know what - you are doing. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about these options. - - Most users should say N to this question. - -Use one physical chunk of memory only -CONFIG_SINGLE_MEMORY_CHUNK - Ignore all but the first contiguous chunk of physical memory for VM - purposes. This will save a few bytes kernel size and may speed up - some operations. Say N if not sure. - -Use read-modify-write instructions -CONFIG_RMW_INSNS - This allows to use certain instructions that work with indivisible - read-modify-write bus cycles. While this is faster than the - workaround of disabling interrupts, it can conflict with DMA - ( = direct memory access) on many Amiga systems, and it is also said - to destabilize other machines. It is very likely that this will - cause serious problems on any Amiga or Atari Medusa if set. The only - configuration where it should work are 68030-based Ataris, where it - apparently improves performance. But you've been warned! Unless you - really know what you are doing, say N. Try Y only if you're quite - adventurous. - -Amiga Zorro (AutoConfig) bus support -CONFIG_ZORRO - This enables support for the Zorro bus in the Amiga. If you have - expansion cards in your Amiga that conform to the Amiga - AutoConfig(tm) specification, say Y, otherwise N. Note that even - expansion cards that do not fit in the Zorro slots but fit in e.g. - the CPU slot may fall in this category, so you have to say Y to let - Linux use these. - -Zorro device name database -CONFIG_ZORRO_NAMES - By default, the kernel contains a database of all known Zorro device - names to make the information in /proc/iomem comprehensible to the - user. This database increases the size of the kernel image by about - 15KB, but it gets freed after the system boots up, so it doesn't - take up kernel memory. Anyway, if you are building an installation - floppy or kernel for an embedded system where kernel image size - really matters, you can disable this feature and you'll get device - ID numbers instead of names. - - When in doubt, say Y. - -Amiga 1200/600 PCMCIA support -CONFIG_AMIGA_PCMCIA - Include support in the kernel for pcmcia on Amiga 1200 and Amiga - 600. If you intend to use pcmcia cards say Y; otherwise say N. - -Hisoft Whippet PCMCIA serial support -CONFIG_WHIPPET_SERIAL - HiSoft has a web page at , but there - is no listing for the Whippet in their Amiga section. - -Amiga Zorro II ramdisk support -CONFIG_AMIGA_Z2RAM - This enables support for using Chip RAM and Zorro II RAM as a - ramdisk or as a swap partition. Say Y if you want to include this - driver in the kernel. This driver is also available as a module - ( = code which can be inserted in and removed from the running - kernel whenever you want). The module is called z2ram.o. If you want - to compile it as a module, say M here and read - . - -Support for ST-RAM as swap space -CONFIG_STRAM_SWAP - Some Atari 68k machines (including the 520STF and 1020STE) divide - their addressable memory into ST and TT sections. The TT section - (up to 512MB) is the main memory; the ST section (up to 4MB) is - accessible to the built-in graphics board, runs slower, and is - present mainly for backward compatibility with older machines. - - This enables support for using (parts of) ST-RAM as swap space, - instead of as normal system memory. This can first enhance system - performance if you have lots of alternate RAM (compared to the size - of ST-RAM), because executable code always will reside in faster - memory. ST-RAM will remain as ultra-fast swap space. On the other - hand, it allows much improved dynamic allocations of ST-RAM buffers - for device driver modules (e.g. floppy, ACSI, SLM printer, DMA - sound). The probability that such allocations at module load time - fail is drastically reduced. - -ST-RAM statistics in /proc -CONFIG_STRAM_PROC - Say Y here to report ST-RAM usage statistics in /proc/stram. See - the help for CONFIG_STRAM_SWAP for discussion of ST-RAM and its - uses. - -Atari ACSI support -CONFIG_ATARI_ACSI - This enables support for the Atari ACSI interface. The driver - supports hard disks and CD-ROMs, which have 512-byte sectors, or can - be switched to that mode. Due to the ACSI command format, only disks - up to 1 GB are supported. Special support for certain ACSI to SCSI - adapters, which could relax that, isn't included yet. The ACSI - driver is also the basis for certain other drivers for devices - attached to the ACSI bus: Atari SLM laser printer, BioNet-100 - Ethernet, and PAMsNet Ethernet. If you want to use one of these - devices, you need ACSI support, too. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called acsi.o. - -Probe all LUNs on each ACSI device -CONFIG_ACSI_MULTI_LUN - If you have a ACSI device that supports more than one LUN (Logical - Unit Number), e.g. a CD jukebox, you should say Y here so that all - will be found by the ACSI driver. An ACSI device with multiple LUNs - acts logically like multiple ACSI devices. The vast majority of ACSI - devices have only one LUN, and so most people can say N here and - should in fact do so, because it is safer. - -Atari SLM laser printer support -CONFIG_ATARI_SLM - If you have an Atari SLM laser printer, say Y to include support for - it in the kernel. Otherwise, say N. This driver is also available as - a module ( = code which can be inserted in and removed from the - running kernel whenever you want). The module will be called - acsi_slm.o. Be warned: the driver needs much ST-RAM and can cause - problems due to that fact! - -A3000 WD33C93A support -CONFIG_A3000_SCSI - If you have an Amiga 3000 and have SCSI devices connected to the - built-in SCSI controller, say Y. Otherwise, say N. This driver is - also available as a module ( = code which can be inserted in and - removed from the running kernel whenever you want). The module is - called wd33c93.o. If you want to compile it as a module, say M here - and read . - -A2091 WD33C93A support -CONFIG_A2091_SCSI - If you have a Commodore A2091 SCSI controller, say Y. Otherwise, - say N. This driver is also available as a module ( = code which can - be inserted in and removed from the running kernel whenever you - want). The module is called wd33c93.o. If you want to compile it as - a module, say M here and read . - -GVP Series II WD33C93A support -CONFIG_GVP11_SCSI - If you have a Great Valley Products Series II SCSI controller, - answer Y. Also say Y if you have a later model of GVP SCSI - controller (such as the GVP A4008 or a Combo board). Otherwise, - answer N. This driver does NOT work for the T-Rex series of - accelerators from TekMagic and GVP-M. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you - want). The module will be called gvp11.o. If you want to compile it - as a module, say M here and read . - -CyberStorm SCSI support -CONFIG_CYBERSTORM_SCSI - If you have an Amiga with an original (MkI) Phase5 Cyberstorm - accelerator board and the optional Cyberstorm SCSI controller, - answer Y. Otherwise, say N. - -CyberStorm II SCSI support -CONFIG_CYBERSTORMII_SCSI - If you have an Amiga with a Phase5 Cyberstorm MkII accelerator board - and the optional Cyberstorm SCSI controller, say Y. Otherwise, - answer N. - -Blizzard 2060 SCSI support -CONFIG_BLZ2060_SCSI - If you have an Amiga with a Phase5 Blizzard 2060 accelerator board - and want to use the onboard SCSI controller, say Y. Otherwise, - answer N. - -Blizzard 1230IV/1260 SCSI support -CONFIG_BLZ1230_SCSI - If you have an Amiga 1200 with a Phase5 Blizzard 1230IV or Blizzard - 1260 accelerator, and the optional SCSI module, say Y. Otherwise, - say N. - -Fastlane SCSI support -CONFIG_FASTLANE_SCSI - If you have the Phase5 Fastlane Z3 SCSI controller, or plan to use - one in the near future, say Y to this question. Otherwise, say N. - -BSC Oktagon SCSI support -CONFIG_OKTAGON_SCSI - If you have the BSC Oktagon SCSI disk controller for the Amiga, say - Y to this question. If you're in doubt about whether you have one, - see the picture at - . - -Atari native SCSI support -CONFIG_ATARI_SCSI - If you have an Atari with built-in NCR5380 SCSI controller (TT, - Falcon, ...) say Y to get it supported. Of course also, if you have - a compatible SCSI controller (e.g. for Medusa). This driver is also - available as a module ( = code which can be inserted in and removed - from the running kernel whenever you want). The module is called - atari_scsi.o. If you want to compile it as a module, say M here and - read . This driver supports both - styles of NCR integration into the system: the TT style (separate - DMA), and the Falcon style (via ST-DMA, replacing ACSI). It does - NOT support other schemes, like in the Hades (without DMA). - -Long delays for Toshiba CD-ROMs -CONFIG_ATARI_SCSI_TOSHIBA_DELAY - This option increases the delay after a SCSI arbitration to - accommodate some flaky Toshiba CD-ROM drives. Say Y if you intend to - use a Toshiba CD-ROM drive; otherwise, the option is not needed and - would impact performance a bit, so say N. - -Reset SCSI-devices at boottime -CONFIG_ATARI_SCSI_RESET_BOOT - Reset the devices on your Atari whenever it boots. This makes the - boot process fractionally longer but may assist recovery from errors - that leave the devices with SCSI operations partway completed. - -Hades SCSI DMA emulator -CONFIG_TT_DMA_EMUL - This option enables code which emulates the TT SCSI DMA chip on the - Hades. This increases the SCSI transfer rates at least ten times - compared to PIO transfers. - -Sun3x ESP SCSI -CONFIG_SUN3X_ESP - This option will enable support for the ESP SCSI controller found - onboard the Sun 3/80. - -Ariadne support -CONFIG_ARIADNE - If you have a Village Tronic Ariadne Ethernet adapter, say Y. - Otherwise, say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you - want). The module is called ariadne.o. If you want to compile it as - a module, say M here and read . - -Zorro NS8390-based Ethernet support -CONFIG_ZORRO8390 - This driver is for Zorro Ethernet cards using an NS8390-compatible - chipset, like the Village Tronic Ariadne II and the Individual - Computers X-Surf Ethernet cards. If you have such a card, say Y. - Otherwise, say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called zorro8390.o. If you want to compile it as - a module, say M here and read . - -A2065 support -CONFIG_A2065 - If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise, - say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you - want). The module is called a2065.o. If you want to compile it as a - module, say M here and read . - -Hydra support -CONFIG_HYDRA - If you have a Hydra Ethernet adapter, say Y. Otherwise, say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you - want). The module is called hydra.o. If you want to compile it as a - module, say M here and read . - -Sun3 NCR5380 SCSI -CONFIG_SUN3_SCSI - This option will enable support for the OBIO (onboard io) NCR5380 - SCSI controller found in the Sun 3/50 and 3/60, as well as for - "Sun3" type VME scsi controllers also based on the NCR5380. - General Linux information on the Sun 3 series (now discontinued) - is at . - -PCMCIA NE2000 and compatibles support -CONFIG_APNE - If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise, - say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you - want). The module is called apne.o. If you want to compile it as a - module, say M here and read . - -Atari Lance support -CONFIG_ATARILANCE - Say Y to include support for several Atari Ethernet adapters based - on the AMD Lance chipset: RieblCard (with or without battery), or - PAMCard VME (also the version by Rhotron, with different addresses). - -BioNet-100 support -CONFIG_ATARI_BIONET - Say Y to include support for BioData's BioNet-100 Ethernet adapter - for the ACSI port. The driver works (has to work...) with a polled - I/O scheme, so it's rather slow :-( - -PAMsNet support -CONFIG_ATARI_PAMSNET - Say Y to include support for the PAMsNet Ethernet adapter for the - ACSI port ("ACSI node"). The driver works (has to work...) with a - polled I/O scheme, so it's rather slow :-( - -Amiga mouse support -CONFIG_AMIGAMOUSE - If you want to be able to use an Amiga mouse in Linux, say Y. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called amigamouse.o. If you want to compile it as a - module, say M here and read . - -Atari mouse support -CONFIG_ATARIMOUSE - If you want to be able to use an Atari mouse in Linux, say Y. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called atarimouse.o. If you want to compile it as a - module, say M here and read . - -Atari MFP serial support -CONFIG_ATARI_MFPSER - If you like to use the MFP serial ports ("Modem1", "Serial1") under - Linux, say Y. The driver equally supports all kinds of MFP serial - ports and automatically detects whether Serial1 is available. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . - - Note for Falcon users: You also have an MFP port, it's just not - wired to the outside... But you could use the port under Linux. - -Atari SCC serial support -CONFIG_ATARI_SCC - If you have serial ports based on a Zilog SCC chip (Modem2, Serial2, - LAN) and like to use them under Linux, say Y. All built-in SCC's are - supported (TT, MegaSTE, Falcon), and also the ST-ESCC. If you have - two connectors for channel A (Serial2 and LAN), they are visible as - two separate devices. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . - -Atari SCC serial DMA support -CONFIG_ATARI_SCC_DMA - This enables DMA support for receiving data on channel A of the SCC. - If you have a TT you may say Y here and read - drivers/char/atari_SCC.README. All other users should say N here, - because only the TT has SCC-DMA, even if your machine keeps claiming - so at boot time. - -Atari MIDI serial support -CONFIG_ATARI_MIDI - If you want to use your Atari's MIDI port in Linux, say Y. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you - want). If you want to compile it as a module, say M here and read - . - -Atari DSP56k Digital Signal Processor support -CONFIG_ATARI_DSP56K - If you want to be able to use the DSP56001 in Falcons, say Y. This - driver is still experimental, and if you don't know what it is, or - if you don't have this processor, just say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . - -Support for early boot text console -CONFIG_BOOTX_TEXT - Say Y here to see progress messages from the boot firmware in text - mode. Requires either BootX or Open Firmware. - -Amiga builtin serial support -CONFIG_AMIGA_BUILTIN_SERIAL - If you want to use your Amiga's built-in serial port in Linux, - answer Y. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you - want). If you want to compile it as a module, say M here and read - . - -GVP IO-Extender support -CONFIG_GVPIOEXT - If you want to use a GVP IO-Extender serial card in Linux, say Y. - Otherwise, say N. - -GVP IO-Extender parallel printer support -CONFIG_GVPIOEXT_LP - Say Y to enable driving a printer from the parallel port on your - GVP IO-Extender card, N otherwise. - -GVP IO-Extender PLIP support -CONFIG_GVPIOEXT_PLIP - Say Y to enable doing IP over the parallel port on your GVP - IO-Extender card, N otherwise. - -Multiface Card III serial support -CONFIG_MULTIFACE_III_TTY - If you want to use a Multiface III card's serial port in Linux, - answer Y. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . - -Amiga/Atari/PowerMac DMA sound support -CONFIG_DMASOUND - Support built-in audio chips accessible by DMA on various machines - that have them. Note that this symbol does not affect the kernel - directly; rather, it controls whether configuration questions - enabling DMA sound drivers for various specific machine - architectures will be used. - -Atari DMA sound support -CONFIG_DMASOUND_ATARI - If you want to use the internal audio of your Atari in Linux, answer - Y to this question. This will provide a Sun-like /dev/audio, - compatible with the Linux/i386 sound system. Otherwise, say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you - want). If you want to compile it as a module, say M here and read - . - -PowerMac DMA sound support -CONFIG_DMASOUND_PMAC - If you want to use the internal audio of your PowerMac in Linux, - answer Y to this question. This will provide a Sun-like /dev/audio, - compatible with the Linux/i386 sound system. Otherwise, say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you - want). If you want to compile it as a module, say M here and read - . - -Amiga DMA sound support -CONFIG_DMASOUND_PAULA - If you want to use the internal audio of your Amiga in Linux, answer - Y to this question. This will provide a Sun-like /dev/audio, - compatible with the Linux/i386 sound system. Otherwise, say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you - want). If you want to compile it as a module, say M here and read - . - -Q40 sound support -CONFIG_DMASOUND_Q40 - If you want to use the internal audio of your Q40 in Linux, answer - Y to this question. This will provide a Sun-like /dev/audio, - compatible with the Linux/i386 sound system. Otherwise, say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you - want). If you want to compile it as a module, say M here and read - . - -HP DCA serial support -CONFIG_HPDCA - If you want to use the internal "DCA" serial ports on an HP300 - machine, say Y here. - -HP on-board LANCE support -CONFIG_HPLANCE - If you want to use the builtin "LANCE" Ethernet controller on an - HP300 machine, say Y here. - -DIO bus support -CONFIG_DIO - Say Y here to enable support for the "DIO" expansion bus used in - HP300 machines. If you are using such a system you almost certainly - want this. - -# Choice: ppctype -Processor Type -CONFIG_6xx - There are four types of PowerPC chips supported. The more common - types (601, 603, 604, 740, 750, 7400), the Motorola embedded - versions (821, 823, 850, 855, 860, 8260), the IBM embedded versions - (403 and 405) and the high end 64 bit Power processors (Power 3, - Power 4). Unless you are building a kernel for one of the embedded - processor systems, or a 64 bit IBM RS/6000, choose 6xx. Note that - the kernel runs in 32-bit mode even on 64-bit chips. Also note that - because the 82xx family has a 603e core, specific support for that - chipset is asked later on. - -Motorola MPC8260 CPM support -CONFIG_8260 - The MPC8260 CPM (Communications Processor Module) is a typical - embedded CPU made by Motorola. Selecting this option means that - you wish to build a kernel for a machine with specifically an 8260 - for a CPU. - - If in doubt, say N. - -# Choice: ppc4xxtype -Oak -CONFIG_OAK - Select Oak if you have an IBM 403GCX "Oak" Evaluation Board. - - Select Walnut if you have an IBM 405GP "Walnut" Evaluation Board. - - More information on these boards is available at: - . - -Walnut -CONFIG_WALNUT - Select Walnut if you have an IBM 405GP "Walnut" Evaluation Board. - -Workarounds for PPC601 bugs -CONFIG_PPC601_SYNC_FIX - Some versions of the PPC601 (the first PowerPC chip) have bugs which - mean that extra synchronization instructions are required near - certain instructions, typically those that make major changes to the - CPU state. These extra instructions reduce performance slightly. - If you say N here, these extra instructions will not be included, - resulting in a kernel which will run faster but may not run at all - on some systems with the PPC601 chip. - - If in doubt, say Y here. - -8xx Cache (Copy-Back or Writethrough) -CONFIG_8xx_COPYBACK - Saying Y here will cause the cache on an MPC8xx processor to be used - in Copy-Back mode. If you say N here, it is used in Writethrough - mode. - - If in doubt, say Y here. - -MPC860 (Pre Rev. C) CPU6 Silicon Errata -CONFIG_8xx_CPU6 - MPC860 CPUs, prior to Rev C have some bugs in the silicon, which - require workarounds for Linux (and most other OSes to work). If you - get a BUG() very early in boot, this might fix the problem. For - more details read the document entitled "MPC860 Family Device Errata - Reference" on Motorola's website. This option also incurs a - performance hit. - - If in doubt, say N here. - -MPC8xx direct IDE support on PCMCIA port -CONFIG_BLK_DEV_MPC8xx_IDE - This option provides support for IDE on Motorola MPC8xx Systems. - Please see 'Type of MPC8xx IDE interface' for details. - - If unsure, say N. - -# Choice: mpc8xxtype -Type of MPC8xx IDE interface -CONFIG_IDE_8xx_PCCARD - Select how the IDE devices are connected to the MPC8xx system: - - 8xx_PCCARD uses the 8xx internal PCMCIA interface in combination - with a PC Card (e.g. ARGOSY portable Hard Disk Adapter), - ATA PC Card HDDs or ATA PC Flash Cards (example: TQM8xxL - systems) - - 8xx_DIRECT is used for directly connected IDE devices using the 8xx - internal PCMCIA interface (example: IVMS8 systems) - - EXT_DIRECT is used for IDE devices directly connected to the 8xx - bus using some glue logic, but _not_ the 8xx internal - PCMCIA interface (example: IDIF860 systems) - -Use SMC2 for UART -CONFIG_8xx_SMC2 - If you would like to use SMC2 as a serial port, say Y here. - - If in doubt, say Y here. - -Use SMC2 for Console -CONFIG_CONS_SMC2 - If you are going to have a serial console on your device and are - using SMC2 for your serial port, say Y here, else say N. - -Use the alternate SMC2 I/O -CONFIG_ALTSMC2 - If you have an MPC823 or MPC850 and would like to use the alternate - SMC2 for I/O, say Y here. - - If in doubt, say N here. - -Enable SCC2 and SCC3 for UART -CONFIG_USE_SCC_IO - If your MPC8xx board has other SCC ports that you would like to use - for for a serial port, say Y here. - - If in doubt, say N here. - -# Choice: ppc6xxtype -Machine Type -CONFIG_ALL_PPC - Linux currently supports several different kinds of PowerPC-based - machines: Apple Power Macintoshes and clones (such as the Motorola - Starmax series), PReP (PowerPC Reference Platform) machines (such - as the Motorola PowerStacks, Motorola cPCI/VME embedded systems, - and some IBM RS/6000 systems), CHRP (Common Hardware Reference - Platform), and several embedded PowerPC systems containing 4xx, 6xx, - 7xx, 8xx, 74xx, and 82xx processors. Currently, the default option - is to build a kernel which works on the first three. - - Select PowerMac/PReP/MTX/CHRP if configuring for any of the above. - - Select Gemini if configuring for a Synergy Microsystems' Gemini - series Single Board Computer. More information is available at: - . - - Select APUS if configuring for a PowerUP Amiga. More information is - available at: . - - Note that Total Impact briQ is handled as a CHRP machine. - -Synergy-Gemini -CONFIG_GEMINI - Select Gemini if configuring for a Synergy Microsystems' Gemini - series Single Board Computer. More information is available at: - . - -Amiga-Apus -CONFIG_APUS - Select APUS if configuring for a PowerUP Amiga. - More information is available at: - . - -AltiVec kernel support -CONFIG_ALTIVEC - This option enables kernel support for the Altivec extensions to the - PowerPC processor. The kernel currently supports saving and restoring - altivec registers, and turning on the 'altivec enable' bit so user - processes can execute altivec instructions. - - This option is only usefully if you have a processor that supports - altivec (G4, otherwise known as 74xx series), but does not have - any affect on a non-altivec cpu (it does, however add code to the - kernel). - - If in doubt, say Y here. - -Thermal Management Support -CONFIG_TAU - G3 and G4 processors have an on-chip temperature sensor called the - 'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die - temperature within 2-4 degrees Celsius. This option shows the current - on-die temperature in /proc/cpuinfo if the cpu supports it. - - Unfortunately, on some chip revisions, this sensor is very inaccurate - and in some cases, does not work at all, so don't assume the cpu - temp is actually what /proc/cpuinfo says it is. - -Interrupt driven TAU driver -CONFIG_TAU_INT - The TAU supports an interrupt driven mode which causes an interrupt - whenever the temperature goes out of range. This is the fastest way - to get notified the temp has exceeded a range. With this option off, - a timer is used to re-check the temperature periodically. - - However, on some cpus it appears that the TAU interrupt hardware - is buggy and can cause a situation which would lead unexplained hard - lockups. - - Unless you are extending the TAU driver, or enjoy kernel/hardware - debugging, leave this option off. - -Average high and low temp -CONFIG_TAU_AVERAGE - The TAU hardware can compare the temperature to an upper and lower bound. - The default behaviour is to show both the upper and lower bound in - /proc/cpuinfo. If the range is large, the temperature is either changing - a lot, or the TAU hardware is broken (likely on some G4's). If the range - is small (around 4 degrees), the temperature is relatively stable. - -Power management support for PowerBooks -CONFIG_PMAC_PBOOK - This provides support for putting a PowerBook to sleep; it also - enables media bay support. Power management works on the - PB2400/3400/3500, Wallstreet, Lombard, and Bronze PowerBook G3. You - must get the power management daemon, pmud, to make it work and you - must have the /dev/pmu device (see the pmud README). - - Get pmud from . - - If you have a PowerBook, you should say Y. - - You may also want to compile the dma sound driver as a module and - have it autoloaded. The act of removing the module shuts down the - sound hardware for more power savings. - -APM emulation -CONFIG_PMAC_APM_EMU - This driver provides an emulated /dev/apm_bios and /proc/apm. The - first one is mostly intended for XFree to sleep & wakeup properly, - the second ones provides some battery informations to allow existing - APM utilities to work. It provides less useful informations than - tools specifically designed for PowerBooks or /proc/pmu/battery_x - -Backlight control for LCD screens -CONFIG_PMAC_BACKLIGHT - Say Y here to build in code to manage the LCD backlight on a - Macintosh PowerBook. With this code, the backlight will be turned - on and off appropriately on power-management and lid-open/lid-closed - events; also, the PowerBook button device will be enabled so you can - change the screen brightness. - -# Choice: ppc8xxtype -Embedded 8xx Board Type -CONFIG_RPXLITE - Single-board computers based around the PowerPC MPC8xx chips and - intended for embedded applications. The following types are - supported: - - RPX-Lite: - Embedded Planet RPX Lite. PC104 form-factor SBC based on the MPC823. - - RPX-Classic: - Embedded Planet RPX Classic Low-fat. Credit-card-size SBC based on - the MPC 860 - - BSE-IP: - Bright Star Engineering ip-Engine. - - TQM823L: - TQM850L: - TQM855L: - TQM860L: - MPC8xx based family of mini modules, half credit card size, - up to 64 MB of RAM, 8 MB Flash, (Fast) Ethernet, 2 x serial ports, - 2 x CAN bus interface, ... - Manufacturer: TQ Components, www.tq-group.de - Date of Release: October (?) 1999 - End of Life: not yet :-) - URL: - - module: - - starter kit: - - images: - - FPS850L: - FingerPrint Sensor System (based on TQM850L) - Manufacturer: IKENDI AG, - Date of Release: November 1999 - End of life: end 2000 ? - URL: see TQM850L - - SPD823TS: - MPC823 based board used in the "Tele Server" product - Manufacturer: Speech Design, - Date of Release: Mid 2000 (?) - End of life: - - URL: - select "English", then "Teleteam Solutions", then "TeleServer" - - IVMS8: - MPC860 based board used in the "Integrated Voice Mail System", - Small Version (8 voice channels) - Manufacturer: Speech Design, - Date of Release: December 2000 (?) - End of life: - - URL: - - IVML24: - MPC860 based board used in the "Integrated Voice Mail System", - Large Version (24 voice channels) - Manufacturer: Speech Design, - Date of Release: March 2001 (?) - End of life: - - URL: - - SM850: - Service Module (based on TQM850L) - Manufacturer: Dependable Computer Systems, - Date of Release: end 2000 (?) - End of life: mid 2001 (?) - URL: - - HERMES_PRO: - Hermes-Pro ISDN/LAN router with integrated 8 x hub - Manufacturer: Multidata Gesellschaft für Datentechnik und Informatik - - Date of Release: 2000 (?) - End of life: - - URL: - - IP860: - VMEBus IP (Industry Pack) carrier board with MPC860 - Manufacturer: MicroSys GmbH, - Date of Release: ? - End of life: - - URL: - - PCU_E: - PCU = Peripheral Controller Unit, Extended - Manufacturer: Siemens AG, ICN (Information and Communication Networks) - - Date of Release: April 2001 - End of life: August 2001 - URL: n. a. - -RPX-Classic -CONFIG_RPXCLASSIC - The RPX-Classic is a single-board computer based on the Motorola - MPC860. It features 16MB of DRAM and a variable amount of flash, - I2C EEPROM, thermal monitoring, a PCMCIA slot, a DIP switch and two - LEDs. Variants with Ethernet ports exist. Say Y here to support it - directly. - -BSE-IP -CONFIG_BSEIP - Say Y here to support the Bright Star Engineering ipEngine SBC. - This is a credit-card-sized device featuring a MPC823 processor, - 26MB DRAM, 4MB flash, Ethernet, a 16K-gate FPGA, USB, an LCD/video - controller, and two RS232 ports. - -TQM823L -CONFIG_TQM823L - Say Y here to support the TQM823L, one of an MPC8xx-based family of - mini SBCs (half credit-card size) from TQ Components first released - in late 1999. Technical references are at - , and - , and an image at - . - -TQM850L -CONFIG_TQM850L - Say Y here to support the TQM850L, one of an MPC8xx-based family of - mini SBCs (half credit-card size) from TQ Components first released - in late 1999. Technical references are at - , and - , and an image at - . - -TQM855L -CONFIG_TQM855L - Say Y here to support the TQM855L, one of an MPC8xx-based family of - mini SBCs (half credit-card size) from TQ Components first released - in late 1999. Technical references are at - , and - , and an image at - . - -TQM860L -CONFIG_TQM860L - Say Y here to support the TQM860L, one of an MPC8xx-based family of - mini SBCs (half credit-card size) from TQ Components first released - in late 1999. Technical references are at - , and - , and an image at - . - -FPS850 -CONFIG_FPS850 - Say Y here to support the FingerPrint Sensor from AKENDI IG, based - on the TQ Components TQM850L module, released November 1999 and - discontinued a year later. - -TQM860 -CONFIG_TQM860 - Say Y here to support the TQM860, one of an MPC8xx-based family of - SBCs (credit-card size) from TQ Components first released in - mid-1999 and discontinued mid-2000. - -SM850 -CONFIG_SM850 - Say Y here to support the Service Module 850 from Dependable - Computer Systems, an SBC based on the TQM850L module by TQ - Components. This board is no longer in production. The - manufacturer's website is at . - -SPD823TS -CONFIG_SPD823TS - Say Y here to support the Speech Design 823 Tele-Server from Speech - Design, released in 2000. The manufacturer's website is at - . - -IVMS8 -CONFIG_IVMS8 - Say Y here to support the Integrated Voice-Mail Small 8-channel SBC - from Speech Design, released March 2001. The manufacturer's website - is at . - -# IVML24 is not yet active -IVML24 -CONFIG_IVML24 - Say Y here to support the Integrated Voice-Mail Large 24-channel SBC - from Speech Design, released March 2001. The manufacturer's website - is at . - -MBX -CONFIG_MBX - MBX is a line of Motorola single-board computer based around the - MPC821 and MPC860 processors, and intended for embedded-controller - applications. Say Y here to support these boards directly. - -WinCept -CONFIG_WINCEPT - The Wincept 100/110 is a Motorola single-board computer based on the - MPC821 PowerPC, introduced in 1998 and designed to be used in - thin-client machines. Say Y to support it directly. - -# More systems that will be supported soon, according to -# Wolfgang Denk : -# -# TQM8260: -# MPC8260 based module -# -# Manufacturer: TQ Components, www.tq-group.de -# Date of Release: June 2001 -# End of Life: not yet :-) -# URL: -# -# IP860: -# VMEBus IP (Industry Pack) carrier board with MPC860 -# -# Manufacturer: MicroSys GmbH, -# Date of Release: ? -# End of life: - -# URL: -# -# CU824: -# VMEBus Board with PCI extension with MPC8240 CPU -# -# Manufacturer: MicroSys GmbH, -# Date of Release: early 2001 (?) -# End of life: - -# URL: -# -# PM826: -# Modular system with MPC8260 CPU -# -# Manufacturer: MicroSys GmbH, -# Date of Release: mid 2001 -# End of life: - -# URL: -# -# PCU_E: -# PCU = Peripheral Controller Unit; E = extended (?) -# -# Mfr: Siemens AG, ICN (Information and Communication Networks) -# -# Date of Release: April 2001 -# End of life: - -# URL: n. a.o - -# Choice: ppc82xxtype -Embedded 82xx Board Type -CONFIG_EST8260 - EST8260: - The EST8260 is a single-board computer manufactured by Wind River - Systems, Inc. (formerly Embedded Support Tools Corp.) and based on - the MPC8260. Wind River Systems has a website at - , but the EST8260 cannot be found on it - and has probably been discontinued or rebadged. - - TQM8260: - MPC8260 based module, little larger than credit card, - up to 128 MB global + 64 MB local RAM, 32 MB Flash, - 32 kB EEPROM, 256 kB L@ Cache, 10baseT + 100baseT Ethernet, - 2 x serial ports, ... - Manufacturer: TQ Components, www.tq-group.de - Date of Release: June 2001 - End of Life: not yet :-) - URL: - - PM826: - Modular system with MPC8260 CPU - Manufacturer: MicroSys GmbH, - Date of Release: mid 2001 - End of life: - - URL: - - CU824: - VMEBus Board with PCI extension with MPC8240 CPU - Manufacturer: MicroSys GmbH, - Date of Release: early 2001 (?) - End of life: - - URL: - -ADB raw keycode support -CONFIG_MAC_ADBKEYCODES - This provides support for sending raw ADB keycodes to console - devices. This is the default up to 2.4.0, but in future this may be - phased out in favor of generic Linux keycodes. If you say Y here, - you can dynamically switch via the - /proc/sys/dev/mac_hid/keyboard_sends_linux_keycodes - sysctl and with the "keyboard_sends_linux_keycodes=" kernel - argument. - - This option is now deprecated and will be removed in a future - kernel release. - - If unsure, say N here. - -I2C/SPI Microcode Patch -CONFIG_UCODE_PATCH - Motorola releases microcode updates for their 8xx CPM modules. The - microcode update file has updates for IIC, SMC and USB. Currently only - the USB update is available by default, if the MPC8xx USB option is - enabled. If in doubt, say 'N' here. - -Mouse button 2+3 emulation support -CONFIG_MAC_EMUMOUSEBTN - This provides generic support for emulating the 2nd and 3rd mouse - button with keypresses. If you say Y here, the emulation is still - disabled by default. The emulation is controlled by these sysctl - entries: - /proc/sys/dev/mac_hid/mouse_button_emulation - /proc/sys/dev/mac_hid/mouse_button2_keycode - /proc/sys/dev/mac_hid/mouse_button3_keycode - -Set high memory pool address -CONFIG_HIGHMEM_START_BOOL - Unless you know what you are doing you *should not* set this option. - - It can be used to override the default PKMAP_BASE address which - is the location of the high memory pool. This can be useful in - optimizing virtual memory usage in a system. - -Set maximum low memory -CONFIG_LOWMEM_SIZE_BOOL - Unless you know what you are doing you *should not* set this option. - - It can be used to override the standard calculated value of - MAX_LOW_MEM. This can be useful in optimizing virtual memory usage - in a system. - -Set custom kernel base address -CONFIG_KERNEL_START_BOOL - Unless you know what you are doing you *should not* set this option. - - It can be used to override the standard PAGE_OFFSET/KERNELBASE - value used by the kernel. This can be useful in controlling - amount of virtual address space available to the kernel. - -Set custom user task size -CONFIG_TASK_SIZE_BOOL - Unless you know what you are doing you *should not* set this option. - - It can be used to override the standard TASK_SIZE value used - by the kernel. This can be useful in controlling amount of - virtual address space available to user tasks. - -Enhanced Real Time Clock Support (/dev/rtc) -CONFIG_PPC_RTC - If you say Y here and create a character special file /dev/rtc with - major number 10 and minor number 135 using mknod ("man mknod"), you - will get access to the real time clock (or hardware clock) built - into your computer. - - If unsure, say Y here. - -Support for Open Firmware device tree in /proc -CONFIG_PROC_DEVICETREE - This option adds a device-tree directory under /proc which contains - an image of the device tree that the kernel copies from Open - Firmware. If unsure, say Y here. - -RTAS (RunTime Abstraction Services) in /proc -CONFIG_PPC_RTAS - When you use this option, you will be able to use RTAS from - userspace. - - RTAS stands for RunTime Abstraction Services and should - provide a portable way to access and set system information. This is - commonly used on RS/6000 (pSeries) computers. - - You can access RTAS via the special proc file system entry rtas. - Don't confuse this rtas entry with the one in /proc/device-tree/rtas - which is readonly. - - If you don't know if you can use RTAS look into - /proc/device-tree/rtas. If there are some entries, it is very likely - that you will be able to use RTAS. - - You can do cool things with rtas. To print out information about - various sensors in the system, just do a - - $ cat /proc/rtas/sensors - - or if you power off your machine at night but want it running when - you enter your office at 7:45 am, do a - - # date -d 'tomorrow 7:30' +%s > /proc/rtas/poweron - - and shutdown. - - If unsure, say Y. - -Support for Lpar Configuration data in /proc -CONFIG_LPARCFG - This option adds lparcfg entry as /proc/ppc64/lparcfg which returns - system configuration info in = pairs. - -MESH (Power Mac internal SCSI) support -CONFIG_SCSI_MESH - Many Power Macintoshes and clones have a MESH (Macintosh Enhanced - SCSI Hardware) SCSI bus adaptor (the 7200 doesn't, but all of the - other Power Macintoshes do). Say Y to include support for this SCSI - adaptor. This driver is also available as a module called mesh.o - ( = code which can be inserted in and removed from the running - kernel whenever you want). If you want to compile it as a module, - say M here and read . - -Maximum synchronous transfer rate (MB/s) (0 = async) -CONFIG_SCSI_MESH_SYNC_RATE - On Power Macintoshes (and clones) where the MESH SCSI bus adaptor - drives a bus which is entirely internal to the machine (such as the - 7500, 7600, 8500, etc.), the MESH is capable of synchronous - operation at up to 10 MB/s. On machines where the SCSI bus - controlled by the MESH can have external devices connected, it is - usually rated at 5 MB/s. 5 is a safe value here unless you know the - MESH SCSI bus is internal only; in that case you can say 10. Say 0 - to disable synchronous operation. - -53C94 (Power Mac external SCSI) support -CONFIG_SCSI_MAC53C94 - On Power Macintoshes (and clones) with two SCSI buses, the external - SCSI bus is usually controlled by a 53C94 SCSI bus adaptor. Older - machines which only have one SCSI bus, such as the 7200, also use - the 53C94. Say Y to include support for the 53C94. - - This driver is also available as a module called mac53c94.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -MACE (Power Mac Ethernet) support -CONFIG_MACE - Power Macintoshes and clones with Ethernet built-in on the - motherboard will usually use a MACE (Medium Access Control for - Ethernet) interface. Say Y to include support for the MACE chip. - - This driver is also available as a module called mace.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Use AAUI port instead of TP by default -CONFIG_MACE_AAUI_PORT - Some Apple machines (notably the Apple Network Server) which use the - MACE ethernet chip have an Apple AUI port (small 15-pin connector), - instead of an 8-pin RJ45 connector for twisted-pair ethernet. Say - Y here if you have such a machine. If unsure, say N. - The driver will default to AAUI on ANS anyway, and if you use it as - a module, you can provide the port_aaui=0|1 to force the driver. - -BMAC (G3 Ethernet) support -CONFIG_BMAC - Say Y for support of BMAC Ethernet interfaces. These are used on G3 - computers. - - This driver is also available as a module called bmac.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -GMAC (G4/iBook Ethernet) support -CONFIG_GMAC - Say Y for support of GMAC Ethernet interfaces. These are used on G4 - and iBook computers. - - This driver is also available as a module called gmac.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -National DP83902AV (Oak Ethernet) support -CONFIG_OAKNET - Say Y if your machine has this type of Ethernet network card. - - This driver is also available as a module called oaknet.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Video For Linux -CONFIG_VIDEO_DEV - Support for audio/video capture and overlay devices and FM radio - cards. The exact capabilities of each device vary. User tools for - this are available from - . - - If you are interested in writing a driver for such an audio/video - device or user software interacting with such a driver, please read - the file . - - This driver is also available as a module called videodev.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Video For Linux /proc file system information -CONFIG_VIDEO_PROC_FS - If you say Y here, you are able to access video device information - in /proc/video. - - To use this option, you have to check, that the "/proc file system - support" (CONFIG_PROC_FS) is enabled too. - -AIMSlab RadioTrack (aka RadioReveal) support -CONFIG_RADIO_RTRACK - Choose Y here if you have one of these FM radio cards, and then fill - in the port address below. - - Note that newer AIMSlab RadioTrack cards have a different chipset - and are not supported by this driver. For these cards, use the - RadioTrack II driver below. - - If you have a GemTeks combined (PnP) sound- and radio card you must - use this driver as a module and setup the card with isapnptools. - You must also pass the module a suitable io parameter, 0x248 has - been reported to be used by these cards. - - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux API. Information on - this API and pointers to "v4l" programs may be found on the WWW at - . More - information is contained in the file - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called radio-aimslab.o. - -RadioTrack I/O port -CONFIG_RADIO_RTRACK_PORT - Enter either 0x30f or 0x20f here. The card default is 0x30f, if you - haven't changed the jumper setting on the card. - -AIMSlab RadioTrack II support -CONFIG_RADIO_RTRACK2 - Choose Y here if you have this FM radio card, and then fill in the - port address below. - - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux API. Information on - this API and pointers to "v4l" programs may be found on the WWW at - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called radio-rtrack2.o. - -RadioTrack II I/O port -CONFIG_RADIO_RTRACK2_PORT - Enter either 0x30c or 0x20c here. The card default is 0x30c, if you - haven't changed the jumper setting on the card. - -Aztech/Packard Bell Radio -CONFIG_RADIO_AZTECH - Choose Y here if you have one of these FM radio cards, and then fill - in the port address below. - - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux API. Information on - this API and pointers to "v4l" programs may be found on the WWW at - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called radio-aztech.o. - -Aztech/Packard Bell radio card I/O port -CONFIG_RADIO_AZTECH_PORT - Enter either 0x350 or 0x358 here. The card default is 0x350, if you - haven't changed the setting of jumper JP3 on the card. Removing the - jumper sets the card to 0x358. - -ADS Cadet AM/FM Radio Tuner Card -CONFIG_RADIO_CADET - Choose Y here if you have one of these AM/FM radio cards, and then - fill in the port address below. - - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux API. Information on - this API and pointers to "v4l" programs may be found on the WWW at - . - - Further documentation on this driver can be found on the WWW at - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called radio-cadet.o. - -SF16FMI Radio -CONFIG_RADIO_SF16FMI - Choose Y here if you have one of these FM radio cards. If you - compile the driver into the kernel and your card is not PnP one, you - have to add "sf16fm=" to the kernel command line (I/O address is - 0x284 or 0x384). - - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux API. Information on - this API and pointers to "v4l" programs may be found on the WWW at - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called radio-sf16fmi.o. - -SF16FMR2 Radio -CONFIG_RADIO_SF16FMR2 - Choose Y here if you have one of these FM radio cards. If you - compile the driver into the kernel and your card is not PnP one, you - have to add "sf16fmr2=" to the kernel command line (I/O address is - 0x284 or 0x384, default 0x384). - - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux API. Information on - this API and pointers to "v4l" programs may be found on the WWW at - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called radio-sf16fmr2.o. - -Typhoon Radio (a.k.a. EcoRadio) -CONFIG_RADIO_TYPHOON - Choose Y here if you have one of these FM radio cards, and then fill - in the port address and the frequency used for muting below. - - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux API. Information on - this API and pointers to "v4l" programs may be found on the WWW at - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called radio-typhoon.o. - -Support for /proc/radio-typhoon -CONFIG_RADIO_TYPHOON_PROC_FS - Say Y here if you want the typhoon radio card driver to write - status information (frequency, volume, muted, mute frequency, - base address) to /proc/radio-typhoon. The file can be viewed with - your favorite pager (i.e. use "more /proc/radio-typhoon" or "less - /proc/radio-typhoon" or simply "cat /proc/radio-typhoon"). - -Typhoon I/O port (0x316 or 0x336) -CONFIG_RADIO_TYPHOON_PORT - Enter the I/O port of your Typhoon or EcoRadio radio card. - -Typhoon frequency set when muting the device (kHz) -CONFIG_RADIO_TYPHOON_MUTEFREQ - Enter the frequency used for muting the radio. The device is never - completely silent. If the volume is just turned down, you can still - hear silent voices and music. For that reason, the frequency of the - radio device is set to the frequency you can enter here whenever - the device is muted. There should be no local radio station at that - frequency. - -Zoltrix Radio -CONFIG_RADIO_ZOLTRIX - Choose Y here if you have one of these FM radio cards, and then fill - in the port address below. - - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux API. Information on - this API and pointers to "v4l" programs may be found on the WWW at - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called radio-zoltrix.o. - -ZOLTRIX I/O port (0x20c or 0x30c) -CONFIG_RADIO_ZOLTRIX_PORT - Enter the I/O port of your Zoltrix radio card. - -I2C on parallel port -CONFIG_I2C_PARPORT - I2C is a simple serial bus system used in many micro controller - applications. Saying Y here will allow you to use your parallel - port as an I2C interface. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called i2c-parport.o. - -miroSOUND PCM20 radio -CONFIG_RADIO_MIROPCM20 - Choose Y here if you have this FM radio card. You also need to say Y - to "ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20 radio)" (in "Sound") - for this to work. - - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux API. Information on - this API and pointers to "v4l" programs may be found on the WWW at - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called miropcm20.o. - -miroSOUND PCM20 radio RDS user interface (EXPERIMENTAL) -CONFIG_RADIO_MIROPCM20_RDS - Choose Y here if you want to see RDS/RBDS information like - RadioText, Programme Service name, Clock Time and date, Programme - TYpe and Traffic Announcement/Programme identification. You also - need to say Y to "miroSOUND PCM20 radio" and devfs! - - It's not possible to read the raw RDS packets from the device, so - the driver cant provide an V4L interface for this. But the - availability of RDS is reported over V4L by the basic driver - already. Here RDS can be read from files in /dev/v4l/rds. - - As module the driver will be called miropcm20-rds.o. - -Maestro on board radio -CONFIG_RADIO_MAESTRO - Say Y here to directly support the on-board radio tuner on the - Maestro 2 or 2E sound card. - - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux API. Information on - this API and pointers to "v4l" programs may be found on the WWW at - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called radio-maestro.o. - -Guillemot MAXI Radio FM 2000 Radio Card -CONFIG_RADIO_MAXIRADIO - Choose Y here if you have this radio card. This card may also be - found as GemTek PCI FM. - - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux API. Information on - this API and pointers to "v4l" programs may be found on the WWW at - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called radio-maxiradio.o. - -GemTek Radio Card support -CONFIG_RADIO_GEMTEK - Choose Y here if you have this FM radio card, and then fill in the - port address below. - - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux API. Information on - this API and pointers to "v4l" programs may be found on the WWW at - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called radio-gemtek.o. - -GemTek I/O port -CONFIG_RADIO_GEMTEK_PORT - Enter either 0x20c, 0x30c, 0x24c or 0x34c here. The card default is - 0x34c, if you haven't changed the jumper setting on the card. On - Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM GemTek), the I/O - port is 0x28c. - -GemTek PCI Radio Card support -CONFIG_RADIO_GEMTEK_PCI - Choose Y here if you have this PCI FM radio card. - - In order to control your radio card, you will need to use programs - that are compatible with the Video for Linux API. Information on - this API and pointers to "v4l" programs may be found on the WWW at - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called radio-gemtek-pci.o. - -PlanB Video-In for PowerMacs -CONFIG_VIDEO_PLANB - PlanB is the V4L driver for the PowerMac 7x00/8x00 series video - input hardware. If you want to experiment with this, say Y. - Otherwise, or if you don't understand a word, say N. - See for more info. - - Saying M will compile this driver as a module (planb.o). - -TerraTec ActiveRadio -CONFIG_RADIO_TERRATEC - Choose Y here if you have this FM radio card, and then fill in the - port address below. (TODO) - - Note: This driver is in its early stages. Right now volume and - frequency control and muting works at least for me, but - unfortunately I have not found anybody who wants to use this card - with Linux. So if it is this what YOU are trying to do right now, - PLEASE DROP ME A NOTE!! Rolf Offermanns (rolf@offermanns.de) - - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux API. Information on - this API and pointers to "v4l" programs may be found on the WWW at - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called radio-terratec.o. - -Terratec I/O port (normally 0x590) -CONFIG_RADIO_TERRATEC_PORT - Fill in the I/O port of your TerraTec FM radio card. If unsure, go - with the default. - -Trust FM radio card -CONFIG_RADIO_TRUST - This is a driver for the Trust FM radio cards. Say Y if you have - such a card and want to use it under Linux. - - This driver is also available as a module called radio-trust.o ( = - code which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -Trust I/O port (usually 0x350 or 0x358) -CONFIG_RADIO_TRUST_PORT - Enter the I/O port of your Trust FM radio card. If unsure, try the - values "0x350" or "0x358". - -BT848 Video For Linux -CONFIG_VIDEO_BT848 - Support for BT848 based frame grabber/overlay boards. This includes - the Miro, Hauppauge and STB boards. Please read the material in - for more information. - - If you say Y or M here, you need to say Y or M to "I2C support" and - "I2C bit-banging interfaces" in the character device section. - - This driver is available as a module called bttv.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -BT878 audio DMA -CONFIG_SOUND_BT878 - Audio DMA support for bt878 based grabber boards. As you might have - already noticed, bt878 is listed with two functions in /proc/pci. - Function 0 does the video stuff (bt848 compatible), function 1 does - the same for audio data. This is a driver for the audio part of - the chip. If you say 'Y' here you get a oss-compatible dsp device - where you can record from. If you want just watch TV you probably - don't need this driver as most TV cards handle sound with a short - cable from the TV card to your sound card's line-in. - - This driver is available as a module called btaudio.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -SGI Vino Video For Linux -CONFIG_VIDEO_VINO - Say Y here to include support for SGI VINO (Video In No Out) system - found on SGI Indy workstations. - -Stradis 4:2:2 MPEG-2 video driver -CONFIG_VIDEO_STRADIS - Say Y here to enable support for the Stradis 4:2:2 MPEG-2 video - driver for PCI. There is a product page at - . - -Zoran ZR36057/36060 Video For Linux -CONFIG_VIDEO_ZORAN - Say Y here to include support for video cards based on the Zoran - ZR36057/36060 encoder/decoder chip (including the Iomega Buz and the - Miro DC10 and DC30 video capture cards). - -Include support for Iomega Buz -CONFIG_VIDEO_ZORAN_BUZ - Say Y here to include support for the Iomega Buz video card. There - is a Buz/Linux homepage at . - -Miro DC10(+) support -CONFIG_VIDEO_ZORAN_DC10 - Say Y to support the Pinnacle Systems Studio DC10 plus TV/Video - card. Linux page at - . Vendor - page at . - -Linux Media Labs LML33 support -CONFIG_VIDEO_ZORAN_LML33 - Say Y here to support the Linux Media Labs LML33 TV/Video card. - Resources page is at . - -Zoran ZR36120/36125 Video For Linux -CONFIG_VIDEO_ZR36120 - Support for ZR36120/ZR36125 based frame grabber/overlay boards. - This includes the Victor II, WaveWatcher, Video Wonder, Maxi-TV, - and Buster boards. Please read the material in - for more information. - - This driver is also available as a module called zr36120.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -SAA5249 Teletext processor -CONFIG_VIDEO_SAA5249 - Support for I2C bus based teletext using the SAA5249 chip. At the - moment this is only useful on some European WinTV cards. - - This driver is also available as a module called saa5249.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -QuickCam BW Video For Linux -CONFIG_VIDEO_BWQCAM - Say Y have if you the black and white version of the QuickCam - camera. See the next option for the color version. - - This driver is also available as a module called bw-qcam.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -QuickCam Colour Video For Linux -CONFIG_VIDEO_CQCAM - This is the video4linux driver for the colour version of the - Connectix QuickCam. If you have one of these cameras, say Y here, - otherwise say N. This driver does not work with the original - monochrome QuickCam, QuickCam VC or QuickClip. It is also available - as a module (c-qcam.o). - Read for more information. - -W9966 Webcam (FlyCam Supra and others) Video For Linux -CONFIG_VIDEO_W9966 - Video4linux driver for Winbond's w9966 based Webcams. - Currently tested with the LifeView FlyCam Supra. - If you have one of these cameras, say Y here - otherwise say N. - This driver is also available as a module (w9966.o). - - Check out and - for more information. - -Philips SAA7114H for SiByte BCM91250A -CONFIG_VIDEO_SWARM_7114H - Say Y or M to build the video4linux driver for the Philips SAA7114H - video decoder on Broadcom SWARM board (BCM91250A). The decoder chip - is on the BCM1250's "E2" 8-bit FIFO port. - -CPiA Video For Linux -CONFIG_VIDEO_CPIA - This is the video4linux driver for cameras based on Vision's CPiA - (Colour Processor Interface ASIC), such as the Creative Labs Video - Blaster Webcam II. If you have one of these cameras, say Y here - and select parallel port and/or USB lowlevel support below, - otherwise say N. This will not work with the Creative Webcam III. - - Please read for more - information. - - This driver is also available as a module (cpia.o). - -CPiA Parallel Port Lowlevel Support -CONFIG_VIDEO_CPIA_PP - This is the lowlevel parallel port support for cameras based on - Vision's CPiA (Colour Processor Interface ASIC), such as the - Creative Webcam II. If you have the parallel port version of one - of these cameras, say Y here, otherwise say N. It is also available - as a module (cpia_pp.o). - -CPiA USB Lowlevel Support -CONFIG_VIDEO_CPIA_USB - This is the lowlevel USB support for cameras based on Vision's CPiA - (Colour Processor Interface ASIC), such as the Creative Webcam II. - If you have the USB version of one of these cameras, say Y here, - otherwise say N. This will not work with the Creative Webcam III. - It is also available as a module (cpia_usb.o). - -Mediavision Pro Movie Studio Video For Linux -CONFIG_VIDEO_PMS - Say Y if you have such a thing. This driver is also available as a - module called pms.o ( = code which can be inserted in and removed - from the running kernel whenever you want). If you want to compile - it as a module, say M here and read - . - -Sony Vaio Picturebook Motion Eye Video For Linux -CONFIG_VIDEO_MEYE - This is the video4linux driver for the Motion Eye camera found - in the Vaio Picturebook laptops. Please read the material in - for more information. - - If you say Y or M here, you need to say Y or M to "Sony Programmable - I/O Control Device" in the character device section. - - This driver is available as a module called meye.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -IBM's S/390 architecture -CONFIG_ARCH_S390 - Select this option, if you want to run the Kernel on one of IBM's - mainframes of the S/390 generation. You should have installed the - s390-compiler released by IBM (based on gcc-2.95.1) before. - -Merge some code into the kernel to make the image IPLable -CONFIG_IPL - If you want to use the produced kernel to IPL directly from a - device, you have to merge a bootsector specific to the device - into the first bytes of the kernel. You will have to select the - IPL device on another question, that pops up, when you select - CONFIG_IPL. - -IPL from a S/390 tape unit -CONFIG_IPL_TAPE - Select this option if you want to IPL the image from a Tape. - -IPL from a virtual card reader emulated by VM/ESA -CONFIG_IPL_VM - Select this option if you are running under VM/ESA and want - to IPL the image from the emulated card reader. - -CONFIG_PFAULT - Select this option, if you want to use PFAULT pseudo page fault - handling under VM. If running native or in LPAR, this option - has no effect. If your VM does not support PFAULT, PAGEEX - pseudo page fault handling will be used. - Note that VM 4.2 supports PFAULT but has a bug in its - implementation that causes some problems. - Everybody who wants to run Linux under VM != VM4.2 should select - this option. - -CONFIG_SHARED_KERNEL - Select this option, if you want to share the text segment of the - Linux kernel between different VM guests. This reduces memory - usage with lots of guests but greatly increases kernel size. - You should only select this option if you know what you are - doing and want to exploit this feature. - -Support for IBM-style disk-labels (S/390) -CONFIG_S390_PARTITION - Enable this option to assure standard IBM labels on the DASDs. - You must enable it, if you are planning to access DASDs also - attached to another IBM mainframe operation system (OS/390, - VM/ESA, VSE/ESA). - -Support for DASD hard disks -CONFIG_DASD - Enable this option if you want to access DASDs directly utilizing - S/390s channel subsystem commands. This is necessary for running - natively on a single image or an LPAR. - -Support for ECKD hard disks -CONFIG_DASD_ECKD - ECKD (Extended Count Key Data) devices are the most commonly used - devices on S/390s. You should enable this option unless you are - very sure you have no ECKD device. - -ECKD demand loading -CONFIG_DASD_AUTO_ECKD - This option enables demand loading of the ECKD module. - -Support for FBA hard disks -CONFIG_DASD_FBA - Select this option if you want to use FBA (Fixed Block) devices. - If you are not sure what it is, say "Y". - -FBA demand loading -CONFIG_DASD_AUTO_FBA - This option enables demand loading of the FBA module. - -Support for DIAG access to CMS reserved Disks -CONFIG_DASD_DIAG - Select this option if you want to use CMS reserved Disks under VM - with the Diagnose250 command. If you are not running under VM or - unsure what it is, say "N". - -DIAG demand loading -CONFIG_DASD_AUTO_DIAG - This option enables demand loading of the DIAG module. - -Merge some code into the kernel to make the image IPLable -CONFIG_IPLABLE - If you want to use the produced kernel to IPL directly from a - device, you have to merge a bootsector specific to the device - into the first bytes of the kernel. You will have to select the - IPL device on another question, that pops up, when you select - CONFIG_IPLABE. - -Support for 3215 line mode terminal -CONFIG_TN3215 - Include support for IBM 3215 line-mode terminals. - -Support for console on 3215 line mode terminal -CONFIG_TN3215_CONSOLE - Include support for using an IBM 3215 line-mode terminal as a - Linux system console. - -Support for 3270 line mode terminal -CONFIG_TN3270 - Include support for IBM 3270 line-mode terminals. - -Support for console on 3270 line mode terminal -CONFIG_TN3270_CONSOLE - Include support for using an IBM 3270 line-mode terminal as a Linux - system console. Available only if 3270 support is compiled in - statically. - -Support for HWC line mode terminal -CONFIG_HWC - Include support for IBM HWC line-mode terminals. - -Console on HWC line mode terminal -CONFIG_HWC_CONSOLE - Include support for using an IBM HWC line-mode terminal as the Linux - system console. - -Control Program Identification -CONFIG_HWC_CPI - Allows for Control Program Identification via the HWC interface, - i.e. provides a mean to pass an OS instance name (system name) - to the machine. - - This option should only be selected as a module since the - system name has to be passed as module parameter. The module - will be called hwc_cpi.o. - -S/390 tape device support -CONFIG_S390_TAPE - Select this option if you want to access channel-attached tape - devices on IBM S/390 or zSeries. - If you select this option you will also want to select at - least one of the tape interface options and one of the tape - hardware options in order to access a tape device. - This option is also available as a module. The module will be - called tape390.o and include all selected interfaces. - The hardware drivers will be seperate modules. - If unsure, say "Y". - -Support for tape character devices -CONFIG_S390_TAPE_CHAR - Select this option if you want to access your channel-attached - tape devices using the character device interface. - This interface is similar to other Linux tape devices like - SCSI-Tapes (st) and the floppy tape device (ftape). - If unsure, say "Y". - -Support for tape block devices -CONFIG_S390_TAPE_BLOCK - Select this option if you want to access your channel-attached tape - devices using the block device interface. This interface is similar - to CD-ROM devices on other platforms. The tapes can only be - accessed read-only when using this interface. Have a look at - Documentation/s390/TAPE for further information about creating - volumes for and using this interface. It is safe to say "Y" here. - -Support for 3490 tape hardware -CONFIG_S390_TAPE_3490 - Select this option if you want to access IBM 3490 magnetic - tape subsystems and 100% compatibles. - This option is also available as a module. The module will be - called tape3490.o. If CONFIG_S390_TAPE is selected as a module, - this hardware driver cannot be built-in but is only available - as a module. - It is safe to say "Y" here. - -Support for 3480 tape hardware -CONFIG_S390_TAPE_3480 - Select this option if you want to access IBM 3480 magnetic - tape subsystems and 100% compatibles. - This option is also available as a module. The module will be - called tape3480.o. If CONFIG_S390_TAPE is selected as a module, - this hardware driver cannot be built-in but is only available - as a module. - It is safe to say "Y" here. - -CTC device support -CONFIG_CTC - Select this option if you want to use channel-to-channel networking - on IBM S/390 or zSeries. This device driver supports real CTC - coupling using ESCON. It also supports virtual CTCs when running - under VM. It will use the channel device configuration if this is - available. This option is also available as a module which will be - called ctc.o. If you do not know what it is, it's safe to say "Y". - -XPRAM disk support -CONFIG_BLK_DEV_XPRAM - Select this option if you want to use your expanded storage on S/390 - or zSeries as a disk. This is useful as a _fast_ swap device if you - want to access more than 2G of memory when running in 31 bit mode. - This option is also available as a module which will be called - xpram.o. If unsure, say "N". - -Fast IRQ handling -CONFIG_FAST_IRQ - Select this option in order to get the interrupts processed faster - on your S/390 or zSeries machine. If selected, after an interrupt - is processed, the channel subsystem will be asked for other pending - interrupts which will also be processed before leaving the interrupt - context. This speeds up the I/O a lot. Say "Y". - -IUCV device support (VM only) -CONFIG_IUCV - Select this option if you want to use inter-user communication - vehicle networking under VM or VIF. This option is also available - as a module which will be called iucv.o. If unsure, say "Y". - -Process warning machine checks -CONFIG_MACHCHK_WARNING - Select this option if you want the machine check handler on IBM S/390 or - zSeries to process warning machine checks (e.g. on power failures). - If unsure, say "Y". - -Use chscs for Common I/O -CONFIG_CHSC - Select this option if you want the s390 common I/O layer to use information - obtained by channel subsystem calls. This will enable Linux to process link - failures and resource accessibility events. Moreover, if you have procfs - enabled, you'll be able to toggle chpids logically offline and online. Even - if you don't understand what this means, you should say "Y". - -Process warning machine checks -CONFIG_MACHCHK_WARNING - Select this option if you want the machine check handler on IBM S/390 or - zSeries to process warning machine checks (e.g. on power failures). - If unsure, say "Y". - -Use chscs for Common I/O -CONFIG_CHSC - Select this option if you want the s390 common I/O layer to use information - obtained by channel subsystem calls. This will enable Linux to process link - failures and resource accessibility events. Moreover, if you have procfs - enabled, you'll be able to toggle chpids logically offline and online. Even - if you don't understand what this means, you should say "Y". - -Kernel support for 31 bit ELF binaries -CONFIG_S390_SUPPORT - Select this option if you want to enable your system kernel to - handle system-calls from ELF binaries for 31 bit ESA. This option - (and some other stuff like libraries and such) is needed for - executing 31 bit applications. It is safe to say "Y". - -Channel Device Configuration -CONFIG_CHANDEV - The channel device layer is a layer to provide a consistent - interface for configuration & default machine check (devices - appearing & disappearing) handling on Linux for s/390 & z/Series - channel devices. - - s/390 & z/Series channel devices include among others - - lcs (the most common ethernet/token ring/fddi standard on - zSeries) - ctc/escon hi speed like serial link standard on zSeries - claw used to talk to cisco routers. - qeth gigabit ethernet. - - These devices use two channels one read & one write for - configuration & communication (& a third channel, the data - channel the case of gigabit ethernet). The motivation - behind developing this layer was that there was a lot of - duplicate code among the channel device drivers for - configuration. - - Also the lcs & ctc drivers tended to fight over - 3088/08's & 3088/1F's which could be either 2216/3172 - channel attached lcs compatible devices or escon/ctc pipes - had to be configured separately as they couldn't autodetect, - this is now simplified by doing the configuration in a single - place (the channel device layer). - - This layer isn't invasive & it is quite okay to use channel - drivers which don't use the channel device layer in - conjunction with drivers which do. - - For more info see the chandev manpage usually distributed in - in the Linux source tree. - -SAB3036 tuner support -CONFIG_TUNER_3036 - Say Y here to include support for Philips SAB3036 compatible tuners. - If in doubt, say N. - -Compaq SMART2 support -CONFIG_BLK_CPQ_DA - This is the driver for Compaq Smart Array controllers. Everyone - using these boards should say Y here. See the file - for the current list of boards - supported by this driver, and for further information on the use of - this driver. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - cpqarray.o - -Show crashed user process info -CONFIG_PROCESS_DEBUG - Say Y to print all process fault locations to the console. This is - a debugging option; you probably do not want to set it unless you - are an S390 port maintainer. - -# -# ARM options -# -# CML2 transition note: CML1 asks ARCH_ARCA5K, then has ARCH_A5K and ARCH_ARK -# as subquestions. CML2 asks the subquestions in the armtype menu and makes -# ARCH_ARCA5K a derived symbol. -ARM System type -CONFIG_ARCH_ARCA5K - This selects what ARM system you wish to build the kernel for. It - also selects to some extent the CPU type. If you are unsure what - to set this option to, please consult any information supplied with - your system. - -# Choice: armtype -A5000 -CONFIG_ARCH_A5K - Say Y here to to support the Acorn A5000. Linux can support the - internal IDE disk and CD-ROM interface, serial and parallel port, - and the floppy drive. Note that on some A5000s the floppy is - plugged into the wrong socket on the motherboard. - -Archimedes -CONFIG_ARCH_ARC - The Acorn Archimedes was an personal computer based on an 8K ARM2 - processor, released in 1987. It supported 512K of RAM and 2 800K - floppy disks. Picture and more detailed specifications at - . - -EBSA-110 -CONFIG_ARCH_EBSA110 - This is an evaluation board for the StrongARM processor available - from Digital. It has limited hardware on-board, including an onboard - Ethernet interface, two PCMCIA sockets, two serial ports and a - parallel port. - -RiscPC -CONFIG_ARCH_RPC - On the Acorn Risc-PC, Linux can support the internal IDE disk and - CD-ROM interface, serial and parallel port, and the floppy drive. - -2MB physical memory -CONFIG_PAGESIZE_16 - Say Y here if your Archimedes or A5000 system has only 2MB of - memory, otherwise say N. The resulting kernel will not run on a - machine with 4MB of memory. - -CATS -CONFIG_ARCH_CATS - Say Y here if you intend to run this kernel on the CATS. - - Saying N will reduce the size of the Footbridge kernel. - -EBSA285 (addin mode) -CONFIG_ARCH_EBSA285_ADDIN - Say Y here if you intend to run this kernel on the EBSA285 card - in addin mode. - - Saying N will reduce the size of the Footbridge kernel. - -EBSA285 (host mode) -CONFIG_ARCH_EBSA285_HOST - Say Y here if you intend to run this kernel on the EBSA285 card - in host ("central function") mode. - - Saying N will reduce the size of the Footbridge kernel. - -LinkUp Systems L7200 SDB -CONFIG_ARCH_L7200 - Say Y here if you intend to run this kernel on a LinkUp Systems - L7200 Software Development Board which uses an ARM720T processor. - Information on this board can be obtained at: - - - - If you have any questions or comments about the Linux kernel port - to this board, send e-mail to sjhill@cotw.com. - -NetWinder -CONFIG_ARCH_NETWINDER - Say Y here if you intend to run this kernel on the Rebel.COM - NetWinder. Information about this machine can be found at: - - - - Saying N will reduce the size of the Footbridge kernel. - -P720T -CONFIG_ARCH_P720T - Say Y here if you intend to run this kernel on the ARM Prospector - 720T. - -Compaq Personal Server -CONFIG_ARCH_PERSONAL_SERVER - Say Y here if you intend to run this kernel on the Compaq - Personal Server. - - Saying N will reduce the size of the Footbridge kernel. - - The Compaq Personal Server is not available for purchase. - There are no product plans beyond the current research - prototypes at this time. Information is available at: - - - - If you have any questions or comments about the Compaq Personal - Server, send e-mail to skiff@crl.dec.com. - -Cirrus Logic EDB-7211 evaluation board -CONFIG_ARCH_EDB7211 - Say Y here if you intend to run this kernel on a Cirrus Logic EDB-7211 - evaluation board. - -EP7211 infrared support -CONFIG_EP7211_IR - Say Y here if you wish to use the infrared port on the EP7211. Note - that you can't use the first UART and the infrared port at the same - time, and that the EP7211 only supports SIR mode, at speeds up to - 115.2 kbps. To use the I/R port, you will need to get the source to - irda-utils and apply the patch at - . - -Assabet -CONFIG_SA1100_ASSABET - Say Y here if you are using the Intel(R) StrongARM(R) SA-1110 - Microprocessor Development Board (also known as the Assabet). - -Neponset -CONFIG_ASSABET_NEPONSET - Say Y here if you are using the Intel(R) StrongARM(R) SA-1110 - Microprocessor Development Board (Assabet) with the SA-1111 - Development Board (Nepon). - -Compaq iPAQ H3600 -CONFIG_SA1100_H3600 - Say Y here if you intend to run this kernel on the Compaq iPAQ - H3600 handheld computer. Information about this machine and the - Linux port to this machine can be found at: - - - - -Brutus -CONFIG_SA1100_BRUTUS - Say Y here if you are using the Intel(R) StrongARM(R) SA-1100 - Microprocessor Development Board (also known as the Brutus). - -LART -CONFIG_SA1100_LART - Say Y here if you are using the Linux Advanced Radio Terminal - (also known as the LART). See for - information on the LART. - -GraphicsClient -CONFIG_SA1100_GRAPHICSCLIENT - Say Y here if you are using an Applied Data Systems Intel(R) - StrongARM(R) SA-1100 based Graphics Client SBC. See - for information on this system. - -GraphicsMaster -CONFIG_SA1100_GRAPHICSMASTER - Say Y here if you are using an Applied Data Systems Intel(R) - StrongARM(R) SA-1100 based Graphics Master SBC with SA-1111 - StrongARM companion chip. See - for information - on this system. - -ADSBitsy -CONFIG_SA1100_ADSBITSY - Say Y here if you are using Applied Data Systems Intel(R) - StrongARM(R) 1110 based Bitsy, 3 x 5 inches in size, Compaq - IPAQ - - like platform. See - for more - information. - -ITSY -CONFIG_SA1100_ITSY - Say Y here if you are using the Compaq Itsy experimental pocket - computer. See for - more information. - -PLEB -CONFIG_SA1100_PLEB - Say Y here if you are using a Portable Linux Embedded Board - (also known as PLEB). See - for more information. - -CerfBoard -CONFIG_SA1100_CERF - The Intrinsyc CerfBoard is based on the StrongARM 1110. - More information is available at: - . - - Say Y if configuring for an Intrinsyc CerfBoard. - Say N otherwise. - -FlexaNet -CONFIG_SA1100_FLEXANET - Say Y here if you intend to run this kernel on the FlexaNet - handheld instruments. Information about this machine can be - found at: . - -nanoEngine -CONFIG_SA1100_NANOENGINE - The nanoEngine is a StrongARM 1110-based single board computer - from Bright Star Engineering. More information is available at: - . - - Say Y if configuring for a nanoEngine. - Say N otherwise. - -Pangolin -CONFIG_SA1100_PANGOLIN - Pangolin is a StrongARM 1110-based evaluation platform produced - by Dialogue Technology. It has EISA slots for ease of configuration - with SDRAM/Flash memory card, USB/Serial/Audio card, Compact Flash - card, and TFT-LCD card. - - Say Y if configuring for a Pangolin. - Say N otherwise. - -Victor -CONFIG_SA1100_VICTOR - Say Y here if you are using a Visu Aide Intel(R) StrongARM(R) - SA-1100 based Victor Digital Talking Book Reader. See - for information on - this system. - -# Choice: cerf_ram -Cerf on-board RAM size -CONFIG_SA1100_CERF_8MB - Declare the size of the CerfBoard's on-board RAM. - Alternatives are 8, 16, 32, and 64MB. - -16MB -CONFIG_SA1100_CERF_16MB - Declare that the CerfBoard has 16MB RAM. - -32MB -CONFIG_SA1100_CERF_32MB - Declare that the CerfBoard has 32MB RAM. - -64MB -CONFIG_SA1100_CERF_64MB - Declare that the CerfBoard has 64MB RAM. - -# Choice: cerf_flash -Cerf flash memory size -CONFIG_SA1100_CERF_FLASH_8MB - Tell the Cerf kernel the size of on-board memory. The choices - are 8MB, 16MB, or 32MB. - -16MB -CONFIG_SA1100_CERF_FLASH_16MB - Configure the Cerf kernel to expect 16MB of flash memory. - -32MB -CONFIG_SA1100_CERF_FLASH_32MB - Configure the Cerf kernel to expect 32MB of flash memory. - -Support ARM610 processor -CONFIG_CPU_ARM610 - The ARM610 is the successor to the ARM3 processor - and was produced by VLSI Technology Inc. - - Say Y if you want support for the ARM610 processor. - Otherwise, say N. - -Support ARM710 processor -CONFIG_CPU_ARM710 - A 32-bit RISC microprocessor based on the ARM7 processor core - designed by Advanced RISC Machines Ltd. The ARM710 is the - successor to the ARM610 processor. It was released in - July 1994 by VLSI Technology Inc. - - Say Y if you want support for the ARM710 processor. - Otherwise, say N. - -Support ARM720T processor -CONFIG_CPU_ARM720T - A 32-bit RISC processor with 8kByte Cache, Write Buffer and - MMU built around an ARM7TDMI core. - - Say Y if you want support for the ARM720T processor. - Otherwise, say N. - -Support ARM920T processor -CONFIG_CPU_ARM920T - The ARM920T is licensed to be produced by numerous vendors, - and is used in the Maverick EP9312. More information at - . - - Say Y if you want support for the ARM920T processor. - Otherwise, say N. - -Support ARM1020 processor -CONFIG_CPU_ARM1020 - The ARM1020 is the cached version of the ARM10 processor, - with an addition of a floating-point unit. - - Say Y if you want support for the ARM1020 processor. - Otherwise, say N. - -Disable I-Cache -CONFIG_CPU_ICACHE_DISABLE - Say Y here to disable the processor instruction cache. Unless - you have a reason not to or are unsure, say N. - -Disable D-Cache -CONFIG_CPU_DCACHE_DISABLE - Say Y here to disable the processor data cache. Unless - you have a reason not to or are unsure, say N. - -Force write through D-cache -CONFIG_CPU_DCACHE_WRITETHROUGH - Say Y here to use the data cache in write-through mode. Unless you - specifically require this or are unsure, say N. - -Round robin I and D cache replacement algorithm -CONFIG_CPU_CACHE_ROUND_ROBIN - Say Y here to use the predictable round-robin cache replacement - policy. Unless you specifically require this or are unsure, say N. - -Disable branch prediction -CONFIG_CPU_BPREDICT_DISABLE - Say Y here to disable branch prediction. If unsure, say N. - -Compressed boot loader in ROM/flash -CONFIG_ZBOOT_ROM - Say Y here if you intend to execute your compressed kernel image (zImage) - directly from ROM or flash. If unsure, say N. - -Compressed ROM boot loader base address -CONFIG_ZBOOT_ROM_TEXT - The base address for zImage. Unless you have special requirements, you - should not change this value. - -Compressed ROM boot loader BSS address -CONFIG_ZBOOT_ROM_BSS - The base address of 64KiB of read/write memory, which must be available - while the decompressor is running. Unless you have special requirements, - you should not change this value. - -Support StrongARM SA-110 processor -CONFIG_CPU_SA110 - The Intel StrongARM(R) SA-110 is a 32-bit microprocessor and - is available at five speeds ranging from 100 MHz to 233 MHz. - More information is available at - . - - Say Y if you want support for the SA-110 processor. - Otherwise, say N. - -Tulsa -CONFIG_SA1100_PFS168 - The Radisys Corp. PFS-168 (aka Tulsa) is an Intel® StrongArm® SA-1110 based - computer which includes the SA-1111 Microprocessor Companion Chip and other - custom I/O designed to add connectivity and multimedia features for vending - and business machine applications. Say Y here if you require support for - this target. - -HP Jornada 720 -CONFIG_SA1100_JORNADA720 - Say Y here if you want to build a kernel for the HP Jornada 720 - handheld computer. See - for details. - -InHand Electronics OmniMeter -CONFIG_SA1100_OMNIMETER - Say Y here if you are using the inhand electronics OmniMeter. See - for details. - -Load kernel using Angel Debug Monitor -CONFIG_ANGELBOOT - Say Y if you plan to load the kernel using Angel, ARM Ltd's target - debug stub. If you are not using Angel, you must say N. It is - important to get this setting correct. - -CDB89712 -CONFIG_ARCH_CDB89712 - This is an evaluation board from Cirrus for the CS89712 processor. The - board includes 2 serial ports, Ethernet, IRDA, and expansion headers. - It comes with 16 MB SDRAM and 8 MB flash ROM. - -CLPS-711X internal ROM bootstrap -CONFIG_EP72XX_ROM_BOOT - If you say Y here, your CLPS711x-based kernel will use the bootstrap - mode memory map instead of the normal memory map. - - Processors derived from the Cirrus CLPS-711X core support two boot modes. - Normal mode boots from the external memory device at CS0. Bootstrap mode - rearranges parts of the memory map, placing an internal 128 byte bootstrap - ROM at CS0. This option performs the address map changes required to - support booting in this mode. - - You almost surely want to say N here. - -Math emulation -CONFIG_FPE_NWFPE - Say Y to include the NWFPE floating point emulator in the kernel. - This is necessary to run most binaries. Linux does not currently - support floating point hardware so you need to say Y here even if - your machine has an FPA or floating point co-processor podule. - - It is also possible to say M to build the emulator as a module - (nwfpe.o) or indeed to leave it out altogether. However, unless you - know what you are doing this can easily render your machine - unbootable. Saying Y is the safe option. - - You may say N here if you are going to load the Acorn FPEmulator - early in the bootup. - -FastFPE math emulation -CONFIG_FPE_FASTFPE - Say Y here to include the FAST floating point emulator in the kernel. - This is an experimental much faster emulator which has only 32 bit - precision for the mantissa. It does not support any exceptions. - This makes it very simple, it is approximately 4-8 times faster than - NWFPE. - - It should be sufficient for most programs. It is definitely not - suitable if you do scientific calculations that need double - precision for iteration formulas that sum up lots of very small - numbers. If you do not feel you need a faster FP emulation you - should better choose NWFPE. - - It is also possible to say M to build the emulator as a module - (fastfpe.o). But keep in mind that you should only load the FP - emulator early in the bootup. You should never change from NWFPE to - FASTFPE or vice versa in an active system! - -DS1620 thermometer support -CONFIG_DS1620 - Say Y here to include support for the thermal management hardware - found in the NetWinder. This driver allows the user to control the - temperature set points and to read the current temperature. - - It is also possible to say M here to build it as a module (ds1620.o) - It is recommended to be used on a NetWinder, but it is not a - necessity. - -Check for stack overflows -CONFIG_DEBUG_STACKOVERFLOW - This option make do_IRQ() check for enough stack space beeing left. - This is safe to enable. - -Debug high memory support -CONFIG_DEBUG_HIGHMEM - This options enables addition error checking for high memory systems. - Disable for production systems. - -Verbose kernel error messages -CONFIG_DEBUG_ERRORS - This option controls verbose debugging information which can be - printed when the kernel detects an internal error. This debugging - information is useful to kernel hackers when tracking down problems, - but mostly meaningless to other people. It's safe to say Y unless - you are concerned with the code size or don't want to see these - messages. - -Compile kernel with frame pointer -CONFIG_FRAME_POINTER - If you say Y here, the resulting kernel will be slightly larger and - slower, but it will give very useful debugging information. If you - don't debug the kernel, you can say N, but we may not be able to - solve problems without frame pointers. - -Verbose user fault messages -CONFIG_DEBUG_USER - When a user program crashes due to an exception, the kernel can - print a brief message explaining what the problem was. This is - sometimes helpful for debugging but serves no purpose on a - production system. Most people should say N here. - -Include gdb debugging information in kernel binary -CONFIG_DEBUG_INFO - Say Y here to include source-level debugging information in the - `vmlinux' binary image. This is handy if you want to use gdb or - addr2line to debug the kernel. It has no impact on the in-memory - footprint of the running kernel but it can increase the amount of - time and disk space needed for compilation of the kernel. If in - doubt say N. - -Kernel low-level debugging functions -CONFIG_DEBUG_LL - Say Y here to include definitions of printascii, printchar, printhex - in the kernel. This is helpful if you are debugging code that - executes before the console is initialized. - -Kernel low-level debugging messages via footbridge serial port -CONFIG_DEBUG_DC21285_PORT - Say Y here if you want the debug print routines to direct their - output to the serial port in the DC21285 (Footbridge). Saying N - will cause the debug messages to appear on the first 16550 - serial port. - -Kernel low-level debugging messages via UART2 -CONFIG_DEBUG_CLPS711X_UART2 - Say Y here if you want the debug print routines to direct their - output to the second serial port on these devices. Saying N will - cause the debug messages to appear on the first serial port. - -Kernel log buffer length shift -CONFIG_LOG_BUF_SHIFT - The kernel log buffer has a fixed size of : - 64 kB (2^16) on MULTIQUAD and IA64, - 128 kB (2^17) on S390 - 32 kB (2^15) on SMP systems - 16 kB (2^14) on UP systems - - You have the ability to change this size with this paramter which - fixes the bit shift of to get the buffer length (which must be a - power of 2). Eg: a value of 16 sets the buffer to 64 kB (2^16). - The default value of 0 uses standard values above. - -Disable pgtable cache -CONFIG_NO_PGT_CACHE - Normally the kernel maintains a `quicklist' of preallocated - pagetable structures in order to increase performance. On machines - with very few pages this may however be a loss. Say Y here to - disable the pgtable cache. - -RISC OS personality -CONFIG_ARTHUR - Say Y here to include the kernel code necessary if you want to run - Acorn RISC OS/Arthur binaries under Linux. This code is still very - experimental; if this sounds frightening, say N and sleep in peace. - You can also say M here to compile this support as a module (which - will be called arthur.o). - -Initial kernel command line -CONFIG_CMDLINE - On some architectures (EBSA110 and CATS), there is currently no way - for the boot loader to pass arguments to the kernel. For these - architectures, you should supply some command-line options at build - time by entering them here. As a minimum, you should specify the - memory size and the root device (e.g., mem=64M root=/dev/nfs). - -Kernel-mode alignment trap handler -CONFIG_ALIGNMENT_TRAP - ARM processors can not fetch/store information which is not - naturally aligned on the bus, i.e., a 4 byte fetch must start at an - address divisible by 4. On 32-bit ARM processors, these non-aligned - fetch/store instructions will be emulated in software if you say - here, which has a severe performance impact. This is necessary for - correct operation of some network protocols. With an IP-only - configuration it is safe to say N, otherwise say Y. - -DC21285 serial port support -CONFIG_SERIAL_21285 - If you have a machine based on a 21285 (Footbridge) StrongARM(R)/ - PCI bridge you can enable its onboard serial port by enabling this - option. The device has major ID 4, minor 64. - -Console on DC21285 serial port -CONFIG_SERIAL_21285_CONSOLE - If you have enabled the serial port on the 21285 footbridge you can - make it the console by answering Y to this option. - -SA1100 serial port support -CONFIG_SERIAL_SA1100 - * Orphaned entry retained 20 April 2001 by Russell King * - * If you read this note from the configurator, please contact * - * the Configure.help maintainers. * - If you have a machine based on a SA1100/SA1110 StrongARM CPU you can - enable its onboard serial port by enabling this option. - Please read for further - info. - -Console on SA1100 serial port -CONFIG_SERIAL_SA1100_CONSOLE - * Orphaned entry retained 20 April 2001 by Russell King * - * If you read this note from the configurator, please contact * - * the Configure.help maintainers. * - If you have enabled the serial port on the SA1100/SA1110 StrongARM - CPU you can make it the console by answering Y to this option. - -L7200 serial port support -CONFIG_SERIAL_L7200 - * Orphaned entry retained 20 April 2001 by Russell King * - * If you read this note from the configurator, please contact * - * the Configure.help maintainers. * - If you have a LinkUp Systems L7200 board you can enable its two - onboard serial ports by enabling this option. The device numbers - are major ID 4 with minor 64 and 65 respectively. - -Console on L7200 serial port -CONFIG_SERIAL_L7200_CONSOLE - * Orphaned entry retained 20 April 2001 by Russell King * - * If you read this note from the configurator, please contact * - * the Configure.help maintainers. * - If you have enabled the serial ports on the L7200 development board - you can make the first serial port the console by answering Y to - this option. - -L7200 SDB keyboard support -CONFIG_KEYBOARD_L7200 - * Orphaned entry retained 20 April 2001 by Russell King * - * If you read this note from the configurator, please contact * - * the Configure.help maintainers. * - Enable this option if you would like to be able to use a keyboard - on a LinkUp Systems L7200 board. - -L7200 SDB Fujitsu keyboard support -CONFIG_KEYBOARD_L7200_NORM - * Orphaned entry retained 20 April 2001 by Russell King * - * If you read this note from the configurator, please contact * - * the Configure.help maintainers. * - Select the Fujitsu keyboard if you want a normal QWERTY style - keyboard on the LinkUp SDB. - -L7200 SDB Prototype keyboard support -CONFIG_KEYBOARD_L7200_DEMO - * Orphaned entry retained 20 April 2001 by Russell King * - * If you read this note from the configurator, please contact * - * the Configure.help maintainers. * - Select the prototype keyboard if you want to play with the - LCD/keyboard combination on the LinkUp SDB. - -Footbridge Mode -CONFIG_HOST_FOOTBRIDGE - * Orphaned entry retained 20 April 2001 by Russell King * - * If you read this note from the configurator, please contact * - * the Configure.help maintainers. * - The 21285 Footbridge chip can operate in either `host mode' or - `add-in' mode. Say Y if your 21285 is in host mode, and therefore - is the configuration master, otherwise say N. This must not be - set to Y if the card is used in 'add-in' mode. - -MFM hard disk support -CONFIG_BLK_DEV_MFM - Support the MFM hard drives on the Acorn Archimedes both - on-board the A4x0 motherboards and via the Acorn MFM modules. - Drives up to 64MB are supported. If you haven't got one of these - machines or drives just say N. - -Old Archimedes floppy (1772) support -CONFIG_BLK_DEV_FD1772 - Support the floppy drive on the Acorn Archimedes (A300, A4x0, A540, - R140 and R260) series of computers; it supports only 720K floppies - at the moment. If you don't have one of these machines just answer - N. - -Autodetect hard drive geometry -CONFIG_BLK_DEV_MFM_AUTODETECT - If you answer Y, the MFM code will attempt to automatically detect - the cylinders/heads/sectors count on your hard drive. WARNING: This - sometimes doesn't work and it also does some dodgy stuff which - potentially might damage your drive. - -NetWinder /dev/flash support -CONFIG_NWFLASH - If you say Y here and create a character device /dev/flash with - major 10 and minor 160 you can manipulate the flash ROM containing - the NetWinder firmware. Be careful as accidentally overwriting the - flash contents can render your computer unbootable. On no account - allow random users access to this device. :-) - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called nwflash.o. If you want to compile it as a - module, say M here and read . - - If you're not sure, say N. - -SRM environment variables in procfs -CONFIG_SRM_ENV - If you enable this option, a subdirectory inside /proc called - /proc/srm_environment will give you access to the all important - SRM environment variables (those which have a name) and also - to all others (by their internal number). - - SRM is something like a BIOS for Alpha machines. There are some - other such BIOSes, like AlphaBIOS, which this driver cannot - support (hey, that's not SRM!). - - Despite the fact that this driver doesn't work on all Alphas (but - only on those which have SRM as their firmware), it's save to - build it even if your particular machine doesn't know about SRM - (or if you intend to compile a generic kernel). It will simply - not create those subdirectory in /proc (and give you some warning, - of course). - - This driver is also available as a module and will be called - srm_env.o then. - -Footbridge internal watchdog -CONFIG_21285_WATCHDOG - The Intel Footbridge chip contains a builtin watchdog circuit. Say Y - here if you wish to use this. Alternatively say M to compile the - driver as a module, which will be called wdt285.o. - - This driver does not work on all machines. In particular, early CATS - boards have hardware problems that will cause the machine to simply - lock up if the watchdog fires. - - "If in doubt, leave it out" - say N. - -NetWinder WB83C977 watchdog -CONFIG_977_WATCHDOG - Say Y here to include support for the WB977 watchdog included in - NetWinder machines. Alternatively say M to compile the driver as - a module, which will be called wdt977.o. - - Not sure? It's safe to say N. - -IrDA subsystem support -CONFIG_IRDA - Say Y here if you want to build support for the IrDA (TM) protocols. - The Infrared Data Associations (tm) specifies standards for wireless - infrared communication and is supported by most laptops and PDA's. - - To use Linux support for the IrDA (tm) protocols, you will also need - some user-space utilities like irattach. For more information, see - the file . You also want to - read the IR-HOWTO, available at - . - - If you want to exchange bits of data (vCal, vCard) with a PDA, you - will need to install some OBEX application, such as OpenObex : - - - This support is also available as a module called irda.o. If you - want to compile it as a module, say M here and read - . - -Ultra (connectionless) protocol -CONFIG_IRDA_ULTRA - Say Y here to support the connectionless Ultra IRDA protocol. - Ultra allows to exchange data over IrDA with really simple devices - (watch, beacon) without the overhead of the IrDA protocol (no handshaking, - no management frames, simple fixed header). - Ultra is available as a special socket : socket(AF_IRDA, SOCK_DGRAM, 1); - -IrDA cache last LSAP -CONFIG_IRDA_CACHE_LAST_LSAP - Say Y here if you want IrLMP to cache the last LSAP used. This - makes sense since most frames will be sent/received on the same - connection. Enabling this option will save a hash-lookup per frame. - - If unsure, say Y. - -IrDA Fast RRs -CONFIG_IRDA_FAST_RR - Say Y here is you want IrLAP to send fast RR (Receive Ready) frames - when acting as a primary station. - Disabling this option will make latency over IrDA very bad. Enabling - this option will make the IrDA stack send more packet than strictly - necessary, thus reduce your battery life (but not that much). - - Fast RR will make IrLAP send out a RR frame immediately when - receiving a frame if its own transmit queue is currently empty. This - will give a lot of speed improvement when receiving much data since - the secondary station will not have to wait the max. turn around - time (usually 500ms) before it is allowed to transmit the next time. - If the transmit queue of the secondary is also empty, the primary will - start backing-off before sending another RR frame, waiting longer - each time until the back-off reaches the max. turn around time. - This back-off increase in controlled via - /proc/sys/net/irda/fast_poll_increase - - If unsure, say Y. - -IrDA debugging information -CONFIG_IRDA_DEBUG - Say Y here if you want the IrDA subsystem to write debug information - to your syslog. You can change the debug level in - /proc/sys/net/irda/debug . - When this option is enabled, the IrDA also perform many extra internal - verifications which will usually prevent the kernel to crash in case of - bugs. - - If unsure, say Y (since it makes it easier to find the bugs). - -IrLAN protocol -CONFIG_IRLAN - Say Y here if you want to build support for the IrLAN protocol. If - you want to compile it as a module (irlan.o), say M here and read - . IrLAN emulates an Ethernet and - makes it possible to put up a wireless LAN using infrared beams. - - The IrLAN protocol can be used to talk with infrared access points - like the HP NetbeamIR, or the ESI JetEye NET. You can also connect - to another Linux machine running the IrLAN protocol for ad-hoc - networking! - -IrNET protocol -CONFIG_IRNET - Say Y here if you want to build support for the IrNET protocol. If - you want to compile it as a module (irnet.o), say M here and read - . IrNET is a PPP driver, so you - will also need a working PPP subsystem (driver, daemon and - config)... - - IrNET is an alternate way to transfer TCP/IP traffic over IrDA. It - uses synchronous PPP over a set of point to point IrDA sockets. You - can use it between Linux machine or with W2k. - -IrCOMM protocol -CONFIG_IRCOMM - Say Y here if you want to build support for the IrCOMM protocol. If - you want to compile it as a module (you will get ircomm.o and - ircomm-tty.o), say M here and read . - IrCOMM implements serial port emulation, and makes it possible to - use all existing applications that understands TTY's with an - infrared link. Thus you should be able to use application like PPP, - minicom and others. Enabling this option will create two modules - called ircomm and ircomm_tty. - -IrTTY IrDA Device Driver -CONFIG_IRTTY_SIR - Say Y here if you want to build support for the IrTTY line - discipline. If you want to compile it as a module (irtty.o), say M - here and read . IrTTY makes it - possible to use Linux's own serial driver for all IrDA ports that - are 16550 compatible. Most IrDA chips are 16550 compatible so you - should probably say Y to this option. Using IrTTY will however - limit the speed of the connection to 115200 bps (IrDA SIR mode). - - If unsure, say Y. - -IrPORT IrDA serial driver -CONFIG_IRPORT_SIR - Say Y here if you want to build support for the IrPORT IrDA device - driver. If you want to compile it as a module (irport.o), say M here - and read . IrPORT can be used - instead of IrTTY and sometimes this can be better. One example is - if your IrDA port does not have echo-canceling, which will work OK - with IrPORT since this driver is working in half-duplex mode only. - You don't need to use irattach with IrPORT, but you just insert it - the same way as FIR drivers (insmod irport io=0x3e8 irq=11). Notice - that IrPORT is a SIR device driver which means that speed is limited - to 115200 bps. - - If unsure, say Y. - -USB IrDA FIR dongle Device Driver -CONFIG_USB_IRDA - Say Y here if you want to build support for the USB IrDA FIR Dongle - device driver. If you want to compile it as a module (irda-usb.o), - say M here and read . IrDA-USB - support the various IrDA USB dongles available and most of their - peculiarities. Those dongles plug in the USB port of your computer, - are plug and play, and support SIR and FIR (4Mbps) speeds. On the - other hand, those dongles tend to be less efficient than a FIR - chipset. - - Please note that the driver is still experimental. And of course, - you will need both USB and IrDA support in your kernel... - -Datafab MDCFE-B Compact Flash Reader support -CONFIG_USB_STORAGE_DATAFAB - This option enables a sub-driver of the USB Mass Storage driver. These - sub-drivers are considered experimental, and should only be used by very - brave people. System crashes and other bad things are likely to occur if - you use this driver. If in doubt, select N. - -HP CD-Writer 82xx support -CONFIG_USB_STORAGE_HP8200e - This option enables a sub-driver of the USB Mass Storage driver. These - sub-drivers are considered experimental, and should only be used by very - brave people. System crashes and other bad things are likely to occur if - you use this driver. If in doubt, select N. - -Lexar Jumpshot Compact Flash Reader -CONFIG_USB_STORAGE_JUMPSHOT - This option enables a sub-driver of the USB Mass Storage driver. These - sub-drivers are considered experimental, and should only be used by very - brave people. System crashes and other bad things are likely to occur if - you use this driver. If in doubt, select N. - -Tieman Voyager USB Braille display support (EXPERIMENTAL) -CONFIG_USB_BRLVGER - Say Y here if you want to use the Voyager USB Braille display from - Tieman. See for more - information. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called brlvger.o. If you want to compile it as - a module, say M here and read . - -KB Gear JamStudio tablet support -CONFIG_USB_KBTAB - Say Y here if you want to use the USB version of the KB Gear - JamStudio tablet. Make sure to say Y to "Mouse support" - (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" - (CONFIG_INPUT_EVDEV) as well. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called kbtab.o. If you want to compile it as a - module, say M here and read . - -USB Inside Out Edgeport Serial Driver (TI devices) -CONFIG_USB_SERIAL_EDGEPORT_TI - Say Y here if you want to use any of the devices from Inside Out - Networks (Digi) that are not supported by the io_edgeport driver. - This includes the Edgeport/1 device. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called io_ti.o. If you want to compile it - as a module, say M here and read . - -USB Keyspan MPR Firmware -CONFIG_USB_SERIAL_KEYSPAN_MPR - Say Y here to include firmware for the Keyspan MPR converter. - -Winbond W83977AF IrDA Device Driver -CONFIG_WINBOND_FIR - Say Y here if you want to build IrDA support for the Winbond - W83977AF super-io chipset. This driver should be used for the IrDA - chipset in the Corel NetWinder. The driver supports SIR, MIR and - FIR (4Mbps) speeds. - - If you want to compile it as a module, say M here and read - . The module will be called - w83977af_ir.o. - -NSC PC87108/PC87338 IrDA Device Driver -CONFIG_NSC_FIR - Say Y here if you want to build support for the NSC PC87108 and - PC87338 IrDA chipsets. This driver supports SIR, - MIR and FIR (4Mbps) speeds. - - If you want to compile it as a module, say M here and read - . The module will be called - nsc-ircc.o. - -National Semiconductor DP83820 support -CONFIG_NS83820 - This is a driver for the National Semiconductor DP83820 series - of gigabit ethernet MACs. Cards using this chipset include: - - SMC 9452TX SMC SMC9462TX - D-Link DGE-500T PureData PDP8023Z-TG - SOHO-GA2000T SOHO-GA2500T. - NetGear GA621 - - This driver supports the use of zero copy on tx, checksum - validation on rx, and 64 bit addressing. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called ns83820.o. - -Toshiba Type-O IR Port device driver (old driver) -CONFIG_TOSHIBA_OLD - Say Y here if you want to build support for the Toshiba Type-O IR - chipset. This chipset is used by the Toshiba Libretto 100CT, and - many more laptops. This driver is obsolete, will no more be - maintained and will be removed in favor of the new driver. - If you want to compile it as a module, say M here and read - . - The module will be called toshoboe.o. - -Toshiba Type-O IR Port device driver -CONFIG_TOSHIBA_FIR - Say Y here if you want to build support for the Toshiba Type-O IR - and Donau oboe chipsets. These chipsets are used by the Toshiba - Libretto 100/110CT, Tecra 8100, Portege 7020 and many more laptops. - If you want to compile it as a module, say M here and read - . - The module will be called donauboe.o. - -SMC IrCC -CONFIG_SMC_IRCC_FIR - Say Y here if you want to build support for the SMC Infrared - Communications Controller. It is used in the Fujitsu Lifebook 635t - and Sony PCG-505TX. If you want to compile it as a module, say M - here and read . The module will be - called smc-ircc.o. - -VIA IrCC -CONFIG_VIA_IRCC_FIR - Say Y here if you want to build support for the VIA Fast Infrared - Communications Controller. It is used in all sorts of VIA686a- and - VT1211-based notebooks. If you want to compile it as a module, say M - here and read . The module will be - called via-ircc.o. - -ALi M5123 FIR controller driver -CONFIG_ALI_FIR - Say Y here if you want to build support for the ALi M5123 FIR - Controller. The ALi M5123 FIR Controller is embedded in ALi M1543C, - M1535, M1535D, M1535+, M1535D Sourth Bridge. This driver supports - SIR, MIR and FIR (4Mbps) speeds. - - If you want to compile it as a module, say M here and read - . The module will be called - ali-ircc.o. - -VLSI 82C147 PCI-IrDA SIR/MIR/FIR Controller driver -CONFIG_VLSI_FIR - Say Y here if you want to build support for the VLSI 82C147 - PCI-IrDA Controller. This controller is used by the HP OmniBook 800 - and 5500 notebooks. The driver provides support for SIR, MIR and - FIR (4Mbps) speeds. - - If you want to compile it as a module, say M here and read - . The module will be called vlsi_ir.o. - -Serial dongle support -CONFIG_DONGLE - Say Y here if you have an infrared device that connects to your - computer's serial port. These devices are called dongles. Then say Y - or M to the driver for your particular dongle below. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about serial dongles. - -ESI JetEye PC dongle -CONFIG_ESI_DONGLE - Say Y here if you want to build support for the Extended Systems - JetEye PC dongle. If you want to compile it as a module, say M here - and read . The ESI dongle attaches - to the normal 9-pin serial port connector, and can currently only be - used by IrTTY. To activate support for ESI dongles you will have to - start irattach like this: "irattach -d esi". - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called esi.o. - -ACTiSYS IR-220L and IR220L+ dongle -CONFIG_ACTISYS_DONGLE - Say Y here if you want to build support for the ACTiSYS IR-220L and - IR220L+ dongles. If you want to compile it as a module, say M here - and read . The ACTiSYS dongles - attaches to the normal 9-pin serial port connector, and can - currently only be used by IrTTY. To activate support for ACTiSYS - dongles you will have to start irattach like this: - "irattach -d actisys" or "irattach -d actisys+". - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called actisys.o. - -Tekram IrMate 210B dongle -CONFIG_TEKRAM_DONGLE - Say Y here if you want to build support for the Tekram IrMate 210B - dongle. If you want to compile it as a module, say M here and read - . The Tekram dongle attaches to the - normal 9-pin serial port connector, and can currently only be used - by IrTTY. To activate support for Tekram dongles you will have to - start irattach like this: "irattach -d tekram". - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called tekram.o. - -Greenwich GIrBIL dongle -CONFIG_GIRBIL_DONGLE - Say Y here if you want to build support for the Greenwich GIrBIL - dongle. If you want to compile it as a module, say M here and read - . The Greenwich dongle attaches to - the normal 9-pin serial port connector, and can currently only be - used by IrTTY. To activate support for Greenwich dongles you will - have to insert "irattach -d girbil" in the /etc/irda/drivers script. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called girbil.o. - -Parallax LiteLink dongle -CONFIG_LITELINK_DONGLE - Say Y here if you want to build support for the Parallax Litelink - dongle. If you want to compile it as a module, say M here and read - . The Parallax dongle attaches to - the normal 9-pin serial port connector, and can currently only be - used by IrTTY. To activate support for Parallax dongles you will - have to start irattach like this "irattach -d litelink". - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called litelink.o. - -Microchip MCP2120 dongle -CONFIG_MCP2120_DONGLE - Say Y here if you want to build support for the Microchip MCP2120 - dongle. If you want to compile it as a module, say M here and read - . The MCP2120 dongle attaches to - the normal 9-pin serial port connector, and can currently only be - used by IrTTY. To activate support for MCP2120 dongles you will - have to insert "irattach -d mcp2120" in the /etc/irda/drivers script. - - You must build this dongle yourself. For more information see: - - -Old Belkin dongle -CONFIG_OLD_BELKIN_DONGLE - Say Y here if you want to build support for the Adaptec Airport 1000 - and 2000 dongles. If you want to compile it as a module, say M here - and read . The module will be - called old_belkin.o. Some information is contained in the comments - at the top of . - -ACTiSYS IR-200L dongle (Experimental) -CONFIG_ACT200L_DONGLE - Say Y here if you want to build support for the ACTiSYS IR-200L - dongle. If you want to compile it as a module, say M here and read - Documentation/modules.txt. The ACTiSYS IR-200L dongle attaches to - the normal 9-pin serial port connector, and can currently only be - used by IrTTY. To activate support for ACTiSYS IR-200L dongles - you will have to start irattach like this: "irattach -d act200l". - -Mobile Action MA600 dongle (Experimental) -CONFIG_MA600_DONGLE - Say Y here if you want to build support for the Mobile Action MA600 - dongle. If you want to compile it as a module, say M here and read - . The MA600 dongle attaches to - the normal 9-pin serial port connector, and can currently only be - tested on IrCOMM. To activate support for MA600 dongles you will - have to insert "irattach -d ma600" in the /etc/irda/drivers script. - Note: irutils 0.9.15 requires no modification. irutils 0.9.9 needs - modification. For more information, download the following tar gzip - file. - - There is a pre-compiled module on - - -VME (Motorola and BVM) support -CONFIG_VME - Say Y here if you want to build a kernel for a 680x0 based VME - board. Boards currently supported include Motorola boards MVME147, - MVME162, MVME166, MVME167, MVME172, and MVME177. BVME4000 and - BVME6000 boards from BVM Ltd are also supported. - -MVME147 support -CONFIG_MVME147 - Say Y to include support for early Motorola VME boards. This will - build a kernel which can run on MVME147 single-board computers. If - you select this option you will have to select the appropriate - drivers for SCSI, Ethernet and serial ports later on. - -MVME162, 166 and 167 support -CONFIG_MVME16x - Say Y to include support for Motorola VME boards. This will build a - kernel which can run on MVME162, MVME166, MVME167, MVME172, and - MVME177 boards. If you select this option you will have to select - the appropriate drivers for SCSI, Ethernet and serial ports later - on. - -BVME4000 and BVME6000 support -CONFIG_BVME6000 - Say Y to include support for VME boards from BVM Ltd. This will - build a kernel which can run on BVME4000 and BVME6000 boards. If - you select this option you will have to select the appropriate - drivers for SCSI, Ethernet and serial ports later on. - -Use write-through caching for 68060 supervisor accesses -CONFIG_060_WRITETHROUGH - The 68060 generally uses copyback caching of recently accessed data. - Copyback caching means that memory writes will be held in an on-chip - cache and only written back to memory some time later. Saying Y - here will force supervisor (kernel) accesses to use writethrough - caching. Writethrough caching means that data is written to memory - straight away, so that cache and memory data always agree. - Writethrough caching is less efficient, but is needed for some - drivers on 68060 based systems where the 68060 bus snooping signal - is hardwired on. The 53c710 SCSI driver is known to suffer from - this problem. - -WD33C93 SCSI driver for MVME147 -CONFIG_MVME147_SCSI - Support for the on-board SCSI controller on the Motorola MVME147 - single-board computer. - -SCC support for MVME147 serial ports -CONFIG_MVME147_SCC - This is the driver for the serial ports on the Motorola MVME147 - boards. Everyone using one of these boards should say Y here. - -NCR53C710 SCSI driver for MVME16x -CONFIG_MVME16x_SCSI - The Motorola MVME162, 166, 167, 172 and 177 boards use the NCR53C710 - SCSI controller chip. Almost everyone using one of these boards - will want to say Y to this question. - -NCR53C710 SCSI driver for BVME6000 -CONFIG_BVME6000_SCSI - The BVME4000 and BVME6000 boards from BVM Ltd use the NCR53C710 - SCSI controller chip. Almost everyone using one of these boards - will want to say Y to this question. - -MVME147 (Lance) Ethernet support -CONFIG_MVME147_NET - Support for the on-board Ethernet interface on the Motorola MVME147 - single-board computer. Say Y here to include the - driver for this chip in your kernel. If you want to compile it as - a module, say M here and read . - -MVME16x Ethernet support -CONFIG_MVME16x_NET - This is the driver for the Ethernet interface on the Motorola - MVME162, 166, 167, 172 and 177 boards. Say Y here to include the - driver for this chip in your kernel. If you want to compile it as - a module, say M here and read . - -BVME6000 Ethernet support -CONFIG_BVME6000_NET - This is the driver for the Ethernet interface on BVME4000 and - BVME6000 VME boards. Say Y here to include the driver for this chip - in your kernel. If you want to compile it as a module, say M here - and read . - -CD2401 support for MVME166/7 serial ports -CONFIG_SERIAL167 - This is the driver for the serial ports on the Motorola MVME166, - 167, and 172 boards. Everyone using one of these boards should say - Y here. - -SCC support for MVME162 serial ports -CONFIG_MVME162_SCC - This is the driver for the serial ports on the Motorola MVME162 and - 172 boards. Everyone using one of these boards should say Y here. - -SCC support for BVME6000 serial ports -CONFIG_BVME6000_SCC - This is the driver for the serial ports on the BVME4000 and BVME6000 - boards from BVM Ltd. Everyone using one of these boards should say - Y here. - -7-Segment Display support -CONFIG_DISPLAY7SEG - This is the driver for the 7-segment display and LED present on - Sun Microsystems CompactPCI models CP1400 and CP1500. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called display7seg.o. If you want to compile it - as a module, say M here and read . - - If you do not have a CompactPCI model CP1400 or CP1500, or - another UltraSPARC-IIi-cEngine boardset with a 7-segment display, - you should say N to this option. - -# Choice: cristype -Etrax-100-LX-v1 -CONFIG_ETRAX100LX - Support version 1 of the Etrax 100LX. - -Etrax-100-LX-v2 -CONFIG_ETRAX100LX_V2 - Support version 2 of the Etrax 100LX. - -Etrax-100-LX-for-xsim-simulator -CONFIG_SVINTO_SIM - Support the xsim ETRAX Simulator. - -DRAM size (dec, in MB) -CONFIG_ETRAX_DRAM_SIZE - Size of DRAM (decimal in MB) typically 2, 8 or 16. - -ETRAX Flash Memory configuration -CONFIG_ETRAX_FLASH_BUSWIDTH - Width in bytes of the Flash bus (1, 2 or 4). Is usually 2. - -# Choice: crisleds -LED configuration on PA -CONFIG_ETRAX_PA_LEDS - The Etrax network driver is responsible for flashing LED's when - packets arrive and are sent. It uses macros defined in - , and those macros are defined after what - YOU choose in this option. The actual bits used are configured - separately. Select this if the LEDs are on port PA. Some products - put the leds on PB or a memory-mapped latch (CSP0) instead. - -LED configuration on PB -CONFIG_ETRAX_PB_LEDS - The Etrax network driver is responsible for flashing LED's when - packets arrive and are sent. It uses macros defined in - , and those macros are defined after what - YOU choose in this option. The actual bits used are configured - separately. Select this if the LEDs are on port PB. Some products - put the leds on PA or a memory-mapped latch (CSP0) instead. - -LED configuration on CSP0 -CONFIG_ETRAX_CSP0_LEDS - The Etrax network driver is responsible for flashing LED's when - packets arrive and are sent. It uses macros defined in - , and those macros are defined after what - YOU choose in this option. The actual bits used are configured - separately. Select this if the LEDs are on a memory-mapped latch - using chip select CSP0, this is mapped at 0x90000000. - Some products put the leds on PA or PB instead. - -No LED at all -CONFIG_ETRAX_NO_LEDS - Select this option if you don't have any LED at all. - -First green LED bit -CONFIG_ETRAX_LED1G - Bit to use for the first green LED. - Most Axis products use bit 2 here. - -First red LED bit -CONFIG_ETRAX_LED1R - Bit to use for the first red LED. - Most Axis products use bit 3 here. - For products with only one controllable LED, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Second green LED bit -CONFIG_ETRAX_LED2G - Bit to use for the second green LED. The "Active" LED. - Most Axis products use bit 4 here. - For products with only one controllable LED, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Second red LED bit -CONFIG_ETRAX_LED2R - Bit to use for the second red LED. - Most Axis products use bit 5 here. - For products with only one controllable LED, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Third green LED bit -CONFIG_ETRAX_LED3G - Bit to use for the third green LED. The "Drive" LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Third red LED bit -CONFIG_ETRAX_LED3R - Bit to use for the third red LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Fourth green LED bit -CONFIG_ETRAX_LED4G - Bit to use for the fourth green LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Fourth red LED bit -CONFIG_ETRAX_LED4R - Bit to use for the fourth red LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Fifth green LED bit -CONFIG_ETRAX_LED5G - Bit to use for the fifth green LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Fifth red LED bit -CONFIG_ETRAX_LED5R - Bit to use for the fifth red LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Sixth green LED bit -CONFIG_ETRAX_LED6G - Bit to use for the sixth green LED. The "Drive" LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Sixth red LED bit -CONFIG_ETRAX_LED6R - Bit to use for the sixth red LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Seventh green LED bit -CONFIG_ETRAX_LED7G - Bit to use for the seventh green LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Seventh red LED bit -CONFIG_ETRAX_LED7R - Bit to use for the seventh red LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Eighth yellow LED bit -CONFIG_ETRAX_LED8Y - Bit to use for the eighth yellow LED. The "Drive" LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Ninth yellow LED bit -CONFIG_ETRAX_LED9Y - Bit to use for the ninth yellow LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Tenth yellow LED bit -CONFIG_ETRAX_LED10Y - Bit to use for the tenth yellow LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Eleventh yellow LED bit -CONFIG_ETRAX_LED11Y - Bit to use for the eleventh yellow LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Twelfth red LED bit -CONFIG_ETRAX_LED12R - Bit to use for the twelfth red LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -Flash LED off during activity -CONFIG_ETRAX_LED_OFF_DURING_ACTIVITY - This option allows you to decide whether the network LED (and - Bluetooth LED in case you use Bluetooth) will be on or off when - the network is connected, and whether it should flash off or on - when there is activity. If you say y to this option the network - LED will be lit when there is a connection, and will flash off - when there is activity. - -PA button configuration -CONFIG_ETRAX_PA_BUTTON_BITMASK - This is a bitmask with information about what bits on PA that - are used for buttons. - Most products has a so called TEST button on PA1, if that's true - use 02 here. - Use 00 if there are no buttons on PA. - If the bitmask is <> 00 a button driver will be included in the gpio - driver. Etrax general I/O support must be enabled. - -PA changeable direction bits -CONFIG_ETRAX_PA_CHANGEABLE_DIR - This is a bitmask with information of what bits in PA that a user - can change direction on using ioctl's. - Bit set = changeable. - You probably want 00 here. - -PA changeable data bits -CONFIG_ETRAX_PA_CHANGEABLE_BITS - This is a bitmask with information of what bits in PA that a user - can change change the value on using ioctl's. - Bit set = changeable. - You probably want 00 here. - -PA changeable direction bits -CONFIG_ETRAX_PB_CHANGEABLE_DIR - This is a bitmask with information of what bits in PB that a user - can change direction on using ioctl's. - Bit set = changeable. - You probably want 00 here. - -PB changeable data bits -CONFIG_ETRAX_PB_CHANGEABLE_BITS - This is a bitmask with information of what bits in PB that a user - can change the value on using ioctl's. - Bit set = changeable. - You probably want 00 here. - -Kernel debugger (kgdb) -CONFIG_ETRAX_KGDB - The CRIS version of gdb can be used to remotely debug a running - Linux kernel via the serial debug port. Provided you have gdb-cris - installed, run gdb-cris vmlinux, then type - - (gdb) set remotebaud 115200 <- kgdb uses 115200 as default - (gdb) target remote /dev/ttyS0 <- maybe you use another port - - This should connect you to your booted kernel (or boot it now if you - didn't before). The kernel halts when it boots, waiting for gdb if - this option is turned on! - -Etrax bus waitstates -CONFIG_ETRAX_DEF_R_WAITSTATES - Waitstates for SRAM, Flash and peripherals (not DRAM). 95f8 is a - good choice for most Axis products... - -Etrax bus configuration -CONFIG_ETRAX_DEF_R_BUS_CONFIG - Assorted bits controlling write mode, DMA burst length etc. 104 is - a good choice for most Axis products... - -Etrax SDRAM configuration -CONFIG_ETRAX_SDRAM - Enable this if you use SDRAM chips and configure - R_SDRAM_CONFIG and R_SDRAM_TIMING as well. - -DRAM size (dec, in MB) -CONFIG_ETRAX_DEF_R_DRAM_CONFIG - The R_DRAM_CONFIG register specifies everything on how the DRAM - chips in the system are connected to the Etrax CPU. This is - different depending on the manufacturer, chip type and number of - chips. So this value often needs to be different for each Axis - product. - -Etrax DRAM timing -CONFIG_ETRAX_DEF_R_DRAM_TIMING - Different DRAM chips have different speeds. Current Axis products - use 50ns DRAM chips which can use the timing: 5611. - -Etrax SDRAM configuration -CONFIG_ETRAX_DEF_R_SDRAM_CONFIG - The R_SDRAM_CONFIG register specifies everything on how the SDRAM - chips in the system are connected to the Etrax CPU. This is - different depending on the manufacturer, chip type and number of - chips. So this value often needs to be different for each Axis - product. - -Etrax SDRAM timing -CONFIG_ETRAX_DEF_R_SDRAM_TIMING - Different SDRAM chips have different timing. - -Etrax General port A direction -CONFIG_ETRAX_DEF_R_PORT_PA_DIR - Configures the direction of general port A bits. 1 is out, 0 is in. - This is often totally different depending on the product used. - There are some guidelines though - if you know that only LED's are - connected to port PA, then they are usually connected to bits 2-4 - and you can therefore use 1c. On other boards which don't have the - LED's at the general ports, these bits are used for all kinds of - stuff. If you don't know what to use, it is always safe to put all - as inputs, although floating inputs isn't good. - -Etrax General port A data -CONFIG_ETRAX_DEF_R_PORT_PA_DATA - Configures the initial data for the general port A bits. Most - products should use 00 here. - -Etrax General port B config -CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG - Configures the type of the general port B bits. 1 is chip select, - 0 is port. Most products should use 00 here. - -Etrax General port B direction -CONFIG_ETRAX_DEF_R_PORT_PB_DIR - Configures the direction of general port B bits. 1 is out, 0 is in. - This is often totally different depending on the product used. Bits - 0 and 1 on port PB are usually used for I2C communication, but the - kernel I2C driver sets the appropriate directions itself so you - don't need to take that into consideration when setting this option. - If you don't know what to use, it is always safe to put all as - inputs. - -Etrax General port B data -CONFIG_ETRAX_DEF_R_PORT_PB_DATA - Configures the initial data for the general port A bits. Most - products should use FF here. - -Etrax General port device -CONFIG_ETRAX_GPIO - Enables the Etrax general port device (major 120, minors 0 and 1). - You can use this driver to access the general port bits. It supports - these ioctl's: - #include - fd = open("/dev/gpioa", O_RDWR); // or /dev/gpiob - ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS), bits_to_set); - ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS), bits_to_clear); - val = ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_READBITS), NULL); - Remember that you need to setup the port directions appropriately in - the General configuration. - -Etrax parallel data support -CONFIG_ETRAX_PARDATA - Adds support for writing data to the parallel port par0 of the ETRAX - 100. If you create a character special file with major number 126, - you can write to the data bits of par0. - Note: you need to disable Etrax100 parallel port support. - -Etrax parallel LCD (HD44780) Driver -CONFIG_ETRAX_LCD_HD44780 - Adds support for a HD44780 controlled LCD connected to the parallel - port par0 of the Etrax. - -Etrax Serial port ser0 support -CONFIG_ETRAX_SERIAL - Enables the ETRAX 100 serial driver for ser0 (ttyS0) - You probably want this enabled. - -/proc/serial entry -CONFIG_ETRAX_SERIAL_PROC_ENTRY - Enables /proc/serial entry where errors and statistics can be - viewed. CONFIG_PROC_FS must also be set for this to work. - -Etrax Serial port fast flush of DMA using fast timer API -CONFIG_ETRAX_SERIAL_FAST_TIMER - Select this to have the serial DMAs flushed at a higher rate than - normally, possible by using the fast timer API, the timeout is - approx. 4 character times. - If unsure, say N. - -Etrax Serial port fast flush of DMA -CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST - Select this to have the serial DMAs flushed at a higher rate than - normally possible through a fast timer interrupt (currently at - 15360 Hz). - If unsure, say N. - -Etrax Serial port receive flush timeout -CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS - Number of timer ticks between flush of receive fifo (1 tick = 10ms). - Try 0-3 for low latency applications. Approx 5 for high load - applications (e.g. PPP). Maybe this should be more adaptive some - day... - -Etrax Serial port ser0 DTR, RI, DSR and CD support on PB -CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PB - Enables the status and control signals DTR, RI, DSR and CD on PB for - ser0. - -Serial port 1 enabled -CONFIG_ETRAX_SERIAL_PORT1 - Enables the ETRAX 100 serial driver for ser1 (ttyS1). - -Etrax Serial port ser1 DTR, RI, DSR and CD support on PB -CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_ON_PB - Enables the status and control signals DTR, RI, DSR and CD on PB for - ser1. - -Serial port 2 enabled -CONFIG_ETRAX_SERIAL_PORT2 - Enables the ETRAX 100 serial driver for ser2 (ttyS2). - -Etrax Serial port ser2 DTR, RI, DSR and CD support on PA -CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_PA - Enables the status and control signals DTR, RI, DSR and CD on PA for - ser2. - -Serial port 3 enabled -CONFIG_ETRAX_SERIAL_PORT3 - Enables the ETRAX 100 serial driver for ser3 (ttyS3). - -Etrax100 RS-485 support -CONFIG_ETRAX_RS485 - Enables support for RS-485 serial communication. For a primer on - RS-485, see . - -Etrax100 RS-485 mode on PA -CONFIG_ETRAX_RS485_ON_PA - Control Driver Output Enable on RS485 transceiver using a pin on PA - port: - Axis 2400/2401 uses PA 3. - -Etrax100 RS-485 mode on PA bit -CONFIG_ETRAX_RS485_ON_PA_BIT - Control Driver Output Enable on RS485 transceiver using a this bit - on PA port. - -Ser0 DTR on PB bit -CONFIG_ETRAX_SER0_DTR_ON_PB_BIT - Specify the pin of the PB port to carry the DTR signal for serial - port 0. - -Ser0 RI on PB bit -CONFIG_ETRAX_SER0_RI_ON_PB_BIT - Specify the pin of the PB port to carry the RI signal for serial - port 0. - -Ser0 DSR on PB bit -CONFIG_ETRAX_SER0_DSR_ON_PB_BIT - Specify the pin of the PB port to carry the DSR signal for serial - port 0. - -Ser0 CD on PB bit -CONFIG_ETRAX_SER0_CD_ON_PB_BIT - Specify the pin of the PB port to carry the CD signal for serial - port 0. - -Ser1 DTR on PB bit -CONFIG_ETRAX_SER1_DTR_ON_PB_BIT - Specify the pin of the PB port to carry the DTR signal for serial - port 1. - -Ser1 RI on PB bit -CONFIG_ETRAX_SER1_RI_ON_PB_BIT - Specify the pin of the PB port to carry the RI signal for serial - port 1. - -Ser1 DSR on PB bit -CONFIG_ETRAX_SER1_DSR_ON_PB_BIT - Specify the pin of the PB port to carry the DSR signal for serial - port 1. - -Ser1 CD on PB bit -CONFIG_ETRAX_SER1_CD_ON_PB_BIT - Specify the pin of the PB port to carry the CD signal for serial - port 1. - -Ser2 DTR on PA bit -CONFIG_ETRAX_SER2_DTR_ON_PA_BIT - Specify the pin of the PA port to carry the DTR signal for serial - port 2. - -Ser2 RI on PA bit -CONFIG_ETRAX_SER2_RI_ON_PA_BIT - Specify the pin of the PA port to carry the RI signal for serial - port 2. - -Ser2 DSR on PA bit -CONFIG_ETRAX_SER2_DSR_ON_PA_BIT - Specify the pin of the PA port to carry the DTR signal for serial - port 2. - -Ser2 CD on PA bit -CONFIG_ETRAX_SER2_CD_ON_PA_BIT - Specify the pin of the PA port to carry the CD signal for serial - port 2. - -Etrax100 RS-485 disable receiver -CONFIG_ETRAX_RS485_DISABLE_RECEIVER - It's necessary to disable the serial receiver to avoid serial - loopback. Not all products are able to do this in software only. - Axis 2400/2401 must disable receiver. - -Etrax100 I2C Support -CONFIG_ETRAX_I2C - Enables an I2C driver on PB0 and PB1 on ETRAX100. - EXAMPLE usage: - i2c_arg = I2C_WRITEARG(STA013_WRITE_ADDR, reg, val); - ioctl(fd, _IO(ETRAXI2C_IOCTYPE, I2C_WRITEREG), i2c_arg); - i2c_arg = I2C_READARG(STA013_READ_ADDR, reg); - val = ioctl(fd, _IO(ETRAXI2C_IOCTYPE, I2C_READREG), i2c_arg); - -Etrax100 I2C configuration -CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C - Select whether to use the special I2C mode in the PB I/O register or - not. This option needs to be selected in order to use some drivers - that access the I2C I/O pins directly instead of going through the - I2C driver, like the DS1302 realtime-clock driver. If you are - uncertain, choose Y here. - -Etrax100 I2C EEPROM (NVRAM) support -CONFIG_ETRAX_I2C_EEPROM - Enables I2C EEPROM (non-volatile RAM) on PB0 and PB1 using the I2C - driver. Select size option: Probed, 2k, 8k, 16k. - (Probing works for 2k and 8k but not that well for 16k) - -Etrax100 I2C EEPROM (NVRAM) size/16kB -CONFIG_ETRAX_I2C_EEPROM_16KB - Use a 16kB EEPROM. - -Etrax100 I2C EEPROM (NVRAM) size/2kB -CONFIG_ETRAX_I2C_EEPROM_2KB - Use a 2kB EEPROM. - -Etrax100 I2C EEPROM (NVRAM) size/8kB -CONFIG_ETRAX_I2C_EEPROM_8KB - Use a 8kB EEPROM. - -# Choice: etrax_eeprom -Etrax100 I2C EEPROM (NVRAM) size/probe -CONFIG_ETRAX_I2C_EEPROM_PROBE - Specifies size or auto probe of the EEPROM size. - Options: Probed, 2k, 8k, 16k. - (Probing works for 2k and 8k but not that well for 16k) - -Etrax DS1302 Real-Time Clock driver -CONFIG_ETRAX_DS1302 - Enables the driver for the DS1302 Real-Time Clock battery-backed - chip on some products. The kernel reads the time when booting, and - the date can be set using ioctl(fd, RTC_SET_TIME, &rt) with rt a - rtc_time struct (see ) on the /dev/rtc - device, major 121. You can check the time with cat /proc/rtc, but - normal time reading should be done using libc function time and - friends. - -Etrax DS1302 RST on the Generic Port -CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT - If your product has the RST signal line for the DS1302 RTC on the - Generic Port then say Y here, otherwise leave it as N in which - case the RST signal line is assumed to be connected to Port PB - (just like the SCL and SDA lines). - -Etrax DS1302 RST bit number -CONFIG_ETRAX_DS1302_RSTBIT - This is the bit number for the RST signal line of the DS1302 RTC on - the selected port. If you have selected the generic port then it - should be bit 27, otherwise your best bet is bit 5. - -Etrax DS1302 SCL bit number -CONFIG_ETRAX_DS1302_SCLBIT - This is the bit number for the SCL signal line of the DS1302 RTC on - Port PB. This is probably best left at 3. - -Etrax DS1302 SDA bit number -CONFIG_ETRAX_DS1302_SDABIT - This is the bit number for the SDA signal line of the DS1302 RTC on - Port PB. This is probably best left at 2. - -Etrax 100 IDE Reset -CONFIG_ETRAX_IDE_CSP0_8_RESET - Configures the pin used to reset the IDE bus. - -Etrax 100 IDE Reset -CONFIG_ETRAX_IDE_CSPE1_16_RESET - Configures the pin used to reset the IDE bus. - -Delay for drives to regain consciousness -CONFIG_ETRAX_IDE_DELAY - Sets the time to wait for disks to regain consciousness after reset. - -Etrax 100 IDE Reset -CONFIG_ETRAX_IDE_G27_RESET - Configures the pin used to reset the IDE bus. - -# Choice: ide_reset -IDE reset on PB Bit 7 -CONFIG_ETRAX_IDE_PB7_RESET - Configures the pin used to reset the IDE bus. - -USB 1.1 host -CONFIG_ETRAX_USB_HOST - This option enables the host functionality of the ETRAX 100LX - built-in USB controller. In host mode the controller is designed - for CTRL and BULK traffic only, INTR traffic may work as well - however (depending on the requirements of timeliness). - -USB 1.1 host port 1 enabled -CONFIG_ETRAX_USB_HOST_PORT1 - This option enables port 1 of the ETRAX 100LX USB root hub (RH). - -USB 1.1 host port 2 enabled -CONFIG_ETRAX_USB_HOST_PORT2 - This option enables port 2 of the ETRAX 100LX USB root hub (RH). - -ETRAX 100LX 10/100Mbit Ethernet controller -CONFIG_ETRAX_ETHERNET - This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet - controller. - -ETRAX 100LX Synchronous serial ports -CONFIG_ETRAX_SYNCHRONOUS_SERIAL - This option enables support for the ETRAX 100LX built-in - synchronous serial ports. These ports are used for continuous - streamed data like audio. The default setting is compatible - with the STA 013 MP3 decoder, but can easily be tuned to fit - any other audio encoder/decoder and SPI. - -ETRAX 100LX Synchronous serial port 0 enabled -CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0 - Enables the ETRAX 100LX synchronous serial port 0 (syncser0). - -ETRAX 100LX Synchronous serial port 0 uses DMA -CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA - Makes synchronous serial port 0 use DMA. - -ETRAX 100LX Synchronous serial port 1 enabled -CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1 - Enables the ETRAX 100LX synchronous serial port 1 (syncser1). - -ETRAX 100LX Synchronous serial port 1 uses DMA -CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA - Makes synchronous serial port 1 use DMA. - -Delay for drives to regain consciousness -CONFIG_IDE_DELAY - Number of seconds to wait for IDE drives to spin up after an IDE - reset. - -ARTPEC-1 support -CONFIG_JULIETTE - The ARTPEC-1 is a video-compression chip used in the AXIS 2100 - network camera, which is built around an ETRAX-100 board. With this - option selected, the ETRAX kernel configures a DMA channel at boot - time to talk to the chip. - -Axis flash-map support -CONFIG_ETRAX_AXISFLASHMAP - This option enables MTD mapping of flash devices. Needed to use - flash memories. If unsure, say Y. - -Byte-offset of partition table sector -CONFIG_ETRAX_PTABLE_SECTOR - Byte-offset of the partition table in the first flash chip. - The default value is 64kB and should not be changed unless - you know exactly what you are doing. The only valid reason - for changing this is when the flash block size is bigger - than 64kB (e.g. when using two parallel 16 bit flashes). - -Enable Etrax100 watchdog -CONFIG_ETRAX_WATCHDOG - Enable the built-in watchdog timer support on Etrax100 embedded - network computers. - -# Choice: crisdebug -Serial-0 -CONFIG_ETRAX_DEBUG_PORT0 - Choose a serial port for the ETRAX debug console. Default to - port 0. - -Etrax debug port on ser1 -CONFIG_ETRAX_DEBUG_PORT1 - Use serial port 1 for the console. - -Etrax debug port on ser2 -CONFIG_ETRAX_DEBUG_PORT2 - Use serial port 2 for the console. - -Etrax debug port on ser3 -CONFIG_ETRAX_DEBUG_PORT3 - Use serial port 3 for the console. - -No Etrax debug port -CONFIG_ETRAX_DEBUG_PORT_NULL - Disable serial-port debugging. - -Parallel port support -CONFIG_ETRAX_PARPORT - Say Y here to enable the ETRAX on-board parallel ports. - -Parallel port 0 enabled -CONFIG_ETRAX_PARALLEL_PORT0 - Say Y here to enable parallel port 0. - -Parallel port 1 enabled -CONFIG_ETRAX_PARALLEL_PORT1 - Say Y here to enable parallel port 1. - -# Choice: crisrescue -Select a product rescue port -CONFIG_ETRAX_RESCUE_SER0 - Select one of the four serial ports as a rescue port. The default - is port 0. - -Serial-1 -CONFIG_ETRAX_RESCUE_SER1 - Use serial port 1 as the rescue port. - -Serial-2 -CONFIG_ETRAX_RESCUE_SER2 - Use serial port 2 as the rescue port. - -Serial-3 -CONFIG_ETRAX_RESCUE_SER3 - Use serial port 3 as the rescue port. - -RIO Hardware Watchdog support -CONFIG_WATCHDOG_RIO - Say Y here to support the hardware watchdog capability on Sun RIO - machines. The watchdog timeout period is normally one minute but - can be changed with a boot-time parameter. - -CP1XXX Hardware Watchdog support -CONFIG_WATCHDOG_CP1XXX - This is the driver for the hardware watchdog timers present on - Sun Microsystems CompactPCI models CP1400 and CP1500. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cpwatchdog.o. If you want to compile it - as a module, say M here and read . - - If you do not have a CompactPCI model CP1400 or CP1500, or - another UltraSPARC-IIi-cEngine boardset with hardware watchdog, - you should say N to this option. - -# Choice: ia64type -Itanium -CONFIG_ITANIUM - Select your IA-64 processor type. The default is Intel Itanium. - This choice is safe for all IA-64 systems, but may not perform - optimally on systems with, say, Itanium 2 or newer processors. - -Itanium 2 -CONFIG_MCKINLEY - Select this to configure for an Itanium 2 (McKinley) processor. - -# Choice: ia64system -IA-64 system type -CONFIG_IA64_GENERIC - This selects the system type of your hardware. A "generic" kernel - will run on any supported IA-64 system. However, if you configure - a kernel for your specific system, it will be faster and smaller. - - generic For any supported IA-64 system - DIG-compliant For DIG ("Developer's Interface Guide") compliant systems - HP For HP systems - SGI-SN2 For SGI SN2 systems - Ski-simulator For the HP simulator () - - If you don't know what to do, choose "generic". - -CONFIG_IA64_HP_ZX1 - Build a kernel that runs on HP zx1-based systems. This adds support - for the zx1 IOMMU and makes root bus bridges appear in PCI config space - (required for zx1 agpgart support). - -# Choice: pagesize -Kernel page size -CONFIG_IA64_PAGE_SIZE_4KB - This lets you select the page size of the kernel. For best IA-64 - performance, a page size of 8KB or 16KB is recommended. For best - IA-32 compatibility, a page size of 4KB should be selected (the vast - majority of IA-32 binaries work perfectly fine with a larger page - size). For Itanium systems, do NOT chose a page size larger than - 16KB. - - 4KB For best IA-32 compatibility - 8KB For best IA-64 performance - 16KB For best IA-64 performance - 64KB Not for Itanium. - - If you don't know what to do, choose 8KB. - -Enable Itanium B-step specific code -CONFIG_ITANIUM_BSTEP_SPECIFIC - Select this option to build a kernel for an Itanium prototype system - with a B-step CPU. Only B3 step CPUs are supported. You have a B3-step - CPU if the "revision" field in /proc/cpuinfo is equal to 4. If the - "revision" field shows a number bigger than 4, you do not have to turn - on this option. - -Enable IA-64 Machine Check Abort -CONFIG_IA64_MCA - Say Y here to enable machine check support for IA-64. If you're - unsure, answer Y. - -Use PAL_HALT_LIGHT in idle loop -CONFIG_IA64_PAL_IDLE - Say Y here to enable use of PAL_HALT_LIGHT in the cpu_idle loop. - This allows the CPU to enter a low power state when idle. You - can enable CONFIG_IA64_PALINFO and check /proc/pal/cpu0/power_info - to see the power consumption and latency for this state. If you're - unsure your firmware supports it, answer N. - -Disable IA-64 Virtual Hash Page Table -CONFIG_DISABLE_VHPT - The Virtual Hash Page Table (VHPT) enhances virtual address - translation performance. Normally you want the VHPT active but you - can select this option to disable the VHPT for debugging. If you're - unsure, answer N. - -Turn on compare-and-exchange bug checking (slow!) -CONFIG_IA64_DEBUG_CMPXCHG - Selecting this option turns on bug checking for the IA64 - compare-and-exchange instructions. This is slow! Itaniums - from step B3 or later don't have this problem. If you're unsure, - select N. - -IA64 IRQ bug checking -CONFIG_IA64_DEBUG_IRQ - Selecting this option turns on bug checking for the IA64 irq_save - and restore instructions. It's useful for tracking down spinlock - problems, but slow! If you're unsure, select N. - -Early printk support -CONFIG_IA64_EARLY_PRINTK - Selecting this option uses a UART or VGA screen (or both) for - printk() output before the consoles are initialised. It is useful - for debugging problems early in the boot process, but only if you - have a serial terminal or a VGA screen attached. If you're unsure, - select N. - -Early printk on serial port -CONFIG_IA64_EARLY_PRINTK_UART - Select this option to use a serial port for early printk() output. - You must also select either CONFIG_IA64_EARLY_PRINTK_UART_BASE or - CONFIG_SERIAL_HCDP. If you select CONFIG_SERIAL_HCDP, early - printk() output will appear on the first console device described by - the HCDP. If you set CONFIG_IA64_EARLY_PRINTK_UART_BASE, the HCDP - will be ignored. - -UART base address -CONFIG_IA64_EARLY_PRINTK_UART_BASE - The physical MMIO address of the UART to use for early printk(). - This overrides any UART located using the EFI HCDP table. - -Early printk on VGA -CONFIG_IA64_EARLY_PRINTK_VGA - Select this option to use VGA for early printk() output. - -Print possible IA64 hazards to console -CONFIG_IA64_PRINT_HAZARDS - Selecting this option prints more information for Illegal Dependency - Faults, that is, for Read after Write, Write after Write or Write - after Read violations. If you're unsure, select Y. - -Performance monitor support -CONFIG_PERFMON - Selects whether support for the IA-64 performance monitor hardware - is included in the kernel. This makes some kernel data-structures a - little bigger and slows down execution a bit, but it is still - usually a good idea to turn this on. If you're unsure, say N. - -/proc/pal support -CONFIG_IA64_PALINFO - If you say Y here, you are able to get PAL (Processor Abstraction - Layer) information in /proc/pal. This contains useful information - about the processors in your systems, such as cache and TLB sizes - and the PAL firmware version in use. - - To use this option, you have to check that the "/proc file system - support" (CONFIG_PROC_FS) is enabled, too. - -PPC4xx DMA controller support -CONFIG_PPC4xx_DMA - Select this to enable support for the PPC4xx general purpose DMA - controller. - -ttyS0 device -CONFIG_UART0_TTYS0 - This option reverses the mapping between the hardware UART and software - device. Selecting UART0 gives the normal mapping of UART0=ttyS0 and - UART1=ttyS1. Selecting UART1 gives the reverse mapping of UART0=ttyS1 - and UART1=ttyS0. Most people will use UART0. - -PowerPC 405 on-chip ethernet -CONFIG_IBM_OCP_ENET - If you want to use the 405 built-in ethernet select this. - -CONFIG_IBM_OCP_ENET_ERROR_MSG - Enable this option to print verbose debug messages for troubleshooting. - -PowerPC 405 on-chip ethernet -- Number of receive buffers -CONFIG_IBM_OCP_ENET_RX_BUFF - Number of ethernet receive (read) buffers. Unless you know what you - are doing the default should be fine. - -PowerPC 405 on-chip ethernet -- Number of transmit buffers -CONFIG_IBM_OCP_ENET_TX_BUFF - Number of ethernet transmit (write) buffers. Unless you know what - you are doing the default should be fine. - -PowerPC 405 on-chip ethernet -- Amount of bytes to Reserve on a skb -CONFIG_IBM_OCP_ENET_SKB_RES - Many standard ethernet drivers need to reserve 2 bytes of data - on the skb before giving the data ptr to the hardware. This is - so the IP data will be 16-byte aligned when it goes up the stack. - This is a requirement for some processors and it can cause major - slow downs on others. The 405GP dose not have problems with the - misaligned data so the default is 0. If you need to route the - incoming ethernet packets to another device that has alignment - requirements this can help remove a data copy. A value of 2 can - help at getting 16-byte aligned IP data for another device. A - larger value can be used when routing to a IP tunnel device. - Make sure XXX_DESC_SIZE - XXX_SKB_RES >= 1514, or larger if VLANS - are used. - -PPC 405 I2C Algorithm -CONFIG_PPC405_I2C_ALGO - Enable this option to use the built-in I2C on your 405. - -PPC 405 I2C Adapter -CONFIG_PPC405_I2C_ADAP - Enable this option to use the built-in I2C on your 405. - -/proc/efi/vars support -CONFIG_EFI_VARS - If you say Y here, you are able to get EFI (Extensible Firmware - Interface) variable information in /proc/efi/vars. You may read, - write, create, and destroy EFI variables through this interface. - - To use this option, you have to check that the "/proc file system - support" (CONFIG_PROC_FS) is enabled, too. - -Kernel support for IA-32 emulation -CONFIG_IA32_SUPPORT - IA64 processors can run IA32 (that is, x86) binaries by emulating - the IA32 instruction set. Say Y here to build in kernel support for - this. If in doubt, say Y. - -Physical memory granularity (16 MB) -CONFIG_IA64_GRANULE_16MB - IA64 identity-mapped regions use a large page size. We'll call such - large pages "granules". If you can think of a better name that's - unambiguous, let us know... Unless your identity-mapped regions are - very large, select a granule size of 16MB. - -Physical memory granularity (64 MB) -CONFIG_IA64_GRANULE_64MB - IA64 identity-mapped regions use a large page size. We'll call such - large pages "granules". If you can think of a better name that's - unambiguous, let us know... Unless your identity-mapped regions are - very large, select a granule size of 16MB. (This is the "large" choice.) - -Enable SGI SN extra debugging code -CONFIG_IA64_SGI_SN_DEBUG - Turns on extra debugging code in the SGI SN (Scalable NUMA) platform - for IA64. Unless you are debugging problems on an SGI SN IA64 box, - say N. - -Enable SGI Medusa Simulator Support -CONFIG_IA64_SGI_SN_SIM - If you are compiling a kernel that will run under SGI's IA64 - simulator (Medusa) then say Y, otherwise say N. - -PCIBA Support -CONFIG_PCIBA - IRIX PCIBA-inspired user mode PCI interface for the SGI SN (Scalable - NUMA) platform for IA64. Unless you are compiling a kernel for an SGI SN IA64 box, say N. - -Enable protocol mode for the L1 console -SERIAL_SGI_L1_PROTOCOL - Uses protocol mode instead of raw mode for the level 1 console on the - SGI SN (Scalable NUMA) platform for IA64. If you are compiling for - an SGI SN box then Y is the recommended value, otherwise say N. - -Directly Connected Compact Flash support -CONFIG_CF_ENABLER - Compact Flash is a small, removable mass storage device introduced - in 1994 originally as a PCMCIA device. If you say `Y' here, you - compile in support for Compact Flash devices directly connected to - a SuperH processor. A Compact Flash FAQ is available at - . - - If your board has "Directly Connected" CompactFlash at area 5 or 6, - you may want to enable this option. Then, you can use CF as - primary IDE drive (only tested for SanDisk). - - If in doubt, select 'N'. - -Kernel debugging -CONFIG_DEBUG_KERNEL - Say Y here if you are developing drivers or trying to debug and - identify kernel problems. - -Debug memory allocations -CONFIG_DEBUG_SLAB - Say Y here to have the kernel do limited verification on memory - allocation as well as poisoning memory on free to catch use of freed - memory. - -Memory mapped I/O debugging -CONFIG_DEBUG_IOVIRT - Say Y here to get warned whenever an attempt is made to do I/O on - obviously invalid addresses such as those generated when ioremap() - calls are forgotten. Memory mapped I/O will go through an extra - check to catch access to unmapped ISA addresses, an access method - that can still be used by old drivers that are being ported from - 2.0/2.2. - -Spinlock debugging -CONFIG_DEBUG_SPINLOCK - Say Y here and build SMP to catch missing spinlock initialization - and certain other kinds of spinlock errors commonly made. This is - best used in conjunction with the NMI watchdog so that spinlock - deadlocks are also debuggable. - -Additional run-time checks -CONFIG_CHECKING - Enables some internal consistency checks for kernel debugging. - You should normally say N. - -Read-write spinlock debugging -CONFIG_DEBUG_RWLOCK - If you say Y here then read-write lock processing will count how many - times it has tried to get the lock and issue an error message after - too many attempts. If you suspect a rwlock problem or a kernel - hacker asks for this option then say Y. Otherwise say N. - -Semaphore debugging -CONFIG_DEBUG_SEMAPHORE - If you say Y here then semaphore processing will issue lots of - verbose debugging messages. If you suspect a semaphore problem or a - kernel hacker asks for this option then say Y. Otherwise say N. - -Verbose BUG() reporting (adds 70K) -CONFIG_DEBUG_BUGVERBOSE - Say Y here to make BUG() panics output the file name and line number - of the BUG call as well as the EIP and oops trace. This aids - debugging but costs about 70-100K of memory. - -Include kgdb kernel debugger -CONFIG_KGDB - Include in-kernel hooks for kgdb, the Linux kernel source level - debugger. For i386 architecture there is project page at - . - -Include xmon kernel debugger -CONFIG_XMON - Include in-kernel hooks for the xmon kernel monitor/debugger - supported by the PPC port. - -Include BDI2000 debugger support -CONFIG_BDI_SWITCH - Include in-kernel support for the Abatron BDI2000 debugger. To - learn more about the Abatron BDI2000, visit the web page at - . - -Add additional CFLAGS to the kernel build -CONFIG_MORE_COMPILE_OPTIONS - If you want to add additional CFLAGS to the kernel build, such as - -g for KGDB, XMON or the BDI2000, enable this option and then - enter what you would like to add in the next question. - -Include kgdb kernel debugger -CONFIG_KWDB - Include in-kernel hooks for kdb, the source level debugger for the - PA-RISC port. - -IODC console -CONFIG_IODC_CONSOLE - IODC is HP's pre-PCI standard for device identification (a la PCI - vendor, device IDs), detection, configuration, initialization and so - on. It also can provide firmware function to do the actual IO, - which are slow, not really defined for runtime usage and generally - not desirable. - - See - for the gory details. - - Say Y here to enable use of the IODC firmware functions for console - I/O. This is only useful on older PA-RISC workstations. If in - doubt, say Y. - -U2/Uturn I/O MMU -CONFIG_IOMMU_CCIO - Say Y here to enable DMA management routines for the first - generation of PA-RISC cache-coherent machines. Programs the - U2/Uturn chip in "Virtual Mode" and use the I/O MMU. - -LBA/Elroy PCI support -CONFIG_PCI_LBA - Say Y here to give the PA-RISC kernel access to PCI configuration - and IO-port space on PA-RISC workstations equipped with a Lower Bus - Adapter (LBA). This includes A, B, C, J, L, and N-class machines - with 4-digit model numbers, also the A300. - -LASI I/O support -CONFIG_GSC_LASI - Say Y here to directly support the LASI controller chip found on - PA-RISC workstations. Linux-oriented documentation for this chip - can be found at . - -LASI/ASP builtin parallel-port -CONFIG_PARPORT_GSC - Say Y here to build in low-level parallel-support for PC-style - hardware integrated in the LASI-Controller (on the GSC Bus) for - HP-PARISC workstations. - -Fujitsu Vendor Specific -CONFIG_BLK_DEV_IDEDISK_FUJITSU - Enable vendor-specific code for Fujitsu IDE disks. Unless you are - the IDE maintainer, you probably do not want to mess with this. - -IBM Vendor Specific -CONFIG_BLK_DEV_IDEDISK_IBM - Enable vendor-specific code for IBM IDE disks. Unless you are the - IDE maintainer, you probably do not want to mess with this. - -Maxtor Vendor Specific -CONFIG_BLK_DEV_IDEDISK_MAXTOR - Enable vendor-specific code for Maxtor IDE disks. Unless you are - the IDE maintainer, you probably do not want to mess with this. - -Quantum Vendor Specific -CONFIG_BLK_DEV_IDEDISK_QUANTUM - Enable vendor-specific code for Quantum IDE disks. Unless you are - the IDE maintainer, you probably do not want to mess with this. - -Seagate Vendor Specific -CONFIG_BLK_DEV_IDEDISK_SEAGATE - Enable vendor-specific code for Seagate IDE disks. Unless you are - the IDE maintainer, you probably do not want to mess with this. - -Western Digital Vendor Specific -CONFIG_BLK_DEV_IDEDISK_WD - Enable vendor-specific code for Western Digital IDE disks. Unless - you are the IDE maintainer, you probably do not want to mess with - this. - -TiVo Commerial Application Specific -CONFIG_BLK_DEV_TIVO - Enable vendor-specific code for TiVo IDE disks. Unless you are the - IDE maintainer, you probably do not want to mess with this. - -# Choice: superhsys -Generic -CONFIG_SH_GENERIC - Select Generic if configuring for a generic SuperH system. - The "generic" option compiles in *all* the possible hardware - support and relies on the sh_mv= kernel command option to choose - at runtime which routines to use. "MV" stands for "machine vector"; - each of the machines below is described by a machine vector. - - Select SolutionEngine if configuring for a Hitachi SH7709 - or SH7750/7750S evaluation board. - - Select SHMobileSolutionEngine if configuring for SH-Mobile Solution - Engine. - - Select Overdrive if configuring for a ST407750 Overdrive board. - More information at - . - - Select HP620 if configuring for a HP Jornada HP620. - More information (hardware only) at - . - - Select HP680 if configuring for a HP Jornada HP680. - More information (hardware only) at - . - - Select HP690 if configuring for a HP Jornada HP690. - More information (hardware only) at - . - - Select CqREEK if configuring for a CqREEK SH7708 or SH7750. - More information at - . - - Select DMIDA if configuring for a DataMyte 4000 Industrial - Digital Assistant. More information at . - - Select EC3104 if configuring for a system with an Eclipse - International EC3104 chip, e.g. the Harris AD2000 or Compaq Aero 8000. - - Select Dreamcast if configuring for a SEGA Dreamcast. - More information at - . There is a - Dreamcast project is at . - - Select BareCPU if you know what this means, and it applies - to your system. - -# These may have to be merged in when we go to CML2: -# - "SolutionEngine7751" for Hitachi SolutionEngine (7751) -# - "STB1_Harp" for STMicroelectronics HARP -# - "CqREEK" for CQ Publishing CqREEK SH-4 -# - "CAT68701" for CAT 68701 Evaluation Board (SH7708) -# - "BigSur" for Big Sur Evaluation Board -# - "SH2000" for SH2000 Evaluation Board (SH7709A) -# - "ADX" for A&D ADX - -SolutionEngine -CONFIG_SH_SOLUTION_ENGINE - Select SolutionEngine if configuring for a Hitachi SH7709 - or SH7750 evaluation board. - -7751 SolutionEngine -CONFIG_SH_7751_SOLUTION_ENGINE - Select 7751 SolutionEngine if configuring for a Hitachi SH7751 - evaluation board. - -SHMobileSolutionEngine -CONFIG_SH_MOBILE_SOLUTION_ENGINE - Select SHMobileSolutionEngine if configuring for SH-Mobile Solution - Engine. - -Overdrive -CONFIG_SH_OVERDRIVE - Select Overdrive if configuring for a ST407750 Overdrive board. - More information at - . - -HP620 -CONFIG_SH_HP620 - Select HP620 if configuring for a HP jornada HP620. - More information (hardware only) at - . - -HP680 -CONFIG_SH_HP680 - Select HP680 if configuring for a HP Jornada HP680. - More information (hardware only) at - . - -HP690 -CONFIG_SH_HP690 - Select HP690 if configuring for a HP Jornada HP690. - More information (hardware only) - at . - -CqREEK -CONFIG_SH_CQREEK - Select CqREEK if configuring for a CqREEK SH7708 or SH7750. - More information at - . - -DMIDA -CONFIG_SH_DMIDA - Select DMIDA if configuring for a DataMyte 4000 Industrial - Digital Assistant. More information at . - -EC3104 -CONFIG_SH_EC3104 - Select EC3104 if configuring for a system with an Eclipse - International EC3104 chip, e.g. the Harris AD2000. - -Dreamcast -CONFIG_SH_DREAMCAST - Select Dreamcast if configuring for a SEGA Dreamcast. - More information at - . There is a - Dreamcast project is at . - -SH-2000 -CONFIG_SH_SH2000 - SH-2000 is a single-board computer based around SH7709A chip - intended for embedded applications. - It has an Ethernet interface (CS8900A), direct connected - Compact Flash socket, three serial ports and PC-104 bus. - More information at . - -BareCPU -CONFIG_SH_UNKNOWN - "Bare CPU" aka "unknown" means an SH-based system which is not one - of the specific ones mentioned above, which means you need to enter - all sorts of stuff like CONFIG_MEMORY_START because the config - system doesn't already know what it is. You get a machine vector - without any platform-specific code in it, so things like the RTC may - not work. - - This option is for the early stages of porting to a new machine. - -# Choice: superhtype -SH7707 -CONFIG_CPU_SUBTYPE_SH7707 - Select the type of SuperH processor you have. This information is - used for optimizing and configuration purposes. - - Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU. - - Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or - if you have a 100 Mhz SH-3 HD6417708R CPU. - - Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU. - - Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU. - - Select SH7751 if you have a SH7751 - - Select ST40STB1 if you have a ST40STB1 - Select ST40RA/ST40STB1 if you have a ST40RA - (previously known as ST40STB1). - - Select ST40GX1 if you have an ST40GX1. - - Select SH7300 if you have a HD6417300 CPU. - -SH7708 -CONFIG_CPU_SUBTYPE_SH7708 - Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or - if you have a 100 Mhz SH-3 HD6417708R CPU. - -SH7709 -CONFIG_CPU_SUBTYPE_SH7709 - Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU. - -SH7750 -CONFIG_CPU_SUBTYPE_SH7750 - Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU. - -SH7751 -CONFIG_CPU_SUBTYPE_SH7751 - Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU. - -ST40RA/ST40STB1 -CONFIG_CPU_SUBTYPE_ST40STB1 - Select ST40RA/ST40STB1 if you have a ST40RA. This chip was - previously called the ST40STB1. Early versions were also - erronously labelled ST40AR166. - -ST40GX1 -CONFIG_CPU_SUBTYPE_ST40GX1 - Select ST40GX1 if you have a ST40GX1 CPU. - -SH7300 -CONFIG_CPU_SUBTYPE_SH7300 - Select SH7300 if you have a HD6417300 CPU. - -Memory on LMI -CONFIG_ST40_LMI_MEMORY - Currently all ST40 CPUs have two external buses the - 'Local Memory Interface' (LMI) which supports SDRAM and - DDR SDRAM, and the 'Enhanced flash Memory Interface' (EMI), - which supports SDRAM, Flash, peripherials and MPX. Linux - can support memory on either of these buses, it is simply - necessary to specify its base address. This option is simply - a shortcut method of specifying that RAM starts from the - bottom of the LMI. - -Physical memory start address -CONFIG_MEMORY_START - Computers built with Hitachi SuperH processors always - map the ROM starting at address zero. But the processor - does not specify the range that RAM takes. - - The physical memory (RAM) start address will be automatically - set to 08000000, unless you selected one of the following - processor types: SolutionEngine, Overdrive, HP620, HP680, HP690, - in which case the start address will be set to 0c000000. - - Tweak this only when porting to a new machine which is not already - known by the config system. Changing it from the known correct - value on any of the known systems will only lead to disaster. - -Hitachi HD64461 companion chip support -CONFIG_HD64461 - The Hitachi HD64461 provides an interface for - the SH7709 CPU, supporting a LCD controller, - CRT color controller, IrDA up to 4 Mbps, and a - PCMCIA controller supporting 2 slots. - - More information is available at - . - - Say Y if you want support for the HD64461. - Otherwise, say N. - -HD64461 PCMCIA enabler -CONFIG_HD64461_ENABLER - Say Y here if you want to enable PCMCIA support - via the HD64461 companion chip. - Otherwise, say N. - -HD64461 virtualized IRQ number -CONFIG_HD64461_IRQ - The default setting of the HD64461 IRQ is 36. - - Do not change this unless you know what you are doing. - -Hitachi HD64465 companion chip support -CONFIG_HD64465 - The Hitachi HD64465 provides an interface for - the SH7750 CPU, supporting a LCD controller, - CRT color controller, IrDA, USB, PCMCIA, - keyboard controller, and a printer interface. - - More information is available at - . - - Say Y if you want support for the HD64465. - Otherwise, say N. - -HD64465 virtualized IRQ number -CONFIG_HD64465_IRQ - The default setting of the HD64465 IRQ is 5. - - Do not change this unless you know what you are doing. - -HD64465 start address -CONFIG_HD64465_IOBASE - The default setting of the HD64465 IO base address is 0xb0000000. - - Do not change this unless you know what you are doing. - -Early printk support -CONFIG_SH_EARLY_PRINTK - Say Y here to redirect kernel printk messages to the serial port - used by the SH-IPL bootloader, starting very early in the boot - process and ending when the kernel's serial console is initialised. - This option is only useful porting the kernel to a new machine, - when the kernel may crash or hang before the serial console is - initialised. If unsure, say N. - -SuperH SCI (serial) support -CONFIG_SH_SCI - Selecting this option will allow the Linux kernel to transfer data - over SCI (Serial Communication Interface) and/or SCIF (Serial - Communication Interface with FIFO) which are built into the Hitachi - SuperH processor. The option provides 1 to 3 (depending - on the CPU model) standard Linux tty devices, /dev/ttySC[012]; one - of these is normally used as the system console. - - If in doubt, press "y". - -Use LinuxSH standard BIOS -CONFIG_SH_STANDARD_BIOS - Say Y here if your target has the gdb-sh-stub - package from www.m17n.org (or any conforming standard LinuxSH BIOS) - in FLASH or EPROM. The kernel will use standard BIOS calls during - boot for various housekeeping tasks (including calls to read and - write characters to a system console, get a MAC address from an - on-board Ethernet interface, and shut down the hardware). Note this - does not work with machines with an existing operating system in - mask ROM and no flash (WindowsCE machines fall in this category). - If unsure, say N. - -GDB Stub kernel debug -CONFIG_DEBUG_KERNEL_WITH_GDB_STUB - If you say Y here, it will be possible to remotely debug the SuperH - kernel using gdb, if you have the gdb-sh-stub package from - www.m17n.org (or any conforming standard LinuxSH BIOS) in FLASH or - EPROM. This enlarges your kernel image disk size by several - megabytes but allows you to load, run and debug the kernel image - remotely using gdb. This is only useful for kernel hackers. If - unsure, say N. - -Console output to GDB -CONFIG_GDB_CONSOLE - If you are using GDB for remote debugging over a serial port and - would like kernel messages to be formatted into GDB $O packets so - that GDB prints them as program output, say 'Y'. - -802.1Q VLAN Support -CONFIG_VLAN_8021Q - Select this and you will be able to create 802.1Q VLAN interfaces on your - ethernet interfaces. 802.1Q VLAN supports almost everything a regular - ethernet interface does, including firewalling, bridging, and of course - IP traffic. You will need the 'vconfig' tool from the VLAN project in - order to effectively use VLANs. See the VLAN web page for more - information: If unsure, - you can safely say 'N'. - -ARC console support -CONFIG_ARC_CONSOLE - Support for the PROM-based console on MIPS machines built according - to the Advanced Risc Computing specification, which is now (2001) - dead. These included boxes from Deskstation, Acer, Olivetti and - NEC. There is a history at . - -AUTCPU12 -CONFIG_ARCH_AUTCPU12 - Say Y if you intend to run the kernel on the autronix autcpu12 - board. This board is based on a Cirrus Logic CS89712. - -IT8172 IDE support -CONFIG_BLK_DEV_IT8172 - Say Y here to support the on-board IDE controller on the Integrated - Technology Express, Inc. ITE8172 SBC. Vendor page at - ; picture of the - board at . - -Support ARM926T processor -CONFIG_CPU_ARM926T - This is a variant of the ARM920. It has slightly different - instruction sequences for cache and TLB operations. Curiously, - there is no documentation on it at the ARM corporate website. - - Say Y if you want support for the ARM926T processor. - Otherwise, say N. - -Support CPU clock change (EXPERIMENTAL) -CONFIG_CPU_FREQ - CPU clock scaling allows you to change the clock speed of the - running CPU on the fly. This is a nice method to save battery power, - because the lower the clock speed, the less power the CPU - consumes. Note that this driver doesn't automatically change the CPU - clock speed, you need some userland tools (which still have to be - written) to implement the policy. If you don't understand what this - is all about, it's safe to say 'N'. - -SiS -CONFIG_DRM_SIS - Choose this option if you have a SIS graphics card. AGP support is - required for this driver to work. - -Etrax Ethernet slave support (over lp0/1) -CONFIG_ETRAX_ETHERNET_LPSLAVE - This option enables a slave ETRAX 100 or ETRAX 100LX, connected to a - master ETRAX 100 or ETRAX 100LX through par0 and par1, to act as an - Ethernet controller. - -Slave has its own LEDs -CONFIG_ETRAX_ETHERNET_LPSLAVE_HAS_LEDS - Enable if the slave has it's own LEDs. - -ATA/IDE support -CONFIG_ETRAX_IDE - Enable this to get support for ATA/IDE. You can't use parallel - ports or SCSI ports at the same time. - -LED on when link -CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK - - Selecting LED_on_when_link will light the LED when there is a - connection and will flash off when there is activity. - - Selecting LED_on_when_activity will light the LED only when - there is activity. - - This setting will also affect the behaviour of other activity LEDs - e.g. Bluetooth. - -Power button bit on port G -CONFIG_ETRAX_POWERBUTTON_BIT - Configure where power button is connected. - -Root device name -CONFIG_ETRAX_ROOT_DEVICE - Specifies the device that should be mounted as root file system - when booting from flash. The axisflashmap driver adds an additional - mtd partition for the appended root file system image, so this option - should normally be the mtdblock device for the partition after the - last partition in the partition table. - -Serial port 0 enabled -CONFIG_ETRAX_SERIAL_PORT0 - Enables the ETRAX 100 serial driver for ser0 (ttyS0) - Normally you want this on, unless you use external DMA 1 that uses - the same DMA channels. - -Shutdown bit on port CSP0 -CONFIG_ETRAX_SHUTDOWN_BIT - Configure what pin on CSPO-port that is used for controlling power - supply. - -Software Shutdown Support -CONFIG_ETRAX_SOFT_SHUTDOWN - Enable this if Etrax is used with a power-supply that can be turned - off and on with PS_ON signal. Gives the possibility to detect - powerbutton and then do a power off after unmounting disks. - -Disable watchdog during Oops printouts -CONFIG_ETRAX_WATCHDOG_NICE_DOGGY - By enabling this you make sure that the watchdog does not bite while - printing oopses. Recommended for development systems but not for - production releases. - -Compaq iPAQ Handheld sleeve support -CONFIG_H3600_SLEEVE - Choose this option to enable support for extension packs (sleeves) - for the Compaq iPAQ H3XXX series of handheld computers. This option - is required for the CF, PCMCIA, Bluetooth and GSM/GPRS extension - packs. - -AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL) -CONFIG_HISAX_FRITZ_PCIPNP - This enables the driver for the AVM Fritz!Card PCI, Fritz!Card PCI v2 - and Fritz!Card PnP. - (the latter also needs you to select "ISA Plug and Play support" - from the menu "Plug and Play configuration") - -IBM PCI Hotplug driver -CONFIG_HOTPLUG_PCI_IBM - Say Y here if you have a motherboard with a IBM PCI Hotplug - controller. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cpqphp.o. If you want to compile it - as a module, say M here and read Documentation/modules.txt. - - When in doubt, say N. - -Enable autotest (llsc). Option to run cache test instead of booting -CONFIG_IA64_SGI_AUTOTEST - Build a kernel used for hardware validation. If you include the - keyword "autotest" on the boot command line, the kernel does NOT boot. - Instead, it starts all cpus and runs cache coherency tests instead. - - If unsure, say N. - -IEC61883-6 (Audio transmission) support -CONFIG_IEEE1394_AMDTP - This option enables the Audio & Music Data Transmission Protocol - (IEC61883-6) driver, which implements audio transmission over - IEEE1394. - - The userspace interface is documented in amdtp.h. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module - will be called amdtp.o. - -IEC61883-1 Plug support -CONFIG_IEEE1394_CMP - This option enables the Connection Management Procedures - (IEC61883-1) driver, which implements input and output plugs. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module - will be called cmp.o. - -OHCI-DV I/O support -CONFIG_IEEE1394_DV1394 - This driver allows you to transmit and receive DV (digital video) - streams on an OHCI-1394 card using a simple frame-oriented - interface. - - The user-space API for dv1394 is documented in dv1394.h. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module - will be called dv1394.o. - -Ethernet over 1394 -CONFIG_IEEE1394_ETH1394 - Extremely Experimental! This driver is a Linux specific way to use your - IEEE1394 Host as an Ethernet type device. This is _NOT_ IP1394. - -Support for older IT8172 (Rev C) -CONFIG_IT8172_REVC - Say Y here to support the older, Revision C version of the Integrated - Technology Express, Inc. ITE8172 SBC. Vendor page at - ; picture of the - board at . - -Enable Smart Card Reader 0 Support -CONFIG_IT8172_SCR0 - Say Y here to support smart-card reader 0 (SCR0) on the Integrated - Technology Express, Inc. ITE8172 SBC. Vendor page at - ; picture of the - board at . - -Enable Smart Card Reader 1 Support -CONFIG_IT8172_SCR1 - Say Y here to support smart-card reader 1 (SCR1) on the Integrated - Technology Express, Inc. ITE8172 SBC. Vendor page at - ; picture of the - board at . - -IT8172 IDE Tuning support -CONFIG_IT8172_TUNING - Say Y here to support tuning the ITE8172's IDE interface. This makes - it possible to set DMA channel or PIO opration and the transfer rate. - -Enable protocol mode for the L1 console -CONFIG_SERIAL_SGI_L1_PROTOCOL - Uses protocol mode instead of raw mode for the level 1 console on the - SGI SN (Scalable NUMA) platform for IA64. If you are compiling for - an SGI SN box then Y is the recommended value, otherwise say N. - -New bus configuration (EXPERIMENTAL) -CONFIG_TULIP_MWI - This configures your Tulip card specifically for the card and - system cache line size type you are using. - - This is experimental code, not yet tested on many boards. - - If unsure, say N. - -Hotplug firmware loading support (EXPERIMENTAL) -CONFIG_FW_LOADER - This option is provided for the case where no in-kernel-tree modules require - hotplug firmware loading support, but a module built outside the kernel tree - does. - -NatSemi SCx200 support -CONFIG_SCx200 - This provides basic support for the National Semiconductor SCx200 - processor. Right now this is just a driver for the GPIO pins. - - If you don't know what to do here, say N. - - This support is also available as a module. If compiled as a - module, it will be called scx200.o. - -NatSemi SCx200 GPIO support -CONFIG_SCx200_GPIO - Give userspace access to the GPIO pins on the National - Semiconductor SCx200 processors. - - This support is also available as a module. If compiled as a - module, it will be called scx200_gpio.o. - -NatSemi SCx200 Watchdog -CONFIG_SCx200_WDT - Enable the built-in watchdog timer support on the National - Semiconductor SCx200 processors. - - If compiled as a module, it will be called scx200_watchdog.o. - -Flash device mapped with DOCCS on NatSemi SCx200 -CONFIG_MTD_SCx200_DOCFLASH - Enable support for a flash chip mapped using the DOCCS signal on a - National Semiconductor SCx200 processor. - - If you don't know what to do here, say N. - - If compiled as a module, it will be called scx200_docflash.o. - -BIOS flash chip on AMD76x southbridge -CONFIG_MTD_AMD76XROM - Support for treating the BIOS flash chip on AMD76x motherboards - as an MTD device - with this you can reprogram your BIOS. - - BE VERY CAREFUL. - - If compiled as a module, it will be called amd76xrom.o. - -BIOS flash chip on Intel Hub Controller 2 -CONFIG_MTD_ICH2ROM - Support for treating the BIOS flash chip on ICH2 motherboards - as an MTD device - with this you can reprogram your BIOS. - - BE VERY CAREFUL. - - If compiled as a module, it will be called ich2rom.o. - -BIOS flash chip on Intel SCB2 boards -CONFIG_MTD_SCB2_FLASH - Support for treating the BIOS flash chip on Intel SCB2 boards - as an MTD device - with this you can reprogram your BIOS. - - BE VERY CAREFUL. - - If compiled as a module, it will be called scb2_flash.o. - -Flash chips on Tsunami TIG bus -CONFIG_MTD_TSUNAMI - Support for the flash chip on Tsunami TIG bus. - - If compiled as a module, it will be called tsunami_flash.o. - -Flash chips on LASAT board -CONFIG_MTD_LASAT - Support for the flash chips on the Lasat 100 and 200 boards. - - If compiled as a module, it will be called lasat.o. - -CFI flash device on SnapGear/SecureEdge -CONFIG_MTD_NETtel - Support for flash chips on NETtel/SecureEdge/SnapGear boards. - - If compiled as a module, it will be called nettel.o. - -CFI Flash device mapped on DIL/Net PC -CONFIG_MTD_DILNETPC - MTD map driver for SSV DIL/Net PC Boards "DNP" and "ADNP". - For details, see - and - - If compiled as a module, it will be called dilnetpc.o. - -Size of DIL/Net PC flash boot partition -CONFIG_MTD_DILNETPC_BOOTSIZE - The amount of space taken up by the kernel or Etherboot - on the DIL/Net PC flash chips. - -CFI Flash device mapped on Epxa10db -CONFIG_MTD_EPXA10DB - This enables support for the flash devices on the Altera - Excalibur XA10 Development Board. If you are building a kernel - for on of these boards then you should say 'Y' otherwise say 'N'. - - If compiled as a module, it will be called epxa10db-flash.o. - -CFI Flash device mapped on the FortuNet board -CONFIG_MTD_FORTUNET - This enables access to the Flash on the FortuNet board. If you - have such a board, say 'Y'. - - If compiled as a module, it will be called fortunet.o. - -NV-RAM mapping AUTCPU12 board -CONFIG_MTD_AUTCPU12 - This enables access to the NV-RAM on autronix autcpu12 board. - If you have such a board, say 'Y'. - - If compiled as a module, it will be called autcpu12-nvram.o. - -CFI Flash device mapped on EDB7312 -CONFIG_MTD_EDB7312 - This enables access to the CFI Flash on the Cogent EDB7312 board. - If you have such a board, say 'Y' here. - - If compiled as a module, it will be called edb7312.o. - -JEDEC Flash device mapped on impA7 -CONFIG_MTD_IMPA7 - This enables access to the NOR Flash on the impA7 board of - implementa GmbH. If you have such a board, say 'Y' here. - - If compiled as a module, it will be called impa7.o. - -JEDEC Flash device mapped on Ceiva/Polaroid PhotoMax Digital Picture Frame -CONFIG_MTD_CEIVA - This enables access to the flash chips on the Ceiva/Polaroid - PhotoMax Digital Picture Frame. - If you have such a device, say 'Y'. - - If compiled as a module, it will be called ceiva.o. - -System flash on MBX860 board -CONFIG_MTD_MBX860 - This enables access routines for the flash chips on the Motorola - MBX860 board. If you have one of these boards and would like - to use the flash chips on it, say 'Y'. - - If compiled as a module, it will be called mbx860.o. - -PCI MTD driver -CONFIG_MTD_PCI - Mapping for accessing flash devices on add-in cards like the Intel XScale - IQ80310 card, and the Intel EBSA285 card in blank ROM programming mode - (please see the manual for the link settings). - - If compiled as a module, it will be called pci.o. - - If you are not sure, say N. - -PCMCIA MTD driver -CONFIG_MTD_PCMCIA - Map driver for accessing PCMCIA linear flash memory cards. These - cards are usually around 4-16MiB in size. This does not include - Compact Flash cards which are treated as IDE devices. - - If compiled as a module, it will be called pcmciamtd.o. - -Generic uClinux RAM/ROM filesystem support -CONFIG_MTD_UCLINUX - Map driver to support image based filesystems for uClinux. - - If compiled as a module, it will be called uclinux.o. - -NatSemi SCx200 I2C using GPIO pins -CONFIG_SCx200_I2C - Enable the use of two GPIO pins of a SCx200 processor as an I2C bus. - - If you don't know what to do here, say N. - - If compiled as a module, it will be called scx200_i2c.o. - -GPIO pin used for SCL -CONFIG_SCx200_I2C_SCL - Enter the GPIO pin number used for the SCL signal. This value can - also be specified with a module parameter. - -GPIO pin used for SDA -CONFIG_SCx200_I2C_SDA - Enter the GPIO pin number used for the SSA signal. This value can - also be specified with a module parameter. - -NatSemi SCx200 ACCESS.bus -CONFIG_SCx200_ACB - Enable the use of the ACCESS.bus controllers of a SCx200 processor. - - If you don't know what to do here, say N. - - If compiled as a module, it will be called scx200_acb.o. - -IPMI top-level message handler -CONFIG_IPMI_HANDLER - This enables the central IPMI message handler, required for IPMI - to work. Note that you must have this enabled to do any other IPMI - things. - - IPMI is a standard for managing sensors (temperature, - voltage, etc.) in a system. - - See Documentation/IPMI.txt for more details on the driver. - - If unsure, say N. - -Generate a panic event to all BMCs on a panic -CONFIG_IPMI_PANIC_EVENT - When a panic occurs, this will cause the IPMI message handler to - generate an IPMI event describing the panic to each interface - registered with the message handler. - -Device interface for IPMI -CONFIG_IPMI_DEVICE_INTERFACE - This provides an IOCTL interface to the IPMI message handler so - userland processes may use IPMI. It supports poll() and select(). - -IPMI KCS handler -CONFIG_IPMI_KCS - Provides a driver for a KCS-style interface to a BMC. - -IPMI Watchdog Timer -CONFIG_IPMI_WATCHDOG - This enables the IPMI watchdog timer. - -CRC32 functions -CONFIG_CRC32 - This option is provided for the case where no in-kernel-tree - modules require CRC32 functions, but a module built outside the - kernel tree does. Such modules that use library CRC32 functions - require that you say M or Y here. - -Chassis LCD and LED support -CONFIG_CHASSIS_LCD_LED - Say Y here if you want to enable support for the Heartbeat, - Disk/Network activities LEDs on some PA-RISC machines, - or support for the LCD that can be found on recent material. - - This has nothing to do with LED State support for A, J and E class. - - If unsure, say Y. - -VSC/GSC/HSC bus support -CONFIG_GSC - The VSC, GSC and HSC busses were used from the earliest 700-series - workstations up to and including the C360/J2240 workstations. They - were also used in servers from the E-class to the K-class. They - are not found in B1000, C3000, J5000, A500, L1000, N4000 and upwards. - If in doubt, say "Y". - -Wax I/O support -CONFIG_GSC_WAX - Say Y here to support the Wax multifunction chip found in some - older systems, including B/C/D/R class and 715/64, 715/80 and - 715/100. Wax includes an EISA adapter, a serial port (not always - used), a HIL interface chip and is also known to be used as the - GSC bridge for an X.25 GSC card. - -GSCtoPCI/Dino PCI support -CONFIG_GSC_DINO - Say Y here to support the Dino & Cujo GSC to PCI bridges found in - machines from the B132 to the C360, the J2240 and the A180. Some - GSC/HSC cards (eg gigabit & dual 100 Mbit Ethernet) have a Dino on - the card, and you also need to say Y here if you have such a card. - Note that Dino also supplies one of the serial ports on certain - machines. If in doubt, say Y. - -HPET timers -CONFIG_HPET_TIMER - Use the IA-PC HPET (High Precision Event Timer) to manage - time in preference to the PIT and RTC, if a HPET is - present. The HPET provides a stable time base on SMP - systems, unlike the RTC, but it is more expensive to access, - as it is off-chip. You can find the HPET spec at - . - - If unsure, say Y. - -IOMMU support -CONFIG_GART_IOMMU - Support the K8 IOMMU. Needed to run systems with more than 4GB of memory - properly with 32-bit PCI devices that do not support DAC (Double Address - Cycle). The IOMMU can be turned off at runtime with the iommu=off parameter. - Normally the kernel will take the right choice by itself. - If unsure say Y - -Debug __init statements -CONFIG_INIT_DEBUG - Fill __init and __initdata at the end of boot. This helps debugging - invalid uses of __init and __initdata after initialization. - -Force IOMMU to on -CONFIG_IOMMU_DEBUG - Force the IOMMU to on even when you have less than 4GB of memory and add - debugging code. - Can be disabled at boot time with iommu=noforce. - -IOMMU leak tracing -CONFIG_IOMMU_LEAK - Add a simple leak tracer to the IOMMU code. This is useful when you - are debugging a buggy device driver that leaks IOMMU mappings. - -pSeries Hypervisor Virtual Console support -CONFIG_HVC_CONSOLE - pSeries machines when partitioned support a hypervisor virtual - console. This driver allows each pSeries partition to have a console - which is accessed via the HMC. - -CONFIG_CRYPTO - This option provides the core Cryptographic API. - -CONFIG_CRYPTO_HMAC - HMAC: Keyed-Hashing for Message Authentication (RFC2104). - This is required for IPSec. - -CONFIG_CRYPTO_NULL - These are 'Null' algorithms, used by IPsec, which do nothing. - -CONFIG_CRYPTO_MD4 - MD4 message digest algorithm (RFC1320). - -CONFIG_CRYPTO_MD5 - MD5 message digest algorithm (RFC1321). - -CONFIG_CRYPTO_SHA1 - SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). - -CONFIG_CRYPTO_SHA256 - SHA256 secure hash standard (DFIPS 180-2). - - This version of SHA implements a 256 bit hash with 128 bits of - security against collision attacks. - -CONFIG_CRYPTO_SHA512 - SHA512 secure hash standard (DFIPS 180-2). - - This version of SHA implements a 512 bit hash with 256 bits of - security against collision attacks. - - This code also includes SHA-384, a 384 bit hash with 192 bits - of security against collision attacks. - -CONFIG_CRYPTO_DES - DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). - -CONFIG_CRYPTO_BLOWFISH - Blowfish cipher algorithm, by Bruce Schneier. - - This is a variable key length cipher which can use keys from 32 - bits to 448 bits in length. It's fast, simple and specifically - designed for use on "large microprocessors". - - See also . - -CONFIG_CRYPTO_TWOFISH - Twofish cipher algorithm. - - Twofish was submitted as an AES (Advanced Encryption Standard) - candidate cipher by researchers at CounterPane Systems. It is a - 16 round block cipher supporting key sizes of 128, 192, and 256 - bits. - - See also: - http://www.counterpane.com/twofish.html - -CONFIG_CRYPTO_SERPENT - Serpent cipher algorithm, by Anderson, Biham & Knudsen. - - Keys are allowed to be from 0 to 256 bits in length, in steps - of 8 bits. - - See also: - http://www.cl.cam.ac.uk/~rja14/serpent.html - -CONFIG_CRYPTO_AES - AES cipher algorithms (FIPS-197). AES uses the Rijndael - algorithm. - - Rijndael appears to be consistently a very good performer in - both hardware and software across a wide range of computing - environments regardless of its use in feedback or non-feedback - modes. Its key setup time is excellent, and its key agility is - good. Rijndael's very low memory requirements make it very well - suited for restricted-space environments, in which it also - demonstrates excellent performance. Rijndael's operations are - among the easiest to defend against power and timing attacks. - - The AES specifies three key sizes: 128, 192 and 256 bits - - See http://csrc.nist.gov/encryption/aes/ for more information. - -CONFIG_CRYPTO_CAST5 - CAST5 (CAST-128) cipher algorithm. - - The CAST5 encryption algorithm (synonymous with CAST-128) is - described in RFC2144. - -CONFIG_CRYPTO_CAST6 - CAST6 (CAST-256) cipher algorithm. - - The CAST6 encryption algorithm (synonymous with CAST-256) is - described in RFC2612. - -CONFIG_CRYPTO_ARC4 - ARC4 cipher algorithm. - - This is a stream cipher using keys ranging from 8 bits to 2048 - bits in length. ARC4 is commonly used in protocols such as WEP - and SSL. - -CONFIG_CRYPTO_DEFLATE - This is the Deflate algorithm (RFC1951), specified for use in - IPSec with the IPCOMP protocol (RFC3173, RFC2394). - - You will most probably want this if using IPSec. - -CONFIG_CRYPTO_TEST - Quick & dirty crypto test module. - -CONFIG_SOUND_WM97XX - Say Y here to support the Wolfson WM9705 and WM9712 touchscreen - controllers. These controllers are mainly found in PDA's - i.e. Dell Axim and Toshiba e740 - - This is experimental code. - Please see Documentation/wolfson-touchscreen.txt for - a complete list of parameters. - - In order to use this driver, a char device called wm97xx with a major - number of 10 and minor number 16 will have to be created under - /dev/touchscreen. - - e.g. - mknod /dev/touchscreen/wm97xx c 10 16 - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here. The module will be called ac97_plugin_wm97xx.o. - - If unsure, say N. - -# -# A couple of things I keep forgetting: -# capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet, -# Intel, IRQ, ISDN, Linux, MSDOS, NetWare, NetWinder, -# NFS, PCI, SCSI, SPARC -# two words: file system, hard drive, hard disk, home page, -# user space, web site -# other: it's safe to save; daemon; use --, not - or ---; -# use KB for 1024 bytes, not kB or K. -# -# -# This is used by Emacs' spell checker ispell.el: -# -# LocalWords: CONFIG coprocessor DX Pentium SX lilo loadlin HOWTO ftp ibiblio -# LocalWords: unc edu docs emu README kB BLK DEV FD Thinkpad fd MFM RLL IDE gz -# LocalWords: cdrom diskless netboot nfs xzvf ATAPI MB ide pavia rubini pl pd -# LocalWords: HD CD-ROMs IDECD NEC MITSUMI filesystem XT XD PCI BIOS cezar ATEN -# LocalWords: ISA EISA Microchannel VESA BIOSes IPC SYSVIPC ipc Ctrl dmesg hlt -# LocalWords: BINFMT Linkable http ac uk jo html GCC SPARC AVANTI CABRIOLET EB -# LocalWords: netscape gcc LD CC toplevel MODVERSIONS insmod rmmod modprobe IP -# LocalWords: genksyms INET loopback gatewaying Ethernet PPP ARP Arp MEMSIZE -# LocalWords: howto multicasting MULTICAST MBONE firewalling ipfw ACCT resp ip -# LocalWords: proc acct IPIP encapsulator decapsulator klogd RARP EXT PS -# LocalWords: telnetting subnetted NAGLE rlogin NOSR ttyS TGA techinfo mbone nl -# LocalWords: Mb SKB IPX Novell dosemu DDP ATALK vmalloc visar ehome -# LocalWords: SD CHR scsi thingy SG CD LUNs LUN jukebox Adaptec BusLogic EATA -# LocalWords: buslogic DMA DPT ATT eata dma PIO UltraStor fdomain umsdos ext -# LocalWords: QLOGIC qlogic TMC seagate Trantor ultrastor FASST wd NETDEVICES -# LocalWords: unix BBS linux CSLIP PLIP Kirch's LDP CSlip SL SCC IRQ csustan -# LocalWords: Turbo Laplink plip NCSA port's ReQuest IRQs EQL SMC AMD PCnet NE -# LocalWords: COM ELPLUS Com EtherLinkIII VLB Arcnet Cabletron DEPCA DE carlos -# LocalWords: depca EtherWorks EWRK ewrk SEEQ EtherExpress EEXPRESS NI xxx dia -# LocalWords: EtherExpress WaveLAN wavelan PCLAN HPLAN VG SK Ansel Xen de ZNET -# LocalWords: PCMCIA cb stanford LAN TEC RealTek ATP atp DLINK NetTools VISWS -# LocalWords: TR Sony CDU caddyless cdu Mitsumi MCD cd mcd XA MultiSession CDA -# LocalWords: Matsushita Panasonic SBPCD Soundblaster Longshine sbpcd Aztech -# LocalWords: Okano Wearnes AZTCD CDD SE aztcd sonycd Goldstar GSCD Philips fs -# LocalWords: LMS OPTCD Sanyo SJCD minix faqs xiafs XIA msdos mtools Cichocki -# LocalWords: std softlinks umssync NetworkFileSharing nfsd mountd CDs HPFS TI -# LocalWords: hpfs SYSV SCO iBCS Wyse WordPerfect tsx mit unixes sysv NR irisa -# LocalWords: SMB WfW Cyclades async mux Logitech busmouse MouseSystem aka AST -# LocalWords: PSMOUSE Compaq trackballs Travelmate Inport ATIXL ATI busmice ld -# LocalWords: gpm config QIC DYNCONF FTAPE Stor Ftape ftape pcsndrv manpage NT -# LocalWords: readprofile diskdrives org com masq EtherTalk tcp netrom sunacm -# LocalWords: misc AIC aic pio scc Portmaster eql GIS PhotoCDs MCDX Perell PG -# LocalWords: mcdx gscd optcd sjcd ISP hdparm Workgroups Lan samba PARIDE PCD -# LocalWords: filesystems smbfs ATA ppp PCTech RZ www powerquest txt CMD ESDI -# LocalWords: chipset FB multicast MROUTE appletalk ifconfig IBMTR multiport -# LocalWords: Multisession STALDRV EasyIO EC EasyConnection ISTALLION ONboard -# LocalWords: Brumby pci TNC cis ohio faq usenet NETLINK dev hydra ca Tyne mem -# LocalWords: carleton DECstation SUNFD JENSEN Noname XXXM SLiRP LILO's amifb -# LocalWords: pppd Zilog ZS SRM bootloader ez mainmenu rarp ipfwadm paride pcd -# LocalWords: RTNETLINK mknod xos MTU lwared Macs netatalk macs cs Wolff -# LocalWords: dartmouth flowerpt MultiMaster FlashPoint tudelft etherexpress -# LocalWords: ICL EtherTeam ETH IDESCSI TXC SmartRAID SmartCache httpd sjc dlp -# LocalWords: thesphere TwoServers BOOTP DHCP ncpfs BPQETHER BPQ MG HIPPI cern -# LocalWords: bsd comp SPARCstation le SunOS ie Gracilis PackeTwin PT pt LU FX -# LocalWords: FX TEAC CR LCS mS ramdisk IDETAPE cmd fperllo encis tcfs unisa -# LocalWords: Vertos Genoa Funai hsfs NCP NetWare tgz APM apm ioctls UltraLite -# LocalWords: TravelMate CDT LCD backlight VC RPC Mips AXP barlow cdrtools pg -# LocalWords: PMAX MILO Alphas Multia Tseng linuxelf endian mipsel mips drv HT -# LocalWords: kerneld callouts AdvanSys advansys Admin WDT DataStor EP verden -# LocalWords: wdt hdb hdc bugfix SiS vlb Acculogic CSA DTC dtc Holtek ht QDI -# LocalWords: QD qd UMC umc ALI ali lena fnet fr azstarnet cdr fb MDA ps esdi -# LocalWords: Avanti XL AlphaStations Jensen DECpc AXPpci UDB Cabriolet MCA RC -# LocalWords: AlphaPC mca AOUT OUTput PPro sipx gwdg lo nwe FourPort Boca unm -# LocalWords: Keepalive linefill RELCOM keepalive analogue CDR conf CDI INIT -# LocalWords: OPTi isp irq noisp VFAT vfat NTFS losetup dmsdosfs dosfs ISDN MP -# LocalWords: NOWAYOUT behaviour dialin isdn callback BTX Teles XXXX LVM lvm -# LocalWords: ICN EDSS Cisco -# LocalWords: ipppd syncppp RFC MPP VJ downloaded icn NICCY Creatix shmem ufr -# LocalWords: ibp md ARCnet ether encap NDIS arcether ODI Amigas AmiTCP NetBSD -# LocalWords: initrd tue util DES funet des OnNet BIOSP smc Travan Iomega CMS -# LocalWords: FC DC dc PPA IOMEGA's ppa RNFS FMV Fujitsu ARPD arpd loran layes -# LocalWords: FRAD indiana framerelay DLCI DCLIs Sangoma SDLA mrouted sync sec -# LocalWords: Starmode Metricom MosquitoNet mosquitonet kbit nfsroot Digiboard -# LocalWords: DIGI Xe Xeve digiboard UMISC touchscreens mtu Ethernets HBAs MEX -# LocalWords: Shifflett netcom js jshiffle WIC DECchip ELCP EtherPower dst RTC -# LocalWords: rtc SMP lp Digi Intl RightSwitch DGRS dgrs AFFS Amiga UFS SDL AP -# LocalWords: Solaris RISCom riscom syncPPP PCBIT pcbit sparc anu au artoo MFB -# LocalWords: hitchcock Crynwr cnam pktdrvr NCSA's CyDROM CyCD-ROM FreeBSD NeXT -# LocalWords: NeXTstep disklabel disklabels SMD FFS tm AmigaOS diskfiles Un IQ -# LocalWords: Bernd informatik rwth aachen uae affs multihosting bytecode java -# LocalWords: applets applet JDK ncsa cabi SNI Alphatronix readme LANs scarab -# LocalWords: winsock RNIS caltech OSPF honour Honouring Mbit LocalTalk DEFRAG -# LocalWords: localtalk download Packetwin Baycom baycom interwork ASCII JNT -# LocalWords: Camtec proxying indyramp defragment defragmented UDP FAS FASXX -# LocalWords: FastSCSI SIO FDC qlogicfas QLogic qlogicisp setbaycom ife ee LJ -# LocalWords: ethz ch Travelmates ProAudioSpectrum ProAudio SoundMan SB SBPro -# LocalWords: Thunderboard SM OPL FM ADLIB TSR Gravis MPU PSS ADI SW DSP codec -# LocalWords: ADSP ESC ASIC daughtercard GUSMAX MSS NX AdLib Excell Ensoniq YM -# LocalWords: SoundScape Spea MediaTriX AudioTriX WSS OTI ThunderBoard VoxWare -# LocalWords: Soundscape SSCAPE TRIX MediaTrix PnP Maui dsp midixx EIA getty -# LocalWords: mgetty sendfax gert greenie muc lowlevel Lasermate LanManager io -# LocalWords: OOPSes trackball binghamton mobileip ncr IOMAPPED settags ns ser -# LocalWords: setsync NEGO MPARITY autotuning prefetch PIIX cdwrite utils rc -# LocalWords: PCWATCHDOG berkprod bitgate boldt ucsb jf kyoto jp euc Tetsuyasu -# LocalWords: YAMADA tetsu cauchy nslab ntt nevod perm su doc kaf kheops wsc -# LocalWords: traduc Bourgin dbourgin menuconfig kfill READMEs HOWTOs Virge WA -# LocalWords: IDEDISK IDEFLOPPY EIDE firewalls QMAGIC ZMAGIC LocalWords opti -# LocalWords: SVGATextMode vga svga Xkernel syr jmwobus comfaqs dhcp flakey GD -# LocalWords: IPv IPng interoperability ipng ipv radio's tapr pkthome PLP nano -# LocalWords: Ses Mhz sethdlc SOUNDMODEM WindowsSoundSystem smdiag pcf inka ES -# LocalWords: smmixer ptt circ soundmodem MKISS FDDI DEFEA DEFPA DEFXX redhat -# LocalWords: HyperNews khg mconv sed lina wuftpd MicroChannel netlink irc cum -# LocalWords: raudio RealAudio PPROP NETBIOS GUI IBMMCA ELMC Racal Interlan fi -# LocalWords: eth shapecfg src esp PCWD PREVSTAT bootparam sig bitwizard SBC -# LocalWords: downloads AFSK TCM FP Karn KA FSK RUH LinkSys cron mouseman LLC -# LocalWords: SyQuest SyQuest's CCITT MicroSolutions BPCD bpcd ESPSERIAL PROM -# LocalWords: SUNESP openprom OPENPROMIO quango themall al TT MC MMU LC RMW AA -# LocalWords: INSNS Ataris AutoConfig ZORRO OCS AMIFB Agnus Denise ECS CDTV GB -# LocalWords: AGA Cybervision CYBER GSP TMS DMI Zorro ACSI ROMs SLM BioNet GVP -# LocalWords: PAMsNet TekMagic Cyberstorm MkI CYBERSTORMII MkII BLZ onboard cx -# LocalWords: Village Tronic ATARILANCE RieblCard PAMCard VME MFP sangoma LAPB -# LocalWords: Rhotron BioData's Multiface AMIGAMOUSE COPCON Amiga's bitplanes -# LocalWords: ATARIMOUSE MFPSER SCC's MegaSTE ESCC Atari's GVPIOEXT DMASOUND -# LocalWords: fdutils cisco univercd rpcg htm iface lapb LAPBETHER tpqic qic -# LocalWords: SYNTH xd en binfmt aout ipip terra ipx sd sr sg wic framebuffer -# LocalWords: ibmmca lapbether mkiss dlci sdla fmv eepro eexpress ni hp ne es -# LocalWords: ibmtr isofs ROMFS romfs pcxx cyclades istallion psaux msbusmouse -# LocalWords: atixlmouse sbin softdog pcwd USS Lite ACI miroSOUND PCM miroPCM -# LocalWords: microcontroller miro Voxware downloading teles acsi slm gvp ltpc -# LocalWords: atari ariadne amigamouse atarimouse builtin IPDDP maths bradford -# LocalWords: AppleTalk Farallon PhoneNet Zubkoff lnz SCCB HAPN WANs vesafb nt -# LocalWords: wanrouter WANPIPE multiprotocol Mbps wanpipe EtherWORKS nodma SC -# LocalWords: smp HiSax SiemensChipSet Siemens AVM Elsa ITK hisax PCC MICROR -# LocalWords: Mircolink EURO DSS Spellcaster BRI sc spellcast Digiboards GPIO -# LocalWords: SYMBIOS COMPAT SDMS rev ASUS Tekram HX VX API ibmmcascsi ASY asy -# LocalWords: loader's PCnetPCI automounter AUTOFS amd autofs VT Gallant's Pnp -# LocalWords: AEDSP aedsp enskip tik Sysctl sysctl PARPORT parport pnp IDs EPP -# LocalWords: Autoprobe bart patrickr HDLS READBACK AB usr DAMA DS SparQ aten -# LocalWords: Symbios PCscsi tmscsim RoamAbout GHz Hinds contrib mathematik ok -# LocalWords: darmstadt okir DIGIEPCA International's Xem digiepca epca bootup -# LocalWords: zorro CAPI AVMB capi avmb VP SYN syncookies EM em pc Ethertalk -# LocalWords: Dayna DL Daynatalk LT PhoneNET ATB Daystar queueing CMDS SCBs ls -# LocalWords: SCB STATS Thinnet ThunderLAN TLAN Netelligent NetFlex tlan james -# LocalWords: caldera Preload Preloading slowdowns schoebel uni NBD nbd prog -# LocalWords: stuttgart rdist TRANS hostnames mango jukeboxes ESS userland PD -# LocalWords: hardlinked NAMETRANS env mtab fstab umount nologin runlevel gid -# LocalWords: adm Nodename hostname uname Kernelname bootp nmi DI OV StegFS -# LocalWords: KERNNAME kname ktype kernelname Kerneltype KERNTYPE Alt RX mdafb -# LocalWords: dataless kerneltype SYSNAME Comtrol Rocketport palmtop fbset EGS -# LocalWords: nvram SYSRQ SysRq PrintScreen sysrq NVRAMs NvRAM Shortwave RTTY -# LocalWords: Sitor Amtor Pactor GTOR hayes TX TMOUT JFdocs BIGMEM DAC IRQ's -# LocalWords: IDEPCI IDEDMA PDC pdc TRM trm raidtools luthien nuclecu BAGET VR -# LocalWords: unam mx miguel koobera uic EMUL solaris pp ieee lpsg co DMAs TOS -# LocalWords: BLDCONFIG preloading jumperless BOOTINIT modutils multipath GRE -# LocalWords: misconfigured autoconfiguration IPGRE ICMP tracert ipautofw PIM -# LocalWords: netis rlynch autofw ipportfw monmouth ipsubs portforwarding pimd -# LocalWords: portfw PIMSM netweb usc pim pf EUI aggregatable PB decapsulate -# LocalWords: ipddp Decapsulation DECAP bool HAMRADIO tcpdump af CDs tx FBCON -# LocalWords: ethertap multisession PPC MMIO GDT GDTH ICP gdth hamradio bpp -# LocalWords: lmh weejock AIMSlab RadioTrack RTRACK HZP OptoSCC TRX rx TRXECHO -# LocalWords: DMASCC paccomm dmascc addr cfg oevsv oe kib picpar FDX baudrate -# LocalWords: baudrates fdx HDX hdx PSK kanren frforum QoS SCHED CBQ SCH sched -# LocalWords: sch cbq CSZ Shenker Zhang csz SFQ sfq TBF tbf PFIFO fifo PRIO RW -# LocalWords: prio Micom xIO dwmw rimi OMIRR omirr omirrd unicode ntfs cmu NIC -# LocalWords: Braam braam Schmidt's freiburg nls codepages codepage Romanian -# LocalWords: Slovak Slovenian Sorbian Nordic iso Catalan Faeroese Galician SZ -# LocalWords: Valencian Slovene Esperanto Estonian Latvian Belarusian KOI mt -# LocalWords: charset Inuit Greenlandic Sami Lappish koi Alexey Kuznetsov's sa -# LocalWords: Specialix specialix DTR RTS RTSCTS cycladesZ Exabyte ftape's inr -# LocalWords: Iomega's LBFM claus ZFTAPE VFS zftape zft William's lzrw DFLT kb -# LocalWords: MTSETBLK MTIOCTOP qft setblk zftape's tar's afio's setdrvbuffer -# LocalWords: Procfs Exabyte's THR FCD sysvinit init PSC pscwdt VMIDI Euro SAB -# LocalWords: Mostek Fastlane PowerMac PReP PMAC PowerPC Macintoshes Starmax -# LocalWords: PowerStack Starmaxes MCOMMON DEVICETREE ATY IMS IMSTT videodev -# LocalWords: BT Hauppauge STB bttv Quickcam BW BWQCAM bw qcam Mediavision PMS -# LocalWords: pms Avatar Freecom Imation Superdisk BPCK bpck COMM comm DSTR ru -# LocalWords: dstr EPAT EPEZ epat EPIA epia FreeCom FRPW frpw KingByte KBIC HW -# LocalWords: KingByte's kbic OnSpec ValuStore FASTROUTE fastroute FLOWCONTROL -# LocalWords: struct APIC realtime OSs LynxOS CNC tmp cvf HFS hfs ADFS Risc os -# LocalWords: adfs ncpmount namespace SUBDIR reexport NDS kcore FT SPX spx DAT -# LocalWords: interserver BLKSZ NUMBUFFERS apmd Tadpole ANA roestock QuickCam -# LocalWords: isapnptools Colour CQCAM colour Connectix QuickClip prive mentre -# LocalWords: KMOD kmod conformant utexas kharker UnixWare Mwave cgi cl ts ibm -# LocalWords: eXchange threepio oakland simtel pre ULTRAMCA EtherLink isa luik -# LocalWords: EtherLink OpenBSD pts DEVPTS devpts ptmx ttyp glibc readback SA -# LocalWords: mwave OLDCARD isdnloop linklevel loopctrl Eicon Diehl DIEHLDIVA -# LocalWords: ASUSCOM AsusCom TELEINT semiactiv Sedlbauer Sportster TA MIC ITH -# LocalWords: NETjet NetJet Niccy Neuhaus sparcs AOC AOCD AOCE Microlink SAA -# LocalWords: teletext WinTV saa iproute tc Quadra Performa PowerBook tor AUN -# LocalWords: setserial compsoc steve Econet econet AUNUDP psched TEQL TLE CLS -# LocalWords: teql FW Ingres TwistedPair MTRR MTRRs mtrr cfs crypto TD ktti KT -# LocalWords: PHd ICS ipchains adelaide rustcorp syslog Cumana steganography -# LocalWords: AcornSCSI EcoSCSI EESOX EESOXSCSI Powertec POWERTECSCSI dec SF -# LocalWords: RadioReveal gatekeeper aimslab aztech FMI sf fmi RTL rtl cesdis -# LocalWords: Yellowfin gsfc nasa gov yellowfin pcnet Mylex LNE lne EtherH hs -# LocalWords: EBSA chattr RiscOS Winmodem AGP Atomwide DUALSP pcsp robinson CT -# LocalWords: SGALAXY Waverider DSPxxx TRXPRO AudioTrix OSWF MOT CFB DSY kbps -# LocalWords: tuwien kkudielk LVD mega lun MAXTAGS Gbps arcnet Olicom SNA PAE -# LocalWords: SysKonnect tms sna etherboot ufs NetBEUI MultiSound MSNDCLAS GX -# LocalWords: MSNDINIT MSNDPERM MSNDPIN PNDSPINI PNDSPERM Ensoniq's RetinaZ SS -# LocalWords: AudioPCI lspci SonicVibes sonicvibes SPARCs roadrunner CLgen UPA -# LocalWords: swansea shtml Zoltrix zoltrix BINUTILS EGCS binutils VIDC DACs -# LocalWords: CyberVision Cirrus PowerBooks Topcat SBUS CGsix TurboGX BWtwo SS -# LocalWords: CGthree TCX unswappable vfb fbcon hicolor truecolor AFB ILBM SOC -# LocalWords: IPLAN gracilis Fibre SBus SparcSTORAGE SV jnewbigin swin QNX qnx -# LocalWords: PTY PTYS ptyxx ttyxx PTYs ssh sb Avance ALS pss pvv kerneli hd -# LocalWords: synth WaveFront MSND NONPNP AudioExcelDSP STRAM APUS CHRP MBX Nx -# LocalWords: PowerMac's BMAC radiotrack rtrack miropcm OFFBOARD HPT UDMA DVD -# LocalWords: hpt fokus gmd Cyrix DXL SLC DLC NexGen MediaGX GXm IDT WinChip -# LocalWords: MMX MII valkyrie mdacon vdolive VDOLive cuseeme CU hippi rrunner -# LocalWords: SeeMe ipmasqadm juanjox ipmarkfw markfw TNCs Microdyne rhine lib -# LocalWords: libc jsX gamepad gameport CHF FCS FPGaming MadCatz ASSASIN GrIP -# LocalWords: Assasin gamepads GamePad PDPI gamecards gamecard WingMan BSP WCS -# LocalWords: ThunderPad CyberMan SideWinder ThrustMaster DirectConnect NES XF -# LocalWords: Millenium SNES PSX Multisystem Nintendo PlayStation Amstrad CPC -# LocalWords: Sega TurboGraFX Steffen Schwenke Multiststem PDIF FIFOSIZE EPLUS -# LocalWords: PowerUP RoadRunner tahallah dos functionkey setterm imladris Woz -# LocalWords: PowerMacs Winbond Algorithmics ALGOR algor ECOFF IRIX SGI SGI's -# LocalWords: gfx virtualized Xpmac mklinux XFree FBDev Woodhouse mvhi Seeq fp -# LocalWords: SGISEEQ HIgh ADB ADBMOUSE crosscompiler CROSSCOMPILE FPE GDB gdb -# LocalWords: JOYPORT rp spoofing DawiControl NOGENSUPP EEPROM HSSI Alessandro -# LocalWords: singleprocessor tex MATHEMU FRIQ Maxell friq Alcor XLT AlphaBook -# LocalWords: AlphaPCI DP LX Miata Mikasa Noritake RPX UX BX Takara EV PRIMO -# LocalWords: TSC Matrox Productiva matroxfb matrox multihead ia linuxhq MFW -# LocalWords: mfw AAA MCS Initio XXU initio imm AutoDetect IZIP CTR usec HDLC -# LocalWords: COSA SRP muni cz kas cosa Alteon AceNIC acenic VTOC OSes GMT SAx -# LocalWords: Inspiron localtime INTS Thinkpads Ralf Brown's Flightstick NNN -# LocalWords: Xterminator Blackhawk NN mpu ioports DCA HPDCA HPLANCE DIO Corel -# LocalWords: GemTek gemtek CMDLINE IrDA PDA's irmanager irattach RR AVA DN rg -# LocalWords: uit dagb irda LSAP IrLMP RR's IrLAP IR alloc skb's kfree skb's -# LocalWords: GZIP IrLAN NetbeamIR ESI JetEye IrOBEX IrCOMM TTY's minicom dti -# LocalWords: ircomm ircomm pluto thiguchi IrTTY Linux's bps NetWinder MIR NSC -# LocalWords: ACTiSYS dongle dongles esi actisys IrMate tekram BVM MVME -# LocalWords: BVME BVME WRITETHROUGH copyback writethrough fwmark syncookie tu -# LocalWords: alphalinux GOBIOS csn chemnitz nat ACARD AMI MegaRAID megaraid -# LocalWords: QNXFS ISI isicom xterms Apollos VPN RCPCI rcpci sgi visws pcmcia -# LocalWords: IrLPT UIRCC Tecra Strebel jstrebel suse Eichwalder ke INI INIA -# LocalWords: FCP qlogicfc sym isapnp DTLK DoubleTalk rcsys dtlk DMAP SGIVW ar -# LocalWords: dmabuf EcoRadio MUTEFREQ GIrBIL girbil tepkom vol mha diplom PQS -# LocalWords: bmac Microgate SyncLink synclink hdlc excl ioaddr Tane tanep TCQ -# LocalWords: PDS SMALLDOS charsets bigfoot kernelfr mcs cls fw rsvp SKnet sk -# LocalWords: SKMC USB UHCI OHCI intel compaq usb ohci HCD Virt Compaq's hcd -# LocalWords: VROOTHUB KBD ARRs MCRs NWBUTTON nwbutton NUM WaveArtist APNE cpu -# LocalWords: apne blackhawke PlanB lu mlan planb NWFPE FPA nwfpe unbootable -# LocalWords: FPEmulator ds vmlinux initialization discardable pgtable PGT mdw -# LocalWords: quicklist pagetable arthur StrongARM podule podules Autodetect -# LocalWords: dodgy IrPORT irport Litelink litelink SuSE rtfm internet hda CY -# LocalWords: multmode DriveReady SeekComplete DriveStatusError miscompile AEC -# LocalWords: mainboard's Digital's alim FastTrak aec PIIXn piix Gayle Eyetech -# LocalWords: Catweasel IDEDOUBLER Powerbook Centris ICSIDE RapIDE OSM HDM IOP -# LocalWords: HDM's OSM's lan FibreChannel ECP autoprobe itg lbl ipmasq cjb IC -# LocalWords: bieringer Caulfield's dreamtime decnet SIOCFIGCONF SIOCGIFCONF -# LocalWords: rtnetlink Endnode Aironet Arlan Telxon ylenurme arlan ACB aeschi -# LocalWords: Sealevel sealevel Cyclom br wanconfig tarball conectiva cycsyn -# LocalWords: devel bazar cyclomx NetGear GA IBMOL Lanstreamer uhci eu efs CYZ -# LocalWords: olympic linuxtr usbcore acm EZUSB downloader EFS XFS INTR op IIC -# LocalWords: heine soundcore JavaStations JavaStation GemTeks TerraTec TODO -# LocalWords: ActiveRadio Standalone terratec Rolf Offermanns rolf offermanns -# LocalWords: Zoran ZR Buz LML CPQ DA cpqarray PPDEV deviceid vlp ppdev atyfb -# LocalWords: AcceleRAID eXtremeRAID NETFILTER Netfilter masqueraded netfilter -# LocalWords: kernelnotes Cardbus PCMCIA's CardBus clgenfb Permedia YAM MMAP -# LocalWords: mmapped ATM atm PVCs SVCs InARP ATMARP neighbour neighbours MPOA -# LocalWords: VCs ENI FPGA Tonga MMF MF UTP printks ZeitNet ZN ZATM uPD SAR PN -# LocalWords: approx NICStAR NICs ForeRunnerLE Madge Collage ATMizer Dxxxx VCI -# LocalWords: ServeRAID IPS ips ipslinux gzip BSDCOMP LZW RAYCS Interphase app -# LocalWords: Tachyon IPHASE Surfboard NextLevel SURFboard jacksonville Tigon -# LocalWords: fventuri adelphia siglercm linuxpower AceNICs Starfire starfire -# LocalWords: ISOC CPiA cpia uss ACPI UDF DirectCD udf CDRW's OSF Manx acpi DM -# LocalWords: Unixware cymru Computone IntelliPort Intelliport computone SI sx -# LocalWords: adbmouse DRI DRM dlabs GMX PLCs Applicom fieldbus applicom int -# LocalWords: VWSND eg ESSSOLO CFU CFNR scribed eiconctrl eicon hylafax KFPU -# LocalWords: EXTRAPREC fpu mainboards KHTTPD kHTTPd khttpd Xcelerator SBNI tw -# LocalWords: LOGIBUSMOUSE Granch granch sbni Raylink NOHIGHMEM Athlon SIM sim -# LocalWords: hpl Tourrilhes DuraLAN starfire Davicom davicom dmfe auk tms tr -# LocalWords: TokenExpress Belkin Peracom eTek DVDs infradead Cxxx Adlib AV ZX -# LocalWords: NeoMagic CPi CPt Celeron decapsulation Undeletion BFS bfs nVidia -# LocalWords: OnStream Irongate Riva phonedev QuickNet LineJack PhoneJack IXJ -# LocalWords: Quicknet PhoneJACK LineJACK ixj pnpdump Quicknet's Joandi SSID -# LocalWords: aironet quickconfig adhoc btw bap NONCS cardservices Xircom lin -# LocalWords: Netwave AirSurfer netwave HomePNA failover MVP iMacs ALi aktual -# LocalWords: Aladin HIDBP usbkbd KEYBDEV MOUSEDEV JOYDEV EVDEV UAB WhiteHEAT -# LocalWords: Handspring ov DABUSB URB URB's dabusb CRAMFS NFSv ELV IOAPIC WIP -# LocalWords: NLMv SMBus ALGOBIT algo PHILIPSPAR philips elv Velleman velleman -# LocalWords: ALGOPCF Elektor elektor CHARDEV dfx TDFX tdfx Extensa dof gravis -# LocalWords: assasin logitech Overdrive thrustmaster DWave Aureal magellan db -# LocalWords: SpaceTec SpaceOrb SpaceBall spaceorb FLX spaceball turbografx zr -# LocalWords: amiga ESS's WaveWatcher Maxi belkin RW's ata glx GART MPV Baget -# LocalWords: OpenGL Xserver agpgart HOTPLUG CyberPro Integraphics Netwinder -# LocalWords: aty FONTWIDTH eni zatm nicstar ForeRunner OC DECstations DEC's -# LocalWords: PHYsical SUNI reinsertion ChipSAR KVC PHY ClassID iphase iadbg -# LocalWords: DEVS FireWire PCILynx pcilynx LOCALRAM miro's DV RAWIO GRED Mk -# LocalWords: Diffserv DSMARK Ingress Qdisc TCINDEX TMSPCI tmspci Ringode JE -# LocalWords: MADGEMC madgemc TokenRing SMCTR TokenCard smctr Wacom Graphire -# LocalWords: mousedev ConnectTech HandSpring Xirlink IBMCAM ibmcam SN -# LocalWords: DEVICEFS yyy Cymraeg Dwave SIMM JSFLASH JavaStation's multilink -# LocalWords: nsc ircc DDB Vrc CMN TB PROMs Vino rivafb DDC Matroxes MGA TVO -# LocalWords: MAVEN fbdev crtc maven matroxset NTSC PCA SBA AAL SKFP DAS SAS -# LocalWords: skfp Intuos ADMtek's pegasus PLUSB plusb pointopoint mp rio Xeon -# LocalWords: DEVFS devfs dd bs EDSS german TELESPCI FRITZPCI HFC HFCS BDS HST -# LocalWords: ISURF ISAR Saphir HSTSAPHIR Telekom BKM Scitel Quadro SCT Gazel -# LocalWords: SP PRI Hypercope HYSDN Hypercope's hysdn IbssJoinNetTimeout FTDI -# LocalWords: ARCNet Keyspan PDA ADMtek sgalaxy sgbase opl mpuio mpuirq sbio -# LocalWords: sbirq sbdma gus uart mssio mssirq mssdma sscape maui mouirq iph -# LocalWords: CHDLC UPS's usbmouse wacom wmforce keybdev joydev fibre Trunking -# LocalWords: Etherchannel IOC Moxa Intellio moxa SmartIO mxser Mixcom EFI ir -# LocalWords: MIXCOMWD mixcomwd SENDCOMPLETE GMAC iBook gmac OAKNET oaknet PCG -# LocalWords: diffserv irlan irtty toshoboe IrCC Lifebook idex AUTODMA FIP Cxx -# LocalWords: Yenta Databook TCIC FMVJ fmvj NMCLAN LiveWire nmclan XIRC xirc -# LocalWords: loadkeys setfont shm SuperIO soc SOCAL socal FCAL fc fcal COMX -# LocalWords: MultiGate ITConsult comx CMX HiCOMX downloadable hw LoCOMX PROTO -# LocalWords: locomx MixCOM mixcom proto MyriCOM MYRI Sbus myri sbus IBMLS hme -# LocalWords: lanstreamer baseT HAPPYMEAL qfe sunhme SUNLANCE sunlance BigMAC -# LocalWords: SUNBMAC sunbmac QuadEthernet SUNQE qe FastEthernet sunqe DSB PTI -# LocalWords: DSBR dsbr procinfo QLOGICPTI qpti ptisp QLGC qlogicpti se LBA NF -# LocalWords: OPENPROMFS OpenPROM openpromfs OBP OpenBoot flashable Multiboard -# LocalWords: SPARCAUDIO SparcClassic Ultras DBRI Sparcbook sparcaudio SUNBPP -# LocalWords: UltraDMA WDC CRC CONNTRACK IPTABLES iptables nfmark interface's -# LocalWords: tdfxfb TNTx HGA hgafb VERBOSEDEBUG SunTrunking SunSoft XIRTULIP -# LocalWords: ethercards PNIC Macronix MXIC ASIX xircom Mustek MDC gphoto mdc -# LocalWords: CramFs Cramfs uid cramfs AVM's kernelcapi PCIV cdrdao Cdparanoia -# LocalWords: DMX Domex dmx wellington ftdi sio Accton Billington Corega FEter -# LocalWords: MELCO LUA PNA Linksys SNC chkdsk AWACS Webcam RAMFS Ramfs ramfs -# LocalWords: ramfiles MAKEDEV pty WDTPCI APA apa -# -# The following sets edit modes for GNU EMACS -# Local Variables: -# case-fold-search:nil -# fill-prefix:" " -# adaptive-fill:nil -# fill-column:70 -# End: diff --git a/linux-2.4.26-xen-sparse/arch/xen/Makefile b/linux-2.4.26-xen-sparse/arch/xen/Makefile index e76dd8fcf9..30e221e8c4 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/Makefile +++ b/linux-2.4.26-xen-sparse/arch/xen/Makefile @@ -51,13 +51,8 @@ HEAD := arch/xen/kernel/head.o arch/xen/kernel/init_task.o SUBDIRS += arch/xen/kernel arch/xen/mm arch/xen/lib SUBDIRS += arch/xen/drivers/console SUBDIRS += arch/xen/drivers/evtchn -ifdef CONFIG_XEN_NEWIO SUBDIRS += arch/xen/drivers/blkif SUBDIRS += arch/xen/drivers/netif -else -SUBDIRS += arch/xen/drivers/block -SUBDIRS += arch/xen/drivers/network -endif SUBDIRS += arch/xen/drivers/balloon ifdef CONFIG_XEN_PRIVILEGED_GUEST SUBDIRS += arch/xen/drivers/dom0 @@ -66,13 +61,8 @@ endif CORE_FILES += arch/xen/kernel/kernel.o arch/xen/mm/mm.o CORE_FILES += arch/xen/drivers/evtchn/drv.o CORE_FILES += arch/xen/drivers/console/drv.o -ifdef CONFIG_XEN_NEWIO DRIVERS += arch/xen/drivers/blkif/drv.o DRIVERS += arch/xen/drivers/netif/drv.o -else -DRIVERS += arch/xen/drivers/block/drv.o -DRIVERS += arch/xen/drivers/network/drv.o -endif ifdef CONFIG_XEN_PRIVILEGED_GUEST CORE_FILES += arch/xen/drivers/dom0/drv.o endif diff --git a/linux-2.4.26-xen-sparse/arch/xen/config.in b/linux-2.4.26-xen-sparse/arch/xen/config.in index 45f6cf4c51..e602de8573 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/config.in +++ b/linux-2.4.26-xen-sparse/arch/xen/config.in @@ -15,10 +15,7 @@ define_bool CONFIG_UID16 y mainmenu_option next_comment comment 'Xen' bool 'Support for privileged operations (domain 0)' CONFIG_XEN_PRIVILEGED_GUEST -bool 'New I/O model (no drivers in Xen) [EXPERIMENTAL]' CONFIG_XEN_NEWIO -if [ "$CONFIG_XEN_NEWIO" = "y" ]; then - bool 'Device-driver domain (physical device access)' CONFIG_XEN_PHYSDEV_ACCESS -fi +bool 'Device-driver domain (physical device access)' CONFIG_XEN_PHYSDEV_ACCESS endmenu # The IBM S/390 patch needs this. define_bool CONFIG_NO_IDLE_HZ y @@ -258,7 +255,6 @@ else fi dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM bool 'Per partition statistics in /proc/partitions' CONFIG_BLK_STATS - bool 'XenoLinux virtual block device support' CONFIG_XEN_VBD define_bool CONFIG_BLK_DEV_HD n endmenu fi diff --git a/linux-2.4.26-xen-sparse/arch/xen/defconfigs/dom0 b/linux-2.4.26-xen-sparse/arch/xen/defconfigs/dom0 index 3be5b50bfa..dcd2070f5b 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/defconfigs/dom0 +++ b/linux-2.4.26-xen-sparse/arch/xen/defconfigs/dom0 @@ -11,7 +11,6 @@ CONFIG_UID16=y # Xen # CONFIG_XEN_PRIVILEGED_GUEST=y -CONFIG_XEN_NEWIO=y CONFIG_XEN_PHYSDEV_ACCESS=y CONFIG_NO_IDLE_HZ=y diff --git a/linux-2.4.26-xen-sparse/arch/xen/defconfigs/unprivileged b/linux-2.4.26-xen-sparse/arch/xen/defconfigs/unprivileged index df7e42cc92..9ccf9528de 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/defconfigs/unprivileged +++ b/linux-2.4.26-xen-sparse/arch/xen/defconfigs/unprivileged @@ -11,7 +11,7 @@ CONFIG_UID16=y # Xen # CONFIG_XEN_PRIVILEGED_GUEST=y -# CONFIG_XEN_NEWIO is not set +# CONFIG_XEN_PHYSDEV_ACCESS is not set CONFIG_NO_IDLE_HZ=y # @@ -237,7 +237,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y # CONFIG_BLK_STATS is not set -CONFIG_XEN_VBD=y # CONFIG_BLK_DEV_HD is not set # diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/backend/common.h b/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/backend/common.h index d9f1d22908..6e10732e04 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/backend/common.h +++ b/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/backend/common.h @@ -36,8 +36,8 @@ typedef struct blkif_st { int irq; /* Comms information. */ blkif_ring_t *blk_ring_base; /* ioremap()'ed ptr to shmem_frame. */ - BLK_RING_IDX blk_req_cons; /* Request consumer. */ - BLK_RING_IDX blk_resp_prod; /* Private version of response producer. */ + BLKIF_RING_IDX blk_req_cons; /* Request consumer. */ + BLKIF_RING_IDX blk_resp_prod; /* Private version of resp. producer. */ /* VBDs attached to this interface. */ rb_root_t vbd_rb; /* Mapping from 16-bit vdevices to VBDs. */ spinlock_t vbd_lock; /* Protects VBD mapping. */ @@ -76,7 +76,7 @@ typedef struct _blkif_extent_le { typedef struct _vbd { blkif_vdev_t vdevice; /* what the domain refers to this vbd as */ unsigned char readonly; /* Non-zero -> read-only */ - unsigned char type; /* XD_TYPE_xxx */ + unsigned char type; /* VDISK_TYPE_xxx */ blkif_extent_le_t *extents; /* list of xen_extents making up this vbd */ rb_node_t rb; /* for linking into R-B tree lookup struct */ } vbd_t; @@ -93,7 +93,7 @@ typedef struct { unsigned short dev; unsigned short nr_sects; unsigned long buffer; - xen_sector_t sector_number; + blkif_sector_t sector_number; } phys_seg_t; int vbd_translate(phys_seg_t *pseg, blkif_t *blkif, int operation); diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/backend/main.c b/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/backend/main.c index 803af976d2..b3e82fdf7b 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/backend/main.c +++ b/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/backend/main.c @@ -239,13 +239,13 @@ static int do_block_io_op(blkif_t *blkif, int max_to_do) { blkif_ring_t *blk_ring = blkif->blk_ring_base; blkif_request_t *req; - BLK_RING_IDX i; + BLKIF_RING_IDX i; int more_to_do = 0; /* Take items off the comms ring, taking care not to overflow. */ for ( i = blkif->blk_req_cons; (i != blk_ring->req_prod) && ((i-blkif->blk_resp_prod) != - BLK_RING_SIZE); + BLKIF_RING_SIZE); i++ ) { if ( (max_to_do-- == 0) || (NR_PENDING_REQS == MAX_PENDING_REQS) ) @@ -254,7 +254,7 @@ static int do_block_io_op(blkif_t *blkif, int max_to_do) break; } - req = &blk_ring->ring[MASK_BLK_IDX(i)].req; + req = &blk_ring->ring[MASK_BLKIF_IDX(i)].req; switch ( req->operation ) { case BLKIF_OP_READ: @@ -466,7 +466,7 @@ static void make_response(blkif_t *blkif, unsigned long id, /* Place on the response ring for the relevant domain. */ spin_lock_irqsave(&blkif->blk_ring_lock, flags); resp = &blkif->blk_ring_base-> - ring[MASK_BLK_IDX(blkif->blk_resp_prod)].resp; + ring[MASK_BLKIF_IDX(blkif->blk_resp_prod)].resp; resp->id = id; resp->operation = op; resp->status = st; diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/common.h b/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/common.h index 2d4415bdef..eb63d1cd8c 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/common.h +++ b/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/common.h @@ -22,7 +22,6 @@ #include #include -#include #include #include #include diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/main.c b/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/main.c index 4e5dbca093..1ecb766ade 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/main.c +++ b/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/main.c @@ -30,20 +30,19 @@ static int blkif_control_rsp_valid; static blkif_response_t blkif_control_rsp; static blkif_ring_t *blk_ring; -static BLK_RING_IDX resp_cons; /* Response consumer for comms ring. */ -static BLK_RING_IDX req_prod; /* Private request producer. */ - +static BLKIF_RING_IDX resp_cons; /* Response consumer for comms ring. */ +static BLKIF_RING_IDX req_prod; /* Private request producer. */ static blkif_ring_t *blk_ring_rec; /* Private copy of requests, used for * recovery. Responses not stored here. */ -static BLK_RING_IDX resp_cons_rec; /* Copy of response consumer, used for - * recovery */ +static BLKIF_RING_IDX resp_cons_rec; /* Copy of response consumer, used for + * recovery */ static int recovery = 0; /* "Recovery in progress" flag. Protected * by the io_request_lock */ /* We plug the I/O ring if the driver is suspended or if the ring is full. */ -#define RING_PLUGGED (((req_prod - resp_cons) == BLK_RING_SIZE) || \ +#define RING_PLUGGED (((req_prod - resp_cons) == BLKIF_RING_SIZE) || \ (blkif_state != BLKIF_STATE_CONNECTED)) @@ -353,7 +352,7 @@ static int blkif_queue_request(unsigned long id, (sg_dev == device) && (sg_next_sect == sector_number) ) { - req = &blk_ring->ring[MASK_BLK_IDX(req_prod-1)].req; + req = &blk_ring->ring[MASK_BLKIF_IDX(req_prod-1)].req; bh = (struct buffer_head *)id; bh->b_reqnext = (struct buffer_head *)req->id; req->id = id; @@ -365,7 +364,7 @@ static int blkif_queue_request(unsigned long id, DISABLE_SCATTERGATHER(); /* Update the copy of the request in the recovery ring. */ - blk_ring_rec->ring[MASK_BLK_IDX(blk_ring_rec->req_prod - 1)].req + blk_ring_rec->ring[MASK_BLKIF_IDX(blk_ring_rec->req_prod - 1)].req = *req; return 0; @@ -387,7 +386,7 @@ static int blkif_queue_request(unsigned long id, } /* Fill out a communications ring structure. */ - req = &blk_ring->ring[MASK_BLK_IDX(req_prod)].req; + req = &blk_ring->ring[MASK_BLKIF_IDX(req_prod)].req; req->id = id; req->operation = operation; req->sector_number = (blkif_sector_t)sector_number; @@ -397,7 +396,7 @@ static int blkif_queue_request(unsigned long id, req_prod++; /* Keep a private copy so we can reissue requests when recovering. */ - blk_ring_rec->ring[MASK_BLK_IDX(blk_ring_rec->req_prod)].req = *req; + blk_ring_rec->ring[MASK_BLKIF_IDX(blk_ring_rec->req_prod)].req = *req; blk_ring_rec->req_prod++; return 0; @@ -490,7 +489,7 @@ static void kick_pending_request_queues(void) { /* We kick pending request queues if the ring is reasonably empty. */ if ( (nr_pending != 0) && - ((req_prod - resp_cons) < (BLK_RING_SIZE >> 1)) ) + ((req_prod - resp_cons) < (BLKIF_RING_SIZE >> 1)) ) { /* Attempt to drain the queue, but bail if the ring becomes full. */ while ( (nr_pending != 0) && !RING_PLUGGED ) @@ -501,12 +500,10 @@ static void kick_pending_request_queues(void) static void blkif_int(int irq, void *dev_id, struct pt_regs *ptregs) { - BLK_RING_IDX i; + BLKIF_RING_IDX i; unsigned long flags; struct buffer_head *bh, *next_bh; -// printk(KERN_ALERT "blkif_int\n"); - spin_lock_irqsave(&io_request_lock, flags); if ( unlikely(blkif_state == BLKIF_STATE_CLOSED || recovery) ) @@ -519,7 +516,7 @@ static void blkif_int(int irq, void *dev_id, struct pt_regs *ptregs) for ( i = resp_cons; i != blk_ring->resp_prod; i++ ) { - blkif_response_t *bret = &blk_ring->ring[MASK_BLK_IDX(i)].resp; + blkif_response_t *bret = &blk_ring->ring[MASK_BLKIF_IDX(i)].resp; switch ( bret->operation ) { case BLKIF_OP_READ: @@ -559,22 +556,22 @@ void blkif_control_send(blkif_request_t *req, blkif_response_t *rsp) unsigned long flags; retry: - while ( (req_prod - resp_cons) == BLK_RING_SIZE ) + while ( (req_prod - resp_cons) == BLKIF_RING_SIZE ) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); } spin_lock_irqsave(&io_request_lock, flags); - if ( (req_prod - resp_cons) == BLK_RING_SIZE ) + if ( (req_prod - resp_cons) == BLKIF_RING_SIZE ) { spin_unlock_irqrestore(&io_request_lock, flags); goto retry; } DISABLE_SCATTERGATHER(); - memcpy(&blk_ring->ring[MASK_BLK_IDX(req_prod)].req, req, sizeof(*req)); - memcpy(&blk_ring_rec->ring[MASK_BLK_IDX(blk_ring_rec->req_prod++)].req, + memcpy(&blk_ring->ring[MASK_BLKIF_IDX(req_prod)].req, req, sizeof(*req)); + memcpy(&blk_ring_rec->ring[MASK_BLKIF_IDX(blk_ring_rec->req_prod++)].req, req, sizeof(*req)); req_prod++; flush_requests(); @@ -674,7 +671,7 @@ static void blkif_status_change(blkif_fe_interface_status_changed_t *status) resp_cons_rec++, i++ ) { blk_ring->ring[i].req - = blk_ring_rec->ring[MASK_BLK_IDX(resp_cons_rec)].req; + = blk_ring_rec->ring[MASK_BLKIF_IDX(resp_cons_rec)].req; } /* Reset the private block ring to match the new ring. */ diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/vbd.c b/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/vbd.c index 12ce976cb5..e5d299ae16 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/vbd.c +++ b/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/vbd.c @@ -137,7 +137,7 @@ static int xlvbd_init_device(vdisk_t *xd) major_name = XLSCSI_MAJOR_NAME; max_part = XLSCSI_MAX_PART; - } else if (XD_VIRTUAL(xd->info)) { + } else if (VDISK_VIRTUAL(xd->info)) { major_name = XLVBD_MAJOR_NAME; max_part = XLVBD_MAX_PART; @@ -248,7 +248,7 @@ static int xlvbd_init_device(vdisk_t *xd) blk_size[major] = gd->sizes; } - if ( XD_READONLY(xd->info) ) + if ( VDISK_READONLY(xd->info) ) set_device_ro(device, 1); gd->flags[minor >> gd->minor_shift] |= GENHD_FL_XEN; @@ -298,20 +298,20 @@ static int xlvbd_init_device(vdisk_t *xd) gd->sizes[minor] = capacity>>(BLOCK_SIZE_BITS-9); /* Some final fix-ups depending on the device type */ - switch ( XD_TYPE(xd->info) ) + switch ( VDISK_TYPE(xd->info) ) { - case XD_TYPE_CDROM: - case XD_TYPE_FLOPPY: - case XD_TYPE_TAPE: + case VDISK_TYPE_CDROM: + case VDISK_TYPE_FLOPPY: + case VDISK_TYPE_TAPE: gd->flags[minor >> gd->minor_shift] |= GENHD_FL_REMOVABLE; printk(KERN_ALERT "Skipping partition check on %s /dev/%s\n", - XD_TYPE(xd->info)==XD_TYPE_CDROM ? "cdrom" : - (XD_TYPE(xd->info)==XD_TYPE_TAPE ? "tape" : + VDISK_TYPE(xd->info)==VDISK_TYPE_CDROM ? "cdrom" : + (VDISK_TYPE(xd->info)==VDISK_TYPE_TAPE ? "tape" : "floppy"), disk_name(gd, MINOR(device), buf)); break; - case XD_TYPE_DISK: + case VDISK_TYPE_DISK: /* Only check partitions on real discs (not virtual!). */ if ( gd->flags[minor>>gd->minor_shift] & GENHD_FL_VIRT_PARTNS ) { @@ -325,7 +325,7 @@ static int xlvbd_init_device(vdisk_t *xd) default: printk(KERN_ALERT "XenoLinux: unknown device type %d\n", - XD_TYPE(xd->info)); + VDISK_TYPE(xd->info)); break; } } diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/block/Makefile b/linux-2.4.26-xen-sparse/arch/xen/drivers/block/Makefile deleted file mode 100644 index 35986ca54a..0000000000 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/block/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -O_TARGET := drv.o -obj-y := block.o vbd.o -include $(TOPDIR)/Rules.make diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/block/block.c b/linux-2.4.26-xen-sparse/arch/xen/drivers/block/block.c deleted file mode 100644 index 43a6a23479..0000000000 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/block/block.c +++ /dev/null @@ -1,625 +0,0 @@ -/****************************************************************************** - * block.c - * - * Xenolinux virtual block-device driver. - * - * Copyright (c) 2003-2004, Keir Fraser & Steve Hand - * Modifications by Mark A. Williamson are (c) Intel Research Cambridge - */ - -#include "block.h" -#include -#include -#include -#include -#include - -#include - -typedef unsigned char byte; /* from linux/ide.h */ - -#define STATE_ACTIVE 0 -#define STATE_SUSPENDED 1 -#define STATE_CLOSED 2 -static unsigned int state = STATE_SUSPENDED; - -/* Dynamically-mapped IRQs. */ -static int xlblk_response_irq, xlblk_update_irq; - -static blk_ring_t *blk_ring; -static BLK_RING_IDX resp_cons; /* Response consumer for comms ring. */ -static BLK_RING_IDX req_prod; /* Private request producer. */ - -/* We plug the I/O ring if the driver is suspended or if the ring is full. */ -#define RING_PLUGGED (((req_prod - resp_cons) == BLK_RING_SIZE) || \ - (state != STATE_ACTIVE)) - - -/* - * Request queues with outstanding work, but ring is currently full. - * We need no special lock here, as we always access this with the - * io_request_lock held. We only need a small maximum list. - */ -#define MAX_PENDING 8 -static request_queue_t *pending_queues[MAX_PENDING]; -static int nr_pending; - -static kdev_t sg_dev; -static int sg_operation = -1; -static unsigned long sg_next_sect; -#define DISABLE_SCATTERGATHER() (sg_operation = -1) - -static inline void signal_requests_to_xen(void) -{ - block_io_op_t op; - - DISABLE_SCATTERGATHER(); - blk_ring->req_prod = req_prod; - - op.cmd = BLOCK_IO_OP_SIGNAL; - HYPERVISOR_block_io_op(&op); - return; -} - - -/* - * xlblk_update_int/update-vbds_task - handle VBD update events from Xen - * - * Schedule a task for keventd to run, which will update the VBDs and perform - * the corresponding updates to our view of VBD state, so the XenoLinux will - * respond to changes / additions / deletions to the set of VBDs automatically. - */ -static struct tq_struct update_tq; -static void update_vbds_task(void *unused) -{ - xlvbd_update_vbds(); -} -static void xlblk_update_int(int irq, void *dev_id, struct pt_regs *ptregs) -{ - update_tq.routine = update_vbds_task; - schedule_task(&update_tq); -} - - -int xen_block_open(struct inode *inode, struct file *filep) -{ - short xldev = inode->i_rdev; - struct gendisk *gd = get_gendisk(xldev); - xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev); - short minor = MINOR(xldev); - - if ( gd->part[minor].nr_sects == 0 ) - { - /* - * Device either doesn't exist, or has zero capacity; we use a few - * cheesy heuristics to return the relevant error code - */ - if ( (gd->sizes[minor >> gd->minor_shift] != 0) || - ((minor & (gd->max_p - 1)) != 0) ) - { - /* - * We have a real device, but no such partition, or we just have a - * partition number so guess this is the problem. - */ - return -ENXIO; /* no such device or address */ - } - else if ( gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE ) - { - /* This is a removable device => assume that media is missing. */ - return -ENOMEDIUM; /* media not present (this is a guess) */ - } - else - { - /* Just go for the general 'no such device' error. */ - return -ENODEV; /* no such device */ - } - } - - /* Update of usage count is protected by per-device semaphore. */ - disk->usage++; - - return 0; -} - - -int xen_block_release(struct inode *inode, struct file *filep) -{ - xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev); - - /* - * When usage drops to zero it may allow more VBD updates to occur. - * Update of usage count is protected by a per-device semaphore. - */ - if ( --disk->usage == 0 ) - { - update_tq.routine = update_vbds_task; - schedule_task(&update_tq); - } - - return 0; -} - - -int xen_block_ioctl(struct inode *inode, struct file *filep, - unsigned command, unsigned long argument) -{ - kdev_t dev = inode->i_rdev; - struct hd_geometry *geo = (struct hd_geometry *)argument; - struct gendisk *gd; - struct hd_struct *part; - int i; - - /* NB. No need to check permissions. That is done for us. */ - - DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n", - command, (long) argument, dev); - - gd = get_gendisk(dev); - part = &gd->part[MINOR(dev)]; - - switch ( command ) - { - case BLKGETSIZE: - DPRINTK_IOCTL(" BLKGETSIZE: %x %lx\n", BLKGETSIZE, part->nr_sects); - return put_user(part->nr_sects, (unsigned long *) argument); - - case BLKGETSIZE64: - DPRINTK_IOCTL(" BLKGETSIZE64: %x %llx\n", BLKGETSIZE64, - (u64)part->nr_sects * 512); - return put_user((u64)part->nr_sects * 512, (u64 *) argument); - - case BLKRRPART: /* re-read partition table */ - DPRINTK_IOCTL(" BLKRRPART: %x\n", BLKRRPART); - return xen_block_revalidate(dev); - - case BLKSSZGET: - return hardsect_size[MAJOR(dev)][MINOR(dev)]; - - case BLKBSZGET: /* get block size */ - DPRINTK_IOCTL(" BLKBSZGET: %x\n", BLKBSZGET); - break; - - case BLKBSZSET: /* set block size */ - DPRINTK_IOCTL(" BLKBSZSET: %x\n", BLKBSZSET); - break; - - case BLKRASET: /* set read-ahead */ - DPRINTK_IOCTL(" BLKRASET: %x\n", BLKRASET); - break; - - case BLKRAGET: /* get read-ahead */ - DPRINTK_IOCTL(" BLKRAFET: %x\n", BLKRAGET); - break; - - case HDIO_GETGEO: - /* note: these values are complete garbage */ - DPRINTK_IOCTL(" HDIO_GETGEO: %x\n", HDIO_GETGEO); - if (!argument) return -EINVAL; - if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT; - if (put_user(0xff, (byte *)&geo->heads)) return -EFAULT; - if (put_user(0x3f, (byte *)&geo->sectors)) return -EFAULT; - if (put_user(0x106, (unsigned short *)&geo->cylinders)) return -EFAULT; - return 0; - - case HDIO_GETGEO_BIG: - /* note: these values are complete garbage */ - DPRINTK_IOCTL(" HDIO_GETGEO_BIG: %x\n", HDIO_GETGEO_BIG); - if (!argument) return -EINVAL; - if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT; - if (put_user(0xff, (byte *)&geo->heads)) return -EFAULT; - if (put_user(0x3f, (byte *)&geo->sectors)) return -EFAULT; - if (put_user(0x106, (unsigned int *) &geo->cylinders)) return -EFAULT; - return 0; - - case CDROMMULTISESSION: - DPRINTK("FIXME: support multisession CDs later\n"); - for ( i = 0; i < sizeof(struct cdrom_multisession); i++ ) - if ( put_user(0, (byte *)(argument + i)) ) return -EFAULT; - return 0; - - case SCSI_IOCTL_GET_BUS_NUMBER: - DPRINTK("FIXME: SCSI_IOCTL_GET_BUS_NUMBER ioctl in Xen blkdev"); - return -ENOSYS; - - default: - printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n", command); - return -ENOSYS; - } - - return 0; -} - -/* check media change: should probably do something here in some cases :-) */ -int xen_block_check(kdev_t dev) -{ - DPRINTK("xen_block_check\n"); - return 0; -} - -int xen_block_revalidate(kdev_t dev) -{ - struct block_device *bd; - struct gendisk *gd; - xl_disk_t *disk; - unsigned long capacity; - int i, rc = 0; - - if ( (bd = bdget(dev)) == NULL ) - return -EINVAL; - - /* - * Update of partition info, and check of usage count, is protected - * by the per-block-device semaphore. - */ - down(&bd->bd_sem); - - if ( ((gd = get_gendisk(dev)) == NULL) || - ((disk = xldev_to_xldisk(dev)) == NULL) || - ((capacity = gd->part[MINOR(dev)].nr_sects) == 0) ) - { - rc = -EINVAL; - goto out; - } - - if ( disk->usage > 1 ) - { - rc = -EBUSY; - goto out; - } - - /* Only reread partition table if VBDs aren't mapped to partitions. */ - if ( !(gd->flags[MINOR(dev) >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS) ) - { - for ( i = gd->max_p - 1; i >= 0; i-- ) - { - invalidate_device(dev+i, 1); - gd->part[MINOR(dev+i)].start_sect = 0; - gd->part[MINOR(dev+i)].nr_sects = 0; - gd->sizes[MINOR(dev+i)] = 0; - } - - grok_partitions(gd, MINOR(dev)>>gd->minor_shift, gd->max_p, capacity); - } - - out: - up(&bd->bd_sem); - bdput(bd); - return rc; -} - - -/* - * hypervisor_request - * - * request block io - * - * id: for guest use only. - * operation: XEN_BLOCK_{READ,WRITE,PROBE,VBD*} - * buffer: buffer to read/write into. this should be a - * virtual address in the guest os. - */ -static int hypervisor_request(unsigned long id, - int operation, - char * buffer, - unsigned long sector_number, - unsigned short nr_sectors, - kdev_t device) -{ - unsigned long buffer_ma = phys_to_machine(virt_to_phys(buffer)); - struct gendisk *gd; - blk_ring_req_entry_t *req; - struct buffer_head *bh; - - if ( unlikely(nr_sectors >= (1<<9)) ) - BUG(); - if ( unlikely((buffer_ma & ((1<<9)-1)) != 0) ) - BUG(); - - if ( unlikely(state == STATE_CLOSED) ) - return 1; - - switch ( operation ) - { - - case XEN_BLOCK_READ: - case XEN_BLOCK_WRITE: - gd = get_gendisk(device); - - /* - * Update the sector_number we'll pass down as appropriate; note that - * we could sanity check that resulting sector will be in this - * partition, but this will happen in xen anyhow. - */ - sector_number += gd->part[MINOR(device)].start_sect; - - /* - * If this unit doesn't consist of virtual (i.e., Xen-specified) - * partitions then we clear the partn bits from the device number. - */ - if ( !(gd->flags[MINOR(device)>>gd->minor_shift] & - GENHD_FL_VIRT_PARTNS) ) - device &= ~(gd->max_p - 1); - - if ( (sg_operation == operation) && - (sg_dev == device) && - (sg_next_sect == sector_number) ) - { - req = &blk_ring->ring[MASK_BLK_IDX(req_prod-1)].req; - bh = (struct buffer_head *)id; - bh->b_reqnext = (struct buffer_head *)req->id; - req->id = id; - req->buffer_and_sects[req->nr_segments] = buffer_ma | nr_sectors; - if ( ++req->nr_segments < MAX_BLK_SEGS ) - sg_next_sect += nr_sectors; - else - DISABLE_SCATTERGATHER(); - return 0; - } - else if ( RING_PLUGGED ) - { - return 1; - } - else - { - sg_operation = operation; - sg_dev = device; - sg_next_sect = sector_number + nr_sectors; - } - break; - - default: - panic("unknown op %d\n", operation); - } - - /* Fill out a communications ring structure. */ - req = &blk_ring->ring[MASK_BLK_IDX(req_prod)].req; - req->id = id; - req->operation = operation; - req->sector_number = (xen_sector_t)sector_number; - req->device = device; - req->nr_segments = 1; - req->buffer_and_sects[0] = buffer_ma | nr_sectors; - req_prod++; - - return 0; -} - - -/* - * do_xlblk_request - * read a block; request is in a request queue - */ -void do_xlblk_request(request_queue_t *rq) -{ - struct request *req; - struct buffer_head *bh, *next_bh; - int rw, nsect, full, queued = 0; - - DPRINTK("xlblk.c::do_xlblk_request\n"); - - while ( !rq->plugged && !list_empty(&rq->queue_head)) - { - if ( (req = blkdev_entry_next_request(&rq->queue_head)) == NULL ) - goto out; - - DPRINTK("do_xlblk_request %p: cmd %i, sec %lx, (%li/%li) bh:%p\n", - req, req->cmd, req->sector, - req->current_nr_sectors, req->nr_sectors, req->bh); - - rw = req->cmd; - if ( rw == READA ) - rw = READ; - if ( unlikely((rw != READ) && (rw != WRITE)) ) - panic("XenoLinux Virtual Block Device: bad cmd: %d\n", rw); - - req->errors = 0; - - bh = req->bh; - while ( bh != NULL ) - { - next_bh = bh->b_reqnext; - bh->b_reqnext = NULL; - - full = hypervisor_request( - (unsigned long)bh, - (rw == READ) ? XEN_BLOCK_READ : XEN_BLOCK_WRITE, - bh->b_data, bh->b_rsector, bh->b_size>>9, bh->b_rdev); - - if ( full ) - { - bh->b_reqnext = next_bh; - pending_queues[nr_pending++] = rq; - if ( unlikely(nr_pending >= MAX_PENDING) ) - BUG(); - goto out; - } - - queued++; - - /* Dequeue the buffer head from the request. */ - nsect = bh->b_size >> 9; - bh = req->bh = next_bh; - - if ( bh != NULL ) - { - /* There's another buffer head to do. Update the request. */ - req->hard_sector += nsect; - req->hard_nr_sectors -= nsect; - req->sector = req->hard_sector; - req->nr_sectors = req->hard_nr_sectors; - req->current_nr_sectors = bh->b_size >> 9; - req->buffer = bh->b_data; - } - else - { - /* That was the last buffer head. Finalise the request. */ - if ( unlikely(end_that_request_first(req, 1, "XenBlk")) ) - BUG(); - blkdev_dequeue_request(req); - end_that_request_last(req); - } - } - } - - out: - if ( queued != 0 ) signal_requests_to_xen(); -} - - -static void kick_pending_request_queues(void) -{ - /* We kick pending request queues if the ring is reasonably empty. */ - if ( (nr_pending != 0) && - ((req_prod - resp_cons) < (BLK_RING_SIZE >> 1)) ) - { - /* Attempt to drain the queue, but bail if the ring becomes full. */ - while ( (nr_pending != 0) && !RING_PLUGGED ) - do_xlblk_request(pending_queues[--nr_pending]); - } -} - - -static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs) -{ - BLK_RING_IDX i; - unsigned long flags; - struct buffer_head *bh, *next_bh; - - if ( unlikely(state == STATE_CLOSED) ) - return; - - spin_lock_irqsave(&io_request_lock, flags); - - for ( i = resp_cons; i != blk_ring->resp_prod; i++ ) - { - blk_ring_resp_entry_t *bret = &blk_ring->ring[MASK_BLK_IDX(i)].resp; - switch ( bret->operation ) - { - case XEN_BLOCK_READ: - case XEN_BLOCK_WRITE: - if ( unlikely(bret->status != 0) ) - DPRINTK("Bad return from blkdev data request: %lx\n", - bret->status); - for ( bh = (struct buffer_head *)bret->id; - bh != NULL; - bh = next_bh ) - { - next_bh = bh->b_reqnext; - bh->b_reqnext = NULL; - bh->b_end_io(bh, !bret->status); - } - break; - - default: - BUG(); - } - } - - resp_cons = i; - - kick_pending_request_queues(); - - spin_unlock_irqrestore(&io_request_lock, flags); -} - - -static void reset_xlblk_interface(void) -{ - block_io_op_t op; - - op.cmd = BLOCK_IO_OP_RESET; - if ( HYPERVISOR_block_io_op(&op) != 0 ) - printk(KERN_ALERT "Possible blkdev trouble: couldn't reset ring\n"); - - op.cmd = BLOCK_IO_OP_RING_ADDRESS; - (void)HYPERVISOR_block_io_op(&op); - - set_fixmap(FIX_BLKRING_BASE, op.u.ring_mfn << PAGE_SHIFT); - blk_ring = (blk_ring_t *)fix_to_virt(FIX_BLKRING_BASE); - blk_ring->req_prod = blk_ring->resp_prod = resp_cons = req_prod = 0; - - wmb(); - state = STATE_ACTIVE; -} - - -int __init xlblk_init(void) -{ - int error; - - nr_pending = 0; - - reset_xlblk_interface(); - - xlblk_response_irq = bind_virq_to_irq(VIRQ_BLKDEV); - xlblk_update_irq = bind_virq_to_irq(VIRQ_VBD_UPD); - - error = request_irq(xlblk_response_irq, xlblk_response_int, - SA_SAMPLE_RANDOM, "blkdev", NULL); - if ( error ) - { - printk(KERN_ALERT "Could not allocate receive interrupt\n"); - goto fail; - } - - error = request_irq(xlblk_update_irq, xlblk_update_int, - 0, "blkdev", NULL); - - if ( error ) - { - printk(KERN_ALERT "Could not allocate block update interrupt\n"); - goto fail; - } - - (void)xlvbd_init(); - - return 0; - - fail: - return error; -} - - -static void __exit xlblk_cleanup(void) -{ - xlvbd_cleanup(); - free_irq(xlblk_response_irq, NULL); - free_irq(xlblk_update_irq, NULL); - unbind_virq_from_irq(VIRQ_BLKDEV); - unbind_virq_from_irq(VIRQ_VBD_UPD); -} - - -#ifdef MODULE -module_init(xlblk_init); -module_exit(xlblk_cleanup); -#endif - - -void blkdev_suspend(void) -{ - state = STATE_SUSPENDED; - wmb(); - - while ( resp_cons != blk_ring->req_prod ) - { - barrier(); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - } - - wmb(); - state = STATE_CLOSED; - wmb(); - - clear_fixmap(FIX_BLKRING_BASE); -} - - -void blkdev_resume(void) -{ - reset_xlblk_interface(); - spin_lock_irq(&io_request_lock); - kick_pending_request_queues(); - spin_unlock_irq(&io_request_lock); -} diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/block/block.h b/linux-2.4.26-xen-sparse/arch/xen/drivers/block/block.h deleted file mode 100644 index e41e03970e..0000000000 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/block/block.h +++ /dev/null @@ -1,82 +0,0 @@ -/****************************************************************************** - * block.h - * - * Shared definitions between all levels of XenoLinux Virtual block devices. - */ - -#ifndef __XEN_DRIVERS_BLOCK_H__ -#define __XEN_DRIVERS_BLOCK_H__ - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#if 0 -#define DPRINTK(_f, _a...) printk ( KERN_ALERT _f , ## _a ) -#else -#define DPRINTK(_f, _a...) ((void)0) -#endif - -#if 0 -#define DPRINTK_IOCTL(_f, _a...) printk ( KERN_ALERT _f , ## _a ) -#else -#define DPRINTK_IOCTL(_f, _a...) ((void)0) -#endif - -/* Private gendisk->flags[] values. */ -#define GENHD_FL_XEN 2 /* Is unit a Xen block device? */ -#define GENHD_FL_VIRT_PARTNS 4 /* Are unit partitions virtual? */ - -/* - * We have one of these per vbd, whether ide, scsi or 'other'. - * They hang in an array off the gendisk structure. We may end up putting - * all kinds of interesting stuff here :-) - */ -typedef struct xl_disk { - int usage; -} xl_disk_t; - -extern int xen_control_msg(int operration, char *buffer, int size); -extern int xen_block_open(struct inode *inode, struct file *filep); -extern int xen_block_release(struct inode *inode, struct file *filep); -extern int xen_block_ioctl(struct inode *inode, struct file *filep, - unsigned command, unsigned long argument); -extern int xen_block_check(kdev_t dev); -extern int xen_block_revalidate(kdev_t dev); -extern void do_xlblk_request (request_queue_t *rq); - -extern void xlvbd_update_vbds(void); - -static inline xl_disk_t *xldev_to_xldisk(kdev_t xldev) -{ - struct gendisk *gd = get_gendisk(xldev); - - if ( gd == NULL ) - return NULL; - - return (xl_disk_t *)gd->real_devices + - (MINOR(xldev) >> gd->minor_shift); -} - - -/* Virtual block-device subsystem. */ -extern int xlvbd_init(void); -extern void xlvbd_cleanup(void); - -#endif /* __XEN_DRIVERS_BLOCK_H__ */ diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/block/vbd.c b/linux-2.4.26-xen-sparse/arch/xen/drivers/block/vbd.c deleted file mode 100644 index e08b976c56..0000000000 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/block/vbd.c +++ /dev/null @@ -1,561 +0,0 @@ -/****************************************************************************** - * vbd.c - * - * Xenolinux virtual block-device driver (xvd). - * - * Copyright (c) 2003-2004, Keir Fraser & Steve Hand - * Modifications by Mark A. Williamson are (c) Intel Research Cambridge - */ - -#include "block.h" -#include - -/* - * For convenience we distinguish between ide, scsi and 'other' (i.e. - * potentially combinations of the two) in the naming scheme and in a few - * other places (like default readahead, etc). - */ -#define XLIDE_MAJOR_NAME "hd" -#define XLSCSI_MAJOR_NAME "sd" -#define XLVBD_MAJOR_NAME "xvd" - -#define XLIDE_DEVS_PER_MAJOR 2 -#define XLSCSI_DEVS_PER_MAJOR 16 -#define XLVBD_DEVS_PER_MAJOR 16 - -#define XLIDE_PARTN_SHIFT 6 /* amount to shift minor to get 'real' minor */ -#define XLIDE_MAX_PART (1 << XLIDE_PARTN_SHIFT) /* minors per ide vbd */ - -#define XLSCSI_PARTN_SHIFT 4 /* amount to shift minor to get 'real' minor */ -#define XLSCSI_MAX_PART (1 << XLSCSI_PARTN_SHIFT) /* minors per scsi vbd */ - -#define XLVBD_PARTN_SHIFT 4 /* amount to shift minor to get 'real' minor */ -#define XLVBD_MAX_PART (1 << XLVBD_PARTN_SHIFT) /* minors per 'other' vbd */ - -/* The below are for the generic drivers/block/ll_rw_block.c code. */ -static int xlide_blksize_size[256]; -static int xlide_hardsect_size[256]; -static int xlide_max_sectors[256]; -static int xlscsi_blksize_size[256]; -static int xlscsi_hardsect_size[256]; -static int xlscsi_max_sectors[256]; -static int xlvbd_blksize_size[256]; -static int xlvbd_hardsect_size[256]; -static int xlvbd_max_sectors[256]; - -/* Information from Xen about our VBDs. */ -#define MAX_VBDS 64 -static int nr_vbds; -static xen_disk_t *vbd_info; - -static struct block_device_operations xlvbd_block_fops = -{ - open: xen_block_open, - release: xen_block_release, - ioctl: xen_block_ioctl, - check_media_change: xen_block_check, - revalidate: xen_block_revalidate, -}; - -static int xlvbd_get_vbd_info(xen_disk_t *disk_info) -{ - int error; - block_io_op_t op; - - /* Probe for disk information. */ - memset(&op, 0, sizeof(op)); - op.cmd = BLOCK_IO_OP_VBD_PROBE; - op.u.probe_params.domain = 0; - op.u.probe_params.xdi.max = MAX_VBDS; - op.u.probe_params.xdi.disks = disk_info; - op.u.probe_params.xdi.count = 0; - - if ( (error = HYPERVISOR_block_io_op(&op)) != 0 ) - { - printk(KERN_ALERT "Could not probe disks (%d)\n", error); - return -1; - } - - return op.u.probe_params.xdi.count; -} - -/* - * xlvbd_init_device - initialise a VBD device - * @disk: a xen_disk_t describing the VBD - * - * Takes a xen_disk_t * that describes a VBD the domain has access to. - * Performs appropriate initialisation and registration of the device. - * - * Care needs to be taken when making re-entrant calls to ensure that - * corruption does not occur. Also, devices that are in use should not have - * their details updated. This is the caller's responsibility. - */ -static int xlvbd_init_device(xen_disk_t *xd) -{ - int device = xd->device; - int major = MAJOR(device); - int minor = MINOR(device); - int is_ide = IDE_DISK_MAJOR(major); /* is this an ide device? */ - int is_scsi= SCSI_BLK_MAJOR(major); /* is this a scsi device? */ - char *major_name; - struct gendisk *gd; - struct block_device *bd; - xl_disk_t *disk; - int i, rc = 0, max_part, partno; - unsigned long capacity; - - unsigned char buf[64]; - - if ( (bd = bdget(device)) == NULL ) - return -1; - - /* - * Update of partition info, and check of usage count, is protected - * by the per-block-device semaphore. - */ - down(&bd->bd_sem); - - if ( ((disk = xldev_to_xldisk(device)) != NULL) && (disk->usage != 0) ) - { - printk(KERN_ALERT "VBD update failed - in use [dev=%x]\n", device); - rc = -1; - goto out; - } - - if ( is_ide ) { - - major_name = XLIDE_MAJOR_NAME; - max_part = XLIDE_MAX_PART; - - } else if ( is_scsi ) { - - major_name = XLSCSI_MAJOR_NAME; - max_part = XLSCSI_MAX_PART; - - } else if (XD_VIRTUAL(xd->info)) { - - major_name = XLVBD_MAJOR_NAME; - max_part = XLVBD_MAX_PART; - - } else { - - /* SMH: hmm - probably a CCISS driver or sim; assume CCISS for now */ - printk(KERN_ALERT "Assuming device %02x:%02x is CCISS/SCSI\n", - major, minor); - is_scsi = 1; - major_name = "cciss"; - max_part = XLSCSI_MAX_PART; - - } - - partno = minor & (max_part - 1); - - if ( (gd = get_gendisk(device)) == NULL ) - { - rc = register_blkdev(major, major_name, &xlvbd_block_fops); - if ( rc < 0 ) - { - printk(KERN_ALERT "XL VBD: can't get major %d\n", major); - goto out; - } - - if ( is_ide ) - { - blksize_size[major] = xlide_blksize_size; - hardsect_size[major] = xlide_hardsect_size; - max_sectors[major] = xlide_max_sectors; - read_ahead[major] = 8; /* from drivers/ide/ide-probe.c */ - } - else if ( is_scsi ) - { - blksize_size[major] = xlscsi_blksize_size; - hardsect_size[major] = xlscsi_hardsect_size; - max_sectors[major] = xlscsi_max_sectors; - read_ahead[major] = 0; /* XXX 8; -- guessing */ - } - else - { - blksize_size[major] = xlvbd_blksize_size; - hardsect_size[major] = xlvbd_hardsect_size; - max_sectors[major] = xlvbd_max_sectors; - read_ahead[major] = 8; - } - - blk_init_queue(BLK_DEFAULT_QUEUE(major), do_xlblk_request); - - /* - * Turn off barking 'headactive' mode. We dequeue buffer heads as - * soon as we pass them down to Xen. - */ - blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0); - - /* Construct an appropriate gendisk structure. */ - gd = kmalloc(sizeof(struct gendisk), GFP_KERNEL); - gd->major = major; - gd->major_name = major_name; - - gd->max_p = max_part; - if ( is_ide ) - { - gd->minor_shift = XLIDE_PARTN_SHIFT; - gd->nr_real = XLIDE_DEVS_PER_MAJOR; - } - else if ( is_scsi ) - { - gd->minor_shift = XLSCSI_PARTN_SHIFT; - gd->nr_real = XLSCSI_DEVS_PER_MAJOR; - } - else - { - gd->minor_shift = XLVBD_PARTN_SHIFT; - gd->nr_real = XLVBD_DEVS_PER_MAJOR; - } - - /* - ** The sizes[] and part[] arrays hold the sizes and other - ** information about every partition with this 'major' (i.e. - ** every disk sharing the 8 bit prefix * max partns per disk) - */ - gd->sizes = kmalloc(max_part*gd->nr_real*sizeof(int), GFP_KERNEL); - gd->part = kmalloc(max_part*gd->nr_real*sizeof(struct hd_struct), - GFP_KERNEL); - memset(gd->sizes, 0, max_part * gd->nr_real * sizeof(int)); - memset(gd->part, 0, max_part * gd->nr_real - * sizeof(struct hd_struct)); - - - gd->real_devices = kmalloc(gd->nr_real * sizeof(xl_disk_t), - GFP_KERNEL); - memset(gd->real_devices, 0, gd->nr_real * sizeof(xl_disk_t)); - - gd->next = NULL; - gd->fops = &xlvbd_block_fops; - - gd->de_arr = kmalloc(gd->nr_real * sizeof(*gd->de_arr), - GFP_KERNEL); - gd->flags = kmalloc(gd->nr_real * sizeof(*gd->flags), GFP_KERNEL); - - memset(gd->de_arr, 0, gd->nr_real * sizeof(*gd->de_arr)); - memset(gd->flags, 0, gd->nr_real * sizeof(*gd->flags)); - - add_gendisk(gd); - - blk_size[major] = gd->sizes; - } - - if ( XD_READONLY(xd->info) ) - set_device_ro(device, 1); - - gd->flags[minor >> gd->minor_shift] |= GENHD_FL_XEN; - - /* NB. Linux 2.4 only handles 32-bit sector offsets and capacities. */ - capacity = (unsigned long)xd->capacity; - - if ( partno != 0 ) - { - /* - * If this was previously set up as a real disc we will have set - * up partition-table information. Virtual partitions override - * 'real' partitions, and the two cannot coexist on a device. - */ - if ( !(gd->flags[minor >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS) && - (gd->sizes[minor & ~(max_part-1)] != 0) ) - { - /* - * Any non-zero sub-partition entries must be cleaned out before - * installing 'virtual' partition entries. The two types cannot - * coexist, and virtual partitions are favoured. - */ - kdev_t dev = device & ~(max_part-1); - for ( i = max_part - 1; i > 0; i-- ) - { - invalidate_device(dev+i, 1); - gd->part[MINOR(dev+i)].start_sect = 0; - gd->part[MINOR(dev+i)].nr_sects = 0; - gd->sizes[MINOR(dev+i)] = 0; - } - printk(KERN_ALERT - "Virtual partitions found for /dev/%s - ignoring any " - "real partition information we may have found.\n", - disk_name(gd, MINOR(device), buf)); - } - - /* Need to skankily setup 'partition' information */ - gd->part[minor].start_sect = 0; - gd->part[minor].nr_sects = capacity; - gd->sizes[minor] = capacity; - - gd->flags[minor >> gd->minor_shift] |= GENHD_FL_VIRT_PARTNS; - } - else - { - gd->part[minor].nr_sects = capacity; - gd->sizes[minor] = capacity>>(BLOCK_SIZE_BITS-9); - - /* Some final fix-ups depending on the device type */ - switch ( XD_TYPE(xd->info) ) - { - case XD_TYPE_CDROM: - case XD_TYPE_FLOPPY: - case XD_TYPE_TAPE: - gd->flags[minor >> gd->minor_shift] |= GENHD_FL_REMOVABLE; - printk(KERN_ALERT - "Skipping partition check on %s /dev/%s\n", - XD_TYPE(xd->info)==XD_TYPE_CDROM ? "cdrom" : - (XD_TYPE(xd->info)==XD_TYPE_TAPE ? "tape" : - "floppy"), disk_name(gd, MINOR(device), buf)); - break; - - case XD_TYPE_DISK: - /* Only check partitions on real discs (not virtual!). */ - if ( gd->flags[minor>>gd->minor_shift] & GENHD_FL_VIRT_PARTNS ) - { - printk(KERN_ALERT - "Skipping partition check on virtual /dev/%s\n", - disk_name(gd, MINOR(device), buf)); - break; - } - register_disk(gd, device, gd->max_p, &xlvbd_block_fops, capacity); - break; - - default: - printk(KERN_ALERT "XenoLinux: unknown device type %d\n", - XD_TYPE(xd->info)); - break; - } - } - - out: - up(&bd->bd_sem); - bdput(bd); - return rc; -} - - -/* - * xlvbd_remove_device - remove a device node if possible - * @device: numeric device ID - * - * Updates the gendisk structure and invalidates devices. - * - * This is OK for now but in future, should perhaps consider where this should - * deallocate gendisks / unregister devices. - */ -static int xlvbd_remove_device(int device) -{ - int i, rc = 0, minor = MINOR(device); - struct gendisk *gd; - struct block_device *bd; - xl_disk_t *disk = NULL; - - if ( (bd = bdget(device)) == NULL ) - return -1; - - /* - * Update of partition info, and check of usage count, is protected - * by the per-block-device semaphore. - */ - down(&bd->bd_sem); - - if ( ((gd = get_gendisk(device)) == NULL) || - ((disk = xldev_to_xldisk(device)) == NULL) ) - BUG(); - - if ( disk->usage != 0 ) - { - printk(KERN_ALERT "VBD removal failed - in use [dev=%x]\n", device); - rc = -1; - goto out; - } - - if ( (minor & (gd->max_p-1)) != 0 ) - { - /* 1: The VBD is mapped to a partition rather than a whole unit. */ - invalidate_device(device, 1); - gd->part[minor].start_sect = 0; - gd->part[minor].nr_sects = 0; - gd->sizes[minor] = 0; - - /* Clear the consists-of-virtual-partitions flag if possible. */ - gd->flags[minor >> gd->minor_shift] &= ~GENHD_FL_VIRT_PARTNS; - for ( i = 1; i < gd->max_p; i++ ) - if ( gd->sizes[(minor & ~(gd->max_p-1)) + i] != 0 ) - gd->flags[minor >> gd->minor_shift] |= GENHD_FL_VIRT_PARTNS; - - /* - * If all virtual partitions are now gone, and a 'whole unit' VBD is - * present, then we can try to grok the unit's real partition table. - */ - if ( !(gd->flags[minor >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS) && - (gd->sizes[minor & ~(gd->max_p-1)] != 0) && - !(gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE) ) - { - register_disk(gd, - device&~(gd->max_p-1), - gd->max_p, - &xlvbd_block_fops, - gd->part[minor&~(gd->max_p-1)].nr_sects); - } - } - else - { - /* - * 2: The VBD is mapped to an entire 'unit'. Clear all partitions. - * NB. The partition entries are only cleared if there are no VBDs - * mapped to individual partitions on this unit. - */ - i = gd->max_p - 1; /* Default: clear subpartitions as well. */ - if ( gd->flags[minor >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS ) - i = 0; /* 'Virtual' mode: only clear the 'whole unit' entry. */ - while ( i >= 0 ) - { - invalidate_device(device+i, 1); - gd->part[minor+i].start_sect = 0; - gd->part[minor+i].nr_sects = 0; - gd->sizes[minor+i] = 0; - i--; - } - } - - out: - up(&bd->bd_sem); - bdput(bd); - return rc; -} - -/* - * xlvbd_update_vbds - reprobes the VBD status and performs updates driver - * state. The VBDs need to be updated in this way when the domain is - * initialised and also each time we receive an XLBLK_UPDATE event. - */ -void xlvbd_update_vbds(void) -{ - int i, j, k, old_nr, new_nr; - xen_disk_t *old_info, *new_info, *merged_info; - - old_info = vbd_info; - old_nr = nr_vbds; - - new_info = kmalloc(MAX_VBDS * sizeof(xen_disk_t), GFP_KERNEL); - if ( unlikely(new_nr = xlvbd_get_vbd_info(new_info)) < 0 ) - { - kfree(new_info); - return; - } - - /* - * Final list maximum size is old list + new list. This occurs only when - * old list and new list do not overlap at all, and we cannot yet destroy - * VBDs in the old list because the usage counts are busy. - */ - merged_info = kmalloc((old_nr + new_nr) * sizeof(xen_disk_t), GFP_KERNEL); - - /* @i tracks old list; @j tracks new list; @k tracks merged list. */ - i = j = k = 0; - - while ( (i < old_nr) && (j < new_nr) ) - { - if ( old_info[i].device < new_info[j].device ) - { - if ( xlvbd_remove_device(old_info[i].device) != 0 ) - memcpy(&merged_info[k++], &old_info[i], sizeof(xen_disk_t)); - i++; - } - else if ( old_info[i].device > new_info[j].device ) - { - if ( xlvbd_init_device(&new_info[j]) == 0 ) - memcpy(&merged_info[k++], &new_info[j], sizeof(xen_disk_t)); - j++; - } - else - { - if ( ((old_info[i].capacity == new_info[j].capacity) && - (old_info[i].info == new_info[j].info)) || - (xlvbd_remove_device(old_info[i].device) != 0) ) - memcpy(&merged_info[k++], &old_info[i], sizeof(xen_disk_t)); - else if ( xlvbd_init_device(&new_info[j]) == 0 ) - memcpy(&merged_info[k++], &new_info[j], sizeof(xen_disk_t)); - i++; j++; - } - } - - for ( ; i < old_nr; i++ ) - { - if ( xlvbd_remove_device(old_info[i].device) != 0 ) - memcpy(&merged_info[k++], &old_info[i], sizeof(xen_disk_t)); - } - - for ( ; j < new_nr; j++ ) - { - if ( xlvbd_init_device(&new_info[j]) == 0 ) - memcpy(&merged_info[k++], &new_info[j], sizeof(xen_disk_t)); - } - - vbd_info = merged_info; - nr_vbds = k; - - kfree(old_info); - kfree(new_info); -} - - -/* - * Set up all the linux device goop for the virtual block devices (vbd's) that - * xen tells us about. Note that although from xen's pov VBDs are addressed - * simply an opaque 16-bit device number, the domain creation tools - * conventionally allocate these numbers to correspond to those used by 'real' - * linux -- this is just for convenience as it means e.g. that the same - * /etc/fstab can be used when booting with or without xen. - */ -int __init xlvbd_init(void) -{ - int i; - - /* - * If compiled as a module, we don't support unloading yet. We therefore - * permanently increment the reference count to disallow it. - */ - SET_MODULE_OWNER(&xlvbd_block_fops); - MOD_INC_USE_COUNT; - - /* Initialize the global arrays. */ - for ( i = 0; i < 256; i++ ) - { - /* from the generic ide code (drivers/ide/ide-probe.c, etc) */ - xlide_blksize_size[i] = 1024; - xlide_hardsect_size[i] = 512; - xlide_max_sectors[i] = 128; /* 'hwif->rqsize' if we knew it */ - - /* from the generic scsi disk code (drivers/scsi/sd.c) */ - xlscsi_blksize_size[i] = 1024; /* XXX 512; */ - xlscsi_hardsect_size[i] = 512; - xlscsi_max_sectors[i] = 128*8; /* XXX 128; */ - - /* we don't really know what to set these too since it depends */ - xlvbd_blksize_size[i] = 512; - xlvbd_hardsect_size[i] = 512; - xlvbd_max_sectors[i] = 128; - } - - vbd_info = kmalloc(MAX_VBDS * sizeof(xen_disk_t), GFP_KERNEL); - nr_vbds = xlvbd_get_vbd_info(vbd_info); - - if ( nr_vbds < 0 ) - { - kfree(vbd_info); - vbd_info = NULL; - nr_vbds = 0; - } - else - { - for ( i = 0; i < nr_vbds; i++ ) - xlvbd_init_device(&vbd_info[i]); - } - - return 0; -} - - -#ifdef MODULE -module_init(xlvbd_init); -#endif diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/dom0/Makefile b/linux-2.4.26-xen-sparse/arch/xen/drivers/dom0/Makefile index 3e2e17bd23..a3fee726b3 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/dom0/Makefile +++ b/linux-2.4.26-xen-sparse/arch/xen/drivers/dom0/Makefile @@ -1,3 +1,3 @@ O_TARGET := drv.o -obj-y := core.o vfr.o +obj-y := core.o include $(TOPDIR)/Rules.make diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/dom0/vfr.c b/linux-2.4.26-xen-sparse/arch/xen/drivers/dom0/vfr.c deleted file mode 100644 index 9d8ca0a32d..0000000000 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/dom0/vfr.c +++ /dev/null @@ -1,343 +0,0 @@ -/****************************************************************************** - * vfr.c - * - * Interface to the virtual firewall/router. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static struct proc_dir_entry *proc_vfr; - -static unsigned char readbuf[1024]; - -/* Helpers, implemented at the bottom. */ -u32 getipaddr(const char *buff, unsigned int len); -u16 antous(const char *buff, int len); -u64 antoull(const char *buff, int len); -int anton(const char *buff, int len); - -static int vfr_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - strcpy(page, readbuf); - *readbuf = '\0'; - *eof = 1; - *start = page; - return strlen(page); -} - -/* The format for the vfr interface is as follows: - * - * COMMAND = [= [...]] - * - * where: - * - * COMMAND = { ACCEPT | COUNT } - * - * field=val pairs are as follows: - * - * field = { srcaddr | dstaddr } - * val is a dot seperated, numeric IP address. - * - * field = { srcport | dstport } - * val is a (16-bit) unsigned int - * - * field = { proto } - * val = { IP | TCP | UDP | ARP } - * - */ - -#define isspace(_x) ( ((_x)==' ') || ((_x)=='\t') || ((_x)=='\v') || \ - ((_x)=='\f') || ((_x)=='\r') || ((_x)=='\n') ) - -static int vfr_write_proc(struct file *file, const char *buffer, - u_long count, void *data) -{ - network_op_t op; - int ret, len; - int ts, te, tl; // token start, end, and length - int fs, fe, fl; // field. - - len = count; - ts = te = 0; - - memset(&op, 0, sizeof(network_op_t)); - - // get the command: - while ( count && isspace(buffer[ts]) ) { ts++; count--; } // skip spaces. - te = ts; - while ( count && !isspace(buffer[te]) ) { te++; count--; } // command end - if ( te <= ts ) goto bad; - tl = te - ts; - - if ( strncmp(&buffer[ts], "ADD", tl) == 0 ) - { - op.cmd = NETWORK_OP_ADDRULE; - } - else if ( strncmp(&buffer[ts], "DELETE", tl) == 0 ) - { - op.cmd = NETWORK_OP_DELETERULE; - } - else if ( strncmp(&buffer[ts], "PRINT", tl) == 0 ) - { - op.cmd = NETWORK_OP_GETRULELIST; - goto doneparsing; - } - - ts = te; - - // get the action - while ( count && (buffer[ts] == ' ') ) { ts++; count--; } // skip spaces. - te = ts; - while ( count && (buffer[te] != ' ') ) { te++; count--; } // command end - if ( te <= ts ) goto bad; - tl = te - ts; - - if ( strncmp(&buffer[ts], "ACCEPT", tl) == 0 ) - { - op.u.net_rule.action = NETWORK_ACTION_ACCEPT; - goto keyval; - } - if ( strncmp(&buffer[ts], "COUNT", tl) == 0 ) - { - op.u.net_rule.action = NETWORK_ACTION_COUNT; - goto keyval; - } - - // default case; - return (len); - - - // get the key=val pairs. - keyval: - while (count) - { - //get field - ts = te; while ( count && isspace(buffer[ts]) ) { ts++; count--; } - te = ts; - while ( count && !isspace(buffer[te]) && (buffer[te] != '=') ) - { te++; count--; } - if ( te <= ts ) - goto doneparsing; - tl = te - ts; - fs = ts; fe = te; fl = tl; // save the field markers. - // skip " = " (ignores extra equals.) - while ( count && (isspace(buffer[te]) || (buffer[te] == '=')) ) - { te++; count--; } - ts = te; - while ( count && !isspace(buffer[te]) ) { te++; count--; } - tl = te - ts; - - if ( (fl <= 0) || (tl <= 0) ) goto bad; - - /* NB. Prefix matches must go first! */ - if (strncmp(&buffer[fs], "src", fl) == 0) - { - op.u.net_rule.src_dom = VIF_SPECIAL; - op.u.net_rule.src_idx = VIF_ANY_INTERFACE; - } - else if (strncmp(&buffer[fs], "dst", fl) == 0) - { - op.u.net_rule.dst_dom = VIF_SPECIAL; - op.u.net_rule.dst_idx = VIF_PHYSICAL_INTERFACE; - } - else if (strncmp(&buffer[fs], "srcaddr", fl) == 0) - { - op.u.net_rule.src_addr = getipaddr(&buffer[ts], tl); - } - else if (strncmp(&buffer[fs], "dstaddr", fl) == 0) - { - op.u.net_rule.dst_addr = getipaddr(&buffer[ts], tl); - } - else if (strncmp(&buffer[fs], "srcaddrmask", fl) == 0) - { - op.u.net_rule.src_addr_mask = getipaddr(&buffer[ts], tl); - } - else if (strncmp(&buffer[fs], "dstaddrmask", fl) == 0) - { - op.u.net_rule.dst_addr_mask = getipaddr(&buffer[ts], tl); - } - else if (strncmp(&buffer[fs], "srcport", fl) == 0) - { - op.u.net_rule.src_port = antous(&buffer[ts], tl); - } - else if (strncmp(&buffer[fs], "dstport", fl) == 0) - { - op.u.net_rule.dst_port = antous(&buffer[ts], tl); - } - else if (strncmp(&buffer[fs], "srcportmask", fl) == 0) - { - op.u.net_rule.src_port_mask = antous(&buffer[ts], tl); - } - else if (strncmp(&buffer[fs], "dstportmask", fl) == 0) - { - op.u.net_rule.dst_port_mask = antous(&buffer[ts], tl); - } - else if (strncmp(&buffer[fs], "srcdom", fl) == 0) - { - op.u.net_rule.src_dom = antoull(&buffer[ts], tl); - } - else if (strncmp(&buffer[fs], "srcidx", fl) == 0) - { - op.u.net_rule.src_idx = anton(&buffer[ts], tl); - } - else if (strncmp(&buffer[fs], "dstdom", fl) == 0) - { - op.u.net_rule.dst_dom = antoull(&buffer[ts], tl); - } - else if (strncmp(&buffer[fs], "dstidx", fl) == 0) - { - op.u.net_rule.dst_idx = anton(&buffer[ts], tl); - } - else if ( (strncmp(&buffer[fs], "proto", fl) == 0)) - { - if (strncmp(&buffer[ts], "any", tl) == 0) - op.u.net_rule.proto = NETWORK_PROTO_ANY; - if (strncmp(&buffer[ts], "ip", tl) == 0) - op.u.net_rule.proto = NETWORK_PROTO_IP; - if (strncmp(&buffer[ts], "tcp", tl) == 0) - op.u.net_rule.proto = NETWORK_PROTO_TCP; - if (strncmp(&buffer[ts], "udp", tl) == 0) - op.u.net_rule.proto = NETWORK_PROTO_UDP; - if (strncmp(&buffer[ts], "arp", tl) == 0) - op.u.net_rule.proto = NETWORK_PROTO_ARP; - } - } - - doneparsing: - ret = HYPERVISOR_network_op(&op); - return(len); - - bad: - return(len); - - -} - -static int __init init_module(void) -{ - if ( !(start_info.flags & SIF_PRIVILEGED) ) - return 0; - - *readbuf = '\0'; - proc_vfr = create_xen_proc_entry("vfr", 0600); - if ( proc_vfr != NULL ) - { - proc_vfr->owner = THIS_MODULE; - proc_vfr->nlink = 1; - proc_vfr->read_proc = vfr_read_proc; - proc_vfr->write_proc = vfr_write_proc; - printk("Successfully installed virtual firewall/router interface\n"); - } - return 0; -} - -static void __exit cleanup_module(void) -{ - if ( proc_vfr == NULL ) return; - remove_xen_proc_entry("vfr"); - proc_vfr = NULL; -} - -module_init(init_module); -module_exit(cleanup_module); - -/* Helper functions start here: */ - -int anton(const char *buff, int len) -{ - int ret; - char c; - int sign = 1; - - ret = 0; - - if (len == 0) return 0; - if (*buff == '-') { sign = -1; buff++; len--; } - - while ( (len) && ((c = *buff) >= '0') && (c <= '9') ) - { - ret *= 10; - ret += c - '0'; - buff++; len--; - } - - ret *= sign; - return ret; -} - -u16 antous(const char *buff, int len) -{ - u16 ret; - char c; - - ret = 0; - - while ( (len) && ((c = *buff) >= '0') && (c <= '9') ) - { - ret *= 10; - ret += c - '0'; - buff++; len--; - } - - return ret; -} - -u64 antoull(const char *buff, int len) -{ - u64 ret; - char c; - - ret = 0; - - while ( (len) && ((c = *buff) >= '0') && (c <= '9') ) - { - ret *= 10; - ret += c - '0'; - buff++; len--; - } - - return ret; -} - -u32 getipaddr(const char *buff, unsigned int len) -{ - char c; - u32 ret, val; - - ret = 0; val = 0; - - while ( len ) - { - if (!((((c = *buff) >= '0') && ( c <= '9')) || ( c == '.' ) ) ) - { - return(0); // malformed. - } - - if ( c == '.' ) { - if (val > 255) return (0); //malformed. - ret = ret << 8; - ret += val; - val = 0; - len--; buff++; - continue; - } - val *= 10; - val += c - '0'; - buff++; len--; - } - ret = ret << 8; - ret += val; - - return (ret); -} - diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c b/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c index 2c4e5cb211..67de998304 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c +++ b/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c @@ -612,7 +612,7 @@ static void netif_page_release(struct page *page) #if 0 long flush_bufs_for_netif(netif_t *netif) { - NET_RING_IDX i; + NETIF_RING_IDX i; /* Return any outstanding receive buffers to the guest OS. */ spin_lock(&netif->rx_lock); @@ -663,7 +663,7 @@ static void make_tx_response(netif_t *netif, u16 id, s8 st) { - NET_RING_IDX i = netif->tx_resp_prod; + NETIF_RING_IDX i = netif->tx_resp_prod; netif_tx_response_t *resp; resp = &netif->tx->ring[MASK_NETIF_TX_IDX(i)].resp; @@ -683,7 +683,7 @@ static int make_rx_response(netif_t *netif, memory_t addr, u16 size) { - NET_RING_IDX i = netif->rx_resp_prod; + NETIF_RING_IDX i = netif->rx_resp_prod; netif_rx_response_t *resp; resp = &netif->rx->ring[MASK_NETIF_RX_IDX(i)].resp; diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/frontend/main.c b/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/frontend/main.c index 4d4c579703..821ad1b0ed 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/frontend/main.c +++ b/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/frontend/main.c @@ -145,7 +145,7 @@ static void network_tx_buf_gc(struct net_device *dev) for ( i = np->tx_resp_cons; i != prod; i++ ) { - id = np->tx->ring[MASK_NET_TX_IDX(i)].resp.id; + id = np->tx->ring[MASK_NETIF_TX_IDX(i)].resp.id; skb = np->tx_skbs[id]; ADD_ID_TO_FREELIST(np->tx_skbs, id); dev_kfree_skb_any(skb); @@ -204,7 +204,7 @@ static void network_alloc_rx_buffers(struct net_device *dev) np->rx_skbs[id] = skb; - np->rx->ring[MASK_NET_RX_IDX(i)].req.id = id; + np->rx->ring[MASK_NETIF_RX_IDX(i)].req.id = id; rx_pfn_array[nr_pfns] = virt_to_machine(skb->head) >> PAGE_SHIFT; @@ -283,7 +283,7 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) id = GET_ID_FROM_FREELIST(np->tx_skbs); np->tx_skbs[id] = skb; - tx = &np->tx->ring[MASK_NET_TX_IDX(i)].req; + tx = &np->tx->ring[MASK_NETIF_TX_IDX(i)].req; tx->id = id; tx->addr = virt_to_machine(skb->data); @@ -366,7 +366,7 @@ static int netif_poll(struct net_device *dev, int *pbudget) (i != np->rx->resp_prod) && (work_done < budget); i++, work_done++ ) { - rx = &np->rx->ring[MASK_NET_RX_IDX(i)].resp; + rx = &np->rx->ring[MASK_NETIF_RX_IDX(i)].resp; skb = np->rx_skbs[rx->id]; ADD_ID_TO_FREELIST(np->rx_skbs, rx->id); @@ -701,8 +701,8 @@ static int __init init_module(void) struct net_device *dev; struct net_private *np; - if ( start_info.flags & SIF_INITDOMAIN - || start_info.flags & SIF_NET_BE_DOMAIN ) + if ( (start_info.flags & SIF_INITDOMAIN) || + (start_info.flags & SIF_NET_BE_DOMAIN) ) return 0; printk("Initialising Xen virtual ethernet frontend driver"); diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/network/Makefile b/linux-2.4.26-xen-sparse/arch/xen/drivers/network/Makefile deleted file mode 100644 index 2e4c1f4825..0000000000 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/network/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -O_TARGET := drv.o -obj-y := network.o -include $(TOPDIR)/Rules.make diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/network/network.c b/linux-2.4.26-xen-sparse/arch/xen/drivers/network/network.c deleted file mode 100644 index e6c340685a..0000000000 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/network/network.c +++ /dev/null @@ -1,656 +0,0 @@ -/****************************************************************************** - * network.c - * - * Virtual network driver for XenoLinux. - * - * Copyright (c) 2002-2003, K A Fraser - */ - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#define RX_BUF_SIZE ((PAGE_SIZE/2)+1) /* Fool the slab allocator :-) */ - -static void network_interrupt(int irq, void *dev_id, struct pt_regs *ptregs); -static void network_tx_buf_gc(struct net_device *dev); -static void network_alloc_rx_buffers(struct net_device *dev); -static void cleanup_module(void); - -/* Dynamically-mapped IRQs. */ -static int network_irq, debug_irq; - -static struct list_head dev_list; - -struct net_private -{ - struct list_head list; - struct net_device *dev; - - struct net_device_stats stats; - NET_RING_IDX rx_resp_cons, tx_resp_cons; - unsigned int net_ring_fixmap_idx, tx_full; - net_ring_t *net_ring; - net_idx_t *net_idx; - spinlock_t tx_lock; - unsigned int idx; /* Domain-specific index of this VIF. */ - - unsigned int rx_bufs_to_notify; - -#define STATE_ACTIVE 0 -#define STATE_SUSPENDED 1 -#define STATE_CLOSED 2 - unsigned int state; - - /* - * {tx,rx}_skbs store outstanding skbuffs. The first entry in each - * array is an index into a chain of free entries. - */ - struct sk_buff *tx_skbs[XENNET_TX_RING_SIZE+1]; - struct sk_buff *rx_skbs[XENNET_RX_RING_SIZE+1]; -}; - -/* Access macros for acquiring freeing slots in {tx,rx}_skbs[]. */ -#define ADD_ID_TO_FREELIST(_list, _id) \ - (_list)[(_id)] = (_list)[0]; \ - (_list)[0] = (void *)(unsigned long)(_id); -#define GET_ID_FROM_FREELIST(_list) \ - ({ unsigned long _id = (unsigned long)(_list)[0]; \ - (_list)[0] = (_list)[_id]; \ - (unsigned short)_id; }) - - -static void _dbg_network_int(struct net_device *dev) -{ - struct net_private *np = dev->priv; - - if ( np->state == STATE_CLOSED ) - return; - - printk(KERN_ALERT "net: tx_full=%d, tx_resp_cons=0x%08x," - " tx_req_prod=0x%08x\nnet: tx_resp_prod=0x%08x," - " tx_event=0x%08x, state=%d\n", - np->tx_full, np->tx_resp_cons, - np->net_idx->tx_req_prod, np->net_idx->tx_resp_prod, - np->net_idx->tx_event, - test_bit(__LINK_STATE_XOFF, &dev->state)); - printk(KERN_ALERT "net: rx_resp_cons=0x%08x," - " rx_req_prod=0x%08x\nnet: rx_resp_prod=0x%08x, rx_event=0x%08x\n", - np->rx_resp_cons, np->net_idx->rx_req_prod, - np->net_idx->rx_resp_prod, np->net_idx->rx_event); -} - - -static void dbg_network_int(int irq, void *unused, struct pt_regs *ptregs) -{ - struct list_head *ent; - struct net_private *np; - list_for_each ( ent, &dev_list ) - { - np = list_entry(ent, struct net_private, list); - _dbg_network_int(np->dev); - } -} - - -static int network_open(struct net_device *dev) -{ - struct net_private *np = dev->priv; - netop_t netop; - int i, ret; - - netop.cmd = NETOP_RESET_RINGS; - netop.vif = np->idx; - if ( (ret = HYPERVISOR_net_io_op(&netop)) != 0 ) - { - printk(KERN_ALERT "Possible net trouble: couldn't reset ring idxs\n"); - return ret; - } - - netop.cmd = NETOP_GET_VIF_INFO; - netop.vif = np->idx; - if ( (ret = HYPERVISOR_net_io_op(&netop)) != 0 ) - { - printk(KERN_ALERT "Couldn't get info for vif %d\n", np->idx); - return ret; - } - - memcpy(dev->dev_addr, netop.u.get_vif_info.vmac, ETH_ALEN); - - set_fixmap(FIX_NETRING0_BASE + np->net_ring_fixmap_idx, - netop.u.get_vif_info.ring_mfn << PAGE_SHIFT); - np->net_ring = (net_ring_t *)fix_to_virt( - FIX_NETRING0_BASE + np->net_ring_fixmap_idx); - np->net_idx = &HYPERVISOR_shared_info->net_idx[np->idx]; - - np->rx_bufs_to_notify = 0; - np->rx_resp_cons = np->tx_resp_cons = np->tx_full = 0; - memset(&np->stats, 0, sizeof(np->stats)); - spin_lock_init(&np->tx_lock); - memset(np->net_ring, 0, sizeof(*np->net_ring)); - memset(np->net_idx, 0, sizeof(*np->net_idx)); - - /* Initialise {tx,rx}_skbs to be a free chain containing every entry. */ - for ( i = 0; i <= XENNET_TX_RING_SIZE; i++ ) - np->tx_skbs[i] = (void *)(i+1); - for ( i = 0; i <= XENNET_RX_RING_SIZE; i++ ) - np->rx_skbs[i] = (void *)(i+1); - - wmb(); - np->state = STATE_ACTIVE; - - network_alloc_rx_buffers(dev); - - netif_start_queue(dev); - - MOD_INC_USE_COUNT; - - return 0; -} - - -static void network_tx_buf_gc(struct net_device *dev) -{ - NET_RING_IDX i, prod; - unsigned short id; - struct net_private *np = dev->priv; - struct sk_buff *skb; - tx_entry_t *tx_ring = np->net_ring->tx_ring; - - do { - prod = np->net_idx->tx_resp_prod; - - for ( i = np->tx_resp_cons; i != prod; i++ ) - { - id = tx_ring[MASK_NET_TX_IDX(i)].resp.id; - skb = np->tx_skbs[id]; - ADD_ID_TO_FREELIST(np->tx_skbs, id); - dev_kfree_skb_any(skb); - } - - np->tx_resp_cons = prod; - - /* - * Set a new event, then check for race with update of tx_cons. Note - * that it is essential to schedule a callback, no matter how few - * buffers are pending. Even if there is space in the transmit ring, - * higher layers may be blocked because too much data is outstanding: - * in such cases notification from Xen is likely to be the only kick - * that we'll get. - */ - np->net_idx->tx_event = - prod + ((np->net_idx->tx_req_prod - prod) >> 1) + 1; - mb(); - } - while ( prod != np->net_idx->tx_resp_prod ); - - if ( np->tx_full && - ((np->net_idx->tx_req_prod - prod) < XENNET_TX_RING_SIZE) ) - { - np->tx_full = 0; - if ( np->state == STATE_ACTIVE ) - netif_wake_queue(dev); - } -} - - -static inline pte_t *get_ppte(void *addr) -{ - pgd_t *pgd; pmd_t *pmd; pte_t *pte; - pgd = pgd_offset_k( (unsigned long)addr); - pmd = pmd_offset(pgd, (unsigned long)addr); - pte = pte_offset(pmd, (unsigned long)addr); - return pte; -} - - -static void network_alloc_rx_buffers(struct net_device *dev) -{ - unsigned short id; - struct net_private *np = dev->priv; - struct sk_buff *skb; - netop_t netop; - NET_RING_IDX i = np->net_idx->rx_req_prod; - - if ( unlikely((i - np->rx_resp_cons) == XENNET_RX_RING_SIZE) || - unlikely(np->state != STATE_ACTIVE) ) - return; - - do { - skb = dev_alloc_skb(RX_BUF_SIZE); - if ( unlikely(skb == NULL) ) - break; - - skb->dev = dev; - - if ( unlikely(((unsigned long)skb->head & (PAGE_SIZE-1)) != 0) ) - panic("alloc_skb needs to provide us page-aligned buffers."); - - id = GET_ID_FROM_FREELIST(np->rx_skbs); - np->rx_skbs[id] = skb; - - np->net_ring->rx_ring[MASK_NET_RX_IDX(i)].req.id = id; - np->net_ring->rx_ring[MASK_NET_RX_IDX(i)].req.addr = - virt_to_machine(get_ppte(skb->head)); - - /* Shadow optimisation: disown this page from p->m map */ - phys_to_machine_mapping[virt_to_phys(skb->head)>>PAGE_SHIFT] = 0x80000004; - np->rx_bufs_to_notify++; - } - while ( (++i - np->rx_resp_cons) != XENNET_RX_RING_SIZE ); - - /* - * We may have allocated buffers which have entries outstanding in the page - * update queue -- make sure we flush those first! - */ - flush_page_update_queue(); - - np->net_idx->rx_req_prod = i; - np->net_idx->rx_event = np->rx_resp_cons + 1; - - /* Batch Xen notifications. */ - if ( np->rx_bufs_to_notify > (XENNET_RX_RING_SIZE/4) ) - { - netop.cmd = NETOP_PUSH_BUFFERS; - netop.vif = np->idx; - (void)HYPERVISOR_net_io_op(&netop); - np->rx_bufs_to_notify = 0; - } -} - - -static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - unsigned short id; - struct net_private *np = (struct net_private *)dev->priv; - tx_req_entry_t *tx; - netop_t netop; - NET_RING_IDX i; - - if ( unlikely(np->tx_full) ) - { - printk(KERN_ALERT "%s: full queue wasn't stopped!\n", dev->name); - netif_stop_queue(dev); - return -ENOBUFS; - } - - if ( unlikely((((unsigned long)skb->data & ~PAGE_MASK) + skb->len) >= - PAGE_SIZE) ) - { - struct sk_buff *new_skb = dev_alloc_skb(RX_BUF_SIZE); - if ( unlikely(new_skb == NULL) ) - return 1; - skb_put(new_skb, skb->len); - memcpy(new_skb->data, skb->data, skb->len); - dev_kfree_skb(skb); - skb = new_skb; - } - - spin_lock_irq(&np->tx_lock); - - i = np->net_idx->tx_req_prod; - - id = GET_ID_FROM_FREELIST(np->tx_skbs); - np->tx_skbs[id] = skb; - - tx = &np->net_ring->tx_ring[MASK_NET_TX_IDX(i)].req; - - tx->id = id; - tx->addr = phys_to_machine(virt_to_phys(skb->data)); - tx->size = skb->len; - - wmb(); - np->net_idx->tx_req_prod = i + 1; - - network_tx_buf_gc(dev); - - if ( (i - np->tx_resp_cons) == (XENNET_TX_RING_SIZE - 1) ) - { - np->tx_full = 1; - netif_stop_queue(dev); - } - - spin_unlock_irq(&np->tx_lock); - - np->stats.tx_bytes += skb->len; - np->stats.tx_packets++; - - /* Only notify Xen if there are no outstanding responses. */ - mb(); - if ( np->net_idx->tx_resp_prod == i ) - { - netop.cmd = NETOP_PUSH_BUFFERS; - netop.vif = np->idx; - (void)HYPERVISOR_net_io_op(&netop); - } - - return 0; -} - - -static inline void _network_interrupt(struct net_device *dev) -{ - struct net_private *np = dev->priv; - unsigned long flags; - struct sk_buff *skb; - rx_resp_entry_t *rx; - NET_RING_IDX i; - - if ( unlikely(np->state == STATE_CLOSED) ) - return; - - spin_lock_irqsave(&np->tx_lock, flags); - network_tx_buf_gc(dev); - spin_unlock_irqrestore(&np->tx_lock, flags); - - again: - for ( i = np->rx_resp_cons; i != np->net_idx->rx_resp_prod; i++ ) - { - rx = &np->net_ring->rx_ring[MASK_NET_RX_IDX(i)].resp; - - skb = np->rx_skbs[rx->id]; - ADD_ID_TO_FREELIST(np->rx_skbs, rx->id); - -/* XXXXX this is unsafe for live migrate -- if we do a scan be fore this -point we won't transmit the right mfn! We have to fix this up in -xc_linux_save */ - - phys_to_machine_mapping[virt_to_phys(skb->head) >> PAGE_SHIFT] = - (*(unsigned long *)get_ppte(skb->head)) >> PAGE_SHIFT; - - if ( unlikely(rx->status != RING_STATUS_OK) ) - { - /* Gate this error. We get a (valid) slew of them on suspend. */ - if ( np->state == STATE_ACTIVE ) - { - /* With live migrate, we even get these... Disable for now. */ - // printk(KERN_ALERT "bad buffer on RX ring!(%d)\n", rx->status); - } - else - phys_to_machine_mapping[virt_to_phys(skb->head) >> PAGE_SHIFT] = - 0x80000004; // disown this page -- it was a flush - - dev_kfree_skb_any(skb); - continue; - } - - /* - * Set up shinfo -- from alloc_skb This was particularily nasty: the - * shared info is hidden at the back of the data area (presumably so it - * can be shared), but on page flip it gets very spunked. - */ - atomic_set(&(skb_shinfo(skb)->dataref), 1); - skb_shinfo(skb)->nr_frags = 0; - skb_shinfo(skb)->frag_list = NULL; - - skb->data = skb->tail = skb->head + rx->offset; - skb_put(skb, rx->size); - skb->protocol = eth_type_trans(skb, dev); - - np->stats.rx_packets++; - - np->stats.rx_bytes += rx->size; - netif_rx(skb); - dev->last_rx = jiffies; - } - - np->rx_resp_cons = i; - - network_alloc_rx_buffers(dev); - - /* Deal with hypervisor racing our resetting of rx_event. */ - mb(); - if ( np->net_idx->rx_resp_prod != i ) - goto again; -} - - -static void network_interrupt(int irq, void *unused, struct pt_regs *ptregs) -{ - struct list_head *ent; - struct net_private *np; - list_for_each ( ent, &dev_list ) - { - np = list_entry(ent, struct net_private, list); - _network_interrupt(np->dev); - } -} - - -static int network_close(struct net_device *dev) -{ - struct net_private *np = dev->priv; - netop_t netop; - - np->state = STATE_SUSPENDED; - wmb(); - - netif_stop_queue(np->dev); - - netop.cmd = NETOP_FLUSH_BUFFERS; - netop.vif = np->idx; - (void)HYPERVISOR_net_io_op(&netop); - - while ( (np->rx_resp_cons != np->net_idx->rx_req_prod) || - (np->tx_resp_cons != np->net_idx->tx_req_prod) ) - { - barrier(); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - } - - wmb(); - np->state = STATE_CLOSED; - wmb(); - - /* Now no longer safe to take interrupts for this device. */ - clear_fixmap(FIX_NETRING0_BASE + np->net_ring_fixmap_idx); - - MOD_DEC_USE_COUNT; - - return 0; -} - - -static struct net_device_stats *network_get_stats(struct net_device *dev) -{ - struct net_private *np = (struct net_private *)dev->priv; - return &np->stats; -} - - -/* - * This notifier is installed for domain 0 only. - * All other domains have VFR rules installed on their behalf by domain 0 - * when they are created. For bootstrap, Xen creates wildcard rules for - * domain 0 -- this notifier is used to detect when we find our proper - * IP address, so we can poke down proper rules and remove the wildcards. - */ -static int inetdev_notify(struct notifier_block *this, - unsigned long event, - void *ptr) -{ - struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; - struct net_device *dev = ifa->ifa_dev->dev; - struct list_head *ent; - struct net_private *np; - int idx = -1; - network_op_t op; - - list_for_each ( ent, &dev_list ) - { - np = list_entry(dev_list.next, struct net_private, list); - if ( np->dev == dev ) - idx = np->idx; - } - - if ( idx == -1 ) - goto out; - - memset(&op, 0, sizeof(op)); - op.u.net_rule.proto = NETWORK_PROTO_ANY; - op.u.net_rule.action = NETWORK_ACTION_ACCEPT; - - if ( event == NETDEV_UP ) - op.cmd = NETWORK_OP_ADDRULE; - else if ( event == NETDEV_DOWN ) - op.cmd = NETWORK_OP_DELETERULE; - else - goto out; - - op.u.net_rule.src_dom = 0; - op.u.net_rule.src_idx = idx; - op.u.net_rule.dst_dom = VIF_SPECIAL; - op.u.net_rule.dst_idx = VIF_PHYSICAL_INTERFACE; - op.u.net_rule.src_addr = ntohl(ifa->ifa_address); - op.u.net_rule.src_addr_mask = ~0UL; - op.u.net_rule.dst_addr = 0; - op.u.net_rule.dst_addr_mask = 0; - (void)HYPERVISOR_network_op(&op); - - op.u.net_rule.src_dom = VIF_SPECIAL; - op.u.net_rule.src_idx = VIF_ANY_INTERFACE; - op.u.net_rule.dst_dom = 0; - op.u.net_rule.dst_idx = idx; - op.u.net_rule.src_addr = 0; - op.u.net_rule.src_addr_mask = 0; - op.u.net_rule.dst_addr = ntohl(ifa->ifa_address); - op.u.net_rule.dst_addr_mask = ~0UL; - (void)HYPERVISOR_network_op(&op); - - out: - return NOTIFY_DONE; -} - -static struct notifier_block notifier_inetdev = { - .notifier_call = inetdev_notify, - .next = NULL, - .priority = 0 -}; - - -static int __init init_module(void) -{ - int i, fixmap_idx=-1, err; - struct net_device *dev; - struct net_private *np; - netop_t netop; - - INIT_LIST_HEAD(&dev_list); - - /* - * Domain 0 must poke its own network rules as it discovers its IP - * addresses. All other domains have a privileged "parent" to do this for - * them at start of day. - */ - if ( start_info.flags & SIF_INITDOMAIN ) - (void)register_inetaddr_notifier(¬ifier_inetdev); - - network_irq = bind_virq_to_irq(VIRQ_NET); - debug_irq = bind_virq_to_irq(VIRQ_DEBUG); - - err = request_irq(network_irq, network_interrupt, - SA_SAMPLE_RANDOM, "network", NULL); - if ( err ) - { - printk(KERN_WARNING "Could not allocate network interrupt\n"); - goto fail; - } - - err = request_irq(debug_irq, dbg_network_int, - SA_SHIRQ, "net_dbg", &dbg_network_int); - if ( err ) - printk(KERN_WARNING "Non-fatal error -- no debug interrupt\n"); - - for ( i = 0; i < MAX_DOMAIN_VIFS; i++ ) - { - /* If the VIF is invalid then the query hypercall will fail. */ - netop.cmd = NETOP_GET_VIF_INFO; - netop.vif = i; - if ( HYPERVISOR_net_io_op(&netop) != 0 ) - continue; - - /* We actually only support up to 4 vifs right now. */ - if ( ++fixmap_idx == 4 ) - break; - - dev = alloc_etherdev(sizeof(struct net_private)); - if ( dev == NULL ) - { - err = -ENOMEM; - goto fail; - } - - np = dev->priv; - np->state = STATE_CLOSED; - np->net_ring_fixmap_idx = fixmap_idx; - np->idx = i; - - SET_MODULE_OWNER(dev); - dev->open = network_open; - dev->hard_start_xmit = network_start_xmit; - dev->stop = network_close; - dev->get_stats = network_get_stats; - - memcpy(dev->dev_addr, netop.u.get_vif_info.vmac, ETH_ALEN); - - if ( (err = register_netdev(dev)) != 0 ) - { - kfree(dev); - goto fail; - } - - np->dev = dev; - list_add(&np->list, &dev_list); - } - - return 0; - - fail: - cleanup_module(); - return err; -} - - -static void cleanup_module(void) -{ - struct net_private *np; - struct net_device *dev; - - while ( !list_empty(&dev_list) ) - { - np = list_entry(dev_list.next, struct net_private, list); - list_del(&np->list); - dev = np->dev; - unregister_netdev(dev); - kfree(dev); - } - - if ( start_info.flags & SIF_INITDOMAIN ) - (void)unregister_inetaddr_notifier(¬ifier_inetdev); - - free_irq(network_irq, NULL); - free_irq(debug_irq, NULL); - - unbind_virq_from_irq(VIRQ_NET); - unbind_virq_from_irq(VIRQ_DEBUG); -} - - -module_init(init_module); -module_exit(cleanup_module); diff --git a/linux-2.4.26-xen-sparse/drivers/block/ll_rw_blk.c b/linux-2.4.26-xen-sparse/drivers/block/ll_rw_blk.c index d219c28403..a7f03c0fd5 100644 --- a/linux-2.4.26-xen-sparse/drivers/block/ll_rw_blk.c +++ b/linux-2.4.26-xen-sparse/drivers/block/ll_rw_blk.c @@ -1626,7 +1626,7 @@ int __init blk_dev_init(void) jsfd_init(); #endif -#if defined(CONFIG_XEN_VBD) || defined(CONFIG_XEN_NEWIO) +#if defined(CONFIG_XEN) xlblk_init(); #endif diff --git a/linux-2.4.26-xen-sparse/include/asm-xen/hypervisor.h b/linux-2.4.26-xen-sparse/include/asm-xen/hypervisor.h index c341fe5990..d70338ae52 100644 --- a/linux-2.4.26-xen-sparse/include/asm-xen/hypervisor.h +++ b/linux-2.4.26-xen-sparse/include/asm-xen/hypervisor.h @@ -210,17 +210,6 @@ static inline int HYPERVISOR_set_callbacks( return ret; } -static inline int HYPERVISOR_net_io_op(netop_t *op) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_net_io_op), - "b" (op) : "memory" ); - - return ret; -} - static inline int HYPERVISOR_fpu_taskswitch(void) { int ret; @@ -315,28 +304,6 @@ static inline int HYPERVISOR_dom0_op(dom0_op_t *dom0_op) return ret; } -static inline int HYPERVISOR_network_op(void *network_op) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_network_op), - "b" (network_op) : "memory" ); - - return ret; -} - -static inline int HYPERVISOR_block_io_op(void *block_io_op) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_block_io_op), - "b" (block_io_op) : "memory" ); - - return ret; -} - static inline int HYPERVISOR_set_debugreg(int reg, unsigned long value) { int ret; diff --git a/linux-2.4.26-xen-sparse/include/linux/blk.h b/linux-2.4.26-xen-sparse/include/linux/blk.h index e7c7575454..d032dff7ba 100644 --- a/linux-2.4.26-xen-sparse/include/linux/blk.h +++ b/linux-2.4.26-xen-sparse/include/linux/blk.h @@ -55,9 +55,9 @@ extern int xpram_init(void); extern int tapeblock_init(void); #endif /* CONFIG_ARCH_S390 */ -#if defined(CONFIG_XEN_VBD) +#if defined(CONFIG_XEN) extern int xlblk_init(void); -#endif /* CONFIG_XEN_VBD */ +#endif /* CONFIG_XEN */ extern void set_device_ro(kdev_t dev,int flag); void add_blkdev_randomness(int major); diff --git a/linux-2.4.26-xen-sparse/include/linux/major.h b/linux-2.4.26-xen-sparse/include/linux/major.h deleted file mode 100644 index f311bd4a9d..0000000000 --- a/linux-2.4.26-xen-sparse/include/linux/major.h +++ /dev/null @@ -1,206 +0,0 @@ -#ifndef _LINUX_MAJOR_H -#define _LINUX_MAJOR_H - -/* - * This file has definitions for major device numbers. - * For the device number assignments, see Documentation/devices.txt. - */ - -/* limits */ - -/* - * Important: Don't change this to 256. Major number 255 is and must be - * reserved for future expansion into a larger dev_t space. - */ -#define MAX_CHRDEV 255 -#define MAX_BLKDEV 255 - -#define UNNAMED_MAJOR 0 -#define MEM_MAJOR 1 -#define RAMDISK_MAJOR 1 -#define FLOPPY_MAJOR 2 -#define PTY_MASTER_MAJOR 2 -#define IDE0_MAJOR 3 -#define PTY_SLAVE_MAJOR 3 -#define HD_MAJOR IDE0_MAJOR -#define TTY_MAJOR 4 -#define TTYAUX_MAJOR 5 -#define LP_MAJOR 6 -#define VCS_MAJOR 7 -#define LOOP_MAJOR 7 -#define SCSI_DISK0_MAJOR 8 -#define SCSI_TAPE_MAJOR 9 -#define MD_MAJOR 9 -#define MISC_MAJOR 10 -#define SCSI_CDROM_MAJOR 11 -#define MUX_MAJOR 11 /* PA-RISC only */ -#define QIC02_TAPE_MAJOR 12 -#define XT_DISK_MAJOR 13 -#define SOUND_MAJOR 14 -#define CDU31A_CDROM_MAJOR 15 -#define JOYSTICK_MAJOR 15 -#define GOLDSTAR_CDROM_MAJOR 16 -#define OPTICS_CDROM_MAJOR 17 -#define SANYO_CDROM_MAJOR 18 -#define CYCLADES_MAJOR 19 -#define CYCLADESAUX_MAJOR 20 -#define MITSUMI_X_CDROM_MAJOR 20 -#define MFM_ACORN_MAJOR 21 /* ARM Linux /dev/mfm */ -#define SCSI_GENERIC_MAJOR 21 -#define Z8530_MAJOR 34 -#define DIGI_MAJOR 23 -#define IDE1_MAJOR 22 -#define DIGICU_MAJOR 22 -#define MITSUMI_CDROM_MAJOR 23 -#define CDU535_CDROM_MAJOR 24 -#define STL_SERIALMAJOR 24 -#define MATSUSHITA_CDROM_MAJOR 25 -#define STL_CALLOUTMAJOR 25 -#define MATSUSHITA_CDROM2_MAJOR 26 -#define QIC117_TAPE_MAJOR 27 -#define MATSUSHITA_CDROM3_MAJOR 27 -#define MATSUSHITA_CDROM4_MAJOR 28 -#define STL_SIOMEMMAJOR 28 -#define ACSI_MAJOR 28 -#define AZTECH_CDROM_MAJOR 29 -#define GRAPHDEV_MAJOR 29 /* SparcLinux & Linux/68k /dev/fb */ -#define SHMIQ_MAJOR 85 /* Linux/mips, SGI /dev/shmiq */ -#define CM206_CDROM_MAJOR 32 -#define IDE2_MAJOR 33 -#define IDE3_MAJOR 34 -#define XPRAM_MAJOR 35 /* expanded storage on S/390 = "slow ram" */ - /* proposed by Peter */ -#define NETLINK_MAJOR 36 -#define PS2ESDI_MAJOR 36 -#define IDETAPE_MAJOR 37 -#define Z2RAM_MAJOR 37 -#define APBLOCK_MAJOR 38 /* AP1000 Block device */ -#define DDV_MAJOR 39 /* AP1000 DDV block device */ -#define NBD_MAJOR 43 /* Network block device */ -#define RISCOM8_NORMAL_MAJOR 48 -#define DAC960_MAJOR 48 /* 48..55 */ -#define RISCOM8_CALLOUT_MAJOR 49 -#define MKISS_MAJOR 55 -#define DSP56K_MAJOR 55 /* DSP56001 processor device */ - -#define IDE4_MAJOR 56 -#define IDE5_MAJOR 57 - -#define LVM_BLK_MAJOR 58 /* Logical Volume Manager */ - -#define SCSI_DISK1_MAJOR 65 -#define SCSI_DISK2_MAJOR 66 -#define SCSI_DISK3_MAJOR 67 -#define SCSI_DISK4_MAJOR 68 -#define SCSI_DISK5_MAJOR 69 -#define SCSI_DISK6_MAJOR 70 -#define SCSI_DISK7_MAJOR 71 - - -#define COMPAQ_SMART2_MAJOR 72 -#define COMPAQ_SMART2_MAJOR1 73 -#define COMPAQ_SMART2_MAJOR2 74 -#define COMPAQ_SMART2_MAJOR3 75 -#define COMPAQ_SMART2_MAJOR4 76 -#define COMPAQ_SMART2_MAJOR5 77 -#define COMPAQ_SMART2_MAJOR6 78 -#define COMPAQ_SMART2_MAJOR7 79 - -#define SPECIALIX_NORMAL_MAJOR 75 -#define SPECIALIX_CALLOUT_MAJOR 76 - -#define COMPAQ_CISS_MAJOR 104 -#define COMPAQ_CISS_MAJOR1 105 -#define COMPAQ_CISS_MAJOR2 106 -#define COMPAQ_CISS_MAJOR3 107 -#define COMPAQ_CISS_MAJOR4 108 -#define COMPAQ_CISS_MAJOR5 109 -#define COMPAQ_CISS_MAJOR6 110 -#define COMPAQ_CISS_MAJOR7 111 - -#define ATARAID_MAJOR 114 - -#define DASD_MAJOR 94 /* Official assignations from Peter */ - -#define MDISK_MAJOR 95 /* Official assignations from Peter */ - -#define I2O_MAJOR 80 /* 80->87 */ - -#define IDE6_MAJOR 88 -#define IDE7_MAJOR 89 -#define IDE8_MAJOR 90 -#define IDE9_MAJOR 91 - -#define UBD_MAJOR 98 - -#define AURORA_MAJOR 79 - -#define JSFD_MAJOR 99 - -#define PHONE_MAJOR 100 - -#define LVM_CHAR_MAJOR 109 /* Logical Volume Manager */ - -#define UMEM_MAJOR 116 /* http://www.umem.com/ Battery Backed RAM */ - -#define UMEM_MAJOR 116 /* http://www.umem.com/ Battery Backed RAM */ - -/* - * XLVIRT supports 16 devices of <= 16 partitions each. - * eg. xvda == (125, 0), xvdb == (125, 16), ... - */ -#define XLVIRT_MAJOR 125 - -#define RTF_MAJOR 150 -#define RAW_MAJOR 162 - -#define USB_ACM_MAJOR 166 -#define USB_ACM_AUX_MAJOR 167 -#define USB_CHAR_MAJOR 180 - -#define UNIX98_PTY_MASTER_MAJOR 128 -#define UNIX98_PTY_MAJOR_COUNT 8 -#define UNIX98_PTY_SLAVE_MAJOR (UNIX98_PTY_MASTER_MAJOR+UNIX98_PTY_MAJOR_COUNT) - -#define VXVM_MAJOR 199 /* VERITAS volume i/o driver */ -#define VXSPEC_MAJOR 200 /* VERITAS volume config driver */ -#define VXDMP_MAJOR 201 /* VERITAS volume multipath driver */ - -#define MSR_MAJOR 202 -#define CPUID_MAJOR 203 - -#define OSST_MAJOR 206 /* OnStream-SCx0 SCSI tape */ - -#define IBM_TTY3270_MAJOR 227 /* Official allocations now */ -#define IBM_FS3270_MAJOR 228 - -/* - * Tests for SCSI devices. - */ - -#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \ - ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR)) - -#define SCSI_BLK_MAJOR(M) \ - (SCSI_DISK_MAJOR(M) \ - || (M) == SCSI_CDROM_MAJOR) - -static __inline__ int scsi_blk_major(int m) { - return SCSI_BLK_MAJOR(m); -} - -/* - * Tests for IDE devices - */ -#define IDE_DISK_MAJOR(M) ((M) == IDE0_MAJOR || (M) == IDE1_MAJOR || \ - (M) == IDE2_MAJOR || (M) == IDE3_MAJOR || \ - (M) == IDE4_MAJOR || (M) == IDE5_MAJOR || \ - (M) == IDE6_MAJOR || (M) == IDE7_MAJOR || \ - (M) == IDE8_MAJOR || (M) == IDE9_MAJOR) - -static __inline__ int ide_blk_major(int m) -{ - return IDE_DISK_MAJOR(m); -} - -#endif diff --git a/linux-2.4.26-xen-sparse/init/do_mounts.c b/linux-2.4.26-xen-sparse/init/do_mounts.c deleted file mode 100644 index 6d09888fc8..0000000000 --- a/linux-2.4.26-xen-sparse/init/do_mounts.c +++ /dev/null @@ -1,1084 +0,0 @@ -#define __KERNEL_SYSCALLS__ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define BUILD_CRAMDISK - -extern int get_filesystem_list(char * buf); - -extern asmlinkage long sys_mount(char *dev_name, char *dir_name, char *type, - unsigned long flags, void *data); -extern asmlinkage long sys_mkdir(const char *name, int mode); -extern asmlinkage long sys_chdir(const char *name); -extern asmlinkage long sys_fchdir(int fd); -extern asmlinkage long sys_chroot(const char *name); -extern asmlinkage long sys_unlink(const char *name); -extern asmlinkage long sys_symlink(const char *old, const char *new); -extern asmlinkage long sys_mknod(const char *name, int mode, dev_t dev); -extern asmlinkage long sys_umount(char *name, int flags); -extern asmlinkage long sys_ioctl(int fd, int cmd, unsigned long arg); - -#ifdef CONFIG_BLK_DEV_INITRD -unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */ -static int __initdata mount_initrd = 1; - -static int __init no_initrd(char *str) -{ - mount_initrd = 0; - return 1; -} - -__setup("noinitrd", no_initrd); -#else -static int __initdata mount_initrd = 0; -#endif - -int __initdata rd_doload; /* 1 = load RAM disk, 0 = don't load */ - -int root_mountflags = MS_RDONLY | MS_VERBOSE; -static char root_device_name[64]; - -/* this is initialized in init/main.c */ -kdev_t ROOT_DEV; - -static int do_devfs = 0; - -static int __init load_ramdisk(char *str) -{ - rd_doload = simple_strtol(str,NULL,0) & 3; - return 1; -} -__setup("load_ramdisk=", load_ramdisk); - -static int __init readonly(char *str) -{ - if (*str) - return 0; - root_mountflags |= MS_RDONLY; - return 1; -} - -static int __init readwrite(char *str) -{ - if (*str) - return 0; - root_mountflags &= ~MS_RDONLY; - return 1; -} - -__setup("ro", readonly); -__setup("rw", readwrite); - -static struct dev_name_struct { - const char *name; - const int num; -} root_dev_names[] __initdata = { - { "nfs", MKDEV(NFS_MAJOR, NFS_MINOR) }, - { "hda", 0x0300 }, - { "hdb", 0x0340 }, - { "loop", 0x0700 }, - { "hdc", 0x1600 }, - { "hdd", 0x1640 }, - { "hde", 0x2100 }, - { "hdf", 0x2140 }, - { "hdg", 0x2200 }, - { "hdh", 0x2240 }, - { "hdi", 0x3800 }, - { "hdj", 0x3840 }, - { "hdk", 0x3900 }, - { "hdl", 0x3940 }, - { "hdm", 0x5800 }, - { "hdn", 0x5840 }, - { "hdo", 0x5900 }, - { "hdp", 0x5940 }, - { "hdq", 0x5A00 }, - { "hdr", 0x5A40 }, - { "hds", 0x5B00 }, - { "hdt", 0x5B40 }, - { "sda", 0x0800 }, - { "sdb", 0x0810 }, - { "sdc", 0x0820 }, - { "sdd", 0x0830 }, - { "sde", 0x0840 }, - { "sdf", 0x0850 }, - { "sdg", 0x0860 }, - { "sdh", 0x0870 }, - { "sdi", 0x0880 }, - { "sdj", 0x0890 }, - { "sdk", 0x08a0 }, - { "sdl", 0x08b0 }, - { "sdm", 0x08c0 }, - { "sdn", 0x08d0 }, - { "sdo", 0x08e0 }, - { "sdp", 0x08f0 }, - { "ada", 0x1c00 }, - { "adb", 0x1c10 }, - { "adc", 0x1c20 }, - { "add", 0x1c30 }, - { "ade", 0x1c40 }, - { "fd", 0x0200 }, - { "md", 0x0900 }, - { "xda", 0x0d00 }, - { "xdb", 0x0d40 }, - { "ram", 0x0100 }, - { "scd", 0x0b00 }, - { "mcd", 0x1700 }, - { "cdu535", 0x1800 }, - { "sonycd", 0x1800 }, - { "aztcd", 0x1d00 }, - { "cm206cd", 0x2000 }, - { "gscd", 0x1000 }, - { "sbpcd", 0x1900 }, - { "eda", 0x2400 }, - { "edb", 0x2440 }, - { "pda", 0x2d00 }, - { "pdb", 0x2d10 }, - { "pdc", 0x2d20 }, - { "pdd", 0x2d30 }, - { "pcd", 0x2e00 }, - { "pf", 0x2f00 }, - { "apblock", APBLOCK_MAJOR << 8}, - { "ddv", DDV_MAJOR << 8}, - { "jsfd", JSFD_MAJOR << 8}, -#if defined(CONFIG_ARCH_S390) - { "dasda", (DASD_MAJOR << MINORBITS) }, - { "dasdb", (DASD_MAJOR << MINORBITS) + (1 << 2) }, - { "dasdc", (DASD_MAJOR << MINORBITS) + (2 << 2) }, - { "dasdd", (DASD_MAJOR << MINORBITS) + (3 << 2) }, - { "dasde", (DASD_MAJOR << MINORBITS) + (4 << 2) }, - { "dasdf", (DASD_MAJOR << MINORBITS) + (5 << 2) }, - { "dasdg", (DASD_MAJOR << MINORBITS) + (6 << 2) }, - { "dasdh", (DASD_MAJOR << MINORBITS) + (7 << 2) }, -#endif - { "ida/c0d0p",0x4800 }, - { "ida/c0d1p",0x4810 }, - { "ida/c0d2p",0x4820 }, - { "ida/c0d3p",0x4830 }, - { "ida/c0d4p",0x4840 }, - { "ida/c0d5p",0x4850 }, - { "ida/c0d6p",0x4860 }, - { "ida/c0d7p",0x4870 }, - { "ida/c0d8p",0x4880 }, - { "ida/c0d9p",0x4890 }, - { "ida/c0d10p",0x48A0 }, - { "ida/c0d11p",0x48B0 }, - { "ida/c0d12p",0x48C0 }, - { "ida/c0d13p",0x48D0 }, - { "ida/c0d14p",0x48E0 }, - { "ida/c0d15p",0x48F0 }, - { "ida/c1d0p",0x4900 }, - { "ida/c2d0p",0x4A00 }, - { "ida/c3d0p",0x4B00 }, - { "ida/c4d0p",0x4C00 }, - { "ida/c5d0p",0x4D00 }, - { "ida/c6d0p",0x4E00 }, - { "ida/c7d0p",0x4F00 }, - { "cciss/c0d0p",0x6800 }, - { "cciss/c0d1p",0x6810 }, - { "cciss/c0d2p",0x6820 }, - { "cciss/c0d3p",0x6830 }, - { "cciss/c0d4p",0x6840 }, - { "cciss/c0d5p",0x6850 }, - { "cciss/c0d6p",0x6860 }, - { "cciss/c0d7p",0x6870 }, - { "cciss/c0d8p",0x6880 }, - { "cciss/c0d9p",0x6890 }, - { "cciss/c0d10p",0x68A0 }, - { "cciss/c0d11p",0x68B0 }, - { "cciss/c0d12p",0x68C0 }, - { "cciss/c0d13p",0x68D0 }, - { "cciss/c0d14p",0x68E0 }, - { "cciss/c0d15p",0x68F0 }, - { "cciss/c1d0p",0x6900 }, - { "cciss/c2d0p",0x6A00 }, - { "cciss/c3d0p",0x6B00 }, - { "cciss/c4d0p",0x6C00 }, - { "cciss/c5d0p",0x6D00 }, - { "cciss/c6d0p",0x6E00 }, - { "cciss/c7d0p",0x6F00 }, - { "ataraid/d0p",0x7200 }, - { "ataraid/d1p",0x7210 }, - { "ataraid/d2p",0x7220 }, - { "ataraid/d3p",0x7230 }, - { "ataraid/d4p",0x7240 }, - { "ataraid/d5p",0x7250 }, - { "ataraid/d6p",0x7260 }, - { "ataraid/d7p",0x7270 }, - { "ataraid/d8p",0x7280 }, - { "ataraid/d9p",0x7290 }, - { "ataraid/d10p",0x72A0 }, - { "ataraid/d11p",0x72B0 }, - { "ataraid/d12p",0x72C0 }, - { "ataraid/d13p",0x72D0 }, - { "ataraid/d14p",0x72E0 }, - { "ataraid/d15p",0x72F0 }, - { "rd/c0d0p",0x3000 }, - { "rd/c0d0p1",0x3001 }, - { "rd/c0d0p2",0x3002 }, - { "rd/c0d0p3",0x3003 }, - { "rd/c0d0p4",0x3004 }, - { "rd/c0d0p5",0x3005 }, - { "rd/c0d0p6",0x3006 }, - { "rd/c0d0p7",0x3007 }, - { "rd/c0d0p8",0x3008 }, - { "rd/c0d1p",0x3008 }, - { "rd/c0d1p1",0x3009 }, - { "rd/c0d1p2",0x300a }, - { "rd/c0d1p3",0x300b }, - { "rd/c0d1p4",0x300c }, - { "rd/c0d1p5",0x300d }, - { "rd/c0d1p6",0x300e }, - { "rd/c0d1p7",0x300f }, - { "rd/c0d1p8",0x3010 }, - { "nftla", 0x5d00 }, - { "nftlb", 0x5d10 }, - { "nftlc", 0x5d20 }, - { "nftld", 0x5d30 }, - { "ftla", 0x2c00 }, - { "ftlb", 0x2c08 }, - { "ftlc", 0x2c10 }, - { "ftld", 0x2c18 }, - { "mtdblock", 0x1f00 }, - { "nb", 0x2b00 }, -#if defined(CONFIG_XEN_VBD) - { "xvda", 0x7D00 }, { "xvdb", 0x7D10 }, - { "xvdc", 0x7D20 }, { "xvdd", 0x7D30 }, - { "xvde", 0x7D40 }, { "xvdf", 0x7D50 }, - { "xvdg", 0x7D60 }, { "xvdh", 0x7D70 }, - { "xvdi", 0x7D80 }, { "xvdj", 0x7D90 }, - { "xvdk", 0x7DA0 }, { "xvdl", 0x7DB0 }, - { "xvdm", 0x7DC0 }, { "xvdn", 0x7DD0 }, - { "xvdo", 0x7DE0 }, { "xvdp", 0x7DF0 }, -#endif - { NULL, 0 } -}; - -kdev_t __init name_to_kdev_t(char *line) -{ - int base = 0, offs; - char *end; - - if (strncmp(line,"/dev/",5) == 0) { - struct dev_name_struct *dev = root_dev_names; - line += 5; - do { - int len = strlen(dev->name); - if (strncmp(line,dev->name,len) == 0) { - line += len; - base = dev->num; - break; - } - dev++; - } while (dev->name); - } - offs = simple_strtoul(line, &end, base?10:16); - if (*end) - offs = 0; - return to_kdev_t(base + offs); -} - -static int __init root_dev_setup(char *line) -{ - int i; - char ch; - - ROOT_DEV = name_to_kdev_t(line); - memset (root_device_name, 0, sizeof root_device_name); - if (strncmp (line, "/dev/", 5) == 0) line += 5; - for (i = 0; i < sizeof root_device_name - 1; ++i) - { - ch = line[i]; - if ( isspace (ch) || (ch == ',') || (ch == '\0') ) break; - root_device_name[i] = ch; - } - return 1; -} - -__setup("root=", root_dev_setup); - -static char * __initdata root_mount_data; -static int __init root_data_setup(char *str) -{ - root_mount_data = str; - return 1; -} - -static char * __initdata root_fs_names; -static int __init fs_names_setup(char *str) -{ - root_fs_names = str; - return 1; -} - -__setup("rootflags=", root_data_setup); -__setup("rootfstype=", fs_names_setup); - -static void __init get_fs_names(char *page) -{ - char *s = page; - - if (root_fs_names) { - strcpy(page, root_fs_names); - while (*s++) { - if (s[-1] == ',') - s[-1] = '\0'; - } - } else { - int len = get_filesystem_list(page); - char *p, *next; - - page[len] = '\0'; - for (p = page-1; p; p = next) { - next = strchr(++p, '\n'); - if (*p++ != '\t') - continue; - while ((*s++ = *p++) != '\n') - ; - s[-1] = '\0'; - } - } - *s = '\0'; -} -static void __init mount_block_root(char *name, int flags) -{ - char *fs_names = __getname(); - char *p; - - get_fs_names(fs_names); -retry: - for (p = fs_names; *p; p += strlen(p)+1) { - int err = sys_mount(name, "/root", p, flags, root_mount_data); - switch (err) { - case 0: - goto out; - case -EACCES: - flags |= MS_RDONLY; - goto retry; - case -EINVAL: - case -EBUSY: - continue; - } - /* - * Allow the user to distinguish between failed open - * and bad superblock on root device. - */ - printk ("VFS: Cannot open root device \"%s\" or %s\n", - root_device_name, kdevname (ROOT_DEV)); - printk ("Please append a correct \"root=\" boot option\n"); - panic("VFS: Unable to mount root fs on %s", - kdevname(ROOT_DEV)); - } - panic("VFS: Unable to mount root fs on %s", kdevname(ROOT_DEV)); -out: - putname(fs_names); - sys_chdir("/root"); - ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev; - printk("VFS: Mounted root (%s filesystem)%s.\n", - current->fs->pwdmnt->mnt_sb->s_type->name, - (current->fs->pwdmnt->mnt_sb->s_flags & MS_RDONLY) ? " readonly" : ""); -} - -#ifdef CONFIG_ROOT_NFS -static int __init mount_nfs_root(void) -{ - void *data = nfs_root_data(); - - if (data && sys_mount("/dev/root","/root","nfs",root_mountflags,data) == 0) - return 1; - return 0; -} -#endif - -static int __init create_dev(char *name, kdev_t dev, char *devfs_name) -{ - void *handle; - char path[64]; - int n; - - sys_unlink(name); - if (!do_devfs) - return sys_mknod(name, S_IFBLK|0600, kdev_t_to_nr(dev)); - - handle = devfs_find_handle(NULL, dev ? NULL : devfs_name, - MAJOR(dev), MINOR(dev), DEVFS_SPECIAL_BLK, 1); - if (!handle) - return -1; - n = devfs_generate_path(handle, path + 5, sizeof (path) - 5); - if (n < 0) - return -1; - return sys_symlink(path + n + 5, name); -} - -#if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD) -static void __init change_floppy(char *fmt, ...) -{ - struct termios termios; - char buf[80]; - char c; - int fd; - va_list args; - va_start(args, fmt); - vsprintf(buf, fmt, args); - va_end(args); - fd = open("/dev/root", O_RDWR | O_NDELAY, 0); - if (fd >= 0) { - sys_ioctl(fd, FDEJECT, 0); - close(fd); - } - printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf); - fd = open("/dev/console", O_RDWR, 0); - if (fd >= 0) { - sys_ioctl(fd, TCGETS, (long)&termios); - termios.c_lflag &= ~ICANON; - sys_ioctl(fd, TCSETSF, (long)&termios); - read(fd, &c, 1); - termios.c_lflag |= ICANON; - sys_ioctl(fd, TCSETSF, (long)&termios); - close(fd); - } -} -#endif - -#ifdef CONFIG_BLK_DEV_RAM - -int __initdata rd_prompt = 1; /* 1 = prompt for RAM disk, 0 = don't prompt */ - -static int __init prompt_ramdisk(char *str) -{ - rd_prompt = simple_strtol(str,NULL,0) & 1; - return 1; -} -__setup("prompt_ramdisk=", prompt_ramdisk); - -int __initdata rd_image_start; /* starting block # of image */ - -static int __init ramdisk_start_setup(char *str) -{ - rd_image_start = simple_strtol(str,NULL,0); - return 1; -} -__setup("ramdisk_start=", ramdisk_start_setup); - -static int __init crd_load(int in_fd, int out_fd); - -/* - * This routine tries to find a RAM disk image to load, and returns the - * number of blocks to read for a non-compressed image, 0 if the image - * is a compressed image, and -1 if an image with the right magic - * numbers could not be found. - * - * We currently check for the following magic numbers: - * minix - * ext2 - * romfs - * cramfs - * gzip - */ -static int __init -identify_ramdisk_image(int fd, int start_block) -{ - const int size = 512; - struct minix_super_block *minixsb; - struct ext2_super_block *ext2sb; - struct romfs_super_block *romfsb; - struct cramfs_super *cramfsb; - int nblocks = -1; - unsigned char *buf; - - buf = kmalloc(size, GFP_KERNEL); - if (buf == 0) - return -1; - - minixsb = (struct minix_super_block *) buf; - ext2sb = (struct ext2_super_block *) buf; - romfsb = (struct romfs_super_block *) buf; - cramfsb = (struct cramfs_super *) buf; - memset(buf, 0xe5, size); - - /* - * Read block 0 to test for gzipped kernel - */ - lseek(fd, start_block * BLOCK_SIZE, 0); - read(fd, buf, size); - - /* - * If it matches the gzip magic numbers, return -1 - */ - if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) { - printk(KERN_NOTICE - "RAMDISK: Compressed image found at block %d\n", - start_block); - nblocks = 0; - goto done; - } - - /* romfs is at block zero too */ - if (romfsb->word0 == ROMSB_WORD0 && - romfsb->word1 == ROMSB_WORD1) { - printk(KERN_NOTICE - "RAMDISK: romfs filesystem found at block %d\n", - start_block); - nblocks = (ntohl(romfsb->size)+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; - goto done; - } - - if (cramfsb->magic == CRAMFS_MAGIC) { - printk(KERN_NOTICE - "RAMDISK: cramfs filesystem found at block %d\n", - start_block); - nblocks = (cramfsb->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS; - goto done; - } - - /* - * Read block 1 to test for minix and ext2 superblock - */ - lseek(fd, (start_block+1) * BLOCK_SIZE, 0); - read(fd, buf, size); - - /* Try minix */ - if (minixsb->s_magic == MINIX_SUPER_MAGIC || - minixsb->s_magic == MINIX_SUPER_MAGIC2) { - printk(KERN_NOTICE - "RAMDISK: Minix filesystem found at block %d\n", - start_block); - nblocks = minixsb->s_nzones << minixsb->s_log_zone_size; - goto done; - } - - /* Try ext2 */ - if (ext2sb->s_magic == cpu_to_le16(EXT2_SUPER_MAGIC)) { - printk(KERN_NOTICE - "RAMDISK: ext2 filesystem found at block %d\n", - start_block); - nblocks = le32_to_cpu(ext2sb->s_blocks_count); - goto done; - } - - printk(KERN_NOTICE - "RAMDISK: Couldn't find valid RAM disk image starting at %d.\n", - start_block); - -done: - lseek(fd, start_block * BLOCK_SIZE, 0); - kfree(buf); - return nblocks; -} -#endif - -static int __init rd_load_image(char *from) -{ - int res = 0; - -#ifdef CONFIG_BLK_DEV_RAM - int in_fd, out_fd; - unsigned long rd_blocks, devblocks; - int nblocks, i; - char *buf; - unsigned short rotate = 0; -#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES) - char rotator[4] = { '|' , '/' , '-' , '\\' }; -#endif - - out_fd = open("/dev/ram", O_RDWR, 0); - if (out_fd < 0) - goto out; - - in_fd = open(from, O_RDONLY, 0); - if (in_fd < 0) - goto noclose_input; - - nblocks = identify_ramdisk_image(in_fd, rd_image_start); - if (nblocks < 0) - goto done; - - if (nblocks == 0) { -#ifdef BUILD_CRAMDISK - if (crd_load(in_fd, out_fd) == 0) - goto successful_load; -#else - printk(KERN_NOTICE - "RAMDISK: Kernel does not support compressed " - "RAM disk images\n"); -#endif - goto done; - } - - /* - * NOTE NOTE: nblocks suppose that the blocksize is BLOCK_SIZE, so - * rd_load_image will work only with filesystem BLOCK_SIZE wide! - * So make sure to use 1k blocksize while generating ext2fs - * ramdisk-images. - */ - if (sys_ioctl(out_fd, BLKGETSIZE, (unsigned long)&rd_blocks) < 0) - rd_blocks = 0; - else - rd_blocks >>= 1; - - if (nblocks > rd_blocks) { - printk("RAMDISK: image too big! (%d/%lu blocks)\n", - nblocks, rd_blocks); - goto done; - } - - /* - * OK, time to copy in the data - */ - buf = kmalloc(BLOCK_SIZE, GFP_KERNEL); - if (buf == 0) { - printk(KERN_ERR "RAMDISK: could not allocate buffer\n"); - goto done; - } - - if (sys_ioctl(in_fd, BLKGETSIZE, (unsigned long)&devblocks) < 0) - devblocks = 0; - else - devblocks >>= 1; - - if (strcmp(from, "/dev/initrd") == 0) - devblocks = nblocks; - - if (devblocks == 0) { - printk(KERN_ERR "RAMDISK: could not determine device size\n"); - goto done; - } - - printk(KERN_NOTICE "RAMDISK: Loading %d blocks [%ld disk%s] into ram disk... ", - nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : ""); - for (i=0; i < nblocks; i++) { - if (i && (i % devblocks == 0)) { - printk("done disk #%ld.\n", i/devblocks); - rotate = 0; - if (close(in_fd)) { - printk("Error closing the disk.\n"); - goto noclose_input; - } - change_floppy("disk #%d", i/devblocks+1); - in_fd = open(from, O_RDONLY, 0); - if (in_fd < 0) { - printk("Error opening disk.\n"); - goto noclose_input; - } - printk("Loading disk #%ld... ", i/devblocks+1); - } - read(in_fd, buf, BLOCK_SIZE); - write(out_fd, buf, BLOCK_SIZE); -#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES) - if (!(i % 16)) { - printk("%c\b", rotator[rotate & 0x3]); - rotate++; - } -#endif - } - printk("done.\n"); - kfree(buf); - -successful_load: - res = 1; -done: - close(in_fd); -noclose_input: - close(out_fd); -out: - sys_unlink("/dev/ram"); -#endif - return res; -} - -static int __init rd_load_disk(int n) -{ -#ifdef CONFIG_BLK_DEV_RAM - if (rd_prompt) - change_floppy("root floppy disk to be loaded into RAM disk"); - create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n), NULL); -#endif - return rd_load_image("/dev/root"); -} - -#ifdef CONFIG_DEVFS_FS - -static void __init convert_name(char *prefix, char *name, char *p, int part) -{ - int host, bus, target, lun; - char dest[64]; - char src[64]; - char *base = p - 1; - - /* Decode "c#b#t#u#" */ - if (*p++ != 'c') - return; - host = simple_strtol(p, &p, 10); - if (*p++ != 'b') - return; - bus = simple_strtol(p, &p, 10); - if (*p++ != 't') - return; - target = simple_strtol(p, &p, 10); - if (*p++ != 'u') - return; - lun = simple_strtol(p, &p, 10); - if (!part) - sprintf(dest, "%s/host%d/bus%d/target%d/lun%d", - prefix, host, bus, target, lun); - else if (*p++ == 'p') - sprintf(dest, "%s/host%d/bus%d/target%d/lun%d/part%s", - prefix, host, bus, target, lun, p); - else - sprintf(dest, "%s/host%d/bus%d/target%d/lun%d/disc", - prefix, host, bus, target, lun); - *base = '\0'; - sprintf(src, "/dev/%s", name); - sys_mkdir(src, 0755); - *base = '/'; - sprintf(src, "/dev/%s", name); - sys_symlink(dest, src); -} - -static void __init devfs_make_root(char *name) -{ - - if (!strncmp(name, "sd/", 3)) - convert_name("../scsi", name, name+3, 1); - else if (!strncmp(name, "sr/", 3)) - convert_name("../scsi", name, name+3, 0); - else if (!strncmp(name, "ide/hd/", 7)) - convert_name("..", name, name + 7, 1); - else if (!strncmp(name, "ide/cd/", 7)) - convert_name("..", name, name + 7, 0); -} -#else -static void __init devfs_make_root(char *name) -{ -} -#endif - -static void __init mount_root(void) -{ -#ifdef CONFIG_ROOT_NFS - if (MAJOR(ROOT_DEV) == NFS_MAJOR - && MINOR(ROOT_DEV) == NFS_MINOR) { - if (mount_nfs_root()) { - sys_chdir("/root"); - ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev; - printk("VFS: Mounted root (nfs filesystem).\n"); - return; - } - printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n"); - ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0); - } -#endif -printk("root_device_name = %s\n",root_device_name); - devfs_make_root(root_device_name); - create_dev("/dev/root", ROOT_DEV, root_device_name); -#ifdef CONFIG_BLK_DEV_FD - if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) { - /* rd_doload is 2 for a dual initrd/ramload setup */ - if (rd_doload==2) { - if (rd_load_disk(1)) { - ROOT_DEV = MKDEV(RAMDISK_MAJOR, 1); - create_dev("/dev/root", ROOT_DEV, NULL); - } - } else - change_floppy("root floppy"); - } -#endif - mount_block_root("/dev/root", root_mountflags); -} - -#ifdef CONFIG_BLK_DEV_INITRD -static int old_fd, root_fd; -static int do_linuxrc(void * shell) -{ - static char *argv[] = { "linuxrc", NULL, }; - extern char * envp_init[]; - - close(old_fd); - close(root_fd); - close(0); - close(1); - close(2); - setsid(); - (void) open("/dev/console",O_RDWR,0); - (void) dup(0); - (void) dup(0); - return execve(shell, argv, envp_init); -} - -#endif - -static void __init handle_initrd(void) -{ -#ifdef CONFIG_BLK_DEV_INITRD - int ram0 = kdev_t_to_nr(MKDEV(RAMDISK_MAJOR,0)); - int error; - int i, pid; - - create_dev("/dev/root.old", ram0, NULL); - /* mount initrd on rootfs' /root */ - mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); - sys_mkdir("/old", 0700); - root_fd = open("/", 0, 0); - old_fd = open("/old", 0, 0); - /* move initrd over / and chdir/chroot in initrd root */ - sys_chdir("/root"); - sys_mount(".", "/", NULL, MS_MOVE, NULL); - sys_chroot("."); - mount_devfs_fs (); - - pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); - if (pid > 0) { - while (pid != wait(&i)) - yield(); - } - - /* move initrd to rootfs' /old */ - sys_fchdir(old_fd); - sys_mount("/", ".", NULL, MS_MOVE, NULL); - /* switch root and cwd back to / of rootfs */ - sys_fchdir(root_fd); - sys_chroot("."); - sys_umount("/old/dev", 0); - close(old_fd); - close(root_fd); - - if (real_root_dev == ram0) { - sys_chdir("/old"); - return; - } - - ROOT_DEV = real_root_dev; - mount_root(); - - printk(KERN_NOTICE "Trying to move old root to /initrd ... "); - error = sys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL); - if (!error) - printk("okay\n"); - else { - int fd = open("/dev/root.old", O_RDWR, 0); - printk("failed\n"); - printk(KERN_NOTICE "Unmounting old root\n"); - sys_umount("/old", MNT_DETACH); - printk(KERN_NOTICE "Trying to free ramdisk memory ... "); - if (fd < 0) { - error = fd; - } else { - error = sys_ioctl(fd, BLKFLSBUF, 0); - close(fd); - } - printk(!error ? "okay\n" : "failed\n"); - } -#endif -} - -static int __init initrd_load(void) -{ -#ifdef CONFIG_BLK_DEV_INITRD - create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, 0), NULL); - create_dev("/dev/initrd", MKDEV(RAMDISK_MAJOR, INITRD_MINOR), NULL); -#endif - return rd_load_image("/dev/initrd"); -} - -/* - * Prepare the namespace - decide what/where to mount, load ramdisks, etc. - */ -void prepare_namespace(void) -{ - int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; -#ifdef CONFIG_ALL_PPC - extern void arch_discover_root(void); - arch_discover_root(); -#endif /* CONFIG_ALL_PPC */ -#ifdef CONFIG_BLK_DEV_INITRD - if (!initrd_start) - mount_initrd = 0; - real_root_dev = ROOT_DEV; -#endif - sys_mkdir("/dev", 0700); - sys_mkdir("/root", 0700); - sys_mknod("/dev/console", S_IFCHR|0600, MKDEV(TTYAUX_MAJOR, 1)); -#ifdef CONFIG_DEVFS_FS - sys_mount("devfs", "/dev", "devfs", 0, NULL); - do_devfs = 1; -#endif - - create_dev("/dev/root", ROOT_DEV, NULL); - if (mount_initrd) { - if (initrd_load() && ROOT_DEV != MKDEV(RAMDISK_MAJOR, 0)) { - handle_initrd(); - goto out; - } - } else if (is_floppy && rd_doload && rd_load_disk(0)) - ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); - mount_root(); -out: - sys_umount("/dev", 0); - sys_mount(".", "/", NULL, MS_MOVE, NULL); - sys_chroot("."); - mount_devfs_fs (); -} - -#ifdef CONFIG_BLK_DEV_RAM - -#if defined(BUILD_CRAMDISK) && defined(CONFIG_BLK_DEV_RAM) - -/* - * gzip declarations - */ - -#define OF(args) args - -#ifndef memzero -#define memzero(s, n) memset ((s), 0, (n)) -#endif - -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -#define INBUFSIZ 4096 -#define WSIZE 0x8000 /* window size--must be a power of two, and */ - /* at least 32K for zip's deflate method */ - -static uch *inbuf; -static uch *window; - -static unsigned insize; /* valid bytes in inbuf */ -static unsigned inptr; /* index of next byte to be processed in inbuf */ -static unsigned outcnt; /* bytes in output buffer */ -static int exit_code; -static long bytes_out; -static int crd_infd, crd_outfd; - -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) - -/* Diagnostic functions (stubbed out) */ -#define Assert(cond,msg) -#define Trace(x) -#define Tracev(x) -#define Tracevv(x) -#define Tracec(c,x) -#define Tracecv(c,x) - -#define STATIC static - -static int fill_inbuf(void); -static void flush_window(void); -static void *malloc(int size); -static void free(void *where); -static void error(char *m); -static void gzip_mark(void **); -static void gzip_release(void **); - -#include "../lib/inflate.c" - -static void __init *malloc(int size) -{ - return kmalloc(size, GFP_KERNEL); -} - -static void __init free(void *where) -{ - kfree(where); -} - -static void __init gzip_mark(void **ptr) -{ -} - -static void __init gzip_release(void **ptr) -{ -} - - -/* =========================================================================== - * Fill the input buffer. This is called only when the buffer is empty - * and at least one byte is really needed. - */ -static int __init fill_inbuf(void) -{ - if (exit_code) return -1; - - insize = read(crd_infd, inbuf, INBUFSIZ); - if (insize == 0) return -1; - - inptr = 1; - - return inbuf[0]; -} - -/* =========================================================================== - * Write the output window window[0..outcnt-1] and update crc and bytes_out. - * (Used for the decompressed data only.) - */ -static void __init flush_window(void) -{ - ulg c = crc; /* temporary variable */ - unsigned n; - uch *in, ch; - - write(crd_outfd, window, outcnt); - in = window; - for (n = 0; n < outcnt; n++) { - ch = *in++; - c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - bytes_out += (ulg)outcnt; - outcnt = 0; -} - -static void __init error(char *x) -{ - printk(KERN_ERR "%s", x); - exit_code = 1; -} - -static int __init crd_load(int in_fd, int out_fd) -{ - int result; - - insize = 0; /* valid bytes in inbuf */ - inptr = 0; /* index of next byte to be processed in inbuf */ - outcnt = 0; /* bytes in output buffer */ - exit_code = 0; - bytes_out = 0; - crc = (ulg)0xffffffffL; /* shift register contents */ - - crd_infd = in_fd; - crd_outfd = out_fd; - inbuf = kmalloc(INBUFSIZ, GFP_KERNEL); - if (inbuf == 0) { - printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n"); - return -1; - } - window = kmalloc(WSIZE, GFP_KERNEL); - if (window == 0) { - printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n"); - kfree(inbuf); - return -1; - } - makecrc(); - result = gunzip(); - kfree(inbuf); - kfree(window); - return result; -} - -#endif /* BUILD_CRAMDISK && CONFIG_BLK_DEV_RAM */ -#endif /* CONFIG_BLK_DEV_RAM */ diff --git a/tools/examples/xc_dom_control.py b/tools/examples/xc_dom_control.py index 9a73d4533f..56c6fb852e 100755 --- a/tools/examples/xc_dom_control.py +++ b/tools/examples/xc_dom_control.py @@ -26,13 +26,6 @@ Usage: %s [command] cpu_atropos_set [dom] [period] [slice] [latency] [xtratime] -- set Atropos scheduling parameters for domain cpu_rrobin_slice [slice] -- set Round Robin scheduler slice - vif_stats [dom] [vif] -- get stats for a given network vif - vif_addip [dom] [vif] [ip] -- add an IP address to a given vif - vif_setsched [dom] [vif] [bytes] [usecs] -- rate limit vif bandwidth - vif_getsched [dom] [vif] -- print vif's scheduling parameters - vbd_add [dom] [uname] [dev] [mode] -- make disk/partition uname available to - domain as dev e.g. 'vbd_add 2 phy:sda3 hda1 w' - vbd_remove [dom] [dev] -- remove disk or partition attached as 'dev' """ % sys.argv[0] import Xc, sys, re, string, time, os, signal @@ -159,102 +152,6 @@ elif cmd == 'cpu_bvtset': rc = xc.bvtsched_domain_set(dom=dom, mcuadv=mcuadv, warp=warp, warpl=warpl, warpu=warpu) -elif cmd == 'vif_stats': - if len(sys.argv) < 4: - usage() - sys.exit(-1) - - vif = int(sys.argv[3]) - - print xc.vif_stats_get(dom=dom, vif=vif) - -elif cmd == 'vif_addip': - if len(sys.argv) < 5: - usage() - sys.exit(-1) - - vif = int(sys.argv[3]) - ip = sys.argv[4] - - # XXX This function should be moved to Xc once we sort out the VFR - import xenctl.utils - xenctl.utils.setup_vfr_rules_for_vif( dom, vif, ip ) - -elif cmd == 'vif_setsched': - if len(sys.argv) < 6: - usage() - sys.exit(-1) - - vif = int(sys.argv[3]) - credit_bytes = int(sys.argv[4]) - credit_usecs = int(sys.argv[5]) - - rc = xc.xc_vif_scheduler_set(dom=dom, vif=vif, - credit_bytes=credit_bytes, - credit_usecs=credit_usecs) - -elif cmd == 'vif_getsched': - if len(sys.argv) < 4: - usage() - sys.exit(-1) - - vif = int(sys.argv[3]) - - print xc.vif_scheduler_get(dom=dom, vif=vif) - - -elif cmd == 'vbd_add': - import xenctl.utils - - xenctl.utils.VBD_EXPERT_LEVEL = 0 # sets the allowed level of potentially unsafe mappings - - if len(sys.argv) < 6: - usage() - sys.exit(1) - - uname = sys.argv[3] - dev = sys.argv[4] - mode = sys.argv[5] - - writeable = 0 - if mode == 'rw' or mode == 'w': - writeable = 1; - - segments = xenctl.utils.lookup_disk_uname(uname) - - if not segments: - print "Lookup Failed" - sys.exit(1) - - if xenctl.utils.vd_extents_validate(segments,writeable) < 0: - print "That mapping is too unsafe for the current VBD expertise level" - sys.exit(1) - - virt_dev = xenctl.utils.blkdev_name_to_number(dev) - - xc.vbd_create(dom,virt_dev,writeable) - - if xc.vbd_setextents( dom, virt_dev, segments ): - print "Error populating VBD vbd=%d\n" % virt_dev - sys.exit(1) - - print "Added disk/partition %s to domain %d as device %s (%x)" % (uname, dom, dev, virt_dev) - -elif cmd == 'vbd_remove': - import xenctl.utils - - if len(sys.argv) < 4: - usage() - sys.exit(1) - - dev = sys.argv[3] - virt_dev = xenctl.utils.blkdev_name_to_number(dev) - - if not xc.vbd_destroy(dom,virt_dev): - print "Removed disk/partition attached as device %s (%x) in domain %d" % (dev, virt_dev, dom) - else: - print "Failed" - sys.exit(1) elif cmd == 'cpu_atropos_set': # args: dom period slice latency xtratime if len(sys.argv) < 6: diff --git a/tools/examples/xc_dom_create.py b/tools/examples/xc_dom_create.py index f1e759d4f6..0b4ede8583 100755 --- a/tools/examples/xc_dom_create.py +++ b/tools/examples/xc_dom_create.py @@ -200,15 +200,6 @@ output('VM cmdline : "%s"' % cmdline) if dryrun: sys.exit(1) -##### HACK HACK HACK -##### Until everyone moves to the new I/O world, and a more robust domain -##### controller (xend), we use this little trick to discover whether we -##### are in a testing environment for new I/O stuff. -new_io_world = True -for line in os.popen('cat /proc/interrupts').readlines(): - if re.search('blkdev', line): - new_io_world = False - ##### Code beyond this point is actually used to manage the mechanics of ##### starting (and watching if necessary) guest virtual machines. @@ -275,17 +266,16 @@ def make_domain(): xenctl.utils.VBD_EXPERT_MODE = vbd_expert if not (flags & 1<<4): # It's not a block backend (or it's old IO world) - if new_io_world: - cmsg = 'new_block_interface(dom='+str(id)+')' - xend_response = xenctl.utils.xend_control_message(cmsg) - if not xend_response['success']: - print "Error creating block interface" - print "Error type: " + xend_response['error_type'] - if xend_response['error_type'] == 'exception': - print "Exception type: " + xend_response['exception_type'] - print "Exception val: " + xend_response['exception_value'] - xc.domain_destroy ( dom=id ) - sys.exit() + cmsg = 'new_block_interface(dom='+str(id)+')' + xend_response = xenctl.utils.xend_control_message(cmsg) + if not xend_response['success']: + print "Error creating block interface" + print "Error type: " + xend_response['error_type'] + if xend_response['error_type'] == 'exception': + print "Exception type: " + xend_response['exception_type'] + print "Exception val: " + xend_response['exception_value'] + xc.domain_destroy ( dom=id ) + sys.exit() for ( uname, virt_name, rw ) in vbd_list: virt_dev = xenctl.utils.blkdev_name_to_number( virt_name ) @@ -296,47 +286,26 @@ def make_domain(): xc.domain_destroy ( dom=id ) sys.exit() - if new_io_world: - if len(segments) > 1: - print "New I/O world cannot deal with multi-extent vdisks" - xc.domain_destroy ( dom=id ) - sys.exit() - seg = segments[0] - cmsg = 'new_block_device(dom=' + str(id) + \ - ',handle=0,vdev=' + str(virt_dev) + \ - ',pdev=' + str(seg['device']) + \ - ',start_sect=' + str(seg['start_sector']) + \ - ',nr_sect=' + str(seg['nr_sectors']) + \ - ',readonly=' + str(not re.match('w',rw)) + ')' - xend_response = xenctl.utils.xend_control_message(cmsg) - if not xend_response['success']: - print "Error creating virtual block device" - print "Error type: " + xend_response['error_type'] - if xend_response['error_type'] == 'exception': - print "Exception type: " + xend_response['exception_type'] - print "Exception val: " + xend_response['exception_value'] - xc.domain_destroy ( dom=id ) - sys.exit() - else: - # check that setting up this VBD won't violate the sharing - # allowed by the current VBD expertise level - if xenctl.utils.vd_extents_validate(segments, - rw=='w' or rw=='rw') < 0: - xc.domain_destroy( dom = id ) - sys.exit() - - if xc.vbd_create( dom=id, vbd=virt_dev, - writeable= rw=='w' or rw=='rw' ): - print "Error creating VBD %d (writeable=%d)\n" % (virt_dev,rw) - xc.domain_destroy ( dom=id ) - sys.exit() - - if xc.vbd_setextents( dom=id, - vbd=virt_dev, - extents=segments): - print "Error populating VBD vbd=%d\n" % virt_dev - xc.domain_destroy ( dom=id ) - sys.exit() + if len(segments) > 1: + print "New I/O world cannot deal with multi-extent vdisks" + xc.domain_destroy ( dom=id ) + sys.exit() + seg = segments[0] + cmsg = 'new_block_device(dom=' + str(id) + \ + ',handle=0,vdev=' + str(virt_dev) + \ + ',pdev=' + str(seg['device']) + \ + ',start_sect=' + str(seg['start_sector']) + \ + ',nr_sect=' + str(seg['nr_sectors']) + \ + ',readonly=' + str(not re.match('w',rw)) + ')' + xend_response = xenctl.utils.xend_control_message(cmsg) + if not xend_response['success']: + print "Error creating virtual block device" + print "Error type: " + xend_response['error_type'] + if xend_response['error_type'] == 'exception': + print "Exception type: " + xend_response['exception_type'] + print "Exception val: " + xend_response['exception_value'] + xc.domain_destroy ( dom=id ) + sys.exit() else: # It's a block backend - notify Xend. cmsg = 'set_block_backend(dom='+str(id)+')' xend_response = xenctl.utils.xend_control_message(cmsg) @@ -349,44 +318,38 @@ def make_domain(): xc.domain_destroy ( dom=id ) sys.exit() - if new_io_world: - if not (flags & 1<<5): # If it's not the net backend, give it a frontend. - cmsg = 'new_network_interface(dom='+str(id)+')' - xend_response = xenctl.utils.xend_control_message(cmsg) - if not xend_response['success']: - print "Error creating network interface" - print "Error type: " + xend_response['error_type'] - if xend_response['error_type'] == 'exception': - print "Exception type: " + xend_response['exception_type'] - print "Exception val: " + xend_response['exception_value'] - xc.domain_destroy ( dom=id ) - sys.exit() - else: # It's a new net backend - notify Xend. - cmsg = 'set_network_backend(dom='+str(id)+')' - xend_response = xenctl.utils.xend_control_message(cmsg) - if not xend_response['success']: - print "Error registering network backend" - print "Error type: " + xend_response['error_type'] - if xend_response['error_type'] == 'exception': - print "Exception type: " + xend_response['exception_type'] - print "Exception val: " + xend_response['exception_value'] - xc.domain_destroy ( dom=id ) - sys.exit() - else: - # setup virtual firewall rules for all aliases - for ip in vfr_ipaddr: - xenctl.utils.setup_vfr_rules_for_vif( id, 0, ip ) - - if new_io_world: - # check for physical device access - for (pci_bus, pci_dev, pci_func) in pci_device_list: - if xc.physdev_pci_access_modify( - dom=id, bus=pci_bus, dev=pci_dev, - func=pci_func, enable=1 ) < 0: - print "Non-fatal error enabling PCI device access." - else: - print "Enabled PCI access (%d:%d:%d)." % \ - (pci_bus,pci_dev,pci_func) + if not (flags & 1<<5): # If it's not the net backend, give it a frontend. + cmsg = 'new_network_interface(dom='+str(id)+')' + xend_response = xenctl.utils.xend_control_message(cmsg) + if not xend_response['success']: + print "Error creating network interface" + print "Error type: " + xend_response['error_type'] + if xend_response['error_type'] == 'exception': + print "Exception type: " + xend_response['exception_type'] + print "Exception val: " + xend_response['exception_value'] + xc.domain_destroy ( dom=id ) + sys.exit() + else: # It's a new net backend - notify Xend. + cmsg = 'set_network_backend(dom='+str(id)+')' + xend_response = xenctl.utils.xend_control_message(cmsg) + if not xend_response['success']: + print "Error registering network backend" + print "Error type: " + xend_response['error_type'] + if xend_response['error_type'] == 'exception': + print "Exception type: " + xend_response['exception_type'] + print "Exception val: " + xend_response['exception_value'] + xc.domain_destroy ( dom=id ) + sys.exit() + + # check for physical device access + for (pci_bus, pci_dev, pci_func) in pci_device_list: + if xc.physdev_pci_access_modify( + dom=id, bus=pci_bus, dev=pci_dev, + func=pci_func, enable=1 ) < 0: + print "Non-fatal error enabling PCI device access." + else: + print "Enabled PCI access (%d:%d:%d)." % \ + (pci_bus,pci_dev,pci_func) if restore: # send an unsolicited ARP reply for all non link-local IPs diff --git a/tools/xc/lib/xc.h b/tools/xc/lib/xc.h index 19cd720265..7ca6ba9dda 100644 --- a/tools/xc/lib/xc.h +++ b/tools/xc/lib/xc.h @@ -129,82 +129,6 @@ int xc_rrobin_global_set(int xc_handle, u64 slice); int xc_rrobin_global_get(int xc_handle, u64 *slice); -typedef struct { - unsigned long credit_bytes; - unsigned long credit_usec; -} xc_vif_sched_params_t; - -typedef struct { - u64 tx_bytes, tx_pkts; - u64 rx_bytes, rx_pkts; -} xc_vif_stats_t; - -int xc_vif_scheduler_set(int xc_handle, - u32 domid, - unsigned int vifid, - xc_vif_sched_params_t *params); -int xc_vif_scheduler_get(int xc_handle, - u32 domid, - unsigned int vifid, - xc_vif_sched_params_t *params); -int xc_vif_stats_get(int xc_handle, - u32 domid, - unsigned int vifid, - xc_vif_stats_t *stats); - -typedef struct { -#define XC_VBDDOM_PROBE_ALL (0x7FFFFFFFU) - u32 domid; - unsigned short vbdid; -#define XC_VBDF_WRITEABLE (1<<0) - unsigned long flags; - u64 nr_sectors; -} xc_vbd_t; - -typedef struct { - unsigned short real_device; - u64 start_sector; - u64 nr_sectors; -} xc_vbdextent_t; - -typedef struct { - int ht_per_core; - int cores; - unsigned long total_pages; - unsigned long free_pages; - unsigned long cpu_khz; -} xc_physinfo_t; - -int xc_vbd_create(int xc_handle, - u32 domid, - unsigned short vbdid, - int writeable); -int xc_vbd_destroy(int xc_handle, - u32 domid, - unsigned short vbdid); -int xc_vbd_grow(int xc_handle, - u32 domid, - unsigned short vbdid, - xc_vbdextent_t *extent); -int xc_vbd_shrink(int xc_handle, - u32 domid, - unsigned short vbdid); -int xc_vbd_setextents(int xc_handle, - u32 domid, - unsigned short vbdid, - unsigned int nr_extents, - xc_vbdextent_t *extents); -int xc_vbd_getextents(int xc_handle, - u32 domid, - unsigned short vbdid, - unsigned int max_extents, - xc_vbdextent_t *extents, - int *writeable); -int xc_vbd_probe(int xc_handle, - u32 domid, - unsigned int max_vbds, - xc_vbd_t *vbds); - #define DOMID_SELF (0x7FFFFFFEU) typedef struct { @@ -254,6 +178,14 @@ int xc_readconsolering(int xc_handle, unsigned int max_chars, int clear); +typedef struct { + int ht_per_core; + int cores; + unsigned long total_pages; + unsigned long free_pages; + unsigned long cpu_khz; +} xc_physinfo_t; + int xc_physinfo(int xc_handle, xc_physinfo_t *info); diff --git a/tools/xc/lib/xc_linux_build.c b/tools/xc/lib/xc_linux_build.c index c5329231c4..0c49c7242b 100644 --- a/tools/xc/lib/xc_linux_build.c +++ b/tools/xc/lib/xc_linux_build.c @@ -516,7 +516,6 @@ int xc_linux_build(int xc_handle, memset( &launch_op, 0, sizeof(launch_op) ); launch_op.u.builddomain.domain = (domid_t)domid; - launch_op.u.builddomain.num_vifs = 1; launch_op.u.builddomain.ctxt = ctxt; launch_op.cmd = DOM0_BUILDDOMAIN; diff --git a/tools/xc/lib/xc_linux_restore.c b/tools/xc/lib/xc_linux_restore.c index 42a158e127..5900919e32 100644 --- a/tools/xc/lib/xc_linux_restore.c +++ b/tools/xc/lib/xc_linux_restore.c @@ -592,7 +592,6 @@ int xc_linux_restore(int xc_handle, op.cmd = DOM0_BUILDDOMAIN; op.u.builddomain.domain = (domid_t)dom; - op.u.builddomain.num_vifs = 1; op.u.builddomain.ctxt = &ctxt; rc = do_dom0_op(xc_handle, &op); diff --git a/tools/xc/lib/xc_netbsd_build.c b/tools/xc/lib/xc_netbsd_build.c index 991edb0634..40e7160634 100644 --- a/tools/xc/lib/xc_netbsd_build.c +++ b/tools/xc/lib/xc_netbsd_build.c @@ -335,7 +335,6 @@ int xc_netbsd_build(int xc_handle, memset( &launch_op, 0, sizeof(launch_op) ); launch_op.u.builddomain.domain = (domid_t)domid; - launch_op.u.builddomain.num_vifs = 1; launch_op.u.builddomain.ctxt = ctxt; launch_op.cmd = DOM0_BUILDDOMAIN; rc = do_dom0_op(xc_handle, &launch_op); diff --git a/tools/xc/lib/xc_private.h b/tools/xc/lib/xc_private.h index 330edca50f..6602cf7a9f 100644 --- a/tools/xc/lib/xc_private.h +++ b/tools/xc/lib/xc_private.h @@ -19,14 +19,11 @@ /* from xen/include/hypervisor-ifs */ #include #include -#include #include #include #include - - /* from xend/lib */ #include @@ -131,49 +128,6 @@ static inline int do_multicall_op(int xc_handle, out1: return ret; } -static inline int do_network_op(int xc_handle, network_op_t *op) -{ - int ret = -1; - privcmd_hypercall_t hypercall; - - hypercall.op = __HYPERVISOR_network_op; - hypercall.arg[0] = (unsigned long)op; - - if ( mlock(op, sizeof(*op)) != 0 ) - { - PERROR("Could not lock memory for Xen hypercall"); - goto out1; - } - - if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 ) - goto out2; - - out2: (void)munlock(op, sizeof(*op)); - out1: return ret; -} - - -static inline int do_block_io_op(int xc_handle, block_io_op_t *op) -{ - int ret = -1; - privcmd_hypercall_t hypercall; - - hypercall.op = __HYPERVISOR_block_io_op; - hypercall.arg[0] = (unsigned long)op; - - if ( mlock(op, sizeof(*op)) != 0 ) - { - PERROR("Could not lock memory for Xen hypercall"); - goto out1; - } - - if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 ) - goto out2; - - out2: (void)munlock(op, sizeof(*op)); - out1: return ret; -} - /* * PFN mapping. */ diff --git a/tools/xc/lib/xc_vbd.c b/tools/xc/lib/xc_vbd.c deleted file mode 100644 index a23e0b0603..0000000000 --- a/tools/xc/lib/xc_vbd.c +++ /dev/null @@ -1,212 +0,0 @@ -/****************************************************************************** - * xc_vbd.c - * - * API for manipulating and accessing per-domain virtual block devices. - * - * Copyright (c) 2003, K A Fraser. - */ - -#define _GNU_SOURCE -#include "xc_private.h" - -int xc_vbd_create(int xc_handle, - u32 domid, - unsigned short vbdid, - int writeable) -{ - block_io_op_t op; - op.cmd = BLOCK_IO_OP_VBD_CREATE; - op.u.create_params.domain = (domid_t)domid; - op.u.create_params.vdevice = vbdid; - op.u.create_params.mode = VBD_MODE_R | (writeable ? VBD_MODE_W : 0); - return do_block_io_op(xc_handle, &op); -} - - -int xc_vbd_destroy(int xc_handle, - u32 domid, - unsigned short vbdid) -{ - block_io_op_t op; - op.cmd = BLOCK_IO_OP_VBD_DELETE; - op.u.delete_params.domain = (domid_t)domid; - op.u.delete_params.vdevice = vbdid; - return do_block_io_op(xc_handle, &op); -} - - -int xc_vbd_grow(int xc_handle, - u32 domid, - unsigned short vbdid, - xc_vbdextent_t *extent) -{ - block_io_op_t op; - op.cmd = BLOCK_IO_OP_VBD_GROW; - op.u.grow_params.domain = (domid_t)domid; - op.u.grow_params.vdevice = vbdid; - op.u.grow_params.extent.device = extent->real_device; - op.u.grow_params.extent.start_sector = (xen_sector_t)extent->start_sector; - op.u.grow_params.extent.nr_sectors = (xen_sector_t)extent->nr_sectors; - return do_block_io_op(xc_handle, &op); -} - - -int xc_vbd_shrink(int xc_handle, - u32 domid, - unsigned short vbdid) -{ - block_io_op_t op; - op.cmd = BLOCK_IO_OP_VBD_SHRINK; - op.u.shrink_params.domain = (domid_t)domid; - op.u.shrink_params.vdevice = vbdid; - return do_block_io_op(xc_handle, &op); -} - - -int xc_vbd_setextents(int xc_handle, - u32 domid, - unsigned short vbdid, - unsigned int nr_extents, - xc_vbdextent_t *extents) -{ - int i, rc; - block_io_op_t op; - xen_extent_t *real_extents = NULL; - - if ( nr_extents != 0 ) - { - real_extents = malloc(nr_extents * sizeof(xc_vbdextent_t)); - if ( (real_extents == NULL) || - (mlock(real_extents, nr_extents * sizeof(xc_vbdextent_t)) != 0) ) - { - if ( real_extents != NULL ) - free(real_extents); - return -ENOMEM; - } - - for ( i = 0; i < nr_extents; i++ ) - { - real_extents[i].device = extents[i].real_device; - real_extents[i].start_sector = - (xen_sector_t)extents[i].start_sector; - real_extents[i].nr_sectors = - (xen_sector_t)extents[i].nr_sectors; - } - } - - op.cmd = BLOCK_IO_OP_VBD_SET_EXTENTS; - op.u.setextents_params.domain = (domid_t)domid; - op.u.setextents_params.vdevice = vbdid; - op.u.setextents_params.nr_extents = nr_extents; - op.u.setextents_params.extents = real_extents; - rc = do_block_io_op(xc_handle, &op); - - if ( real_extents != NULL ) - { - (void)munlock(real_extents, nr_extents * sizeof(xc_vbdextent_t)); - free(real_extents); - } - - return rc; -} - - -int xc_vbd_getextents(int xc_handle, - u32 domid, - unsigned short vbdid, - unsigned int max_extents, - xc_vbdextent_t *extents, - int *writeable) -{ - int i, rc; - block_io_op_t op; - xen_extent_t *real_extents = malloc(max_extents * sizeof(xc_vbdextent_t)); - - if ( (real_extents == NULL) || - (mlock(real_extents, max_extents * sizeof(xc_vbdextent_t)) != 0) ) - { - if ( real_extents != NULL ) - free(real_extents); - return -ENOMEM; - } - - op.cmd = BLOCK_IO_OP_VBD_INFO; - op.u.info_params.domain = (domid_t)domid; - op.u.info_params.vdevice = vbdid; - op.u.info_params.maxextents = max_extents; - op.u.info_params.extents = real_extents; - rc = do_block_io_op(xc_handle, &op); - - (void)munlock(real_extents, max_extents * sizeof(xc_vbdextent_t)); - - if ( rc >= 0 ) - { - for ( i = 0; i < op.u.info_params.nextents; i++ ) - { - extents[i].real_device = real_extents[i].device; - extents[i].start_sector = (u64)real_extents[i].start_sector; - extents[i].nr_sectors = (u64)real_extents[i].nr_sectors; - } - - if ( writeable != NULL ) - *writeable = !!(op.u.info_params.mode & VBD_MODE_W); - - rc = op.u.info_params.nextents; - } - - free(real_extents); - - return rc; -} - - -int xc_vbd_probe(int xc_handle, - u32 domid, - unsigned int max_vbds, - xc_vbd_t *vbds) -{ - block_io_op_t op; - xen_disk_info_t *xdi = &op.u.probe_params.xdi; - int i, j, ret, allocsz = max_vbds * sizeof(xen_disk_t); - - op.cmd = BLOCK_IO_OP_VBD_PROBE; - op.u.probe_params.domain = (domid_t)domid; - - xdi->max = max_vbds; - xdi->disks = malloc(allocsz); - xdi->count = 0; - - if ( (xdi->disks == NULL) || (mlock(xdi->disks, allocsz) != 0) ) - { - if ( xdi->disks != NULL ) - free(xdi->disks); - return -ENOMEM; - } - - ret = do_block_io_op(xc_handle, &op); - - (void)munlock(xdi->disks, allocsz); - - if ( ret >= 0 ) - { - for ( i = 0, j = 0; i < xdi->count; i++ ) - { - if ( !(xdi->disks[i].info & XD_FLAG_VIRT) ) - continue; - - vbds[j].domid = (u32)xdi->disks[i].domain; - vbds[j].vbdid = xdi->disks[i].device; - vbds[j].flags = (xdi->disks[i].info & XD_FLAG_RO) ? - 0 : XC_VBDF_WRITEABLE; - vbds[j].nr_sectors = (u64)xdi->disks[i].capacity; - - j++; - } - - ret = j; - } - - free(xdi->disks); - - return ret; -} diff --git a/tools/xc/lib/xc_vif.c b/tools/xc/lib/xc_vif.c deleted file mode 100644 index cae5e3438c..0000000000 --- a/tools/xc/lib/xc_vif.c +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * xc_vif.c - * - * API for manipulating and accessing per-network-interface parameters. - * - * Copyright (c) 2003, K A Fraser. - */ - -#include "xc_private.h" - -int xc_vif_scheduler_set(int xc_handle, - u32 domid, - unsigned int vifid, - xc_vif_sched_params_t *params) -{ - network_op_t netop; - netop.cmd = NETWORK_OP_VIFSETPARAMS; - netop.u.vif_setparams.domain = (domid_t)domid; - netop.u.vif_setparams.vif = vifid; - netop.u.vif_setparams.credit_bytes = params->credit_bytes; - netop.u.vif_setparams.credit_usec = params->credit_usec; - return do_network_op(xc_handle, &netop); -} - - -int xc_vif_scheduler_get(int xc_handle, - u32 domid, - unsigned int vifid, - xc_vif_sched_params_t *params) -{ - network_op_t netop; - int rc; - - netop.cmd = NETWORK_OP_VIFGETINFO; - netop.u.vif_getinfo.domain = (domid_t)domid; - netop.u.vif_getinfo.vif = vifid; - - if ( (rc = do_network_op(xc_handle, &netop)) >= 0 ) - { - params->credit_bytes = netop.u.vif_getinfo.credit_bytes; - params->credit_usec = netop.u.vif_getinfo.credit_usec; - } - - return rc; -} - - -int xc_vif_stats_get(int xc_handle, - u32 domid, - unsigned int vifid, - xc_vif_stats_t *stats) -{ - network_op_t netop; - int rc; - - netop.cmd = NETWORK_OP_VIFGETINFO; - netop.u.vif_getinfo.domain = (domid_t)domid; - netop.u.vif_getinfo.vif = vifid; - - if ( (rc = do_network_op(xc_handle, &netop)) >= 0 ) - { - stats->tx_bytes = netop.u.vif_getinfo.total_bytes_sent; - stats->tx_pkts = netop.u.vif_getinfo.total_packets_sent; - stats->rx_bytes = netop.u.vif_getinfo.total_bytes_received; - stats->rx_pkts = netop.u.vif_getinfo.total_packets_received; - } - - return rc; -} diff --git a/tools/xc/py/Xc.c b/tools/xc/py/Xc.c index e1ac79077d..7e904fc973 100644 --- a/tools/xc/py/Xc.c +++ b/tools/xc/py/Xc.c @@ -644,388 +644,6 @@ static PyObject *pyxc_bvtsched_domain_get(PyObject *self, "warpu", warpu); } -static PyObject *pyxc_vif_scheduler_set(PyObject *self, - PyObject *args, - PyObject *kwds) -{ - XcObject *xc = (XcObject *)self; - - u32 dom; - unsigned int vif; - xc_vif_sched_params_t sched = { 0, 0 }; - - static char *kwd_list[] = { "dom", "vif", "credit_bytes", - "credit_usecs", NULL }; - - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii|ll", kwd_list, - &dom, &vif, - &sched.credit_bytes, - &sched.credit_usec) ) - return NULL; - - if ( xc_vif_scheduler_set(xc->xc_handle, dom, vif, &sched) != 0 ) - return PyErr_SetFromErrno(xc_error); - - Py_INCREF(zero); - return zero; -} - -static PyObject *pyxc_vif_scheduler_get(PyObject *self, - PyObject *args, - PyObject *kwds) -{ - XcObject *xc = (XcObject *)self; - - u32 dom; - unsigned int vif; - xc_vif_sched_params_t sched; - - static char *kwd_list[] = { "dom", "vif", NULL }; - - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, - &dom, &vif) ) - return NULL; - - if ( xc_vif_scheduler_get(xc->xc_handle, dom, vif, &sched) != 0 ) - return PyErr_SetFromErrno(xc_error); - - return Py_BuildValue("{s:l,s:l}", - "credit_bytes", sched.credit_bytes, - "credit_usecs", sched.credit_usec); -} - -static PyObject *pyxc_vif_stats_get(PyObject *self, - PyObject *args, - PyObject *kwds) -{ - XcObject *xc = (XcObject *)self; - - u32 dom; - unsigned int vif; - xc_vif_stats_t stats; - - static char *kwd_list[] = { "dom", "vif", NULL }; - - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, - &dom, &vif) ) - return NULL; - - if ( xc_vif_stats_get(xc->xc_handle, dom, vif, &stats) != 0 ) - return PyErr_SetFromErrno(xc_error); - - return Py_BuildValue("{s:L,s:L,s:L,s:L}", - "tx_bytes", stats.tx_bytes, - "tx_packets", stats.tx_pkts, - "rx_bytes", stats.rx_bytes, - "rx_packets", stats.rx_pkts); -} - -static PyObject *pyxc_vbd_create(PyObject *self, - PyObject *args, - PyObject *kwds) -{ - XcObject *xc = (XcObject *)self; - - u32 dom; - unsigned int vbd; - int writeable; - - static char *kwd_list[] = { "dom", "vbd", "writeable", NULL }; - - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iii", kwd_list, - &dom, &vbd, &writeable) ) - return NULL; - - if ( xc_vbd_create(xc->xc_handle, dom, vbd, writeable) != 0 ) - return PyErr_SetFromErrno(xc_error); - - Py_INCREF(zero); - return zero; -} - -static PyObject *pyxc_vbd_destroy(PyObject *self, - PyObject *args, - PyObject *kwds) -{ - XcObject *xc = (XcObject *)self; - - u32 dom; - unsigned int vbd; - - static char *kwd_list[] = { "dom", "vbd", NULL }; - - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, - &dom, &vbd) ) - return NULL; - - if ( xc_vbd_destroy(xc->xc_handle, dom, vbd) != 0 ) - return PyErr_SetFromErrno(xc_error); - - Py_INCREF(zero); - return zero; -} - -static PyObject *pyxc_vbd_grow(PyObject *self, - PyObject *args, - PyObject *kwds) -{ - XcObject *xc = (XcObject *)self; - - u32 dom; - unsigned int vbd; - xc_vbdextent_t extent; - - static char *kwd_list[] = { "dom", "vbd", "device", - "start_sector", "nr_sectors", NULL }; - - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiLL", kwd_list, - &dom, &vbd, - &extent.real_device, - &extent.start_sector, - &extent.nr_sectors) ) - return NULL; - - if ( xc_vbd_grow(xc->xc_handle, dom, vbd, &extent) != 0 ) - return PyErr_SetFromErrno(xc_error); - - Py_INCREF(zero); - return zero; -} - -static PyObject *pyxc_vbd_shrink(PyObject *self, - PyObject *args, - PyObject *kwds) -{ - XcObject *xc = (XcObject *)self; - - u32 dom; - unsigned int vbd; - - static char *kwd_list[] = { "dom", "vbd", NULL }; - - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, - &dom, &vbd) ) - return NULL; - - if ( xc_vbd_shrink(xc->xc_handle, dom, vbd) != 0 ) - return PyErr_SetFromErrno(xc_error); - - Py_INCREF(zero); - return zero; -} - -static PyObject *pyxc_vbd_setextents(PyObject *self, - PyObject *args, - PyObject *kwds) -{ - XcObject *xc = (XcObject *)self; - PyObject *list, *dict, *obj; - - u32 dom; - unsigned int vbd; - xc_vbdextent_t *extents = NULL; - int i, nr_extents; - - static char *kwd_list[] = { "dom", "vbd", "extents", NULL }; - - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiO", kwd_list, - &dom, &vbd, &list) ) - return NULL; - - if ( !PyList_Check(list) ) - { - PyErr_SetString(PyExc_TypeError, "parameter 'extents' is not a list"); - return NULL; - } - - if ( (nr_extents = PyList_Size(list)) != 0 ) - { - if ( (extents = malloc(nr_extents * sizeof(xc_vbdextent_t))) == NULL ) - return PyErr_NoMemory(); - - for ( i = 0; i < nr_extents; i++ ) - { - dict = PyList_GetItem(list, i); - if ( !PyDict_Check(dict) ) - { - PyErr_SetString(PyExc_TypeError, "extent is not a dictionary"); - goto fail; - } - - if ( (obj = PyDict_GetItemString(dict, "device")) == NULL ) - { - PyErr_SetString(PyExc_TypeError, - "'device' is not in the dictionary"); - goto fail; - } - if ( PyInt_Check(obj) ) - { - extents[i].real_device = (unsigned short)PyInt_AsLong(obj); - } - else if ( PyLong_Check(obj) ) - { - extents[i].real_device = (unsigned short)PyLong_AsLong(obj); - } - else - { - PyErr_SetString(PyExc_TypeError, - "'device' is not an int or long"); - goto fail; - } - - if ( (obj = PyDict_GetItemString(dict, "start_sector")) == NULL ) - { - PyErr_SetString(PyExc_TypeError, - "'start_sector' is not in the dictionary"); - goto fail; - } - if ( PyInt_Check(obj) ) - { - extents[i].start_sector = PyInt_AsLong(obj); - } - else if ( PyLong_Check(obj) ) - { - extents[i].start_sector = PyLong_AsUnsignedLongLong(obj); - } - else - { - PyErr_SetString(PyExc_TypeError, - "'start_sector' is not an int or long"); - goto fail; - } - - if ( (obj = PyDict_GetItemString(dict, "nr_sectors")) == NULL ) - { - PyErr_SetString(PyExc_TypeError, - "'nr_sectors' is not in the dictionary"); - goto fail; - } - if ( PyInt_Check(obj) ) - { - extents[i].nr_sectors = PyInt_AsLong(obj); - } - else if ( PyLong_Check(obj) ) - { - extents[i].nr_sectors = PyLong_AsUnsignedLongLong(obj); - } - else - { - PyErr_SetString(PyExc_TypeError, - "'nr_sectors' is not an int or long"); - goto fail; - } - } - } - - if ( xc_vbd_setextents(xc->xc_handle, dom, vbd, nr_extents, extents) != 0 ) - { - PyErr_SetFromErrno(xc_error); - goto fail; - } - - if ( extents != NULL ) - free(extents); - - Py_INCREF(zero); - return zero; - - fail: - if ( extents != NULL ) - free(extents); - return NULL; -} - -#define MAX_EXTENTS 1024 -static PyObject *pyxc_vbd_getextents(PyObject *self, - PyObject *args, - PyObject *kwds) -{ - XcObject *xc = (XcObject *)self; - PyObject *list; - - u32 dom; - unsigned int vbd; - xc_vbdextent_t *extents; - int i, nr_extents; - - static char *kwd_list[] = { "dom", "vbd", NULL }; - - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, - &dom, &vbd) ) - return NULL; - - if ( (extents = malloc(MAX_EXTENTS * sizeof(xc_vbdextent_t))) == NULL ) - return PyErr_NoMemory(); - - nr_extents = xc_vbd_getextents(xc->xc_handle, dom, vbd, MAX_EXTENTS, - extents, NULL); - - if ( nr_extents < 0 ) - { - free(extents); - return PyErr_SetFromErrno(xc_error); - } - - list = PyList_New(nr_extents); - for ( i = 0; i < nr_extents; i++ ) - { - PyList_SetItem( - list, i, - Py_BuildValue("{s:i,s:L,s:L}", - "device", extents[i].real_device, - "start_sector", extents[i].start_sector, - "nr_sectors", extents[i].nr_sectors)); - } - - free(extents); - - return list; -} - -static PyObject *pyxc_vbd_probe(PyObject *self, - PyObject *args, - PyObject *kwds) -{ - XcObject *xc = (XcObject *)self; - PyObject *list; - - u32 dom = XC_VBDDOM_PROBE_ALL; - unsigned int max_vbds = 1024; - xc_vbd_t *info; - int nr_vbds, i; - - static char *kwd_list[] = { "dom", "max_vbds", NULL }; - - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list, - &dom, &max_vbds) ) - return NULL; - - if ( (info = malloc(max_vbds * sizeof(xc_vbd_t))) == NULL ) - return PyErr_NoMemory(); - - if ( (nr_vbds = xc_vbd_probe(xc->xc_handle, dom, max_vbds, info)) < 0 ) - { - free(info); - return PyErr_SetFromErrno(xc_error); - } - - list = PyList_New(nr_vbds); - for ( i = 0; i < nr_vbds; i++ ) - { - PyList_SetItem( - list, i, - Py_BuildValue("{s:i,s:i,s:i,s:L}", - "dom", info[i].domid, - "vbd", info[i].vbdid, - "writeable", !!(info[i].flags & XC_VBDF_WRITEABLE), - "nr_sectors", info[i].nr_sectors)); - } - - free(info); - - return list; -} - static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self, PyObject *args, PyObject *kwds) @@ -1553,110 +1171,6 @@ static PyMethodDef pyxc_methods[] = { "Returns [dict]:\n" " slice [long]: Scheduler time slice.\n" }, - { "vif_scheduler_set", - (PyCFunction)pyxc_vif_scheduler_set, - METH_VARARGS | METH_KEYWORDS, "\n" - "Set per-network-interface scheduling parameters.\n" - " dom [int]: Identifier of domain to be adjusted.\n" - " vif [int]: Identifier of VIF to be adjusted.\n" - " credit_bytes [int, 0]: Tx bytes permitted each interval.\n" - " credit_usecs [int, 0]: Interval, in usecs. 0 == no scheduling.\n\n" - "Returns: [int] 0 on success; -1 on error.\n" }, - - { "vif_scheduler_get", - (PyCFunction)pyxc_vif_scheduler_get, - METH_VARARGS | METH_KEYWORDS, "\n" - "Query the per-network-interface scheduling parameters.\n" - " dom [int]: Identifier of domain to be queried.\n" - " vif [int]: Identifier of VIF to be queried.\n\n" - "Returns: [dict] dictionary is empty on failure.\n" - " credit_bytes [int]: Tx bytes permitted each interval.\n" - " credit_usecs [int]: Interval, in usecs. 0 == no scheduling.\n" }, - - { "vif_stats_get", - (PyCFunction)pyxc_vif_stats_get, - METH_VARARGS | METH_KEYWORDS, "\n" - "Query the per-network-interface statistics.\n" - " dom [int]: Identifier of domain to be queried.\n" - " vif [int]: Identifier of VIF to be queried.\n\n" - "Returns: [dict] dictionary is empty on failure.\n" - " tx_bytes [long]: Bytes transmitted.\n" - " tx_packets [long]: Packets transmitted.\n" - " rx_bytes [long]: Bytes received.\n" - " rx_packets [long]: Packets received.\n" }, - - { "vbd_create", - (PyCFunction)pyxc_vbd_create, - METH_VARARGS | METH_KEYWORDS, "\n" - "Create a new virtual block device associated with a given domain.\n" - " dom [int]: Identifier of domain to get a new VBD.\n" - " vbd [int]: Identifier for new VBD.\n" - " writeable [int]: Bool - is the new VBD writeable?\n\n" - "Returns: [int] 0 on success; -1 on error.\n" }, - - { "vbd_destroy", - (PyCFunction)pyxc_vbd_destroy, - METH_VARARGS | METH_KEYWORDS, "\n" - "Destroy a virtual block device.\n" - " dom [int]: Identifier of domain containing the VBD.\n" - " vbd [int]: Identifier of the VBD.\n\n" - "Returns: [int] 0 on success; -1 on error.\n" }, - - { "vbd_grow", - (PyCFunction)pyxc_vbd_grow, - METH_VARARGS | METH_KEYWORDS, "\n" - "Grow a virtual block device by appending a new extent.\n" - " dom [int]: Identifier of domain containing the VBD.\n" - " vbd [int]: Identifier of the VBD.\n" - " device [int]: Identifier of the real underlying block device.\n" - " start_sector [long]: Real start sector of this extent.\n" - " nr_sectors [long]: Length, in sectors, of this extent.\n\n" - "Returns: [int] 0 on success; -1 on error.\n" }, - - { "vbd_shrink", - (PyCFunction)pyxc_vbd_shrink, - METH_VARARGS | METH_KEYWORDS, "\n" - "Shrink a virtual block device by deleting its final extent.\n" - " dom [int]: Identifier of domain containing the VBD.\n" - " vbd [int]: Identifier of the VBD.\n\n" - "Returns: [int] 0 on success; -1 on error.\n" }, - - { "vbd_setextents", - (PyCFunction)pyxc_vbd_setextents, - METH_VARARGS | METH_KEYWORDS, "\n" - "Set all the extent information for a virtual block device.\n" - " dom [int]: Identifier of domain containing the VBD.\n" - " vbd [int]: Identifier of the VBD.\n" - " extents [list of dicts]: Per-extent information.\n" - " device [int]: Id of the real underlying block device.\n" - " start_sector [long]: Real start sector of this extent.\n" - " nr_sectors [long]: Length, in sectors, of this extent.\n\n" - "Returns: [int] 0 on success; -1 on error.\n" }, - - { "vbd_getextents", - (PyCFunction)pyxc_vbd_getextents, - METH_VARARGS | METH_KEYWORDS, "\n" - "Get info on all the extents in a virtual block device.\n" - " dom [int]: Identifier of domain containing the VBD.\n" - " vbd [int]: Identifier of the VBD.\n\n" - "Returns: [list of dicts] per-extent information; empty on error.\n" - " device [int]: Identifier of the real underlying block device.\n" - " start_sector [long]: Real start sector of this extent.\n" - " nr_sectors [long]: Length, in sectors, of this extent.\n" }, - - { "vbd_probe", - (PyCFunction)pyxc_vbd_probe, - METH_VARARGS | METH_KEYWORDS, "\n" - "Get information regarding extant virtual block devices.\n" - " dom [int, ALL]: Domain to query (default is to query all).\n" - " max_vbds [int, 1024]: Maximum VBDs to query.\n\n" - "Returns: [list of dicts] if list length is less than 'max_vbds'\n" - " parameter then there was an error, or there were fewer vbds.\n" - " dom [int]: Domain containing this VBD.\n" - " vbd [int]: Domain-specific identifier of this VBD.\n" - " writeable [int]: Bool - is this VBD writeable?\n" - " nr_sectors [long]: Size of this VBD, in 512-byte sectors.\n" }, - { "evtchn_bind_interdomain", (PyCFunction)pyxc_evtchn_bind_interdomain, METH_VARARGS | METH_KEYWORDS, "\n" diff --git a/tools/xenctl/lib/utils.py b/tools/xenctl/lib/utils.py index 11aadb4f08..8391ff590c 100644 --- a/tools/xenctl/lib/utils.py +++ b/tools/xenctl/lib/utils.py @@ -28,32 +28,6 @@ except ImportError: ##### Networking-related functions -def get_current_ipaddr(dev='eth0'): - """Return a string containing the primary IP address for the given - network interface (default 'eth0'). - """ - fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' ) - lines = fd.readlines() - for line in lines: - m = re.search( '^\s+inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*', - line ) - if m: - return m.group(1) - return None - -def get_current_ipmask(dev='eth0'): - """Return a string containing the primary IP netmask for the given - network interface (default 'eth0'). - """ - fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' ) - lines = fd.readlines() - for line in lines: - m = re.search( '^.+Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*', - line ) - if m: - return m.group(1) - return None - def get_current_ipgw(): """Return a string containing the default IP gateway.""" fd = os.popen( '/sbin/route -n' ) @@ -65,38 +39,6 @@ def get_current_ipgw(): return m.group(1) return None -def setup_vfr_rules_for_vif(dom,vif,addr): - """Takes a tuple ( domain-id, vif-id, ip-addr ), where the ip-addr - is expressed as a textual dotted quad, and set up appropriate routing - rules in Xen. No return value. - """ - fd = os.open( '/proc/xen/vfr', os.O_WRONLY ) - if ( re.search( '169\.254', addr) ): - os.write( fd, 'ADD ACCEPT srcaddr=' + addr + - ' srcaddrmask=255.255.255.255' + - ' srcdom=' + str(dom) + ' srcidx=' + str(vif) + - ' dstdom=0 dstidx=0 proto=any\n' ) - else: - os.write( fd, 'ADD ACCEPT srcaddr=' + addr + - ' srcaddrmask=255.255.255.255' + - ' srcdom=' + str(dom) + ' srcidx=' + str(vif) + - ' dst=PHYS proto=any\n' ) - os.write( fd, 'ADD ACCEPT dstaddr=' + addr + - ' dstaddrmask=255.255.255.255' + - ' src=ANY' + - ' dstdom=' + str(dom) + ' dstidx=' + str(vif) + - ' proto=any\n' ) - os.close( fd ) - return None - -def add_offset_to_ip( ip, off ): - l = string.split(ip,'.') - a = ( (string.atoi(l[0])<<24) | (string.atoi(l[1])<<16) | - (string.atoi(l[2])<<8) | string.atoi(l[3]) ) + off - - return '%d.%d.%d.%d' % ( ((a>>24)&0xff), ((a>>16)&0xff), - ((a>>8)&0xff), (a&0xff) ) - def check_subnet( ip, network, netmask ): l = string.split(ip,'.') n_ip = ( (string.atoi(l[0])<<24) | (string.atoi(l[1])<<16) | diff --git a/xen/Makefile b/xen/Makefile index 6ec66b6964..f149ad8ba6 100644 --- a/xen/Makefile +++ b/xen/Makefile @@ -29,7 +29,6 @@ dist: $(TARGET) clean: delete-links $(MAKE) -C tools clean $(MAKE) -C common clean - $(MAKE) -C net clean $(MAKE) -C drivers clean $(MAKE) -C arch/$(TARGET_ARCH) clean rm -f *.o $(TARGET)* *~ core $(GENERATED_FILES) @@ -37,9 +36,6 @@ clean: delete-links $(TARGET): delete-unfresh-files make-links $(GENERATED_FILES) $(MAKE) -C tools $(MAKE) -C common - if [ "$(old_drivers)" == "y" ]; then \ - $(MAKE) -C net ; \ - fi $(MAKE) -C drivers $(MAKE) -C arch/$(TARGET_ARCH) @@ -76,7 +72,7 @@ include/xen/compile.h: .PHONY: $(GENERATED_FILES) make-links delete-links default .PHONY: debug install clean delete-unfresh-files -SUBDIRS = arch common drivers net +SUBDIRS = arch common drivers TAGS: etags `find include/asm-$(TARGET_ARCH) -name '*.h'` find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print | xargs etags -a diff --git a/xen/Rules.mk b/xen/Rules.mk index fd2bddfc01..ffd18003ab 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -1,7 +1,6 @@ debug ?= n debugger ?= n -old_drivers ?= n perfc ?= n trace ?= n @@ -26,15 +25,6 @@ ALL_OBJS := $(BASEDIR)/common/common.o ALL_OBJS += $(BASEDIR)/drivers/char/driver.o ALL_OBJS += $(BASEDIR)/drivers/acpi/driver.o ALL_OBJS += $(BASEDIR)/drivers/pci/driver.o -ifeq ($(old_drivers),y) -ALL_OBJS += $(BASEDIR)/net/network.o -ALL_OBJS += $(BASEDIR)/drivers/net/driver.o -ALL_OBJS += $(BASEDIR)/drivers/block/driver.o -ALL_OBJS += $(BASEDIR)/drivers/cdrom/driver.o -ALL_OBJS += $(BASEDIR)/drivers/ide/driver.o -ALL_OBJS += $(BASEDIR)/drivers/scsi/driver.o -ALL_OBJS += $(BASEDIR)/drivers/message/fusion/driver.o -endif ALL_OBJS += $(BASEDIR)/arch/$(TARGET_ARCH)/arch.o HOSTCC = gcc @@ -50,10 +40,6 @@ ifeq ($(debugger),y) CFLAGS += -DXEN_DEBUGGER endif -ifeq ($(old_drivers),y) -CFLAGS += -DOLD_DRIVERS -endif - ifeq ($(perfc),y) CFLAGS += -DPERF_COUNTERS endif diff --git a/xen/arch/i386/entry.S b/xen/arch/i386/entry.S index 3493ff641a..f710ba51ad 100644 --- a/xen/arch/i386/entry.S +++ b/xen/arch/i386/entry.S @@ -711,21 +711,12 @@ ENTRY(hypervisor_call_table) .long SYMBOL_NAME(do_set_gdt) .long SYMBOL_NAME(do_stack_switch) .long SYMBOL_NAME(do_set_callbacks) /* 5 */ -#ifdef OLD_DRIVERS - .long SYMBOL_NAME(do_net_io_op) -#else - .long SYMBOL_NAME(do_ni_syscall) -#endif + .long SYMBOL_NAME(do_ni_syscall) # do_net_io_op .long SYMBOL_NAME(do_fpu_taskswitch) .long SYMBOL_NAME(do_sched_op) .long SYMBOL_NAME(do_dom0_op) -#ifdef OLD_DRIVERS - .long SYMBOL_NAME(do_network_op) /* 10 */ - .long SYMBOL_NAME(do_block_io_op) -#else - .long SYMBOL_NAME(do_ni_syscall) /* 10 */ - .long SYMBOL_NAME(do_ni_syscall) -#endif + .long SYMBOL_NAME(do_ni_syscall) /* 10 */ # do_network_op + .long SYMBOL_NAME(do_ni_syscall) # do_block_io_op .long SYMBOL_NAME(do_set_debugreg) .long SYMBOL_NAME(do_get_debugreg) .long SYMBOL_NAME(do_update_descriptor) diff --git a/xen/arch/i386/io_apic.c b/xen/arch/i386/io_apic.c index 0c9af32961..9c94e787e0 100644 --- a/xen/arch/i386/io_apic.c +++ b/xen/arch/i386/io_apic.c @@ -208,79 +208,8 @@ static void set_ioapic_affinity (unsigned int irq, unsigned long mask) spin_unlock_irqrestore(&ioapic_lock, flags); } -/* - * In new I/O model, the interrupt is pinned to the CPU of the first - * device-driver domain that attaches. Dynamic balancing is pointless. - */ -#if defined(CONFIG_SMP) && defined(OLD_DRIVERS) - -typedef struct { - unsigned int cpu; - unsigned long timestamp; -} ____cacheline_aligned irq_balance_t; - -static irq_balance_t irq_balance[NR_IRQS] __cacheline_aligned - = { [ 0 ... NR_IRQS-1 ] = { 0, 0 } }; - -extern unsigned long irq_affinity [NR_IRQS]; - -#define IDLE_ENOUGH(cpu,now) \ - (idle_cpu(cpu) && ((now) - irq_stat[(cpu)].idle_timestamp > 1)) - -#define IRQ_ALLOWED(cpu,allowed_mask) \ - ((1 << cpu) & (allowed_mask)) - -static unsigned long move(int curr_cpu, unsigned long allowed_mask, unsigned long now, int direction) -{ - int search_idle = 1; - int cpu = curr_cpu; - - goto inside; - - do { - if (unlikely(cpu == curr_cpu)) - search_idle = 0; -inside: - if (direction == 1) { - cpu++; - if (cpu >= smp_num_cpus) - cpu = 0; - } else { - cpu--; - if (cpu == -1) - cpu = smp_num_cpus-1; - } - } while (!IRQ_ALLOWED(cpu,allowed_mask) || - (search_idle && !IDLE_ENOUGH(cpu,now))); - - return cpu; -} - -static inline void balance_irq(int irq) -{ - irq_balance_t *entry = irq_balance + irq; - unsigned long now = jiffies; - - if (unlikely(entry->timestamp != now)) { - unsigned long allowed_mask; - int random_number; - - rdtscl(random_number); - random_number &= 1; - - allowed_mask = cpu_online_map & irq_affinity[irq]; - entry->timestamp = now; - entry->cpu = move(entry->cpu, allowed_mask, now, random_number); - set_ioapic_affinity(irq, apicid_to_phys_cpu_present(entry->cpu)); - } -} - -#else - #define balance_irq(_irq) ((void)0) -#endif - /* * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to * specific CPU-side IRQs. diff --git a/xen/arch/i386/setup.c b/xen/arch/i386/setup.c index 5219fda9ab..70610339b3 100644 --- a/xen/arch/i386/setup.c +++ b/xen/arch/i386/setup.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -328,11 +329,6 @@ void __init start_of_day(void) extern void timer_bh(void); extern void init_timervecs(void); extern void ac_timer_init(void); -#ifdef OLD_DRIVERS - extern int setup_network_devices(void); - extern void net_init(void); - extern void initialize_block_io(void); -#endif extern void initialize_keytable(); extern void initialize_keyboard(void); extern int opt_nosmp, opt_watchdog, opt_noacpi, opt_ignorebiostables; @@ -437,12 +433,6 @@ void __init start_of_day(void) pci_init(); #endif do_initcalls(); -#ifdef OLD_DRIVERS - if ( !setup_network_devices() ) - panic("Must have a network device!\n"); - net_init(); /* initializes virtual network system. */ - initialize_block_io(); /* setup block devices */ -#endif #ifdef CONFIG_SMP wait_init_idle = cpu_online_map; diff --git a/xen/arch/i386/smp.c b/xen/arch/i386/smp.c index e3d861e826..3c1082683f 100644 --- a/xen/arch/i386/smp.c +++ b/xen/arch/i386/smp.c @@ -222,33 +222,6 @@ asmlinkage void smp_invalidate_interrupt(void) local_flush_tlb(); } -#ifdef OLD_DRIVERS -int try_flush_tlb_mask(unsigned long mask) -{ - if ( mask & (1 << smp_processor_id()) ) - { - local_flush_tlb(); - mask &= ~(1 << smp_processor_id()); - } - - if ( mask != 0 ) - { - if ( unlikely(!spin_trylock(&flush_lock)) ) - return 0; - flush_cpumask = mask; - send_IPI_mask(mask, INVALIDATE_TLB_VECTOR); - while ( flush_cpumask != 0 ) - { - rep_nop(); - barrier(); - } - spin_unlock(&flush_lock); - } - - return 1; -} -#endif - void flush_tlb_mask(unsigned long mask) { ASSERT(!in_irq()); diff --git a/xen/common/Makefile b/xen/common/Makefile index 12454c9aed..34febca43e 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -6,10 +6,6 @@ OBJS := $(subst debug.o,,$(OBJS)) OBJS := $(subst debug-linux.o,,$(OBJS)) endif -ifneq ($(old_drivers),y) -OBJS := $(subst network.o,,$(OBJS)) -endif - ifneq ($(perfc),y) OBJS := $(subst perfc.o,,$(OBJS)) endif diff --git a/xen/common/brlock.c b/xen/common/brlock.c deleted file mode 100644 index 5cc7366f9c..0000000000 --- a/xen/common/brlock.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * linux/lib/brlock.c - * - * 'Big Reader' read-write spinlocks. See linux/brlock.h for details. - * - * Copyright 2000, Ingo Molnar - * Copyright 2000, David S. Miller - */ - -#include - -#ifdef CONFIG_SMP - -#include -#include - -#ifdef __BRLOCK_USE_ATOMICS - -brlock_read_lock_t __brlock_array[NR_CPUS][__BR_IDX_MAX] = - { [0 ... NR_CPUS-1] = { [0 ... __BR_IDX_MAX-1] = RW_LOCK_UNLOCKED } }; - -void __br_write_lock (enum brlock_indices idx) -{ - int i; - - for (i = 0; i < smp_num_cpus; i++) - write_lock(&__brlock_array[cpu_logical_map(i)][idx]); -} - -void __br_write_unlock (enum brlock_indices idx) -{ - int i; - - for (i = 0; i < smp_num_cpus; i++) - write_unlock(&__brlock_array[cpu_logical_map(i)][idx]); -} - -#else /* ! __BRLOCK_USE_ATOMICS */ - -brlock_read_lock_t __brlock_array[NR_CPUS][__BR_IDX_MAX] = - { [0 ... NR_CPUS-1] = { [0 ... __BR_IDX_MAX-1] = 0 } }; - -struct br_wrlock __br_write_locks[__BR_IDX_MAX] = - { [0 ... __BR_IDX_MAX-1] = { SPIN_LOCK_UNLOCKED } }; - -void __br_write_lock (enum brlock_indices idx) -{ - int i; - -again: - spin_lock(&__br_write_locks[idx].lock); - for (i = 0; i < smp_num_cpus; i++) - if (__brlock_array[cpu_logical_map(i)][idx] != 0) { - spin_unlock(&__br_write_locks[idx].lock); - barrier(); - cpu_relax(); - goto again; - } -} - -void __br_write_unlock (enum brlock_indices idx) -{ - spin_unlock(&__br_write_locks[idx].lock); -} - -#endif /* __BRLOCK_USE_ATOMICS */ - -#endif /* CONFIG_SMP */ diff --git a/xen/common/domain.c b/xen/common/domain.c index 3da5d7913a..9bad3e1cdf 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -1,10 +1,10 @@ + #include #include #include #include #include #include -#include #include #include #include @@ -15,9 +15,7 @@ #include #include #include -#include #include -#include #include #include @@ -79,8 +77,6 @@ struct task_struct *do_createdomain(domid_t dom_id, unsigned int cpu) strncpy(p->name, buf, MAX_DOMAIN_NAME); p->name[MAX_DOMAIN_NAME-1] = '\0'; - spin_lock_init(&p->blk_ring_lock); - p->addr_limit = USER_DS; spin_lock_init(&p->page_list_lock); @@ -98,8 +94,6 @@ struct task_struct *do_createdomain(domid_t dom_id, unsigned int cpu) machine_to_phys_mapping[virt_to_phys(p->mm.perdomain_pt) >> PAGE_SHIFT] = 0x0fffdeadUL; /* debug */ - init_blkdev_info(p); - /* Per-domain PCI-device list. */ spin_lock_init(&p->pcidev_lock); INIT_LIST_HEAD(&p->pcidev_list); @@ -172,7 +166,6 @@ struct task_struct *find_last_domain(void) void __kill_domain(struct task_struct *p) { - int i; struct task_struct **pp; unsigned long flags; @@ -189,15 +182,8 @@ void __kill_domain(struct task_struct *p) DPRINTK("Killing domain %u\n", p->domain); - unlink_blkdev_info(p); - - for ( i = 0; i < MAX_DOMAIN_VIFS; i++ ) - unlink_net_vif(p->net_vif_list[i]); - destroy_event_channels(p); - delete_all_domain_vfr_rules(p); - /* * Note this means that find_domain_by_id may fail, even when the caller * holds a reference to the domain being queried. Take care! @@ -269,6 +255,13 @@ void stop_domain(u8 reason) { struct task_struct *p; + if ( current->domain == 0 ) + { + extern void machine_restart(char *); + printk("Domain 0 halted: rebooting machine!\n"); + machine_restart(0); + } + current->stop_code = reason; memcpy(¤t->shared_info->execution_context, get_execution_context(), @@ -307,11 +300,7 @@ struct pfn_info *alloc_domain_page(struct task_struct *p) unsigned long flags, mask, pfn_stamp, cpu_stamp; int i; -#ifdef OLD_DRIVERS - ASSERT((p == NULL) || !in_irq()); -#else ASSERT(!in_irq()); -#endif spin_lock_irqsave(&free_list_lock, flags); if ( likely(!list_empty(&free_list)) ) @@ -340,15 +329,7 @@ struct pfn_info *alloc_domain_page(struct task_struct *p) if ( unlikely(mask != 0) ) { -#ifdef OLD_DRIVERS - /* In IRQ ctxt, flushing is best-effort only, to avoid deadlock. */ - if ( likely(!in_irq()) ) - flush_tlb_mask(mask); - else if ( unlikely(!try_flush_tlb_mask(mask)) ) - goto free_and_exit; -#else flush_tlb_mask(mask); -#endif perfc_incrc(need_flush_tlb_flush); } } @@ -567,12 +548,6 @@ void release_task(struct task_struct *p) DPRINTK("Releasing task %u\n", p->domain); - /* - * This frees up blkdev rings and vbd-access lists. Totally safe since - * blkdev ref counting actually uses the task_struct refcnt. - */ - destroy_blkdev_info(p); - /* Free all memory associated with this domain. */ free_page((unsigned long)p->mm.perdomain_pt); UNSHARE_PFN(virt_to_page(p->shared_info)); @@ -649,10 +624,6 @@ int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain) /* Set up the shared info structure. */ update_dom_time(p->shared_info); - /* Add virtual network interfaces and point to them in startinfo. */ - while ( builddomain->num_vifs-- > 0 ) - (void)create_net_vif(p->domain); - set_bit(PF_CONSTRUCTED, &p->flags); out: @@ -781,7 +752,6 @@ static int loadelfimage(char *elfbase) int construct_dom0(struct task_struct *p, unsigned long alloc_start, unsigned long alloc_end, - unsigned int num_vifs, char *image_start, unsigned long image_len, char *initrd_start, unsigned long initrd_len, char *cmdline) @@ -823,14 +793,6 @@ int construct_dom0(struct task_struct *p, extern void physdev_init_dom0(struct task_struct *); -#ifdef OLD_DRIVERS - extern void ide_probe_devices(xen_disk_info_t *); - extern void scsi_probe_devices(xen_disk_info_t *); - extern void cciss_probe_devices(xen_disk_info_t *); - xen_disk_info_t xdi; - xen_disk_t *xd; -#endif - /* Sanity! */ if ( p->domain != 0 ) BUG(); @@ -1082,34 +1044,6 @@ int construct_dom0(struct task_struct *p, /* Give up the VGA console if DOM0 is configured to grab it. */ console_endboot(strstr(cmdline, "tty0") != NULL); - /* Add virtual network interfaces. */ - while ( num_vifs-- > 0 ) - (void)create_net_vif(0); - -#ifdef OLD_DRIVERS - /* DOM0 gets access to all real block devices. */ -#define MAX_REAL_DISKS 256 - xd = kmalloc(MAX_REAL_DISKS * sizeof(xen_disk_t), GFP_KERNEL); - xdi.max = MAX_REAL_DISKS; - xdi.count = 0; - xdi.disks = xd; - ide_probe_devices(&xdi); - scsi_probe_devices(&xdi); - cciss_probe_devices(&xdi); - for ( i = 0; i < xdi.count; i++ ) - { - xen_extent_t e; - e.device = xd[i].device; - e.start_sector = 0; - e.nr_sectors = xd[i].capacity; - if ( (__vbd_create(p, xd[i].device, VBD_MODE_R|VBD_MODE_W, - xd[i].info) != 0) || - (__vbd_grow(p, xd[i].device, &e) != 0) ) - BUG(); - } - kfree(xd); -#endif - /* DOM0 gets access to everything. */ physdev_init_dom0(p); diff --git a/xen/common/kernel.c b/xen/common/kernel.c index 3e8e617cb3..d749a795a2 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -16,23 +16,18 @@ #include #include #include -#include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include #include #include #include +#include +#include +#include +#include +#include kmem_cache_t *task_struct_cachep; @@ -283,7 +278,7 @@ void cmain(unsigned long magic, multiboot_info_t *mbi) * above our MAX_DIRECTMAP_ADDRESS in boot/boot.S. The second module, if * present, is an initrd ramdisk. */ - if ( construct_dom0(new_dom, dom0_memory_start, dom0_memory_end, 1, + if ( construct_dom0(new_dom, dom0_memory_start, dom0_memory_end, (char *)initial_images_start, mod[0].mod_end-mod[0].mod_start, (mbi->mods_count == 1) ? 0 : diff --git a/xen/common/network.c b/xen/common/network.c deleted file mode 100644 index 255feae2af..0000000000 --- a/xen/common/network.c +++ /dev/null @@ -1,615 +0,0 @@ -/****************************************************************************** - * network.c - * - * Network virtualization for Xen. Lower-level network interactions are in - * net/dev.c and in the drivers. This file contains routines to interact - * with the virtual interfaces (vifs) and the virtual firewall/router through - * the use of rules. - * - * Copyright (c) 2002-2003, A K Warfield and K A Fraser - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -net_rule_ent_t *net_rule_list; /* global list of rules */ -kmem_cache_t *net_vif_cache; -kmem_cache_t *net_rule_cache; -static rwlock_t net_rule_lock = RW_LOCK_UNLOCKED; /* rule mutex */ - -void print_net_rule_list(); - - -/* ----[ VIF Functions ]----------------------------------------------------*/ - - -net_vif_t *find_net_vif(domid_t dom, unsigned int idx) -{ - struct task_struct *p; - net_vif_t *vif = NULL; - unsigned long flags; - - read_lock_irqsave(&tasklist_lock, flags); - p = task_hash[TASK_HASH(dom)]; - while ( p != NULL ) - { - if ( p->domain == dom ) - { - vif = p->net_vif_list[idx]; - if ( vif != NULL ) - get_vif(vif); - break; - } - p = p->next_hash; - } - read_unlock_irqrestore(&tasklist_lock, flags); - - return vif; -} - - -/* - * create_net_vif - Create a new vif and append it to the specified domain. - * - * The domain is examined to determine how many vifs currently are allocated - * and the newly allocated vif is appended. The vif is also added to the - * global list. - * - */ -net_vif_t *create_net_vif(domid_t dom) -{ - unsigned int idx; - net_vif_t *new_vif = NULL; - net_ring_t *new_ring = NULL; - struct task_struct *p = NULL; - unsigned long flags, vmac_hash; - unsigned char vmac_key[ETH_ALEN + 2 + MAX_DOMAIN_NAME]; - - if ( (p = find_domain_by_id(dom)) == NULL ) - return NULL; - - write_lock_irqsave(&tasklist_lock, flags); - - for ( idx = 0; idx < MAX_DOMAIN_VIFS; idx++ ) - if ( p->net_vif_list[idx] == NULL ) - break; - if ( idx == MAX_DOMAIN_VIFS ) - goto fail; - - if ( (new_vif = kmem_cache_alloc(net_vif_cache, GFP_KERNEL)) == NULL ) - goto fail; - - memset(new_vif, 0, sizeof(*new_vif)); - - if ( sizeof(net_ring_t) > PAGE_SIZE ) - BUG(); - new_ring = (net_ring_t *)get_free_page(GFP_KERNEL); - clear_page(new_ring); - SHARE_PFN_WITH_DOMAIN(virt_to_page(new_ring), p); - - machine_to_phys_mapping[virt_to_phys(new_ring)>>PAGE_SHIFT] = - 0x80000001; // magic value aids debugging - - /* - * Fill in the new vif struct. Note that, while the vif's refcnt is - * non-zero, we hold a reference to the task structure. - */ - atomic_set(&new_vif->refcnt, 1); - new_vif->shared_rings = new_ring; - new_vif->shared_idxs = &p->shared_info->net_idx[idx]; - new_vif->domain = p; - new_vif->idx = idx; - new_vif->list.next = NULL; - spin_lock_init(&new_vif->rx_lock); - spin_lock_init(&new_vif->tx_lock); - - new_vif->credit_bytes = new_vif->remaining_credit = ~0UL; - new_vif->credit_usec = 0UL; - init_ac_timer(&new_vif->credit_timeout); - - if ( (p->domain == 0) && (idx == 0) ) - { - /* - * DOM0/VIF0 gets the real physical MAC address, so that users can - * easily get a Xen-based machine up and running by using an existing - * DHCP entry. - */ - memcpy(new_vif->vmac, the_dev->dev_addr, ETH_ALEN); - } - else - { - /* - * Most VIFs get a random MAC address with a "special" vendor id. - * We try to get MAC addresses to be unique across multiple servers - * by including the physical MAC address in the hash. The hash also - * includes the vif index and the domain's name. - * - * NB. The vendor is currently an "obsolete" one that used to belong - * to DEC (AA-00-00). Using it is probably a bit rude :-) - * - * NB2. The first bit of the first random octet is set to zero for - * all dynamic MAC addresses. This may allow us to manually specify - * MAC addresses for some VIFs with no fear of clashes. - */ - memcpy(&vmac_key[0], the_dev->dev_addr, ETH_ALEN); - *(__u16 *)(&vmac_key[ETH_ALEN]) = htons(idx); - strcpy(&vmac_key[ETH_ALEN+2], p->name); - vmac_hash = hash(vmac_key, ETH_ALEN + 2 + strlen(p->name)); - memcpy(new_vif->vmac, "\xaa\x00\x00", 3); - new_vif->vmac[3] = (vmac_hash >> 16) & 0xef; /* First bit is zero. */ - new_vif->vmac[4] = (vmac_hash >> 8) & 0xff; - new_vif->vmac[5] = (vmac_hash >> 0) & 0xff; - } - - p->net_vif_list[idx] = new_vif; - - write_unlock_irqrestore(&tasklist_lock, flags); - return new_vif; - - fail: - write_unlock_irqrestore(&tasklist_lock, flags); - if ( new_vif != NULL ) - kmem_cache_free(net_vif_cache, new_vif); - if ( p != NULL ) - put_task_struct(p); - return NULL; -} - -void destroy_net_vif(net_vif_t *vif) -{ - extern long flush_bufs_for_vif(net_vif_t *vif); - struct task_struct *p = vif->domain; - (void)flush_bufs_for_vif(vif); - UNSHARE_PFN(virt_to_page(vif->shared_rings)); - kmem_cache_free(net_vif_cache, vif); - put_task_struct(p); -} - -void unlink_net_vif(net_vif_t *vif) -{ - unsigned long flags; - - if ( vif == NULL ) - return; - - write_lock_irqsave(&tasklist_lock, flags); - vif->domain->net_vif_list[vif->idx] = NULL; - write_unlock_irqrestore(&tasklist_lock, flags); - - put_vif(vif); -} - - -int vif_query(vif_query_t *vq) -{ - net_vif_t *vif; - struct task_struct *p; - int buf[32]; - int i; - int count = 0; - - if ( (p = find_domain_by_id(vq->domain)) == NULL ) - { - buf[0] = -1; - copy_to_user(vq->buf, buf, sizeof(int)); - return -ESRCH; - } - - for ( i = 0; i < MAX_DOMAIN_VIFS; i++ ) - { - vif = p->net_vif_list[i]; - if ( vif == NULL ) continue; - buf[++count] = i; - } - - buf[0] = count; - - copy_to_user(vq->buf, buf, (buf[0] + 1) * sizeof(int)); - - put_task_struct(p); - - return 0; -} - -int vif_getinfo(vif_getinfo_t *info) -{ - net_vif_t *vif; - - if ( (vif = find_net_vif(info->domain, info->vif)) == NULL ) - return -ESRCH; - - info->total_bytes_sent = vif->total_bytes_sent; - info->total_bytes_received = vif->total_bytes_received; - info->total_packets_sent = vif->total_packets_sent; - info->total_packets_received = vif->total_packets_received; - - info->credit_bytes = vif->credit_bytes; - info->credit_usec = vif->credit_usec; - - put_vif(vif); - - return 0; -} - - -int vif_setparams(vif_setparams_t *params) -{ - net_vif_t *vif; - - if ( (vif = find_net_vif(params->domain, params->vif)) == NULL ) - return -ESRCH; - - /* Turning off rate limiting? */ - if ( params->credit_usec == 0 ) - params->credit_bytes = ~0UL; - - vif->credit_bytes = vif->remaining_credit = params->credit_bytes; - vif->credit_usec = params->credit_usec; - - put_vif(vif); - - return 0; -} - - -/* ----[ Net Rule Functions ]-----------------------------------------------*/ - -int add_net_rule(net_rule_t *rule) -{ - net_rule_ent_t *new_ent; - - if ( (new_ent = kmem_cache_alloc(net_rule_cache, GFP_KERNEL)) == NULL ) - return -ENOMEM; - - memcpy(&new_ent->r, rule, sizeof(net_rule_t)); - - write_lock(&net_rule_lock); - new_ent->next = net_rule_list; - net_rule_list = new_ent; - write_unlock(&net_rule_lock); - - return 0; -} - -int delete_net_rule(net_rule_t *rule) -{ - net_rule_ent_t **pent, *ent; - - write_lock(&net_rule_lock); - - for ( pent = &net_rule_list; (ent = *pent) != NULL; pent = &ent->next ) - { - if ( memcmp(rule, &ent->r, sizeof(net_rule_t)) == 0 ) - { - *pent = ent->next; - kmem_cache_free(net_rule_cache, ent); - break; - } - } - - write_unlock(&net_rule_lock); - return 0; -} - -void delete_all_domain_vfr_rules(struct task_struct *p) -{ - net_rule_ent_t **pent, *ent; - - write_lock(&net_rule_lock); - - for ( pent = &net_rule_list; (ent = *pent) != NULL; ) - { - if ( (ent->r.src_dom == p->domain) || (ent->r.dst_dom == p->domain) ) - { - *pent = ent->next; - kmem_cache_free(net_rule_cache, ent); - continue; - } - - pent = &ent->next; - } - - write_unlock(&net_rule_lock); -} - -static char *idx_to_name(unsigned int idx) -{ - if ( idx == VIF_PHYSICAL_INTERFACE ) - return "PHYSICAL"; - if ( idx == VIF_ANY_INTERFACE ) - return "ANY"; - return "UNKNOWN"; -} - -static char *print_ip_addr(char *buf, unsigned long addr) -{ - sprintf(buf, "%lu.%lu.%lu.%lu", - (addr>>24)&255, (addr>>16)&255, (addr>>8)&255, addr&255); - return buf; -} - -void print_net_rule(net_rule_t *r) -{ - char buf[20]; - - printk("===] NET RULE:\n"); - printk("=] src_addr : %s\n", print_ip_addr(buf, r->src_addr)); - printk("=] src_addr_mask : %s\n", print_ip_addr(buf, r->src_addr_mask)); - printk("=] dst_addr : %s\n", print_ip_addr(buf, r->dst_addr)); - printk("=] dst_addr_mask : %s\n", print_ip_addr(buf, r->dst_addr_mask)); - printk("=] src_port : %u\n", r->src_port); - printk("=] src_port_mask : %u\n", r->src_port_mask); - printk("=] dst_port : %u\n", r->dst_port); - printk("=] dst_port_mask : %u\n", r->dst_port_mask); - printk("=] dst_proto : %u\n", r->proto); - - if ( r->src_dom == VIF_SPECIAL ) - printk("=] src_dom/idx : %s\n", idx_to_name(r->src_idx)); - else - printk("=] src_dom/idx : %u/%u\n", r->src_dom, r->src_idx); - - if ( r->dst_dom == VIF_SPECIAL ) - printk("=] dst_dom/idx : %s\n", idx_to_name(r->dst_idx)); - else - printk("=] dst_dom/idx : %u/%u\n", r->dst_dom, r->dst_idx); - - printk("=] action : %u\n", r->action); -} - -void print_net_rule_list(void) -{ - net_rule_ent_t *ent; - int count = 0; - - read_lock(&net_rule_lock); - - ent = net_rule_list; - - while ( ent != NULL ) - { - print_net_rule(&ent->r); - ent = ent->next; - count++; - } - - printk("\nTotal of %d rules.\n", count); - - read_unlock(&net_rule_lock); -} - - -/* net_find_rule - Find the destination vif according to the current rules. - * - * Apply the rules to this skbuff and return the vif id that it is bound for. - * If there is no match, VIF_DROP is returned. - */ -static net_vif_t *net_find_rule(u8 nproto, u8 tproto, u32 src_addr, - u32 dst_addr, u16 src_port, - u16 dst_port, - domid_t src_dom, unsigned int src_idx) -{ - net_rule_ent_t *ent; - domid_t dst_dom = VIF_SPECIAL; - unsigned int dst_idx = VIF_UNKNOWN_INTERFACE; - - read_lock(&net_rule_lock); - - ent = net_rule_list; - - while ( ent != NULL ) - { - if ( (((ent->r.src_dom == src_dom) && - (ent->r.src_idx == src_idx)) || - ((ent->r.src_dom == VIF_SPECIAL) && - (ent->r.src_idx == VIF_ANY_INTERFACE))) && - - ((src_dom != ent->r.dst_dom) || - (src_idx != ent->r.dst_idx)) && - - (!((ent->r.src_addr ^ src_addr) & ent->r.src_addr_mask )) && - (!((ent->r.dst_addr ^ dst_addr) & ent->r.dst_addr_mask )) && - (!((ent->r.src_port ^ src_port) & ent->r.src_port_mask )) && - (!((ent->r.dst_port ^ dst_port) & ent->r.dst_port_mask )) && - - ((ent->r.proto == NETWORK_PROTO_ANY) || - ((ent->r.proto == NETWORK_PROTO_IP) && - (nproto == (u8)ETH_P_IP)) || - ((ent->r.proto == NETWORK_PROTO_ARP) && - (nproto == (u8)ETH_P_ARP)) || - ((ent->r.proto == NETWORK_PROTO_TCP) && - (tproto == IPPROTO_TCP)) || - ((ent->r.proto == NETWORK_PROTO_UDP) && - (tproto == IPPROTO_UDP))) - ) - { - dst_dom = ent->r.dst_dom; - dst_idx = ent->r.dst_idx; - /* - * XXX FFS! We keep going to find the "best" rule. Where best - * corresponds to vaguely sane routing of a packet. We need a less - * shafted model for our "virtual firewall/router" methinks! - */ - if ( dst_dom != VIF_SPECIAL ) - break; - } - ent = ent->next; - } - - read_unlock(&net_rule_lock); - - if ( dst_dom == VIF_SPECIAL ) - { - if ( dst_idx == VIF_PHYSICAL_INTERFACE ) - return VIF_PHYS; - return VIF_DROP; - } - - return find_net_vif(dst_dom, dst_idx); -} - -/* net_get_target_vif - Find the vif that the given sk_buff is bound for. - * - * This is intended to be the main interface to the VFR rules, where - * net_find_rule (above) is a private aspect of the current matching - * implementation. All in-hypervisor routing should use this function only - * to ensure that this can be rewritten later. - * - * Currently, network rules are stored in a global linked list. New rules are - * added to the front of this list, and (at present) the first matching rule - * determines the vif that a packet is sent to. This is obviously not ideal, - * it might be more advisable to have chains, or at lest most-specific - * matching, and moreover routing latency increases linearly (for old rules) - * as new rules are added. - * - * net_get_target_vif examines the sk_buff and pulls out the relevant fields - * based on the packet type. it then calls net_find_rule to scan the rule - * list. - */ -net_vif_t *net_get_target_vif(u8 *data, unsigned int len, net_vif_t *src_vif) -{ - net_vif_t *target = VIF_DROP; - u8 *h_raw, *nh_raw; - domid_t src_dom = VIF_SPECIAL; - unsigned int src_idx = VIF_PHYSICAL_INTERFACE; - - if ( src_vif != VIF_PHYS ) - { - src_dom = src_vif->domain->domain; - src_idx = src_vif->idx; - } - - if ( len < ETH_HLEN ) - goto drop; - - nh_raw = data + ETH_HLEN; - switch ( ntohs(*(unsigned short *)(data + 12)) ) - { - case ETH_P_ARP: - if ( len < (ETH_HLEN + 28) ) goto drop; - target = net_find_rule((u8)ETH_P_ARP, 0, ntohl(*(u32 *)(nh_raw + 14)), - ntohl(*(u32 *)(nh_raw + 24)), 0, 0, - src_dom, src_idx); - break; - - case ETH_P_IP: - if ( len < (ETH_HLEN + 20) ) goto drop; - h_raw = data + ((*(unsigned char *)(nh_raw)) & 0x0f) * 4; - /* NB. For now we ignore ports. */ - target = net_find_rule((u8)ETH_P_IP, *(u8 *)(data + 9), - ntohl(*(u32 *)(nh_raw + 12)), - ntohl(*(u32 *)(nh_raw + 16)), - 0, - 0, - src_dom, src_idx); - break; - } - return target; - - drop: - DPRINTK("VIF%u/%u: pkt to drop!\n", src_dom, src_idx); - return VIF_DROP; -} - -/* ----[ Syscall Interface ]------------------------------------------------*/ - -/* - * This is the hook function to handle guest-invoked traps requesting - * changes to the network system. - */ - -long do_network_op(network_op_t *u_network_op) -{ - long ret=0; - network_op_t op; - - if ( current->domain != 0 ) - return -EPERM; - - if ( copy_from_user(&op, u_network_op, sizeof(op)) ) - return -EFAULT; - - switch ( op.cmd ) - { - - case NETWORK_OP_ADDRULE: - { - add_net_rule(&op.u.net_rule); - } - break; - - case NETWORK_OP_DELETERULE: - { - delete_net_rule(&op.u.net_rule); - } - break; - - case NETWORK_OP_GETRULELIST: - { - /* - * This should ship a rule list up to the guest OS. For now - * we just dump the rules to our own console. - */ - print_net_rule_list(); - } - break; - - case NETWORK_OP_VIFGETINFO: - { - ret = vif_getinfo(&op.u.vif_getinfo); - copy_to_user(u_network_op, &op, sizeof(op)); - } - break; - - case NETWORK_OP_VIFQUERY: - { - ret = vif_query(&op.u.vif_query); - } - break; - - case NETWORK_OP_VIFSETPARAMS: - { - ret = vif_setparams(&op.u.vif_setparams); - } - break; - - default: - ret = -ENOSYS; - } - - return ret; -} - -void __init net_init (void) -{ - net_rule_list = NULL; - net_vif_cache = kmem_cache_create("net_vif_cache", - sizeof(net_vif_t), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - net_rule_cache = kmem_cache_create("net_rule_cache", - sizeof(net_rule_ent_t), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); -} diff --git a/xen/common/rbtree.c b/xen/common/rbtree.c deleted file mode 100644 index 027d9d6df3..0000000000 --- a/xen/common/rbtree.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - Red Black Trees - (C) 1999 Andrea Arcangeli - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - linux/lib/rbtree.c -*/ - -#include - -static void __rb_rotate_left(rb_node_t * node, rb_root_t * root) -{ - rb_node_t * right = node->rb_right; - - if ((node->rb_right = right->rb_left)) - right->rb_left->rb_parent = node; - right->rb_left = node; - - if ((right->rb_parent = node->rb_parent)) - { - if (node == node->rb_parent->rb_left) - node->rb_parent->rb_left = right; - else - node->rb_parent->rb_right = right; - } - else - root->rb_node = right; - node->rb_parent = right; -} - -static void __rb_rotate_right(rb_node_t * node, rb_root_t * root) -{ - rb_node_t * left = node->rb_left; - - if ((node->rb_left = left->rb_right)) - left->rb_right->rb_parent = node; - left->rb_right = node; - - if ((left->rb_parent = node->rb_parent)) - { - if (node == node->rb_parent->rb_right) - node->rb_parent->rb_right = left; - else - node->rb_parent->rb_left = left; - } - else - root->rb_node = left; - node->rb_parent = left; -} - -void rb_insert_color(rb_node_t * node, rb_root_t * root) -{ - rb_node_t * parent, * gparent; - - while ((parent = node->rb_parent) && parent->rb_color == RB_RED) - { - gparent = parent->rb_parent; - - if (parent == gparent->rb_left) - { - { - register rb_node_t * uncle = gparent->rb_right; - if (uncle && uncle->rb_color == RB_RED) - { - uncle->rb_color = RB_BLACK; - parent->rb_color = RB_BLACK; - gparent->rb_color = RB_RED; - node = gparent; - continue; - } - } - - if (parent->rb_right == node) - { - register rb_node_t * tmp; - __rb_rotate_left(parent, root); - tmp = parent; - parent = node; - node = tmp; - } - - parent->rb_color = RB_BLACK; - gparent->rb_color = RB_RED; - __rb_rotate_right(gparent, root); - } else { - { - register rb_node_t * uncle = gparent->rb_left; - if (uncle && uncle->rb_color == RB_RED) - { - uncle->rb_color = RB_BLACK; - parent->rb_color = RB_BLACK; - gparent->rb_color = RB_RED; - node = gparent; - continue; - } - } - - if (parent->rb_left == node) - { - register rb_node_t * tmp; - __rb_rotate_right(parent, root); - tmp = parent; - parent = node; - node = tmp; - } - - parent->rb_color = RB_BLACK; - gparent->rb_color = RB_RED; - __rb_rotate_left(gparent, root); - } - } - - root->rb_node->rb_color = RB_BLACK; -} -EXPORT_SYMBOL(rb_insert_color); - -static void __rb_erase_color(rb_node_t * node, rb_node_t * parent, - rb_root_t * root) -{ - rb_node_t * other; - - while ((!node || node->rb_color == RB_BLACK) && node != root->rb_node) - { - if (parent->rb_left == node) - { - other = parent->rb_right; - if (other->rb_color == RB_RED) - { - other->rb_color = RB_BLACK; - parent->rb_color = RB_RED; - __rb_rotate_left(parent, root); - other = parent->rb_right; - } - if ((!other->rb_left || - other->rb_left->rb_color == RB_BLACK) - && (!other->rb_right || - other->rb_right->rb_color == RB_BLACK)) - { - other->rb_color = RB_RED; - node = parent; - parent = node->rb_parent; - } - else - { - if (!other->rb_right || - other->rb_right->rb_color == RB_BLACK) - { - register rb_node_t * o_left; - if ((o_left = other->rb_left)) - o_left->rb_color = RB_BLACK; - other->rb_color = RB_RED; - __rb_rotate_right(other, root); - other = parent->rb_right; - } - other->rb_color = parent->rb_color; - parent->rb_color = RB_BLACK; - if (other->rb_right) - other->rb_right->rb_color = RB_BLACK; - __rb_rotate_left(parent, root); - node = root->rb_node; - break; - } - } - else - { - other = parent->rb_left; - if (other->rb_color == RB_RED) - { - other->rb_color = RB_BLACK; - parent->rb_color = RB_RED; - __rb_rotate_right(parent, root); - other = parent->rb_left; - } - if ((!other->rb_left || - other->rb_left->rb_color == RB_BLACK) - && (!other->rb_right || - other->rb_right->rb_color == RB_BLACK)) - { - other->rb_color = RB_RED; - node = parent; - parent = node->rb_parent; - } - else - { - if (!other->rb_left || - other->rb_left->rb_color == RB_BLACK) - { - register rb_node_t * o_right; - if ((o_right = other->rb_right)) - o_right->rb_color = RB_BLACK; - other->rb_color = RB_RED; - __rb_rotate_left(other, root); - other = parent->rb_left; - } - other->rb_color = parent->rb_color; - parent->rb_color = RB_BLACK; - if (other->rb_left) - other->rb_left->rb_color = RB_BLACK; - __rb_rotate_right(parent, root); - node = root->rb_node; - break; - } - } - } - if (node) - node->rb_color = RB_BLACK; -} - -void rb_erase(rb_node_t * node, rb_root_t * root) -{ - rb_node_t * child, * parent; - int color; - - if (!node->rb_left) - child = node->rb_right; - else if (!node->rb_right) - child = node->rb_left; - else - { - rb_node_t * old = node, * left; - - node = node->rb_right; - while ((left = node->rb_left)) - node = left; - child = node->rb_right; - parent = node->rb_parent; - color = node->rb_color; - - if (child) - child->rb_parent = parent; - if (parent) - { - if (parent->rb_left == node) - parent->rb_left = child; - else - parent->rb_right = child; - } - else - root->rb_node = child; - - if (node->rb_parent == old) - parent = node; - node->rb_parent = old->rb_parent; - node->rb_color = old->rb_color; - node->rb_right = old->rb_right; - node->rb_left = old->rb_left; - - if (old->rb_parent) - { - if (old->rb_parent->rb_left == old) - old->rb_parent->rb_left = node; - else - old->rb_parent->rb_right = node; - } else - root->rb_node = node; - - old->rb_left->rb_parent = node; - if (old->rb_right) - old->rb_right->rb_parent = node; - goto color; - } - - parent = node->rb_parent; - color = node->rb_color; - - if (child) - child->rb_parent = parent; - if (parent) - { - if (parent->rb_left == node) - parent->rb_left = child; - else - parent->rb_right = child; - } - else - root->rb_node = child; - - color: - if (color == RB_BLACK) - __rb_erase_color(child, parent, root); -} -EXPORT_SYMBOL(rb_erase); diff --git a/xen/drivers/Makefile b/xen/drivers/Makefile index 78635ed603..ac1f14ca6a 100644 --- a/xen/drivers/Makefile +++ b/xen/drivers/Makefile @@ -3,22 +3,8 @@ default: $(MAKE) -C char $(MAKE) -C acpi $(MAKE) -C pci - if [ "$(old_drivers)" == "y" ]; then \ - $(MAKE) -C net ; \ - $(MAKE) -C block ; \ - $(MAKE) -C cdrom ; \ - $(MAKE) -C ide ; \ - $(MAKE) -C scsi ; \ - $(MAKE) -C message/fusion ; \ - fi clean: $(MAKE) -C char clean $(MAKE) -C acpi clean $(MAKE) -C pci clean - $(MAKE) -C net clean - $(MAKE) -C block clean - $(MAKE) -C cdrom clean - $(MAKE) -C ide clean - $(MAKE) -C scsi clean - $(MAKE) -C message/fusion clean diff --git a/xen/drivers/acpi_ksyms.c b/xen/drivers/acpi_ksyms.c deleted file mode 100644 index 3933d4e8aa..0000000000 --- a/xen/drivers/acpi_ksyms.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * acpi_ksyms.c - ACPI Kernel Symbols ($Revision: 15 $) - * - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include - -#ifdef CONFIG_ACPI_INTERPRETER - -/* ACPI Debugger */ - -#ifdef ENABLE_DEBUGGER - -extern int acpi_in_debugger; - -EXPORT_SYMBOL(acpi_in_debugger); -EXPORT_SYMBOL(acpi_db_user_commands); - -#endif /* ENABLE_DEBUGGER */ - -/* ACPI Core Subsystem */ - -#ifdef ACPI_DEBUG_OUTPUT -EXPORT_SYMBOL(acpi_dbg_layer); -EXPORT_SYMBOL(acpi_dbg_level); -EXPORT_SYMBOL(acpi_ut_debug_print_raw); -EXPORT_SYMBOL(acpi_ut_debug_print); -EXPORT_SYMBOL(acpi_ut_status_exit); -EXPORT_SYMBOL(acpi_ut_value_exit); -EXPORT_SYMBOL(acpi_ut_exit); -EXPORT_SYMBOL(acpi_ut_trace); -#endif /*ACPI_DEBUG_OUTPUT*/ - -EXPORT_SYMBOL(acpi_get_handle); -EXPORT_SYMBOL(acpi_get_parent); -EXPORT_SYMBOL(acpi_get_type); -EXPORT_SYMBOL(acpi_get_name); -EXPORT_SYMBOL(acpi_get_object_info); -EXPORT_SYMBOL(acpi_get_next_object); -EXPORT_SYMBOL(acpi_evaluate_object); -EXPORT_SYMBOL(acpi_get_table); -EXPORT_SYMBOL(acpi_get_firmware_table); -EXPORT_SYMBOL(acpi_install_notify_handler); -EXPORT_SYMBOL(acpi_remove_notify_handler); -EXPORT_SYMBOL(acpi_install_gpe_handler); -EXPORT_SYMBOL(acpi_remove_gpe_handler); -EXPORT_SYMBOL(acpi_install_address_space_handler); -EXPORT_SYMBOL(acpi_remove_address_space_handler); -EXPORT_SYMBOL(acpi_install_fixed_event_handler); -EXPORT_SYMBOL(acpi_remove_fixed_event_handler); -EXPORT_SYMBOL(acpi_acquire_global_lock); -EXPORT_SYMBOL(acpi_release_global_lock); -EXPORT_SYMBOL(acpi_install_gpe_block); -EXPORT_SYMBOL(acpi_remove_gpe_block); -EXPORT_SYMBOL(acpi_get_current_resources); -EXPORT_SYMBOL(acpi_get_possible_resources); -EXPORT_SYMBOL(acpi_walk_resources); -EXPORT_SYMBOL(acpi_set_current_resources); -EXPORT_SYMBOL(acpi_enable_event); -EXPORT_SYMBOL(acpi_disable_event); -EXPORT_SYMBOL(acpi_clear_event); -EXPORT_SYMBOL(acpi_get_timer_duration); -EXPORT_SYMBOL(acpi_get_timer); -EXPORT_SYMBOL(acpi_get_sleep_type_data); -EXPORT_SYMBOL(acpi_get_register); -EXPORT_SYMBOL(acpi_set_register); -EXPORT_SYMBOL(acpi_enter_sleep_state); -EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios); -EXPORT_SYMBOL(acpi_get_system_info); -EXPORT_SYMBOL(acpi_get_devices); - -/* ACPI OS Services Layer (acpi_osl.c) */ - -EXPORT_SYMBOL(acpi_os_free); -EXPORT_SYMBOL(acpi_os_printf); -EXPORT_SYMBOL(acpi_os_sleep); -EXPORT_SYMBOL(acpi_os_stall); -EXPORT_SYMBOL(acpi_os_signal); -EXPORT_SYMBOL(acpi_os_queue_for_execution); -EXPORT_SYMBOL(acpi_os_signal_semaphore); -EXPORT_SYMBOL(acpi_os_create_semaphore); -EXPORT_SYMBOL(acpi_os_delete_semaphore); -EXPORT_SYMBOL(acpi_os_wait_semaphore); - -EXPORT_SYMBOL(acpi_os_read_pci_configuration); - -/* ACPI Utilities (acpi_utils.c) */ - -EXPORT_SYMBOL(acpi_extract_package); -EXPORT_SYMBOL(acpi_evaluate_integer); -EXPORT_SYMBOL(acpi_evaluate_reference); - -#endif /*CONFIG_ACPI_INTERPRETER*/ - - -/* ACPI Bus Driver (acpi_bus.c) */ - -#ifdef CONFIG_ACPI_BUS - -EXPORT_SYMBOL(acpi_fadt); -EXPORT_SYMBOL(acpi_walk_namespace); -EXPORT_SYMBOL(acpi_root_dir); -EXPORT_SYMBOL(acpi_bus_get_device); -EXPORT_SYMBOL(acpi_bus_get_status); -EXPORT_SYMBOL(acpi_bus_get_power); -EXPORT_SYMBOL(acpi_bus_set_power); -EXPORT_SYMBOL(acpi_bus_generate_event); -EXPORT_SYMBOL(acpi_bus_receive_event); -EXPORT_SYMBOL(acpi_bus_register_driver); -EXPORT_SYMBOL(acpi_bus_unregister_driver); -EXPORT_SYMBOL(acpi_bus_scan); -EXPORT_SYMBOL(acpi_init); - -#endif /*CONFIG_ACPI_BUS*/ - - -/* ACPI PCI Driver (pci_irq.c) */ - -#ifdef CONFIG_ACPI_PCI - -#include -extern int acpi_pci_irq_enable(struct pci_dev *dev); -EXPORT_SYMBOL(acpi_pci_irq_enable); -extern int acpi_pci_irq_lookup (int segment, int bus, int device, int pin); -EXPORT_SYMBOL(acpi_pci_irq_lookup); -EXPORT_SYMBOL(acpi_pci_register_driver); -EXPORT_SYMBOL(acpi_pci_unregister_driver); -#endif /*CONFIG_ACPI_PCI */ - -#ifdef CONFIG_ACPI_EC -/* ACPI EC driver (ec.c) */ - -EXPORT_SYMBOL(ec_read); -EXPORT_SYMBOL(ec_write); -#endif - diff --git a/xen/drivers/block/Makefile b/xen/drivers/block/Makefile deleted file mode 100644 index 96eb9e1f5d..0000000000 --- a/xen/drivers/block/Makefile +++ /dev/null @@ -1,16 +0,0 @@ - -include $(BASEDIR)/Rules.mk - - -# SMH: need to ensure cciss init function called /after/ generic blkdev -# stuff in ll_rw_blk etc. Linux barking link-order invocation of init -# functions means we need to explicitly order things here. -OBJS := blkpg.o elevator.o ll_rw_blk.o xen_vbd.o genhd.o xen_block.o -OBJS += cciss.o cciss_scsi.o - - -default: $(OBJS) - $(LD) -r -o driver.o $(OBJS) - -clean: - rm -f *.o *~ core diff --git a/xen/drivers/block/blkpg.c b/xen/drivers/block/blkpg.c deleted file mode 100644 index 451503e081..0000000000 --- a/xen/drivers/block/blkpg.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Partition table and disk geometry handling - * - * This obsoletes the partition-handling code in genhd.c: - * Userspace can look at a disk in arbitrary format and tell - * the kernel what partitions there are on the disk, and how - * these should be numbered. - * It also allows one to repartition a disk that is being used. - * - * A single ioctl with lots of subfunctions: - * - * Device number stuff: - * get_whole_disk() (given the device number of a partition, find - * the device number of the encompassing disk) - * get_all_partitions() (given the device number of a disk, return the - * device numbers of all its known partitions) - * - * Partition stuff: - * add_partition() - * delete_partition() - * test_partition_in_use() (also for test_disk_in_use) - * - * Geometry stuff: - * get_geometry() - * set_geometry() - * get_bios_drivedata() - * - * For today, only the partition stuff - aeb, 990515 - */ - -#include -#include -#include -/*#include */ /* for BLKRASET, ... */ -#include /* for capable() */ -#include /* for set_device_ro() */ -#include -#include -/*#include */ /* for is_swap_partition() */ -#include /* for EXPORT_SYMBOL */ - -#include - -#define is_mounted(_dev) (0) -#define is_swap_partition(_dev) (0) - -#define fsync_dev(_dev) (panic("fsync_dev???")) -#define invalidate_buffers(_dev) (panic("invalidate_buffers???")) - -/* - * What is the data describing a partition? - * - * 1. a device number (kdev_t) - * 2. a starting sector and number of sectors (hd_struct) - * given in the part[] array of the gendisk structure for the drive. - * - * The number of sectors is replicated in the sizes[] array of - * the gendisk structure for the major, which again is copied to - * the blk_size[][] array. - * (However, hd_struct has the number of 512-byte sectors, - * g->sizes[] and blk_size[][] have the number of 1024-byte blocks.) - * Note that several drives may have the same major. - */ - -/* - * Add a partition. - * - * returns: EINVAL: bad parameters - * ENXIO: cannot find drive - * EBUSY: proposed partition overlaps an existing one - * or has the same number as an existing one - * 0: all OK. - */ -int add_partition(kdev_t dev, struct blkpg_partition *p) { - struct gendisk *g; - long long ppstart, pplength; - long pstart, plength; - int i, drive, first_minor, end_minor, minor; - - /* convert bytes to sectors, check for fit in a hd_struct */ - ppstart = (p->start >> 9); - pplength = (p->length >> 9); - pstart = ppstart; - plength = pplength; - if (pstart != ppstart || plength != pplength - || pstart < 0 || plength < 0) - return -EINVAL; - - /* find the drive major */ - g = get_gendisk(dev); - if (!g) - return -ENXIO; - - /* existing drive? */ - drive = (MINOR(dev) >> g->minor_shift); - first_minor = (drive << g->minor_shift); - end_minor = first_minor + g->max_p; - if (drive >= g->nr_real) - return -ENXIO; - - /* drive and partition number OK? */ - if (first_minor != MINOR(dev) || p->pno <= 0 || p->pno >= g->max_p) - return -EINVAL; - - /* partition number in use? */ - minor = first_minor + p->pno; - if (g->part[minor].nr_sects != 0) - return -EBUSY; - - /* overlap? */ - for (i=first_minor+1; ipart[i].start_sect || - pstart >= g->part[i].start_sect + g->part[i].nr_sects)) - return -EBUSY; - - /* all seems OK */ - g->part[minor].start_sect = pstart; - g->part[minor].nr_sects = plength; - if (g->sizes) - g->sizes[minor] = (plength >> (BLOCK_SIZE_BITS - 9)); -#ifdef DEVFS_MUST_DIE - devfs_register_partitions (g, first_minor, 0); -#endif - return 0; -} - -/* - * Delete a partition given by partition number - * - * returns: EINVAL: bad parameters - * ENXIO: cannot find partition - * EBUSY: partition is busy - * 0: all OK. - * - * Note that the dev argument refers to the entire disk, not the partition. - */ -int del_partition(kdev_t dev, struct blkpg_partition *p) { - struct gendisk *g; - kdev_t devp; - int drive, first_minor, minor; - - /* find the drive major */ - g = get_gendisk(dev); - if (!g) - return -ENXIO; - - /* drive and partition number OK? */ - drive = (MINOR(dev) >> g->minor_shift); - first_minor = (drive << g->minor_shift); - if (first_minor != MINOR(dev) || p->pno <= 0 || p->pno >= g->max_p) - return -EINVAL; - - /* existing drive and partition? */ - minor = first_minor + p->pno; - if (drive >= g->nr_real || g->part[minor].nr_sects == 0) - return -ENXIO; - - /* partition in use? Incomplete check for now. */ - devp = MKDEV(MAJOR(dev), minor); - if (is_mounted(devp) || is_swap_partition(devp)) - return -EBUSY; - - /* all seems OK */ - fsync_dev(devp); - invalidate_buffers(devp); - - g->part[minor].start_sect = 0; - g->part[minor].nr_sects = 0; - if (g->sizes) - g->sizes[minor] = 0; -#ifdef DEVFS_MUST_DIE - devfs_register_partitions (g, first_minor, 0); -#endif - - return 0; -} - -int blkpg_ioctl(kdev_t dev, struct blkpg_ioctl_arg *arg) -{ - struct blkpg_ioctl_arg a; - struct blkpg_partition p; - int len; - - if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg))) - return -EFAULT; - - switch (a.op) { - case BLKPG_ADD_PARTITION: - case BLKPG_DEL_PARTITION: - len = a.datalen; - if (len < sizeof(struct blkpg_partition)) - return -EINVAL; - if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition))) - return -EFAULT; - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (a.op == BLKPG_ADD_PARTITION) - return add_partition(dev, &p); - else - return del_partition(dev, &p); - default: - return -EINVAL; - } -} - -/* - * Common ioctl's for block devices - */ - -int blk_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg) -{ -#if 1 - printk("May want to check out blk_ioctl...\n"); - return -EINVAL; -#else - struct gendisk *g; - u64 ullval = 0; - int intval; - - if (!dev) - return -EINVAL; - - switch (cmd) { - case BLKROSET: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (get_user(intval, (int *)(arg))) - return -EFAULT; - set_device_ro(dev, intval); - return 0; - case BLKROGET: - intval = (is_read_only(dev) != 0); - return put_user(intval, (int *)(arg)); - - case BLKRASET: - if(!capable(CAP_SYS_ADMIN)) - return -EACCES; - if(arg > 0xff) - return -EINVAL; - read_ahead[MAJOR(dev)] = arg; - return 0; - case BLKRAGET: - if (!arg) - return -EINVAL; - return put_user(read_ahead[MAJOR(dev)], (long *) arg); - - case BLKFLSBUF: - if(!capable(CAP_SYS_ADMIN)) - return -EACCES; - fsync_dev(dev); - invalidate_buffers(dev); - return 0; - - case BLKSSZGET: - /* get block device sector size as needed e.g. by fdisk */ - intval = get_hardsect_size(dev); - return put_user(intval, (int *) arg); - - case BLKGETSIZE: - case BLKGETSIZE64: - g = get_gendisk(dev); - if (g) - ullval = g->part[MINOR(dev)].nr_sects; - - if (cmd == BLKGETSIZE) - return put_user((unsigned long)ullval, (unsigned long *)arg); - else - return put_user(ullval << 9, (u64 *)arg); -#if 0 - case BLKRRPART: /* Re-read partition tables */ - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - return reread_partitions(dev, 1); -#endif - - case BLKPG: - return blkpg_ioctl(dev, (struct blkpg_ioctl_arg *) arg); - - case BLKELVGET: - return blkelvget_ioctl(&blk_get_queue(dev)->elevator, - (blkelv_ioctl_arg_t *) arg); - case BLKELVSET: - return blkelvset_ioctl(&blk_get_queue(dev)->elevator, - (blkelv_ioctl_arg_t *) arg); - - case BLKBSZGET: - /* get the logical block size (cf. BLKSSZGET) */ - intval = BLOCK_SIZE; - if (blksize_size[MAJOR(dev)]) - intval = blksize_size[MAJOR(dev)][MINOR(dev)]; - return put_user (intval, (int *) arg); - - case BLKBSZSET: - /* set the logical block size */ - if (!capable (CAP_SYS_ADMIN)) - return -EACCES; - if (!dev || !arg) - return -EINVAL; - if (get_user (intval, (int *) arg)) - return -EFAULT; - if (intval > PAGE_SIZE || intval < 512 || - (intval & (intval - 1))) - return -EINVAL; - if (is_mounted (dev) || is_swap_partition (dev)) - return -EBUSY; - set_blocksize (dev, intval); - return 0; - - default: - return -EINVAL; - } -#endif -} - -EXPORT_SYMBOL(blk_ioctl); diff --git a/xen/drivers/block/cciss.c b/xen/drivers/block/cciss.c deleted file mode 100644 index dbd5541dcc..0000000000 --- a/xen/drivers/block/cciss.c +++ /dev/null @@ -1,3448 +0,0 @@ -/* - * Disk Array driver for HP SA 5xxx and 6xxx Controllers - * Copyright 2000, 2002 Hewlett-Packard Development Company, L.P. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Questions/Comments/Bugfixes to Cciss-discuss@lists.sourceforge.net - * - */ - -#include /* CONFIG_PROC_FS */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) -#define DRIVER_NAME "HP CISS Driver (v 2.4.50)" -#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,50) - -/* Embedded module documentation macros - see modules.h */ -MODULE_AUTHOR("Hewlett-Packard Company"); -MODULE_DESCRIPTION("Driver for HP SA5xxx SA6xxx Controllers version 2.4.50"); -MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400 6i"); -MODULE_LICENSE("GPL"); - -#include "cciss_cmd.h" -#include "cciss.h" - -/* define the PCI info for the cards we can control */ -const struct pci_device_id cciss_pci_device_id[] = { - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISS, - 0x0E11, 0x4070, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB, - 0x0E11, 0x4080, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB, - 0x0E11, 0x4082, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB, - 0x0E11, 0x4083, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, - 0x0E11, 0x409A, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, - 0x0E11, 0x409B, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, - 0x0E11, 0x409C, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, - 0x0E11, 0x409D, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, - 0x0E11, 0x4091, 0, 0, 0}, - {0,} -}; -MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); - -#define NR_PRODUCTS (sizeof(products)/sizeof(struct board_type)) - -/* board_id = Subsystem Device ID & Vendor ID - * product = Marketing Name for the board - * access = Address of the struct of function pointers - */ -static struct board_type products[] = { - { 0x40700E11, "Smart Array 5300", &SA5_access}, - { 0x40800E11, "Smart Array 5i", &SA5B_access}, - { 0x40820E11, "Smart Array 532", &SA5B_access}, - { 0x40830E11, "Smart Array 5312", &SA5B_access}, - { 0x409A0E11, "Smart Array 641", &SA5_access}, - { 0x409B0E11, "Smart Array 642", &SA5_access}, - { 0x409C0E11, "Smart Array 6400", &SA5_access}, - { 0x409D0E11, "Smart Array 6400 EM", &SA5_access}, - { 0x40910E11, "Smart Array 6i", &SA5_access}, -}; - -/* How long to wait (in millesconds) for board to go into simple mode */ -#define MAX_CONFIG_WAIT 30000 -#define MAX_IOCTL_CONFIG_WAIT 1000 - -/*define how many times we will try a command because of bus resets */ -#define MAX_CMD_RETRIES 3 - -#define READ_AHEAD 128 -#define NR_CMDS 128 /* #commands that can be outstanding */ -#define MAX_CTLR 32 - -/* No sense in giving up our preallocated major numbers */ -#if MAX_CTLR < 8 -#error"cciss.c: MAX_CTLR must be 8 or greater" -#endif - -/* Originally cciss driver only supports 8 major number */ -#define MAX_CTLR_ORIG COMPAQ_CISS_MAJOR7 - COMPAQ_CISS_MAJOR + 1 - -#define CCISS_DMA_MASK (~0UL) - -#ifdef CONFIG_CISS_MONITOR_THREAD -static int cciss_monitor(void *ctlr); -static int start_monitor_thread(ctlr_info_t *h, unsigned char *cmd, - unsigned long count, int (*cciss_monitor)(void *), int *rc); -static u32 heartbeat_timer = 0; -#else -#define cciss_monitor(x) -#define kill_monitor_thead(x) -#endif - -static ctlr_info_t *hba[MAX_CTLR]; -static int map_major_to_ctlr[MAX_BLKDEV] = {0}; /* gets ctlr num from maj num */ - -static void do_cciss_request(request_queue_t *q); -static int cciss_open(struct inode *inode, struct file *filep); -static int cciss_release(struct inode *inode, struct file *filep); -static int cciss_ioctl(struct inode *inode, struct file *filep, - unsigned int cmd, unsigned long arg); - -static int revalidate_logvol(kdev_t dev, int maxusage); -static int frevalidate_logvol(kdev_t dev); -#if 0 -static int deregister_disk(int ctlr, int logvol); -static int register_new_disk(int cltr, int opened_vol, __u64 requested_lun); -static int cciss_rescan_disk(int cltr, int logvol); -#endif - -static void cciss_getgeometry(int cntl_num); - -static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c); -static void start_io( ctlr_info_t *h); - - -#ifdef CONFIG_PROC_FS -static int cciss_proc_get_info(char *buffer, char **start, off_t offset, - int length, int *eof, void *data); -static void cciss_procinit(int i); - -XXX -#else -/*static int cciss_proc_get_info(char *buffer, char **start, off_t offset, - int length, int *eof, void *data) { return 0;} -*/ -static void cciss_procinit(int i) {} - -#endif /* CONFIG_PROC_FS */ - - -static struct block_device_operations cciss_fops = { - open: cciss_open, - release: cciss_release, - ioctl: cciss_ioctl, - revalidate: frevalidate_logvol, -}; - -#include "cciss_scsi.c" /* For SCSI tape support */ - -#define ENG_GIG 1048576000 -#define ENG_GIG_FACTOR (ENG_GIG/512) -#define RAID_UNKNOWN 6 -static const char *raid_label[] = {"0","4","1(0+1)","5","5+1","ADG", - "UNKNOWN"}; -/* - * Report information about this controller. - */ -#ifdef CONFIG_PROC_FS -static int cciss_proc_get_info(char *buffer, char **start, off_t offset, - int length, int *eof, void *data) -{ - off_t pos = 0; - off_t len = 0; - int size, i, ctlr; - ctlr_info_t *h = (ctlr_info_t*)data; - drive_info_struct *drv; - unsigned long flags; - unsigned int vol_sz, vol_sz_frac; - - spin_lock_irqsave(&io_request_lock, flags); - if (h->busy_configuring) { - spin_unlock_irqrestore(&io_request_lock, flags); - return -EBUSY; - } - h->busy_configuring = 1; - spin_unlock_irqrestore(&io_request_lock, flags); - - ctlr = h->ctlr; - size = sprintf(buffer, "%s: HP %s Controller\n" - "Board ID: 0x%08lx\n" - "Firmware Version: %c%c%c%c\n" - "IRQ: %d\n" - "Logical drives: %d\n" - "Current Q depth: %d\n" - "Current # commands on controller: %d\n" - "Max Q depth since init: %d\n" - "Max # commands on controller since init: %d\n" - "Max SG entries since init: %d\n" - MONITOR_PERIOD_PATTERN - MONITOR_DEADLINE_PATTERN - MONITOR_STATUS_PATTERN - "\n", - h->devname, - h->product_name, - (unsigned long)h->board_id, - h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], h->firm_ver[3], - (unsigned int)h->intr, - h->num_luns, - h->Qdepth, h->commands_outstanding, - h->maxQsinceinit, h->max_outstanding, h->maxSG, - MONITOR_PERIOD_VALUE(h), - MONITOR_DEADLINE_VALUE(h), - CTLR_STATUS(h)); - - pos += size; len += size; - cciss_proc_tape_report(ctlr, buffer, &pos, &len); - for(i=0; i<=h->highest_lun; i++) { - drv = &h->drv[i]; - if (drv->nr_blocks == 0) - continue; - vol_sz = drv->nr_blocks/ENG_GIG_FACTOR; - vol_sz_frac = (drv->nr_blocks%ENG_GIG_FACTOR)*100/ENG_GIG_FACTOR; - - if (drv->raid_level > 5) - drv->raid_level = RAID_UNKNOWN; - size = sprintf(buffer+len, "cciss/c%dd%d:" - "\t%4d.%02dGB\tRAID %s\n", - ctlr, i, vol_sz,vol_sz_frac, - raid_label[drv->raid_level]); - pos += size, len += size; - } - - *eof = 1; - *start = buffer+offset; - len -= offset; - if (len>length) - len = length; - h->busy_configuring = 0; - return len; -} - -static int -cciss_proc_write(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - unsigned char cmd[80]; - int len; - ctlr_info_t *h = (ctlr_info_t *) data; - int rc; - - if (count > sizeof(cmd)-1) - return -EINVAL; - if (copy_from_user(cmd, buffer, count)) - return -EFAULT; - cmd[count] = '\0'; - len = strlen(cmd); - if (cmd[len-1] == '\n') - cmd[--len] = '\0'; - -# ifdef CONFIG_CISS_SCSI_TAPE - if (strcmp("engage scsi", cmd)==0) { - rc = cciss_engage_scsi(h->ctlr); - if (rc != 0) - return -rc; - return count; - } - /* might be nice to have "disengage" too, but it's not - safely possible. (only 1 module use count, lock issues.) */ -# endif - - if (START_MONITOR_THREAD(h, cmd, count, cciss_monitor, &rc) == 0) - return rc; - - return -EINVAL; -} - -/* - * Get us a file in /proc/cciss that says something about each controller. - * Create /proc/cciss if it doesn't exist yet. - */ -static void __init cciss_procinit(int i) -{ - struct proc_dir_entry *pde; - - if (proc_cciss == NULL) { - proc_cciss = proc_mkdir("cciss", proc_root_driver); - if (!proc_cciss) { - printk("cciss: proc_mkdir failed\n"); - return; - } - } - - pde = create_proc_read_entry(hba[i]->devname, - S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, - proc_cciss, cciss_proc_get_info, hba[i]); - pde->write_proc = cciss_proc_write; -} -#endif /* CONFIG_PROC_FS */ - -/* - * For operations that cannot sleep, a command block is allocated at init, - * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track - * which ones are free or in use. For operations that can wait for kmalloc - * to possible sleep, this routine can be called with get_from_pool set to 0. - * cmd_free() MUST be called with a got_from_pool set to 0 if cmd_alloc was. - */ -static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool) -{ - CommandList_struct *c; - int i; - u64bit temp64; - dma_addr_t cmd_dma_handle, err_dma_handle; - - if (!get_from_pool) { - c = (CommandList_struct *) pci_alloc_consistent( - h->pdev, sizeof(CommandList_struct), &cmd_dma_handle); - if (c==NULL) - return NULL; - memset(c, 0, sizeof(CommandList_struct)); - - c->err_info = (ErrorInfo_struct *)pci_alloc_consistent( - h->pdev, sizeof(ErrorInfo_struct), - &err_dma_handle); - - if (c->err_info == NULL) - { - pci_free_consistent(h->pdev, - sizeof(CommandList_struct), c, cmd_dma_handle); - return NULL; - } - memset(c->err_info, 0, sizeof(ErrorInfo_struct)); - } else /* get it out of the controllers pool */ - { - do { - i = find_first_zero_bit(h->cmd_pool_bits, NR_CMDS); - if (i == NR_CMDS) - return NULL; - } while(test_and_set_bit(i%32, h->cmd_pool_bits+(i/32)) != 0); -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss: using command buffer %d\n", i); -#endif - c = h->cmd_pool + i; - memset(c, 0, sizeof(CommandList_struct)); - cmd_dma_handle = h->cmd_pool_dhandle - + i*sizeof(CommandList_struct); - c->err_info = h->errinfo_pool + i; - memset(c->err_info, 0, sizeof(ErrorInfo_struct)); - err_dma_handle = h->errinfo_pool_dhandle - + i*sizeof(ErrorInfo_struct); - h->nr_allocs++; - } - - c->busaddr = (__u32) cmd_dma_handle; - temp64.val = (__u64) err_dma_handle; - c->ErrDesc.Addr.lower = temp64.val32.lower; - c->ErrDesc.Addr.upper = temp64.val32.upper; - c->ErrDesc.Len = sizeof(ErrorInfo_struct); - - c->ctlr = h->ctlr; - return c; - - -} - -/* - * Frees a command block that was previously allocated with cmd_alloc(). - */ -static void cmd_free(ctlr_info_t *h, CommandList_struct *c, int got_from_pool) -{ - int i; - u64bit temp64; - - if (!got_from_pool) { - temp64.val32.lower = c->ErrDesc.Addr.lower; - temp64.val32.upper = c->ErrDesc.Addr.upper; - pci_free_consistent(h->pdev, sizeof(ErrorInfo_struct), - c->err_info, (dma_addr_t) temp64.val); - pci_free_consistent(h->pdev, sizeof(CommandList_struct), - c, (dma_addr_t) c->busaddr); - } else - { - i = c - h->cmd_pool; - clear_bit(i%32, h->cmd_pool_bits+(i/32)); - h->nr_frees++; - } -} - -/* - * fills in the disk information. - */ -static void cciss_geninit( int ctlr) -{ - drive_info_struct *drv; - int i,j; - - /* Loop through each real device */ - hba[ctlr]->gendisk.nr_real = 0; - for(i=0; i< NWD; i++) { - drv = &(hba[ctlr]->drv[i]); - if (!(drv->nr_blocks)) - continue; - hba[ctlr]->hd[i << NWD_SHIFT].nr_sects = - hba[ctlr]->sizes[i << NWD_SHIFT] = drv->nr_blocks; - - /* for each partition */ - for(j=0; jblocksizes[(i<hardsizes[ (i<block_size; - } - } - hba[ctlr]->gendisk.nr_real = hba[ctlr]->highest_lun+1; -} - - -void cciss_probe_devices(xen_disk_info_t *xdi) -{ - int i, ctlr; - drive_info_struct *drv; - xen_disk_t *xd = &xdi->disks[xdi->count]; - - - for(ctlr = 0; ctlr < MAX_CTLR; ctlr++) { - - if(hba[ctlr] != NULL) { - - /* Loop through each real device */ - for(i=0; i < NWD; i++) { - - drv = &(hba[ctlr]->drv[i]); - - if (!(drv->nr_blocks)) - continue; - - if ( xdi->count == xdi->max ) - BUG(); - - - hba[ctlr]->hd[i << NWD_SHIFT].nr_sects = - hba[ctlr]->sizes[i << NWD_SHIFT] = drv->nr_blocks; - - /* We export 'raw' linux device numbers to domain 0. */ - xd->device = MKDEV(hba[ctlr]->major, i << 4); - xd->info = XD_TYPE_DISK; /* XXX should check properly */ - xd->capacity = drv->nr_blocks; /* number of 512 byte sectors */ - xd->domain = 0; - - xdi->count++; - xd++; - - } - - } - } - - return; -} - -/* - * Open. Make sure the device is really there. - */ -static int cciss_open(struct inode *inode, struct file *filep) -{ - int ctlr = map_major_to_ctlr[MAJOR(inode->i_rdev)]; - int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT; - -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss_open %x (%x:%x)\n", inode->i_rdev, ctlr, dsk); -#endif /* CCISS_DEBUG */ - - if (ctlr > MAX_CTLR || hba[ctlr] == NULL || !CTLR_IS_ALIVE(hba[ctlr])) - return -ENXIO; - /* - * Root is allowed to open raw volume zero even if its not configured - * so array config can still work. Root is also allowed to open any - * volume that has a LUN ID, so it can issue IOCTL to reread the - * disk information. I don't think I really like this. - * but I'm already using way to many device nodes to claim another one - * for "raw controller". - */ - if (hba[ctlr]->sizes[MINOR(inode->i_rdev)] == 0) { /* not online? */ - if (MINOR(inode->i_rdev) != 0) { /* not node 0? */ - /* if not node 0 make sure it is a partition = 0 */ - if (MINOR(inode->i_rdev) & 0x0f) { - return -ENXIO; - /* if it is, make sure we have a LUN ID */ - } else if (hba[ctlr]->drv[MINOR(inode->i_rdev) - >> NWD_SHIFT].LunID == 0) { - return -ENXIO; - } - } - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - } - - hba[ctlr]->drv[dsk].usage_count++; - hba[ctlr]->usage_count++; - return 0; -} -/* - * Close. Sync first. - */ -static int cciss_release(struct inode *inode, struct file *filep) -{ - int ctlr = map_major_to_ctlr[MAJOR(inode->i_rdev)]; - int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT; - -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss_release %x (%x:%x)\n", inode->i_rdev, ctlr, dsk); -#endif /* CCISS_DEBUG */ - - /* fsync_dev(inode->i_rdev); */ - - hba[ctlr]->drv[dsk].usage_count--; - hba[ctlr]->usage_count--; - return 0; -} - -/* - * ioctl - */ -static int cciss_ioctl(struct inode *inode, struct file *filep, - unsigned int cmd, unsigned long arg) -{ -#if 0 - //int ctlr = map_major_to_ctlr[MAJOR(inode->i_rdev)]; - - //int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT; -#endif - -printk(KERN_ALERT "cciss_ioctl: Called BUT NOT SUPPORTED cmd=%x %lx\n", cmd, arg); - -return -EBADRQC; - -#if 0 - -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss_ioctl: Called with cmd=%x %lx\n", cmd, arg); -#endif /* CCISS_DEBUG */ - - switch(cmd) { - case HDIO_GETGEO: - { - struct hd_geometry driver_geo; - if (hba[ctlr]->drv[dsk].cylinders) { - driver_geo.heads = hba[ctlr]->drv[dsk].heads; - driver_geo.sectors = hba[ctlr]->drv[dsk].sectors; - driver_geo.cylinders = hba[ctlr]->drv[dsk].cylinders; - } else { - driver_geo.heads = 0xff; - driver_geo.sectors = 0x3f; - driver_geo.cylinders = - hba[ctlr]->drv[dsk].nr_blocks / (0xff*0x3f); - } - driver_geo.start= - hba[ctlr]->hd[MINOR(inode->i_rdev)].start_sect; - if (copy_to_user((void *) arg, &driver_geo, - sizeof( struct hd_geometry))) - return -EFAULT; - return 0; - } - case HDIO_GETGEO_BIG: - { - struct hd_big_geometry driver_geo; - if (hba[ctlr]->drv[dsk].cylinders) { - driver_geo.heads = hba[ctlr]->drv[dsk].heads; - driver_geo.sectors = hba[ctlr]->drv[dsk].sectors; - driver_geo.cylinders = hba[ctlr]->drv[dsk].cylinders; - } else { - driver_geo.heads = 0xff; - driver_geo.sectors = 0x3f; - driver_geo.cylinders = - hba[ctlr]->drv[dsk].nr_blocks / (0xff*0x3f); - } - driver_geo.start= - hba[ctlr]->hd[MINOR(inode->i_rdev)].start_sect; - if (copy_to_user((void *) arg, &driver_geo, - sizeof( struct hd_big_geometry))) - return -EFAULT; - return 0; - } - case BLKRRPART: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - return revalidate_logvol(inode->i_rdev, 1); - case BLKGETSIZE: - case BLKGETSIZE64: - case BLKFLSBUF: - case BLKBSZSET: - case BLKBSZGET: - case BLKROSET: - case BLKROGET: - case BLKRASET: - case BLKRAGET: - case BLKPG: - case BLKELVGET: - case BLKELVSET: - return blk_ioctl(inode->i_rdev, cmd, arg); - case CCISS_GETPCIINFO: - { - cciss_pci_info_struct pciinfo; - - if (!arg) - return -EINVAL; - pciinfo.bus = hba[ctlr]->pdev->bus->number; - pciinfo.dev_fn = hba[ctlr]->pdev->devfn; - pciinfo.board_id = hba[ctlr]->board_id; - if (copy_to_user((void *) arg, &pciinfo, sizeof( cciss_pci_info_struct ))) - return -EFAULT; - return 0; - } - case CCISS_GETINTINFO: - { - cciss_coalint_struct intinfo; - ctlr_info_t *c = hba[ctlr]; - - if (!arg) - return -EINVAL; - intinfo.delay = readl(&c->cfgtable->HostWrite.CoalIntDelay); - intinfo.count = readl(&c->cfgtable->HostWrite.CoalIntCount); - if (copy_to_user((void *) arg, &intinfo, sizeof( cciss_coalint_struct ))) - return -EFAULT; - return 0; - } - case CCISS_SETINTINFO: - { - cciss_coalint_struct intinfo; - ctlr_info_t *c = hba[ctlr]; - unsigned long flags; - int i; - - if (!arg) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (copy_from_user(&intinfo, (void *) arg, sizeof( cciss_coalint_struct))) - return -EFAULT; - if ( (intinfo.delay == 0 ) && (intinfo.count == 0)) { - return -EINVAL; - } - - spin_lock_irqsave(&io_request_lock, flags); - /* Can only safely update if no commands outstanding */ - if (c->commands_outstanding > 0 ) { - spin_unlock_irqrestore(&io_request_lock, flags); - return -EINVAL; - } - /* Update the field, and then ring the doorbell */ - writel( intinfo.delay, - &(c->cfgtable->HostWrite.CoalIntDelay)); - writel( intinfo.count, - &(c->cfgtable->HostWrite.CoalIntCount)); - writel( CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL); - - for(i=0;ivaddr + SA5_DOORBELL) - & CFGTBL_ChangeReq)) - break; - /* delay and try again */ - udelay(1000); - } - spin_unlock_irqrestore(&io_request_lock, flags); - if (i >= MAX_IOCTL_CONFIG_WAIT) - /* there is an unlikely case where this can happen, - * involving hot replacing a failed 144 GB drive in a - * RAID 5 set just as we attempt this ioctl. */ - return -EAGAIN; - return 0; - } - case CCISS_GETNODENAME: - { - NodeName_type NodeName; - ctlr_info_t *c = hba[ctlr]; - int i; - - if (!arg) - return -EINVAL; - for(i=0;i<16;i++) - NodeName[i] = readb(&c->cfgtable->ServerName[i]); - if (copy_to_user((void *) arg, NodeName, sizeof( NodeName_type))) - return -EFAULT; - return 0; - } - case CCISS_SETNODENAME: - { - NodeName_type NodeName; - ctlr_info_t *c = hba[ctlr]; - unsigned long flags; - int i; - - if (!arg) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - if (copy_from_user(NodeName, (void *) arg, sizeof( NodeName_type))) - return -EFAULT; - - spin_lock_irqsave(&io_request_lock, flags); - - /* Update the field, and then ring the doorbell */ - for(i=0;i<16;i++) - writeb( NodeName[i], &c->cfgtable->ServerName[i]); - - writel( CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL); - - for(i=0;ivaddr + SA5_DOORBELL) - & CFGTBL_ChangeReq)) - break; - /* delay and try again */ - udelay(1000); - } - spin_unlock_irqrestore(&io_request_lock, flags); - if (i >= MAX_IOCTL_CONFIG_WAIT) - /* there is an unlikely case where this can happen, - * involving hot replacing a failed 144 GB drive in a - * RAID 5 set just as we attempt this ioctl. */ - return -EAGAIN; - return 0; - } - - case CCISS_GETHEARTBEAT: - { - Heartbeat_type heartbeat; - ctlr_info_t *c = hba[ctlr]; - - if (!arg) - return -EINVAL; - heartbeat = readl(&c->cfgtable->HeartBeat); - if (copy_to_user((void *) arg, &heartbeat, sizeof( Heartbeat_type))) - return -EFAULT; - return 0; - } - case CCISS_GETBUSTYPES: - { - BusTypes_type BusTypes; - ctlr_info_t *c = hba[ctlr]; - - if (!arg) - return -EINVAL; - BusTypes = readl(&c->cfgtable->BusTypes); - if (copy_to_user((void *) arg, &BusTypes, sizeof( BusTypes_type) )) - return -EFAULT; - return 0; - } - case CCISS_GETFIRMVER: - { - FirmwareVer_type firmware; - - if (!arg) - return -EINVAL; - memcpy(firmware, hba[ctlr]->firm_ver, 4); - - if (copy_to_user((void *) arg, firmware, sizeof( FirmwareVer_type))) - return -EFAULT; - return 0; - } - case CCISS_GETDRIVVER: - { - DriverVer_type DriverVer = DRIVER_VERSION; - - if (!arg) - return -EINVAL; - - if (copy_to_user((void *) arg, &DriverVer, sizeof( DriverVer_type) )) - return -EFAULT; - return 0; - } - case CCISS_RESCANDISK: - { - return cciss_rescan_disk(ctlr, dsk); - } - case CCISS_DEREGDISK: - return deregister_disk(ctlr,dsk); - - case CCISS_REGNEWD: - return register_new_disk(ctlr, dsk, 0); - case CCISS_REGNEWDISK: - { - __u64 new_logvol; - - if (!arg) - return -EINVAL; - if (copy_from_user(&new_logvol, (void *) arg, - sizeof( __u64))) - return -EFAULT; - return register_new_disk(ctlr, dsk, new_logvol); - } - case CCISS_GETLUNINFO: - { - LogvolInfo_struct luninfo; - int num_parts = 0; - int i, start; - - luninfo.LunID = hba[ctlr]->drv[dsk].LunID; - luninfo.num_opens = hba[ctlr]->drv[dsk].usage_count; - - /* count partitions 1 to 15 with sizes > 0 */ - start = (dsk << NWD_SHIFT); - for(i=1; i sizes[minor] != 0) - num_parts++; - } - luninfo.num_parts = num_parts; - if (copy_to_user((void *) arg, &luninfo, - sizeof( LogvolInfo_struct) )) - return -EFAULT; - return 0; - } -#if 0 - case CCISS_PASSTHRU: - { - IOCTL_Command_struct iocommand; - ctlr_info_t *h = hba[ctlr]; - CommandList_struct *c; - char *buff = NULL; - u64bit temp64; - unsigned long flags; - DECLARE_COMPLETION(wait); - - if (!arg) - return -EINVAL; - - if (!capable(CAP_SYS_RAWIO)) - return -EPERM; - - if (copy_from_user(&iocommand, (void *) arg, sizeof( IOCTL_Command_struct) )) - return -EFAULT; - if ((iocommand.buf_size < 1) && - (iocommand.Request.Type.Direction - != XFER_NONE)) { - return -EINVAL; - } - /* Check kmalloc limits */ - if (iocommand.buf_size > 128000) - return -EINVAL; - if (iocommand.buf_size > 0) { - buff = kmalloc(iocommand.buf_size, GFP_KERNEL); - if (buff == NULL) - return -ENOMEM; - } - if (iocommand.Request.Type.Direction == XFER_WRITE) { - /* Copy the data into the buffer we created */ - if (copy_from_user(buff, iocommand.buf, iocommand.buf_size)) - { - kfree(buff); - return -EFAULT; - } - } - if ((c = cmd_alloc(h , 0)) == NULL) { - kfree(buff); - return -ENOMEM; - } - /* Fill in the command type */ - c->cmd_type = CMD_IOCTL_PEND; - /* Fill in Command Header */ - c->Header.ReplyQueue = 0; /* unused in simple mode */ - if (iocommand.buf_size > 0) { /* buffer to fill */ - c->Header.SGList = 1; - c->Header.SGTotal= 1; - } else { /* no buffers to fill */ - c->Header.SGList = 0; - c->Header.SGTotal= 0; - } - c->Header.LUN = iocommand.LUN_info; - c->Header.Tag.lower = c->busaddr; /* use the kernel address */ - /* the cmd block for tag */ - - /* Fill in Request block */ - c->Request = iocommand.Request; - - /* Fill in the scatter gather information */ - if (iocommand.buf_size > 0 ) { - temp64.val = pci_map_single( h->pdev, buff, - iocommand.buf_size, - PCI_DMA_BIDIRECTIONAL); - c->SG[0].Addr.lower = temp64.val32.lower; - c->SG[0].Addr.upper = temp64.val32.upper; - c->SG[0].Len = iocommand.buf_size; - c->SG[0].Ext = 0; /* we are not chaining */ - } - c->waiting = &wait; - - /* Put the request on the tail of the request queue */ - spin_lock_irqsave(&io_request_lock, flags); - addQ(&h->reqQ, c); - h->Qdepth++; - start_io(h); - spin_unlock_irqrestore(&io_request_lock, flags); - - wait_for_completion(&wait); - - /* unlock the buffers from DMA */ - temp64.val32.lower = c->SG[0].Addr.lower; - temp64.val32.upper = c->SG[0].Addr.upper; - pci_unmap_single( h->pdev, (dma_addr_t) temp64.val, - iocommand.buf_size, PCI_DMA_BIDIRECTIONAL); - - /* Copy the error information out */ - iocommand.error_info = *(c->err_info); - if (copy_to_user((void *) arg, &iocommand, - sizeof( IOCTL_Command_struct) ) ) { - kfree(buff); - cmd_free(h, c, 0); - return( -EFAULT); - } - - if (iocommand.Request.Type.Direction == XFER_READ) { - /* Copy the data out of the buffer we created */ - if (copy_to_user(iocommand.buf, buff, - iocommand.buf_size)) { - kfree(buff); - cmd_free(h, c, 0); - return -EFAULT; - } - } - kfree(buff); - cmd_free(h, c, 0); - return 0; - } - case CCISS_BIG_PASSTHRU: - { - BIG_IOCTL_Command_struct iocommand; - ctlr_info_t *h = hba[ctlr]; - CommandList_struct *c; - char *buff[MAXSGENTRIES] = {NULL,}; - int buff_size[MAXSGENTRIES] = {0,}; - u64bit temp64; - unsigned long flags; - BYTE sg_used = 0; - int status = 0; - int i; - DECLARE_COMPLETION(wait); - - if (!arg) - return -EINVAL; - - if (!capable(CAP_SYS_RAWIO)) - return -EPERM; - - if (copy_from_user(&iocommand, (void *) arg, sizeof( BIG_IOCTL_Command_struct) )) - return -EFAULT; - if ((iocommand.buf_size < 1) && - (iocommand.Request.Type.Direction != XFER_NONE)) { - return -EINVAL; - } - /* Check kmalloc limits using all SGs */ - if (iocommand.malloc_size > MAX_KMALLOC_SIZE) - return -EINVAL; - if (iocommand.buf_size > iocommand.malloc_size * MAXSGENTRIES) - return -EINVAL; - if (iocommand.buf_size > 0) { - __u32 size_left_alloc = iocommand.buf_size; - BYTE *data_ptr = (BYTE *) iocommand.buf; - while (size_left_alloc > 0) { - buff_size[sg_used] = (size_left_alloc - > iocommand.malloc_size) - ? iocommand.malloc_size : size_left_alloc; - buff[sg_used] = kmalloc( buff_size[sg_used], - GFP_KERNEL); - if (buff[sg_used] == NULL) { - status = -ENOMEM; - goto cleanup1; - } - if (iocommand.Request.Type.Direction == - XFER_WRITE) - /* Copy the data into the buffer created */ - if (copy_from_user(buff[sg_used], data_ptr, - buff_size[sg_used])) { - status = -ENOMEM; - goto cleanup1; - } - size_left_alloc -= buff_size[sg_used]; - data_ptr += buff_size[sg_used]; - sg_used++; - } - - } - if ((c = cmd_alloc(h , 0)) == NULL) { - status = -ENOMEM; - goto cleanup1; - } - /* Fill in the command type */ - c->cmd_type = CMD_IOCTL_PEND; - /* Fill in Command Header */ - c->Header.ReplyQueue = 0; /* unused in simple mode */ - - if (iocommand.buf_size > 0) { /* buffer to fill */ - c->Header.SGList = sg_used; - c->Header.SGTotal= sg_used; - } else { /* no buffers to fill */ - c->Header.SGList = 0; - c->Header.SGTotal= 0; - } - c->Header.LUN = iocommand.LUN_info; - c->Header.Tag.lower = c->busaddr; /* use the kernel address */ - /* the cmd block for tag */ - - /* Fill in Request block */ - c->Request = iocommand.Request; - /* Fill in the scatter gather information */ - if (iocommand.buf_size > 0 ) { - int i; - for(i=0; i< sg_used; i++) { - temp64.val = pci_map_single( h->pdev, buff[i], - buff_size[i], - PCI_DMA_BIDIRECTIONAL); - - c->SG[i].Addr.lower = temp64.val32.lower; - c->SG[i].Addr.upper = temp64.val32.upper; - c->SG[i].Len = buff_size[i]; - c->SG[i].Ext = 0; /* we are not chaining */ - } - } - c->waiting = &wait; - /* Put the request on the tail of the request queue */ - spin_lock_irqsave(&io_request_lock, flags); - addQ(&h->reqQ, c); - h->Qdepth++; - start_io(h); - spin_unlock_irqrestore(&io_request_lock, flags); - wait_for_completion(&wait); - /* unlock the buffers from DMA */ - for(i=0; i< sg_used; i++) { - temp64.val32.lower = c->SG[i].Addr.lower; - temp64.val32.upper = c->SG[i].Addr.upper; - pci_unmap_single( h->pdev, (dma_addr_t) temp64.val, - buff_size[i], PCI_DMA_BIDIRECTIONAL); - } - /* Copy the error information out */ - iocommand.error_info = *(c->err_info); - if (copy_to_user((void *) arg, &iocommand, - sizeof( IOCTL_Command_struct) ) ) { - cmd_free(h, c, 0); - status = -EFAULT; - goto cleanup1; - } - if (iocommand.Request.Type.Direction == XFER_READ) { - /* Copy the data out of the buffer we created */ - BYTE *ptr = (BYTE *) iocommand.buf; - for(i=0; i< sg_used; i++) { - if (copy_to_user(ptr, buff[i], buff_size[i])) { - cmd_free(h, c, 0); - status = -EFAULT; - goto cleanup1; - - } - ptr += buff_size[i]; - } - } - cmd_free(h, c, 0); - status = 0; - - -cleanup1: - for(i=0; i< sg_used; i++) { - if (buff[i] != NULL) - kfree(buff[i]); - } - return status; - } -#endif //PASSTHROUGH - - default: - return -EBADRQC; - } - -#endif - -} - -/* Borrowed and adapted from sd.c */ -static int revalidate_logvol(kdev_t dev, int maxusage) -{ - int ctlr, target; - struct gendisk *gdev; - unsigned long flags; - int max_p; - int start; - int i; - - target = MINOR(dev) >> NWD_SHIFT; - ctlr = map_major_to_ctlr[MAJOR(dev)]; - gdev = &(hba[ctlr]->gendisk); - - spin_lock_irqsave(&io_request_lock, flags); - if (hba[ctlr]->drv[target].usage_count > maxusage) { - spin_unlock_irqrestore(&io_request_lock, flags); - printk(KERN_WARNING "cciss: Device busy for " - "revalidation (usage=%d)\n", - hba[ctlr]->drv[target].usage_count); - return -EBUSY; - } - hba[ctlr]->drv[target].usage_count++; - spin_unlock_irqrestore(&io_request_lock, flags); - - max_p = gdev->max_p; - start = target << gdev->minor_shift; - - for(i=max_p-1; i>=0; i--) { - int minor = start+i; - invalidate_device(MKDEV(hba[ctlr]->major, minor), 1); - gdev->part[minor].start_sect = 0; - gdev->part[minor].nr_sects = 0; - - /* reset the blocksize so we can read the partition table */ - blksize_size[hba[ctlr]->major][minor] = 1024; - } - /* setup partitions per disk */ - grok_partitions(gdev, target, MAX_PART, - hba[ctlr]->drv[target].nr_blocks); - hba[ctlr]->drv[target].usage_count--; - return 0; -} - -static int frevalidate_logvol(kdev_t dev) -{ -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss: frevalidate has been called\n"); -#endif /* CCISS_DEBUG */ - return revalidate_logvol(dev, 0); -} -#if 0 -static int deregister_disk(int ctlr, int logvol) -{ - unsigned long flags; - struct gendisk *gdev = &(hba[ctlr]->gendisk); - ctlr_info_t *h = hba[ctlr]; - int start, max_p, i; - - if (!capable(CAP_SYS_RAWIO)) - return -EPERM; - - spin_lock_irqsave(&io_request_lock, flags); - /* make sure logical volume is NOT is use */ - if (h->drv[logvol].usage_count > 1 || h->busy_configuring) { - spin_unlock_irqrestore(&io_request_lock, flags); - return -EBUSY; - } - h->busy_configuring = 1; - spin_unlock_irqrestore(&io_request_lock, flags); - - /* invalidate the devices and deregister the disk */ - max_p = gdev->max_p; - start = logvol << gdev->minor_shift; - for (i=max_p-1; i>=0; i--) { - int minor = start+i; - /* printk("invalidating( %d %d)\n", ctlr, minor); */ - invalidate_device(MKDEV(hba[ctlr]->major, minor), 1); - /* so open will now fail */ - h->sizes[minor] = 0; - /* so it will no longer appear in /proc/partitions */ - gdev->part[minor].start_sect = 0; - gdev->part[minor].nr_sects = 0; - } - /* check to see if it was the last disk */ - if (logvol == h->highest_lun) { - /* if so, find the new hightest lun */ - int i, newhighest =-1; - for(i=0; ihighest_lun; i++) { - /* if the disk has size > 0, it is available */ - if (h->sizes[i << gdev->minor_shift] != 0) - newhighest = i; - } - h->highest_lun = newhighest; - - } - --h->num_luns; - gdev->nr_real = h->highest_lun+1; - /* zero out the disk size info */ - h->drv[logvol].nr_blocks = 0; - h->drv[logvol].block_size = 0; - h->drv[logvol].cylinders = 0; - h->drv[logvol].LunID = 0; - h->busy_configuring = 0; - return 0; -} -static int sendcmd_withirq(__u8 cmd, - int ctlr, - void *buff, - size_t size, - unsigned int use_unit_num, - unsigned int log_unit, - __u8 page_code, - __u8 cmdtype) -{ - ctlr_info_t *h = hba[ctlr]; - CommandList_struct *c; - u64bit buff_dma_handle; - unsigned long flags; - int return_status = IO_OK; -#if 0 - DECLARE_COMPLETION(wait); -#else - /* XXX SMH: no waiting for us ... spin instead */ - int wait = 1; - int usecs = 0; -#endif - - if ((c = cmd_alloc(h , 0)) == NULL) - return -ENOMEM; - c->cmd_type = CMD_IOCTL_PEND; - /* Fill in Command Header */ - c->Header.ReplyQueue = 0; /* unused in simple mode */ - if (buff != NULL) { /* buffer to fill */ - c->Header.SGList = 1; - c->Header.SGTotal= 1; - } else { - /* no buffers to fill */ - c->Header.SGList = 0; - c->Header.SGTotal= 0; - } - c->Header.Tag.lower = c->busaddr; /* tag is phys addr of cmd */ - /* Fill in Request block */ - c->Request.CDB[0] = cmd; - c->Request.Type.Type = cmdtype; - if (cmdtype == TYPE_CMD) { - switch (cmd) { - case CISS_INQUIRY: - /* If the logical unit number is 0 then, this is going - to controller so It's a physical command - mode = 0 target = 0. - So we have nothing to write. - Otherwise - mode = 1 target = LUNID - */ - if (use_unit_num != 0) { - c->Header.LUN.LogDev.VolId = - hba[ctlr]->drv[log_unit].LunID; - c->Header.LUN.LogDev.Mode = 1; - } - if (page_code != 0) { - c->Request.CDB[1] = 0x01; - c->Request.CDB[2] = page_code; - } - c->Request.CDBLen = 6; - c->Request.Type.Attribute = ATTR_SIMPLE; - c->Request.Type.Direction = XFER_READ; /* Read */ - c->Request.Timeout = 0; /* Don't time out */ - c->Request.CDB[4] = size & 0xFF; - break; - case CISS_REPORT_LOG: - /* Talking to controller so It's a physical command - mode = 00 target = 0. - So we have nothing to write. - */ - c->Request.CDBLen = 12; - c->Request.Type.Attribute = ATTR_SIMPLE; - c->Request.Type.Direction = XFER_READ; /* Read */ - c->Request.Timeout = 0; /* Don't time out */ - c->Request.CDB[6] = (size >> 24) & 0xFF; /* MSB */ - c->Request.CDB[7] = (size >> 16) & 0xFF; - c->Request.CDB[8] = (size >> 8) & 0xFF; - c->Request.CDB[9] = size & 0xFF; - break; - case CCISS_READ_CAPACITY: - c->Header.LUN.LogDev.VolId= - hba[ctlr]->drv[log_unit].LunID; - c->Header.LUN.LogDev.Mode = 1; - c->Request.CDBLen = 10; - c->Request.Type.Attribute = ATTR_SIMPLE; - c->Request.Type.Direction = XFER_READ; /* Read */ - c->Request.Timeout = 0; /* Don't time out */ - break; - default: - printk(KERN_WARNING - "cciss: Unknown Command 0x%x sent attempted\n", cmd); - cmd_free(h, c, 1); - return IO_ERROR; - } - } else if (cmdtype == TYPE_MSG) { - switch (cmd) { - case 3: /* No-Op message */ - c->Request.CDBLen = 1; - c->Request.Type.Attribute = ATTR_SIMPLE; - c->Request.Type.Direction = XFER_WRITE; - c->Request.Timeout = 0; - c->Request.CDB[0] = cmd; - break; - default: - printk(KERN_WARNING - "cciss%d: unknown message type %d\n", - ctlr, cmd); - cmd_free(h, c, 1); - return IO_ERROR; - } - } else { - printk(KERN_WARNING - "cciss%d: unknown command type %d\n", ctlr, cmdtype); - cmd_free(h, c, 1); - return IO_ERROR; - } - - /* Fill in the scatter gather information */ - if (size > 0) { - buff_dma_handle.val = (__u64) pci_map_single( h->pdev, - buff, size, PCI_DMA_BIDIRECTIONAL); - c->SG[0].Addr.lower = buff_dma_handle.val32.lower; - c->SG[0].Addr.upper = buff_dma_handle.val32.upper; - c->SG[0].Len = size; - c->SG[0].Ext = 0; /* we are not chaining */ - } - -resend_cmd2: - -#if 0 - c->waiting = &wait; -#else - /* XXX SMH: we spin instead of waiting... */ - c->waiting = (void *)&wait; -#endif - - /* Put the request on the tail of the queue and send it */ - spin_lock_irqsave(&io_request_lock, flags); - addQ(&h->reqQ, c); - h->Qdepth++; - start_io(h); - spin_unlock_irqrestore(&io_request_lock, flags); - -#if 0 - wait_for_completion(&wait); -#else - /* XXX SMH: spin instead of waiting on wait queue */ - while(wait) { - do_softirq(); - udelay(500); - usecs += 500; - if(usecs > 1000000) { - printk("cciss: still waiting...!\n"); - usecs = 0; - } - } -#endif - - - if (c->err_info->CommandStatus != 0) { - /* an error has occurred */ - switch (c->err_info->CommandStatus) { - case CMD_TARGET_STATUS: - printk(KERN_WARNING "cciss: cmd %p has " - " completed with errors\n", c); - if (c->err_info->ScsiStatus) { - printk(KERN_WARNING "cciss: cmd %p " - "has SCSI Status = %x\n", c, - c->err_info->ScsiStatus); - } - break; - case CMD_DATA_UNDERRUN: - case CMD_DATA_OVERRUN: - /* expected for inquire and report lun commands */ - break; - case CMD_INVALID: - printk(KERN_WARNING "cciss: cmd %p is " - "reported invalid\n", c); - return_status = IO_ERROR; - break; - case CMD_PROTOCOL_ERR: - printk(KERN_WARNING "cciss: cmd %p has " - "protocol error \n", c); - return_status = IO_ERROR; - break; - case CMD_HARDWARE_ERR: - printk(KERN_WARNING "cciss: cmd %p had " - " hardware error\n", c); - return_status = IO_ERROR; - break; - case CMD_CONNECTION_LOST: - printk(KERN_WARNING "cciss: cmd %p had " - "connection lost\n", c); - return_status = IO_ERROR; - break; - case CMD_ABORTED: - printk(KERN_WARNING "cciss: cmd %p was " - "aborted\n", c); - return_status = IO_ERROR; - break; - case CMD_ABORT_FAILED: - printk(KERN_WARNING "cciss: cmd %p reports " - "abort failed\n", c); - return_status = IO_ERROR; - break; - case CMD_UNSOLICITED_ABORT: - printk(KERN_WARNING "cciss: cmd %p aborted " - "do to an unsolicited abort\n", c); - if (c->retry_count < MAX_CMD_RETRIES) - { - printk(KERN_WARNING "retrying cmd\n"); - c->retry_count++; - /* erase the old error */ - /* information */ - memset(c->err_info, 0, - sizeof(ErrorInfo_struct)); - return_status = IO_OK; -#if 0 - INIT_COMPLETION(wait); -#else - /* XXX SMH: spin instead of waiting. */ - wait = 0; -#endif - goto resend_cmd2; - - } - return_status = IO_ERROR; - break; - default: - printk(KERN_WARNING "cciss: cmd %p returned " - "unknown status %x\n", c, - c->err_info->CommandStatus); - return_status = IO_ERROR; - } - } - - /* unlock the buffers from DMA */ - pci_unmap_single( h->pdev, (dma_addr_t) buff_dma_handle.val, - size, PCI_DMA_BIDIRECTIONAL); - cmd_free(h, c, 0); - return return_status; -} -static int register_new_disk(int ctlr, int opened_vol, __u64 requested_lun) -{ - struct gendisk *gdev = &(hba[ctlr]->gendisk); - ctlr_info_t *h = hba[ctlr]; - int start, max_p, i; - int num_luns; - int logvol; - int new_lun_found = 0; - int new_lun_index = 0; - int free_index_found = 0; - int free_index = 0; - ReportLunData_struct *ld_buff; - ReadCapdata_struct *size_buff; - InquiryData_struct *inq_buff; - int return_code; - int listlength = 0; - __u32 lunid = 0; - unsigned int block_size; - unsigned int total_size; - unsigned long flags; - int req_lunid = (int) (requested_lun & (__u64) 0xffffffff); - - if (!capable(CAP_SYS_RAWIO)) - return -EPERM; - /* if we have no space in our disk array left to add anything */ - spin_lock_irqsave(&io_request_lock, flags); - if (h->num_luns >= CISS_MAX_LUN) { - spin_unlock_irqrestore(&io_request_lock, flags); - return -EINVAL; - } - if (h->busy_configuring) { - spin_unlock_irqrestore(&io_request_lock, flags); - return -EBUSY; - } - h->busy_configuring = 1; - spin_unlock_irqrestore(&io_request_lock, flags); - - ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL); - if (ld_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - h->busy_configuring = 0; - return -ENOMEM; - } - memset(ld_buff, 0, sizeof(ReportLunData_struct)); - size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL); - if (size_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - kfree(ld_buff); - h->busy_configuring = 0; - return -ENOMEM; - } - inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); - if (inq_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - kfree(ld_buff); - kfree(size_buff); - h->busy_configuring = 0; - return -ENOMEM; - } - - return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, - sizeof(ReportLunData_struct), 0, 0, 0, TYPE_CMD); - - if (return_code == IO_OK) { - listlength = be32_to_cpu(*((__u32 *) &ld_buff->LUNListLength[0])); - } else { - /* reading number of logical volumes failed */ - printk(KERN_WARNING "cciss: report logical volume" - " command failed\n"); - listlength = 0; - h->busy_configuring = 0; - return -1; - } - num_luns = listlength / 8; /* 8 bytes pre entry */ - if (num_luns > CISS_MAX_LUN) - num_luns = CISS_MAX_LUN; - -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "Length = %x %x %x %x = %d\n", ld_buff->LUNListLength[0], - ld_buff->LUNListLength[1], ld_buff->LUNListLength[2], - ld_buff->LUNListLength[3], num_luns); -#endif - for(i=0; i< num_luns; i++) { - int j; - int lunID_found = 0; - - lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24; - lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16; - lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8; - lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]); - - /* check to see if this is a new lun */ - for(j=0; j <= h->highest_lun; j++) { -#ifdef CCISS_DEBUG - printk("Checking %d %x against %x\n", j,h->drv[j].LunID, - lunid); -#endif /* CCISS_DEBUG */ - if (h->drv[j].LunID == lunid) { - lunID_found = 1; - break; - } - - } - if (lunID_found == 1) - continue; - else { /* new lun found */ - -#ifdef CCISS_DEBUG - printk("new lun found at %d\n", i); -#endif /* CCISS_DEBUG */ - if (req_lunid) /* we are looking for a specific lun */ - { - if (lunid != req_lunid) - { -#ifdef CCISS_DEBUG - printk("new lun %x is not %x\n", - lunid, req_lunid); -#endif /* CCISS_DEBUG */ - continue; - } - } - new_lun_index = i; - new_lun_found = 1; - break; - } - } - if (!new_lun_found) { - printk(KERN_DEBUG "cciss: New Logical Volume not found\n"); - h->busy_configuring = 0; - return -1; - } - /* Now find the free index */ - for(i=0; i drv[i].LunID == 0) { -#ifdef CCISS_DEBUG - printk("free index found at %d\n", i); -#endif /* CCISS_DEBUG */ - free_index_found = 1; - free_index = i; - break; - } - } - if (!free_index_found) { - printk(KERN_WARNING "cciss: unable to find free slot for disk\n"); - h->busy_configuring = 0; - return -1; - } - - logvol = free_index; - hba[ctlr]->drv[logvol].LunID = lunid; - /* there could be gaps in lun numbers, track hightest */ - if (hba[ctlr]->highest_lun < logvol) - hba[ctlr]->highest_lun = logvol; - - memset(size_buff, 0, sizeof(ReadCapdata_struct)); - return_code = sendcmd_withirq(CCISS_READ_CAPACITY, ctlr, - size_buff, sizeof(ReadCapdata_struct), 1, - logvol, 0, TYPE_CMD); - if (return_code == IO_OK) { - total_size = (0xff & - (unsigned int) size_buff->total_size[0]) << 24; - total_size |= (0xff & - (unsigned int) size_buff->total_size[1]) << 16; - total_size |= (0xff & - (unsigned int) size_buff->total_size[2]) << 8; - total_size |= (0xff & - (unsigned int) size_buff->total_size[3]); - total_size++; /* command returns highest block address */ - - block_size = (0xff & - (unsigned int) size_buff->block_size[0]) << 24; - block_size |= (0xff & - (unsigned int) size_buff->block_size[1]) << 16; - block_size |= (0xff & - (unsigned int) size_buff->block_size[2]) << 8; - block_size |= (0xff & - (unsigned int) size_buff->block_size[3]); - } else { - /* read capacity command failed */ - printk(KERN_WARNING "cciss: read capacity failed\n"); - total_size = 0; - block_size = BLOCK_SIZE; - } - printk(KERN_INFO " blocks= %d block_size= %d\n", - total_size, block_size); - /* Execute the command to read the disk geometry */ - memset(inq_buff, 0, sizeof(InquiryData_struct)); - return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buff, - sizeof(InquiryData_struct), 1, logvol ,0xC1, TYPE_CMD); - if (return_code == IO_OK) { - if (inq_buff->data_byte[8] == 0xFF) { - printk(KERN_WARNING - "cciss: reading geometry failed, " - "volume does not support reading geometry\n"); - - hba[ctlr]->drv[logvol].block_size = block_size; - hba[ctlr]->drv[logvol].nr_blocks = total_size; - hba[ctlr]->drv[logvol].heads = 255; - hba[ctlr]->drv[logvol].sectors = 32; /* secs/trk */ - hba[ctlr]->drv[logvol].cylinders = total_size / 255 /32; - hba[ctlr]->drv[logvol].raid_level = RAID_UNKNOWN; - } else { - hba[ctlr]->drv[logvol].block_size = block_size; - hba[ctlr]->drv[logvol].nr_blocks = total_size; - hba[ctlr]->drv[logvol].heads = inq_buff->data_byte[6]; - hba[ctlr]->drv[logvol].sectors = inq_buff->data_byte[7]; - hba[ctlr]->drv[logvol].cylinders = - (inq_buff->data_byte[4] & 0xff) << 8; - hba[ctlr]->drv[logvol].cylinders += - inq_buff->data_byte[5]; - hba[ctlr]->drv[logvol].raid_level = - inq_buff->data_byte[8]; - } - } else { - /* Get geometry failed */ - printk(KERN_WARNING "cciss: reading geometry failed, " - "continuing with default geometry\n"); - - hba[ctlr]->drv[logvol].block_size = block_size; - hba[ctlr]->drv[logvol].nr_blocks = total_size; - hba[ctlr]->drv[logvol].heads = 255; - hba[ctlr]->drv[logvol].sectors = 32; /* Sectors per track */ - hba[ctlr]->drv[logvol].cylinders = total_size / 255 / 32; - } - if (hba[ctlr]->drv[logvol].raid_level > 5) - hba[ctlr]->drv[logvol].raid_level = RAID_UNKNOWN; - - printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d RAID %s\n\n", - hba[ctlr]->drv[logvol].heads, - hba[ctlr]->drv[logvol].sectors, - hba[ctlr]->drv[logvol].cylinders, - raid_label[hba[ctlr]->drv[logvol].raid_level]); - - - /* special case for c?d0, which may be opened even when - it does not "exist". In that case, don't mess with usage count. - Also, /dev/c1d1 could be used to re-add c0d0 so we can't just - check whether logvol == 0, must check logvol != opened_vol */ - if (logvol != opened_vol) - hba[ctlr]->drv[logvol].usage_count = 0; - - max_p = gdev->max_p; - start = logvol<< gdev->minor_shift; - hba[ctlr]->hd[start].nr_sects = total_size; - hba[ctlr]->sizes[start] = total_size; - - for(i=max_p-1; i>=0; i--) { - int minor = start+i; - - invalidate_device(MKDEV(hba[ctlr]->major, minor), 1); - gdev->part[minor].start_sect = 0; - gdev->part[minor].nr_sects = 0; - - /* reset the blocksize so we can read the partition table */ - blksize_size[hba[ctlr]->major][minor] = block_size; - hba[ctlr]->hardsizes[minor] = block_size; - } - - - - ++hba[ctlr]->num_luns; - gdev->nr_real = hba[ctlr]->highest_lun + 1; - - - /* setup partitions per disk */ - grok_partitions(gdev, logvol, MAX_PART, - hba[ctlr]->drv[logvol].nr_blocks); - kfree(ld_buff); - kfree(size_buff); - kfree(inq_buff); - h->busy_configuring = 0; - return logvol; -} - -static int cciss_rescan_disk(int ctlr, int logvol) -{ - struct gendisk *gdev = &(hba[ctlr]->gendisk); - int start, max_p, i; - ReadCapdata_struct *size_buff; - InquiryData_struct *inq_buff; - int return_code; - unsigned int block_size; - unsigned int total_size; - - if (!capable(CAP_SYS_RAWIO)) - return -EPERM; - if (hba[ctlr]->sizes[logvol << NWD_SHIFT] != 0) { - /* disk is possible on line, return just a warning */ - return 1; - } - size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL); - if (size_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - return -1; - } - inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); - if (inq_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - kfree(size_buff); - return -1; - } - memset(size_buff, 0, sizeof(ReadCapdata_struct)); - return_code = sendcmd_withirq(CCISS_READ_CAPACITY, ctlr, size_buff, - sizeof( ReadCapdata_struct), 1, logvol, 0, - TYPE_CMD); - if (return_code == IO_OK) { - total_size = (0xff & - (unsigned int)(size_buff->total_size[0])) << 24; - total_size |= (0xff & - (unsigned int)(size_buff->total_size[1])) << 16; - total_size |= (0xff & - (unsigned int)(size_buff->total_size[2])) << 8; - total_size |= (0xff & (unsigned int) - (size_buff->total_size[3])); - total_size++; /* command returns highest block address */ - - block_size = (0xff & - (unsigned int)(size_buff->block_size[0])) << 24; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[1])) << 16; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[2])) << 8; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[3])); - } else { /* read capacity command failed */ - printk(KERN_WARNING "cciss: read capacity failed\n"); - total_size = block_size = 0; - } - printk(KERN_INFO " blocks= %d block_size= %d\n", - total_size, block_size); - /* Execute the command to read the disk geometry */ - memset(inq_buff, 0, sizeof(InquiryData_struct)); - return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buff, - sizeof(InquiryData_struct), 1, logvol ,0xC1, TYPE_CMD); - if (return_code == IO_OK) { - if (inq_buff->data_byte[8] == 0xFF) { - printk(KERN_WARNING "cciss: reading geometry failed, " - "volume does not support reading geometry\n"); - - hba[ctlr]->drv[logvol].nr_blocks = total_size; - hba[ctlr]->drv[logvol].heads = 255; - hba[ctlr]->drv[logvol].sectors = 32; /* Sectors/track */ - hba[ctlr]->drv[logvol].cylinders = total_size / 255 /32; - } else { - hba[ctlr]->drv[logvol].nr_blocks = total_size; - hba[ctlr]->drv[logvol].heads = inq_buff->data_byte[6]; - hba[ctlr]->drv[logvol].sectors = inq_buff->data_byte[7]; - hba[ctlr]->drv[logvol].cylinders = - (inq_buff->data_byte[4] & 0xff) << 8; - hba[ctlr]->drv[logvol].cylinders += - inq_buff->data_byte[5]; - } - } else { /* Get geometry failed */ - printk(KERN_WARNING "cciss: reading geometry failed, " - "continuing with default geometry\n"); - - hba[ctlr]->drv[logvol].nr_blocks = total_size; - hba[ctlr]->drv[logvol].heads = 255; - hba[ctlr]->drv[logvol].sectors = 32; /* Sectors / track */ - hba[ctlr]->drv[logvol].cylinders = total_size / 255 /32; - } - - printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d \n\n", - hba[ctlr]->drv[logvol].heads, - hba[ctlr]->drv[logvol].sectors, - hba[ctlr]->drv[logvol].cylinders); - max_p = gdev->max_p; - start = logvol<< gdev->minor_shift; - hba[ctlr]->hd[start].nr_sects = hba[ctlr]->sizes[start]= total_size; - - for (i=max_p-1; i>=0; i--) { - int minor = start+i; - invalidate_device(MKDEV(hba[ctlr]->major, minor), 1); - gdev->part[minor].start_sect = 0; - gdev->part[minor].nr_sects = 0; - - /* reset the blocksize so we can read the partition table */ - blksize_size[hba[ctlr]->major][minor] = block_size; - hba[ctlr]->hardsizes[minor] = block_size; - } - - /* setup partitions per disk */ - grok_partitions(gdev, logvol, MAX_PART, - hba[ctlr]->drv[logvol].nr_blocks ); - - kfree(size_buff); - kfree(inq_buff); - return 0; -} -#endif - -/* - * Wait polling for a command to complete. - * The memory mapped FIFO is polled for the completion. - * Used only at init time, interrupts disabled. - */ -static unsigned long pollcomplete(int ctlr) -{ - unsigned long done; - int i; - - /* Wait (up to 20 seconds) for a command to complete */ - - for (i = 20 * HZ; i > 0; i--) { - done = hba[ctlr]->access.command_completed(hba[ctlr]); - if (done == FIFO_EMPTY) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); - } else - return done; - } - /* Invalid address to tell caller we ran out of time */ - return 1; -} -/* - * Send a command to the controller, and wait for it to complete. - * Only used at init time. - */ -static int sendcmd( - __u8 cmd, - int ctlr, - void *buff, - size_t size, - unsigned int use_unit_num, /* 0: address the controller, - 1: address logical volume log_unit, - 2: periph device address is scsi3addr */ - unsigned int log_unit, - __u8 page_code, - unsigned char *scsi3addr) -{ - CommandList_struct *c; - int i; - unsigned long complete; - ctlr_info_t *info_p= hba[ctlr]; - u64bit buff_dma_handle; - int status = IO_OK; - - c = cmd_alloc(info_p, 1); - if (c == NULL) { - printk(KERN_WARNING "cciss: unable to get memory"); - return IO_ERROR; - } - /* Fill in Command Header */ - c->Header.ReplyQueue = 0; /* unused in simple mode */ - if (buff != NULL) { /* buffer to fill */ - c->Header.SGList = 1; - c->Header.SGTotal= 1; - } else { /* no buffers to fill */ - c->Header.SGList = 0; - c->Header.SGTotal= 0; - } - c->Header.Tag.lower = c->busaddr; /* use the kernel address */ - /* the cmd block for tag */ - /* Fill in Request block */ - switch (cmd) { - case CISS_INQUIRY: - /* If the logical unit number is 0 then, this is going - to controller so It's a physical command - mode = 0 target = 0. - So we have nothing to write. - otherwise, if use_unit_num == 1, - mode = 1(volume set addressing) target = LUNID - otherwise, if use_unit_num == 2, - mode = 0(periph dev addr) target = scsi3addr - */ - if (use_unit_num == 1) { - c->Header.LUN.LogDev.VolId= - hba[ctlr]->drv[log_unit].LunID; - c->Header.LUN.LogDev.Mode = 1; - } - else if (use_unit_num == 2) { - memcpy(c->Header.LUN.LunAddrBytes,scsi3addr,8); - c->Header.LUN.LogDev.Mode = 0; - /* phys dev addr */ - } - - /* are we trying to read a vital product page */ - if (page_code != 0) { - c->Request.CDB[1] = 0x01; - c->Request.CDB[2] = page_code; - } - c->Request.CDBLen = 6; - c->Request.Type.Type = TYPE_CMD; /* It is a command. */ - c->Request.Type.Attribute = ATTR_SIMPLE; - c->Request.Type.Direction = XFER_READ; /* Read */ - c->Request.Timeout = 0; /* Don't time out */ - c->Request.CDB[0] = CISS_INQUIRY; - c->Request.CDB[4] = size & 0xFF; - break; - case CISS_REPORT_LOG: - case CISS_REPORT_PHYS: - /* Talking to controller so It's a physical command - mode = 00 target = 0. - So we have nothing to write. - */ - c->Request.CDBLen = 12; - c->Request.Type.Type = TYPE_CMD; /* It is a command. */ - c->Request.Type.Attribute = ATTR_SIMPLE; - c->Request.Type.Direction = XFER_READ; /* Read */ - c->Request.Timeout = 0; /* Don't time out */ - c->Request.CDB[0] = cmd; - c->Request.CDB[6] = (size >> 24) & 0xFF; /* MSB */ - c->Request.CDB[7] = (size >> 16) & 0xFF; - c->Request.CDB[8] = (size >> 8) & 0xFF; - c->Request.CDB[9] = size & 0xFF; - break; - - case CCISS_READ_CAPACITY: - c->Header.LUN.LogDev.VolId= - hba[ctlr]->drv[log_unit].LunID; - c->Header.LUN.LogDev.Mode = 1; - c->Request.CDBLen = 10; - c->Request.Type.Type = TYPE_CMD; /* It is a command. */ - c->Request.Type.Attribute = ATTR_SIMPLE; - c->Request.Type.Direction = XFER_READ; /* Read */ - c->Request.Timeout = 0; /* Don't time out */ - c->Request.CDB[0] = CCISS_READ_CAPACITY; - break; - case CCISS_CACHE_FLUSH: - c->Request.CDBLen = 12; - c->Request.Type.Type = TYPE_CMD; /* It is a command. */ - c->Request.Type.Attribute = ATTR_SIMPLE; - c->Request.Type.Direction = XFER_WRITE; /* No data */ - c->Request.Timeout = 0; /* Don't time out */ - c->Request.CDB[0] = BMIC_WRITE; /* BMIC Passthru */ - c->Request.CDB[6] = BMIC_CACHE_FLUSH; - break; - default: - printk(KERN_WARNING - "cciss: Unknown Command 0x%x sent attempted\n", - cmd); - cmd_free(info_p, c, 1); - return IO_ERROR; - }; - /* Fill in the scatter gather information */ - if (size > 0) { - buff_dma_handle.val = (__u64) pci_map_single( info_p->pdev, - buff, size, PCI_DMA_BIDIRECTIONAL); - c->SG[0].Addr.lower = buff_dma_handle.val32.lower; - c->SG[0].Addr.upper = buff_dma_handle.val32.upper; - c->SG[0].Len = size; - c->SG[0].Ext = 0; /* we are not chaining */ - } -resend_cmd1: - /* - * Disable interrupt - */ -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss: turning intr off\n"); -#endif /* CCISS_DEBUG */ - info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF); - - /* Make sure there is room in the command FIFO */ - /* Actually it should be completely empty at this time. */ - for (i = 200000; i > 0; i--) { - /* if fifo isn't full go */ - if (!(info_p->access.fifo_full(info_p))) { - - break; - } - udelay(10); - printk(KERN_WARNING "cciss cciss%d: SendCmd FIFO full," - " waiting!\n", ctlr); - } - /* - * Send the cmd - */ - info_p->access.submit_command(info_p, c); - complete = pollcomplete(ctlr); - -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss: command completed\n"); -#endif /* CCISS_DEBUG */ - - if (complete != 1) { - if ( (complete & CISS_ERROR_BIT) - && (complete & ~CISS_ERROR_BIT) == c->busaddr) { - /* if data overrun or underun on Report command - ignore it - */ - if (((c->Request.CDB[0] == CISS_REPORT_LOG) || - (c->Request.CDB[0] == CISS_REPORT_PHYS) || - (c->Request.CDB[0] == CISS_INQUIRY)) && - ((c->err_info->CommandStatus == - CMD_DATA_OVERRUN) || - (c->err_info->CommandStatus == - CMD_DATA_UNDERRUN) - )) { - complete = c->busaddr; - } else { - if (c->err_info->CommandStatus == - CMD_UNSOLICITED_ABORT) { - printk(KERN_WARNING "cciss: " - "cmd %p aborted do " - "to an unsolicited abort \n", c); - if (c->retry_count < MAX_CMD_RETRIES) { - printk(KERN_WARNING - "retrying cmd\n"); - c->retry_count++; - /* erase the old error */ - /* information */ - memset(c->err_info, 0, - sizeof(ErrorInfo_struct)); - goto resend_cmd1; - } else { - printk(KERN_WARNING - "retried to many times\n"); - status = IO_ERROR; - goto cleanup1; - } - } - printk(KERN_WARNING "cciss cciss%d: sendcmd" - " Error %x \n", ctlr, - c->err_info->CommandStatus); - printk(KERN_WARNING "cciss cciss%d: sendcmd" - " offensive info\n" - " size %x\n num %x value %x\n", ctlr, - c->err_info->MoreErrInfo.Invalid_Cmd.offense_size, - c->err_info->MoreErrInfo.Invalid_Cmd.offense_num, - c->err_info->MoreErrInfo.Invalid_Cmd.offense_value); - status = IO_ERROR; - goto cleanup1; - } - } - if (complete != c->busaddr) { - printk( KERN_WARNING "cciss cciss%d: SendCmd " - "Invalid command list address returned! (%lx)\n", - ctlr, complete); - status = IO_ERROR; - goto cleanup1; - } - } else { - printk( KERN_WARNING - "cciss cciss%d: SendCmd Timeout out, " - "No command list address returned!\n", - ctlr); - status = IO_ERROR; - } - -cleanup1: - /* unlock the data buffer from DMA */ - pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val, - size, PCI_DMA_BIDIRECTIONAL); - cmd_free(info_p, c, 1); - return status; -} -/* - * Map (physical) PCI mem into (virtual) kernel space - */ -static ulong remap_pci_mem(ulong base, ulong size) -{ - ulong page_base = ((ulong) base) & PAGE_MASK; - ulong page_offs = ((ulong) base) - page_base; - ulong page_remapped = (ulong) ioremap(page_base, page_offs+size); - - return (ulong) (page_remapped ? (page_remapped + page_offs) : 0UL); -} - -/* - * Enqueuing and dequeuing functions for cmdlists. - */ -static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c) -{ - if (*Qptr == NULL) { - *Qptr = c; - c->next = c->prev = c; - } else { - c->prev = (*Qptr)->prev; - c->next = (*Qptr); - (*Qptr)->prev->next = c; - (*Qptr)->prev = c; - } -} - -static inline CommandList_struct *removeQ(CommandList_struct **Qptr, - CommandList_struct *c) -{ - if (c && c->next != c) { - if (*Qptr == c) *Qptr = c->next; - c->prev->next = c->next; - c->next->prev = c->prev; - } else { - *Qptr = NULL; - } - return c; -} - -/* - * Takes jobs of the Q and sends them to the hardware, then puts it on - * the Q to wait for completion. - */ -static void start_io( ctlr_info_t *h) -{ - CommandList_struct *c; - - while(( c = h->reqQ) != NULL ) { - /* can't do anything if fifo is full */ - if ((h->access.fifo_full(h))) { - printk(KERN_WARNING "cciss: fifo full \n"); - return; - } - /* Get the frist entry from the Request Q */ - removeQ(&(h->reqQ), c); - h->Qdepth--; - - /* Tell the controller execute command */ - h->access.submit_command(h, c); - - /* Put job onto the completed Q */ - addQ (&(h->cmpQ), c); - } -} - -static inline void complete_buffers( struct buffer_head *bh, int status) -{ - struct buffer_head *xbh; - - while(bh) { - xbh = bh->b_reqnext; - bh->b_reqnext = NULL; - blk_finished_io(bh->b_size >> 9); - bh->b_end_io(bh, status); - bh = xbh; - } -} -/* This code assumes io_request_lock is already held */ -/* Zeros out the error record and then resends the command back */ -/* to the controller */ -static inline void resend_cciss_cmd( ctlr_info_t *h, CommandList_struct *c) -{ - /* erase the old error information */ - memset(c->err_info, 0, sizeof(ErrorInfo_struct)); - - /* add it to software queue and then send it to the controller */ - addQ(&(h->reqQ),c); - h->Qdepth++; - if (h->Qdepth > h->maxQsinceinit) - h->maxQsinceinit = h->Qdepth; - - start_io(h); -} -/* checks the status of the job and calls complete buffers to mark all - * buffers for the completed job. - */ -static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd, - int timeout) -{ - int status = 1; - int retry_cmd = 0; - int i, ddir; - u64bit temp64; - - if (timeout) - status = 0; - - if (cmd->err_info->CommandStatus != 0) { - /* an error has occurred */ - switch (cmd->err_info->CommandStatus) { - unsigned char sense_key; - case CMD_TARGET_STATUS: - status = 0; - - if (cmd->err_info->ScsiStatus == 0x02) { - printk(KERN_WARNING "cciss: cmd %p " - "has CHECK CONDITION," - " sense key = 0x%x\n", cmd, - cmd->err_info->SenseInfo[2]); - /* check the sense key */ - sense_key = 0xf & - cmd->err_info->SenseInfo[2]; - /* recovered error */ - if ( sense_key == 0x1) - status = 1; - } else { - printk(KERN_WARNING "cciss: cmd %p " - "has SCSI Status 0x%x\n", - cmd, cmd->err_info->ScsiStatus); - } - break; - case CMD_DATA_UNDERRUN: - printk(KERN_WARNING "cciss: cmd %p has" - " completed with data underrun " - "reported\n", cmd); - break; - case CMD_DATA_OVERRUN: - printk(KERN_WARNING "cciss: cmd %p has" - " completed with data overrun " - "reported\n", cmd); - break; - case CMD_INVALID: - printk(KERN_WARNING "cciss: cmd %p is " - "reported invalid\n", cmd); - status = 0; - break; - case CMD_PROTOCOL_ERR: - printk(KERN_WARNING "cciss: cmd %p has " - "protocol error \n", cmd); - status = 0; - break; - case CMD_HARDWARE_ERR: - printk(KERN_WARNING "cciss: cmd %p had " - " hardware error\n", cmd); - status = 0; - break; - case CMD_CONNECTION_LOST: - printk(KERN_WARNING "cciss: cmd %p had " - "connection lost\n", cmd); - status=0; - break; - case CMD_ABORTED: - printk(KERN_WARNING "cciss: cmd %p was " - "aborted\n", cmd); - status=0; - break; - case CMD_ABORT_FAILED: - printk(KERN_WARNING "cciss: cmd %p reports " - "abort failed\n", cmd); - status=0; - break; - case CMD_UNSOLICITED_ABORT: - printk(KERN_WARNING "cciss: cmd %p aborted do " - "to an unsolicited abort \n", - cmd); - if (cmd->retry_count < MAX_CMD_RETRIES) { - retry_cmd=1; - printk(KERN_WARNING - "retrying cmd\n"); - cmd->retry_count++; - } else { - printk(KERN_WARNING - "retried to many times\n"); - } - status=0; - break; - case CMD_TIMEOUT: - printk(KERN_WARNING "cciss: cmd %p timedout\n", - cmd); - status=0; - break; - default: - printk(KERN_WARNING "cciss: cmd %p returned " - "unknown status %x\n", cmd, - cmd->err_info->CommandStatus); - status=0; - } - } - /* We need to return this command */ - if (retry_cmd) { - resend_cciss_cmd(h,cmd); - return; - } - /* command did not need to be retried */ - /* unmap the DMA mapping for all the scatter gather elements */ - if (cmd->Request.Type.Direction == XFER_READ) - ddir = PCI_DMA_FROMDEVICE; - else - ddir = PCI_DMA_TODEVICE; - for(i=0; iHeader.SGList; i++) { - temp64.val32.lower = cmd->SG[i].Addr.lower; - temp64.val32.upper = cmd->SG[i].Addr.upper; - pci_unmap_page(hba[cmd->ctlr]->pdev, - temp64.val, cmd->SG[i].Len, ddir); - } - complete_buffers(cmd->rq->bh, status); -#ifdef CCISS_DEBUG - printk("Done with %p\n", cmd->rq); -#endif /* CCISS_DEBUG */ - end_that_request_last(cmd->rq); - cmd_free(h,cmd,1); -} - - -static inline int cpq_new_segment(request_queue_t *q, struct request *rq, - int max_segments) -{ - if (rq->nr_segments < MAXSGENTRIES) { - rq->nr_segments++; - return 1; - } - return 0; -} - -static int cpq_back_merge_fn(request_queue_t *q, struct request *rq, - struct buffer_head *bh, int max_segments) -{ - if (blk_seg_merge_ok(rq->bhtail, bh)) - return 1; - return cpq_new_segment(q, rq, max_segments); -} - -static int cpq_front_merge_fn(request_queue_t *q, struct request *rq, - struct buffer_head *bh, int max_segments) -{ - if (blk_seg_merge_ok(bh, rq->bh)) - return 1; - return cpq_new_segment(q, rq, max_segments); -} - -static int cpq_merge_requests_fn(request_queue_t *q, struct request *rq, - struct request *nxt, int max_segments) -{ - int total_segments = rq->nr_segments + nxt->nr_segments; - - if (blk_seg_merge_ok(rq->bhtail, nxt->bh)) - total_segments--; - - if (total_segments > MAXSGENTRIES) - return 0; - - rq->nr_segments = total_segments; - return 1; -} - -/* - * Get a request and submit it to the controller. - * Currently we do one request at a time. Ideally we would like to send - * everything to the controller on the first call, but there is a danger - * of holding the io_request_lock for to long. - */ -static void do_cciss_request(request_queue_t *q) -{ - ctlr_info_t *h= q->queuedata; - CommandList_struct *c; - int log_unit, start_blk, seg; - unsigned long long lastdataend; - struct buffer_head *bh; - struct list_head *queue_head = &q->queue_head; - struct request *creq; - u64bit temp64; - struct scatterlist tmp_sg[MAXSGENTRIES]; - int i, ddir; - - if (q->plugged) - goto startio; - -next: - if (list_empty(queue_head)) - goto startio; - - creq = blkdev_entry_next_request(queue_head); - if (creq->nr_segments > MAXSGENTRIES) - BUG(); - - if( h->ctlr != map_major_to_ctlr[MAJOR(creq->rq_dev)] ) { - printk(KERN_WARNING "doreq cmd for %d, %x at %p\n", - h->ctlr, creq->rq_dev, creq); - blkdev_dequeue_request(creq); - complete_buffers(creq->bh, 0); - end_that_request_last(creq); - goto startio; - } - - /* make sure controller is alive. */ - if (!CTLR_IS_ALIVE(h)) { - printk(KERN_WARNING "cciss%d: I/O quit ", h->ctlr); - blkdev_dequeue_request(creq); - complete_buffers(creq->bh, 0); - end_that_request_last(creq); - return; - } - - if (( c = cmd_alloc(h, 1)) == NULL) - goto startio; - - blkdev_dequeue_request(creq); - - spin_unlock_irq(&io_request_lock); - - c->cmd_type = CMD_RWREQ; - c->rq = creq; - bh = creq->bh; - - /* fill in the request */ - log_unit = MINOR(creq->rq_dev) >> NWD_SHIFT; - c->Header.ReplyQueue = 0; /* unused in simple mode */ - c->Header.Tag.lower = c->busaddr; /* use the physical address */ - /* the cmd block for tag */ - c->Header.LUN.LogDev.VolId= hba[h->ctlr]->drv[log_unit].LunID; - c->Header.LUN.LogDev.Mode = 1; - c->Request.CDBLen = 10; /* 12 byte commands not in FW yet. */ - c->Request.Type.Type = TYPE_CMD; /* It is a command. */ - c->Request.Type.Attribute = ATTR_SIMPLE; - c->Request.Type.Direction = - (creq->cmd == READ) ? XFER_READ: XFER_WRITE; - c->Request.Timeout = 0; /* Don't time out */ - c->Request.CDB[0] = (creq->cmd == READ) ? CCISS_READ : CCISS_WRITE; - start_blk = hba[h->ctlr]->hd[MINOR(creq->rq_dev)].start_sect + creq->sector; -#ifdef CCISS_DEBUG - if (bh == NULL) - panic("cciss: bh== NULL?"); - printk(KERN_DEBUG "cciss: sector =%d nr_sectors=%d\n",(int) creq->sector, - (int) creq->nr_sectors); -#endif /* CCISS_DEBUG */ - seg = 0; - lastdataend = ~0ULL; - while(bh) { - - if (bh_phys(bh) == lastdataend) - { /* tack it on to the last segment */ - tmp_sg[seg-1].length +=bh->b_size; - lastdataend += bh->b_size; - } else { - if (seg == MAXSGENTRIES) - BUG(); - tmp_sg[seg].page = bh->b_page; - tmp_sg[seg].length = bh->b_size; - tmp_sg[seg].offset = bh_offset(bh); - lastdataend = bh_phys(bh) + bh->b_size; - seg++; - } - bh = bh->b_reqnext; - } - - /* get the DMA records for the setup */ - if (c->Request.Type.Direction == XFER_READ) - ddir = PCI_DMA_FROMDEVICE; - else - ddir = PCI_DMA_TODEVICE; - for (i=0; iSG[i].Len = tmp_sg[i].length; - temp64.val = pci_map_page(h->pdev, tmp_sg[i].page, - tmp_sg[i].offset, tmp_sg[i].length, ddir); - c->SG[i].Addr.lower = temp64.val32.lower; - c->SG[i].Addr.upper = temp64.val32.upper; - c->SG[i].Ext = 0; /* we are not chaining */ - } - /* track how many SG entries we are using */ - if (seg > h->maxSG) - h->maxSG = seg; - -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss: Submitting %d sectors in %d segments\n", creq->nr_sectors, seg); -#endif /* CCISS_DEBUG */ - - c->Header.SGList = c->Header.SGTotal = seg; - c->Request.CDB[1]= 0; - c->Request.CDB[2]= (start_blk >> 24) & 0xff; /* MSB */ - c->Request.CDB[3]= (start_blk >> 16) & 0xff; - c->Request.CDB[4]= (start_blk >> 8) & 0xff; - c->Request.CDB[5]= start_blk & 0xff; - c->Request.CDB[6]= 0; /* (sect >> 24) & 0xff; MSB */ - c->Request.CDB[7]= (creq->nr_sectors >> 8) & 0xff; - c->Request.CDB[8]= creq->nr_sectors & 0xff; - c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0; - - spin_lock_irq(&io_request_lock); - - addQ(&(h->reqQ),c); - h->Qdepth++; - if (h->Qdepth > h->maxQsinceinit) - h->maxQsinceinit = h->Qdepth; - - goto next; - -startio: - start_io(h); -} - -static void do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - ctlr_info_t *h = dev_id; - CommandList_struct *c; - unsigned long flags; - __u32 a, a1; - - - /* Is this interrupt for us? */ - if ((h->access.intr_pending(h) == 0) || (h->interrupts_enabled == 0)) - return; - - /* - * If there are completed commands in the completion queue, - * we had better do something about it. - */ - spin_lock_irqsave(&io_request_lock, flags); - while( h->access.intr_pending(h)) { - while((a = h->access.command_completed(h)) != FIFO_EMPTY) { - a1 = a; - a &= ~3; - if ((c = h->cmpQ) == NULL) { - printk(KERN_WARNING "cciss: Completion of %08lx ignored\n", (unsigned long)a1); - continue; - } - while(c->busaddr != a) { - c = c->next; - if (c == h->cmpQ) - break; - } - /* - * If we've found the command, take it off the - * completion Q and free it - */ - if (c->busaddr == a) { - removeQ(&h->cmpQ, c); - if (c->cmd_type == CMD_RWREQ) { - complete_command(h, c, 0); - } else if (c->cmd_type == CMD_IOCTL_PEND) { -#if 0 - complete(c->waiting); -#else - /* XXX SMH: use a flag to signal */ - if(*(int *)(c->waiting) != 0) - *(int *)(c->waiting) = 0; -#endif - } -# ifdef CONFIG_CISS_SCSI_TAPE - else if (c->cmd_type == CMD_SCSI) { - complete_scsi_command(c, 0, a1); - } -# endif - continue; - } - } - } - /* - * See if we can queue up some more IO - */ - do_cciss_request(BLK_DEFAULT_QUEUE(h->major)); - spin_unlock_irqrestore(&io_request_lock, flags); -} -/* - * We cannot read the structure directly, for portablity we must use - * the io functions. - * This is for debug only. - */ -#ifdef CCISS_DEBUG -static void print_cfg_table( CfgTable_struct *tb) -{ - int i; - char temp_name[17]; - - printk("Controller Configuration information\n"); - printk("------------------------------------\n"); - for(i=0;i<4;i++) - temp_name[i] = readb(&(tb->Signature[i])); - temp_name[4]='\0'; - printk(" Signature = %s\n", temp_name); - printk(" Spec Number = %d\n", readl(&(tb->SpecValence))); - printk(" Transport methods supported = 0x%x\n", - readl(&(tb-> TransportSupport))); - printk(" Transport methods active = 0x%x\n", - readl(&(tb->TransportActive))); - printk(" Requested transport Method = 0x%x\n", - readl(&(tb->HostWrite.TransportRequest))); - printk(" Coalese Interrupt Delay = 0x%x\n", - readl(&(tb->HostWrite.CoalIntDelay))); - printk(" Coalese Interrupt Count = 0x%x\n", - readl(&(tb->HostWrite.CoalIntCount))); - printk(" Max outstanding commands = 0x%d\n", - readl(&(tb->CmdsOutMax))); - printk(" Bus Types = 0x%x\n", readl(&(tb-> BusTypes))); - for(i=0;i<16;i++) - temp_name[i] = readb(&(tb->ServerName[i])); - temp_name[16] = '\0'; - printk(" Server Name = %s\n", temp_name); - printk(" Heartbeat Counter = 0x%x\n\n\n", - readl(&(tb->HeartBeat))); -} -#endif /* CCISS_DEBUG */ - -static void release_io_mem(ctlr_info_t *c) -{ - /* if IO mem was not protected do nothing */ - if (c->io_mem_addr == 0) - return; - release_region(c->io_mem_addr, c->io_mem_length); - c->io_mem_addr = 0; - c->io_mem_length = 0; -} -static int find_PCI_BAR_index(struct pci_dev *pdev, - unsigned long pci_bar_addr) -{ - int i, offset, mem_type, bar_type; - if (pci_bar_addr == PCI_BASE_ADDRESS_0) /* looking for BAR zero? */ - return 0; - offset = 0; - for (i=0; iirq; - __u32 board_id; - __u64 cfg_offset; - __u32 cfg_base_addr; - __u64 cfg_base_addr_index; - int i; - - /* check to see if controller has been disabled */ - /* BEFORE we try to enable it */ - (void) pci_read_config_word(pdev, PCI_COMMAND,&command); - if (!(command & 0x02)) { - printk(KERN_WARNING "cciss: controller appears to be disabled\n"); - return -1; - } - if (pci_enable_device(pdev)) { - printk(KERN_ERR "cciss: Unable to Enable PCI device\n"); - return -1; - } - if (pci_set_dma_mask(pdev, CCISS_DMA_MASK ) != 0) { - printk(KERN_ERR "cciss: Unable to set DMA mask\n"); - return -1; - } - - subsystem_vendor_id = pdev->subsystem_vendor; - subsystem_device_id = pdev->subsystem_device; - board_id = (((__u32) (subsystem_device_id << 16) & 0xffff0000) | - subsystem_vendor_id ); - - - /* search for our IO range so we can protect it */ - for (i=0; iio_mem_addr = pci_resource_start(pdev, i); - c->io_mem_length = pci_resource_end(pdev, i) - - pci_resource_start(pdev, i) + 1; -#ifdef CCISS_DEBUG - printk("IO value found base_addr[%d] %lx %lx\n", i, - c->io_mem_addr, c->io_mem_length); -#endif /* CCISS_DEBUG */ - /* register the IO range */ - if (!request_region( c->io_mem_addr, - c->io_mem_length, "cciss")) { - printk(KERN_WARNING - "cciss I/O memory range already in " - "use addr=%lx length=%ld\n", - c->io_mem_addr, c->io_mem_length); - c->io_mem_addr= 0; - c->io_mem_length = 0; - } - break; - } - } - -#ifdef CCISS_DEBUG - printk("command = %x\n", command); - printk("irq = %x\n", irq); - printk("board_id = %x\n", board_id); -#endif /* CCISS_DEBUG */ - - c->intr = irq; - - /* - * Memory base addr is first addr , the second points to the config - * table - */ - - c->paddr = pci_resource_start(pdev, 0); /* addressing mode bits already removed */ -#ifdef CCISS_DEBUG - printk("address 0 = %x\n", c->paddr); -#endif /* CCISS_DEBUG */ - c->vaddr = remap_pci_mem(c->paddr, 200); - - /* get the address index number */ - cfg_base_addr = readl(c->vaddr + SA5_CTCFG_OFFSET); - /* I am not prepared to deal with a 64 bit address value */ - cfg_base_addr &= (__u32) 0x0000ffff; -#ifdef CCISS_DEBUG - printk("cfg base address = %x\n", cfg_base_addr); -#endif /* CCISS_DEBUG */ - cfg_base_addr_index = - find_PCI_BAR_index(pdev, cfg_base_addr); -#ifdef CCISS_DEBUG - printk("cfg base address index = %x\n", cfg_base_addr_index); -#endif /* CCISS_DEBUG */ - if (cfg_base_addr_index == -1) { - printk(KERN_WARNING "cciss: Cannot find cfg_base_addr_index\n"); - release_io_mem(hba[i]); - return -1; - } - - cfg_offset = readl(c->vaddr + SA5_CTMEM_OFFSET); -#ifdef CCISS_DEBUG - printk("cfg offset = %x\n", cfg_offset); -#endif /* CCISS_DEBUG */ - c->cfgtable = (CfgTable_struct *) - remap_pci_mem(pci_resource_start(pdev, cfg_base_addr_index) - + cfg_offset, sizeof(CfgTable_struct)); - c->board_id = board_id; - -#ifdef CCISS_DEBUG - print_cfg_table(c->cfgtable); -#endif /* CCISS_DEBUG */ - - for(i=0; iproduct_name = products[i].product_name; - c->access = *(products[i].access); - break; - } - } - if (i == NR_PRODUCTS) { - printk(KERN_WARNING "cciss: Sorry, I don't know how" - " to access the Smart Array controller %08lx\n", - (unsigned long)board_id); - return -1; - } - if ( (readb(&c->cfgtable->Signature[0]) != 'C') || - (readb(&c->cfgtable->Signature[1]) != 'I') || - (readb(&c->cfgtable->Signature[2]) != 'S') || - (readb(&c->cfgtable->Signature[3]) != 'S') ) { - printk("Does not appear to be a valid CISS config table\n"); - return -1; - } -#ifdef CCISS_DEBUG - printk("Trying to put board into Simple mode\n"); -#endif /* CCISS_DEBUG */ - c->max_commands = readl(&(c->cfgtable->CmdsOutMax)); - /* Update the field, and then ring the doorbell */ - writel( CFGTBL_Trans_Simple, - &(c->cfgtable->HostWrite.TransportRequest)); - writel( CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL); - - /* Here, we wait, possibly for a long time, (4 secs or more). - * In some unlikely cases, (e.g. A failed 144 GB drive in a - * RAID 5 set was hot replaced just as we're coming in here) it - * can take that long. Normally (almost always) we will wait - * less than 1 sec. */ - for(i=0;ivaddr + SA5_DOORBELL) & CFGTBL_ChangeReq)) - break; - /* delay and try again */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } - -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "I counter got to %d %x\n", i, readl(c->vaddr + SA5_DOORBELL)); -#endif /* CCISS_DEBUG */ -#ifdef CCISS_DEBUG - print_cfg_table(c->cfgtable); -#endif /* CCISS_DEBUG */ - - if (!(readl(&(c->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) { - printk(KERN_WARNING "cciss: unable to get board into" - " simple mode\n"); - return -1; - } - return 0; - -} - -/* - * Gets information about the local volumes attached to the controller. - */ -static void cciss_getgeometry(int cntl_num) -{ - ReportLunData_struct *ld_buff; - ReadCapdata_struct *size_buff; - InquiryData_struct *inq_buff; - int return_code; - int i; - int listlength = 0; - __u32 lunid = 0; - int block_size; - int total_size; - - ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL); - if (ld_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - return; - } - memset(ld_buff, 0, sizeof(ReportLunData_struct)); - size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL); - if (size_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - kfree(ld_buff); - return; - } - inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); - if (inq_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - kfree(ld_buff); - kfree(size_buff); - return; - } - /* Get the firmware version */ - return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff, - sizeof(InquiryData_struct), 0, 0 ,0, NULL); - if (return_code == IO_OK) { - hba[cntl_num]->firm_ver[0] = inq_buff->data_byte[32]; - hba[cntl_num]->firm_ver[1] = inq_buff->data_byte[33]; - hba[cntl_num]->firm_ver[2] = inq_buff->data_byte[34]; - hba[cntl_num]->firm_ver[3] = inq_buff->data_byte[35]; - } else { /* send command failed */ - printk(KERN_WARNING "cciss: unable to determine firmware" - " version of controller\n"); - } - /* Get the number of logical volumes */ - return_code = sendcmd(CISS_REPORT_LOG, cntl_num, ld_buff, - sizeof(ReportLunData_struct), 0, 0, 0, NULL); - - if (return_code == IO_OK) { -#ifdef CCISS_DEBUG - printk("LUN Data\n--------------------------\n"); -#endif /* CCISS_DEBUG */ - - listlength = be32_to_cpu(*((__u32 *) &ld_buff->LUNListLength[0])); - } else { /* reading number of logical volumes failed */ - printk(KERN_WARNING "cciss: report logical volume" - " command failed\n"); - listlength = 0; - } - hba[cntl_num]->num_luns = listlength / 8; /* 8 bytes pre entry */ - if (hba[cntl_num]->num_luns > CISS_MAX_LUN) { - printk(KERN_ERR "cciss: only %d number of logical volumes supported\n", - CISS_MAX_LUN); - hba[cntl_num]->num_luns = CISS_MAX_LUN; - } -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "Length = %x %x %x %x = %d\n", ld_buff->LUNListLength[0], - ld_buff->LUNListLength[1], ld_buff->LUNListLength[2], - ld_buff->LUNListLength[3], hba[cntl_num]->num_luns); -#endif /* CCISS_DEBUG */ - - hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns-1; - for(i=0; i< hba[cntl_num]->num_luns; i++) { - lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24; - lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16; - lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8; - lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]); - hba[cntl_num]->drv[i].LunID = lunid; - -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "LUN[%d]: %x %x %x %x = %x\n", i, - ld_buff->LUN[i][0], ld_buff->LUN[i][1],ld_buff->LUN[i][2], - ld_buff->LUN[i][3], hba[cntl_num]->drv[i].LunID); -#endif /* CCISS_DEBUG */ - - memset(size_buff, 0, sizeof(ReadCapdata_struct)); - return_code = sendcmd(CCISS_READ_CAPACITY, cntl_num, size_buff, - sizeof( ReadCapdata_struct), 1, i, 0, NULL); - if (return_code == IO_OK) { - total_size = (0xff & - (unsigned int)(size_buff->total_size[0])) << 24; - total_size |= (0xff & - (unsigned int)(size_buff->total_size[1])) << 16; - total_size |= (0xff & - (unsigned int)(size_buff->total_size[2])) << 8; - total_size |= (0xff & (unsigned int) - (size_buff->total_size[3])); - total_size++; /* command returns highest */ - /* block address */ - - block_size = (0xff & - (unsigned int)(size_buff->block_size[0])) << 24; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[1])) << 16; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[2])) << 8; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[3])); - } else { /* read capacity command failed */ - printk(KERN_WARNING "cciss: read capacity failed\n"); - total_size = block_size = 0; - } - printk(KERN_INFO " blocks= %d block_size= %d\n", - total_size, block_size); - - /* Execute the command to read the disk geometry */ - memset(inq_buff, 0, sizeof(InquiryData_struct)); - return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff, - sizeof(InquiryData_struct), 1, i, 0xC1, NULL ); - if (return_code == IO_OK) { - if (inq_buff->data_byte[8] == 0xFF) { - printk(KERN_WARNING "cciss: reading geometry failed, volume does not support reading geometry\n"); - - hba[cntl_num]->drv[i].block_size = block_size; - hba[cntl_num]->drv[i].nr_blocks = total_size; - hba[cntl_num]->drv[i].heads = 255; - hba[cntl_num]->drv[i].sectors = 32; /* Sectors */ - /* per track */ - hba[cntl_num]->drv[i].cylinders = total_size - / 255 / 32; - } else { - - hba[cntl_num]->drv[i].block_size = block_size; - hba[cntl_num]->drv[i].nr_blocks = total_size; - hba[cntl_num]->drv[i].heads = - inq_buff->data_byte[6]; - hba[cntl_num]->drv[i].sectors = - inq_buff->data_byte[7]; - hba[cntl_num]->drv[i].cylinders = - (inq_buff->data_byte[4] & 0xff) << 8; - hba[cntl_num]->drv[i].cylinders += - inq_buff->data_byte[5]; - hba[cntl_num]->drv[i].raid_level = - inq_buff->data_byte[8]; - } - } - else { /* Get geometry failed */ - printk(KERN_WARNING "cciss: reading geometry failed, continuing with default geometry\n"); - - hba[cntl_num]->drv[i].block_size = block_size; - hba[cntl_num]->drv[i].nr_blocks = total_size; - hba[cntl_num]->drv[i].heads = 255; - hba[cntl_num]->drv[i].sectors = 32; /* Sectors */ - /* per track */ - hba[cntl_num]->drv[i].cylinders = total_size / 255 / 32; - } - if (hba[cntl_num]->drv[i].raid_level > 5) - hba[cntl_num]->drv[i].raid_level = RAID_UNKNOWN; - printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d RAID %s\n\n", - hba[cntl_num]->drv[i].heads, - hba[cntl_num]->drv[i].sectors, - hba[cntl_num]->drv[i].cylinders, - raid_label[hba[cntl_num]->drv[i].raid_level]); - } - kfree(ld_buff); - kfree(size_buff); - kfree(inq_buff); -} - -/* Function to find the first free pointer into our hba[] array */ -/* Returns -1 if no free entries are left. */ -static int alloc_cciss_hba(void) -{ - int i; - for(i=0; i< MAX_CTLR; i++) { - if (hba[i] == NULL) { - hba[i] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL); - if (hba[i]==NULL) { - printk(KERN_ERR "cciss: out of memory.\n"); - return -1; - } - return i; - } - } - printk(KERN_WARNING - "cciss: This driver supports a maximum of %d controllers.\n" - "You can change this value in cciss.c and recompile.\n", - MAX_CTLR); - return -1; -} - -static void free_hba(int i) -{ - kfree(hba[i]); - hba[i]=NULL; -} -#ifdef CONFIG_CISS_MONITOR_THREAD -static void fail_all_cmds(unsigned long ctlr) -{ - /* If we get here, the board is apparently dead. */ - ctlr_info_t *h = hba[ctlr]; - CommandList_struct *c; - unsigned long flags; - - printk(KERN_WARNING "cciss%d: controller not responding.\n", h->ctlr); - h->alive = 0; /* the controller apparently died... */ - - spin_lock_irqsave(&io_request_lock, flags); - - pci_disable_device(h->pdev); /* Make sure it is really dead. */ - - /* move everything off the request queue onto the completed queue */ - while( (c = h->reqQ) != NULL ) { - removeQ(&(h->reqQ), c); - h->Qdepth--; - addQ (&(h->cmpQ), c); - } - - /* Now, fail everything on the completed queue with a HW error */ - while( (c = h->cmpQ) != NULL ) { - removeQ(&h->cmpQ, c); - c->err_info->CommandStatus = CMD_HARDWARE_ERR; - if (c->cmd_type == CMD_RWREQ) { - complete_command(h, c, 0); - } else if (c->cmd_type == CMD_IOCTL_PEND) - complete(c->waiting); -# ifdef CONFIG_CISS_SCSI_TAPE - else if (c->cmd_type == CMD_SCSI) - complete_scsi_command(c, 0, 0); -# endif - } - spin_unlock_irqrestore(&io_request_lock, flags); - return; -} -static int cciss_monitor(void *ctlr) -{ - /* If the board fails, we ought to detect that. So we periodically - send down a No-Op message and expect it to complete quickly. If it - doesn't, then we assume the board is dead, and fail all commands. - This is useful mostly in a multipath configuration, so that failover - will happen. */ - - int rc; - ctlr_info_t *h = (ctlr_info_t *) ctlr; - unsigned long flags; - u32 current_timer; - - daemonize(); - exit_files(current); - reparent_to_init(); - - printk("cciss%d: Monitor thread starting.\n", h->ctlr); - - /* only listen to signals if the HA was loaded as a module. */ -#define SHUTDOWN_SIGS (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM)) - siginitsetinv(¤t->blocked, SHUTDOWN_SIGS); - sprintf(current->comm, "ccissmon%d", h->ctlr); - h->monitor_thread = current; - - init_timer(&h->watchdog); - h->watchdog.function = fail_all_cmds; - h->watchdog.data = (unsigned long) h->ctlr; - while (1) { - /* check heartbeat timer */ - current_timer = readl(&h->cfgtable->HeartBeat); - current_timer &= 0x0fffffff; - if (heartbeat_timer == current_timer) { - fail_all_cmds(h->ctlr); - break; - } - else - heartbeat_timer = current_timer; - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(h->monitor_period * HZ); - h->watchdog.expires = jiffies + HZ * h->monitor_deadline; - add_timer(&h->watchdog); - /* send down a trivial command (no op message) to ctlr */ - rc = sendcmd_withirq(3, h->ctlr, NULL, 0, 0, 0, 0, TYPE_MSG); - del_timer(&h->watchdog); - if (!CTLR_IS_ALIVE(h)) - break; - if (signal_pending(current)) { - printk(KERN_WARNING "%s received signal.\n", - current->comm); - break; - } - if (h->monitor_period == 0) /* zero period means exit thread */ - break; - } - printk(KERN_INFO "%s exiting.\n", current->comm); - spin_lock_irqsave(&io_request_lock, flags); - h->monitor_started = 0; - h->monitor_thread = NULL; - spin_unlock_irqrestore(&io_request_lock, flags); - return 0; -} -static int start_monitor_thread(ctlr_info_t *h, unsigned char *cmd, - unsigned long count, int (*cciss_monitor)(void *), int *rc) -{ - unsigned long flags; - unsigned int new_period, old_period, new_deadline, old_deadline; - - if (strncmp("monitor", cmd, 7) == 0) { - new_period = simple_strtol(cmd + 8, NULL, 10); - spin_lock_irqsave(&io_request_lock, flags); - new_deadline = h->monitor_deadline; - spin_unlock_irqrestore(&io_request_lock, flags); - } else if (strncmp("deadline", cmd, 8) == 0) { - new_deadline = simple_strtol(cmd + 9, NULL, 10); - spin_lock_irqsave(&io_request_lock, flags); - new_period = h->monitor_period; - spin_unlock_irqrestore(&io_request_lock, flags); - } else - return -1; - if (new_period != 0 && new_period < CCISS_MIN_PERIOD) - new_period = CCISS_MIN_PERIOD; - if (new_period > CCISS_MAX_PERIOD) - new_period = CCISS_MAX_PERIOD; - if (new_deadline >= new_period) { - new_deadline = new_period - 5; - printk(KERN_INFO "setting deadline to %d\n", new_deadline); - } - spin_lock_irqsave(&io_request_lock, flags); - if (h->monitor_started != 0) { - old_period = h->monitor_period; - old_deadline = h->monitor_deadline; - h->monitor_period = new_period; - h->monitor_deadline = new_deadline; - spin_unlock_irqrestore(&io_request_lock, flags); - if (new_period == 0) { - printk(KERN_INFO "cciss%d: stopping monitor thread\n", - h->ctlr); - *rc = count; - return 0; - } - if (new_period != old_period) - printk(KERN_INFO "cciss%d: adjusting monitor thread " - "period from %d to %d seconds\n", - h->ctlr, old_period, new_period); - if (new_deadline != old_deadline) - printk(KERN_INFO "cciss%d: adjusting monitor thread " - "deadline from %d to %d seconds\n", - h->ctlr, old_deadline, new_deadline); - *rc = count; - return 0; - } - h->monitor_started = 1; - h->monitor_period = new_period; - h->monitor_deadline = new_deadline; - spin_unlock_irqrestore(&io_request_lock, flags); - kernel_thread(cciss_monitor, h, 0); - *rc = count; - return 0; -} - -static void kill_monitor_thread(ctlr_info_t *h) -{ - if (h->monitor_thread) - send_sig(SIGKILL, h->monitor_thread, 1); -} -#else -#define kill_monitor_thread(h) -#endif -/* - * This is it. Find all the controllers and register them. I really hate - * stealing all these major device numbers. - * returns the number of block devices registered. - */ -static int __init cciss_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - request_queue_t *q; - int i; - int j; -#if 0 - int rc; -#endif - - printk(KERN_DEBUG "cciss: Device 0x%x has been found at" - " bus %d dev %d func %d\n", - pdev->device, pdev->bus->number, PCI_SLOT(pdev->devfn), - PCI_FUNC(pdev->devfn)); - i = alloc_cciss_hba(); - if (i < 0 ) - return -1; - memset(hba[i], 0, sizeof(ctlr_info_t)); - if (cciss_pci_init(hba[i], pdev) != 0) { - free_hba(i); - return -1; - } - sprintf(hba[i]->devname, "cciss%d", i); - hba[i]->ctlr = i; - - /* register with the major number, or get a dynamic major number */ - /* by passing 0 as argument */ - - if (i < MAX_CTLR_ORIG) - hba[i]->major = MAJOR_NR + i; - - hba[i]->pdev = pdev; - ASSERT_CTLR_ALIVE(hba[i]); - -#if 0 - rc = (register_blkdev(hba[i]->major, hba[i]->devname, &cciss_fops)); - if (rc < 0) { - printk(KERN_ERR "cciss: Unable to get major number " - "%d for %s\n", hba[i]->major, hba[i]->devname); - release_io_mem(hba[i]); - free_hba(i); - return -1; - } else - { - if (i < MAX_CTLR_ORIG) { - hba[i]->major = MAJOR_NR + i; - map_major_to_ctlr[MAJOR_NR + i] = i; - } else { - hba[i]->major = rc; - map_major_to_ctlr[rc] = i; - } - } - -XXXX Need to register this... - -#endif - - /* make sure the board interrupts are off */ - hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF); - if (request_irq(hba[i]->intr, do_cciss_intr, - SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, - hba[i]->devname, hba[i])) { - - printk(KERN_ERR "cciss: Unable to get irq %d for %s\n", - hba[i]->intr, hba[i]->devname); - unregister_blkdev( hba[i]->major, hba[i]->devname); - map_major_to_ctlr[hba[i]->major] = 0; - release_io_mem(hba[i]); - free_hba(i); - return -1; - } - hba[i]->cmd_pool_bits = (__u32*)kmalloc( - ((NR_CMDS+31)/32)*sizeof(__u32), GFP_KERNEL); - hba[i]->cmd_pool = (CommandList_struct *)pci_alloc_consistent( - hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct), - &(hba[i]->cmd_pool_dhandle)); - hba[i]->errinfo_pool = (ErrorInfo_struct *)pci_alloc_consistent( - hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct), - &(hba[i]->errinfo_pool_dhandle)); - if ((hba[i]->cmd_pool_bits == NULL) - || (hba[i]->cmd_pool == NULL) - || (hba[i]->errinfo_pool == NULL)) { - - if (hba[i]->cmd_pool_bits) - kfree(hba[i]->cmd_pool_bits); - if (hba[i]->cmd_pool) - pci_free_consistent(hba[i]->pdev, - NR_CMDS * sizeof(CommandList_struct), - hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle); - if (hba[i]->errinfo_pool) - pci_free_consistent(hba[i]->pdev, - NR_CMDS * sizeof( ErrorInfo_struct), - hba[i]->errinfo_pool, - hba[i]->errinfo_pool_dhandle); - free_irq(hba[i]->intr, hba[i]); - unregister_blkdev(hba[i]->major, hba[i]->devname); - map_major_to_ctlr[hba[i]->major] = 0; - release_io_mem(hba[i]); - free_hba(i); - printk( KERN_ERR "cciss: out of memory"); - return -1; - } - - /* Initialize the pdev driver private data. - have it point to hba[i]. */ - pci_set_drvdata(pdev, hba[i]); - /* command and error info recs zeroed out before - they are used */ - memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+31)/32)*sizeof(__u32)); - -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "Scanning for drives on controller cciss%d\n",i); -#endif /* CCISS_DEBUG */ - - cciss_getgeometry(i); - - cciss_find_non_disk_devices(i); /* find our tape drives, if any */ - - /* Turn the interrupts on so we can service requests */ - hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON); - - cciss_procinit(i); - - q = BLK_DEFAULT_QUEUE(hba[i]->major); - q->queuedata = hba[i]; - blk_init_queue(q, do_cciss_request); -#if 0 - // XXX SMH; no bounce support for us yet - blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask); -#endif - blk_queue_headactive(q, 0); - - /* fill in the other Kernel structs */ - blksize_size[hba[i]->major] = hba[i]->blocksizes; - hardsect_size[hba[i]->major] = hba[i]->hardsizes; - read_ahead[hba[i]->major] = READ_AHEAD; - - /* Set the pointers to queue functions */ - q->back_merge_fn = cpq_back_merge_fn; - q->front_merge_fn = cpq_front_merge_fn; - q->merge_requests_fn = cpq_merge_requests_fn; - - - /* Fill in the gendisk data */ - hba[i]->gendisk.major = hba[i]->major; - hba[i]->gendisk.major_name = "cciss"; - hba[i]->gendisk.minor_shift = NWD_SHIFT; - hba[i]->gendisk.max_p = MAX_PART; - hba[i]->gendisk.part = hba[i]->hd; - hba[i]->gendisk.sizes = hba[i]->sizes; - hba[i]->gendisk.nr_real = hba[i]->highest_lun+1; - hba[i]->gendisk.fops = &cciss_fops; - - /* Get on the disk list */ - add_gendisk(&(hba[i]->gendisk)); - - cciss_geninit(i); - for(j=0; jgendisk), - MKDEV(hba[i]->major, j <<4), - MAX_PART, &cciss_fops, - hba[i]->drv[j].nr_blocks); - - cciss_register_scsi(i, 1); /* hook ourself into SCSI subsystem */ - - return 1; -} - -static void __devexit cciss_remove_one (struct pci_dev *pdev) -{ - ctlr_info_t *tmp_ptr; - int i; - char flush_buf[4]; - int return_code; - - if (pci_get_drvdata(pdev) == NULL) { - printk( KERN_ERR "cciss: Unable to remove device \n"); - return; - } - tmp_ptr = pci_get_drvdata(pdev); - i = tmp_ptr->ctlr; - if (hba[i] == NULL) { - printk(KERN_ERR "cciss: device appears to " - "already be removed \n"); - return; - } - kill_monitor_thread(hba[i]); - /* no sense in trying to flush a dead board's cache. */ - if (CTLR_IS_ALIVE(hba[i])) { - /* Turn board interrupts off and flush the cache */ - /* write all data in the battery backed cache to disks */ - memset(flush_buf, 0, 4); - return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, - 4, 0, 0, 0, NULL); - if (return_code != IO_OK) - printk(KERN_WARNING - "cciss%d: Error flushing cache\n", i); - } - free_irq(hba[i]->intr, hba[i]); - pci_set_drvdata(pdev, NULL); - iounmap((void*)hba[i]->vaddr); - cciss_unregister_scsi(i); /* unhook from SCSI subsystem */ - unregister_blkdev(hba[i]->major, hba[i]->devname); - map_major_to_ctlr[hba[i]->major] = 0; - //remove_proc_entry(hba[i]->devname, proc_cciss); - - - /* remove it from the disk list */ - del_gendisk(&(hba[i]->gendisk)); - - pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct), - hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle); - pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct), - hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); - kfree(hba[i]->cmd_pool_bits); - release_io_mem(hba[i]); - free_hba(i); -} - -static struct pci_driver cciss_pci_driver = { - name: "cciss", - probe: cciss_init_one, - remove: __devexit_p(cciss_remove_one), - id_table: cciss_pci_device_id, /* id_table */ -}; - -/* -* This is it. Register the PCI driver information for the cards we control -* the OS will call our registered routines when it finds one of our cards. -*/ -int __init cciss_init(void) -{ - int ret = pci_module_init(&cciss_pci_driver); - if (ret >= 0) - printk(KERN_INFO DRIVER_NAME "\n"); - return ret; -} - -EXPORT_NO_SYMBOLS; -static int __init init_cciss_module(void) -{ - - return cciss_init(); -} - -static void __exit cleanup_cciss_module(void) -{ - int i; - - pci_unregister_driver(&cciss_pci_driver); - /* double check that all controller entrys have been removed */ - for (i=0; i< MAX_CTLR; i++) { - if (hba[i] != NULL) { - printk(KERN_WARNING "cciss: had to remove" - " controller %d\n", i); - cciss_remove_one(hba[i]->pdev); - } - } - //remove_proc_entry("cciss", proc_root_driver); -} - -module_init(init_cciss_module); -module_exit(cleanup_cciss_module); diff --git a/xen/drivers/block/cciss.h b/xen/drivers/block/cciss.h deleted file mode 100644 index 439c7ddb2a..0000000000 --- a/xen/drivers/block/cciss.h +++ /dev/null @@ -1,293 +0,0 @@ -#ifndef CCISS_H -#define CCISS_H - -#include - -#include "cciss_cmd.h" - - -#define NWD 16 -#define NWD_SHIFT 4 -#define MAX_PART 16 - -#define IO_OK 0 -#define IO_ERROR 1 - -#define MAJOR_NR COMPAQ_CISS_MAJOR - -struct ctlr_info; -typedef struct ctlr_info ctlr_info_t; - -struct access_method { - void (*submit_command)(ctlr_info_t *h, CommandList_struct *c); - void (*set_intr_mask)(ctlr_info_t *h, unsigned long val); - unsigned long (*fifo_full)(ctlr_info_t *h); - unsigned long (*intr_pending)(ctlr_info_t *h); - unsigned long (*command_completed)(ctlr_info_t *h); -}; -typedef struct _drive_info_struct -{ - __u32 LunID; - int usage_count; - unsigned int nr_blocks; - int block_size; - int heads; - int sectors; - int cylinders; - int raid_level; -} drive_info_struct; - -struct ctlr_info -{ - int ctlr; - int major; - char devname[8]; - char *product_name; - char firm_ver[4]; // Firmware version - struct pci_dev *pdev; - __u32 board_id; - unsigned long vaddr; - unsigned long paddr; - unsigned long io_mem_addr; - unsigned long io_mem_length; - CfgTable_struct *cfgtable; - int intr; - int interrupts_enabled; - int max_commands; - int commands_outstanding; - int max_outstanding; /* Debug */ - int num_luns; - int highest_lun; - int usage_count; /* number of opens all all minor devices */ - - // information about each logical volume - drive_info_struct drv[CISS_MAX_LUN]; - - struct access_method access; - - /* queue and queue Info */ - CommandList_struct *reqQ; - CommandList_struct *cmpQ; - unsigned int Qdepth; - unsigned int maxQsinceinit; - unsigned int maxSG; - - //* pointers to command and error info pool */ - CommandList_struct *cmd_pool; - dma_addr_t cmd_pool_dhandle; - ErrorInfo_struct *errinfo_pool; - dma_addr_t errinfo_pool_dhandle; - __u32 *cmd_pool_bits; - int nr_allocs; - int nr_frees; - - // Disk structures we need to pass back - struct gendisk gendisk; - // indexed by minor numbers - struct hd_struct hd[256]; - int sizes[256]; - int blocksizes[256]; - int hardsizes[256]; - int busy_configuring; -#ifdef CONFIG_CISS_SCSI_TAPE - void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ -#endif -#ifdef CONFIG_CISS_MONITOR_THREAD - struct timer_list watchdog; - struct task_struct *monitor_thread; - unsigned int monitor_period; - unsigned int monitor_deadline; - unsigned char alive; - unsigned char monitor_started; -#define CCISS_MIN_PERIOD 10 -#define CCISS_MAX_PERIOD 3600 -#define CTLR_IS_ALIVE(h) (h->alive) -#define ASSERT_CTLR_ALIVE(h) { h->alive = 1; \ - h->monitor_period = 0; \ - h->monitor_started = 0; } -#define MONITOR_STATUS_PATTERN "Status: %s\n" -#define CTLR_STATUS(h) CTLR_IS_ALIVE(h) ? "operational" : "failed" -#define MONITOR_PERIOD_PATTERN "Monitor thread period: %d\n" -#define MONITOR_PERIOD_VALUE(h) (h->monitor_period) -#define MONITOR_DEADLINE_PATTERN "Monitor thread deadline: %d\n" -#define MONITOR_DEADLINE_VALUE(h) (h->monitor_deadline) -#define START_MONITOR_THREAD(h, cmd, count, cciss_monitor, rc) \ - start_monitor_thread(h, cmd, count, cciss_monitor, rc) -#else - -#define MONITOR_PERIOD_PATTERN "%s" -#define MONITOR_PERIOD_VALUE(h) "" -#define MONITOR_DEADLINE_PATTERN "%s" -#define MONITOR_DEADLINE_VALUE(h) "" -#define MONITOR_STATUS_PATTERN "%s\n" -#define CTLR_STATUS(h) "" -#define CTLR_IS_ALIVE(h) (1) -#define ASSERT_CTLR_ALIVE(h) -#define START_MONITOR_THREAD(a,b,c,d,rc) (*rc == 0) - -#endif -}; - -/* Defining the diffent access_menthods */ -/* - * Memory mapped FIFO interface (SMART 53xx cards) - */ -#define SA5_DOORBELL 0x20 -#define SA5_REQUEST_PORT_OFFSET 0x40 -#define SA5_REPLY_INTR_MASK_OFFSET 0x34 -#define SA5_REPLY_PORT_OFFSET 0x44 -#define SA5_INTR_STATUS 0x30 - -#define SA5_CTCFG_OFFSET 0xB4 -#define SA5_CTMEM_OFFSET 0xB8 - -#define SA5_INTR_OFF 0x08 -#define SA5B_INTR_OFF 0x04 -#define SA5_INTR_PENDING 0x08 -#define SA5B_INTR_PENDING 0x04 -#define FIFO_EMPTY 0xffffffff - -#define CISS_ERROR_BIT 0x02 - -#define CCISS_INTR_ON 1 -#define CCISS_INTR_OFF 0 -/* - Send the command to the hardware -*/ -static void SA5_submit_command( ctlr_info_t *h, CommandList_struct *c) -{ -#ifdef CCISS_DEBUG - printk("Sending %x - down to controller\n", c->busaddr ); -#endif /* CCISS_DEBUG */ - writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET); - h->commands_outstanding++; - if ( h->commands_outstanding > h->max_outstanding) - h->max_outstanding = h->commands_outstanding; -} - -/* - * This card is the opposite of the other cards. - * 0 turns interrupts on... - * 0x08 turns them off... - */ -static void SA5_intr_mask(ctlr_info_t *h, unsigned long val) -{ - if (val) - { /* Turn interrupts on */ - h->interrupts_enabled = 1; - writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); - } else /* Turn them off */ - { - h->interrupts_enabled = 0; - writel( SA5_INTR_OFF, - h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); - } -} -/* - * This card is the opposite of the other cards. - * 0 turns interrupts on... - * 0x04 turns them off... - */ -static void SA5B_intr_mask(ctlr_info_t *h, unsigned long val) -{ - if (val) - { /* Turn interrupts on */ - h->interrupts_enabled = 1; - writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); - } else /* Turn them off */ - { - h->interrupts_enabled = 0; - writel( SA5B_INTR_OFF, - h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); - } -} -/* - * Returns true if fifo is full. - * - */ -static unsigned long SA5_fifo_full(ctlr_info_t *h) -{ - if( h->commands_outstanding >= h->max_commands) - return(1); - else - return(0); - -} -/* - * returns value read from hardware. - * returns FIFO_EMPTY if there is nothing to read - */ -static unsigned long SA5_completed(ctlr_info_t *h) -{ - unsigned long register_value - = readl(h->vaddr + SA5_REPLY_PORT_OFFSET); - if(register_value != FIFO_EMPTY) - { - h->commands_outstanding--; -#ifdef CCISS_DEBUG - printk("cciss: Read %lx back from board\n", register_value); -#endif /* CCISS_DEBUG */ - } -#ifdef CCISS_DEBUG - else - { - printk("cciss: FIFO Empty read\n"); - } -#endif - return ( register_value); - -} -/* - * Returns true if an interrupt is pending.. - */ -static unsigned long SA5_intr_pending(ctlr_info_t *h) -{ - unsigned long register_value = - readl(h->vaddr + SA5_INTR_STATUS); -#ifdef CCISS_DEBUG - printk("cciss: intr_pending %lx\n", register_value); -#endif /* CCISS_DEBUG */ - if( register_value & SA5_INTR_PENDING) - return 1; - return 0 ; -} - -/* - * Returns true if an interrupt is pending.. - */ -static unsigned long SA5B_intr_pending(ctlr_info_t *h) -{ - unsigned long register_value = - readl(h->vaddr + SA5_INTR_STATUS); -#ifdef CCISS_DEBUG - printk("cciss: intr_pending %lx\n", register_value); -#endif /* CCISS_DEBUG */ - if( register_value & SA5B_INTR_PENDING) - return 1; - return 0 ; -} - - -static struct access_method SA5_access = { - SA5_submit_command, - SA5_intr_mask, - SA5_fifo_full, - SA5_intr_pending, - SA5_completed, -}; - -static struct access_method SA5B_access = { - SA5_submit_command, - SA5B_intr_mask, - SA5_fifo_full, - SA5B_intr_pending, - SA5_completed, -}; - -struct board_type { - __u32 board_id; - char *product_name; - struct access_method *access; -}; -#endif /* CCISS_H */ - diff --git a/xen/drivers/block/cciss_cmd.h b/xen/drivers/block/cciss_cmd.h deleted file mode 100644 index f97ceab79a..0000000000 --- a/xen/drivers/block/cciss_cmd.h +++ /dev/null @@ -1,271 +0,0 @@ -#ifndef CCISS_CMD_H -#define CCISS_CMD_H -/* ########################################################################## */ -/* DEFINES */ -/* ########################################################################## */ -#define CISS_VERSION "1.00" - -/* general boundary defintions */ -#define SENSEINFOBYTES 32 /* note that this value may vary */ - /* between host implementations */ -#define MAXSGENTRIES 31 -#define MAXREPLYQS 256 - -/* Command Status value */ -#define CMD_SUCCESS 0x0000 -#define CMD_TARGET_STATUS 0x0001 -#define CMD_DATA_UNDERRUN 0x0002 -#define CMD_DATA_OVERRUN 0x0003 -#define CMD_INVALID 0x0004 -#define CMD_PROTOCOL_ERR 0x0005 -#define CMD_HARDWARE_ERR 0x0006 -#define CMD_CONNECTION_LOST 0x0007 -#define CMD_ABORTED 0x0008 -#define CMD_ABORT_FAILED 0x0009 -#define CMD_UNSOLICITED_ABORT 0x000A -#define CMD_TIMEOUT 0x000B -#define CMD_UNABORTABLE 0x000C - -/* transfer direction */ -#define XFER_NONE 0x00 -#define XFER_WRITE 0x01 -#define XFER_READ 0x02 -#define XFER_RSVD 0x03 - -/* task attribute */ -#define ATTR_UNTAGGED 0x00 -#define ATTR_SIMPLE 0x04 -#define ATTR_HEADOFQUEUE 0x05 -#define ATTR_ORDERED 0x06 -#define ATTR_ACA 0x07 - -/* cdb type */ -#define TYPE_CMD 0x00 -#define TYPE_MSG 0x01 - -/* config space register offsets */ -#define CFG_VENDORID 0x00 -#define CFG_DEVICEID 0x02 -#define CFG_I2OBAR 0x10 -#define CFG_MEM1BAR 0x14 - -/* i2o space register offsets */ -#define I2O_IBDB_SET 0x20 -#define I2O_IBDB_CLEAR 0x70 -#define I2O_INT_STATUS 0x30 -#define I2O_INT_MASK 0x34 -#define I2O_IBPOST_Q 0x40 -#define I2O_OBPOST_Q 0x44 - -/* Configuration Table */ -#define CFGTBL_ChangeReq 0x00000001l -#define CFGTBL_AccCmds 0x00000001l - -#define CFGTBL_Trans_Simple 0x00000002l - -#define CFGTBL_BusType_Ultra2 0x00000001l -#define CFGTBL_BusType_Ultra3 0x00000002l -#define CFGTBL_BusType_Fibre1G 0x00000100l -#define CFGTBL_BusType_Fibre2G 0x00000200l -typedef struct _vals32 -{ - __u32 lower; - __u32 upper; -} vals32; - -typedef union _u64bit -{ - vals32 val32; - __u64 val; -} u64bit; - -/* Type defs used in the following structs */ -typedef __u8 BYTE; -typedef __u16 WORD; -typedef __u16 HWORD; -typedef __u32 DWORD; -typedef vals32 QWORD; - -/* ######################################################################### */ -/* STRUCTURES */ -/* ######################################################################### */ -#define CISS_MAX_LUN 16 -#define CISS_MAX_PHYS_LUN 1024 -/* SCSI-3 Cmmands */ - -#pragma pack(1) - -#define CISS_INQUIRY 0x12 -/* Data returned */ -typedef struct _InquiryData_struct -{ - BYTE data_byte[36]; -} InquiryData_struct; - -#define CISS_REPORT_LOG 0xc2 /* Report Logical LUNs */ -#define CISS_REPORT_PHYS 0xc3 /* Report Physical LUNs */ -/* Data returned */ -typedef struct _ReportLUNdata_struct -{ - BYTE LUNListLength[4]; - DWORD reserved; - BYTE LUN[CISS_MAX_LUN][8]; -} ReportLunData_struct; - -#define CCISS_READ_CAPACITY 0x25 /* Read Capacity */ -typedef struct _ReadCapdata_struct -{ - BYTE total_size[4]; /* Total size in blocks */ - BYTE block_size[4]; /* Size of blocks in bytes */ -} ReadCapdata_struct; - -/* 12 byte commands not implemented in firmware yet. */ -/* #define CCISS_READ 0xa8 Read(12) */ -/* #define CCISS_WRITE 0xaa Write(12) */ - #define CCISS_READ 0x28 /* Read(10) */ - #define CCISS_WRITE 0x2a /* Write(10) */ - -/* BMIC commands */ -#define BMIC_READ 0x26 -#define BMIC_WRITE 0x27 -#define BMIC_CACHE_FLUSH 0xc2 -#define CCISS_CACHE_FLUSH 0x01 /* 0xC2 was already being used by CCISS */ - -/* Command List Structure */ -typedef union _SCSI3Addr_struct { - struct { - BYTE Dev; - BYTE Bus:6; - BYTE Mode:2; /* b00 */ - } PeripDev; - struct { - BYTE DevLSB; - BYTE DevMSB:6; - BYTE Mode:2; /* b01 */ - } LogDev; - struct { - BYTE Dev:5; - BYTE Bus:3; - BYTE Targ:6; - BYTE Mode:2; /* b10 */ - } LogUnit; -} SCSI3Addr_struct; - -typedef struct _PhysDevAddr_struct { - DWORD TargetId:24; - DWORD Bus:6; - DWORD Mode:2; - SCSI3Addr_struct Target[2]; /* 2 level target device addr */ -} PhysDevAddr_struct; - -typedef struct _LogDevAddr_struct { - DWORD VolId:30; - DWORD Mode:2; - BYTE reserved[4]; -} LogDevAddr_struct; - -typedef union _LUNAddr_struct { - BYTE LunAddrBytes[8]; - SCSI3Addr_struct SCSI3Lun[4]; - PhysDevAddr_struct PhysDev; - LogDevAddr_struct LogDev; -} LUNAddr_struct; - -typedef struct _CommandListHeader_struct { - BYTE ReplyQueue; - BYTE SGList; - HWORD SGTotal; - QWORD Tag; - LUNAddr_struct LUN; -} CommandListHeader_struct; -typedef struct _RequestBlock_struct { - BYTE CDBLen; - struct { - BYTE Type:3; - BYTE Attribute:3; - BYTE Direction:2; - } Type; - HWORD Timeout; - BYTE CDB[16]; -} RequestBlock_struct; -typedef struct _ErrDescriptor_struct { - QWORD Addr; - DWORD Len; -} ErrDescriptor_struct; -typedef struct _SGDescriptor_struct { - QWORD Addr; - DWORD Len; - DWORD Ext; -} SGDescriptor_struct; - -typedef union _MoreErrInfo_struct{ - struct { - BYTE Reserved[3]; - BYTE Type; - DWORD ErrorInfo; - }Common_Info; - struct{ - BYTE Reserved[2]; - BYTE offense_size; /* size of offending entry */ - BYTE offense_num; /* byte # of offense 0-base */ - DWORD offense_value; - }Invalid_Cmd; -}MoreErrInfo_struct; -typedef struct _ErrorInfo_struct { - BYTE ScsiStatus; - BYTE SenseLen; - HWORD CommandStatus; - DWORD ResidualCnt; - MoreErrInfo_struct MoreErrInfo; - BYTE SenseInfo[SENSEINFOBYTES]; -} ErrorInfo_struct; - -/* Command types */ -#define CMD_RWREQ 0x00 -#define CMD_IOCTL_PEND 0x01 -#define CMD_SCSI 0x03 -#define CMD_MSG_DONE 0x04 -#define CMD_MSG_TIMEOUT 0x05 - -typedef struct _CommandList_struct { - CommandListHeader_struct Header; - RequestBlock_struct Request; - ErrDescriptor_struct ErrDesc; - SGDescriptor_struct SG[MAXSGENTRIES]; - /* information associated with the command */ - __u32 busaddr; /* physical address of this record */ - ErrorInfo_struct * err_info; /* pointer to the allocated mem */ - int ctlr; - int cmd_type; - struct _CommandList_struct *prev; - struct _CommandList_struct *next; - struct request * rq; - struct completion *waiting; - int retry_count; -#ifdef CONFIG_CISS_SCSI_TAPE - void * scsi_cmd; -#endif -} CommandList_struct; - -/* Configuration Table Structure */ -typedef struct _HostWrite_struct { - DWORD TransportRequest; - DWORD Reserved; - DWORD CoalIntDelay; - DWORD CoalIntCount; -} HostWrite_struct; - -typedef struct _CfgTable_struct { - BYTE Signature[4]; - DWORD SpecValence; - DWORD TransportSupport; - DWORD TransportActive; - HostWrite_struct HostWrite; - DWORD CmdsOutMax; - DWORD BusTypes; - DWORD Reserved; - BYTE ServerName[16]; - DWORD HeartBeat; -} CfgTable_struct; -#pragma pack() -#endif /* CCISS_CMD_H */ diff --git a/xen/drivers/block/cciss_scsi.c b/xen/drivers/block/cciss_scsi.c deleted file mode 100644 index f44a2010af..0000000000 --- a/xen/drivers/block/cciss_scsi.c +++ /dev/null @@ -1,1590 +0,0 @@ -/* - * Disk Array driver for HP SA 5xxx and 6xxx Controllers, SCSI Tape module - * Copyright 2001, 2002 Hewlett-Packard Development Company, L.P. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Questions/Comments/Bugfixes to Cciss-discuss@lists.sourceforge.net - * - * Author: Stephen M. Cameron - */ -#ifdef CONFIG_CISS_SCSI_TAPE - -/* Here we have code to present the driver as a scsi driver - as it is simultaneously presented as a block driver. The - reason for doing this is to allow access to SCSI tape drives - through the array controller. Note in particular, neither - physical nor logical disks are presented through the scsi layer. */ - -#include "../scsi/scsi.h" -#include "../scsi/hosts.h" -#include -#include - -#include "cciss_scsi.h" - -/* some prototypes... */ -static int sendcmd( - __u8 cmd, - int ctlr, - void *buff, - size_t size, - unsigned int use_unit_num, /* 0: address the controller, - 1: address logical volume log_unit, - 2: address is in scsi3addr */ - unsigned int log_unit, - __u8 page_code, - unsigned char *scsi3addr ); - - -int __init cciss_scsi_detect(Scsi_Host_Template *tpnt); -int cciss_scsi_release(struct Scsi_Host *sh); -const char *cciss_scsi_info(struct Scsi_Host *sa); - -int cciss_scsi_proc_info( - char *buffer, /* data buffer */ - char **start, /* where data in buffer starts */ - off_t offset, /* offset from start of imaginary file */ - int length, /* length of data in buffer */ - int hostnum, /* which host adapter (always zero for me) */ - int func); /* 0 == read, 1 == write */ - -int cciss_scsi_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)); -#if 0 -int cciss_scsi_abort(Scsi_Cmnd *cmd); -#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS -int cciss_scsi_reset(Scsi_Cmnd *cmd, unsigned int reset_flags); -#else -int cciss_scsi_reset(Scsi_Cmnd *cmd); -#endif -#endif - -static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR]; - -/* We need one Scsi_Host_Template *per controller* instead of - the usual one Scsi_Host_Template per controller *type*. This - is so PCI hot plug could have a remote possibility of still - working even with the SCSI system. It's so - scsi_unregister_module will differentiate the controllers. - When register_scsi_module is called, each host template is - customized (name change) in cciss_register_scsi() - (that's called from cciss.c:cciss_init_one()) */ - -static -Scsi_Host_Template driver_template[MAX_CTLR]; - -#pragma pack(1) -struct cciss_scsi_cmd_stack_elem_t { - CommandList_struct cmd; - ErrorInfo_struct Err; - __u32 busaddr; // 32 bits always, must fit through cmd register. -}; - -#pragma pack() - -#define CMD_STACK_SIZE (SCSI_CCISS_CAN_QUEUE * \ - CCISS_MAX_SCSI_DEVS_PER_HBA + 2) - // plus two for init time usage - -#pragma pack(1) -struct cciss_scsi_cmd_stack_t { - struct cciss_scsi_cmd_stack_elem_t *pool; - struct cciss_scsi_cmd_stack_elem_t *elem[CMD_STACK_SIZE]; - dma_addr_t cmd_pool_handle; - int top; -}; -#pragma pack() - -struct cciss_scsi_adapter_data_t { - struct Scsi_Host *scsi_host; - struct cciss_scsi_cmd_stack_t cmd_stack; - int registered; - spinlock_t lock; // to protect ccissscsi[ctlr]; -}; -#if 1 -#define CPQ_TAPE_LOCK(ctlr, flags) spin_lock_irqsave( \ - &(((struct cciss_scsi_adapter_data_t *) \ - hba[ctlr]->scsi_ctlr)->lock), flags); -#define CPQ_TAPE_UNLOCK(ctlr, flags) spin_unlock_irqrestore( \ - &(((struct cciss_scsi_adapter_data_t *) \ - hba[ctlr]->scsi_ctlr)->lock), flags); -#else -#define CPQ_TAPE_LOCK(x,y) -#define CPQ_TAPE_UNLOCK(x,y) -#endif - -static CommandList_struct * -scsi_cmd_alloc(ctlr_info_t *h) -{ - /* assume only one process in here at a time, locking done by caller. */ - - /* take the top memory chunk off the stack and return it, if any. */ - struct cciss_scsi_cmd_stack_elem_t *c; - struct cciss_scsi_adapter_data_t *sa; - struct cciss_scsi_cmd_stack_t *stk; - u64bit temp64; - - sa = (struct cciss_scsi_adapter_data_t *) h->scsi_ctlr; - stk = &sa->cmd_stack; - - if (stk->top < 0) - return NULL; - c = stk->elem[stk->top]; - memset(&c->cmd, 0, sizeof(c->cmd)); - memset(&c->Err, 0, sizeof(c->Err)); - /* set physical addr of cmd and addr of scsi parameters */ - c->cmd.busaddr = c->busaddr; - - temp64.val = (__u64) (c->busaddr + sizeof(CommandList_struct)); - stk->top--; - c->cmd.ErrDesc.Addr.lower = temp64.val32.lower; - c->cmd.ErrDesc.Addr.upper = temp64.val32.upper; - c->cmd.ErrDesc.Len = sizeof(ErrorInfo_struct); - - c->cmd.ctlr = h->ctlr; - c->cmd.err_info = &c->Err; - - return (CommandList_struct *) c; -} - -static void -scsi_cmd_free(ctlr_info_t *h, CommandList_struct *cmd) -{ - /* assume only one process in here at a time, locking done by caller. */ - /* drop the free memory chunk on top of the stack. */ - - struct cciss_scsi_adapter_data_t *sa; - struct cciss_scsi_cmd_stack_t *stk; - - sa = (struct cciss_scsi_adapter_data_t *) h->scsi_ctlr; - stk = &sa->cmd_stack; - if (stk->top >= CMD_STACK_SIZE) { - printk("cciss: scsi_cmd_free called too many times.\n"); - BUG(); - } - stk->top++; - stk->elem[stk->top] = (struct cciss_scsi_cmd_stack_elem_t *) cmd; -} - -static int -scsi_cmd_stack_setup(int ctlr) -{ - int i; - struct cciss_scsi_adapter_data_t *sa; - struct cciss_scsi_cmd_stack_t *stk; - size_t size; - - sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr; - stk = &sa->cmd_stack; - size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE; - - stk->pool = (struct cciss_scsi_cmd_stack_elem_t *) - pci_alloc_consistent(hba[ctlr]->pdev, size, &stk->cmd_pool_handle); - - if (stk->pool == NULL) { - printk("stk->pool is null\n"); - return -1; - } - - for (i=0; ielem[i] = &stk->pool[i]; - stk->elem[i]->busaddr = (__u32) (stk->cmd_pool_handle + - (sizeof(struct cciss_scsi_cmd_stack_elem_t) * i)); - } - stk->top = CMD_STACK_SIZE-1; - return 0; -} - -static void -scsi_cmd_stack_free(int ctlr) -{ - struct cciss_scsi_adapter_data_t *sa; - struct cciss_scsi_cmd_stack_t *stk; - size_t size; - - sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr; - stk = &sa->cmd_stack; - if (stk->top != CMD_STACK_SIZE-1) { - printk( "cciss: %d scsi commands are still outstanding.\n", - CMD_STACK_SIZE - stk->top); - // BUG(); - printk("WE HAVE A BUG HERE!!! stk=0x%08x\n", - (unsigned int) stk); - } - size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE; - - pci_free_consistent(hba[ctlr]->pdev, size, stk->pool, stk->cmd_pool_handle); - stk->pool = NULL; -} - -/* scsi_device_types comes from scsi.h */ -#define DEVICETYPE(n) (n<0 || n>MAX_SCSI_DEVICE_CODE) ? \ - "Unknown" : scsi_device_types[n] - -#if 0 -static int xmargin=8; -static int amargin=60; - -static void -print_bytes (unsigned char *c, int len, int hex, int ascii) -{ - - int i; - unsigned char *x; - - if (hex) - { - x = c; - for (i=0;i0) printk("\n"); - if ((i % xmargin) == 0) printk("0x%04x:", i); - printk(" %02x", *x); - x++; - } - printk("\n"); - } - if (ascii) - { - x = c; - for (i=0;i0) printk("\n"); - if ((i % amargin) == 0) printk("0x%04x:", i); - if (*x > 26 && *x < 128) printk("%c", *x); - else printk("."); - x++; - } - printk("\n"); - } -} - -static void -print_cmd(CommandList_struct *cp) -{ - printk("queue:%d\n", cp->Header.ReplyQueue); - printk("sglist:%d\n", cp->Header.SGList); - printk("sgtot:%d\n", cp->Header.SGTotal); - printk("Tag:0x%08x/0x%08x\n", cp->Header.Tag.upper, - cp->Header.Tag.lower); - printk("LUN:0x%02x%02x%02x%02x%02x%02x%02x%02x\n", - cp->Header.LUN.LunAddrBytes[0], - cp->Header.LUN.LunAddrBytes[1], - cp->Header.LUN.LunAddrBytes[2], - cp->Header.LUN.LunAddrBytes[3], - cp->Header.LUN.LunAddrBytes[4], - cp->Header.LUN.LunAddrBytes[5], - cp->Header.LUN.LunAddrBytes[6], - cp->Header.LUN.LunAddrBytes[7]); - printk("CDBLen:%d\n", cp->Request.CDBLen); - printk("Type:%d\n",cp->Request.Type.Type); - printk("Attr:%d\n",cp->Request.Type.Attribute); - printk(" Dir:%d\n",cp->Request.Type.Direction); - printk("Timeout:%d\n",cp->Request.Timeout); - printk( "CDB: %02x %02x %02x %02x %02x %02x %02x %02x" - " %02x %02x %02x %02x %02x %02x %02x %02x\n", - cp->Request.CDB[0], cp->Request.CDB[1], - cp->Request.CDB[2], cp->Request.CDB[3], - cp->Request.CDB[4], cp->Request.CDB[5], - cp->Request.CDB[6], cp->Request.CDB[7], - cp->Request.CDB[8], cp->Request.CDB[9], - cp->Request.CDB[10], cp->Request.CDB[11], - cp->Request.CDB[12], cp->Request.CDB[13], - cp->Request.CDB[14], cp->Request.CDB[15]), - printk("edesc.Addr: 0x%08x/0%08x, Len = %d\n", - cp->ErrDesc.Addr.upper, cp->ErrDesc.Addr.lower, - cp->ErrDesc.Len); - printk("sgs..........Errorinfo:\n"); - printk("scsistatus:%d\n", cp->err_info->ScsiStatus); - printk("senselen:%d\n", cp->err_info->SenseLen); - printk("cmd status:%d\n", cp->err_info->CommandStatus); - printk("resid cnt:%d\n", cp->err_info->ResidualCnt); - printk("offense size:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_size); - printk("offense byte:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_num); - printk("offense value:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_value); - -} - -#endif - -static int -find_bus_target_lun(int ctlr, int *bus, int *target, int *lun) -{ - /* finds an unused bus, target, lun for a new device */ - /* assumes hba[ctlr]->scsi_ctlr->lock is held */ - int i, found=0; - unsigned char target_taken[CCISS_MAX_SCSI_DEVS_PER_HBA]; - - memset(&target_taken[0], 0, CCISS_MAX_SCSI_DEVS_PER_HBA); - -# if SELF_SCSI_ID >= 0 - target_taken[SELF_SCSI_ID] = 1; -# endif - for (i=0;iscsi_ctlr->lock is held */ - int n = ccissscsi[ctlr].ndevices; - struct cciss_scsi_dev_t *sd; - - if (n >= CCISS_MAX_SCSI_DEVS_PER_HBA) { - printk("cciss%d: Too many devices, " - "some will be inaccessible.\n", ctlr); - return -1; - } - sd = &ccissscsi[ctlr].dev[n]; - if (find_bus_target_lun(ctlr, &sd->bus, &sd->target, &sd->lun) != 0) - return -1; - memcpy(&sd->scsi3addr[0], scsi3addr, 8); - sd->devtype = devtype; - ccissscsi[ctlr].ndevices++; - - /* initially, (before registering with scsi layer) we don't - know our hostno and we don't want to print anything first - time anyway (the scsi layer's inquiries will show that info) */ - if (hostno != -1) - printk("cciss%d: %s device c%db%dt%dl%d added.\n", - ctlr, DEVICETYPE(sd->devtype), hostno, - sd->bus, sd->target, sd->lun); - return 0; -} - -static void -cciss_scsi_remove_entry(int ctlr, int hostno, int entry) -{ - /* assumes hba[ctlr]->scsi_ctlr->lock is held */ - int i; - struct cciss_scsi_dev_t sd; - - if (entry < 0 || entry >= CCISS_MAX_SCSI_DEVS_PER_HBA) return; - sd = ccissscsi[ctlr].dev[entry]; - for (i=entry;iscsi3addr)) { - if (sd[j].devtype == csd->devtype) - found=2; - else - found=1; - break; - } - } - - if (found == 0) { /* device no longer present. */ - changes++; - /* printk("cciss%d: %s device c%db%dt%dl%d removed.\n", - ctlr, DEVICETYPE(csd->devtype), hostno, - csd->bus, csd->target, csd->lun); */ - cciss_scsi_remove_entry(ctlr, hostno, i); - /* note, i not incremented */ - } - else if (found == 1) { /* device is different kind */ - changes++; - printk("cciss%d: device c%db%dt%dl%d type changed " - "(device type now %s).\n", - ctlr, hostno, csd->bus, csd->target, csd->lun, - DEVICETYPE(csd->devtype)); - csd->devtype = sd[j].devtype; - i++; /* so just move along. */ - } else /* device is same as it ever was, */ - i++; /* so just move along. */ - } - - /* Now, make sure every device listed in sd[] is also - listed in ccissscsi[], adding them if they aren't found */ - - for (i=0;iscsi3addr)) { - if (sd[i].devtype == csd->devtype) - found=2; /* found device */ - else - found=1; /* found a bug. */ - break; - } - } - if (!found) { - changes++; - if (cciss_scsi_add_entry(ctlr, hostno, - &sd[i].scsi3addr[0], sd[i].devtype) != 0) - break; - } else if (found == 1) { - /* should never happen... */ - changes++; - printk("cciss%d: device unexpectedly changed type\n", - ctlr); - /* but if it does happen, we just ignore that device */ - } - } - CPQ_TAPE_UNLOCK(ctlr, flags); - - if (!changes) - printk("cciss%d: No device changes detected.\n", ctlr); - - return 0; -} - -static int -lookup_scsi3addr(int ctlr, int bus, int target, int lun, char *scsi3addr) -{ - int i; - struct cciss_scsi_dev_t *sd; - unsigned long flags; - - CPQ_TAPE_LOCK(ctlr, flags); - for (i=0;ibus == bus && - sd->target == target && - sd->lun == lun) { - memcpy(scsi3addr, &sd->scsi3addr[0], 8); - CPQ_TAPE_UNLOCK(ctlr, flags); - return 0; - } - } - CPQ_TAPE_UNLOCK(ctlr, flags); - return -1; -} - - -static void -cciss_find_non_disk_devices(int cntl_num) -{ - ReportLunData_struct *ld_buff; - InquiryData_struct *inq_buff; - int return_code; - int i; - int listlength = 0; - int num_luns; - unsigned char scsi3addr[8]; - unsigned long flags; - int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8; - - hba[cntl_num]->scsi_ctlr = (void *) - kmalloc(sizeof(struct cciss_scsi_adapter_data_t), - GFP_KERNEL); - if (hba[cntl_num]->scsi_ctlr == NULL) - return; - - ((struct cciss_scsi_adapter_data_t *) - hba[cntl_num]->scsi_ctlr)->scsi_host = NULL; - ((struct cciss_scsi_adapter_data_t *) - hba[cntl_num]->scsi_ctlr)->lock = SPIN_LOCK_UNLOCKED; - ((struct cciss_scsi_adapter_data_t *) - hba[cntl_num]->scsi_ctlr)->registered = 0; - - if (scsi_cmd_stack_setup(cntl_num) != 0) { - printk("Trouble, returned non-zero!\n"); - return; - } - - ld_buff = kmalloc(reportlunsize, GFP_KERNEL); - if (ld_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - return; - } - memset(ld_buff, 0, sizeof(ReportLunData_struct)); - inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); - if (inq_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - kfree(ld_buff); - return; - } - - /* Get the physical luns */ - return_code = sendcmd(CISS_REPORT_PHYS, cntl_num, ld_buff, - reportlunsize, 0, 0, 0, NULL ); - - if( return_code == IO_OK) { - unsigned char *c = &ld_buff->LUNListLength[0]; - listlength = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; - } - else { /* getting report of physical luns failed */ - printk(KERN_WARNING "cciss: report physical luns" - " command failed\n"); - listlength = 0; - } - - CPQ_TAPE_LOCK(cntl_num, flags); - ccissscsi[cntl_num].ndevices = 0; - num_luns = listlength / 8; // 8 bytes pre entry - /* printk("Found %d LUNs\n", num_luns); */ - - if (num_luns > CISS_MAX_PHYS_LUN) - { - printk(KERN_WARNING - "cciss: Maximum physical LUNs (%d) exceeded. " - "%d LUNs ignored.\n", CISS_MAX_PHYS_LUN, - num_luns - CISS_MAX_PHYS_LUN); - num_luns = CISS_MAX_PHYS_LUN; - } - - for(i=0; iLUN[i], 8); /* ugly... */ - return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff, - sizeof(InquiryData_struct), 2, 0 ,0, scsi3addr ); - if (return_code == IO_OK) { - if(inq_buff->data_byte[8] == 0xFF) - { - printk(KERN_WARNING "cciss: inquiry failed\n"); - } else { - int devtype; - - /* printk("Inquiry...\n"); - print_bytes((unsigned char *) inq_buff, 36, 1, 1); */ - devtype = (inq_buff->data_byte[0] & 0x1f); - - switch (devtype) - { - case 0x01: /* sequential access, (tape) */ - case 0x08: /* medium changer */ - /* this is the only kind of dev */ - /* we want to expose here. */ - if (cciss_scsi_add_entry(cntl_num, -1, - (unsigned char *) ld_buff->LUN[i], - devtype) != 0) - i=num_luns; // leave loop - break; - default: - break; - } - - } - } - else printk("cciss: inquiry failed.\n"); - } -#if 0 - for (i=0;ierr_info; - - /* First, see if it was a message rather than a command */ - if (cp->Request.Type.Type == TYPE_MSG) { - cp->cmd_type = CMD_MSG_DONE; - return; - } - - /* we stored ptr to scsi cmd in the buffer head pointer */ - cmd = (Scsi_Cmnd *) cp->scsi_cmd; - ctlr = hba[cp->ctlr]; - - /* undo the DMA mappings */ - - if (cmd->use_sg) { - pci_unmap_sg(ctlr->pdev, - cmd->buffer, cmd->use_sg, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); - } - else if (cmd->request_bufflen) { - addr64.val32.lower = cp->SG[0].Addr.lower; - addr64.val32.upper = cp->SG[0].Addr.upper; - pci_unmap_single(ctlr->pdev, (dma_addr_t) addr64.val, - cmd->request_bufflen, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); - } - - cmd->result = (DID_OK << 16); /* host byte */ - cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */ - /* cmd->result |= (GOOD < 1); */ /* status byte */ - - cmd->result |= (ei->ScsiStatus); - /* printk("Scsistatus is 0x%02x\n", ei->ScsiStatus); */ - - /* copy the sense data whether we need to or not. */ - - memcpy(cmd->sense_buffer, ei->SenseInfo, - ei->SenseLen > SCSI_SENSE_BUFFERSIZE ? - SCSI_SENSE_BUFFERSIZE : - ei->SenseLen); - cmd->resid = ei->ResidualCnt; - - if(ei->CommandStatus != 0) - { /* an error has occurred */ - switch(ei->CommandStatus) - { - case CMD_TARGET_STATUS: - /* Pass it up to the upper layers... */ - if( ei->ScsiStatus) - cmd->result |= (ei->ScsiStatus < 1); - else { /* scsi status is zero??? How??? */ - - /* Ordinarily, this case should never happen, but there is a bug - in some released firmware revisions that allows it to happen - if, for example, a 4100 backplane loses power and the tape - drive is in it. We assume that it's a fatal error of some - kind because we can't show that it wasn't. We will make it - look like selection timeout since that is the most common - reason for this to occur, and it's severe enough. */ - - cmd->result = DID_NO_CONNECT << 16; - } - break; - case CMD_DATA_UNDERRUN: /* let mid layer handle it. */ - break; - case CMD_DATA_OVERRUN: - printk(KERN_WARNING "cciss: cp %p has" - " completed with data overrun " - "reported\n", cp); - break; - case CMD_INVALID: { - /* print_bytes(cp, sizeof(*cp), 1, 0); - print_cmd(cp); */ - /* We get CMD_INVALID if you address a non-existent tape drive instead - of a selection timeout (no response). You will see this if you yank - out a tape drive, then try to access it. This is kind of a shame - because it means that any other CMD_INVALID (e.g. driver bug) will - get interpreted as a missing target. */ - cmd->result = DID_NO_CONNECT << 16; - } - break; - case CMD_PROTOCOL_ERR: - printk(KERN_WARNING "cciss: cp %p has " - "protocol error \n", cp); - break; - case CMD_HARDWARE_ERR: - cmd->result = DID_ERROR << 16; - printk(KERN_WARNING "cciss: cp %p had " - " hardware error\n", cp); - break; - case CMD_CONNECTION_LOST: - cmd->result = DID_ERROR << 16; - printk(KERN_WARNING "cciss: cp %p had " - "connection lost\n", cp); - break; - case CMD_ABORTED: - cmd->result = DID_ABORT << 16; - printk(KERN_WARNING "cciss: cp %p was " - "aborted\n", cp); - break; - case CMD_ABORT_FAILED: - cmd->result = DID_ERROR << 16; - printk(KERN_WARNING "cciss: cp %p reports " - "abort failed\n", cp); - break; - case CMD_UNSOLICITED_ABORT: - cmd->result = DID_ABORT << 16; - printk(KERN_WARNING "cciss: cp %p aborted " - "do to an unsolicited abort\n", cp); - break; - case CMD_TIMEOUT: - cmd->result = DID_TIME_OUT << 16; - printk(KERN_WARNING "cciss: cp %p timedout\n", - cp); - break; - default: - cmd->result = DID_ERROR << 16; - printk(KERN_WARNING "cciss: cp %p returned " - "unknown status %x\n", cp, - ei->CommandStatus); - } - } - cmd->scsi_done(cmd); - scsi_cmd_free(ctlr, cp); -} - -/* cciss_scsi_detect is called from the scsi mid layer. - The scsi mid layer (scsi_register_module) is - called from cciss.c:cciss_init_one(). */ - -int __init -cciss_scsi_detect(Scsi_Host_Template *tpnt) -{ - int i; - struct Scsi_Host *sh; - - /* Tell the kernel we want to be a SCSI driver... */ - sh = scsi_register(tpnt, sizeof(struct ctlr_info *)); - if (sh == NULL) return 0; - - sh->io_port = 0; // good enough? FIXME, - sh->n_io_port = 0; // I don't think we use these two... - - sh->this_id = SELF_SCSI_ID; - - i = simple_strtol((char *)&tpnt->name[5], NULL, 10); - - if (i<0 || i>=MAX_CTLR || hba[i] == NULL) { - /* we didn't find ourself... we shouldn't get here. */ - printk("cciss_scsi_detect: could not find ourself in hba[]\n"); - return 0; - } - - ((struct cciss_scsi_adapter_data_t *) - hba[i]->scsi_ctlr)->scsi_host = (void *) sh; - sh->hostdata[0] = (unsigned long) hba[i]; - sh->irq = hba[i]->intr; - sh->unique_id = sh->irq; - scsi_set_pci_device(sh, hba[i]->pdev); - - return 1; /* Say we have 1 scsi adapter, this will be */ - /* called multiple times, once for each adapter */ - /* from cciss.c:cciss_init_one(). We do it this */ - /* way for PCI-hot plug reasons. (we don't know how */ - /* many adapters we have total, so we say we have */ - /* 1, each of a unique type.) */ -} - -static void __exit cleanup_cciss_module(void); -int -cciss_scsi_release(struct Scsi_Host *sh) -{ - return 0; -} - -static void -cciss_unmap_one(struct pci_dev *pdev, - CommandList_struct *cp, - size_t buflen, - int data_direction) -{ - u64bit addr64; - - addr64.val32.lower = cp->SG[0].Addr.lower; - addr64.val32.upper = cp->SG[0].Addr.upper; - pci_unmap_single(pdev, (dma_addr_t) addr64.val, buflen, data_direction); -} - -static void -cciss_map_one(struct pci_dev *pdev, - CommandList_struct *cp, - unsigned char *buf, - size_t buflen, - int data_direction) -{ - __u64 addr64; - - addr64 = (__u64) pci_map_single(pdev, buf, buflen, data_direction); - cp->SG[0].Addr.lower = - (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF); - cp->SG[0].Addr.upper = - (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF); - cp->SG[0].Len = buflen; - cp->Header.SGList = (__u8) 1; /* no. SGs contig in this cmd */ - cp->Header.SGTotal = (__u16) 1; /* total sgs in this cmd list */ -} - -static int -cciss_scsi_do_simple_cmd(ctlr_info_t *c, - CommandList_struct *cp, - unsigned char *scsi3addr, - unsigned char *cdb, - unsigned char cdblen, - unsigned char *buf, int bufsize, - int direction) -{ - unsigned long flags; - DECLARE_COMPLETION(wait); - - cp->cmd_type = CMD_IOCTL_PEND; // treat this like an ioctl - cp->scsi_cmd = NULL; - cp->Header.ReplyQueue = 0; // unused in simple mode - memcpy(&cp->Header.LUN, scsi3addr, sizeof(cp->Header.LUN)); - cp->Header.Tag.lower = cp->busaddr; // Use k. address of cmd as tag - // Fill in the request block... - - /* printk("Using scsi3addr 0x%02x%0x2%0x2%0x2%0x2%0x2%0x2%0x2\n", - scsi3addr[0], scsi3addr[1], scsi3addr[2], scsi3addr[3], - scsi3addr[4], scsi3addr[5], scsi3addr[6], scsi3addr[7]); */ - - memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB)); - memcpy(cp->Request.CDB, cdb, cdblen); - cp->Request.Timeout = 0; // No timeout - cp->Request.CDBLen = cdblen; - cp->Request.Type.Type = TYPE_CMD; - cp->Request.Type.Attribute = ATTR_SIMPLE; - cp->Request.Type.Direction = direction; - - /* Fill in the SG list and do dma mapping */ - cciss_map_one(c->pdev, cp, - (unsigned char *) buf, bufsize, - scsi_to_pci_dma_dir(SCSI_DATA_READ)); - - cp->waiting = &wait; - - /* Put the request on the tail of the request queue */ - spin_lock_irqsave(&io_request_lock, flags); - addQ(&c->reqQ, cp); - c->Qdepth++; - start_io(c); - spin_unlock_irqrestore(&io_request_lock, flags); - - wait_for_completion(&wait); - - /* undo the dma mapping */ - cciss_unmap_one(c->pdev, cp, bufsize, - scsi_to_pci_dma_dir(SCSI_DATA_READ)); - - return(0); -} - -static void -cciss_scsi_interpret_error(CommandList_struct *cp) -{ - ErrorInfo_struct *ei; - - ei = cp->err_info; - switch(ei->CommandStatus) - { - case CMD_TARGET_STATUS: - printk(KERN_WARNING "cciss: cmd %p has " - "completed with errors\n", cp); - printk(KERN_WARNING "cciss: cmd %p " - "has SCSI Status = %x\n", - cp, - ei->ScsiStatus); - if (ei->ScsiStatus == 0) - printk(KERN_WARNING - "cciss:SCSI status is abnormally zero. " - "(probably indicates selection timeout " - "reported incorrectly due to a known " - "firmware bug, circa July, 2001.)\n"); - break; - case CMD_DATA_UNDERRUN: /* let mid layer handle it. */ - printk("UNDERRUN\n"); - break; - case CMD_DATA_OVERRUN: - printk(KERN_WARNING "cciss: cp %p has" - " completed with data overrun " - "reported\n", cp); - break; - case CMD_INVALID: { - /* controller unfortunately reports SCSI passthru's */ - /* to non-existent targets as invalid commands. */ - printk(KERN_WARNING "cciss: cp %p is " - "reported invalid (probably means " "target device no longer present)\n", - cp); - /* print_bytes((unsigned char *) cp, sizeof(*cp), 1, 0); - print_cmd(cp); */ - } - break; - case CMD_PROTOCOL_ERR: - printk(KERN_WARNING "cciss: cp %p has " - "protocol error \n", cp); - break; - case CMD_HARDWARE_ERR: - /* cmd->result = DID_ERROR << 16; */ - printk(KERN_WARNING "cciss: cp %p had " - " hardware error\n", cp); - break; - case CMD_CONNECTION_LOST: - printk(KERN_WARNING "cciss: cp %p had " - "connection lost\n", cp); - break; - case CMD_ABORTED: - printk(KERN_WARNING "cciss: cp %p was " - "aborted\n", cp); - break; - case CMD_ABORT_FAILED: - printk(KERN_WARNING "cciss: cp %p reports " - "abort failed\n", cp); - break; - case CMD_UNSOLICITED_ABORT: - printk(KERN_WARNING "cciss: cp %p aborted " - "do to an unsolicited abort\n", cp); - break; - case CMD_TIMEOUT: - printk(KERN_WARNING "cciss: cp %p timedout\n", - cp); - break; - default: - printk(KERN_WARNING "cciss: cp %p returned " - "unknown status %x\n", cp, - ei->CommandStatus); - } -} - -static int -cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, - InquiryData_struct *buf) -{ - int rc; - CommandList_struct *cp; - char cdb[6]; - ErrorInfo_struct *ei; - - cp = scsi_cmd_alloc(c); - ei = cp->err_info; - - if (cp == NULL) { /* trouble... */ - printk("cmd_alloc returned NULL!\n"); - return -1; - } - - cdb[0] = CISS_INQUIRY; - cdb[1] = 0; - cdb[2] = 0; - cdb[3] = 0; - cdb[4] = sizeof(*buf) & 0xff; - cdb[5] = 0; - rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, cdb, - 6, (unsigned char *) buf, - sizeof(*buf), XFER_READ); - - if (rc != 0) return rc; /* something went wrong */ - - if (ei->CommandStatus != 0 && - ei->CommandStatus != CMD_DATA_UNDERRUN) { - cciss_scsi_interpret_error(cp); - scsi_cmd_free(c, cp); - return -1; - } - scsi_cmd_free(c, cp); - return 0; -} - -static int -cciss_scsi_do_report_phys_luns(ctlr_info_t *c, - ReportLunData_struct *buf, int bufsize) -{ - int rc; - CommandList_struct *cp; - unsigned char cdb[12]; - unsigned char scsi3addr[8]; - ErrorInfo_struct *ei; - - cp = scsi_cmd_alloc(c); - if (cp == NULL) { /* trouble... */ - printk("cmd_alloc returned NULL!\n"); - return -1; - } - - memset(&scsi3addr[0], 0, 8); /* address the controller */ - cdb[0] = CISS_REPORT_PHYS; - cdb[1] = 0; - cdb[2] = 0; - cdb[3] = 0; - cdb[4] = 0; - cdb[5] = 0; - cdb[6] = (bufsize >> 24) & 0xFF; //MSB - cdb[7] = (bufsize >> 16) & 0xFF; - cdb[8] = (bufsize >> 8) & 0xFF; - cdb[9] = bufsize & 0xFF; - cdb[10] = 0; - cdb[11] = 0; - - rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, - cdb, 12, - (unsigned char *) buf, - bufsize, XFER_READ); - - if (rc != 0) return rc; /* something went wrong */ - - ei = cp->err_info; - if (ei->CommandStatus != 0 && - ei->CommandStatus != CMD_DATA_UNDERRUN) { - cciss_scsi_interpret_error(cp); - scsi_cmd_free(c, cp); - return -1; - } - scsi_cmd_free(c, cp); - return 0; -} - -static void -cciss_update_non_disk_devices(int cntl_num, int hostno) -{ - /* the idea here is we could get notified from /proc - that some devices have changed, so we do a report - physical luns cmd, and adjust our list of devices - accordingly. (We can't rely on the scsi-mid layer just - doing inquiries, because the "busses" that the scsi - mid-layer probes are totally fabricated by this driver, - so new devices wouldn't show up. - - the scsi3addr's of devices won't change so long as the - adapter is not reset. That means we can rescan and - tell which devices we already know about, vs. new - devices, vs. disappearing devices. - - Also, if you yank out a tape drive, then put in a disk - in it's place, (say, a configured volume from another - array controller for instance) _don't_ poke this driver - (so it thinks it's still a tape, but _do_ poke the scsi - mid layer, so it does an inquiry... the scsi mid layer - could see the physical disk. This would be bad. Need to - think about how to prevent that. One idea would be to - snoop all scsi responses and if an inquiry repsonse comes - back that reports a disk, chuck it an return selection - timeout instead and adjust our table... Not sure i like - that though. - - */ - - ReportLunData_struct *ld_buff; - InquiryData_struct *inq_buff; - unsigned char scsi3addr[8]; - ctlr_info_t *c; - __u32 num_luns=0; - unsigned char *ch; - /* unsigned char found[CCISS_MAX_SCSI_DEVS_PER_HBA]; */ - struct cciss_scsi_dev_t currentsd[CCISS_MAX_SCSI_DEVS_PER_HBA]; - int ncurrent=0; - int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8; - int i; - - c = (ctlr_info_t *) hba[cntl_num]; - ld_buff = kmalloc(reportlunsize, GFP_KERNEL); - if (ld_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - return; - } - memset(ld_buff, 0, reportlunsize); - inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); - if (inq_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - kfree(ld_buff); - return; - } - - if (cciss_scsi_do_report_phys_luns(c, ld_buff, reportlunsize) == 0) { - ch = &ld_buff->LUNListLength[0]; - num_luns = ((ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | ch[3]) / 8; - if (num_luns > CISS_MAX_PHYS_LUN) { - printk(KERN_WARNING - "cciss: Maximum physical LUNs (%d) exceeded. " - "%d LUNs ignored.\n", CISS_MAX_PHYS_LUN, - num_luns - CISS_MAX_PHYS_LUN); - num_luns = CISS_MAX_PHYS_LUN; - } - } - else { - printk(KERN_ERR "cciss: Report physical LUNs failed.\n"); - return; - } - - - /* adjust our table of devices */ - for(i=0; iLUN[i][0], 8); - - if (cciss_scsi_do_inquiry(hba[cntl_num], - scsi3addr, inq_buff) != 0) - { - /* Inquiry failed (msg printed already) */ - devtype = 0; /* so we will skip this device. */ - } else /* what kind of device is this? */ - devtype = (inq_buff->data_byte[0] & 0x1f); - - switch (devtype) - { - case 0x01: /* sequential access, (tape) */ - case 0x08: /* medium changer */ - if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) { - printk(KERN_INFO "cciss%d: %s ignored, " - "too many devices.\n", cntl_num, - DEVICETYPE(devtype)); - break; - } - memcpy(¤tsd[ncurrent].scsi3addr[0], - &scsi3addr[0], 8); - currentsd[ncurrent].devtype = devtype; - currentsd[ncurrent].bus = -1; - currentsd[ncurrent].target = -1; - currentsd[ncurrent].lun = -1; - ncurrent++; - break; - default: - break; - } - } - - adjust_cciss_scsi_table(cntl_num, hostno, currentsd, ncurrent); - - kfree(inq_buff); - kfree(ld_buff); - return; -} - -static int -is_keyword(char *ptr, int len, char *verb) // Thanks to ncr53c8xx.c -{ - int verb_len = strlen(verb); - if (len >= verb_len && !memcmp(verb,ptr,verb_len)) - return verb_len; - else - return 0; -} - -static int -cciss_scsi_user_command(int ctlr, int hostno, char *buffer, int length) -{ - int arg_len; - - if ((arg_len = is_keyword(buffer, length, "rescan")) != 0) - cciss_update_non_disk_devices(ctlr, hostno); - else - return -EINVAL; - return length; -} - -/* It's a pity that we need this, but, we do... */ -extern struct Scsi_Host *scsi_hostlist; /* from ../scsi/hosts.c */ - -int -cciss_scsi_proc_info(char *buffer, /* data buffer */ - char **start, /* where data in buffer starts */ - off_t offset, /* offset from start of imaginary file */ - int length, /* length of data in buffer */ - int hostnum, /* which host adapter (always zero for me) */ - int func) /* 0 == read, 1 == write */ -{ - - int buflen, datalen; - struct Scsi_Host *sh; - int found; - ctlr_info_t *ci; - int cntl_num; - - /* Lets see if we can find our Scsi_Host... - this might be kind of "bad", searching scis_hostlist this way - but how else can we find the scsi host? I think I've seen - this coded both ways, (circular list and null terminated list) - I coded it to work either way, since I wasn't sure. */ - - sh = scsi_hostlist; - found=0; - do { - if (sh == NULL) break; - if (sh->host_no == hostnum) { - found++; - break; - } - sh = sh->next; - } while (sh != scsi_hostlist && sh != NULL); - - if (sh == NULL || found == 0) /* This really shouldn't ever happen. */ - return -EINVAL; - - ci = (ctlr_info_t *) sh->hostdata[0]; - if (ci == NULL) /* This really shouldn't ever happen. */ - return -EINVAL; - - cntl_num = ci->ctlr; /* Get our index into the hba[] array */ - - if (func == 0) { /* User is reading from /proc/scsi/ciss*?/?* */ - buflen = sprintf(buffer, "hostnum=%d\n", hostnum); - - datalen = buflen - offset; - if (datalen < 0) { /* they're reading past EOF. */ - datalen = 0; - *start = buffer+buflen; - } else - *start = buffer + offset; - return(datalen); - } else /* User is writing to /proc/scsi/cciss*?/?* ... */ - return cciss_scsi_user_command(cntl_num, hostnum, - buffer, length); -} - -/* this is via the generic proc support */ -const char * -cciss_scsi_info(struct Scsi_Host *sa) -{ - static char buf[300]; - ctlr_info_t *ci; - - /* probably need to work on putting a bit more info in here... */ - /* this is output via the /proc filesystem. */ - - ci = (ctlr_info_t *) sa->hostdata[0]; - - sprintf(buf, "%s %c%c%c%c\n", - ci->product_name, - ci->firm_ver[0], - ci->firm_ver[1], - ci->firm_ver[2], - ci->firm_ver[3]); - - return buf; -} - - -/* cciss_scatter_gather takes a Scsi_Cmnd, (cmd), and does the pci - dma mapping and fills in the scatter gather entries of the - cciss command, cp. */ - -static void -cciss_scatter_gather(struct pci_dev *pdev, - CommandList_struct *cp, - Scsi_Cmnd *cmd) -{ - unsigned int use_sg, nsegs=0, len; - struct scatterlist *scatter = (struct scatterlist *) cmd->buffer; - __u64 addr64; - - /* is it just one virtual address? */ - if (!cmd->use_sg) { - if (cmd->request_bufflen) { /* anything to xfer? */ - - addr64 = (__u64) pci_map_single(pdev, - cmd->request_buffer, - cmd->request_bufflen, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); - - cp->SG[0].Addr.lower = - (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF); - cp->SG[0].Addr.upper = - (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF); - cp->SG[0].Len = cmd->request_bufflen; - nsegs=1; - } - } /* else, must be a list of virtual addresses.... */ - else if (cmd->use_sg <= MAXSGENTRIES) { /* not too many addrs? */ - - use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); - - for (nsegs=0; nsegs < use_sg; nsegs++) { - addr64 = (__u64) sg_dma_address(&scatter[nsegs]); - len = sg_dma_len(&scatter[nsegs]); - cp->SG[nsegs].Addr.lower = - (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF); - cp->SG[nsegs].Addr.upper = - (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF); - cp->SG[nsegs].Len = len; - cp->SG[nsegs].Ext = 0; // we are not chaining - } - } else BUG(); - - cp->Header.SGList = (__u8) nsegs; /* no. SGs contig in this cmd */ - cp->Header.SGTotal = (__u16) nsegs; /* total sgs in this cmd list */ - return; -} - - -int -cciss_scsi_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) -{ - ctlr_info_t **c; - int ctlr, rc; - unsigned char scsi3addr[8]; - CommandList_struct *cp; - - // Get the ptr to our adapter structure (hba[i]) out of cmd->host. - // We violate cmd->host privacy here. (Is there another way?) - c = (ctlr_info_t **) &cmd->host->hostdata[0]; - ctlr = (*c)->ctlr; - - rc = lookup_scsi3addr(ctlr, cmd->channel, cmd->target, cmd->lun, - scsi3addr); - if (rc != 0) { - /* the scsi nexus does not match any that we presented... */ - /* pretend to mid layer that we got selection timeout */ - cmd->result = DID_NO_CONNECT << 16; - done(cmd); - /* we might want to think about registering controller itself - as a processor device on the bus so sg binds to it. */ - return 0; - } - - // printk("cciss_queue_command, p=%p, cmd=0x%02x, c%db%dt%dl%d\n", - // cmd, cmd->cmnd[0], ctlr, cmd->channel, cmd->target, cmd->lun); - - /* Ok, we have a reasonable scsi nexus, so send the cmd down, and - see what the device thinks of it. */ - - cp = scsi_cmd_alloc(*c); - if (cp == NULL) { /* trouble... */ - printk("scsi_cmd_alloc returned NULL!\n"); - /* FIXME: next 3 lines are -> BAD! <- */ - cmd->result = DID_NO_CONNECT << 16; - done(cmd); - return 0; - } - - // Fill in the command list header - - cmd->scsi_done = done; // save this for use by completion code - - // save cp in case we have to abort it - cmd->host_scribble = (unsigned char *) cp; - - cp->cmd_type = CMD_SCSI; - cp->scsi_cmd = cmd; - cp->Header.ReplyQueue = 0; // unused in simple mode - memcpy(&cp->Header.LUN.LunAddrBytes[0], &scsi3addr[0], 8); - cp->Header.Tag.lower = cp->busaddr; // Use k. address of cmd as tag - - // Fill in the request block... - - cp->Request.Timeout = 0; // No timeout - memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB)); - if (cmd->cmd_len > sizeof(cp->Request.CDB)) BUG(); - cp->Request.CDBLen = cmd->cmd_len; - memcpy(cp->Request.CDB, cmd->cmnd, cmd->cmd_len); - cp->Request.Type.Type = TYPE_CMD; - cp->Request.Type.Attribute = ATTR_SIMPLE; - switch(cmd->sc_data_direction) - { - case SCSI_DATA_WRITE: cp->Request.Type.Direction = XFER_WRITE; break; - case SCSI_DATA_READ: cp->Request.Type.Direction = XFER_READ; break; - case SCSI_DATA_NONE: cp->Request.Type.Direction = XFER_NONE; break; - - case SCSI_DATA_UNKNOWN: - // This can happen if a buggy application does a scsi passthru - // and sets both inlen and outlen to non-zero. ( see - // ../scsi/scsi_ioctl.c:scsi_ioctl_send_command() ) - - cp->Request.Type.Direction = XFER_RSVD; - // This is technically wrong, and cciss controllers should - // reject it with CMD_INVALID, which is the most correct - // response, but non-fibre backends appear to let it - // slide by, and give the same results as if this field - // were set correctly. Either way is acceptable for - // our purposes here. - - break; - - default: - printk("cciss: unknown data direction: %d\n", - cmd->sc_data_direction); - BUG(); - break; - } - - cciss_scatter_gather((*c)->pdev, cp, cmd); // Fill the SG list - - /* Put the request on the tail of the request queue */ - - addQ(&(*c)->reqQ, cp); - (*c)->Qdepth++; - start_io(*c); - - /* the cmd'll come back via intr handler in complete_scsi_command() */ - return 0; -} - -static void -init_driver_template(int ctlr) -{ - memset(&driver_template[ctlr], 0, sizeof(driver_template[ctlr])); - driver_template[ctlr].name = ccissscsi[ctlr].name; - driver_template[ctlr].proc_name = ccissscsi[ctlr].name; - driver_template[ctlr].detect = cciss_scsi_detect; - driver_template[ctlr].release = cciss_scsi_release; - driver_template[ctlr].proc_info = cciss_scsi_proc_info; - driver_template[ctlr].queuecommand = cciss_scsi_queue_command; - driver_template[ctlr].eh_abort_handler = NULL; - driver_template[ctlr].eh_device_reset_handler = NULL; - driver_template[ctlr].bios_param = scsicam_bios_param; - driver_template[ctlr].can_queue = SCSI_CCISS_CAN_QUEUE; - driver_template[ctlr].this_id = SELF_SCSI_ID; - driver_template[ctlr].sg_tablesize = MAXSGENTRIES; - driver_template[ctlr].cmd_per_lun = 1; - driver_template[ctlr].use_new_eh_code = 1; - driver_template[ctlr].use_clustering = DISABLE_CLUSTERING; - driver_template[ctlr].module = THIS_MODULE; - - /* set scsi_host to NULL so our detect routine will - find us on register */ - - ((struct cciss_scsi_adapter_data_t *) - hba[ctlr]->scsi_ctlr)->scsi_host = NULL; - -} - -static void -cciss_unregister_scsi(int ctlr) -{ - struct cciss_scsi_adapter_data_t *sa; - struct cciss_scsi_cmd_stack_t *stk; - unsigned long flags; - - /* we are being forcibly unloaded, and may not refuse. */ - - spin_lock_irqsave(&io_request_lock, flags); - sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr; - stk = &sa->cmd_stack; - - /* if we weren't ever actually registered, don't unregister */ - if (((struct cciss_scsi_adapter_data_t *) - hba[ctlr]->scsi_ctlr)->registered) { - spin_unlock_irqrestore(&io_request_lock, flags); - scsi_unregister_module(MODULE_SCSI_HA, &driver_template[ctlr]); - spin_lock_irqsave(&io_request_lock, flags); - } - init_driver_template(ctlr); - scsi_cmd_stack_free(ctlr); - kfree(hba[ctlr]->scsi_ctlr); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -static int -cciss_register_scsi(int ctlr, int this_is_init_time) -{ - unsigned long flags; - - CPQ_TAPE_LOCK(ctlr, flags); - - sprintf( ccissscsi[ctlr].name, "cciss%d", ctlr ); - - init_driver_template(ctlr); - - /* Since this is really a block driver, the SCSI core may not be - initialized yet, in which case, calling scsi_register_module - would hang. instead, we will do it later, via /proc filesystem - and rc scripts, when we know SCSI core is good to go. */ - - if (this_is_init_time) { - CPQ_TAPE_UNLOCK(ctlr, flags); - return 0; - } - - /* Only register if SCSI devices are detected. */ - if (ccissscsi[ctlr].ndevices != 0) { - ((struct cciss_scsi_adapter_data_t *) - hba[ctlr]->scsi_ctlr)->registered = 1; - CPQ_TAPE_UNLOCK(ctlr, flags); - return scsi_register_module(MODULE_SCSI_HA, - &driver_template[ctlr]); - } - CPQ_TAPE_UNLOCK(ctlr, flags); - printk(KERN_INFO - "cciss%d: No appropriate SCSI device detected, " - "SCSI subsystem not engaged.\n", ctlr); - return 0; -} - -static int -cciss_engage_scsi(int ctlr) -{ - struct cciss_scsi_adapter_data_t *sa; - struct cciss_scsi_cmd_stack_t *stk; - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr; - stk = &sa->cmd_stack; - - if (((struct cciss_scsi_adapter_data_t *) - hba[ctlr]->scsi_ctlr)->registered) { - printk("cciss%d: SCSI subsystem already engaged.\n", ctlr); - spin_unlock_irqrestore(&io_request_lock, flags); - return ENXIO; - } - spin_unlock_irqrestore(&io_request_lock, flags); - cciss_update_non_disk_devices(ctlr, -1); - cciss_register_scsi(ctlr, 0); - return 0; -} - -static void -cciss_proc_tape_report(int ctlr, unsigned char *buffer, off_t *pos, off_t *len) -{ - int size; - unsigned int flags; - - *pos = *pos -1; *len = *len - 1; // cut off the last trailing newline - - CPQ_TAPE_LOCK(ctlr, flags); - size = sprintf(buffer + *len, - "Sequential access devices: %d\n\n", - ccissscsi[ctlr].ndevices); - CPQ_TAPE_UNLOCK(ctlr, flags); - *pos += size; *len += size; -} - -#else /* no CONFIG_CISS_SCSI_TAPE */ - -/* If no tape support, then these become defined out of existence */ - -#define cciss_find_non_disk_devices(cntl_num) -#define cciss_unregister_scsi(ctlr) -#define cciss_register_scsi(ctlr, this_is_init_time) -#define cciss_proc_tape_report(ctlr, buffer, pos, len) - -#endif /* CONFIG_CISS_SCSI_TAPE */ diff --git a/xen/drivers/block/cciss_scsi.h b/xen/drivers/block/cciss_scsi.h deleted file mode 100644 index 70c32cf5b3..0000000000 --- a/xen/drivers/block/cciss_scsi.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Disk Array driver for HP SA 5xxx and 6xxx Controllers, SCSI Tape module - * Copyright 2001, 2002 Hewlett-Packard Development Company, L.P. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Questions/Comments/Bugfixes to Cciss-discuss@lists.sourceforge.net - * - */ -#ifdef CONFIG_CISS_SCSI_TAPE -#ifndef _CCISS_SCSI_H_ -#define _CCISS_SCSI_H_ - -#include /* possibly irrelevant, since we don't show disks */ - - // the scsi id of the adapter... -#define SELF_SCSI_ID -1 - // In case we ever want to present controller so sg will - // bind to it. The scsi bus that's presented by the - // driver to the OS is fabricated. The "real" scsi-3 - // bus the hardware presents is fabricated too. - // The actual, honest-to-goodness physical - // bus that the devices are attached to is not - // addressible natively, and may in fact turn - // out to be not scsi at all. - -#define SCSI_CCISS_CAN_QUEUE 2 - -/* this notation works fine for static initializations (as is the usual - case for linux scsi drivers), but not so well for dynamic settings, - so, if you change this, you also have to change cciss_unregister_scsi() - in cciss_scsi.c */ -#define CCISS_SCSI { \ - name: "", \ - detect: cciss_scsi_detect, \ - release: cciss_scsi_release, \ - proc_info: cciss_scsi_proc_info, \ - queuecommand: cciss_scsi_queue_command, \ - bios_param: scsicam_bios_param, \ - can_queue: SCSI_CCISS_CAN_QUEUE, \ - this_id: SELF_SCSI_ID, \ - sg_tablesize: MAXSGENTRIES, \ - cmd_per_lun: 1, \ - use_new_eh_code: 1, \ - use_clustering: DISABLE_CLUSTERING,\ -} - -/* - info: cciss_scsi_info, \ - -Note, cmd_per_lun could give us some trouble, so I'm setting it very low. -Likewise, SCSI_CCISS_CAN_QUEUE is set very conservatively. - -If the upper scsi layer tries to track how many commands we have -outstanding, it will be operating under the misapprehension that it is -the only one sending us requests. We also have the block interface, -which is where most requests must surely come from, so the upper layer's -notion of how many requests we have outstanding will be wrong most or -all of the time. - -Note, the normal SCSI mid-layer error handling doesn't work well -for this driver because 1) it takes the io_request_lock before -calling error handlers and uses a local variable to store flags, -so the io_request_lock cannot be released and interrupts enabled -inside the error handlers, and, the error handlers cannot poll -for command completion because they might get commands from the -block half of the driver completing, and not know what to do -with them. That's what we get for making a hybrid scsi/block -driver, I suppose. - -*/ - -struct cciss_scsi_dev_t { - int devtype; - int bus, target, lun; /* as presented to the OS */ - unsigned char scsi3addr[8]; /* as presented to the HW */ -}; - -struct cciss_scsi_hba_t { - char name[32]; - int ndevices; -#define CCISS_MAX_SCSI_DEVS_PER_HBA 16 - struct cciss_scsi_dev_t dev[CCISS_MAX_SCSI_DEVS_PER_HBA]; -}; - -#endif /* _CCISS_SCSI_H_ */ -#endif /* CONFIG_CISS_SCSI_TAPE */ diff --git a/xen/drivers/block/elevator.c b/xen/drivers/block/elevator.c deleted file mode 100644 index 895dbe59ba..0000000000 --- a/xen/drivers/block/elevator.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * linux/drivers/block/elevator.c - * - * Block device elevator/IO-scheduler. - * - * Copyright (C) 2000 Andrea Arcangeli SuSE - * - * 30042000 Jens Axboe : - * - * Split the elevator a bit so that it is possible to choose a different - * one or even write a new "plug in". There are three pieces: - * - elevator_fn, inserts a new request in the queue list - * - elevator_merge_fn, decides whether a new buffer can be merged with - * an existing request - * - elevator_dequeue_fn, called when a request is taken off the active list - * - * 20082000 Dave Jones : - * Removed tests for max-bomb-segments, which was breaking elvtune - * when run without -bN - * - */ - -#include -#include -/*#include */ -#include -#include -#include -#include -#include - -/* - * This is a bit tricky. It's given that bh and rq are for the same - * device, but the next request might of course not be. Run through - * the tests below to check if we want to insert here if we can't merge - * bh into an existing request - */ -inline int bh_rq_in_between(struct buffer_head *bh, struct request *rq, - struct list_head *head) -{ - struct list_head *next; - struct request *next_rq; - - next = rq->queue.next; - if (next == head) - return 0; - - /* - * if the device is different (usually on a different partition), - * just check if bh is after rq - */ - next_rq = blkdev_entry_to_request(next); - if (next_rq->rq_dev != rq->rq_dev) - return bh->b_rsector > rq->sector; - - /* - * ok, rq, next_rq and bh are on the same device. if bh is in between - * the two, this is the sweet spot - */ - if (bh->b_rsector < next_rq->sector && bh->b_rsector > rq->sector) - return 1; - - /* - * next_rq is ordered wrt rq, but bh is not in between the two - */ - if (next_rq->sector > rq->sector) - return 0; - - /* - * next_rq and rq not ordered, if we happen to be either before - * next_rq or after rq insert here anyway - */ - if (bh->b_rsector > rq->sector || bh->b_rsector < next_rq->sector) - return 1; - - return 0; -} - - -int elevator_linus_merge(request_queue_t *q, struct request **req, - struct list_head * head, - struct buffer_head *bh, int rw, - int max_sectors) -{ - struct list_head *entry = &q->queue_head; - unsigned int count = bh->b_size >> 9, ret = ELEVATOR_NO_MERGE; - - while ((entry = entry->prev) != head) { - struct request *__rq = blkdev_entry_to_request(entry); - - /* - * simply "aging" of requests in queue - */ - if (__rq->elevator_sequence-- <= 0) - break; - - if (__rq->waiting) - continue; - if (__rq->rq_dev != bh->b_rdev) - continue; - if (!*req && bh_rq_in_between(bh, __rq, &q->queue_head)) - *req = __rq; - if (__rq->cmd != rw) - continue; - if (__rq->nr_sectors + count > max_sectors) - continue; - if (__rq->elevator_sequence < count) - break; - if (__rq->sector + __rq->nr_sectors == bh->b_rsector) { - ret = ELEVATOR_BACK_MERGE; - *req = __rq; - break; - } else if (__rq->sector - count == bh->b_rsector) { - ret = ELEVATOR_FRONT_MERGE; - __rq->elevator_sequence -= count; - *req = __rq; - break; - } - } - - return ret; -} - -void elevator_linus_merge_cleanup(request_queue_t *q, struct request *req, int count) -{ - struct list_head *entry = &req->queue, *head = &q->queue_head; - - /* - * second pass scan of requests that got passed over, if any - */ - while ((entry = entry->next) != head) { - struct request *tmp = blkdev_entry_to_request(entry); - tmp->elevator_sequence -= count; - } -} - -void elevator_linus_merge_req(struct request *req, struct request *next) -{ - if (next->elevator_sequence < req->elevator_sequence) - req->elevator_sequence = next->elevator_sequence; -} - -/* - * See if we can find a request that this buffer can be coalesced with. - */ -int elevator_noop_merge(request_queue_t *q, struct request **req, - struct list_head * head, - struct buffer_head *bh, int rw, - int max_sectors) -{ - struct list_head *entry; - unsigned int count = bh->b_size >> 9; - - if (list_empty(&q->queue_head)) - return ELEVATOR_NO_MERGE; - - entry = &q->queue_head; - while ((entry = entry->prev) != head) { - struct request *__rq = blkdev_entry_to_request(entry); - - if (__rq->cmd != rw) - continue; - if (__rq->rq_dev != bh->b_rdev) - continue; - if (__rq->nr_sectors + count > max_sectors) - continue; - if (__rq->waiting) - continue; - if (__rq->sector + __rq->nr_sectors == bh->b_rsector) { - *req = __rq; - return ELEVATOR_BACK_MERGE; - } else if (__rq->sector - count == bh->b_rsector) { - *req = __rq; - return ELEVATOR_FRONT_MERGE; - } - } - - *req = blkdev_entry_to_request(q->queue_head.prev); - return ELEVATOR_NO_MERGE; -} - -void elevator_noop_merge_cleanup(request_queue_t *q, struct request *req, int count) {} - -void elevator_noop_merge_req(struct request *req, struct request *next) {} - -int blkelvget_ioctl(elevator_t * elevator, blkelv_ioctl_arg_t * arg) -{ - blkelv_ioctl_arg_t output; - - output.queue_ID = elevator->queue_ID; - output.read_latency = elevator->read_latency; - output.write_latency = elevator->write_latency; - output.max_bomb_segments = 0; - - if (copy_to_user(arg, &output, sizeof(blkelv_ioctl_arg_t))) - return -EFAULT; - - return 0; -} - -int blkelvset_ioctl(elevator_t * elevator, const blkelv_ioctl_arg_t * arg) -{ - blkelv_ioctl_arg_t input; - - if (copy_from_user(&input, arg, sizeof(blkelv_ioctl_arg_t))) - return -EFAULT; - - if (input.read_latency < 0) - return -EINVAL; - if (input.write_latency < 0) - return -EINVAL; - - elevator->read_latency = input.read_latency; - elevator->write_latency = input.write_latency; - return 0; -} - -void elevator_init(elevator_t * elevator, elevator_t type) -{ - static unsigned int queue_ID; - - *elevator = type; - elevator->queue_ID = queue_ID++; -} diff --git a/xen/drivers/block/genhd.c b/xen/drivers/block/genhd.c deleted file mode 100644 index bd2414c8ca..0000000000 --- a/xen/drivers/block/genhd.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Code extracted from - * linux/kernel/hd.c - * - * Copyright (C) 1991-1998 Linus Torvalds - * - * devfs support - jj, rgooch, 980122 - * - * Moved partition checking code to fs/partitions* - Russell King - * (linux@arm.uk.linux.org) - */ - -/* - * TODO: rip out the remaining init crap from this file --hch - */ - -#include -#include -/*#include */ -#include -#include -#include -#include -#include - - -static rwlock_t gendisk_lock; - -/* - * Global kernel list of partitioning information. - * - * XXX: you should _never_ access this directly. - * the only reason this is exported is source compatiblity. - */ -/*static*/ struct gendisk *gendisk_head; -static struct gendisk *gendisk_array[MAX_BLKDEV]; - -EXPORT_SYMBOL(gendisk_head); - - -/** - * add_gendisk - add partitioning information to kernel list - * @gp: per-device partitioning information - * - * This function registers the partitioning information in @gp - * with the kernel. - */ -void -add_gendisk(struct gendisk *gp) -{ - struct gendisk *sgp; - - write_lock(&gendisk_lock); - - /* - * In 2.5 this will go away. Fix the drivers who rely on - * old behaviour. - */ - - for (sgp = gendisk_head; sgp; sgp = sgp->next) - { - if (sgp == gp) - { -// printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n", -// sgp->major) - goto out; - } - } - gendisk_array[gp->major] = gp; - gp->next = gendisk_head; - gendisk_head = gp; -out: - write_unlock(&gendisk_lock); -} - -EXPORT_SYMBOL(add_gendisk); - - -/** - * del_gendisk - remove partitioning information from kernel list - * @gp: per-device partitioning information - * - * This function unregisters the partitioning information in @gp - * with the kernel. - */ -void -del_gendisk(struct gendisk *gp) -{ - struct gendisk **gpp; - - write_lock(&gendisk_lock); - gendisk_array[gp->major] = NULL; - for (gpp = &gendisk_head; *gpp; gpp = &((*gpp)->next)) - if (*gpp == gp) - break; - if (*gpp) - *gpp = (*gpp)->next; - write_unlock(&gendisk_lock); -} - -EXPORT_SYMBOL(del_gendisk); - - -/** - * get_gendisk - get partitioning information for a given device - * @dev: device to get partitioning information for - * - * This function gets the structure containing partitioning - * information for the given device @dev. - */ -struct gendisk * -get_gendisk(kdev_t dev) -{ - struct gendisk *gp = NULL; - int maj = MAJOR(dev); - - read_lock(&gendisk_lock); - if ((gp = gendisk_array[maj])) - goto out; - - /* This is needed for early 2.4 source compatiblity. --hch */ - for (gp = gendisk_head; gp; gp = gp->next) - if (gp->major == maj) - break; -out: - read_unlock(&gendisk_lock); - return gp; -} - -EXPORT_SYMBOL(get_gendisk); - - -/** - * walk_gendisk - issue a command for every registered gendisk - * @walk: user-specified callback - * @data: opaque data for the callback - * - * This function walks through the gendisk chain and calls back - * into @walk for every element. - */ -int -walk_gendisk(int (*walk)(struct gendisk *, void *), void *data) -{ - struct gendisk *gp; - int error = 0; - - read_lock(&gendisk_lock); - for (gp = gendisk_head; gp; gp = gp->next) - if ((error = walk(gp, data))) - break; - read_unlock(&gendisk_lock); - - return error; -} - - -#ifdef CONFIG_PROC_FS -int -get_partition_list(char *page, char **start, off_t offset, int count) -{ - struct gendisk *gp; - struct hd_struct *hd; - char buf[64]; - int len, n; - - len = sprintf(page, "major minor #blocks name\n\n"); - - read_lock(&gendisk_lock); - for (gp = gendisk_head; gp; gp = gp->next) { - for (n = 0; n < (gp->nr_real << gp->minor_shift); n++) { - if (gp->part[n].nr_sects == 0) - continue; - - hd = &gp->part[n]; disk_round_stats(hd); - len += sprintf(page + len, - "%4d %4d %10d %s\n", gp->major, - n, gp->sizes[n], disk_name(gp, n, buf)); - - if (len < offset) - offset -= len, len = 0; - else if (len >= offset + count) - goto out; - } - } - -out: - read_unlock(&gendisk_lock); - *start = page + offset; - len -= offset; - if (len < 0) - len = 0; - return len > count ? count : len; -} -#endif - -/* XXX SMH: stuff from fs/partitions dumped here temporarily */ - - -/* - * This function will re-read the partition tables for a given device, - * and set things back up again. There are some important caveats, - * however. You must ensure that no one is using the device, and no one - * can start using the device while this function is being executed. - * - * Much of the cleanup from the old partition tables should have already been - * done - */ -void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors, - struct block_device_operations *ops, long size) -{ - if (!gdev) - return; - grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size); -} - -void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size) -{ - int i; - int first_minor = drive << dev->minor_shift; - int end_minor = first_minor + dev->max_p; - - if(!dev->sizes) - blk_size[dev->major] = NULL; - - dev->part[first_minor].nr_sects = size; -#ifdef DEVFS_MUST_DIE - /* No such device or no minors to use for partitions */ - if ( !size && dev->flags && (dev->flags[drive] & GENHD_FL_REMOVABLE) ) - devfs_register_partitions (dev, first_minor, 0); -#endif - - if (!size || minors == 1) - return; - - if (dev->sizes) { - dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9); - for (i = first_minor + 1; i < end_minor; i++) - dev->sizes[i] = 0; - } - blk_size[dev->major] = dev->sizes; -#if 0 - /* XXX SMH: don't actually check partition details yet */ - check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor); -#endif - - /* - * We need to set the sizes array before we will be able to access - * any of the partitions on this device. - */ - if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */ - for (i = first_minor; i < end_minor; i++) - dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9); - } -} - - - -extern int blk_dev_init(void); -extern int net_dev_init(void); -extern void console_map_init(void); -extern int atmdev_init(void); - -int __init device_init(void) -{ - rwlock_init(&gendisk_lock); - blk_dev_init(); - sti(); -#ifdef CONFIG_NET - net_dev_init(); -#endif -#ifdef CONFIG_ATM - (void) atmdev_init(); -#endif -#ifdef CONFIG_VT - console_map_init(); -#endif - return 0; -} - -__initcall(device_init); diff --git a/xen/drivers/block/ll_rw_blk.c b/xen/drivers/block/ll_rw_blk.c deleted file mode 100644 index 7097c5a0ec..0000000000 --- a/xen/drivers/block/ll_rw_blk.c +++ /dev/null @@ -1,1469 +0,0 @@ -/* - * linux/drivers/block/ll_rw_blk.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright (C) 1994, Karl Keyte: Added support for disk statistics - * Elevator latency, (C) 2000 Andrea Arcangeli SuSE - * Queue request tables / lock, selectable elevator, Jens Axboe - */ - -/* - * This handles all read/write requests to block devices - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* This will die as all synchronous stuff is coming to an end */ -#if 0 -#define complete(_r) panic("completion.h stuff may be needed...") -#else -// XXX SMH: we spin when waiting for completion so just toggle flag -#define complete(_r) (*(int *)(_r) = 0) -#endif - -/* - * MAC Floppy IWM hooks - */ - -#ifdef CONFIG_MAC_FLOPPY_IWM -extern int mac_floppy_init(void); -#endif - -/* - * For the allocated request tables - */ -static kmem_cache_t *request_cachep; - -/* - * The "disk" task queue is used to start the actual requests - * after a plug - */ -DECLARE_TASK_QUEUE(tq_disk); - -/* - * Protect the request list against multiple users.. - * - * With this spinlock the Linux block IO subsystem is 100% SMP threaded - * from the IRQ event side, and almost 100% SMP threaded from the syscall - * side (we still have protect against block device array operations, and - * the do_request() side is casually still unsafe. The kernel lock protects - * this part currently.). - * - * there is a fair chance that things will work just OK if these functions - * are called with no global kernel lock held ... - */ -spinlock_t io_request_lock = SPIN_LOCK_UNLOCKED; - -/* This specifies how many sectors to read ahead on the disk. */ - -int read_ahead[MAX_BLKDEV]; - -/* blk_dev_struct is: - * *request_fn - * *current_request - */ -struct blk_dev_struct blk_dev[MAX_BLKDEV]; /* initialized by blk_dev_init() */ - -/* - * blk_size contains the size of all block-devices in units of 1024 byte - * sectors: - * - * blk_size[MAJOR][MINOR] - * - * if (!blk_size[MAJOR]) then no minor size checking is done. - */ -int * blk_size[MAX_BLKDEV]; - -/* - * blksize_size contains the size of all block-devices: - * - * blksize_size[MAJOR][MINOR] - * - * if (!blksize_size[MAJOR]) then 1024 bytes is assumed. - */ -int * blksize_size[MAX_BLKDEV]; - -/* - * hardsect_size contains the size of the hardware sector of a device. - * - * hardsect_size[MAJOR][MINOR] - * - * if (!hardsect_size[MAJOR]) - * then 512 bytes is assumed. - * else - * sector_size is hardsect_size[MAJOR][MINOR] - * This is currently set by some scsi devices and read by the msdos fs driver. - * Other uses may appear later. - */ -int * hardsect_size[MAX_BLKDEV]; - -/* - * The following tunes the read-ahead algorithm in mm/filemap.c - */ -int * max_readahead[MAX_BLKDEV]; - -/* - * Max number of sectors per request - */ -int * max_sectors[MAX_BLKDEV]; - - -static inline int get_max_sectors(kdev_t dev) -{ - if (!max_sectors[MAJOR(dev)]) - return MAX_SECTORS; - return max_sectors[MAJOR(dev)][MINOR(dev)]; -} - -inline request_queue_t *blk_get_queue(kdev_t dev) -{ - struct blk_dev_struct *bdev = blk_dev + MAJOR(dev); - - if (bdev->queue) - return bdev->queue(dev); - else - return &blk_dev[MAJOR(dev)].request_queue; -} - -static int __blk_cleanup_queue(struct request_list *list) -{ - struct list_head *head = &list->free; - struct request *rq; - int i = 0; - - while (!list_empty(head)) { - rq = list_entry(head->next, struct request, queue); - list_del(&rq->queue); - kmem_cache_free(request_cachep, rq); - i++; - }; - - if (i != list->count) - printk("request list leak!\n"); - - list->count = 0; - return i; -} - -/** - * blk_cleanup_queue: - release a &request_queue_t when it is no longer needed - * @q: the request queue to be released - * - * Description: - * blk_cleanup_queue is the pair to blk_init_queue(). It should - * be called when a request queue is being released; typically - * when a block device is being de-registered. Currently, its - * primary task it to free all the &struct request structures that - * were allocated to the queue. - * Caveat: - * Hopefully the low level driver will have finished any - * outstanding requests first... - **/ -void blk_cleanup_queue(request_queue_t * q) -{ - int count = q->nr_requests; - - count -= __blk_cleanup_queue(&q->rq[READ]); - count -= __blk_cleanup_queue(&q->rq[WRITE]); - - if (count) - printk("blk_cleanup_queue: leaked requests (%d)\n", count); - - memset(q, 0, sizeof(*q)); -} - -/** - * blk_queue_headactive - indicate whether head of request queue may be active - * @q: The queue which this applies to. - * @active: A flag indication where the head of the queue is active. - * - * Description: - * The driver for a block device may choose to leave the currently active - * request on the request queue, removing it only when it has completed. - * The queue handling routines assume this by default for safety reasons - * and will not involve the head of the request queue in any merging or - * reordering of requests when the queue is unplugged (and thus may be - * working on this particular request). - * - * If a driver removes requests from the queue before processing them, then - * it may indicate that it does so, there by allowing the head of the queue - * to be involved in merging and reordering. This is done be calling - * blk_queue_headactive() with an @active flag of %0. - * - * If a driver processes several requests at once, it must remove them (or - * at least all but one of them) from the request queue. - * - * When a queue is plugged the head will be assumed to be inactive. - **/ - -void blk_queue_headactive(request_queue_t * q, int active) -{ - q->head_active = active; -} - -/** - * blk_queue_make_request - define an alternate make_request function for a device - * @q: the request queue for the device to be affected - * @mfn: the alternate make_request function - * - * Description: - * The normal way for &struct buffer_heads to be passed to a device - * driver is for them to be collected into requests on a request - * queue, and then to allow the device driver to select requests - * off that queue when it is ready. This works well for many block - * devices. However some block devices (typically virtual devices - * such as md or lvm) do not benefit from the processing on the - * request queue, and are served best by having the requests passed - * directly to them. This can be achieved by providing a function - * to blk_queue_make_request(). - * - * Caveat: - * The driver that does this *must* be able to deal appropriately - * with buffers in "highmemory", either by calling bh_kmap() to get - * a kernel mapping, to by calling create_bounce() to create a - * buffer in normal memory. - **/ - -void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn) -{ - q->make_request_fn = mfn; -} - - -/* - * can we merge the two segments, or do we need to start a new one? - */ -inline int blk_seg_merge_ok(struct buffer_head *bh, struct buffer_head *nxt) -{ - /* - * if bh and nxt are contigous and don't cross a 4g boundary, it's ok - */ - if (BH_CONTIG(bh, nxt) && BH_PHYS_4G(bh, nxt)) - return 1; - - return 0; -} - -static inline int ll_new_segment(request_queue_t *q, struct request *req, int max_segments) -{ - if (req->nr_segments < max_segments) { - req->nr_segments++; - return 1; - } - return 0; -} - -static int ll_back_merge_fn(request_queue_t *q, struct request *req, - struct buffer_head *bh, int max_segments) -{ - if (blk_seg_merge_ok(req->bhtail, bh)) - return 1; - - return ll_new_segment(q, req, max_segments); -} - -static int ll_front_merge_fn(request_queue_t *q, struct request *req, - struct buffer_head *bh, int max_segments) -{ - if (blk_seg_merge_ok(bh, req->bh)) - return 1; - - return ll_new_segment(q, req, max_segments); -} - -static int ll_merge_requests_fn(request_queue_t *q, struct request *req, - struct request *next, int max_segments) -{ - int total_segments = req->nr_segments + next->nr_segments; - - if (blk_seg_merge_ok(req->bhtail, next->bh)) - total_segments--; - - if (total_segments > max_segments) - return 0; - - req->nr_segments = total_segments; - return 1; -} - -/* - * "plug" the device if there are no outstanding requests: this will - * force the transfer to start only after we have put all the requests - * on the list. - * - * This is called with interrupts off and no requests on the queue. - * (and with the request spinlock acquired) - */ -static void generic_plug_device(request_queue_t *q, kdev_t dev) -{ - /* - * no need to replug device - */ - if (!list_empty(&q->queue_head) || q->plugged) - return; - - q->plugged = 1; - queue_task(&q->plug_tq, &tq_disk); -} - -/* - * remove the plug and let it rip.. - */ -static inline void __generic_unplug_device(request_queue_t *q) -{ - if (q->plugged) { - q->plugged = 0; - if (!list_empty(&q->queue_head)) - { - q->request_fn(q); - } - } -} - -void generic_unplug_device(void *data) -{ - request_queue_t *q = (request_queue_t *) data; - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - __generic_unplug_device(q); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/** blk_grow_request_list - * @q: The &request_queue_t - * @nr_requests: how many requests are desired - * - * More free requests are added to the queue's free lists, bringing - * the total number of requests to @nr_requests. - * - * The requests are added equally to the request queue's read - * and write freelists. - * - * This function can sleep. - * - * Returns the (new) number of requests which the queue has available. - */ -int blk_grow_request_list(request_queue_t *q, int nr_requests) -{ - unsigned long flags; - /* Several broken drivers assume that this function doesn't sleep, - * this causes system hangs during boot. - * As a temporary fix, make the the function non-blocking. - */ - spin_lock_irqsave(&io_request_lock, flags); - while (q->nr_requests < nr_requests) { - struct request *rq; - int rw; - - rq = kmem_cache_alloc(request_cachep, SLAB_ATOMIC); - if (rq == NULL) - break; - memset(rq, 0, sizeof(*rq)); - rq->rq_status = RQ_INACTIVE; - rw = q->nr_requests & 1; - list_add(&rq->queue, &q->rq[rw].free); - q->rq[rw].count++; - q->nr_requests++; - } - q->batch_requests = q->nr_requests / 4; - if (q->batch_requests > 32) - q->batch_requests = 32; - spin_unlock_irqrestore(&io_request_lock, flags); - return q->nr_requests; -} - -static void blk_init_free_list(request_queue_t *q) -{ - /*struct sysinfo si;*/ - /*int megs;*/ /* Total memory, in megabytes */ - int nr_requests; - - INIT_LIST_HEAD(&q->rq[READ].free); - INIT_LIST_HEAD(&q->rq[WRITE].free); - q->rq[READ].count = 0; - q->rq[WRITE].count = 0; - q->nr_requests = 0; - -#if 0 - si_meminfo(&si); - megs = si.totalram >> (20 - PAGE_SHIFT); - nr_requests = 128; - if (megs < 32) - nr_requests /= 2; -#else - nr_requests = 128; -#endif - blk_grow_request_list(q, nr_requests); - -#if 0 - init_waitqueue_head(&q->wait_for_requests[0]); - init_waitqueue_head(&q->wait_for_requests[1]); -#endif - spin_lock_init(&q->queue_lock); -} - -static int __make_request(request_queue_t * q, int rw, struct buffer_head * bh); - -/** - * blk_init_queue - prepare a request queue for use with a block device - * @q: The &request_queue_t to be initialised - * @rfn: The function to be called to process requests that have been - * placed on the queue. - * - * Description: - * If a block device wishes to use the standard request handling procedures, - * which sorts requests and coalesces adjacent requests, then it must - * call blk_init_queue(). The function @rfn will be called when there - * are requests on the queue that need to be processed. If the device - * supports plugging, then @rfn may not be called immediately when requests - * are available on the queue, but may be called at some time later instead. - * Plugged queues are generally unplugged when a buffer belonging to one - * of the requests on the queue is needed, or due to memory pressure. - * - * @rfn is not required, or even expected, to remove all requests off the - * queue, but only as many as it can handle at a time. If it does leave - * requests on the queue, it is responsible for arranging that the requests - * get dealt with eventually. - * - * A global spin lock $io_request_lock must be held while manipulating the - * requests on the request queue. - * - * The request on the head of the queue is by default assumed to be - * potentially active, and it is not considered for re-ordering or merging - * whenever the given queue is unplugged. This behaviour can be changed with - * blk_queue_headactive(). - * - * Note: - * blk_init_queue() must be paired with a blk_cleanup_queue() call - * when the block device is deactivated (such as at module unload). - **/ -void blk_init_queue(request_queue_t * q, request_fn_proc * rfn) -{ - INIT_LIST_HEAD(&q->queue_head); - elevator_init(&q->elevator, ELEVATOR_LINUS); - blk_init_free_list(q); - q->request_fn = rfn; - q->back_merge_fn = ll_back_merge_fn; - q->front_merge_fn = ll_front_merge_fn; - q->merge_requests_fn = ll_merge_requests_fn; - q->make_request_fn = __make_request; - q->plug_tq.sync = 0; - q->plug_tq.routine = &generic_unplug_device; - q->plug_tq.data = q; - q->plugged = 0; - /* - * These booleans describe the queue properties. We set the - * default (and most common) values here. Other drivers can - * use the appropriate functions to alter the queue properties. - * as appropriate. - */ - q->plug_device_fn = generic_plug_device; - q->head_active = 1; -} - -#define blkdev_free_rq(list) list_entry((list)->next, struct request, queue); -/* - * Get a free request. io_request_lock must be held and interrupts - * disabled on the way in. Returns NULL if there are no free requests. - */ -static struct request *get_request(request_queue_t *q, int rw) -{ - struct request *rq = NULL; - struct request_list *rl = q->rq + rw; - - if (!list_empty(&rl->free)) { - rq = blkdev_free_rq(&rl->free); - list_del(&rq->queue); - rl->count--; - rq->rq_status = RQ_ACTIVE; - rq->cmd = rw; - rq->special = NULL; - rq->q = q; - } - - return rq; -} - -/* - * Here's the request allocation design: - * - * 1: Blocking on request exhaustion is a key part of I/O throttling. - * - * 2: We want to be `fair' to all requesters. We must avoid starvation, and - * attempt to ensure that all requesters sleep for a similar duration. Hence - * no stealing requests when there are other processes waiting. - * - * 3: We also wish to support `batching' of requests. So when a process is - * woken, we want to allow it to allocate a decent number of requests - * before it blocks again, so they can be nicely merged (this only really - * matters if the process happens to be adding requests near the head of - * the queue). - * - * 4: We want to avoid scheduling storms. This isn't really important, because - * the system will be I/O bound anyway. But it's easy. - * - * There is tension between requirements 2 and 3. Once a task has woken, - * we don't want to allow it to sleep as soon as it takes its second request. - * But we don't want currently-running tasks to steal all the requests - * from the sleepers. We handle this with wakeup hysteresis around - * 0 .. batch_requests and with the assumption that request taking is much, - * much faster than request freeing. - * - * So here's what we do: - * - * a) A READA requester fails if free_requests < batch_requests - * - * We don't want READA requests to prevent sleepers from ever - * waking. Note that READA is used extremely rarely - a few - * filesystems use it for directory readahead. - * - * When a process wants a new request: - * - * b) If free_requests == 0, the requester sleeps in FIFO manner. - * - * b) If 0 < free_requests < batch_requests and there are waiters, - * we still take a request non-blockingly. This provides batching. - * - * c) If free_requests >= batch_requests, the caller is immediately - * granted a new request. - * - * When a request is released: - * - * d) If free_requests < batch_requests, do nothing. - * - * f) If free_requests >= batch_requests, wake up a single waiter. - * - * The net effect is that when a process is woken at the batch_requests level, - * it will be able to take approximately (batch_requests) requests before - * blocking again (at the tail of the queue). - * - * This all assumes that the rate of taking requests is much, much higher - * than the rate of releasing them. Which is very true. - * - * -akpm, Feb 2002. - */ - -static struct request *__get_request_wait(request_queue_t *q, int rw) -{ -#if 0 - register struct request *rq; - /*DECLARE_WAITQUEUE(wait, current);*/ - - generic_unplug_device(q); - add_wait_queue_exclusive(&q->wait_for_requests[rw], &wait); - do { - set_current_state(TASK_UNINTERRUPTIBLE); - if (q->rq[rw].count == 0) - schedule(); - spin_lock_irq(&io_request_lock); - rq = get_request(q,rw); - spin_unlock_irq(&io_request_lock); - } while (rq == NULL); - remove_wait_queue(&q->wait_for_requests[rw], &wait); - current->state = TASK_RUNNING; - return rq; -#else - panic("__get_request_wait shouldn't be depended on"); - return 0; -#endif -} - -/* RO fail safe mechanism */ - -static long ro_bits[MAX_BLKDEV][8]; - -int is_read_only(kdev_t dev) -{ - int minor,major; - - major = MAJOR(dev); - minor = MINOR(dev); - if (major < 0 || major >= MAX_BLKDEV) return 0; - return ro_bits[major][minor >> 5] & (1 << (minor & 31)); -} - -void set_device_ro(kdev_t dev,int flag) -{ - int minor,major; - - major = MAJOR(dev); - minor = MINOR(dev); - if (major < 0 || major >= MAX_BLKDEV) return; - if (flag) ro_bits[major][minor >> 5] |= 1 << (minor & 31); - else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31)); -} - -inline void drive_stat_acct (kdev_t dev, int rw, - unsigned long nr_sectors, int new_io) -{ - /*unsigned int major = MAJOR(dev);*/ - unsigned int index; - - index = disk_index(dev); -#if 0 - if ((index >= DK_MAX_DISK) || (major >= DK_MAX_MAJOR)) - return; -#endif - -#if 0 - kstat.dk_drive[major][index] += new_io; - if (rw == READ) { - kstat.dk_drive_rio[major][index] += new_io; - kstat.dk_drive_rblk[major][index] += nr_sectors; - } else if (rw == WRITE) { - kstat.dk_drive_wio[major][index] += new_io; - kstat.dk_drive_wblk[major][index] += nr_sectors; - } else - printk(KERN_ERR "drive_stat_acct: cmd not R/W?\n"); -#endif -} - -/* Return up to two hd_structs on which to do IO accounting for a given - * request. On a partitioned device, we want to account both against - * the partition and against the whole disk. */ -static void locate_hd_struct(struct request *req, - struct hd_struct **hd1, - struct hd_struct **hd2) -{ - struct gendisk *gd; - - *hd1 = NULL; - *hd2 = NULL; - - gd = get_gendisk(req->rq_dev); - if (gd && gd->part) { - /* Mask out the partition bits: account for the entire disk */ - int devnr = MINOR(req->rq_dev) >> gd->minor_shift; - int whole_minor = devnr << gd->minor_shift; - *hd1 = &gd->part[whole_minor]; - if (whole_minor != MINOR(req->rq_dev)) - *hd2= &gd->part[MINOR(req->rq_dev)]; - } -} - -/* Round off the performance stats on an hd_struct. The average IO - * queue length and utilisation statistics are maintained by observing - * the current state of the queue length and the amount of time it has - * been in this state for. Normally, that accounting is done on IO - * completion, but that can result in more than a second's worth of IO - * being accounted for within any one second, leading to >100% - * utilisation. To deal with that, we do a round-off before returning - * the results when reading /proc/partitions, accounting immediately for - * all queue usage up to the current jiffies and restarting the counters - * again. */ -void disk_round_stats(struct hd_struct *hd) -{ - unsigned long now = jiffies; - - hd->aveq += (hd->ios_in_flight * (jiffies - hd->last_queue_change)); - hd->last_queue_change = now; - - if (hd->ios_in_flight) - hd->io_ticks += (now - hd->last_idle_time); - hd->last_idle_time = now; -} - - -static inline void down_ios(struct hd_struct *hd) -{ - disk_round_stats(hd); - --hd->ios_in_flight; -} - -static inline void up_ios(struct hd_struct *hd) -{ - disk_round_stats(hd); - ++hd->ios_in_flight; -} - -static void account_io_start(struct hd_struct *hd, struct request *req, - int merge, int sectors) -{ - switch (req->cmd) { - case READ: - if (merge) - hd->rd_merges++; - hd->rd_sectors += sectors; - break; - case WRITE: - if (merge) - hd->wr_merges++; - hd->wr_sectors += sectors; - break; - } - if (!merge) - up_ios(hd); -} - -static void account_io_end(struct hd_struct *hd, struct request *req) -{ - unsigned long duration = jiffies - req->start_time; - switch (req->cmd) { - case READ: - hd->rd_ticks += duration; - hd->rd_ios++; - break; - case WRITE: - hd->wr_ticks += duration; - hd->wr_ios++; - break; - } - down_ios(hd); -} - -void req_new_io(struct request *req, int merge, int sectors) -{ - struct hd_struct *hd1, *hd2; - locate_hd_struct(req, &hd1, &hd2); - if (hd1) - account_io_start(hd1, req, merge, sectors); - if (hd2) - account_io_start(hd2, req, merge, sectors); -} - -void req_finished_io(struct request *req) -{ - struct hd_struct *hd1, *hd2; - locate_hd_struct(req, &hd1, &hd2); - if (hd1) - account_io_end(hd1, req); - if (hd2) - account_io_end(hd2, req); -} - -/* - * add-request adds a request to the linked list. - * io_request_lock is held and interrupts disabled, as we muck with the - * request queue list. - * - * By this point, req->cmd is always either READ/WRITE, never READA, - * which is important for drive_stat_acct() above. - */ -static inline void add_request(request_queue_t * q, struct request * req, - struct list_head *insert_here) -{ - drive_stat_acct(req->rq_dev, req->cmd, req->nr_sectors, 1); - - if (!q->plugged && q->head_active && insert_here == &q->queue_head) { - spin_unlock_irq(&io_request_lock); - BUG(); - } - - /* - * elevator indicated where it wants this request to be - * inserted at elevator_merge time - */ - list_add(&req->queue, insert_here); -} - -/* - * Must be called with io_request_lock held and interrupts disabled - */ -void blkdev_release_request(struct request *req) -{ - request_queue_t *q = req->q; - int rw = req->cmd; - - req->rq_status = RQ_INACTIVE; - req->q = NULL; - - /* - * Request may not have originated from ll_rw_blk. if not, - * assume it has free buffers and check waiters - */ - if (q) { - list_add(&req->queue, &q->rq[rw].free); -#if 0 - if (++q->rq[rw].count >= q->batch_requests && - waitqueue_active(&q->wait_for_requests[rw])) - wake_up(&q->wait_for_requests[rw]); -#endif - } -} - -/* - * Has to be called with the request spinlock acquired - */ -static void attempt_merge(request_queue_t * q, - struct request *req, - int max_sectors, - int max_segments) -{ - struct request *next; - struct hd_struct *hd1, *hd2; - - next = blkdev_next_request(req); - if (req->sector + req->nr_sectors != next->sector) - return; - if (req->cmd != next->cmd - || req->rq_dev != next->rq_dev - || req->nr_sectors + next->nr_sectors > max_sectors - || next->waiting) - return; - /* - * If we are not allowed to merge these requests, then - * return. If we are allowed to merge, then the count - * will have been updated to the appropriate number, - * and we shouldn't do it here too. - */ - if (!q->merge_requests_fn(q, req, next, max_segments)) - return; - - q->elevator.elevator_merge_req_fn(req, next); - req->bhtail->b_reqnext = next->bh; - req->bhtail = next->bhtail; - req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors; - list_del(&next->queue); - - /* One last thing: we have removed a request, so we now have one - less expected IO to complete for accounting purposes. */ - - locate_hd_struct(req, &hd1, &hd2); - if (hd1) - down_ios(hd1); - if (hd2) - down_ios(hd2); - blkdev_release_request(next); -} - -static inline void attempt_back_merge(request_queue_t * q, - struct request *req, - int max_sectors, - int max_segments) -{ - if (&req->queue == q->queue_head.prev) - return; - attempt_merge(q, req, max_sectors, max_segments); -} - -static inline void attempt_front_merge(request_queue_t * q, - struct list_head * head, - struct request *req, - int max_sectors, - int max_segments) -{ - struct list_head * prev; - - prev = req->queue.prev; - if (head == prev) - return; - attempt_merge(q, blkdev_entry_to_request(prev), max_sectors, max_segments); -} - -static int __make_request(request_queue_t * q, int rw, - struct buffer_head * bh) -{ - unsigned int sector, count; - int max_segments = MAX_SEGMENTS; - struct request * req, *freereq = NULL; - int rw_ahead, max_sectors, el_ret; - struct list_head *head, *insert_here; - int latency; - elevator_t *elevator = &q->elevator; - - count = bh->b_size >> 9; - sector = bh->b_rsector; - - rw_ahead = 0; /* normal case; gets changed below for READA */ - switch (rw) { - case READA: -#if 0 /* bread() misinterprets failed READA attempts as IO errors on SMP */ - rw_ahead = 1; -#endif - rw = READ; /* drop into READ */ - case READ: - case WRITE: - latency = elevator_request_latency(elevator, rw); - break; - default: - BUG(); - goto end_io; - } - - /* We'd better have a real physical mapping! - Check this bit only if the buffer was dirty and just locked - down by us so at this point flushpage will block and - won't clear the mapped bit under us. */ - if (!buffer_mapped(bh)) - BUG(); - - /* - * Temporary solution - in 2.5 this will be done by the lowlevel - * driver. Create a bounce buffer if the buffer data points into - * high memory - keep the original buffer otherwise. - */ -#if CONFIG_HIGHMEM - bh = create_bounce(rw, bh); -#endif - -/* look for a free request. */ - /* - * Try to coalesce the new request with old requests - */ - max_sectors = get_max_sectors(bh->b_rdev); - -again: - req = NULL; - head = &q->queue_head; - /* - * Now we acquire the request spinlock, we have to be mega careful - * not to schedule or do something nonatomic - */ - spin_lock_irq(&io_request_lock); - - insert_here = head->prev; - if (list_empty(head)) { - q->plug_device_fn(q, bh->b_rdev); /* is atomic */ - goto get_rq; - } else if (q->head_active && !q->plugged) - head = head->next; - - el_ret = elevator->elevator_merge_fn(q, &req, head, bh, rw,max_sectors); - switch (el_ret) { - - case ELEVATOR_BACK_MERGE: - if (!q->back_merge_fn(q, req, bh, max_segments)) { - insert_here = &req->queue; - break; - } - elevator->elevator_merge_cleanup_fn(q, req, count); - req->bhtail->b_reqnext = bh; - req->bhtail = bh; - req->nr_sectors = req->hard_nr_sectors += count; - blk_started_io(count); - drive_stat_acct(req->rq_dev, req->cmd, count, 0); - req_new_io(req, 1, count); - attempt_back_merge(q, req, max_sectors, max_segments); - goto out; - - case ELEVATOR_FRONT_MERGE: - if (!q->front_merge_fn(q, req, bh, max_segments)) { - insert_here = req->queue.prev; - break; - } - elevator->elevator_merge_cleanup_fn(q, req, count); - bh->b_reqnext = req->bh; - req->bh = bh; - req->buffer = bh->b_data; - req->current_nr_sectors = count; - req->sector = req->hard_sector = sector; - req->nr_sectors = req->hard_nr_sectors += count; - blk_started_io(count); - drive_stat_acct(req->rq_dev, req->cmd, count, 0); - req_new_io(req, 1, count); - attempt_front_merge(q, head, req, max_sectors, max_segments); - goto out; - - /* - * elevator says don't/can't merge. get new request - */ - case ELEVATOR_NO_MERGE: - /* - * use elevator hints as to where to insert the - * request. if no hints, just add it to the back - * of the queue - */ - if (req) - insert_here = &req->queue; - break; - - default: - printk("elevator returned crap (%d)\n", el_ret); - BUG(); - } - -get_rq: - if (freereq) { - req = freereq; - freereq = NULL; - } else { - /* - * See description above __get_request_wait() - */ - if (rw_ahead) { - if (q->rq[rw].count < q->batch_requests) { - spin_unlock_irq(&io_request_lock); - goto end_io; - } - req = get_request(q, rw); - if (req == NULL) - BUG(); - } else { - req = get_request(q, rw); - if (req == NULL) { - spin_unlock_irq(&io_request_lock); - freereq = __get_request_wait(q, rw); - goto again; - } - } - } - -/* fill up the request-info, and add it to the queue */ - req->elevator_sequence = latency; - req->cmd = rw; - req->errors = 0; - req->hard_sector = req->sector = sector; - req->hard_nr_sectors = req->nr_sectors = count; - req->current_nr_sectors = count; - req->nr_segments = 1; /* Always 1 for a new request. */ - req->nr_hw_segments = 1; /* Always 1 for a new request. */ - req->buffer = bh->b_data; - req->waiting = NULL; - req->bh = bh; - req->bhtail = bh; - req->rq_dev = bh->b_rdev; - req->start_time = jiffies; - req_new_io(req, 0, count); - blk_started_io(count); - add_request(q, req, insert_here); -out: - if (freereq) - blkdev_release_request(freereq); - spin_unlock_irq(&io_request_lock); - return 0; -end_io: - bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state)); - return 0; -} - -/** - * generic_make_request: hand a buffer head to it's device driver for I/O - * @rw: READ, WRITE, or READA - what sort of I/O is desired. - * @bh: The buffer head describing the location in memory and on the device. - * - * generic_make_request() is used to make I/O requests of block - * devices. It is passed a &struct buffer_head and a &rw value. The - * %READ and %WRITE options are (hopefully) obvious in meaning. The - * %READA value means that a read is required, but that the driver is - * free to fail the request if, for example, it cannot get needed - * resources immediately. - * - * generic_make_request() does not return any status. The - * success/failure status of the request, along with notification of - * completion, is delivered asynchronously through the bh->b_end_io - * function described (one day) else where. - * - * The caller of generic_make_request must make sure that b_page, - * b_addr, b_size are set to describe the memory buffer, that b_rdev - * and b_rsector are set to describe the device address, and the - * b_end_io and optionally b_private are set to describe how - * completion notification should be signaled. BH_Mapped should also - * be set (to confirm that b_dev and b_blocknr are valid). - * - * generic_make_request and the drivers it calls may use b_reqnext, - * and may change b_rdev and b_rsector. So the values of these fields - * should NOT be depended on after the call to generic_make_request. - * Because of this, the caller should record the device address - * information in b_dev and b_blocknr. - * - * Apart from those fields mentioned above, no other fields, and in - * particular, no other flags, are changed by generic_make_request or - * any lower level drivers. - * */ -void generic_make_request (int rw, struct buffer_head * bh) -{ - int major = MAJOR(bh->b_rdev); - int minorsize = 0; - request_queue_t *q; - - if (!bh->b_end_io) - BUG(); - - /* Test device size, when known. */ - if (blk_size[major]) - minorsize = blk_size[major][MINOR(bh->b_rdev)]; - if (minorsize) { - unsigned long maxsector = (minorsize << 1) + 1; - unsigned long sector = bh->b_rsector; - unsigned int count = bh->b_size >> 9; - - if (maxsector < count || maxsector - count < sector) { - /* Yecch */ - bh->b_state &= (1 << BH_Lock) | (1 << BH_Mapped); - - /* This may well happen - the kernel calls bread() - without checking the size of the device, e.g., - when mounting a device. */ - DPRINTK(KERN_INFO - "attempt to access beyond end of device\n"); - DPRINTK(KERN_INFO "%s: rw=%d, want=%ld, limit=%d\n", - kdevname(bh->b_rdev), rw, - (sector + count)>>1, minorsize); - - /* Yecch again */ - bh->b_end_io(bh, 0); - return; - } - } - - /* - * Resolve the mapping until finished. (drivers are - * still free to implement/resolve their own stacking - * by explicitly returning 0) - */ - /* NOTE: we don't repeat the blk_size check for each new device. - * Stacking drivers are expected to know what they are doing. - */ - do { - q = blk_get_queue(bh->b_rdev); - if (!q || !q->make_request_fn) { - DPRINTK(KERN_ERR - "generic_make_request: Trying to access " - "nonexistent block-device %s (%ld)\n", - kdevname(bh->b_rdev), bh->b_rsector); - buffer_IO_error(bh); - break; - } - } while (q->make_request_fn(q, rw, bh)); -} - - -/** - * submit_bh: submit a buffer_head to the block device later for I/O - * @rw: whether to %READ or %WRITE, or maybe to %READA (read ahead) - * @bh: The &struct buffer_head which describes the I/O - * - * submit_bh() is very similar in purpose to generic_make_request(), and - * uses that function to do most of the work. - * - * The extra functionality provided by submit_bh is to determine - * b_rsector from b_blocknr and b_size, and to set b_rdev from b_dev. - * This is is appropriate for IO requests that come from the buffer - * cache and page cache which (currently) always use aligned blocks. - */ -void submit_bh(int rw, struct buffer_head * bh) -{ - if (!test_bit(BH_Lock, &bh->b_state)) - BUG(); - - set_bit(BH_Req, &bh->b_state); - set_bit(BH_Launder, &bh->b_state); - - /* - * First step, 'identity mapping' - RAID or LVM might - * further remap this. - */ - bh->b_rdev = bh->b_dev; - /* bh->b_rsector = bh->b_blocknr * count; */ - - generic_make_request(rw, bh); -} - -/** - * ll_rw_block: low-level access to block devices - * @rw: whether to %READ or %WRITE or maybe %READA (readahead) - * @nr: number of &struct buffer_heads in the array - * @bhs: array of pointers to &struct buffer_head - * - * ll_rw_block() takes an array of pointers to &struct buffer_heads, - * and requests an I/O operation on them, either a %READ or a %WRITE. - * The third %READA option is described in the documentation for - * generic_make_request() which ll_rw_block() calls. - * - * This function provides extra functionality that is not in - * generic_make_request() that is relevant to buffers in the buffer - * cache or page cache. In particular it drops any buffer that it - * cannot get a lock on (with the BH_Lock state bit), any buffer that - * appears to be clean when doing a write request, and any buffer that - * appears to be up-to-date when doing read request. Further it marks - * as clean buffers that are processed for writing (the buffer cache - * wont assume that they are actually clean until the buffer gets - * unlocked). - * - * ll_rw_block sets b_end_io to simple completion handler that marks - * the buffer up-to-date (if approriate), unlocks the buffer and wakes - * any waiters. As client that needs a more interesting completion - * routine should call submit_bh() (or generic_make_request()) - * directly. - * - * Caveat: - * All of the buffers must be for the same device, and must also be - * of the current approved size for the device. */ - -void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]) -{ - unsigned int major; - int correct_size; - int i; - - if (!nr) - return; - - major = MAJOR(bhs[0]->b_dev); - - /* Determine correct block size for this device. */ - correct_size = get_hardsect_size(bhs[0]->b_dev); - - /* Verify requested block sizes. */ - for (i = 0; i < nr; i++) { - struct buffer_head *bh = bhs[i]; - if (bh->b_size % correct_size) { - DPRINTK(KERN_NOTICE "ll_rw_block: device %s: " - "only %d-char blocks implemented (%u)\n", - kdevname(bhs[0]->b_dev), - correct_size, bh->b_size); - goto sorry; - } - } - - if ((rw & WRITE) && is_read_only(bhs[0]->b_dev)) { - DPRINTK(KERN_NOTICE "Can't write to read-only device %s\n", - kdevname(bhs[0]->b_dev)); - goto sorry; - } - - for (i = 0; i < nr; i++) { - struct buffer_head *bh = bhs[i]; - - /* Only one thread can actually submit the I/O. */ - if (test_and_set_bit(BH_Lock, &bh->b_state)) - continue; - - /* We have the buffer lock */ - /*atomic_inc(&bh->b_count);*/ - - switch(rw) { - case WRITE: - if (!atomic_set_buffer_clean(bh)) - /* Hmmph! Nothing to write */ - goto end_io; - /* __mark_buffer_clean(bh); */ - break; - - case READA: - case READ: - if (buffer_uptodate(bh)) - /* Hmmph! Already have it */ - goto end_io; - break; - default: - BUG(); - end_io: - bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state)); - continue; - } - - submit_bh(rw, bh); - } - return; - -sorry: - /* Make sure we don't get infinite dirty retries.. */ - for (i = 0; i < nr; i++) - mark_buffer_clean(bhs[i]); -} - -#ifdef CONFIG_STRAM_SWAP -extern int stram_device_init (void); -#endif - - -/** - * end_that_request_first - end I/O on one buffer. - * @req: the request being processed - * @uptodate: 0 for I/O error - * @name: the name printed for an I/O error - * - * Description: - * Ends I/O on the first buffer attached to @req, and sets it up - * for the next buffer_head (if any) in the cluster. - * - * Return: - * 0 - we are done with this request, call end_that_request_last() - * 1 - still buffers pending for this request - * - * Caveat: - * Drivers implementing their own end_request handling must call - * blk_finished_io() appropriately. - **/ - -int end_that_request_first (struct request *req, int uptodate, char *name) -{ - struct buffer_head * bh; - int nsect; - - req->errors = 0; - if (!uptodate) - printk("end_request: I/O error, dev %s (%s), sector %lu\n", - kdevname(req->rq_dev), name, req->sector); - - if ((bh = req->bh) != NULL) { - nsect = bh->b_size >> 9; - blk_finished_io(nsect); - req->bh = bh->b_reqnext; - bh->b_reqnext = NULL; - bh->b_end_io(bh, uptodate); - if ((bh = req->bh) != NULL) { - req->hard_sector += nsect; - req->hard_nr_sectors -= nsect; - req->sector = req->hard_sector; - req->nr_sectors = req->hard_nr_sectors; - - req->current_nr_sectors = bh->b_size >> 9; - if (req->nr_sectors < req->current_nr_sectors) { - req->nr_sectors = req->current_nr_sectors; - printk("end_request: buffer-list destroyed\n"); - } - req->buffer = bh->b_data; - return 1; - } - } - return 0; -} - -void end_that_request_last(struct request *req) -{ - if (req->waiting != NULL) - complete(req->waiting); - req_finished_io(req); - - blkdev_release_request(req); -} - -int __init blk_dev_init(void) -{ - struct blk_dev_struct *dev; - - request_cachep = kmem_cache_create("blkdev_requests", - sizeof(struct request), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - - if (!request_cachep) - panic("Can't create request pool slab cache\n"); - - for (dev = blk_dev + MAX_BLKDEV; dev-- != blk_dev;) - dev->queue = NULL; - - memset(ro_bits,0,sizeof(ro_bits)); - memset(max_readahead, 0, sizeof(max_readahead)); - memset(max_sectors, 0, sizeof(max_sectors)); - -#ifdef CONFIG_AMIGA_Z2RAM - z2_init(); -#endif -#ifdef CONFIG_STRAM_SWAP - stram_device_init(); -#endif -#ifdef CONFIG_ISP16_CDI - isp16_init(); -#endif -#if defined(CONFIG_IDE) && defined(CONFIG_BLK_DEV_IDE) - ide_init(); /* this MUST precede hd_init */ -#endif -#if defined(CONFIG_IDE) && defined(CONFIG_BLK_DEV_HD) - hd_init(); -#endif -#ifdef CONFIG_BLK_DEV_PS2 - ps2esdi_init(); -#endif -#ifdef CONFIG_BLK_DEV_XD - xd_init(); -#endif -#ifdef CONFIG_BLK_DEV_MFM - mfm_init(); -#endif -#ifdef CONFIG_PARIDE - { extern void paride_init(void); paride_init(); }; -#endif -#ifdef CONFIG_MAC_FLOPPY - swim3_init(); -#endif -#ifdef CONFIG_BLK_DEV_SWIM_IOP - swimiop_init(); -#endif -#ifdef CONFIG_AMIGA_FLOPPY - amiga_floppy_init(); -#endif -#ifdef CONFIG_ATARI_FLOPPY - atari_floppy_init(); -#endif -#ifdef CONFIG_BLK_DEV_FD - floppy_init(); -#else -#if defined(__i386__) /* Do we even need this? */ - outb_p(0xc, 0x3f2); -#endif -#endif -#ifdef CONFIG_CDU31A - cdu31a_init(); -#endif -#ifdef CONFIG_ATARI_ACSI - acsi_init(); -#endif -#ifdef CONFIG_MCD - mcd_init(); -#endif -#ifdef CONFIG_MCDX - mcdx_init(); -#endif -#ifdef CONFIG_SBPCD - sbpcd_init(); -#endif -#ifdef CONFIG_AZTCD - aztcd_init(); -#endif -#ifdef CONFIG_CDU535 - sony535_init(); -#endif -#ifdef CONFIG_GSCD - gscd_init(); -#endif -#ifdef CONFIG_CM206 - cm206_init(); -#endif -#ifdef CONFIG_OPTCD - optcd_init(); -#endif -#ifdef CONFIG_SJCD - sjcd_init(); -#endif -#ifdef CONFIG_APBLOCK - ap_init(); -#endif -#ifdef CONFIG_DDV - ddv_init(); -#endif -#ifdef CONFIG_MDISK - mdisk_init(); -#endif -#ifdef CONFIG_DASD - dasd_init(); -#endif -#if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_BLOCK) - tapeblock_init(); -#endif -#ifdef CONFIG_BLK_DEV_XPRAM - xpram_init(); -#endif - -#ifdef CONFIG_SUN_JSFLASH - jsfd_init(); -#endif - return 0; -}; - -EXPORT_SYMBOL(io_request_lock); -EXPORT_SYMBOL(end_that_request_first); -EXPORT_SYMBOL(end_that_request_last); -EXPORT_SYMBOL(blk_grow_request_list); -EXPORT_SYMBOL(blk_init_queue); -EXPORT_SYMBOL(blk_get_queue); -EXPORT_SYMBOL(blk_cleanup_queue); -EXPORT_SYMBOL(blk_queue_headactive); -EXPORT_SYMBOL(blk_queue_make_request); -EXPORT_SYMBOL(generic_make_request); -EXPORT_SYMBOL(blkdev_release_request); -EXPORT_SYMBOL(req_finished_io); -EXPORT_SYMBOL(generic_unplug_device); -EXPORT_SYMBOL(blk_seg_merge_ok); diff --git a/xen/drivers/block/xen_block.c b/xen/drivers/block/xen_block.c deleted file mode 100644 index 781bca177b..0000000000 --- a/xen/drivers/block/xen_block.c +++ /dev/null @@ -1,663 +0,0 @@ -/****************************************************************************** - * xen_block.c - * - * process incoming block io requests from guestos's. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * These are rather arbitrary. They are fairly large because adjacent requests - * pulled from a communication ring are quite likely to end up being part of - * the same scatter/gather request at the disc. - * - * ** TRY INCREASING 'MAX_PENDING_REQS' IF WRITE SPEEDS SEEM TOO LOW ** - * This will increase the chances of being able to write whole tracks. - * 64 should be enough to keep us competitive with Linux. - */ -#define MAX_PENDING_REQS 64 -#define BATCH_PER_DOMAIN 16 - -/* - * Each outstanding request that we've passed to the lower device layers has a - * 'pending_req' allocated to it. Each buffer_head that completes decrements - * the pendcnt towards zero. When it hits zero, the specified domain has a - * response queued for it, with the saved 'id' passed back. - * - * We can't allocate pending_req's in order, since they may complete out of - * order. We therefore maintain an allocation ring. This ring also indicates - * when enough work has been passed down -- at that point the allocation ring - * will be empty. - */ -static pending_req_t pending_reqs[MAX_PENDING_REQS]; -static unsigned char pending_ring[MAX_PENDING_REQS]; -static spinlock_t pend_prod_lock = SPIN_LOCK_UNLOCKED; -/* NB. We use a different index type to differentiate from shared blk rings. */ -typedef unsigned int PEND_RING_IDX; -#define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1)) -static PEND_RING_IDX pending_prod, pending_cons; -#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons) - -static kmem_cache_t *buffer_head_cachep; - -static struct buffer_head *completed_bhs[NR_CPUS] __cacheline_aligned; - -static int lock_buffer(struct task_struct *p, - unsigned long buffer, - unsigned short size, - int writeable_buffer); -static void unlock_buffer(unsigned long buffer, - unsigned short size, - int writeable_buffer); - -static void io_schedule(unsigned long unused); -static int do_block_io_op_domain(struct task_struct *p, int max_to_do); -static void dispatch_rw_block_io(struct task_struct *p, - blk_ring_req_entry_t *req); -static void make_response(struct task_struct *p, unsigned long id, - unsigned short op, unsigned long st); - - -/****************************************************************** - * BLOCK-DEVICE SCHEDULER LIST MAINTENANCE - */ - -static struct list_head io_schedule_list; -static spinlock_t io_schedule_list_lock; - -static int __on_blkdev_list(struct task_struct *p) -{ - return p->blkdev_list.next != NULL; -} - -static void remove_from_blkdev_list(struct task_struct *p) -{ - unsigned long flags; - if ( !__on_blkdev_list(p) ) return; - spin_lock_irqsave(&io_schedule_list_lock, flags); - if ( __on_blkdev_list(p) ) - { - list_del(&p->blkdev_list); - p->blkdev_list.next = NULL; - put_task_struct(p); - } - spin_unlock_irqrestore(&io_schedule_list_lock, flags); -} - -static void add_to_blkdev_list_tail(struct task_struct *p) -{ - unsigned long flags; - if ( __on_blkdev_list(p) ) return; - spin_lock_irqsave(&io_schedule_list_lock, flags); - if ( !__on_blkdev_list(p) ) - { - list_add_tail(&p->blkdev_list, &io_schedule_list); - get_task_struct(p); - } - spin_unlock_irqrestore(&io_schedule_list_lock, flags); -} - - -/****************************************************************** - * SCHEDULER FUNCTIONS - */ - -static DECLARE_TASKLET(io_schedule_tasklet, io_schedule, 0); - -static void io_schedule(unsigned long unused) -{ - struct task_struct *p; - struct list_head *ent; - - /* Queue up a batch of requests. */ - while ( (NR_PENDING_REQS < MAX_PENDING_REQS) && - !list_empty(&io_schedule_list) ) - { - ent = io_schedule_list.next; - p = list_entry(ent, struct task_struct, blkdev_list); - get_task_struct(p); - remove_from_blkdev_list(p); - if ( do_block_io_op_domain(p, BATCH_PER_DOMAIN) ) - add_to_blkdev_list_tail(p); - put_task_struct(p); - } - - /* Push the batch through to disc. */ - run_task_queue(&tq_disk); -} - -static void maybe_trigger_io_schedule(void) -{ - /* - * Needed so that two processes, who together make the following predicate - * true, don't both read stale values and evaluate the predicate - * incorrectly. Incredibly unlikely to stall the scheduler on x86, but... - */ - smp_mb(); - - if ( (NR_PENDING_REQS < (MAX_PENDING_REQS/2)) && - !list_empty(&io_schedule_list) ) - tasklet_schedule(&io_schedule_tasklet); -} - - - -/****************************************************************** - * COMPLETION CALLBACK -- Called as bh->b_end_io() - */ - -static void end_block_io_op_softirq(struct softirq_action *h) -{ - pending_req_t *pending_req; - struct buffer_head *bh, *nbh; - unsigned int cpu = smp_processor_id(); - - local_irq_disable(); - bh = completed_bhs[cpu]; - completed_bhs[cpu] = NULL; - local_irq_enable(); - - while ( bh != NULL ) - { - pending_req = bh->pending_req; - - unlock_buffer(virt_to_phys(bh->b_data), - bh->b_size, - (pending_req->operation==READ)); - - if ( atomic_dec_and_test(&pending_req->pendcnt) ) - { - make_response(pending_req->domain, pending_req->id, - pending_req->operation, pending_req->status); - put_task_struct(pending_req->domain); - spin_lock(&pend_prod_lock); - pending_ring[MASK_PEND_IDX(pending_prod)] = - pending_req - pending_reqs; - pending_prod++; - spin_unlock(&pend_prod_lock); - maybe_trigger_io_schedule(); - } - - nbh = bh->b_reqnext; - kmem_cache_free(buffer_head_cachep, bh); - bh = nbh; - } -} - -static void end_block_io_op(struct buffer_head *bh, int uptodate) -{ - unsigned long flags; - unsigned int cpu = smp_processor_id(); - - /* An error fails the entire request. */ - if ( !uptodate ) - { - DPRINTK("Buffer not up-to-date at end of operation\n"); - bh->pending_req->status = 2; - } - - local_irq_save(flags); - bh->b_reqnext = completed_bhs[cpu]; - completed_bhs[cpu] = bh; - local_irq_restore(flags); - - __cpu_raise_softirq(cpu, BLKDEV_RESPONSE_SOFTIRQ); -} - - -/* ----[ Syscall Interface ]------------------------------------------------*/ - -long do_block_io_op(block_io_op_t *u_block_io_op) -{ - long ret = 0; - block_io_op_t op; - struct task_struct *p = current; - - if ( unlikely(copy_from_user(&op, u_block_io_op, sizeof(op)) != 0) ) - return -EFAULT; - - switch ( op.cmd ) - { - case BLOCK_IO_OP_SIGNAL: - /* simply indicates there're reqs outstanding => add current to list */ - add_to_blkdev_list_tail(p); - maybe_trigger_io_schedule(); - break; - - case BLOCK_IO_OP_RESET: - /* Avoid a race with the tasklet. */ - remove_from_blkdev_list(p); - if ( p->blk_req_cons != p->blk_resp_prod ) - { - /* Interface isn't quiescent. */ - ret = -EINVAL; - } - else - { - p->blk_req_cons = p->blk_resp_prod = 0; - ret = 0; - } - break; - - case BLOCK_IO_OP_RING_ADDRESS: - op.u.ring_mfn = virt_to_phys(p->blk_ring_base) >> PAGE_SHIFT; - ret = copy_to_user(u_block_io_op, &op, sizeof(op)) ? -EFAULT : 0; - break; - - case BLOCK_IO_OP_VBD_CREATE: - /* create a new VBD */ - ret = vbd_create(&op.u.create_params); - break; - - case BLOCK_IO_OP_VBD_GROW: - /* append an extent to a VBD */ - ret = vbd_grow(&op.u.grow_params); - break; - - case BLOCK_IO_OP_VBD_SHRINK: - /* remove teh final extent from a VBD */ - ret = vbd_shrink(&op.u.shrink_params); - break; - - case BLOCK_IO_OP_VBD_SET_EXTENTS: - /* a fresh extent list for the given VBD */ - ret = vbd_setextents(&op.u.setextents_params); - break; - - case BLOCK_IO_OP_VBD_DELETE: - /* delete a VBD */ - ret = vbd_delete(&op.u.delete_params); - break; - - case BLOCK_IO_OP_VBD_PROBE: - /* query VBD information for self or others (or all) */ - if ( (ret = vbd_probe(&op.u.probe_params)) == 0 ) - copy_to_user(u_block_io_op, &op, sizeof(op)); - break; - - case BLOCK_IO_OP_VBD_INFO: - /* query information about a particular VBD */ - if ( (ret = vbd_info(&op.u.info_params)) == 0 ) - copy_to_user(u_block_io_op, &op, sizeof(op)); - break; - - default: - ret = -ENOSYS; - } - - return ret; -} - - - -/****************************************************************** - * DOWNWARD CALLS -- These interface with the block-device layer proper. - */ - -static int lock_buffer(struct task_struct *p, - unsigned long buffer, - unsigned short size, - int writeable_buffer) -{ - unsigned long pfn; - struct pfn_info *page; - - for ( pfn = buffer >> PAGE_SHIFT; - pfn < ((buffer + size + PAGE_SIZE - 1) >> PAGE_SHIFT); - pfn++ ) - { - if ( unlikely(pfn >= max_page) ) - goto fail; - - page = &frame_table[pfn]; - - if ( unlikely(!get_page(page, p)) ) - goto fail; - - if ( writeable_buffer && - unlikely(!get_page_type(page, PGT_writeable_page)) ) - { - put_page(page); - goto fail; - } - } - - return 1; - - fail: - while ( pfn-- > (buffer >> PAGE_SHIFT) ) - { - if ( writeable_buffer ) - put_page_type(&frame_table[pfn]); - put_page(&frame_table[pfn]); - } - return 0; -} - -static void unlock_buffer(unsigned long buffer, - unsigned short size, - int writeable_buffer) -{ - unsigned long pfn; - - for ( pfn = buffer >> PAGE_SHIFT; - pfn < ((buffer + size + PAGE_SIZE - 1) >> PAGE_SHIFT); - pfn++ ) - { - - /* Find the domain from the frame_table. Yuk... */ - struct task_struct *p = frame_table[pfn].u.domain; - - if( p->mm.shadow_mode == SHM_logdirty ) - mark_dirty( &p->mm, pfn ); - - - if ( writeable_buffer ) - put_page_type(&frame_table[pfn]); - put_page(&frame_table[pfn]); - - } -} - -static int do_block_io_op_domain(struct task_struct *p, int max_to_do) -{ - blk_ring_t *blk_ring = p->blk_ring_base; - blk_ring_req_entry_t *req; - BLK_RING_IDX i; - int more_to_do = 0; - - /* Take items off the comms ring, taking care not to overflow. */ - for ( i = p->blk_req_cons; - (i != blk_ring->req_prod) && ((i-p->blk_resp_prod) != BLK_RING_SIZE); - i++ ) - { - if ( (max_to_do-- == 0) || (NR_PENDING_REQS == MAX_PENDING_REQS) ) - { - more_to_do = 1; - break; - } - - req = &blk_ring->ring[MASK_BLK_IDX(i)].req; - switch ( req->operation ) - { - case XEN_BLOCK_READ: - case XEN_BLOCK_WRITE: - dispatch_rw_block_io(p, req); - break; - - default: - DPRINTK("error: unknown block io operation [%d]\n", - blk_ring->ring[i].req.operation); - make_response(p, blk_ring->ring[i].req.id, - blk_ring->ring[i].req.operation, 1); - break; - } - } - - p->blk_req_cons = i; - return more_to_do; -} - -static void dispatch_rw_block_io(struct task_struct *p, - blk_ring_req_entry_t *req) -{ - extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]); - struct buffer_head *bh; - int operation = (req->operation == XEN_BLOCK_WRITE) ? WRITE : READ; - unsigned short nr_sects; - unsigned long buffer; - int i, tot_sects; - pending_req_t *pending_req; - - /* We map virtual scatter/gather segments to physical segments. */ - int new_segs, nr_psegs = 0; - phys_seg_t phys_seg[MAX_BLK_SEGS * 2]; - - /* Check that number of segments is sane. */ - if ( unlikely(req->nr_segments == 0) || - unlikely(req->nr_segments > MAX_BLK_SEGS) ) - { - DPRINTK("Bad number of segments in request (%d)\n", req->nr_segments); - goto bad_descriptor; - } - - /* - * Check each address/size pair is sane, and convert into a - * physical device and block offset. Note that if the offset and size - * crosses a virtual extent boundary, we may end up with more - * physical scatter/gather segments than virtual segments. - */ - for ( i = tot_sects = 0; i < req->nr_segments; i++, tot_sects += nr_sects ) - { - buffer = req->buffer_and_sects[i] & ~0x1FF; - nr_sects = req->buffer_and_sects[i] & 0x1FF; - - if ( unlikely(nr_sects == 0) ) - { - DPRINTK("zero-sized data request\n"); - goto bad_descriptor; - } - - phys_seg[nr_psegs].dev = req->device; - phys_seg[nr_psegs].sector_number = req->sector_number + tot_sects; - phys_seg[nr_psegs].buffer = buffer; - phys_seg[nr_psegs].nr_sects = nr_sects; - - /* Translate the request into the relevant 'physical device' */ - new_segs = vbd_translate(&phys_seg[nr_psegs], p, operation); - if ( new_segs < 0 ) - { - DPRINTK("access denied: %s of [%llu,%llu] on dev=%04x\n", - operation == READ ? "read" : "write", - req->sector_number + tot_sects, - req->sector_number + tot_sects + nr_sects, - req->device); - goto bad_descriptor; - } - - nr_psegs += new_segs; - ASSERT(nr_psegs <= MAX_BLK_SEGS*2); - } - - for ( i = 0; i < nr_psegs; i++ ) - { - if ( unlikely(!lock_buffer(p, phys_seg[i].buffer, - phys_seg[i].nr_sects << 9, - operation==READ)) ) - { - DPRINTK("invalid buffer\n"); - while ( i-- > 0 ) - unlock_buffer(phys_seg[i].buffer, - phys_seg[i].nr_sects << 9, - operation==READ); - goto bad_descriptor; - } - } - - pending_req = &pending_reqs[pending_ring[MASK_PEND_IDX(pending_cons++)]]; - pending_req->domain = p; - pending_req->id = req->id; - pending_req->operation = operation; - pending_req->status = 0; - atomic_set(&pending_req->pendcnt, nr_psegs); - - get_task_struct(p); - - /* Now we pass each segment down to the real blkdev layer. */ - for ( i = 0; i < nr_psegs; i++ ) - { - bh = kmem_cache_alloc(buffer_head_cachep, GFP_KERNEL); - if ( unlikely(bh == NULL) ) - panic("bh is null\n"); - memset(bh, 0, sizeof (struct buffer_head)); - - bh->b_size = phys_seg[i].nr_sects << 9; - bh->b_dev = phys_seg[i].dev; - bh->b_rsector = (unsigned long)phys_seg[i].sector_number; - - /* SMH: we store a 'pseudo-virtual' bogus address in b_data since - later code will undo this transformation (i.e. +-PAGE_OFFSET). */ - bh->b_data = phys_to_virt(phys_seg[i].buffer); - - /* SMH: bh_phys() uses the below field as a 'cheap' virt_to_phys */ - bh->b_page = &frame_table[phys_seg[i].buffer>>PAGE_SHIFT]; - bh->b_end_io = end_block_io_op; - bh->pending_req = pending_req; - - if ( operation == WRITE ) - { - bh->b_state = (1 << BH_JBD) | (1 << BH_Mapped) | (1 << BH_Req) | - (1 << BH_Dirty) | (1 << BH_Uptodate) | (1 << BH_Write); - } - else - { - bh->b_state = (1 << BH_Mapped) | (1 << BH_Read); - } - - /* Dispatch a single request. We'll flush it to disc later. */ - ll_rw_block(operation, 1, &bh); - } - - return; - - bad_descriptor: - make_response(p, req->id, req->operation, 1); -} - - - -/****************************************************************** - * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING - */ - - -static void make_response(struct task_struct *p, unsigned long id, - unsigned short op, unsigned long st) -{ - blk_ring_resp_entry_t *resp; - - /* Place on the response ring for the relevant domain. */ - spin_lock(&p->blk_ring_lock); - resp = &p->blk_ring_base->ring[MASK_BLK_IDX(p->blk_resp_prod)].resp; - resp->id = id; - resp->operation = op; - resp->status = st; - wmb(); - p->blk_ring_base->resp_prod = ++p->blk_resp_prod; - spin_unlock(&p->blk_ring_lock); - - /* Kick the relevant domain. */ - send_guest_virq(p, VIRQ_BLKDEV); -} - -static void dump_blockq(u_char key, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct task_struct *p; - blk_ring_t *blk_ring; - int i; - - printk("Dumping block queue stats: nr_pending = %d" - " (prod=0x%08x,cons=0x%08x)\n", - NR_PENDING_REQS, pending_prod, pending_cons); - - read_lock_irqsave(&tasklist_lock, flags); - for_each_domain ( p ) - { - printk("Domain: %u\n", p->domain); - blk_ring = p->blk_ring_base; - printk(" req_prod:0x%08x, req_cons:0x%08x resp_prod:0x%08x/" - "0x%08x on_list=%d\n", - blk_ring->req_prod, p->blk_req_cons, - blk_ring->resp_prod, p->blk_resp_prod, - __on_blkdev_list(p)); - } - read_unlock_irqrestore(&tasklist_lock, flags); - - for ( i = 0; i < MAX_PENDING_REQS; i++ ) - { - printk("Pend%d: dom=%p, id=%08lx, cnt=%d, op=%d, status=%d\n", - i, pending_reqs[i].domain, pending_reqs[i].id, - atomic_read(&pending_reqs[i].pendcnt), - pending_reqs[i].operation, pending_reqs[i].status); - } -} - -/* Start-of-day initialisation for a new domain. */ -void init_blkdev_info(struct task_struct *p) -{ - if ( unlikely(sizeof(*p->blk_ring_base) > PAGE_SIZE) ) - BUG(); - - p->blk_ring_base = (blk_ring_t *)get_free_page(GFP_KERNEL); - clear_page(p->blk_ring_base); - SHARE_PFN_WITH_DOMAIN(virt_to_page(p->blk_ring_base), p); - - machine_to_phys_mapping[virt_to_phys(p->blk_ring_base)>>PAGE_SHIFT] = - 0x80000002; // magic value aids debugging - - p->blkdev_list.next = NULL; - spin_lock_init(&p->vbd_lock); -} - -/* End-of-day teardown for a domain. */ -void destroy_blkdev_info(struct task_struct *p) -{ - ASSERT(!__on_blkdev_list(p)); - UNSHARE_PFN(virt_to_page(p->blk_ring_base)); - destroy_all_vbds(p); -} - -void unlink_blkdev_info(struct task_struct *p) -{ - unsigned long flags; - - spin_lock_irqsave(&io_schedule_list_lock, flags); - if ( __on_blkdev_list(p) ) - { - list_del(&p->blkdev_list); - p->blkdev_list.next = (void *)0xdeadbeef; /* prevent reinsertion */ - put_task_struct(p); - } - spin_unlock_irqrestore(&io_schedule_list_lock, flags); -} - -void initialize_block_io () -{ - int i; - - pending_cons = 0; - pending_prod = MAX_PENDING_REQS; - memset(pending_reqs, 0, sizeof(pending_reqs)); - for ( i = 0; i < MAX_PENDING_REQS; i++ ) - pending_ring[i] = i; - - for ( i = 0; i < NR_CPUS; i++ ) - completed_bhs[i] = NULL; - - open_softirq(BLKDEV_RESPONSE_SOFTIRQ, end_block_io_op_softirq, NULL); - - spin_lock_init(&io_schedule_list_lock); - INIT_LIST_HEAD(&io_schedule_list); - - buffer_head_cachep = kmem_cache_create( - "buffer_head_cache", sizeof(struct buffer_head), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - - add_key_handler('b', dump_blockq, "dump xen ide blkdev statistics"); -} diff --git a/xen/drivers/block/xen_vbd.c b/xen/drivers/block/xen_vbd.c deleted file mode 100644 index dc1154a2f9..0000000000 --- a/xen/drivers/block/xen_vbd.c +++ /dev/null @@ -1,726 +0,0 @@ -/****************************************************************************** - * xen_vbd.c - * - * Routines for managing virtual block devices. - * - * Copyright (c) 2003-2004, Keir Fraser & Steve Hand - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -long __vbd_create(struct task_struct *p, - unsigned short vdevice, - unsigned char mode, - unsigned char type) -{ - vbd_t *vbd; - rb_node_t **rb_p, *rb_parent = NULL; - long ret = 0; - - spin_lock(&p->vbd_lock); - - rb_p = &p->vbd_rb.rb_node; - while ( *rb_p != NULL ) - { - rb_parent = *rb_p; - vbd = rb_entry(rb_parent, vbd_t, rb); - if ( vdevice < vbd->vdevice ) - { - rb_p = &rb_parent->rb_left; - } - else if ( vdevice > vbd->vdevice ) - { - rb_p = &rb_parent->rb_right; - } - else - { - DPRINTK("vbd_create attempted for already existing vbd\n"); - ret = -EINVAL; - goto out; - } - } - - if ( unlikely((vbd = kmalloc(sizeof(vbd_t), GFP_KERNEL)) == NULL) ) - { - DPRINTK("vbd_create: out of memory\n"); - ret = -ENOMEM; - goto out; - } - - vbd->vdevice = vdevice; - vbd->mode = mode; - vbd->type = type; - vbd->extents = NULL; - - rb_link_node(&vbd->rb, rb_parent, rb_p); - rb_insert_color(&vbd->rb, &p->vbd_rb); - - send_guest_virq(p, VIRQ_VBD_UPD); - - out: - spin_unlock(&p->vbd_lock); - return ret; -} - - -long vbd_create(vbd_create_t *create) -{ - struct task_struct *p; - long rc; - - if ( unlikely(!IS_PRIV(current)) ) - return -EPERM; - - if ( unlikely((p = find_domain_by_id(create->domain)) == NULL) ) - { - DPRINTK("vbd_create attempted for non-existent domain %u\n", - create->domain); - return -EINVAL; - } - - rc = __vbd_create(p, create->vdevice, create->mode, - XD_TYPE_DISK | XD_FLAG_VIRT); - - put_task_struct(p); - - return rc; -} - - -long __vbd_grow(struct task_struct *p, - unsigned short vdevice, - xen_extent_t *extent) -{ - xen_extent_le_t **px, *x; - vbd_t *vbd = NULL; - rb_node_t *rb; - long ret = 0; - - spin_lock(&p->vbd_lock); - - rb = p->vbd_rb.rb_node; - while ( rb != NULL ) - { - vbd = rb_entry(rb, vbd_t, rb); - if ( vdevice < vbd->vdevice ) - rb = rb->rb_left; - else if ( vdevice > vbd->vdevice ) - rb = rb->rb_right; - else - break; - } - - if ( unlikely(vbd == NULL) || unlikely(vbd->vdevice != vdevice) ) - { - DPRINTK("vbd_grow: attempted to append extent to non-existent VBD.\n"); - ret = -EINVAL; - goto out; - } - - if ( unlikely((x = kmalloc(sizeof(xen_extent_le_t), GFP_KERNEL)) == NULL) ) - { - DPRINTK("vbd_grow: out of memory\n"); - ret = -ENOMEM; - goto out; - } - - x->extent.device = extent->device; - x->extent.start_sector = extent->start_sector; - x->extent.nr_sectors = extent->nr_sectors; - x->next = (xen_extent_le_t *)NULL; - - for ( px = &vbd->extents; *px != NULL; px = &(*px)->next ) - continue; - - *px = x; - - send_guest_virq(p, VIRQ_VBD_UPD); - - out: - spin_unlock(&p->vbd_lock); - return ret; -} - - -/* Grow a VBD by appending a new extent. Fails if the VBD doesn't exist. */ -long vbd_grow(vbd_grow_t *grow) -{ - struct task_struct *p; - long rc; - - if ( unlikely(!IS_PRIV(current)) ) - return -EPERM; - - if ( unlikely((p = find_domain_by_id(grow->domain)) == NULL) ) - { - DPRINTK("vbd_grow: attempted for non-existent domain %u\n", - grow->domain); - return -EINVAL; - } - - rc = __vbd_grow(p, grow->vdevice, &grow->extent); - - put_task_struct(p); - - return rc; -} - - -long vbd_shrink(vbd_shrink_t *shrink) -{ - struct task_struct *p; - xen_extent_le_t **px, *x; - vbd_t *vbd = NULL; - rb_node_t *rb; - long ret = 0; - - if ( !IS_PRIV(current) ) - return -EPERM; - - if ( (p = find_domain_by_id(shrink->domain)) == NULL ) - { - DPRINTK("vbd_shrink attempted for non-existent domain %u\n", - shrink->domain); - return -EINVAL; - } - - spin_lock(&p->vbd_lock); - - rb = p->vbd_rb.rb_node; - while ( rb != NULL ) - { - vbd = rb_entry(rb, vbd_t, rb); - if ( shrink->vdevice < vbd->vdevice ) - rb = rb->rb_left; - else if ( shrink->vdevice > vbd->vdevice ) - rb = rb->rb_right; - else - break; - } - - if ( unlikely(vbd == NULL) || - unlikely(vbd->vdevice != shrink->vdevice) || - unlikely(vbd->extents == NULL) ) - { - DPRINTK("vbd_shrink: attempt to remove non-existent extent.\n"); - ret = -EINVAL; - goto out; - } - - /* Find the last extent. We now know that there is at least one. */ - for ( px = &vbd->extents; (*px)->next != NULL; px = &(*px)->next ) - continue; - - x = *px; - *px = x->next; - kfree(x); - - send_guest_virq(p, VIRQ_VBD_UPD); - - out: - spin_unlock(&p->vbd_lock); - put_task_struct(p); - return ret; -} - - -long vbd_setextents(vbd_setextents_t *setextents) -{ - struct task_struct *p; - xen_extent_t e; - xen_extent_le_t *new_extents, *x, *t; - vbd_t *vbd = NULL; - rb_node_t *rb; - int i; - long ret = 0; - - if ( !IS_PRIV(current) ) - return -EPERM; - - if ( (p = find_domain_by_id(setextents->domain)) == NULL ) - { - DPRINTK("vbd_setextents attempted for non-existent domain %u\n", - setextents->domain); - return -EINVAL; - } - - spin_lock(&p->vbd_lock); - - rb = p->vbd_rb.rb_node; - while ( rb != NULL ) - { - vbd = rb_entry(rb, vbd_t, rb); - if ( setextents->vdevice < vbd->vdevice ) - rb = rb->rb_left; - else if ( setextents->vdevice > vbd->vdevice ) - rb = rb->rb_right; - else - break; - } - - if ( unlikely(vbd == NULL) || - unlikely(vbd->vdevice != setextents->vdevice) ) - { - DPRINTK("vbd_setextents: attempt to modify non-existent VBD.\n"); - ret = -EINVAL; - goto out; - } - - /* Construct the new extent list. */ - new_extents = NULL; - for ( i = setextents->nr_extents - 1; i >= 0; i-- ) - { - if ( unlikely(copy_from_user(&e, - &setextents->extents[i], - sizeof(e)) != 0) ) - { - DPRINTK("vbd_setextents: copy_from_user failed\n"); - ret = -EFAULT; - goto free_and_out; - } - - if ( unlikely((x = kmalloc(sizeof(xen_extent_le_t), GFP_KERNEL)) - == NULL) ) - { - DPRINTK("vbd_setextents: out of memory\n"); - ret = -ENOMEM; - goto free_and_out; - } - - x->extent = e; - x->next = new_extents; - - new_extents = x; - } - - /* Delete the old extent list _after_ successfully creating the new. */ - for ( x = vbd->extents; x != NULL; x = t ) - { - t = x->next; - kfree(x); - } - - /* Make the new list visible. */ - vbd->extents = new_extents; - - send_guest_virq(p, VIRQ_VBD_UPD); - - out: - spin_unlock(&p->vbd_lock); - put_task_struct(p); - return ret; - - free_and_out: - /* Failed part-way through the new list. Delete all that we managed. */ - for ( x = new_extents; x != NULL; x = t ) - { - t = x->next; - kfree(x); - } - goto out; -} - - -long vbd_delete(vbd_delete_t *delete) -{ - struct task_struct *p; - vbd_t *vbd; - rb_node_t *rb; - xen_extent_le_t *x, *t; - - if( !IS_PRIV(current) ) - return -EPERM; - - if ( (p = find_domain_by_id(delete->domain)) == NULL ) - { - DPRINTK("vbd_delete attempted for non-existent domain %u\n", - delete->domain); - return -EINVAL; - } - - spin_lock(&p->vbd_lock); - - rb = p->vbd_rb.rb_node; - while ( rb != NULL ) - { - vbd = rb_entry(rb, vbd_t, rb); - if ( delete->vdevice < vbd->vdevice ) - rb = rb->rb_left; - else if ( delete->vdevice > vbd->vdevice ) - rb = rb->rb_right; - else - goto found; - } - - DPRINTK("vbd_delete attempted for non-existing VBD.\n"); - - spin_unlock(&p->vbd_lock); - put_task_struct(p); - return -EINVAL; - - found: - rb_erase(rb, &p->vbd_rb); - x = vbd->extents; - kfree(vbd); - - while ( x != NULL ) - { - t = x->next; - kfree(x); - x = t; - } - - send_guest_virq(p, VIRQ_VBD_UPD); - - spin_unlock(&p->vbd_lock); - put_task_struct(p); - return 0; -} - - -void destroy_all_vbds(struct task_struct *p) -{ - vbd_t *vbd; - rb_node_t *rb; - xen_extent_le_t *x, *t; - - spin_lock(&p->vbd_lock); - - while ( (rb = p->vbd_rb.rb_node) != NULL ) - { - vbd = rb_entry(rb, vbd_t, rb); - - rb_erase(rb, &p->vbd_rb); - x = vbd->extents; - kfree(vbd); - - while ( x != NULL ) - { - t = x->next; - kfree(x); - x = t; - } - } - - send_guest_virq(p, VIRQ_VBD_UPD); - - spin_unlock(&p->vbd_lock); -} - - -static int vbd_probe_single(xen_disk_info_t *xdi, - vbd_t *vbd, - struct task_struct *p) -{ - xen_extent_le_t *x; - xen_disk_t cur_disk; - - if ( xdi->count == xdi->max ) - { - DPRINTK("vbd_probe_devices: out of space for probe.\n"); - return -ENOMEM; - } - - cur_disk.device = vbd->vdevice; - cur_disk.info = vbd->type; - if ( !VBD_CAN_WRITE(vbd) ) - cur_disk.info |= XD_FLAG_RO; - cur_disk.capacity = 0ULL; - for ( x = vbd->extents; x != NULL; x = x->next ) - cur_disk.capacity += x->extent.nr_sectors; - cur_disk.domain = p->domain; - - /* Now copy into relevant part of user-space buffer */ - if( copy_to_user(&xdi->disks[xdi->count], - &cur_disk, - sizeof(xen_disk_t)) ) - { - DPRINTK("vbd_probe_devices: copy_to_user failed\n"); - return -EFAULT; - } - - xdi->count++; - - return 0; -} - - -static int vbd_probe_devices(xen_disk_info_t *xdi, struct task_struct *p) -{ - int rc = 0; - rb_node_t *rb; - - spin_lock(&p->vbd_lock); - - if ( (rb = p->vbd_rb.rb_node) == NULL ) - goto out; - - new_subtree: - /* STEP 1. Find least node (it'll be left-most). */ - while ( rb->rb_left != NULL ) - rb = rb->rb_left; - - for ( ; ; ) - { - /* STEP 2. Dealt with left subtree. Now process current node. */ - if ( (rc = vbd_probe_single(xdi, rb_entry(rb, vbd_t, rb), p)) != 0 ) - goto out; - - /* STEP 3. Process right subtree, if any. */ - if ( rb->rb_right != NULL ) - { - rb = rb->rb_right; - goto new_subtree; - } - - /* STEP 4. Done both subtrees. Head back through ancesstors. */ - for ( ; ; ) - { - /* We're done when we get back to the root node. */ - if ( rb->rb_parent == NULL ) - goto out; - /* If we are left of parent, then parent is next to process. */ - if ( rb->rb_parent->rb_left == rb ) - break; - /* If we are right of parent, then we climb to grandparent. */ - rb = rb->rb_parent; - } - - rb = rb->rb_parent; - } - - out: - spin_unlock(&p->vbd_lock); - return rc; -} - - -/* - * Return information about the VBDs available for a given domain, or for all - * domains; in the general case the 'domain' argument will be 0 which means - * "information about the caller"; otherwise the 'domain' argument will - * specify either a given domain, or all domains ("VBD_PROBE_ALL") -- both of - * these cases require the caller to be privileged. - */ -long vbd_probe(vbd_probe_t *probe) -{ - struct task_struct *p = NULL; - unsigned long flags; - long ret = 0; - - if ( probe->domain != 0 ) - { - /* We can only probe for ourselves (unless we're privileged). */ - if( (probe->domain != current->domain) && !IS_PRIV(current) ) - return -EPERM; - - if ( (probe->domain != VBD_PROBE_ALL) && - ((p = find_domain_by_id(probe->domain)) == NULL) ) - { - DPRINTK("vbd_probe attempted for non-existent domain %u\n", - probe->domain); - return -EINVAL; - } - } - else - { - /* Default is to probe for ourselves. */ - p = current; - get_task_struct(p); /* to mirror final put_task_struct */ - } - - if ( probe->domain == VBD_PROBE_ALL ) - { - read_lock_irqsave(&tasklist_lock, flags); - for_each_domain ( p ) - { - if ( (ret = vbd_probe_devices(&probe->xdi, p)) != 0 ) - { - read_unlock_irqrestore(&tasklist_lock, flags); - goto out; - } - } - read_unlock_irqrestore(&tasklist_lock, flags); - } - else if ( (ret = vbd_probe_devices(&probe->xdi, p)) != 0 ) - goto out; - - out: - if ( ret != 0 ) - DPRINTK("vbd_probe: err %ld in probing virtual devices\n", ret); - if ( p != NULL ) - put_task_struct(p); - return ret; -} - - -long vbd_info(vbd_info_t *info) -{ - struct task_struct *p; - xen_extent_le_t *x; - xen_extent_t *extents; - vbd_t *vbd = NULL; - rb_node_t *rb; - long ret = 0; - - if ( (info->domain != current->domain) && !IS_PRIV(current) ) - return -EPERM; - - if ( (p = find_domain_by_id(info->domain)) == NULL ) - { - DPRINTK("vbd_info attempted for non-existent domain %u\n", - info->domain); - return -EINVAL; - } - - spin_lock(&p->vbd_lock); - - rb = p->vbd_rb.rb_node; - while ( rb != NULL ) - { - vbd = rb_entry(rb, vbd_t, rb); - if ( info->vdevice < vbd->vdevice ) - rb = rb->rb_left; - else if ( info->vdevice > vbd->vdevice ) - rb = rb->rb_right; - else - break; - } - - if ( unlikely(vbd == NULL) || unlikely(vbd->vdevice != info->vdevice) ) - { - DPRINTK("vbd_info attempted on non-existent VBD.\n"); - ret = -EINVAL; - goto out; - } - - info->mode = vbd->mode; - info->nextents = 0; - - extents = info->extents; - for ( x = vbd->extents; x != NULL; x = x->next ) - { - if ( info->nextents == info->maxextents ) - break; - if ( copy_to_user(extents, &x->extent, sizeof(xen_extent_t)) ) - { - DPRINTK("vbd_info: copy_to_user failed\n"); - ret = -EFAULT; - goto out; - } - extents++; - info->nextents++; - } - - out: - spin_unlock(&p->vbd_lock); - put_task_struct(p); - return ret; -} - - -int vbd_translate(phys_seg_t *pseg, struct task_struct *p, int operation) -{ - xen_extent_le_t *x; - vbd_t *vbd; - rb_node_t *rb; - xen_sector_t sec_off; - unsigned long nr_secs; - - spin_lock(&p->vbd_lock); - - rb = p->vbd_rb.rb_node; - while ( rb != NULL ) - { - vbd = rb_entry(rb, vbd_t, rb); - if ( pseg->dev < vbd->vdevice ) - rb = rb->rb_left; - else if ( pseg->dev > vbd->vdevice ) - rb = rb->rb_right; - else - goto found; - } - - DPRINTK("vbd_translate; domain %u attempted to access " - "non-existent VBD.\n", p->domain); - - spin_unlock(&p->vbd_lock); - return -ENODEV; - - found: - - if ( ((operation == READ) && !VBD_CAN_READ(vbd)) || - ((operation == WRITE) && !VBD_CAN_WRITE(vbd)) ) - { - spin_unlock(&p->vbd_lock); - return -EACCES; - } - - /* - * Now iterate through the list of xen_extents, working out which should - * be used to perform the translation. - */ - sec_off = pseg->sector_number; - nr_secs = pseg->nr_sects; - for ( x = vbd->extents; x != NULL; x = x->next ) - { - if ( sec_off < x->extent.nr_sectors ) - { - pseg->dev = x->extent.device; - pseg->sector_number = x->extent.start_sector + sec_off; - if ( unlikely((sec_off + nr_secs) > x->extent.nr_sectors) ) - goto overrun; - spin_unlock(&p->vbd_lock); - return 1; - } - sec_off -= x->extent.nr_sectors; - } - - DPRINTK("vbd_translate: end of vbd.\n"); - spin_unlock(&p->vbd_lock); - return -EACCES; - - /* - * Here we deal with overrun onto the following extent. We don't deal with - * overrun of more than one boundary since each request is restricted to - * 2^9 512-byte sectors, so it should be trivial for control software to - * ensure that extents are large enough to prevent excessive overrun. - */ - overrun: - - /* Adjust length of first chunk to run to end of first extent. */ - pseg[0].nr_sects = x->extent.nr_sectors - sec_off; - - /* Set second chunk buffer and length to start where first chunk ended. */ - pseg[1].buffer = pseg[0].buffer + (pseg[0].nr_sects << 9); - pseg[1].nr_sects = nr_secs - pseg[0].nr_sects; - - /* Now move to the next extent. Check it exists and is long enough! */ - if ( unlikely((x = x->next) == NULL) || - unlikely(x->extent.nr_sectors < pseg[1].nr_sects) ) - { - DPRINTK("vbd_translate: multiple overruns or end of vbd.\n"); - spin_unlock(&p->vbd_lock); - return -EACCES; - } - - /* Store the real device and start sector for the second chunk. */ - pseg[1].dev = x->extent.device; - pseg[1].sector_number = x->extent.start_sector; - - spin_unlock(&p->vbd_lock); - return 2; -} diff --git a/xen/drivers/cdrom/Makefile b/xen/drivers/cdrom/Makefile deleted file mode 100644 index 729f949b73..0000000000 --- a/xen/drivers/cdrom/Makefile +++ /dev/null @@ -1,7 +0,0 @@ - -include $(BASEDIR)/Rules.mk - -default: $(OBJS) - $(LD) -r -o driver.o $(OBJS) -clean: - rm -f *.o *~ core diff --git a/xen/drivers/cdrom/cdrom.c b/xen/drivers/cdrom/cdrom.c deleted file mode 100644 index db7970e86b..0000000000 --- a/xen/drivers/cdrom/cdrom.c +++ /dev/null @@ -1,2662 +0,0 @@ -/* linux/drivers/cdrom/cdrom.c. - Copyright (c) 1996, 1997 David A. van Leeuwen. - Copyright (c) 1997, 1998 Erik Andersen - Copyright (c) 1998, 1999 Jens Axboe - - May be copied or modified under the terms of the GNU General Public - License. See linux/COPYING for more information. - - Uniform CD-ROM driver for Linux. - See Documentation/cdrom/cdrom-standard.tex for usage information. - - The routines in the file provide a uniform interface between the - software that uses CD-ROMs and the various low-level drivers that - actually talk to the hardware. Suggestions are welcome. - Patches that work are more welcome though. ;-) - - To Do List: - ---------------------------------- - - -- Modify sysctl/proc interface. I plan on having one directory per - drive, with entries for outputing general drive information, and sysctl - based tunable parameters such as whether the tray should auto-close for - that drive. Suggestions (or patches) for this welcome! - - - Revision History - ---------------------------------- - 1.00 Date Unknown -- David van Leeuwen - -- Initial version by David A. van Leeuwen. I don't have a detailed - changelog for the 1.x series, David? - -2.00 Dec 2, 1997 -- Erik Andersen - -- New maintainer! As David A. van Leeuwen has been too busy to activly - maintain and improve this driver, I am now carrying on the torch. If - you have a problem with this driver, please feel free to contact me. - - -- Added (rudimentary) sysctl interface. I realize this is really weak - right now, and is _very_ badly implemented. It will be improved... - - -- Modified CDROM_DISC_STATUS so that it is now incorporated into - the Uniform CD-ROM driver via the cdrom_count_tracks function. - The cdrom_count_tracks function helps resolve some of the false - assumptions of the CDROM_DISC_STATUS ioctl, and is also used to check - for the correct media type when mounting or playing audio from a CD. - - -- Remove the calls to verify_area and only use the copy_from_user and - copy_to_user stuff, since these calls now provide their own memory - checking with the 2.1.x kernels. - - -- Major update to return codes so that errors from low-level drivers - are passed on through (thanks to Gerd Knorr for pointing out this - problem). - - -- Made it so if a function isn't implemented in a low-level driver, - ENOSYS is now returned instead of EINVAL. - - -- Simplified some complex logic so that the source code is easier to read. - - -- Other stuff I probably forgot to mention (lots of changes). - -2.01 to 2.11 Dec 1997-Jan 1998 - -- TO-DO! Write changelogs for 2.01 to 2.12. - -2.12 Jan 24, 1998 -- Erik Andersen - -- Fixed a bug in the IOCTL_IN and IOCTL_OUT macros. It turns out that - copy_*_user does not return EFAULT on error, but instead returns the number - of bytes not copied. I was returning whatever non-zero stuff came back from - the copy_*_user functions directly, which would result in strange errors. - -2.13 July 17, 1998 -- Erik Andersen - -- Fixed a bug in CDROM_SELECT_SPEED where you couldn't lower the speed - of the drive. Thanks to Tobias Ringstr|m for pointing - this out and providing a simple fix. - -- Fixed the procfs-unload-module bug with the fill_inode procfs callback. - thanks to Andrea Arcangeli - -- Fixed it so that the /proc entry now also shows up when cdrom is - compiled into the kernel. Before it only worked when loaded as a module. - - 2.14 August 17, 1998 -- Erik Andersen - -- Fixed a bug in cdrom_media_changed and handling of reporting that - the media had changed for devices that _don't_ implement media_changed. - Thanks to Grant R. Guenther for spotting this bug. - -- Made a few things more pedanticly correct. - -2.50 Oct 19, 1998 - Jens Axboe - -- New maintainers! Erik was too busy to continue the work on the driver, - so now Chris Zwilling and Jens Axboe - will do their best to follow in his footsteps - - 2.51 Dec 20, 1998 - Jens Axboe - -- Check if drive is capable of doing what we ask before blindly changing - cdi->options in various ioctl. - -- Added version to proc entry. - - 2.52 Jan 16, 1999 - Jens Axboe - -- Fixed an error in open_for_data where we would sometimes not return - the correct error value. Thanks Huba Gaspar . - -- Fixed module usage count - usage was based on /proc/sys/dev - instead of /proc/sys/dev/cdrom. This could lead to an oops when other - modules had entries in dev. Feb 02 - real bug was in sysctl.c where - dev would be removed even though it was used. cdrom.c just illuminated - that bug. - - 2.53 Feb 22, 1999 - Jens Axboe - -- Fixup of several ioctl calls, in particular CDROM_SET_OPTIONS has - been "rewritten" because capabilities and options aren't in sync. They - should be... - -- Added CDROM_LOCKDOOR ioctl. Locks the door and keeps it that way. - -- Added CDROM_RESET ioctl. - -- Added CDROM_DEBUG ioctl. Enable debug messages on-the-fly. - -- Added CDROM_GET_CAPABILITY ioctl. This relieves userspace programs - from parsing /proc/sys/dev/cdrom/info. - - 2.54 Mar 15, 1999 - Jens Axboe - -- Check capability mask from low level driver when counting tracks as - per suggestion from Corey J. Scotts . - - 2.55 Apr 25, 1999 - Jens Axboe - -- autoclose was mistakenly checked against CDC_OPEN_TRAY instead of - CDC_CLOSE_TRAY. - -- proc info didn't mask against capabilities mask. - - 3.00 Aug 5, 1999 - Jens Axboe - -- Unified audio ioctl handling across CD-ROM drivers. A lot of the - code was duplicated before. Drives that support the generic packet - interface are now being fed packets from here instead. - -- First attempt at adding support for MMC2 commands - for DVD and - CD-R(W) drives. Only the DVD parts are in now - the interface used is - the same as for the audio ioctls. - -- ioctl cleanups. if a drive couldn't play audio, it didn't get - a change to perform device specific ioctls as well. - -- Defined CDROM_CAN(CDC_XXX) for checking the capabilities. - -- Put in sysctl files for autoclose, autoeject, check_media, debug, - and lock. - -- /proc/sys/dev/cdrom/info has been updated to also contain info about - CD-Rx and DVD capabilities. - -- Now default to checking media type. - -- CDROM_SEND_PACKET ioctl added. The infrastructure was in place for - doing this anyway, with the generic_packet addition. - - 3.01 Aug 6, 1999 - Jens Axboe - -- Fix up the sysctl handling so that the option flags get set - correctly. - -- Fix up ioctl handling so the device specific ones actually get - called :). - - 3.02 Aug 8, 1999 - Jens Axboe - -- Fixed volume control on SCSI drives (or others with longer audio - page). - -- Fixed a couple of DVD minors. Thanks to Andrew T. Veliath - for telling me and for having defined the various - DVD structures and ioctls in the first place! He designed the original - DVD patches for ide-cd and while I rearranged and unified them, the - interface is still the same. - - 3.03 Sep 1, 1999 - Jens Axboe - -- Moved the rest of the audio ioctls from the CD-ROM drivers here. Only - CDROMREADTOCENTRY and CDROMREADTOCHDR are left. - -- Moved the CDROMREADxxx ioctls in here. - -- Defined the cdrom_get_last_written and cdrom_get_next_block as ioctls - and exported functions. - -- Erik Andersen modified all SCMD_ commands - to now read GPCMD_ for the new generic packet interface. All low level - drivers are updated as well. - -- Various other cleanups. - - 3.04 Sep 12, 1999 - Jens Axboe - -- Fixed a couple of possible memory leaks (if an operation failed and - we didn't free the buffer before returning the error). - -- Integrated Uniform CD Changer handling from Richard Sharman - . - -- Defined CD_DVD and CD_CHANGER log levels. - -- Fixed the CDROMREADxxx ioctls. - -- CDROMPLAYTRKIND uses the GPCMD_PLAY_AUDIO_MSF command - too few - drives supported it. We loose the index part, however. - -- Small modifications to accomodate opens of /dev/hdc1, required - for ide-cd to handle multisession discs. - -- Export cdrom_mode_sense and cdrom_mode_select. - -- init_cdrom_command() for setting up a cgc command. - - 3.05 Oct 24, 1999 - Jens Axboe - -- Changed the interface for CDROM_SEND_PACKET. Before it was virtually - impossible to send the drive data in a sensible way. - -- Lowered stack usage in mmc_ioctl(), dvd_read_disckey(), and - dvd_read_manufact. - -- Added setup of write mode for packet writing. - -- Fixed CDDA ripping with cdda2wav - accept much larger requests of - number of frames and split the reads in blocks of 8. - - 3.06 Dec 13, 1999 - Jens Axboe - -- Added support for changing the region of DVD drives. - -- Added sense data to generic command. - - 3.07 Feb 2, 2000 - Jens Axboe - -- Do same "read header length" trick in cdrom_get_disc_info() as - we do in cdrom_get_track_info() -- some drive don't obey specs and - fail if they can't supply the full Mt Fuji size table. - -- Deleted stuff related to setting up write modes. It has a different - home now. - -- Clear header length in mode_select unconditionally. - -- Removed the register_disk() that was added, not needed here. - - 3.08 May 1, 2000 - Jens Axboe - -- Fix direction flag in setup_send_key and setup_report_key. This - gave some SCSI adapters problems. - -- Always return -EROFS for write opens - -- Convert to module_init/module_exit style init and remove some - of the #ifdef MODULE stuff - -- Fix several dvd errors - DVD_LU_SEND_ASF should pass agid, - DVD_HOST_SEND_RPC_STATE did not set buffer size in cdb, and - dvd_do_auth passed uninitialized data to drive because init_cdrom_command - did not clear a 0 sized buffer. - - 3.09 May 12, 2000 - Jens Axboe - -- Fix Video-CD on SCSI drives that don't support READ_CD command. In - that case switch block size and issue plain READ_10 again, then switch - back. - - 3.10 Jun 10, 2000 - Jens Axboe - -- Fix volume control on CD's - old SCSI-II drives now use their own - code, as doing MODE6 stuff in here is really not my intention. - -- Use READ_DISC_INFO for more reliable end-of-disc. - - 3.11 Jun 12, 2000 - Jens Axboe - -- Fix bug in getting rpc phase 2 region info. - -- Reinstate "correct" CDROMPLAYTRKIND - - 3.12 Oct 18, 2000 - Jens Axboe - -- Use quiet bit on packet commands not known to work - --------------------------------------------------------------------------*/ - -#define REVISION "Revision: 3.12" -#define VERSION "Id: cdrom.c 3.12 2000/10/18" - -/* I use an error-log mask to give fine grain control over the type of - messages dumped to the system logs. The available masks include: */ -#define CD_NOTHING 0x0 -#define CD_WARNING 0x1 -#define CD_REG_UNREG 0x2 -#define CD_DO_IOCTL 0x4 -#define CD_OPEN 0x8 -#define CD_CLOSE 0x10 -#define CD_COUNT_TRACKS 0x20 -#define CD_CHANGER 0x40 -#define CD_DVD 0x80 - -/* Define this to remove _all_ the debugging messages */ -/* #define ERRLOGMASK CD_NOTHING */ -#define ERRLOGMASK (CD_WARNING) -/* #define ERRLOGMASK (CD_WARNING|CD_OPEN|CD_COUNT_TRACKS|CD_CLOSE) */ -/* #define ERRLOGMASK (CD_WARNING|CD_REG_UNREG|CD_DO_IOCTL|CD_OPEN|CD_CLOSE|CD_COUNT_TRACKS) */ - -#include -#include -/* #include */ -#include -#include -#include -#include -#include -#include -#include -/* #include */ -/* #include */ -#include - -/* #include */ -/* #include */ -#include - -/* used to tell the module to turn on full debugging messages */ -static int debug; -/* used to keep tray locked at all times */ -static int keeplocked; -/* default compatibility mode */ -static int autoclose=1; -static int autoeject; -static int lockdoor = 1; -/* will we ever get to use this... sigh. */ -static int check_media_type; -MODULE_PARM(debug, "i"); -MODULE_PARM(autoclose, "i"); -MODULE_PARM(autoeject, "i"); -MODULE_PARM(lockdoor, "i"); -MODULE_PARM(check_media_type, "i"); - -#if (ERRLOGMASK!=CD_NOTHING) -#define cdinfo(type, fmt, args...) \ - if ((ERRLOGMASK & type) || debug==1 ) \ - printk(KERN_INFO "cdrom: " fmt, ## args) -#else -#define cdinfo(type, fmt, args...) -#endif - -/* These are used to simplify getting data in from and back to user land */ -#define IOCTL_IN(arg, type, in) \ - if (copy_from_user(&(in), (type *) (arg), sizeof (in))) \ - return -EFAULT; - -#define IOCTL_OUT(arg, type, out) \ - if (copy_to_user((type *) (arg), &(out), sizeof (out))) \ - return -EFAULT; - -/* The (cdo->capability & ~cdi->mask & CDC_XXX) construct was used in - a lot of places. This macro makes the code more clear. */ -#define CDROM_CAN(type) (cdi->ops->capability & ~cdi->mask & (type)) - -/* used in the audio ioctls */ -#define CHECKAUDIO if ((ret=check_for_audio_disc(cdi, cdo))) return ret - -/* Not-exported routines. */ -static int open_for_data(struct cdrom_device_info * cdi); -static int check_for_audio_disc(struct cdrom_device_info * cdi, - struct cdrom_device_ops * cdo); -static void sanitize_format(union cdrom_addr *addr, - u_char * curr, u_char requested); -static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, - unsigned long arg); - -#ifdef CONFIG_SYSCTL -static void cdrom_sysctl_register(void); -#endif /* CONFIG_SYSCTL */ -static struct cdrom_device_info *topCdromPtr; -#if 0 -static devfs_handle_t devfs_handle; -static struct unique_numspace cdrom_numspace = UNIQUE_NUMBERSPACE_INITIALISER; -#endif - -/* This macro makes sure we don't have to check on cdrom_device_ops - * existence in the run-time routines below. Change_capability is a - * hack to have the capability flags defined const, while we can still - * change it here without gcc complaining at every line. - */ -#define ENSURE(call, bits) if (cdo->call == NULL) *change_capability &= ~(bits) - -int register_cdrom(struct cdrom_device_info *cdi) -{ - static char banner_printed; - int major = MAJOR(cdi->dev); - struct cdrom_device_ops *cdo = cdi->ops; - int *change_capability = (int *)&cdo->capability; /* hack */ - - cdinfo(CD_OPEN, "entering register_cdrom\n"); - - if (major < 0 || major >= MAX_BLKDEV) - return -1; - if (cdo->open == NULL || cdo->release == NULL) - return -2; - if ( !banner_printed ) { - printk(KERN_INFO "Uniform CD-ROM driver " REVISION "\n"); - banner_printed = 1; -#ifdef CONFIG_SYSCTL - cdrom_sysctl_register(); -#endif /* CONFIG_SYSCTL */ - } - ENSURE(drive_status, CDC_DRIVE_STATUS ); - ENSURE(media_changed, CDC_MEDIA_CHANGED); - ENSURE(tray_move, CDC_CLOSE_TRAY | CDC_OPEN_TRAY); - ENSURE(lock_door, CDC_LOCK); - ENSURE(select_speed, CDC_SELECT_SPEED); - ENSURE(get_last_session, CDC_MULTI_SESSION); - ENSURE(get_mcn, CDC_MCN); - ENSURE(reset, CDC_RESET); - ENSURE(audio_ioctl, CDC_PLAY_AUDIO); - ENSURE(dev_ioctl, CDC_IOCTLS); - ENSURE(generic_packet, CDC_GENERIC_PACKET); - cdi->mc_flags = 0; - cdo->n_minors = 0; - cdi->options = CDO_USE_FFLAGS; - - if (autoclose==1 && CDROM_CAN(CDC_CLOSE_TRAY)) - cdi->options |= (int) CDO_AUTO_CLOSE; - if (autoeject==1 && CDROM_CAN(CDC_OPEN_TRAY)) - cdi->options |= (int) CDO_AUTO_EJECT; - if (lockdoor==1) - cdi->options |= (int) CDO_LOCK; - if (check_media_type==1) - cdi->options |= (int) CDO_CHECK_TYPE; -#if 0 - if (!devfs_handle) - devfs_handle = devfs_mk_dir (NULL, "cdroms", NULL); - cdi->number = devfs_alloc_unique_number (&cdrom_numspace); - if (cdi->de) { - int pos; - devfs_handle_t slave; - char rname[64]; - - pos = devfs_generate_path (cdi->de, rname + 3, - sizeof rname - 3); - if (pos >= 0) { - char vname[16]; - sprintf (vname, "cdrom%d", cdi->number); - strncpy (rname + pos, "../", 3); - devfs_mk_symlink (devfs_handle, vname, - DEVFS_FL_DEFAULT, - rname + pos, &slave, NULL); - devfs_auto_unregister (cdi->de, slave); - } - } -#endif - cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name); - cdi->next = topCdromPtr; - topCdromPtr = cdi; - return 0; -} -#undef ENSURE - -int unregister_cdrom(struct cdrom_device_info *unreg) -{ - struct cdrom_device_info *cdi, *prev; - int major = MAJOR(unreg->dev); - - cdinfo(CD_OPEN, "entering unregister_cdrom\n"); - - if (major < 0 || major >= MAX_BLKDEV) - return -1; - - prev = NULL; - cdi = topCdromPtr; - while (cdi != NULL && cdi->dev != unreg->dev) { - prev = cdi; - cdi = cdi->next; - } - - if (cdi == NULL) - return -2; - if (prev) - prev->next = cdi->next; - else - topCdromPtr = cdi->next; - cdi->ops->n_minors--; -#if 0 - devfs_unregister (cdi->de); - devfs_dealloc_unique_number (&cdrom_numspace, cdi->number); -#endif - cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name); - return 0; -} - -struct cdrom_device_info *cdrom_find_device(kdev_t dev) -{ - struct cdrom_device_info *cdi; - - cdi = topCdromPtr; - while (cdi != NULL && cdi->dev != dev) - cdi = cdi->next; - - return cdi; -} - -/* We use the open-option O_NONBLOCK to indicate that the - * purpose of opening is only for subsequent ioctl() calls; no device - * integrity checks are performed. - * - * We hope that all cd-player programs will adopt this convention. It - * is in their own interest: device control becomes a lot easier - * this way. - */ -int cdrom_open(struct inode *ip, struct file *fp) -{ - struct cdrom_device_info *cdi; - kdev_t dev = ip->i_rdev; - int ret; - - cdinfo(CD_OPEN, "entering cdrom_open\n"); - if ((cdi = cdrom_find_device(dev)) == NULL) - return -ENODEV; - -#if 0 - if ((fp->f_mode & FMODE_WRITE) && !CDROM_CAN(CDC_DVD_RAM)) - return -EROFS; - - /* if this was a O_NONBLOCK open and we should honor the flags, - * do a quick open without drive/disc integrity checks. */ - if ((fp->f_flags & O_NONBLOCK) && (cdi->options & CDO_USE_FFLAGS)) - ret = cdi->ops->open(cdi, 1); - else - ret = open_for_data(cdi); -#else - ret = open_for_data(cdi); -#endif - - if (!ret) cdi->use_count++; - - cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n", cdi->name, cdi->use_count); - /* Do this on open. Don't wait for mount, because they might - not be mounting, but opening with O_NONBLOCK */ - check_disk_change(dev); - return ret; -} - -static -int open_for_data(struct cdrom_device_info * cdi) -{ - int ret; - struct cdrom_device_ops *cdo = cdi->ops; - tracktype tracks; - cdinfo(CD_OPEN, "entering open_for_data\n"); - /* Check if the driver can report drive status. If it can, we - can do clever things. If it can't, well, we at least tried! */ - if (cdo->drive_status != NULL) { - ret = cdo->drive_status(cdi, CDSL_CURRENT); - cdinfo(CD_OPEN, "drive_status=%d\n", ret); - if (ret == CDS_TRAY_OPEN) { - cdinfo(CD_OPEN, "the tray is open...\n"); - /* can/may i close it? */ - if (CDROM_CAN(CDC_CLOSE_TRAY) && - cdi->options & CDO_AUTO_CLOSE) { - cdinfo(CD_OPEN, "trying to close the tray.\n"); - ret=cdo->tray_move(cdi,0); - if (ret) { - cdinfo(CD_OPEN, "bummer. tried to close the tray but failed.\n"); - /* Ignore the error from the low - level driver. We don't care why it - couldn't close the tray. We only care - that there is no disc in the drive, - since that is the _REAL_ problem here.*/ - ret=-ENOMEDIUM; - goto clean_up_and_return; - } - } else { - cdinfo(CD_OPEN, "bummer. this drive can't close the tray.\n"); - ret=-ENOMEDIUM; - goto clean_up_and_return; - } - /* Ok, the door should be closed now.. Check again */ - ret = cdo->drive_status(cdi, CDSL_CURRENT); - if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) { - cdinfo(CD_OPEN, "bummer. the tray is still not closed.\n"); - cdinfo(CD_OPEN, "tray might not contain a medium.\n"); - ret=-ENOMEDIUM; - goto clean_up_and_return; - } - cdinfo(CD_OPEN, "the tray is now closed.\n"); - } - if (ret!=CDS_DISC_OK) { - ret = -ENOMEDIUM; - goto clean_up_and_return; - } - } - cdrom_count_tracks(cdi, &tracks); - if (tracks.error == CDS_NO_DISC) { - cdinfo(CD_OPEN, "bummer. no disc.\n"); - ret=-ENOMEDIUM; - goto clean_up_and_return; - } - /* CD-Players which don't use O_NONBLOCK, workman - * for example, need bit CDO_CHECK_TYPE cleared! */ - if (tracks.data==0) { - if (cdi->options & CDO_CHECK_TYPE) { - /* give people a warning shot, now that CDO_CHECK_TYPE - is the default case! */ - cdinfo(CD_OPEN, "bummer. wrong media type.\n"); -#if 0 - cdinfo(CD_WARNING, "pid %d must open device O_NONBLOCK!\n", - (unsigned int)current->pid); -#else - cdinfo(CD_WARNING, "xen must open device O_NONBLOCK!\n"); -#endif - ret=-EMEDIUMTYPE; - goto clean_up_and_return; - } - else { - cdinfo(CD_OPEN, "wrong media type, but CDO_CHECK_TYPE not set.\n"); - } - } - - cdinfo(CD_OPEN, "all seems well, opening the device.\n"); - - /* all seems well, we can open the device */ - ret = cdo->open(cdi, 0); /* open for data */ - cdinfo(CD_OPEN, "opening the device gave me %d.\n", ret); - /* After all this careful checking, we shouldn't have problems - opening the device, but we don't want the device locked if - this somehow fails... */ - if (ret) { - cdinfo(CD_OPEN, "open device failed.\n"); - goto clean_up_and_return; - } - if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) { - cdo->lock_door(cdi, 1); - cdinfo(CD_OPEN, "door locked.\n"); - } - cdinfo(CD_OPEN, "device opened successfully.\n"); - return ret; - - /* Something failed. Try to unlock the drive, because some drivers - (notably ide-cd) lock the drive after every command. This produced - a nasty bug where after mount failed, the drive would remain locked! - This ensures that the drive gets unlocked after a mount fails. This - is a goto to avoid bloating the driver with redundant code. */ -clean_up_and_return: - cdinfo(CD_WARNING, "open failed.\n"); - if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) { - cdo->lock_door(cdi, 0); - cdinfo(CD_OPEN, "door unlocked.\n"); - } - return ret; -} - -/* This code is similar to that in open_for_data. The routine is called - whenever an audio play operation is requested. -*/ -int check_for_audio_disc(struct cdrom_device_info * cdi, - struct cdrom_device_ops * cdo) -{ - int ret; - tracktype tracks; - cdinfo(CD_OPEN, "entering check_for_audio_disc\n"); - if (!(cdi->options & CDO_CHECK_TYPE)) - return 0; - if (cdo->drive_status != NULL) { - ret = cdo->drive_status(cdi, CDSL_CURRENT); - cdinfo(CD_OPEN, "drive_status=%d\n", ret); - if (ret == CDS_TRAY_OPEN) { - cdinfo(CD_OPEN, "the tray is open...\n"); - /* can/may i close it? */ - if (CDROM_CAN(CDC_CLOSE_TRAY) && - cdi->options & CDO_AUTO_CLOSE) { - cdinfo(CD_OPEN, "trying to close the tray.\n"); - ret=cdo->tray_move(cdi,0); - if (ret) { - cdinfo(CD_OPEN, "bummer. tried to close tray but failed.\n"); - /* Ignore the error from the low - level driver. We don't care why it - couldn't close the tray. We only care - that there is no disc in the drive, - since that is the _REAL_ problem here.*/ - return -ENOMEDIUM; - } - } else { - cdinfo(CD_OPEN, "bummer. this driver can't close the tray.\n"); - return -ENOMEDIUM; - } - /* Ok, the door should be closed now.. Check again */ - ret = cdo->drive_status(cdi, CDSL_CURRENT); - if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) { - cdinfo(CD_OPEN, "bummer. the tray is still not closed.\n"); - return -ENOMEDIUM; - } - if (ret!=CDS_DISC_OK) { - cdinfo(CD_OPEN, "bummer. disc isn't ready.\n"); - return -EIO; - } - cdinfo(CD_OPEN, "the tray is now closed.\n"); - } - } - cdrom_count_tracks(cdi, &tracks); - if (tracks.error) - return(tracks.error); - - if (tracks.audio==0) - return -EMEDIUMTYPE; - - return 0; -} - - -/* Admittedly, the logic below could be performed in a nicer way. */ -int cdrom_release(struct inode *ip, struct file *fp) -{ - kdev_t dev = ip->i_rdev; - struct cdrom_device_info *cdi = cdrom_find_device(dev); - struct cdrom_device_ops *cdo = cdi->ops; - int opened_for_data; - - cdinfo(CD_CLOSE, "entering cdrom_release\n"); - - if (cdi->use_count > 0) - cdi->use_count--; - if (cdi->use_count == 0) - cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name); - if (cdi->use_count == 0 && - cdo->capability & CDC_LOCK && !keeplocked) { - cdinfo(CD_CLOSE, "Unlocking door!\n"); - cdo->lock_door(cdi, 0); - } -#if 0 - opened_for_data = !(cdi->options & CDO_USE_FFLAGS) || - !(fp && fp->f_flags & O_NONBLOCK); -#else - opened_for_data = 1; /* XXX SMH: guess */ -#endif - cdo->release(cdi); - if (cdi->use_count == 0) { /* last process that closes dev*/ - if (opened_for_data && - cdi->options & CDO_AUTO_EJECT && CDROM_CAN(CDC_OPEN_TRAY)) - cdo->tray_move(cdi, 1); - } - return 0; -} - -static int cdrom_read_mech_status(struct cdrom_device_info *cdi, - struct cdrom_changer_info *buf) -{ - struct cdrom_generic_command cgc; - struct cdrom_device_ops *cdo = cdi->ops; - int length; - - /* - * Sanyo changer isn't spec compliant (doesn't use regular change - * LOAD_UNLOAD command, and it doesn't implement the mech status - * command below - */ - if (cdi->sanyo_slot) { - buf->hdr.nslots = 3; - buf->hdr.curslot = cdi->sanyo_slot == 3 ? 0 : cdi->sanyo_slot; - for (length = 0; length < 3; length++) { - buf->slots[length].disc_present = 1; - buf->slots[length].change = 0; - } - return 0; - } - - length = sizeof(struct cdrom_mechstat_header) + - cdi->capacity * sizeof(struct cdrom_slot); - - init_cdrom_command(&cgc, buf, length, CGC_DATA_READ); - cgc.cmd[0] = GPCMD_MECHANISM_STATUS; - cgc.cmd[8] = (length >> 8) & 0xff; - cgc.cmd[9] = length & 0xff; - return cdo->generic_packet(cdi, &cgc); -} - -static int cdrom_slot_status(struct cdrom_device_info *cdi, int slot) -{ - struct cdrom_changer_info info; - int ret; - - cdinfo(CD_CHANGER, "entering cdrom_slot_status()\n"); - if (cdi->sanyo_slot) - return CDS_NO_INFO; - - if ((ret = cdrom_read_mech_status(cdi, &info))) - return ret; - - if (info.slots[slot].disc_present) - return CDS_DISC_OK; - else - return CDS_NO_DISC; - -} - -/* Return the number of slots for an ATAPI/SCSI cdrom, - * return 1 if not a changer. - */ -int cdrom_number_of_slots(struct cdrom_device_info *cdi) -{ - int status; - int nslots = 1; - struct cdrom_changer_info info; - - cdinfo(CD_CHANGER, "entering cdrom_number_of_slots()\n"); - /* cdrom_read_mech_status requires a valid value for capacity: */ - cdi->capacity = 0; - - if ((status = cdrom_read_mech_status(cdi, &info)) == 0) - nslots = info.hdr.nslots; - - return nslots; -} - - -/* If SLOT < 0, unload the current slot. Otherwise, try to load SLOT. */ -static int cdrom_load_unload(struct cdrom_device_info *cdi, int slot) -{ - struct cdrom_generic_command cgc; - - cdinfo(CD_CHANGER, "entering cdrom_load_unload()\n"); - if (cdi->sanyo_slot && slot < 0) - return 0; - - init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); - cgc.cmd[0] = GPCMD_LOAD_UNLOAD; - cgc.cmd[4] = 2 + (slot >= 0); - cgc.cmd[8] = slot; - - /* The Sanyo 3 CD changer uses byte 7 of the - GPCMD_TEST_UNIT_READY to command to switch CDs instead of - using the GPCMD_LOAD_UNLOAD opcode. */ - if (cdi->sanyo_slot && -1 < slot) { - cgc.cmd[0] = GPCMD_TEST_UNIT_READY; - cgc.cmd[7] = slot; - cgc.cmd[4] = cgc.cmd[8] = 0; - cdi->sanyo_slot = slot ? slot : 3; - } - - return cdi->ops->generic_packet(cdi, &cgc); -} - -int cdrom_select_disc(struct cdrom_device_info *cdi, int slot) -{ - struct cdrom_changer_info info; - int curslot; - int ret; - - cdinfo(CD_CHANGER, "entering cdrom_select_disc()\n"); - if (!CDROM_CAN(CDC_SELECT_DISC)) - return -EDRIVE_CANT_DO_THIS; - - (void) cdi->ops->media_changed(cdi, slot); - - if (slot == CDSL_NONE) { - /* set media changed bits, on both queues */ - cdi->mc_flags = 0x3; - return cdrom_load_unload(cdi, -1); - } - - if ((ret = cdrom_read_mech_status(cdi, &info))) - return ret; - - curslot = info.hdr.curslot; - - if (cdi->use_count > 1 || keeplocked) { - if (slot == CDSL_CURRENT) { - return curslot; - } else { - return -EBUSY; - } - } - - /* Specifying CDSL_CURRENT will attempt to load the currnet slot, - which is useful if it had been previously unloaded. - Whether it can or not, it returns the current slot. - Similarly, if slot happens to be the current one, we still - try and load it. */ - if (slot == CDSL_CURRENT) - slot = curslot; - - /* set media changed bits on both queues */ - cdi->mc_flags = 0x3; - if ((ret = cdrom_load_unload(cdi, slot))) - return ret; - - return slot; -} - -/* We want to make media_changed accessible to the user through an - * ioctl. The main problem now is that we must double-buffer the - * low-level implementation, to assure that the VFS and the user both - * see a medium change once. - */ - -static -int media_changed(struct cdrom_device_info *cdi, int queue) -{ - unsigned int mask = (1 << (queue & 1)); - int ret = !!(cdi->mc_flags & mask); - - if (!CDROM_CAN(CDC_MEDIA_CHANGED)) - return ret; - /* changed since last call? */ - if (cdi->ops->media_changed(cdi, CDSL_CURRENT)) { - cdi->mc_flags = 0x3; /* set bit on both queues */ - ret |= 1; - } - cdi->mc_flags &= ~mask; /* clear bit */ - return ret; -} - -int cdrom_media_changed(kdev_t dev) -{ - struct cdrom_device_info *cdi = cdrom_find_device(dev); - /* This talks to the VFS, which doesn't like errors - just 1 or 0. - * Returning "0" is always safe (media hasn't been changed). Do that - * if the low-level cdrom driver dosn't support media changed. */ - if (cdi == NULL || cdi->ops->media_changed == NULL) - return 0; - if (!CDROM_CAN(CDC_MEDIA_CHANGED)) - return 0; - return media_changed(cdi, 0); -} - -/* badly broken, I know. Is due for a fixup anytime. */ -void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype* tracks) -{ - struct cdrom_tochdr header; - struct cdrom_tocentry entry; - int ret, i; - tracks->data=0; - tracks->audio=0; - tracks->cdi=0; - tracks->xa=0; - tracks->error=0; - cdinfo(CD_COUNT_TRACKS, "entering cdrom_count_tracks\n"); - if (!CDROM_CAN(CDC_PLAY_AUDIO)) { - tracks->error=CDS_NO_INFO; - return; - } - /* Grab the TOC header so we can see how many tracks there are */ - if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header))) { - if (ret == -ENOMEDIUM) - tracks->error = CDS_NO_DISC; - else - tracks->error = CDS_NO_INFO; - return; - } - /* check what type of tracks are on this disc */ - entry.cdte_format = CDROM_MSF; - for (i = header.cdth_trk0; i <= header.cdth_trk1; i++) { - entry.cdte_track = i; - if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry)) { - tracks->error=CDS_NO_INFO; - return; - } - if (entry.cdte_ctrl & CDROM_DATA_TRACK) { - if (entry.cdte_format == 0x10) - tracks->cdi++; - else if (entry.cdte_format == 0x20) - tracks->xa++; - else - tracks->data++; - } else - tracks->audio++; - cdinfo(CD_COUNT_TRACKS, "track %d: format=%d, ctrl=%d\n", - i, entry.cdte_format, entry.cdte_ctrl); - } - cdinfo(CD_COUNT_TRACKS, "disc has %d tracks: %d=audio %d=data %d=Cd-I %d=XA\n", - header.cdth_trk1, tracks->audio, tracks->data, - tracks->cdi, tracks->xa); -} - -/* Requests to the low-level drivers will /always/ be done in the - following format convention: - - CDROM_LBA: all data-related requests. - CDROM_MSF: all audio-related requests. - - However, a low-level implementation is allowed to refuse this - request, and return information in its own favorite format. - - It doesn't make sense /at all/ to ask for a play_audio in LBA - format, or ask for multi-session info in MSF format. However, for - backward compatibility these format requests will be satisfied, but - the requests to the low-level drivers will be sanitized in the more - meaningful format indicated above. - */ - -static -void sanitize_format(union cdrom_addr *addr, - u_char * curr, u_char requested) -{ - if (*curr == requested) - return; /* nothing to be done! */ - if (requested == CDROM_LBA) { - addr->lba = (int) addr->msf.frame + - 75 * (addr->msf.second - 2 + 60 * addr->msf.minute); - } else { /* CDROM_MSF */ - int lba = addr->lba; - addr->msf.frame = lba % 75; - lba /= 75; - lba += 2; - addr->msf.second = lba % 60; - addr->msf.minute = lba / 60; - } - *curr = requested; -} - -void init_cdrom_command(struct cdrom_generic_command *cgc, void *buf, int len, - int type) -{ - memset(cgc, 0, sizeof(struct cdrom_generic_command)); - if (buf) - memset(buf, 0, len); - cgc->buffer = (char *) buf; - cgc->buflen = len; - cgc->data_direction = type; - cgc->timeout = 5*HZ; -} - -/* DVD handling */ - -#define copy_key(dest,src) memcpy((dest), (src), sizeof(dvd_key)) -#define copy_chal(dest,src) memcpy((dest), (src), sizeof(dvd_challenge)) - -static void setup_report_key(struct cdrom_generic_command *cgc, unsigned agid, unsigned type) -{ - cgc->cmd[0] = GPCMD_REPORT_KEY; - cgc->cmd[10] = type | (agid << 6); - switch (type) { - case 0: case 8: case 5: { - cgc->buflen = 8; - break; - } - case 1: { - cgc->buflen = 16; - break; - } - case 2: case 4: { - cgc->buflen = 12; - break; - } - } - cgc->cmd[9] = cgc->buflen; - cgc->data_direction = CGC_DATA_READ; -} - -static void setup_send_key(struct cdrom_generic_command *cgc, unsigned agid, unsigned type) -{ - cgc->cmd[0] = GPCMD_SEND_KEY; - cgc->cmd[10] = type | (agid << 6); - switch (type) { - case 1: { - cgc->buflen = 16; - break; - } - case 3: { - cgc->buflen = 12; - break; - } - case 6: { - cgc->buflen = 8; - break; - } - } - cgc->cmd[9] = cgc->buflen; - cgc->data_direction = CGC_DATA_WRITE; -} - -static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) -{ - int ret; - u_char buf[20]; - struct cdrom_generic_command cgc; - struct cdrom_device_ops *cdo = cdi->ops; - rpc_state_t rpc_state; - - memset(buf, 0, sizeof(buf)); - init_cdrom_command(&cgc, buf, 0, CGC_DATA_READ); - - switch (ai->type) { - /* LU data send */ - case DVD_LU_SEND_AGID: - cdinfo(CD_DVD, "entering DVD_LU_SEND_AGID\n"); - setup_report_key(&cgc, ai->lsa.agid, 0); - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - ai->lsa.agid = buf[7] >> 6; - /* Returning data, let host change state */ - break; - - case DVD_LU_SEND_KEY1: - cdinfo(CD_DVD, "entering DVD_LU_SEND_KEY1\n"); - setup_report_key(&cgc, ai->lsk.agid, 2); - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - copy_key(ai->lsk.key, &buf[4]); - /* Returning data, let host change state */ - break; - - case DVD_LU_SEND_CHALLENGE: - cdinfo(CD_DVD, "entering DVD_LU_SEND_CHALLENGE\n"); - setup_report_key(&cgc, ai->lsc.agid, 1); - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - copy_chal(ai->lsc.chal, &buf[4]); - /* Returning data, let host change state */ - break; - - /* Post-auth key */ - case DVD_LU_SEND_TITLE_KEY: - cdinfo(CD_DVD, "entering DVD_LU_SEND_TITLE_KEY\n"); - setup_report_key(&cgc, ai->lstk.agid, 4); - cgc.cmd[5] = ai->lstk.lba; - cgc.cmd[4] = ai->lstk.lba >> 8; - cgc.cmd[3] = ai->lstk.lba >> 16; - cgc.cmd[2] = ai->lstk.lba >> 24; - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - ai->lstk.cpm = (buf[4] >> 7) & 1; - ai->lstk.cp_sec = (buf[4] >> 6) & 1; - ai->lstk.cgms = (buf[4] >> 4) & 3; - copy_key(ai->lstk.title_key, &buf[5]); - /* Returning data, let host change state */ - break; - - case DVD_LU_SEND_ASF: - cdinfo(CD_DVD, "entering DVD_LU_SEND_ASF\n"); - setup_report_key(&cgc, ai->lsasf.agid, 5); - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - ai->lsasf.asf = buf[7] & 1; - break; - - /* LU data receive (LU changes state) */ - case DVD_HOST_SEND_CHALLENGE: - cdinfo(CD_DVD, "entering DVD_HOST_SEND_CHALLENGE\n"); - setup_send_key(&cgc, ai->hsc.agid, 1); - buf[1] = 0xe; - copy_chal(&buf[4], ai->hsc.chal); - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - ai->type = DVD_LU_SEND_KEY1; - break; - - case DVD_HOST_SEND_KEY2: - cdinfo(CD_DVD, "entering DVD_HOST_SEND_KEY2\n"); - setup_send_key(&cgc, ai->hsk.agid, 3); - buf[1] = 0xa; - copy_key(&buf[4], ai->hsk.key); - - if ((ret = cdo->generic_packet(cdi, &cgc))) { - ai->type = DVD_AUTH_FAILURE; - return ret; - } - ai->type = DVD_AUTH_ESTABLISHED; - break; - - /* Misc */ - case DVD_INVALIDATE_AGID: - cdinfo(CD_DVD, "entering DVD_INVALIDATE_AGID\n"); - setup_report_key(&cgc, ai->lsa.agid, 0x3f); - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - break; - - /* Get region settings */ - case DVD_LU_SEND_RPC_STATE: - cdinfo(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n"); - setup_report_key(&cgc, 0, 8); - memset(&rpc_state, 0, sizeof(rpc_state_t)); - cgc.buffer = (char *) &rpc_state; - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - ai->lrpcs.type = rpc_state.type_code; - ai->lrpcs.vra = rpc_state.vra; - ai->lrpcs.ucca = rpc_state.ucca; - ai->lrpcs.region_mask = rpc_state.region_mask; - ai->lrpcs.rpc_scheme = rpc_state.rpc_scheme; - break; - - /* Set region settings */ - case DVD_HOST_SEND_RPC_STATE: - cdinfo(CD_DVD, "entering DVD_HOST_SEND_RPC_STATE\n"); - setup_send_key(&cgc, 0, 6); - buf[1] = 6; - buf[4] = ai->hrpcs.pdrc; - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - break; - - default: - cdinfo(CD_WARNING, "Invalid DVD key ioctl (%d)\n", ai->type); - return -ENOTTY; - } - - return 0; -} - -static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s) -{ - unsigned char buf[20], *base; - struct dvd_layer *layer; - struct cdrom_generic_command cgc; - struct cdrom_device_ops *cdo = cdi->ops; - int ret, layer_num = s->physical.layer_num; - - if (layer_num >= DVD_LAYERS) - return -EINVAL; - - init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); - cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; - cgc.cmd[6] = layer_num; - cgc.cmd[7] = s->type; - cgc.cmd[9] = cgc.buflen & 0xff; - - /* - * refrain from reporting errors on non-existing layers (mainly) - */ - cgc.quiet = 1; - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - base = &buf[4]; - layer = &s->physical.layer[layer_num]; - - /* - * place the data... really ugly, but at least we won't have to - * worry about endianess in userspace. - */ - memset(layer, 0, sizeof(*layer)); - layer->book_version = base[0] & 0xf; - layer->book_type = base[0] >> 4; - layer->min_rate = base[1] & 0xf; - layer->disc_size = base[1] >> 4; - layer->layer_type = base[2] & 0xf; - layer->track_path = (base[2] >> 4) & 1; - layer->nlayers = (base[2] >> 5) & 3; - layer->track_density = base[3] & 0xf; - layer->linear_density = base[3] >> 4; - layer->start_sector = base[5] << 16 | base[6] << 8 | base[7]; - layer->end_sector = base[9] << 16 | base[10] << 8 | base[11]; - layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15]; - layer->bca = base[16] >> 7; - - return 0; -} - -static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s) -{ - int ret; - u_char buf[8]; - struct cdrom_generic_command cgc; - struct cdrom_device_ops *cdo = cdi->ops; - - init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); - cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; - cgc.cmd[6] = s->copyright.layer_num; - cgc.cmd[7] = s->type; - cgc.cmd[8] = cgc.buflen >> 8; - cgc.cmd[9] = cgc.buflen & 0xff; - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - s->copyright.cpst = buf[4]; - s->copyright.rmi = buf[5]; - - return 0; -} - -static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s) -{ - int ret, size; - u_char *buf; - struct cdrom_generic_command cgc; - struct cdrom_device_ops *cdo = cdi->ops; - - size = sizeof(s->disckey.value) + 4; - - if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL) - return -ENOMEM; - - init_cdrom_command(&cgc, buf, size, CGC_DATA_READ); - cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; - cgc.cmd[7] = s->type; - cgc.cmd[8] = size >> 8; - cgc.cmd[9] = size & 0xff; - cgc.cmd[10] = s->disckey.agid << 6; - - if (!(ret = cdo->generic_packet(cdi, &cgc))) - memcpy(s->disckey.value, &buf[4], sizeof(s->disckey.value)); - - kfree(buf); - return ret; -} - -static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s) -{ - int ret; - u_char buf[4 + 188]; - struct cdrom_generic_command cgc; - struct cdrom_device_ops *cdo = cdi->ops; - - init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); - cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; - cgc.cmd[7] = s->type; - cgc.cmd[9] = cgc.buflen = 0xff; - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - s->bca.len = buf[0] << 8 | buf[1]; - if (s->bca.len < 12 || s->bca.len > 188) { - cdinfo(CD_WARNING, "Received invalid BCA length (%d)\n", s->bca.len); - return -EIO; - } - memcpy(s->bca.value, &buf[4], s->bca.len); - - return 0; -} - -static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s) -{ - int ret = 0, size; - u_char *buf; - struct cdrom_generic_command cgc; - struct cdrom_device_ops *cdo = cdi->ops; - - size = sizeof(s->manufact.value) + 4; - - if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL) - return -ENOMEM; - - init_cdrom_command(&cgc, buf, size, CGC_DATA_READ); - cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; - cgc.cmd[7] = s->type; - cgc.cmd[8] = size >> 8; - cgc.cmd[9] = size & 0xff; - - if ((ret = cdo->generic_packet(cdi, &cgc))) { - kfree(buf); - return ret; - } - - s->manufact.len = buf[0] << 8 | buf[1]; - if (s->manufact.len < 0 || s->manufact.len > 2048) { - cdinfo(CD_WARNING, "Received invalid manufacture info length" - " (%d)\n", s->bca.len); - ret = -EIO; - } else { - memcpy(s->manufact.value, &buf[4], s->manufact.len); - } - - kfree(buf); - return ret; -} - -static int dvd_read_struct(struct cdrom_device_info *cdi, dvd_struct *s) -{ - switch (s->type) { - case DVD_STRUCT_PHYSICAL: - return dvd_read_physical(cdi, s); - - case DVD_STRUCT_COPYRIGHT: - return dvd_read_copyright(cdi, s); - - case DVD_STRUCT_DISCKEY: - return dvd_read_disckey(cdi, s); - - case DVD_STRUCT_BCA: - return dvd_read_bca(cdi, s); - - case DVD_STRUCT_MANUFACT: - return dvd_read_manufact(cdi, s); - - default: - cdinfo(CD_WARNING, ": Invalid DVD structure read requested (%d)\n", - s->type); - return -EINVAL; - } -} - -int cdrom_mode_sense(struct cdrom_device_info *cdi, - struct cdrom_generic_command *cgc, - int page_code, int page_control) -{ - struct cdrom_device_ops *cdo = cdi->ops; - - memset(cgc->cmd, 0, sizeof(cgc->cmd)); - - cgc->cmd[0] = GPCMD_MODE_SENSE_10; - cgc->cmd[2] = page_code | (page_control << 6); - cgc->cmd[7] = cgc->buflen >> 8; - cgc->cmd[8] = cgc->buflen & 0xff; - cgc->data_direction = CGC_DATA_READ; - return cdo->generic_packet(cdi, cgc); -} - -int cdrom_mode_select(struct cdrom_device_info *cdi, - struct cdrom_generic_command *cgc) -{ - struct cdrom_device_ops *cdo = cdi->ops; - - memset(cgc->cmd, 0, sizeof(cgc->cmd)); - memset(cgc->buffer, 0, 2); - cgc->cmd[0] = GPCMD_MODE_SELECT_10; - cgc->cmd[1] = 0x10; /* PF */ - cgc->cmd[7] = cgc->buflen >> 8; - cgc->cmd[8] = cgc->buflen & 0xff; - cgc->data_direction = CGC_DATA_WRITE; - return cdo->generic_packet(cdi, cgc); -} - -static int cdrom_read_subchannel(struct cdrom_device_info *cdi, - struct cdrom_subchnl *subchnl, int mcn) -{ - struct cdrom_device_ops *cdo = cdi->ops; - struct cdrom_generic_command cgc; - char buffer[32]; - int ret; - - init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ); - cgc.cmd[0] = GPCMD_READ_SUBCHANNEL; - cgc.cmd[1] = 2; /* MSF addressing */ - cgc.cmd[2] = 0x40; /* request subQ data */ - cgc.cmd[3] = mcn ? 2 : 1; - cgc.cmd[8] = 16; - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - subchnl->cdsc_audiostatus = cgc.buffer[1]; - subchnl->cdsc_format = CDROM_MSF; - subchnl->cdsc_ctrl = cgc.buffer[5] & 0xf; - subchnl->cdsc_trk = cgc.buffer[6]; - subchnl->cdsc_ind = cgc.buffer[7]; - - subchnl->cdsc_reladdr.msf.minute = cgc.buffer[13]; - subchnl->cdsc_reladdr.msf.second = cgc.buffer[14]; - subchnl->cdsc_reladdr.msf.frame = cgc.buffer[15]; - subchnl->cdsc_absaddr.msf.minute = cgc.buffer[9]; - subchnl->cdsc_absaddr.msf.second = cgc.buffer[10]; - subchnl->cdsc_absaddr.msf.frame = cgc.buffer[11]; - - return 0; -} - -/* - * Specific READ_10 interface - */ -static int cdrom_read_cd(struct cdrom_device_info *cdi, - struct cdrom_generic_command *cgc, int lba, - int blocksize, int nblocks) -{ - struct cdrom_device_ops *cdo = cdi->ops; - - memset(&cgc->cmd, 0, sizeof(cgc->cmd)); - cgc->cmd[0] = GPCMD_READ_10; - cgc->cmd[2] = (lba >> 24) & 0xff; - cgc->cmd[3] = (lba >> 16) & 0xff; - cgc->cmd[4] = (lba >> 8) & 0xff; - cgc->cmd[5] = lba & 0xff; - cgc->cmd[6] = (nblocks >> 16) & 0xff; - cgc->cmd[7] = (nblocks >> 8) & 0xff; - cgc->cmd[8] = nblocks & 0xff; - cgc->buflen = blocksize * nblocks; - return cdo->generic_packet(cdi, cgc); -} - -/* very generic interface for reading the various types of blocks */ -static int cdrom_read_block(struct cdrom_device_info *cdi, - struct cdrom_generic_command *cgc, - int lba, int nblocks, int format, int blksize) -{ - struct cdrom_device_ops *cdo = cdi->ops; - - memset(&cgc->cmd, 0, sizeof(cgc->cmd)); - cgc->cmd[0] = GPCMD_READ_CD; - /* expected sector size - cdda,mode1,etc. */ - cgc->cmd[1] = format << 2; - /* starting address */ - cgc->cmd[2] = (lba >> 24) & 0xff; - cgc->cmd[3] = (lba >> 16) & 0xff; - cgc->cmd[4] = (lba >> 8) & 0xff; - cgc->cmd[5] = lba & 0xff; - /* number of blocks */ - cgc->cmd[6] = (nblocks >> 16) & 0xff; - cgc->cmd[7] = (nblocks >> 8) & 0xff; - cgc->cmd[8] = nblocks & 0xff; - cgc->buflen = blksize * nblocks; - - /* set the header info returned */ - switch (blksize) { - case CD_FRAMESIZE_RAW0 : cgc->cmd[9] = 0x58; break; - case CD_FRAMESIZE_RAW1 : cgc->cmd[9] = 0x78; break; - case CD_FRAMESIZE_RAW : cgc->cmd[9] = 0xf8; break; - default : cgc->cmd[9] = 0x10; - } - - return cdo->generic_packet(cdi, cgc); -} - -/* Just about every imaginable ioctl is supported in the Uniform layer - * these days. ATAPI / SCSI specific code now mainly resides in - * mmc_ioct(). - */ -int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, - unsigned long arg) -{ - kdev_t dev = ip->i_rdev; - struct cdrom_device_info *cdi = cdrom_find_device(dev); - struct cdrom_device_ops *cdo = cdi->ops; - int ret; - - /* the first few commands do not deal with audio drive_info, but - only with routines in cdrom device operations. */ - switch (cmd) { - case CDROMMULTISESSION: { - struct cdrom_multisession ms_info; - u_char requested_format; - cdinfo(CD_DO_IOCTL, "entering CDROMMULTISESSION\n"); - if (!(cdo->capability & CDC_MULTI_SESSION)) - return -ENOSYS; - IOCTL_IN(arg, struct cdrom_multisession, ms_info); - requested_format = ms_info.addr_format; - if (!((requested_format == CDROM_MSF) || - (requested_format == CDROM_LBA))) - return -EINVAL; - ms_info.addr_format = CDROM_LBA; - if ((ret=cdo->get_last_session(cdi, &ms_info))) - return ret; - sanitize_format(&ms_info.addr, &ms_info.addr_format, - requested_format); - IOCTL_OUT(arg, struct cdrom_multisession, ms_info); - cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION successful\n"); - return 0; - } - - case CDROMEJECT: { - cdinfo(CD_DO_IOCTL, "entering CDROMEJECT\n"); - if (!CDROM_CAN(CDC_OPEN_TRAY)) - return -ENOSYS; - if (cdi->use_count != 1 || keeplocked) - return -EBUSY; - if (CDROM_CAN(CDC_LOCK)) - if ((ret=cdo->lock_door(cdi, 0))) - return ret; - - return cdo->tray_move(cdi, 1); - } - - case CDROMCLOSETRAY: { - cdinfo(CD_DO_IOCTL, "entering CDROMCLOSETRAY\n"); - if (!CDROM_CAN(CDC_CLOSE_TRAY)) - return -ENOSYS; - return cdo->tray_move(cdi, 0); - } - - case CDROMEJECT_SW: { - cdinfo(CD_DO_IOCTL, "entering CDROMEJECT_SW\n"); - if (!CDROM_CAN(CDC_OPEN_TRAY)) - return -ENOSYS; - if (keeplocked) - return -EBUSY; - cdi->options &= ~(CDO_AUTO_CLOSE | CDO_AUTO_EJECT); - if (arg) - cdi->options |= CDO_AUTO_CLOSE | CDO_AUTO_EJECT; - return 0; - } - - case CDROM_MEDIA_CHANGED: { - struct cdrom_changer_info info; - - cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n"); - if (!CDROM_CAN(CDC_MEDIA_CHANGED)) - return -ENOSYS; - - /* cannot select disc or select current disc */ - if (!CDROM_CAN(CDC_SELECT_DISC) || arg == CDSL_CURRENT) - return media_changed(cdi, 1); - - if ((unsigned int)arg >= cdi->capacity) - return -EINVAL; - - if ((ret = cdrom_read_mech_status(cdi, &info))) - return ret; - - return info.slots[arg].change; - } - - case CDROM_SET_OPTIONS: { - cdinfo(CD_DO_IOCTL, "entering CDROM_SET_OPTIONS\n"); - /* options need to be in sync with capability. too late for - that, so we have to check each one separately... */ - switch (arg) { - case CDO_USE_FFLAGS: - case CDO_CHECK_TYPE: - break; - case CDO_LOCK: - if (!CDROM_CAN(CDC_LOCK)) - return -ENOSYS; - break; - case 0: - return cdi->options; - /* default is basically CDO_[AUTO_CLOSE|AUTO_EJECT] */ - default: - if (!CDROM_CAN(arg)) - return -ENOSYS; - } - cdi->options |= (int) arg; - return cdi->options; - } - - case CDROM_CLEAR_OPTIONS: { - cdinfo(CD_DO_IOCTL, "entering CDROM_CLEAR_OPTIONS\n"); - cdi->options &= ~(int) arg; - return cdi->options; - } - - case CDROM_SELECT_SPEED: { - cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_SPEED\n"); - if (!CDROM_CAN(CDC_SELECT_SPEED)) - return -ENOSYS; - return cdo->select_speed(cdi, arg); - } - - case CDROM_SELECT_DISC: { - cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_DISC\n"); - if (!CDROM_CAN(CDC_SELECT_DISC)) - return -ENOSYS; - - if ((arg != CDSL_CURRENT) && (arg != CDSL_NONE)) - if ((int)arg >= cdi->capacity) - return -EINVAL; - - /* cdo->select_disc is a hook to allow a driver-specific - * way of seleting disc. However, since there is no - * equiv hook for cdrom_slot_status this may not - * actually be useful... - */ - if (cdo->select_disc != NULL) - return cdo->select_disc(cdi, arg); - - /* no driver specific select_disc(), call our own */ - cdinfo(CD_CHANGER, "Using generic cdrom_select_disc()\n"); - return cdrom_select_disc(cdi, arg); - } - - case CDROMRESET: { - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - cdinfo(CD_DO_IOCTL, "entering CDROM_RESET\n"); - if (!CDROM_CAN(CDC_RESET)) - return -ENOSYS; - return cdo->reset(cdi); - } - - case CDROM_LOCKDOOR: { - cdinfo(CD_DO_IOCTL, "%socking door.\n", arg ? "L" : "Unl"); - if (!CDROM_CAN(CDC_LOCK)) - return -EDRIVE_CANT_DO_THIS; - keeplocked = arg ? 1 : 0; - /* don't unlock the door on multiple opens,but allow root - * to do so */ - if ((cdi->use_count != 1) && !arg && !capable(CAP_SYS_ADMIN)) - return -EBUSY; - return cdo->lock_door(cdi, arg); - } - - case CDROM_DEBUG: { - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - cdinfo(CD_DO_IOCTL, "%sabling debug.\n", arg ? "En" : "Dis"); - debug = arg ? 1 : 0; - return debug; - } - - case CDROM_GET_CAPABILITY: { - cdinfo(CD_DO_IOCTL, "entering CDROM_GET_CAPABILITY\n"); - return (cdo->capability & ~cdi->mask); - } - -/* The following function is implemented, although very few audio - * discs give Universal Product Code information, which should just be - * the Medium Catalog Number on the box. Note, that the way the code - * is written on the CD is /not/ uniform across all discs! - */ - case CDROM_GET_MCN: { - struct cdrom_mcn mcn; - cdinfo(CD_DO_IOCTL, "entering CDROM_GET_MCN\n"); - if (!(cdo->capability & CDC_MCN)) - return -ENOSYS; - if ((ret=cdo->get_mcn(cdi, &mcn))) - return ret; - IOCTL_OUT(arg, struct cdrom_mcn, mcn); - cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN successful\n"); - return 0; - } - - case CDROM_DRIVE_STATUS: { - cdinfo(CD_DO_IOCTL, "entering CDROM_DRIVE_STATUS\n"); - if (!(cdo->capability & CDC_DRIVE_STATUS)) - return -ENOSYS; - if (!CDROM_CAN(CDC_SELECT_DISC)) - return cdo->drive_status(cdi, CDSL_CURRENT); - if ((arg == CDSL_CURRENT) || (arg == CDSL_NONE)) - return cdo->drive_status(cdi, CDSL_CURRENT); - if (((int)arg >= cdi->capacity)) - return -EINVAL; - return cdrom_slot_status(cdi, arg); - } - - /* Ok, this is where problems start. The current interface for the - CDROM_DISC_STATUS ioctl is flawed. It makes the false assumption - that CDs are all CDS_DATA_1 or all CDS_AUDIO, etc. Unfortunatly, - while this is often the case, it is also very common for CDs to - have some tracks with data, and some tracks with audio. Just - because I feel like it, I declare the following to be the best - way to cope. If the CD has ANY data tracks on it, it will be - returned as a data CD. If it has any XA tracks, I will return - it as that. Now I could simplify this interface by combining these - returns with the above, but this more clearly demonstrates - the problem with the current interface. Too bad this wasn't - designed to use bitmasks... -Erik - - Well, now we have the option CDS_MIXED: a mixed-type CD. - User level programmers might feel the ioctl is not very useful. - ---david - */ - case CDROM_DISC_STATUS: { - tracktype tracks; - cdinfo(CD_DO_IOCTL, "entering CDROM_DISC_STATUS\n"); - cdrom_count_tracks(cdi, &tracks); - if (tracks.error) - return(tracks.error); - - /* Policy mode on */ - if (tracks.audio > 0) { - if (tracks.data==0 && tracks.cdi==0 && tracks.xa==0) - return CDS_AUDIO; - else - return CDS_MIXED; - } - if (tracks.cdi > 0) return CDS_XA_2_2; - if (tracks.xa > 0) return CDS_XA_2_1; - if (tracks.data > 0) return CDS_DATA_1; - /* Policy mode off */ - - cdinfo(CD_WARNING,"This disc doesn't have any tracks I recognize!\n"); - return CDS_NO_INFO; - } - - case CDROM_CHANGER_NSLOTS: { - cdinfo(CD_DO_IOCTL, "entering CDROM_CHANGER_NSLOTS\n"); - return cdi->capacity; - } - } - - /* use the ioctls that are implemented through the generic_packet() - interface. this may look at bit funny, but if -ENOTTY is - returned that particular ioctl is not implemented and we - let it go through the device specific ones. */ - if (CDROM_CAN(CDC_GENERIC_PACKET)) { - ret = mmc_ioctl(cdi, cmd, arg); - if (ret != -ENOTTY) { - return ret; - } - } - - /* note: most of the cdinfo() calls are commented out here, - because they fill up the sys log when CD players poll - the drive. */ - switch (cmd) { - case CDROMSUBCHNL: { - struct cdrom_subchnl q; - u_char requested, back; - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - /* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/ - IOCTL_IN(arg, struct cdrom_subchnl, q); - requested = q.cdsc_format; - if (!((requested == CDROM_MSF) || - (requested == CDROM_LBA))) - return -EINVAL; - q.cdsc_format = CDROM_MSF; - if ((ret=cdo->audio_ioctl(cdi, cmd, &q))) - return ret; - back = q.cdsc_format; /* local copy */ - sanitize_format(&q.cdsc_absaddr, &back, requested); - sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested); - IOCTL_OUT(arg, struct cdrom_subchnl, q); - /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ - return 0; - } - case CDROMREADTOCHDR: { - struct cdrom_tochdr header; - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */ - IOCTL_IN(arg, struct cdrom_tochdr, header); - if ((ret=cdo->audio_ioctl(cdi, cmd, &header))) - return ret; - IOCTL_OUT(arg, struct cdrom_tochdr, header); - /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */ - return 0; - } - case CDROMREADTOCENTRY: { - struct cdrom_tocentry entry; - u_char requested_format; - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */ - IOCTL_IN(arg, struct cdrom_tocentry, entry); - requested_format = entry.cdte_format; - if (!((requested_format == CDROM_MSF) || - (requested_format == CDROM_LBA))) - return -EINVAL; - /* make interface to low-level uniform */ - entry.cdte_format = CDROM_MSF; - if ((ret=cdo->audio_ioctl(cdi, cmd, &entry))) - return ret; - sanitize_format(&entry.cdte_addr, - &entry.cdte_format, requested_format); - IOCTL_OUT(arg, struct cdrom_tocentry, entry); - /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */ - return 0; - } - case CDROMPLAYMSF: { - struct cdrom_msf msf; - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); - IOCTL_IN(arg, struct cdrom_msf, msf); - return cdo->audio_ioctl(cdi, cmd, &msf); - } - case CDROMPLAYTRKIND: { - struct cdrom_ti ti; - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n"); - IOCTL_IN(arg, struct cdrom_ti, ti); - CHECKAUDIO; - return cdo->audio_ioctl(cdi, cmd, &ti); - } - case CDROMVOLCTRL: { - struct cdrom_volctrl volume; - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - cdinfo(CD_DO_IOCTL, "entering CDROMVOLCTRL\n"); - IOCTL_IN(arg, struct cdrom_volctrl, volume); - return cdo->audio_ioctl(cdi, cmd, &volume); - } - case CDROMVOLREAD: { - struct cdrom_volctrl volume; - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - cdinfo(CD_DO_IOCTL, "entering CDROMVOLREAD\n"); - if ((ret=cdo->audio_ioctl(cdi, cmd, &volume))) - return ret; - IOCTL_OUT(arg, struct cdrom_volctrl, volume); - return 0; - } - case CDROMSTART: - case CDROMSTOP: - case CDROMPAUSE: - case CDROMRESUME: { - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - cdinfo(CD_DO_IOCTL, "doing audio ioctl (start/stop/pause/resume)\n"); - CHECKAUDIO; - return cdo->audio_ioctl(cdi, cmd, NULL); - } - } /* switch */ - - /* do the device specific ioctls */ - if (CDROM_CAN(CDC_IOCTLS)) - return cdo->dev_ioctl(cdi, cmd, arg); - - return -ENOSYS; -} - -static inline -int msf_to_lba(char m, char s, char f) -{ - return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET; -} - -/* - * Required when we need to use READ_10 to issue other than 2048 block - * reads - */ -static int cdrom_switch_blocksize(struct cdrom_device_info *cdi, int size) -{ - struct cdrom_device_ops *cdo = cdi->ops; - struct cdrom_generic_command cgc; - struct modesel_head mh; - - memset(&mh, 0, sizeof(mh)); - mh.block_desc_length = 0x08; - mh.block_length_med = (size >> 8) & 0xff; - mh.block_length_lo = size & 0xff; - - memset(&cgc, 0, sizeof(cgc)); - cgc.cmd[0] = 0x15; - cgc.cmd[1] = 1 << 4; - cgc.cmd[4] = 12; - cgc.buflen = sizeof(mh); - cgc.buffer = (char *) &mh; - cgc.data_direction = CGC_DATA_WRITE; - mh.block_desc_length = 0x08; - mh.block_length_med = (size >> 8) & 0xff; - mh.block_length_lo = size & 0xff; - - return cdo->generic_packet(cdi, &cgc); -} - -static int cdrom_do_cmd(struct cdrom_device_info *cdi, - struct cdrom_generic_command *cgc) -{ - struct request_sense *usense, sense; - unsigned char *ubuf; - int ret; - - if (cgc->data_direction == CGC_DATA_UNKNOWN) - return -EINVAL; - - if (cgc->buflen < 0 || cgc->buflen >= 131072) - return -EINVAL; - - if ((ubuf = cgc->buffer)) { - cgc->buffer = kmalloc(cgc->buflen, GFP_KERNEL); - if (cgc->buffer == NULL) - return -ENOMEM; - } - - usense = cgc->sense; - cgc->sense = &sense; - if (usense && !access_ok(VERIFY_WRITE, usense, sizeof(*usense))) - return -EFAULT; - - if (cgc->data_direction == CGC_DATA_READ) { - if (!access_ok(VERIFY_READ, ubuf, cgc->buflen)) - return -EFAULT; - } else if (cgc->data_direction == CGC_DATA_WRITE) { - if (copy_from_user(cgc->buffer, ubuf, cgc->buflen)) { - kfree(cgc->buffer); - return -EFAULT; - } - } - - ret = cdi->ops->generic_packet(cdi, cgc); - __copy_to_user(usense, cgc->sense, sizeof(*usense)); - if (!ret && cgc->data_direction == CGC_DATA_READ) - __copy_to_user(ubuf, cgc->buffer, cgc->buflen); - kfree(cgc->buffer); - return ret; -} - -static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, - unsigned long arg) -{ - struct cdrom_device_ops *cdo = cdi->ops; - struct cdrom_generic_command cgc; - kdev_t dev = cdi->dev; - char buffer[32]; - int ret = 0; - - memset(&cgc, 0, sizeof(cgc)); - - /* build a unified command and queue it through - cdo->generic_packet() */ - switch (cmd) { - case CDROMREADRAW: - case CDROMREADMODE1: - case CDROMREADMODE2: { - struct cdrom_msf msf; - int blocksize = 0, format = 0, lba; - - switch (cmd) { - case CDROMREADRAW: - blocksize = CD_FRAMESIZE_RAW; - break; - case CDROMREADMODE1: - blocksize = CD_FRAMESIZE; - format = 2; - break; - case CDROMREADMODE2: - blocksize = CD_FRAMESIZE_RAW0; - break; - } - IOCTL_IN(arg, struct cdrom_msf, msf); - lba = msf_to_lba(msf.cdmsf_min0,msf.cdmsf_sec0,msf.cdmsf_frame0); - /* FIXME: we need upper bound checking, too!! */ - if (lba < 0) - return -EINVAL; - cgc.buffer = (char *) kmalloc(blocksize, GFP_KERNEL); - if (cgc.buffer == NULL) - return -ENOMEM; - cgc.data_direction = CGC_DATA_READ; - ret = cdrom_read_block(cdi, &cgc, lba, 1, format, blocksize); - if (ret) { - /* - * SCSI-II devices are not required to support - * READ_CD, so let's try switching block size - */ - /* FIXME: switch back again... */ - if ((ret = cdrom_switch_blocksize(cdi, blocksize))) { - kfree(cgc.buffer); - return ret; - } - cgc.sense = NULL; - ret = cdrom_read_cd(cdi, &cgc, lba, blocksize, 1); - ret |= cdrom_switch_blocksize(cdi, blocksize); - } - if (!ret && copy_to_user((char *)arg, cgc.buffer, blocksize)) - ret = -EFAULT; - kfree(cgc.buffer); - return ret; - } - case CDROMREADAUDIO: { - struct cdrom_read_audio ra; - int lba, nr; - - IOCTL_IN(arg, struct cdrom_read_audio, ra); - - if (ra.addr_format == CDROM_MSF) - lba = msf_to_lba(ra.addr.msf.minute, - ra.addr.msf.second, - ra.addr.msf.frame); - else if (ra.addr_format == CDROM_LBA) - lba = ra.addr.lba; - else - return -EINVAL; - - /* FIXME: we need upper bound checking, too!! */ - if (lba < 0 || ra.nframes <= 0) - return -EINVAL; - - /* - * start with will ra.nframes size, back down if alloc fails - */ - nr = ra.nframes; - do { - cgc.buffer = kmalloc(CD_FRAMESIZE_RAW * nr, GFP_KERNEL); - if (cgc.buffer) - break; - - nr >>= 1; - } while (nr); - - if (!nr) - return -ENOMEM; - - if (!access_ok(VERIFY_WRITE, ra.buf, ra.nframes*CD_FRAMESIZE_RAW)) { - kfree(cgc.buffer); - return -EFAULT; - } - cgc.data_direction = CGC_DATA_READ; - while (ra.nframes > 0) { - if (nr > ra.nframes) - nr = ra.nframes; - - ret = cdrom_read_block(cdi, &cgc, lba, nr, 1, CD_FRAMESIZE_RAW); - if (ret) - break; - __copy_to_user(ra.buf, cgc.buffer, CD_FRAMESIZE_RAW*nr); - ra.buf += CD_FRAMESIZE_RAW * nr; - ra.nframes -= nr; - lba += nr; - } - kfree(cgc.buffer); - return ret; - } - case CDROMSUBCHNL: { - struct cdrom_subchnl q; - u_char requested, back; - IOCTL_IN(arg, struct cdrom_subchnl, q); - requested = q.cdsc_format; - if (!((requested == CDROM_MSF) || - (requested == CDROM_LBA))) - return -EINVAL; - q.cdsc_format = CDROM_MSF; - if ((ret = cdrom_read_subchannel(cdi, &q, 0))) - return ret; - back = q.cdsc_format; /* local copy */ - sanitize_format(&q.cdsc_absaddr, &back, requested); - sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested); - IOCTL_OUT(arg, struct cdrom_subchnl, q); - /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ - return 0; - } - case CDROMPLAYMSF: { - struct cdrom_msf msf; - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); - IOCTL_IN(arg, struct cdrom_msf, msf); - cgc.cmd[0] = GPCMD_PLAY_AUDIO_MSF; - cgc.cmd[3] = msf.cdmsf_min0; - cgc.cmd[4] = msf.cdmsf_sec0; - cgc.cmd[5] = msf.cdmsf_frame0; - cgc.cmd[6] = msf.cdmsf_min1; - cgc.cmd[7] = msf.cdmsf_sec1; - cgc.cmd[8] = msf.cdmsf_frame1; - cgc.data_direction = CGC_DATA_NONE; - return cdo->generic_packet(cdi, &cgc); - } - case CDROMPLAYBLK: { - struct cdrom_blk blk; - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYBLK\n"); - IOCTL_IN(arg, struct cdrom_blk, blk); - cgc.cmd[0] = GPCMD_PLAY_AUDIO_10; - cgc.cmd[2] = (blk.from >> 24) & 0xff; - cgc.cmd[3] = (blk.from >> 16) & 0xff; - cgc.cmd[4] = (blk.from >> 8) & 0xff; - cgc.cmd[5] = blk.from & 0xff; - cgc.cmd[7] = (blk.len >> 8) & 0xff; - cgc.cmd[8] = blk.len & 0xff; - cgc.data_direction = CGC_DATA_NONE; - return cdo->generic_packet(cdi, &cgc); - } - case CDROMVOLCTRL: - case CDROMVOLREAD: { - struct cdrom_volctrl volctrl; - char mask[32]; - unsigned short offset; - cdinfo(CD_DO_IOCTL, "entering CDROMVOLUME\n"); - - IOCTL_IN(arg, struct cdrom_volctrl, volctrl); - - cgc.buffer = buffer; - cgc.buflen = 24; - if ((ret = cdrom_mode_sense(cdi, &cgc, GPMODE_AUDIO_CTL_PAGE, 0))) - return ret; - - /* some drives have longer pages, adjust and reread. */ - if (buffer[1] > cgc.buflen) { - cgc.buflen = buffer[1] + 2; - if ((ret = cdrom_mode_sense(cdi, &cgc, - GPMODE_AUDIO_CTL_PAGE, 0))) - return ret; - } - - /* get the offset from the length of the page. length - is measure from byte 2 an on, thus the 14. */ - offset = buffer[1] - 14; - - /* now we have the current volume settings. if it was only - a CDROMVOLREAD, return these values */ - if (cmd == CDROMVOLREAD) { - volctrl.channel0 = buffer[offset+9]; - volctrl.channel1 = buffer[offset+11]; - volctrl.channel2 = buffer[offset+13]; - volctrl.channel3 = buffer[offset+15]; - IOCTL_OUT(arg, struct cdrom_volctrl, volctrl); - return 0; - } - - /* get the volume mask */ - cgc.buffer = mask; - if ((ret = cdrom_mode_sense(cdi, &cgc, - GPMODE_AUDIO_CTL_PAGE, 1))) - return ret; - - buffer[offset+9] = volctrl.channel0 & mask[offset+9]; - buffer[offset+11] = volctrl.channel1 & mask[offset+11]; - buffer[offset+13] = volctrl.channel2 & mask[offset+13]; - buffer[offset+15] = volctrl.channel3 & mask[offset+15]; - - /* set volume */ - cgc.buffer = buffer; - return cdrom_mode_select(cdi, &cgc); - } - - case CDROMSTART: - case CDROMSTOP: { - cdinfo(CD_DO_IOCTL, "entering CDROMSTART/CDROMSTOP\n"); - cgc.cmd[0] = GPCMD_START_STOP_UNIT; - cgc.cmd[1] = 1; - cgc.cmd[4] = (cmd == CDROMSTART) ? 1 : 0; - cgc.data_direction = CGC_DATA_NONE; - return cdo->generic_packet(cdi, &cgc); - } - - case CDROMPAUSE: - case CDROMRESUME: { - cdinfo(CD_DO_IOCTL, "entering CDROMPAUSE/CDROMRESUME\n"); - cgc.cmd[0] = GPCMD_PAUSE_RESUME; - cgc.cmd[8] = (cmd == CDROMRESUME) ? 1 : 0; - cgc.data_direction = CGC_DATA_NONE; - return cdo->generic_packet(cdi, &cgc); - } - - case DVD_READ_STRUCT: { - dvd_struct *s; - int size = sizeof(dvd_struct); - if (!CDROM_CAN(CDC_DVD)) - return -ENOSYS; - if ((s = (dvd_struct *) kmalloc(size, GFP_KERNEL)) == NULL) - return -ENOMEM; - cdinfo(CD_DO_IOCTL, "entering DVD_READ_STRUCT\n"); - if (copy_from_user(s, (dvd_struct *)arg, size)) { - kfree(s); - return -EFAULT; - } - if ((ret = dvd_read_struct(cdi, s))) { - kfree(s); - return ret; - } - if (copy_to_user((dvd_struct *)arg, s, size)) - ret = -EFAULT; - kfree(s); - return ret; - } - - case DVD_AUTH: { - dvd_authinfo ai; - if (!CDROM_CAN(CDC_DVD)) - return -ENOSYS; - cdinfo(CD_DO_IOCTL, "entering DVD_AUTH\n"); - IOCTL_IN(arg, dvd_authinfo, ai); - if ((ret = dvd_do_auth (cdi, &ai))) - return ret; - IOCTL_OUT(arg, dvd_authinfo, ai); - return 0; - } - - case CDROM_SEND_PACKET: { - if (!CDROM_CAN(CDC_GENERIC_PACKET)) - return -ENOSYS; - cdinfo(CD_DO_IOCTL, "entering CDROM_SEND_PACKET\n"); - IOCTL_IN(arg, struct cdrom_generic_command, cgc); - return cdrom_do_cmd(cdi, &cgc); - } - case CDROM_NEXT_WRITABLE: { - long next = 0; - cdinfo(CD_DO_IOCTL, "entering CDROM_NEXT_WRITABLE\n"); - if ((ret = cdrom_get_next_writable(dev, &next))) - return ret; - IOCTL_OUT(arg, long, next); - return 0; - } - case CDROM_LAST_WRITTEN: { - long last = 0; - cdinfo(CD_DO_IOCTL, "entering CDROM_LAST_WRITTEN\n"); - if ((ret = cdrom_get_last_written(dev, &last))) - return ret; - IOCTL_OUT(arg, long, last); - return 0; - } - } /* switch */ - - return -ENOTTY; -} - -int cdrom_get_track_info(kdev_t dev, __u16 track, __u8 type, - track_information *ti) -{ - struct cdrom_device_info *cdi = cdrom_find_device(dev); - struct cdrom_device_ops *cdo = cdi->ops; - struct cdrom_generic_command cgc; - int ret; - - init_cdrom_command(&cgc, ti, 8, CGC_DATA_READ); - cgc.cmd[0] = GPCMD_READ_TRACK_RZONE_INFO; - cgc.cmd[1] = type & 3; - cgc.cmd[4] = (track & 0xff00) >> 8; - cgc.cmd[5] = track & 0xff; - cgc.cmd[8] = 8; - cgc.quiet = 1; - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - cgc.buflen = be16_to_cpu(ti->track_information_length) + - sizeof(ti->track_information_length); - - if (cgc.buflen > sizeof(track_information)) - cgc.buflen = sizeof(track_information); - - cgc.cmd[8] = cgc.buflen; - return cdo->generic_packet(cdi, &cgc); -} - -/* requires CD R/RW */ -int cdrom_get_disc_info(kdev_t dev, disc_information *di) -{ - struct cdrom_device_info *cdi = cdrom_find_device(dev); - struct cdrom_device_ops *cdo = cdi->ops; - struct cdrom_generic_command cgc; - int ret; - - /* set up command and get the disc info */ - init_cdrom_command(&cgc, di, sizeof(*di), CGC_DATA_READ); - cgc.cmd[0] = GPCMD_READ_DISC_INFO; - cgc.cmd[8] = cgc.buflen = 2; - cgc.quiet = 1; - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - /* not all drives have the same disc_info length, so requeue - * packet with the length the drive tells us it can supply - */ - cgc.buflen = be16_to_cpu(di->disc_information_length) + - sizeof(di->disc_information_length); - - if (cgc.buflen > sizeof(disc_information)) - cgc.buflen = sizeof(disc_information); - - cgc.cmd[8] = cgc.buflen; - return cdo->generic_packet(cdi, &cgc); -} - - -/* return the last written block on the CD-R media. this is for the udf - file system. */ -int cdrom_get_last_written(kdev_t dev, long *last_written) -{ - struct cdrom_device_info *cdi = cdrom_find_device(dev); - struct cdrom_tocentry toc; - disc_information di; - track_information ti; - __u32 last_track; - int ret = -1; - - if (!CDROM_CAN(CDC_GENERIC_PACKET)) - goto use_toc; - - if ((ret = cdrom_get_disc_info(dev, &di))) - goto use_toc; - - last_track = (di.last_track_msb << 8) | di.last_track_lsb; - if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti))) - goto use_toc; - - /* if this track is blank, try the previous. */ - if (ti.blank) { - last_track--; - if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti))) - goto use_toc; - } - - /* if last recorded field is valid, return it. */ - if (ti.lra_v) { - *last_written = be32_to_cpu(ti.last_rec_address); - } else { - /* make it up instead */ - *last_written = be32_to_cpu(ti.track_start) + - be32_to_cpu(ti.track_size); - if (ti.free_blocks) - *last_written -= (be32_to_cpu(ti.free_blocks) + 7); - } - return 0; - - /* this is where we end up if the drive either can't do a - GPCMD_READ_DISC_INFO or GPCMD_READ_TRACK_RZONE_INFO or if - it fails. then we return the toc contents. */ -use_toc: - toc.cdte_format = CDROM_MSF; - toc.cdte_track = CDROM_LEADOUT; - if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &toc)) - return ret; - sanitize_format(&toc.cdte_addr, &toc.cdte_format, CDROM_LBA); - *last_written = toc.cdte_addr.lba; - return 0; -} - -/* return the next writable block. also for udf file system. */ -int cdrom_get_next_writable(kdev_t dev, long *next_writable) -{ - struct cdrom_device_info *cdi = cdrom_find_device(dev); - disc_information di; - track_information ti; - __u16 last_track; - int ret = -1; - - if (!CDROM_CAN(CDC_GENERIC_PACKET)) - goto use_last_written; - - if ((ret = cdrom_get_disc_info(dev, &di))) - goto use_last_written; - - last_track = (di.last_track_msb << 8) | di.last_track_lsb; - if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti))) - goto use_last_written; - - /* if this track is blank, try the previous. */ - if (ti.blank) { - last_track--; - if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti))) - goto use_last_written; - } - - /* if next recordable address field is valid, use it. */ - if (ti.nwa_v) - *next_writable = be32_to_cpu(ti.next_writable); - else - goto use_last_written; - - return 0; - -use_last_written: - if ((ret = cdrom_get_last_written(dev, next_writable))) { - *next_writable = 0; - return ret; - } else { - *next_writable += 7; - return 0; - } -} - -EXPORT_SYMBOL(cdrom_get_disc_info); -EXPORT_SYMBOL(cdrom_get_track_info); -EXPORT_SYMBOL(cdrom_get_next_writable); -EXPORT_SYMBOL(cdrom_get_last_written); -EXPORT_SYMBOL(cdrom_count_tracks); -EXPORT_SYMBOL(register_cdrom); -EXPORT_SYMBOL(unregister_cdrom); -EXPORT_SYMBOL(cdrom_open); -EXPORT_SYMBOL(cdrom_release); -EXPORT_SYMBOL(cdrom_ioctl); -EXPORT_SYMBOL(cdrom_media_changed); -EXPORT_SYMBOL(cdrom_number_of_slots); -EXPORT_SYMBOL(cdrom_select_disc); -EXPORT_SYMBOL(cdrom_mode_select); -EXPORT_SYMBOL(cdrom_mode_sense); -EXPORT_SYMBOL(init_cdrom_command); -EXPORT_SYMBOL(cdrom_find_device); - -#ifdef CONFIG_SYSCTL - -#define CDROM_STR_SIZE 1000 - -struct cdrom_sysctl_settings { - char info[CDROM_STR_SIZE]; /* general info */ - int autoclose; /* close tray upon mount, etc */ - int autoeject; /* eject on umount */ - int debug; /* turn on debugging messages */ - int lock; /* lock the door on device open */ - int check; /* check media type */ -} cdrom_sysctl_settings; - -int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp, - void *buffer, size_t *lenp) -{ - int pos; - struct cdrom_device_info *cdi; - char *info = cdrom_sysctl_settings.info; - - if (!*lenp || (filp->f_pos && !write)) { - *lenp = 0; - return 0; - } - - pos = sprintf(info, "CD-ROM information, " VERSION "\n"); - - pos += sprintf(info+pos, "\ndrive name:\t"); - for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t%s", cdi->name); - - pos += sprintf(info+pos, "\ndrive speed:\t"); - for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t%d", cdi->speed); - - pos += sprintf(info+pos, "\ndrive # of slots:"); - for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t%d", cdi->capacity); - - pos += sprintf(info+pos, "\nCan close tray:\t"); - for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CLOSE_TRAY) != 0); - - pos += sprintf(info+pos, "\nCan open tray:\t"); - for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_OPEN_TRAY) != 0); - - pos += sprintf(info+pos, "\nCan lock tray:\t"); - for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_LOCK) != 0); - - pos += sprintf(info+pos, "\nCan change speed:"); - for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_SPEED) != 0); - - pos += sprintf(info+pos, "\nCan select disk:"); - for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_DISC) != 0); - - pos += sprintf(info+pos, "\nCan read multisession:"); - for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MULTI_SESSION) != 0); - - pos += sprintf(info+pos, "\nCan read MCN:\t"); - for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MCN) != 0); - - pos += sprintf(info+pos, "\nReports media changed:"); - for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MEDIA_CHANGED) != 0); - - pos += sprintf(info+pos, "\nCan play audio:\t"); - for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_PLAY_AUDIO) != 0); - - pos += sprintf(info+pos, "\nCan write CD-R:\t"); - for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_R) != 0); - - pos += sprintf(info+pos, "\nCan write CD-RW:"); - for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_RW) != 0); - - pos += sprintf(info+pos, "\nCan read DVD:\t"); - for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD) != 0); - - pos += sprintf(info+pos, "\nCan write DVD-R:"); - for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_R) != 0); - - pos += sprintf(info+pos, "\nCan write DVD-RAM:"); - for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_RAM) != 0); - - strcpy(info+pos,"\n\n"); - - return proc_dostring(ctl, write, filp, buffer, lenp); -} - -/* Unfortunately, per device settings are not implemented through - procfs/sysctl yet. When they are, this will naturally disappear. For now - just update all drives. Later this will become the template on which - new registered drives will be based. */ -void cdrom_update_settings(void) -{ - struct cdrom_device_info *cdi; - - for (cdi = topCdromPtr; cdi != NULL; cdi = cdi->next) { - if (autoclose && CDROM_CAN(CDC_CLOSE_TRAY)) - cdi->options |= CDO_AUTO_CLOSE; - else if (!autoclose) - cdi->options &= ~CDO_AUTO_CLOSE; - if (autoeject && CDROM_CAN(CDC_OPEN_TRAY)) - cdi->options |= CDO_AUTO_EJECT; - else if (!autoeject) - cdi->options &= ~CDO_AUTO_EJECT; - if (lockdoor && CDROM_CAN(CDC_LOCK)) - cdi->options |= CDO_LOCK; - else if (!lockdoor) - cdi->options &= ~CDO_LOCK; - if (check_media_type) - cdi->options |= CDO_CHECK_TYPE; - else - cdi->options &= ~CDO_CHECK_TYPE; - } -} - -static int cdrom_sysctl_handler(ctl_table *ctl, int write, struct file * filp, - void *buffer, size_t *lenp) -{ - int *valp = ctl->data; - int val = *valp; - int ret; - - ret = proc_dointvec(ctl, write, filp, buffer, lenp); - - if (write && *valp != val) { - - /* we only care for 1 or 0. */ - if (*valp) - *valp = 1; - else - *valp = 0; - - switch (ctl->ctl_name) { - case DEV_CDROM_AUTOCLOSE: { - if (valp == &cdrom_sysctl_settings.autoclose) - autoclose = cdrom_sysctl_settings.autoclose; - break; - } - case DEV_CDROM_AUTOEJECT: { - if (valp == &cdrom_sysctl_settings.autoeject) - autoeject = cdrom_sysctl_settings.autoeject; - break; - } - case DEV_CDROM_DEBUG: { - if (valp == &cdrom_sysctl_settings.debug) - debug = cdrom_sysctl_settings.debug; - break; - } - case DEV_CDROM_LOCK: { - if (valp == &cdrom_sysctl_settings.lock) - lockdoor = cdrom_sysctl_settings.lock; - break; - } - case DEV_CDROM_CHECK_MEDIA: { - if (valp == &cdrom_sysctl_settings.check) - check_media_type = cdrom_sysctl_settings.check; - break; - } - } - /* update the option flags according to the changes. we - don't have per device options through sysctl yet, - but we will have and then this will disappear. */ - cdrom_update_settings(); - } - - return ret; -} - -/* Place files in /proc/sys/dev/cdrom */ -ctl_table cdrom_table[] = { - {DEV_CDROM_INFO, "info", &cdrom_sysctl_settings.info, - CDROM_STR_SIZE, 0444, NULL, &cdrom_sysctl_info}, - {DEV_CDROM_AUTOCLOSE, "autoclose", &cdrom_sysctl_settings.autoclose, - sizeof(int), 0644, NULL, &cdrom_sysctl_handler }, - {DEV_CDROM_AUTOEJECT, "autoeject", &cdrom_sysctl_settings.autoeject, - sizeof(int), 0644, NULL, &cdrom_sysctl_handler }, - {DEV_CDROM_DEBUG, "debug", &cdrom_sysctl_settings.debug, - sizeof(int), 0644, NULL, &cdrom_sysctl_handler }, - {DEV_CDROM_LOCK, "lock", &cdrom_sysctl_settings.lock, - sizeof(int), 0644, NULL, &cdrom_sysctl_handler }, - {DEV_CDROM_CHECK_MEDIA, "check_media", &cdrom_sysctl_settings.check, - sizeof(int), 0644, NULL, &cdrom_sysctl_handler }, - {0} - }; - -ctl_table cdrom_cdrom_table[] = { - {DEV_CDROM, "cdrom", NULL, 0, 0555, cdrom_table}, - {0} - }; - -/* Make sure that /proc/sys/dev is there */ -ctl_table cdrom_root_table[] = { -#ifdef CONFIG_PROC_FS - {CTL_DEV, "dev", NULL, 0, 0555, cdrom_cdrom_table}, -#endif /* CONFIG_PROC_FS */ - {0} - }; -static struct ctl_table_header *cdrom_sysctl_header; - -static void cdrom_sysctl_register(void) -{ - static int initialized; - - if (initialized == 1) - return; - - cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1); - cdrom_root_table->child->de->owner = THIS_MODULE; - - /* set the defaults */ - cdrom_sysctl_settings.autoclose = autoclose; - cdrom_sysctl_settings.autoeject = autoeject; - cdrom_sysctl_settings.debug = debug; - cdrom_sysctl_settings.lock = lockdoor; - cdrom_sysctl_settings.check = check_media_type; - - initialized = 1; -} - -static void cdrom_sysctl_unregister(void) -{ - if (cdrom_sysctl_header) - unregister_sysctl_table(cdrom_sysctl_header); -} - -#endif /* CONFIG_SYSCTL */ - -static int __init cdrom_init(void) -{ -#ifdef CONFIG_SYSCTL - cdrom_sysctl_register(); -#endif -#if 0 - if (!devfs_handle) - devfs_handle = devfs_mk_dir(NULL, "cdroms", NULL); -#endif - return 0; -} - -static void __exit cdrom_exit(void) -{ - printk(KERN_INFO "Uniform CD-ROM driver unloaded\n"); -#ifdef CONFIG_SYSCTL - cdrom_sysctl_unregister(); -#endif -#if 0 - devfs_unregister(devfs_handle); -#endif -} - -module_init(cdrom_init); -module_exit(cdrom_exit); -MODULE_LICENSE("GPL"); diff --git a/xen/drivers/ide/Makefile b/xen/drivers/ide/Makefile deleted file mode 100644 index 574b7d2d79..0000000000 --- a/xen/drivers/ide/Makefile +++ /dev/null @@ -1,8 +0,0 @@ - -include $(BASEDIR)/Rules.mk - -default: $(OBJS) - $(LD) -r -o driver.o $(OBJS) - -clean: - rm -f *.o *~ core diff --git a/xen/drivers/ide/ide-cd.c b/xen/drivers/ide/ide-cd.c deleted file mode 100644 index ead14222a1..0000000000 --- a/xen/drivers/ide/ide-cd.c +++ /dev/null @@ -1,3084 +0,0 @@ -/* - * linux/drivers/ide/ide-cd.c - * - * Copyright (C) 1994, 1995, 1996 scott snyder - * Copyright (C) 1996-1998 Erik Andersen - * Copyright (C) 1998-2000 Jens Axboe - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * ATAPI CD-ROM driver. To be used with ide.c. - * See Documentation/cdrom/ide-cd for usage information. - * - * Suggestions are welcome. Patches that work are more welcome though. ;-) - * For those wishing to work on this driver, please be sure you download - * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI - * (SFF-8020i rev 2.6) standards. These documents can be obtained by - * anonymous ftp from: - * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps - * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf - * - * Drives that deviate from these standards will be accomodated as much - * as possible via compile time or command-line options. Since I only have - * a few drives, you generally need to send me patches... - * - * ---------------------------------- - * TO DO LIST: - * -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on - * boot - * - * ---------------------------------- - * 1.00 Oct 31, 1994 -- Initial version. - * 1.01 Nov 2, 1994 -- Fixed problem with starting request in - * cdrom_check_status. - * 1.03 Nov 25, 1994 -- leaving unmask_intr[] as a user-setting (as for disks) - * (from mlord) -- minor changes to cdrom_setup() - * -- renamed ide_dev_s to ide_drive_t, enable irq on command - * 2.00 Nov 27, 1994 -- Generalize packet command interface; - * add audio ioctls. - * 2.01 Dec 3, 1994 -- Rework packet command interface to handle devices - * which send an interrupt when ready for a command. - * 2.02 Dec 11, 1994 -- Cache the TOC in the driver. - * Don't use SCMD_PLAYAUDIO_TI; it's not included - * in the current version of ATAPI. - * Try to use LBA instead of track or MSF addressing - * when possible. - * Don't wait for READY_STAT. - * 2.03 Jan 10, 1995 -- Rewrite block read routines to handle block sizes - * other than 2k and to move multiple sectors in a - * single transaction. - * 2.04 Apr 21, 1995 -- Add work-around for Creative Labs CD220E drives. - * Thanks to Nick Saw for - * help in figuring this out. Ditto for Acer and - * Aztech drives, which seem to have the same problem. - * 2.04b May 30, 1995 -- Fix to match changes in ide.c version 3.16 -ml - * 2.05 Jun 8, 1995 -- Don't attempt to retry after an illegal request - * or data protect error. - * Use HWIF and DEV_HWIF macros as in ide.c. - * Always try to do a request_sense after - * a failed command. - * Include an option to give textual descriptions - * of ATAPI errors. - * Fix a bug in handling the sector cache which - * showed up if the drive returned data in 512 byte - * blocks (like Pioneer drives). Thanks to - * Richard Hirst for diagnosing this. - * Properly supply the page number field in the - * MODE_SELECT command. - * PLAYAUDIO12 is broken on the Aztech; work around it. - * 2.05x Aug 11, 1995 -- lots of data structure renaming/restructuring in ide.c - * (my apologies to Scott, but now ide-cd.c is independent) - * 3.00 Aug 22, 1995 -- Implement CDROMMULTISESSION ioctl. - * Implement CDROMREADAUDIO ioctl (UNTESTED). - * Use input_ide_data() and output_ide_data(). - * Add door locking. - * Fix usage count leak in cdrom_open, which happened - * when a read-write mount was attempted. - * Try to load the disk on open. - * Implement CDROMEJECT_SW ioctl (off by default). - * Read total cdrom capacity during open. - * Rearrange logic in cdrom_decode_status. Issue - * request sense commands for failed packet commands - * from here instead of from cdrom_queue_packet_command. - * Fix a race condition in retrieving error information. - * Suppress printing normal unit attention errors and - * some drive not ready errors. - * Implement CDROMVOLREAD ioctl. - * Implement CDROMREADMODE1/2 ioctls. - * Fix race condition in setting up interrupt handlers - * when the `serialize' option is used. - * 3.01 Sep 2, 1995 -- Fix ordering of reenabling interrupts in - * cdrom_queue_request. - * Another try at using ide_[input,output]_data. - * 3.02 Sep 16, 1995 -- Stick total disk capacity in partition table as well. - * Make VERBOSE_IDE_CD_ERRORS dump failed command again. - * Dump out more information for ILLEGAL REQUEST errs. - * Fix handling of errors occurring before the - * packet command is transferred. - * Fix transfers with odd bytelengths. - * 3.03 Oct 27, 1995 -- Some Creative drives have an id of just `CD'. - * `DCI-2S10' drives are broken too. - * 3.04 Nov 20, 1995 -- So are Vertos drives. - * 3.05 Dec 1, 1995 -- Changes to go with overhaul of ide.c and ide-tape.c - * 3.06 Dec 16, 1995 -- Add support needed for partitions. - * More workarounds for Vertos bugs (based on patches - * from Holger Dietze ). - * Try to eliminate byteorder assumptions. - * Use atapi_cdrom_subchnl struct definition. - * Add STANDARD_ATAPI compilation option. - * 3.07 Jan 29, 1996 -- More twiddling for broken drives: Sony 55D, - * Vertos 300. - * Add NO_DOOR_LOCKING configuration option. - * Handle drive_cmd requests w/NULL args (for hdparm -t). - * Work around sporadic Sony55e audio play problem. - * 3.07a Feb 11, 1996 -- check drive->id for NULL before dereferencing, to fix - * problem with "hde=cdrom" with no drive present. -ml - * 3.08 Mar 6, 1996 -- More Vertos workarounds. - * 3.09 Apr 5, 1996 -- Add CDROMCLOSETRAY ioctl. - * Switch to using MSF addressing for audio commands. - * Reformat to match kernel tabbing style. - * Add CDROM_GET_UPC ioctl. - * 3.10 Apr 10, 1996 -- Fix compilation error with STANDARD_ATAPI. - * 3.11 Apr 29, 1996 -- Patch from Heiko Eissfeldt - * to remove redundant verify_area calls. - * 3.12 May 7, 1996 -- Rudimentary changer support. Based on patches - * from Gerhard Zuber . - * Let open succeed even if there's no loaded disc. - * 3.13 May 19, 1996 -- Fixes for changer code. - * 3.14 May 29, 1996 -- Add work-around for Vertos 600. - * (From Hennus Bergman .) - * 3.15 July 2, 1996 -- Added support for Sanyo 3 CD changers - * from Ben Galliart with - * special help from Jeff Lightfoot - * - * 3.15a July 9, 1996 -- Improved Sanyo 3 CD changer identification - * 3.16 Jul 28, 1996 -- Fix from Gadi to reduce kernel stack usage for ioctl. - * 3.17 Sep 17, 1996 -- Tweak audio reads for some drives. - * Start changing CDROMLOADFROMSLOT to CDROM_SELECT_DISC. - * 3.18 Oct 31, 1996 -- Added module and DMA support. - * - * - * 4.00 Nov 5, 1996 -- New ide-cd maintainer, - * Erik B. Andersen - * -- Newer Creative drives don't always set the error - * register correctly. Make sure we see media changes - * regardless. - * -- Integrate with generic cdrom driver. - * -- CDROMGETSPINDOWN and CDROMSETSPINDOWN ioctls, based on - * a patch from Ciro Cattuto <>. - * -- Call set_device_ro. - * -- Implement CDROMMECHANISMSTATUS and CDROMSLOTTABLE - * ioctls, based on patch by Erik Andersen - * -- Add some probes of drive capability during setup. - * - * 4.01 Nov 11, 1996 -- Split into ide-cd.c and ide-cd.h - * -- Removed CDROMMECHANISMSTATUS and CDROMSLOTTABLE - * ioctls in favor of a generalized approach - * using the generic cdrom driver. - * -- Fully integrated with the 2.1.X kernel. - * -- Other stuff that I forgot (lots of changes) - * - * 4.02 Dec 01, 1996 -- Applied patch from Gadi Oxman - * to fix the drive door locking problems. - * - * 4.03 Dec 04, 1996 -- Added DSC overlap support. - * 4.04 Dec 29, 1996 -- Added CDROMREADRAW ioclt based on patch - * by Ales Makarov (xmakarov@sun.felk.cvut.cz) - * - * 4.05 Nov 20, 1997 -- Modified to print more drive info on init - * Minor other changes - * Fix errors on CDROMSTOP (If you have a "Dolphin", - * you must define IHAVEADOLPHIN) - * Added identifier so new Sanyo CD-changer works - * Better detection if door locking isn't supported - * - * 4.06 Dec 17, 1997 -- fixed endless "tray open" messages -ml - * 4.07 Dec 17, 1997 -- fallback to set pc->stat on "tray open" - * 4.08 Dec 18, 1997 -- spew less noise when tray is empty - * -- fix speed display for ACER 24X, 18X - * 4.09 Jan 04, 1998 -- fix handling of the last block so we return - * an end of file instead of an I/O error (Gadi) - * 4.10 Jan 24, 1998 -- fixed a bug so now changers can change to a new - * slot when there is no disc in the current slot. - * -- Fixed a memory leak where info->changer_info was - * malloc'ed but never free'd when closing the device. - * -- Cleaned up the global namespace a bit by making more - * functions static that should already have been. - * 4.11 Mar 12, 1998 -- Added support for the CDROM_SELECT_SPEED ioctl - * based on a patch for 2.0.33 by Jelle Foks - * , a patch for 2.0.33 - * by Toni Giorgino , the SCSI - * version, and my own efforts. -erik - * -- Fixed a stupid bug which egcs was kind enough to - * inform me of where "Illegal mode for this track" - * was never returned due to a comparison on data - * types of limited range. - * 4.12 Mar 29, 1998 -- Fixed bug in CDROM_SELECT_SPEED so write speed is - * now set ionly for CD-R and CD-RW drives. I had - * removed this support because it produced errors. - * It produced errors _only_ for non-writers. duh. - * 4.13 May 05, 1998 -- Suppress useless "in progress of becoming ready" - * messages, since this is not an error. - * -- Change error messages to be const - * -- Remove a "\t" which looks ugly in the syslogs - * 4.14 July 17, 1998 -- Change to pointing to .ps version of ATAPI spec - * since the .pdf version doesn't seem to work... - * -- Updated the TODO list to something more current. - * - * 4.15 Aug 25, 1998 -- Updated ide-cd.h to respect mechine endianess, - * patch thanks to "Eddie C. Dost" - * - * 4.50 Oct 19, 1998 -- New maintainers! - * Jens Axboe - * Chris Zwilling - * - * 4.51 Dec 23, 1998 -- Jens Axboe - * - ide_cdrom_reset enabled since the ide subsystem - * handles resets fine now. - * - Transfer size fix for Samsung CD-ROMs, thanks to - * "Ville Hallik" . - * - other minor stuff. - * - * 4.52 Jan 19, 1999 -- Jens Axboe - * - Detect DVD-ROM/RAM drives - * - * 4.53 Feb 22, 1999 - Include other model Samsung and one Goldstar - * drive in transfer size limit. - * - Fix the I/O error when doing eject without a medium - * loaded on some drives. - * - CDROMREADMODE2 is now implemented through - * CDROMREADRAW, since many drives don't support - * MODE2 (even though ATAPI 2.6 says they must). - * - Added ignore parameter to ide-cd (as a module), eg - * insmod ide-cd ignore='hda hdb' - * Useful when using ide-cd in conjunction with - * ide-scsi. TODO: non-modular way of doing the - * same. - * - * 4.54 Aug 5, 1999 - Support for MMC2 class commands through the generic - * packet interface to cdrom.c. - * - Unified audio ioctl support, most of it. - * - cleaned up various deprecated verify_area(). - * - Added ide_cdrom_packet() as the interface for - * the Uniform generic_packet(). - * - bunch of other stuff, will fill in logs later. - * - report 1 slot for non-changers, like the other - * cd-rom drivers. don't report select disc for - * non-changers as well. - * - mask out audio playing, if the device can't do it. - * - * 4.55 Sep 1, 1999 - Eliminated the rest of the audio ioctls, except - * for CDROMREADTOC[ENTRY|HEADER]. Some of the drivers - * use this independently of the actual audio handling. - * They will disappear later when I get the time to - * do it cleanly. - * - Minimize the TOC reading - only do it when we - * know a media change has occurred. - * - Moved all the CDROMREADx ioctls to the Uniform layer. - * - Heiko Eissfeldt supplied - * some fixes for CDI. - * - CD-ROM leaving door locked fix from Andries - * Brouwer - * - Erik Andersen unified - * commands across the various drivers and how - * sense errors are handled. - * - * 4.56 Sep 12, 1999 - Removed changer support - it is now in the - * Uniform layer. - * - Added partition based multisession handling. - * - Mode sense and mode select moved to the - * Uniform layer. - * - Fixed a problem with WPI CDS-32X drive - it - * failed the capabilities - * - * 4.57 Apr 7, 2000 - Fixed sense reporting. - * - Fixed possible oops in ide_cdrom_get_last_session() - * - Fix locking mania and make ide_cdrom_reset relock - * - Stop spewing errors to log when magicdev polls with - * TEST_UNIT_READY on some drives. - * - Various fixes from Tobias Ringstrom: - * tray if it was locked prior to the reset. - * - cdrom_read_capacity returns one frame too little. - * - Fix real capacity reporting. - * - * 4.58 May 1, 2000 - Clean up ACER50 stuff. - * - Fix small problem with ide_cdrom_capacity - * - * 4.59 Aug 11, 2000 - Fix changer problem in cdrom_read_toc, we weren't - * correctly sensing a disc change. - * - Rearranged some code - * - Use extended sense on drives that support it for - * correctly reporting tray status -- from - * Michael D Johnson - * - *************************************************************************/ - -#define IDECD_VERSION "4.59" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -// #include - -#include -#include -#include -#include -#include - -#include "ide-cd.h" - -/**************************************************************************** - * Generic packet command support and error handling routines. - */ - -/* Mark that we've seen a media change, and invalidate our internal - buffers. */ -static void cdrom_saw_media_change (ide_drive_t *drive) -{ - struct cdrom_info *info = drive->driver_data; - - CDROM_STATE_FLAGS (drive)->media_changed = 1; - CDROM_STATE_FLAGS (drive)->toc_valid = 0; - info->nsectors_buffered = 0; -} - -static int cdrom_log_sense(ide_drive_t *drive, struct packet_command *pc, - struct request_sense *sense) -{ - int log = 0; - - if (sense == NULL || pc == NULL || pc->quiet) - return 0; - - switch (sense->sense_key) { - case NO_SENSE: case RECOVERED_ERROR: - break; - case NOT_READY: - /* - * don't care about tray state messages for - * e.g. capacity commands or in-progress or - * becoming ready - */ - if (sense->asc == 0x3a || sense->asc == 0x04) - break; - log = 1; - break; - case UNIT_ATTENTION: - /* - * Make good and sure we've seen this potential media - * change. Some drives (i.e. Creative) fail to present - * the correct sense key in the error register. - */ - cdrom_saw_media_change(drive); - break; - default: - log = 1; - break; - } - return log; -} - -static -void cdrom_analyze_sense_data(ide_drive_t *drive, - struct packet_command *failed_command, - struct request_sense *sense) -{ - - if (!cdrom_log_sense(drive, failed_command, sense)) - return; - - /* - * If a read toc is executed for a CD-R or CD-RW medium where - * the first toc has not been recorded yet, it will fail with - * 05/24/00 (which is a confusing error) - */ - if (failed_command && failed_command->c[0] == GPCMD_READ_TOC_PMA_ATIP) - if (sense->sense_key == 0x05 && sense->asc == 0x24) - return; - -#if VERBOSE_IDE_CD_ERRORS - { - int i; - const char *s; - char buf[80]; - - printk ("ATAPI device %s:\n", drive->name); - if (sense->error_code==0x70) - printk(" Error: "); - else if (sense->error_code==0x71) - printk(" Deferred Error: "); - else if (sense->error_code == 0x7f) - printk(" Vendor-specific Error: "); - else - printk(" Unknown Error Type: "); - - if (sense->sense_key < ARY_LEN(sense_key_texts)) - s = sense_key_texts[sense->sense_key]; - else - s = "bad sense key!"; - - printk("%s -- (Sense key=0x%02x)\n", s, sense->sense_key); - - if (sense->asc == 0x40) { - sprintf(buf, "Diagnostic failure on component 0x%02x", - sense->ascq); - s = buf; - } else { - int lo = 0, mid, hi = ARY_LEN(sense_data_texts); - unsigned long key = (sense->sense_key << 16); - key |= (sense->asc << 8); - if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd)) - key |= sense->ascq; - s = NULL; - - while (hi > lo) { - mid = (lo + hi) / 2; - if (sense_data_texts[mid].asc_ascq == key || - sense_data_texts[mid].asc_ascq == (0xff0000|key)) { - s = sense_data_texts[mid].text; - break; - } - else if (sense_data_texts[mid].asc_ascq > key) - hi = mid; - else - lo = mid+1; - } - } - - if (s == NULL) { - if (sense->asc > 0x80) - s = "(vendor-specific error)"; - else - s = "(reserved error code)"; - } - - printk(" %s -- (asc=0x%02x, ascq=0x%02x)\n", - s, sense->asc, sense->ascq); - - if (failed_command != NULL) { - - int lo=0, mid, hi= ARY_LEN (packet_command_texts); - s = NULL; - - while (hi > lo) { - mid = (lo + hi) / 2; - if (packet_command_texts[mid].packet_command == - failed_command->c[0]) { - s = packet_command_texts[mid].text; - break; - } - if (packet_command_texts[mid].packet_command > - failed_command->c[0]) - hi = mid; - else - lo = mid+1; - } - - printk (" The failed \"%s\" packet command was: \n \"", s); - for (i=0; ic); i++) - printk ("%02x ", failed_command->c[i]); - printk ("\"\n"); - } - - /* The SKSV bit specifies validity of the sense_key_specific - * in the next two commands. It is bit 7 of the first byte. - * In the case of NOT_READY, if SKSV is set the drive can - * give us nice ETA readings. - */ - if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) { - int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100; - printk(" Command is %02d%% complete\n", progress / 0xffff); - - } - - if (sense->sense_key == ILLEGAL_REQUEST && - (sense->sks[0] & 0x80) != 0) { - printk(" Error in %s byte %d", - (sense->sks[0] & 0x40) != 0 ? - "command packet" : "command data", - (sense->sks[1] << 8) + sense->sks[2]); - - if ((sense->sks[0] & 0x40) != 0) - printk (" bit %d", sense->sks[0] & 0x07); - - printk ("\n"); - } - } - -#else /* not VERBOSE_IDE_CD_ERRORS */ - - /* Suppress printing unit attention and `in progress of becoming ready' - errors when we're not being verbose. */ - - if (sense->sense_key == UNIT_ATTENTION || - (sense->sense_key == NOT_READY && (sense->asc == 4 || - sense->asc == 0x3a))) - return; - - printk("%s: error code: 0x%02x sense_key: 0x%02x asc: 0x%02x ascq: 0x%02x\n", - drive->name, - sense->error_code, sense->sense_key, - sense->asc, sense->ascq); -#endif /* not VERBOSE_IDE_CD_ERRORS */ -} - -static void cdrom_queue_request_sense(ide_drive_t *drive, - struct completion *wait, - struct request_sense *sense, - struct packet_command *failed_command) -{ - struct cdrom_info *info = drive->driver_data; - struct packet_command *pc = &info->request_sense_pc; - struct request *rq; - - if (sense == NULL) - sense = &info->sense_data; - - memset(pc, 0, sizeof(struct packet_command)); - pc->c[0] = GPCMD_REQUEST_SENSE; - pc->c[4] = pc->buflen = 18; - pc->buffer = (char *) sense; - pc->sense = (struct request_sense *) failed_command; - - /* stuff the sense request in front of our current request */ - rq = &info->request_sense_request; - ide_init_drive_cmd(rq); - rq->cmd = REQUEST_SENSE_COMMAND; - rq->buffer = (char *) pc; - rq->waiting = wait; - - (void) ide_do_drive_cmd(drive, rq, ide_preempt); -} - - -static void cdrom_end_request (int uptodate, ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - - if (rq->cmd == REQUEST_SENSE_COMMAND && uptodate) { - struct packet_command *pc = (struct packet_command *) rq->buffer; - cdrom_analyze_sense_data(drive, - (struct packet_command *) pc->sense, - (struct request_sense *) (pc->buffer - pc->c[4])); - } - if (rq->cmd == READ || rq->cmd == WRITE) - if (!rq->current_nr_sectors) - uptodate = 1; - - ide_end_request (uptodate, HWGROUP(drive)); -} - - -/* Returns 0 if the request should be continued. - Returns 1 if the request was ended. */ -static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive, - int good_stat, int *stat_ret) -{ - struct request *rq = HWGROUP(drive)->rq; - int stat, err, sense_key; - struct packet_command *pc; - - /* Check for errors. */ - stat = GET_STAT(); - *stat_ret = stat; - - if (OK_STAT (stat, good_stat, BAD_R_STAT)) - return 0; - - /* Get the IDE error register. */ - err = GET_ERR(); - sense_key = err >> 4; - - if (rq == NULL) { - printk("%s: missing rq in cdrom_decode_status\n", drive->name); - *startstop = ide_stopped; - return 1; - } - - if (rq->cmd == REQUEST_SENSE_COMMAND) { - /* We got an error trying to get sense info - from the drive (probably while trying - to recover from a former error). Just give up. */ - - pc = (struct packet_command *) rq->buffer; - pc->stat = 1; - cdrom_end_request (1, drive); - *startstop = ide_error (drive, "request sense failure", stat); - return 1; - - } else if (rq->cmd == PACKET_COMMAND) { - /* All other functions, except for READ. */ - struct completion *wait = NULL; - pc = (struct packet_command *) rq->buffer; - - /* Check for tray open. */ - if (sense_key == NOT_READY) { - cdrom_saw_media_change (drive); - } else if (sense_key == UNIT_ATTENTION) { - /* Check for media change. */ - cdrom_saw_media_change (drive); - /*printk("%s: media changed\n",drive->name);*/ - return 0; - } else if (!pc->quiet) { - /* Otherwise, print an error. */ - ide_dump_status(drive, "packet command error", stat); - } - - /* Set the error flag and complete the request. - Then, if we have a CHECK CONDITION status, - queue a request sense command. We must be careful, - though: we don't want the thread in - cdrom_queue_packet_command to wake up until - the request sense has completed. We do this - by transferring the semaphore from the packet - command request to the request sense request. */ - - if ((stat & ERR_STAT) != 0) { - // XXX SMH: if we get here we should retry ... hmmm -// printk("ide-cd: error (stat = 0x%x): will retry\n", stat); - wait = rq->waiting; - rq->waiting = NULL; - } - - pc->stat = 1; - cdrom_end_request (1, drive); - - if ((stat & ERR_STAT) != 0) - cdrom_queue_request_sense(drive, wait, pc->sense, pc); - } else { - /* Handle errors from READ and WRITE requests. */ - - if (sense_key == NOT_READY) { - /* Tray open. */ - cdrom_saw_media_change (drive); - - /* Fail the request. */ - printk ("%s: tray open\n", drive->name); - cdrom_end_request (0, drive); - } else if (sense_key == UNIT_ATTENTION) { - /* Media change. */ - cdrom_saw_media_change (drive); - - /* Arrange to retry the request. - But be sure to give up if we've retried - too many times. */ - if (++rq->errors > ERROR_MAX) - cdrom_end_request (0, drive); - } else if (sense_key == ILLEGAL_REQUEST || - sense_key == DATA_PROTECT) { - /* No point in retrying after an illegal - request or data protect error.*/ - ide_dump_status (drive, "command error", stat); - cdrom_end_request (0, drive); - } else if ((err & ~ABRT_ERR) != 0) { - /* Go to the default handler - for other errors. */ - *startstop = ide_error (drive, "cdrom_decode_status", stat); - return 1; - } else if ((++rq->errors > ERROR_MAX)) { - /* We've racked up too many retries. Abort. */ - cdrom_end_request (0, drive); - } - - /* If we got a CHECK_CONDITION status, - queue a request sense command. */ - if ((stat & ERR_STAT) != 0) - cdrom_queue_request_sense(drive, NULL, NULL, NULL); - } - - /* Retry, or handle the next request. */ - *startstop = ide_stopped; - return 1; -} - -static int cdrom_timer_expiry(ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - struct packet_command *pc = (struct packet_command *) rq->buffer; - unsigned long wait = 0; - - /* - * Some commands are *slow* and normally take a long time to - * complete. Usually we can use the ATAPI "disconnect" to bypass - * this, but not all commands/drives support that. Let - * ide_timer_expiry keep polling us for these. - */ - switch (pc->c[0]) { - case GPCMD_BLANK: - case GPCMD_FORMAT_UNIT: - case GPCMD_RESERVE_RZONE_TRACK: - wait = WAIT_CMD; - break; - default: - wait = 0; - break; - } - return wait; -} - -/* Set up the device registers for transferring a packet command on DEV, - expecting to later transfer XFERLEN bytes. HANDLER is the routine - which actually transfers the command to the drive. If this is a - drq_interrupt device, this routine will arrange for HANDLER to be - called when the interrupt from the drive arrives. Otherwise, HANDLER - will be called immediately after the drive is prepared for the transfer. */ - -static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, - int xferlen, - ide_handler_t *handler) -{ - ide_startstop_t startstop; - struct cdrom_info *info = drive->driver_data; - - /* Wait for the controller to be idle. */ - if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY)) - return startstop; - - if (info->dma) { - if (info->cmd == READ) { - info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive); - } else if (info->cmd == WRITE) { - info->dma = !HWIF(drive)->dmaproc(ide_dma_write, drive); - } else { - printk("ide-cd: DMA set, but not allowed\n"); - } - } - - /* Set up the controller registers. */ - OUT_BYTE (info->dma, IDE_FEATURE_REG); - OUT_BYTE (0, IDE_NSECTOR_REG); - OUT_BYTE (0, IDE_SECTOR_REG); - - OUT_BYTE (xferlen & 0xff, IDE_LCYL_REG); - OUT_BYTE (xferlen >> 8 , IDE_HCYL_REG); - if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl, IDE_CONTROL_REG); - - if (info->dma) - (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); - - if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { - ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry); - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ - return ide_started; - } else { - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ - return (*handler) (drive); - } -} - -/* Send a packet command to DRIVE described by CMD_BUF and CMD_LEN. - The device registers must have already been prepared - by cdrom_start_packet_command. - HANDLER is the interrupt handler to call when the command completes - or there's data ready. */ -/* - * changed 5 parameters to 3 for dvd-ram - * struct packet_command *pc; now packet_command_t *pc; - */ -static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, - struct packet_command *pc, - ide_handler_t *handler) -{ - unsigned char *cmd_buf = pc->c; - int cmd_len = sizeof(pc->c); - unsigned int timeout = pc->timeout; - ide_startstop_t startstop; - - if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { - /* Here we should have been called after receiving an interrupt - from the device. DRQ should how be set. */ - int stat_dum; - - /* Check for errors. */ - if (cdrom_decode_status (&startstop, drive, DRQ_STAT, &stat_dum)) - return startstop; - } else { - /* Otherwise, we must wait for DRQ to get set. */ - if (ide_wait_stat (&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) - return startstop; - } - - /* Arm the interrupt handler. */ - ide_set_handler (drive, handler, timeout, cdrom_timer_expiry); - - /* Send the command to the device. */ - atapi_output_bytes (drive, cmd_buf, cmd_len); - return ide_started; -} - -/**************************************************************************** - * Block read functions. - */ - -/* - * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector - * buffer. Once the first sector is added, any subsequent sectors are - * assumed to be continuous (until the buffer is cleared). For the first - * sector added, SECTOR is its sector number. (SECTOR is then ignored until - * the buffer is cleared.) - */ -static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector, - int sectors_to_transfer) -{ - struct cdrom_info *info = drive->driver_data; - - /* Number of sectors to read into the buffer. */ - int sectors_to_buffer = MIN (sectors_to_transfer, - (SECTOR_BUFFER_SIZE >> SECTOR_BITS) - - info->nsectors_buffered); - - char *dest, *dum; - - /* If we couldn't get a buffer, don't try to buffer anything... */ - if (info->buffer == NULL) - sectors_to_buffer = 0; - - /* If this is the first sector in the buffer, remember its number. */ - if (info->nsectors_buffered == 0) - info->sector_buffered = sector; - - /* Read the data into the buffer. */ - dest = info->buffer + info->nsectors_buffered * SECTOR_SIZE; - while (sectors_to_buffer > 0) { - atapi_input_bytes (drive, dest, SECTOR_SIZE); - --sectors_to_buffer; - --sectors_to_transfer; - ++info->nsectors_buffered; - dest += SECTOR_SIZE; - } - - /* Throw away any remaining data. */ - dum = kmalloc(SECTOR_SIZE, GFP_ATOMIC); - while (sectors_to_transfer > 0) { - atapi_input_bytes (drive, dum, SECTOR_SIZE); - --sectors_to_transfer; - } - kfree(dum); -} - -/* - * Check the contents of the interrupt reason register from the cdrom - * and attempt to recover if there are problems. Returns 0 if everything's - * ok; nonzero if the request has been terminated. - */ -static inline -int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) -{ - ireason &= 3; - if (ireason == 2) return 0; - - if (ireason == 0) { - /* Whoops... The drive is expecting to receive data from us! */ - printk ("%s: cdrom_read_intr: " - "Drive wants to transfer data the wrong way!\n", - drive->name); - - /* Throw some data at the drive so it doesn't hang - and quit this request. */ - while (len > 0) { - int dum = 0; - atapi_output_bytes (drive, &dum, sizeof (dum)); - len -= sizeof (dum); - } - } else if (ireason == 1) { - /* Some drives (ASUS) seem to tell us that status - * info is available. just get it and ignore. - */ - GET_STAT(); - return 0; - } else { - /* Drive wants a command packet, or invalid ireason... */ - printk ("%s: cdrom_read_intr: bad interrupt reason %d\n", - drive->name, ireason); - } - - cdrom_end_request (0, drive); - return -1; -} - -/* - * Interrupt routine. Called when a read request has completed. - */ -static ide_startstop_t cdrom_read_intr (ide_drive_t *drive) -{ - int stat; - int ireason, len, sectors_to_transfer, nskip; - struct cdrom_info *info = drive->driver_data; - int i, dma = info->dma, dma_error = 0; - ide_startstop_t startstop; - char *dum; - - struct request *rq = HWGROUP(drive)->rq; - - /* Check for errors. */ - if (dma) { - info->dma = 0; - if ((dma_error = HWIF(drive)->dmaproc(ide_dma_end, drive))) - HWIF(drive)->dmaproc(ide_dma_off, drive); - } - - if (cdrom_decode_status (&startstop, drive, 0, &stat)) - return startstop; - - if (dma) { - if (!dma_error) { - for (i = rq->nr_sectors; i > 0;) { - i -= rq->current_nr_sectors; - ide_end_request(1, HWGROUP(drive)); - } - return ide_stopped; - } else - return ide_error (drive, "dma error", stat); - } - - /* Read the interrupt reason and the transfer length. */ - ireason = IN_BYTE (IDE_NSECTOR_REG); - len = IN_BYTE (IDE_LCYL_REG) + 256 * IN_BYTE (IDE_HCYL_REG); - - /* If DRQ is clear, the command has completed. */ - if ((stat & DRQ_STAT) == 0) { - /* If we're not done filling the current buffer, complain. - Otherwise, complete the command normally. */ - if (rq->current_nr_sectors > 0) { - printk ("%s: cdrom_read_intr: data underrun (%ld blocks)\n", - drive->name, rq->current_nr_sectors); - cdrom_end_request (0, drive); - } else - cdrom_end_request (1, drive); - return ide_stopped; - } - - /* Check that the drive is expecting to do the same thing we are. */ - if (cdrom_read_check_ireason (drive, len, ireason)) - return ide_stopped; - - /* Assume that the drive will always provide data in multiples - of at least SECTOR_SIZE, as it gets hairy to keep track - of the transfers otherwise. */ - if ((len % SECTOR_SIZE) != 0) { - printk ("%s: cdrom_read_intr: Bad transfer size %d\n", - drive->name, len); - if (CDROM_CONFIG_FLAGS (drive)->limit_nframes) - printk (" This drive is not supported by this version of the driver\n"); - else { - printk (" Trying to limit transfer sizes\n"); - CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1; - } - cdrom_end_request (0, drive); - return ide_stopped; - } - - /* The number of sectors we need to read from the drive. */ - sectors_to_transfer = len / SECTOR_SIZE; - - /* First, figure out if we need to bit-bucket - any of the leading sectors. */ - nskip = MIN ((int)(rq->current_nr_sectors - (rq->bh->b_size >> SECTOR_BITS)), - sectors_to_transfer); - - if ( (dum = kmalloc(SECTOR_SIZE, GFP_ATOMIC)) == NULL ) - { - cdrom_end_request (0, drive); - return ide_stopped; - } - while (nskip > 0) { - /* We need to throw away a sector. */ - atapi_input_bytes (drive, dum, SECTOR_SIZE); - - --rq->current_nr_sectors; - --nskip; - --sectors_to_transfer; - } - kfree(dum); - - /* Now loop while we still have data to read from the drive. */ - while (sectors_to_transfer > 0) { - int this_transfer; - - /* If we've filled the present buffer but there's another - chained buffer after it, move on. */ - if (rq->current_nr_sectors == 0 && rq->nr_sectors) - cdrom_end_request (1, drive); - - /* If the buffers are full, cache the rest of the data in our - internal buffer. */ - if (rq->current_nr_sectors == 0) { - cdrom_buffer_sectors(drive, rq->sector, sectors_to_transfer); - sectors_to_transfer = 0; - } else { - /* Transfer data to the buffers. - Figure out how many sectors we can transfer - to the current buffer. */ - this_transfer = MIN (sectors_to_transfer, - rq->current_nr_sectors); - - /* Read this_transfer sectors - into the current buffer. */ - while (this_transfer > 0) { - atapi_input_bytes(drive, rq->buffer, SECTOR_SIZE); - rq->buffer += SECTOR_SIZE; - --rq->nr_sectors; - --rq->current_nr_sectors; - ++rq->sector; - --this_transfer; - --sectors_to_transfer; - } - } - } - - /* Done moving data! - Wait for another interrupt. */ - ide_set_handler(drive, &cdrom_read_intr, WAIT_CMD, NULL); - return ide_started; -} - -/* - * Try to satisfy some of the current read request from our cached data. - * Returns nonzero if the request has been completed, zero otherwise. - */ -static int cdrom_read_from_buffer (ide_drive_t *drive) -{ - struct cdrom_info *info = drive->driver_data; - struct request *rq = HWGROUP(drive)->rq; - - /* Can't do anything if there's no buffer. */ - if (info->buffer == NULL) return 0; - - /* Loop while this request needs data and the next block is present - in our cache. */ - while (rq->nr_sectors > 0 && - rq->sector >= info->sector_buffered && - rq->sector < info->sector_buffered + info->nsectors_buffered) { - if (rq->current_nr_sectors == 0) - cdrom_end_request (1, drive); - - memcpy (rq->buffer, - info->buffer + - (rq->sector - info->sector_buffered) * SECTOR_SIZE, - SECTOR_SIZE); - rq->buffer += SECTOR_SIZE; - --rq->current_nr_sectors; - --rq->nr_sectors; - ++rq->sector; - } - - /* If we've satisfied the current request, - terminate it successfully. */ - if (rq->nr_sectors == 0) { - cdrom_end_request (1, drive); - return -1; - } - - /* Move on to the next buffer if needed. */ - if (rq->current_nr_sectors == 0) - cdrom_end_request (1, drive); - - /* If this condition does not hold, then the kluge i use to - represent the number of sectors to skip at the start of a transfer - will fail. I think that this will never happen, but let's be - paranoid and check. */ - if (rq->current_nr_sectors < (rq->bh->b_size >> SECTOR_BITS) && - (rq->sector % SECTORS_PER_FRAME) != 0) { - printk ("%s: cdrom_read_from_buffer: buffer botch (%ld)\n", - drive->name, rq->sector); - cdrom_end_request (0, drive); - return -1; - } - - return 0; -} - -/* - * Routine to send a read packet command to the drive. - * This is usually called directly from cdrom_start_read. - * However, for drq_interrupt devices, it is called from an interrupt - * when the drive is ready to accept the command. - */ -static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive) -{ - struct packet_command pc; - struct request *rq = HWGROUP(drive)->rq; - int nsect, sector, nframes, frame, nskip; - - /* Number of sectors to transfer. */ - nsect = rq->nr_sectors; - - /* Starting sector. */ - sector = rq->sector; - - /* If the requested sector doesn't start on a cdrom block boundary, - we must adjust the start of the transfer so that it does, - and remember to skip the first few sectors. - If the CURRENT_NR_SECTORS field is larger than the size - of the buffer, it will mean that we're to skip a number - of sectors equal to the amount by which CURRENT_NR_SECTORS - is larger than the buffer size. */ - nskip = (sector % SECTORS_PER_FRAME); - if (nskip > 0) { - /* Sanity check... */ - if (rq->current_nr_sectors != (rq->bh->b_size >> SECTOR_BITS) && - (rq->sector % CD_FRAMESIZE != 0)) { - printk ("%s: cdrom_start_read_continuation: buffer botch (%lu)\n", - drive->name, rq->current_nr_sectors); - cdrom_end_request (0, drive); - return ide_stopped; - } - sector -= nskip; - nsect += nskip; - rq->current_nr_sectors += nskip; - } - - /* Convert from sectors to cdrom blocks, rounding up the transfer - length if needed. */ - nframes = (nsect + SECTORS_PER_FRAME-1) / SECTORS_PER_FRAME; - frame = sector / SECTORS_PER_FRAME; - - /* Largest number of frames was can transfer at once is 64k-1. For - some drives we need to limit this even more. */ - nframes = MIN (nframes, (CDROM_CONFIG_FLAGS (drive)->limit_nframes) ? - (65534 / CD_FRAMESIZE) : 65535); - - /* Set up the command */ - memset (&pc.c, 0, sizeof (pc.c)); - pc.c[0] = GPCMD_READ_10; - pc.c[7] = (nframes >> 8); - pc.c[8] = (nframes & 0xff); - put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]); - pc.timeout = WAIT_CMD; - - /* Send the command to the drive and return. */ - return cdrom_transfer_packet_command(drive, &pc, &cdrom_read_intr); -} - - -#define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */ -#define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */ -#define IDECD_SEEK_TIMEOUT WAIT_CMD /* 10 sec */ - -static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive) -{ - struct cdrom_info *info = drive->driver_data; - int stat; - static int retry = 10; - ide_startstop_t startstop; - - if (cdrom_decode_status (&startstop, drive, 0, &stat)) - return startstop; - CDROM_CONFIG_FLAGS(drive)->seeking = 1; - - if (retry && jiffies - info->start_seek > IDECD_SEEK_TIMER) { - if (--retry == 0) { - /* - * this condition is far too common, to bother - * users about it - */ -#if 0 - printk("%s: disabled DSC seek overlap\n", drive->name); -#endif - drive->dsc_overlap = 0; - } - } - return ide_stopped; -} - -static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive) -{ - struct packet_command pc; - struct request *rq = HWGROUP(drive)->rq; - int sector, frame, nskip; - - sector = rq->sector; - nskip = (sector % SECTORS_PER_FRAME); - if (nskip > 0) - sector -= nskip; - frame = sector / SECTORS_PER_FRAME; - - memset (&pc.c, 0, sizeof (pc.c)); - pc.c[0] = GPCMD_SEEK; - put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]); - - pc.timeout = WAIT_CMD; - return cdrom_transfer_packet_command(drive, &pc, &cdrom_seek_intr); -} - -static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block) -{ - struct cdrom_info *info = drive->driver_data; - - info->dma = 0; - info->cmd = 0; - info->start_seek = jiffies; - return cdrom_start_packet_command (drive, 0, cdrom_start_seek_continuation); -} - -static inline int cdrom_merge_requests(struct request *rq, struct request *nxt) -{ - int ret = 1; - - /* - * partitions not really working, but better check anyway... - */ - if (rq->cmd == nxt->cmd && rq->rq_dev == nxt->rq_dev) { - rq->nr_sectors += nxt->nr_sectors; - rq->hard_nr_sectors += nxt->nr_sectors; - rq->bhtail->b_reqnext = nxt->bh; - rq->bhtail = nxt->bhtail; - list_del(&nxt->queue); - blkdev_release_request(nxt); - ret = 0; - } - - return ret; -} - -/* - * the current request will always be the first one on the list - */ -static void cdrom_attempt_remerge(ide_drive_t *drive, struct request *rq) -{ - struct list_head *entry; - struct request *nxt; - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - - while (1) { - entry = rq->queue.next; - if (entry == &drive->queue.queue_head) - break; - - nxt = blkdev_entry_to_request(entry); - if (rq->sector + rq->nr_sectors != nxt->sector) - break; - else if (rq->nr_sectors + nxt->nr_sectors > SECTORS_MAX) - break; - - if (cdrom_merge_requests(rq, nxt)) - break; - } - - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* Fix up a possibly partially-processed request so that we can - start it over entirely, or even put it back on the request queue. */ -static void restore_request (struct request *rq) -{ - if (rq->buffer != rq->bh->b_data) { - int n = (rq->buffer - rq->bh->b_data) / SECTOR_SIZE; - rq->buffer = rq->bh->b_data; - rq->nr_sectors += n; - rq->sector -= n; - } - rq->current_nr_sectors = rq->bh->b_size >> SECTOR_BITS; - rq->hard_nr_sectors = rq->nr_sectors; - rq->hard_sector = rq->sector; -} - -/* - * Start a read request from the CD-ROM. - */ -static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block) -{ - struct cdrom_info *info = drive->driver_data; - struct request *rq = HWGROUP(drive)->rq; - int minor = MINOR (rq->rq_dev); - - /* If the request is relative to a partition, fix it up to refer to the - absolute address. */ - if (minor & PARTN_MASK) { - rq->sector = block; - minor &= ~PARTN_MASK; - rq->rq_dev = MKDEV(MAJOR(rq->rq_dev), minor); - } - - /* We may be retrying this request after an error. Fix up - any weirdness which might be present in the request packet. */ - restore_request(rq); - - /* Satisfy whatever we can of this request from our cached sector. */ - if (cdrom_read_from_buffer(drive)) - return ide_stopped; - - cdrom_attempt_remerge(drive, rq); - - /* Clear the local sector buffer. */ - info->nsectors_buffered = 0; - - /* use dma, if possible. */ - if (drive->using_dma && (rq->sector % SECTORS_PER_FRAME == 0) && - (rq->nr_sectors % SECTORS_PER_FRAME == 0)) - info->dma = 1; - else - info->dma = 0; - - info->cmd = READ; - /* Start sending the read request to the drive. */ - return cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation); -} - -/**************************************************************************** - * Execute all other packet commands. - */ - -/* Forward declarations. */ -static int cdrom_lockdoor(ide_drive_t *drive, int lockflag, - struct request_sense *sense); - -/* Interrupt routine for packet command completion. */ -static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) -{ - int ireason, len, stat, thislen; - struct request *rq = HWGROUP(drive)->rq; - struct packet_command *pc = (struct packet_command *)rq->buffer; - ide_startstop_t startstop; - - /* Check for errors. */ - if (cdrom_decode_status (&startstop, drive, 0, &stat)) - return startstop; - - /* Read the interrupt reason and the transfer length. */ - ireason = IN_BYTE (IDE_NSECTOR_REG); - len = IN_BYTE (IDE_LCYL_REG) + 256 * IN_BYTE (IDE_HCYL_REG); - - /* If DRQ is clear, the command has completed. - Complain if we still have data left to transfer. */ - if ((stat & DRQ_STAT) == 0) { - /* Some of the trailing request sense fields are optional, and - some drives don't send them. Sigh. */ - if (pc->c[0] == GPCMD_REQUEST_SENSE && - pc->buflen > 0 && - pc->buflen <= 5) { - while (pc->buflen > 0) { - *pc->buffer++ = 0; - --pc->buflen; - } - } - - if (pc->buflen == 0) - cdrom_end_request (1, drive); - else { - /* Comment this out, because this always happens - right after a reset occurs, and it is annoying to - always print expected stuff. */ - /* - printk ("%s: cdrom_pc_intr: data underrun %d\n", - drive->name, pc->buflen); - */ - pc->stat = 1; - cdrom_end_request (1, drive); - } - return ide_stopped; - } - - /* Figure out how much data to transfer. */ - thislen = pc->buflen; - if (thislen > len) thislen = len; - - /* The drive wants to be written to. */ - if ((ireason & 3) == 0) { - /* Transfer the data. */ - atapi_output_bytes (drive, pc->buffer, thislen); - - /* If we haven't moved enough data to satisfy the drive, - add some padding. */ - while (len > thislen) { - int dum = 0; - atapi_output_bytes (drive, &dum, sizeof (dum)); - len -= sizeof (dum); - } - - /* Keep count of how much data we've moved. */ - pc->buffer += thislen; - pc->buflen -= thislen; - } - - /* Same drill for reading. */ - else if ((ireason & 3) == 2) { - - /* Transfer the data. */ - atapi_input_bytes (drive, pc->buffer, thislen); - - /* If we haven't moved enough data to satisfy the drive, - add some padding. */ - while (len > thislen) { - int dum = 0; - atapi_input_bytes (drive, &dum, sizeof (dum)); - len -= sizeof (dum); - } - - /* Keep count of how much data we've moved. */ - pc->buffer += thislen; - pc->buflen -= thislen; - } else { - printk ("%s: cdrom_pc_intr: The drive " - "appears confused (ireason = 0x%2x)\n", - drive->name, ireason); - pc->stat = 1; - } - - /* Now we wait for another interrupt. */ - ide_set_handler (drive, &cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry); - return ide_started; -} - - -static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - struct packet_command *pc = (struct packet_command *)rq->buffer; - - if (!pc->timeout) - pc->timeout = WAIT_CMD; - - /* Send the command to the drive and return. */ - return cdrom_transfer_packet_command(drive, pc, &cdrom_pc_intr); -} - - -static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive) -{ - int len; - struct request *rq = HWGROUP(drive)->rq; - struct packet_command *pc = (struct packet_command *)rq->buffer; - struct cdrom_info *info = drive->driver_data; - - info->dma = 0; - info->cmd = 0; - pc->stat = 0; - len = pc->buflen; - - /* Start sending the command to the drive. */ - return cdrom_start_packet_command (drive, len, cdrom_do_pc_continuation); -} - - -/* Sleep for TIME jiffies. - Not to be called from an interrupt handler. */ -static -void cdrom_sleep (int time) -{ - int sleep = time; - - do { - set_current_state(TASK_INTERRUPTIBLE); - sleep = schedule_timeout(sleep); - } while (sleep); -} - -static -int cdrom_queue_packet_command(ide_drive_t *drive, struct packet_command *pc) -{ - struct request_sense sense; - struct request req; - int retries = 10; - - if (pc->sense == NULL) - pc->sense = &sense; - - /* Start of retry loop. */ - do { - ide_init_drive_cmd (&req); - req.cmd = PACKET_COMMAND; - req.buffer = (char *)pc; - if (ide_do_drive_cmd (drive, &req, ide_wait)) { - printk("%s: do_drive_cmd returned stat=%02x,err=%02x\n", - drive->name, req.buffer[0], req.buffer[1]); - /* FIXME: we should probably abort/retry or something */ - } - if (pc->stat != 0) { - /* The request failed. Retry if it was due to a unit - attention status - (usually means media was changed). */ - struct request_sense *reqbuf = pc->sense; - - if (reqbuf->sense_key == UNIT_ATTENTION) - cdrom_saw_media_change (drive); - else if (reqbuf->sense_key == NOT_READY && - reqbuf->asc == 4 && reqbuf->ascq != 4) { - /* The drive is in the process of loading - a disk. Retry, but wait a little to give - the drive time to complete the load. */ - cdrom_sleep(2 * HZ); - } else { - /* Otherwise, don't retry. */ - retries = 0; - } - --retries; - } - - /* End of retry loop. */ - } while (pc->stat != 0 && retries >= 0); - - /* Return an error if the command failed. */ - return pc->stat ? -EIO : 0; -} - -/* - * Write handling - */ -static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason) -{ - /* Two notes about IDE interrupt reason here - 0 means that - * the drive wants to receive data from us, 2 means that - * the drive is expecting data from us. - */ - ireason &= 3; - - if (ireason == 2) { - /* Whoops... The drive wants to send data. */ - printk("%s: cdrom_write_intr: wrong transfer direction!\n", - drive->name); - - /* Throw some data at the drive so it doesn't hang - and quit this request. */ - while (len > 0) { - int dum = 0; - atapi_output_bytes(drive, &dum, sizeof(dum)); - len -= sizeof(dum); - } - } else { - /* Drive wants a command packet, or invalid ireason... */ - printk("%s: cdrom_write_intr: bad interrupt reason %d\n", - drive->name, ireason); - } - - cdrom_end_request(0, drive); - return 1; -} - -static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) -{ - int stat, ireason, len, sectors_to_transfer, uptodate; - struct cdrom_info *info = drive->driver_data; - int i, dma_error = 0, dma = info->dma; - ide_startstop_t startstop; - - struct request *rq = HWGROUP(drive)->rq; - - /* Check for errors. */ - if (dma) { - info->dma = 0; - if ((dma_error = HWIF(drive)->dmaproc(ide_dma_end, drive))) { - printk("ide-cd: write dma error\n"); - HWIF(drive)->dmaproc(ide_dma_off, drive); - } - } - - if (cdrom_decode_status(&startstop, drive, 0, &stat)) { - printk("ide-cd: write_intr decode_status bad\n"); - return startstop; - } - - /* - * using dma, transfer is complete now - */ - if (dma) { - if (dma_error) - return ide_error(drive, "dma error", stat); - - rq = HWGROUP(drive)->rq; - for (i = rq->nr_sectors; i > 0;) { - i -= rq->current_nr_sectors; - ide_end_request(1, HWGROUP(drive)); - } - return ide_stopped; - } - - /* Read the interrupt reason and the transfer length. */ - ireason = IN_BYTE(IDE_NSECTOR_REG); - len = IN_BYTE(IDE_LCYL_REG) + 256 * IN_BYTE(IDE_HCYL_REG); - - /* If DRQ is clear, the command has completed. */ - if ((stat & DRQ_STAT) == 0) { - /* If we're not done writing, complain. - * Otherwise, complete the command normally. - */ - uptodate = 1; - if (rq->current_nr_sectors > 0) { - printk("%s: write_intr: data underrun (%ld blocks)\n", - drive->name, rq->current_nr_sectors); - uptodate = 0; - } - cdrom_end_request(uptodate, drive); - return ide_stopped; - } - - /* Check that the drive is expecting to do the same thing we are. */ - if (ireason & 3) - if (cdrom_write_check_ireason(drive, len, ireason)) - return ide_stopped; - - sectors_to_transfer = len / SECTOR_SIZE; - - /* - * now loop and write out the data - */ - while (sectors_to_transfer > 0) { - int this_transfer; - - if (!rq->current_nr_sectors) { - printk("ide-cd: write_intr: oops\n"); - break; - } - - /* - * Figure out how many sectors we can transfer - */ - this_transfer = MIN(sectors_to_transfer,rq->current_nr_sectors); - - while (this_transfer > 0) { - atapi_output_bytes(drive, rq->buffer, SECTOR_SIZE); - rq->buffer += SECTOR_SIZE; - --rq->nr_sectors; - --rq->current_nr_sectors; - ++rq->sector; - --this_transfer; - --sectors_to_transfer; - } - - /* - * current buffer complete, move on - */ - if (rq->current_nr_sectors == 0 && rq->nr_sectors) - cdrom_end_request (1, drive); - } - - /* re-arm handler */ - ide_set_handler(drive, &cdrom_write_intr, 5 * WAIT_CMD, NULL); - return ide_started; -} - -static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive) -{ - struct packet_command pc; /* packet_command_t pc; */ - struct request *rq = HWGROUP(drive)->rq; - unsigned nframes, frame; - - nframes = rq->nr_sectors >> 2; - frame = rq->sector >> 2; - - memset(&pc.c, 0, sizeof(pc.c)); - /* - * we might as well use WRITE_12, but none of the device I have - * support the streaming feature anyway, so who cares. - */ - pc.c[0] = GPCMD_WRITE_10; -#if 0 /* the immediate bit */ - pc.c[1] = 1 << 3; -#endif - pc.c[7] = (nframes >> 8) & 0xff; - pc.c[8] = nframes & 0xff; - put_unaligned(cpu_to_be32(frame), (unsigned int *)&pc.c[2]); - pc.timeout = 2 * WAIT_CMD; - - return cdrom_transfer_packet_command(drive, &pc, cdrom_write_intr); -} - -static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq) -{ - struct cdrom_info *info = drive->driver_data; - - /* - * writes *must* be 2kB frame aligned - */ - if ((rq->nr_sectors & 3) || (rq->sector & 3)) { - cdrom_end_request(0, drive); - return ide_stopped; - } - - /* - * for dvd-ram and such media, it's a really big deal to get - * big writes all the time. so scour the queue and attempt to - * remerge requests, often the plugging will not have had time - * to do this properly - */ - cdrom_attempt_remerge(drive, rq); - - info->nsectors_buffered = 0; - - /* use dma, if possible. we don't need to check more, since we - * know that the transfer is always (at least!) 2KB aligned */ - info->dma = drive->using_dma ? 1 : 0; - info->cmd = WRITE; - - /* Start sending the read request to the drive. */ - return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont); -} - -/**************************************************************************** - * cdrom driver request routine. - */ -static ide_startstop_t -ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block) -{ - ide_startstop_t action; - struct cdrom_info *info = drive->driver_data; - - switch (rq->cmd) { - case WRITE: - case READ: { - if (CDROM_CONFIG_FLAGS(drive)->seeking) { - unsigned long elpased = jiffies - info->start_seek; - int stat = GET_STAT(); - - if ((stat & SEEK_STAT) != SEEK_STAT) { - if (elpased < IDECD_SEEK_TIMEOUT) { - ide_stall_queue(drive, IDECD_SEEK_TIMER); - return ide_stopped; - } - printk ("%s: DSC timeout\n", drive->name); - } - CDROM_CONFIG_FLAGS(drive)->seeking = 0; - } - if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) - action = cdrom_start_seek (drive, block); - else { - if (rq->cmd == READ) - action = cdrom_start_read(drive, block); - else - action = cdrom_start_write(drive, rq); - } - info->last_block = block; - return action; - } - - case PACKET_COMMAND: - case REQUEST_SENSE_COMMAND: { - return cdrom_do_packet_command(drive); - } - - case RESET_DRIVE_COMMAND: { - cdrom_end_request(1, drive); - return ide_do_reset(drive); - } - - default: { - printk("ide-cd: bad cmd %d\n", rq->cmd); - cdrom_end_request(0, drive); - return ide_stopped; - } - } -} - - - -/**************************************************************************** - * Ioctl handling. - * - * Routines which queue packet commands take as a final argument a pointer - * to a request_sense struct. If execution of the command results - * in an error with a CHECK CONDITION status, this structure will be filled - * with the results of the subsequent request sense command. The pointer - * can also be NULL, in which case no sense information is returned. - */ - -#if ! STANDARD_ATAPI -static inline -int bin2bcd (int x) -{ - return (x%10) | ((x/10) << 4); -} - - -static inline -int bcd2bin (int x) -{ - return (x >> 4) * 10 + (x & 0x0f); -} - -static -void msf_from_bcd (struct atapi_msf *msf) -{ - msf->minute = bcd2bin (msf->minute); - msf->second = bcd2bin (msf->second); - msf->frame = bcd2bin (msf->frame); -} - -#endif /* not STANDARD_ATAPI */ - - -static inline -void lba_to_msf (int lba, byte *m, byte *s, byte *f) -{ - lba += CD_MSF_OFFSET; - lba &= 0xffffff; /* negative lbas use only 24 bits */ - *m = lba / (CD_SECS * CD_FRAMES); - lba %= (CD_SECS * CD_FRAMES); - *s = lba / CD_FRAMES; - *f = lba % CD_FRAMES; -} - - -static inline -int msf_to_lba (byte m, byte s, byte f) -{ - return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET; -} - -static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense) -{ - struct packet_command pc; - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *cdi = &info->devinfo; - - memset(&pc, 0, sizeof(pc)); - pc.sense = sense; - - pc.c[0] = GPCMD_TEST_UNIT_READY; - -#if ! STANDARD_ATAPI - /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to - switch CDs instead of supporting the LOAD_UNLOAD opcode */ - - pc.c[7] = cdi->sanyo_slot % 3; -#endif /* not STANDARD_ATAPI */ - - return cdrom_queue_packet_command(drive, &pc); -} - - -/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */ -static int -cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense) -{ - struct request_sense my_sense; - struct packet_command pc; - int stat; - - if (sense == NULL) - sense = &my_sense; - - /* If the drive cannot lock the door, just pretend. */ - if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) { - stat = 0; - } else { - memset(&pc, 0, sizeof(pc)); - pc.sense = sense; - pc.c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; - pc.c[4] = lockflag ? 1 : 0; - stat = cdrom_queue_packet_command (drive, &pc); - } - - /* If we got an illegal field error, the drive - probably cannot lock the door. */ - if (stat != 0 && - sense->sense_key == ILLEGAL_REQUEST && - (sense->asc == 0x24 || sense->asc == 0x20)) { - printk ("%s: door locking not supported\n", - drive->name); - CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1; - stat = 0; - } - - /* no medium, that's alright. */ - if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a) - stat = 0; - - if (stat == 0) - CDROM_STATE_FLAGS (drive)->door_locked = lockflag; - - return stat; -} - - -/* Eject the disk if EJECTFLAG is 0. - If EJECTFLAG is 1, try to reload the disk. */ -static int cdrom_eject(ide_drive_t *drive, int ejectflag, - struct request_sense *sense) -{ - struct packet_command pc; - - if (CDROM_CONFIG_FLAGS(drive)->no_eject && !ejectflag) - return -EDRIVE_CANT_DO_THIS; - - /* reload fails on some drives, if the tray is locked */ - if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag) - return 0; - - memset(&pc, 0, sizeof (pc)); - pc.sense = sense; - - pc.c[0] = GPCMD_START_STOP_UNIT; - pc.c[4] = 0x02 + (ejectflag != 0); - return cdrom_queue_packet_command (drive, &pc); -} - -static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, - struct request_sense *sense) -{ - struct { - __u32 lba; - __u32 blocklen; - } capbuf; - - int stat; - struct packet_command pc; - - memset(&pc, 0, sizeof(pc)); - pc.sense = sense; - - pc.c[0] = GPCMD_READ_CDVD_CAPACITY; - pc.buffer = (char *)&capbuf; - pc.buflen = sizeof(capbuf); - - stat = cdrom_queue_packet_command(drive, &pc); - if (stat == 0) - *capacity = 1 + be32_to_cpu(capbuf.lba); - - return stat; -} - -static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag, - int format, char *buf, int buflen, - struct request_sense *sense) -{ - struct packet_command pc; - - memset(&pc, 0, sizeof(pc)); - pc.sense = sense; - - pc.buffer = buf; - pc.buflen = buflen; - pc.quiet = 1; - pc.c[0] = GPCMD_READ_TOC_PMA_ATIP; - pc.c[6] = trackno; - pc.c[7] = (buflen >> 8); - pc.c[8] = (buflen & 0xff); - pc.c[9] = (format << 6); - - if (msf_flag) - pc.c[1] = 2; - - return cdrom_queue_packet_command (drive, &pc); -} - - -/* Try to read the entire TOC for the disk into our internal buffer. */ -static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) -{ - int minor, stat, ntracks, i; - kdev_t dev; - struct cdrom_info *info = drive->driver_data; - struct atapi_toc *toc = info->toc; - struct { - struct atapi_toc_header hdr; - struct atapi_toc_entry ent; - } ms_tmp; - - if (toc == NULL) { - /* Try to allocate space. */ - toc = (struct atapi_toc *) kmalloc (sizeof (struct atapi_toc), - GFP_KERNEL); - info->toc = toc; - if (toc == NULL) { - printk ("%s: No cdrom TOC buffer!\n", drive->name); - return -ENOMEM; - } - } - - /* Check to see if the existing data is still valid. - If it is, just return. */ - (void) cdrom_check_status(drive, sense); - - if (CDROM_STATE_FLAGS(drive)->toc_valid) - return 0; - - /* First read just the header, so we know how long the TOC is. */ - stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr, - sizeof(struct atapi_toc_header), sense); - if (stat) return stat; - -#if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) { - toc->hdr.first_track = bcd2bin (toc->hdr.first_track); - toc->hdr.last_track = bcd2bin (toc->hdr.last_track); - } -#endif /* not STANDARD_ATAPI */ - - ntracks = toc->hdr.last_track - toc->hdr.first_track + 1; - if (ntracks <= 0) - return -EIO; - if (ntracks > MAX_TRACKS) - ntracks = MAX_TRACKS; - - /* Now read the whole schmeer. */ - stat = cdrom_read_tocentry(drive, toc->hdr.first_track, 1, 0, - (char *)&toc->hdr, - sizeof(struct atapi_toc_header) + - (ntracks + 1) * - sizeof(struct atapi_toc_entry), sense); - - if (stat && toc->hdr.first_track > 1) { - /* Cds with CDI tracks only don't have any TOC entries, - despite of this the returned values are - first_track == last_track = number of CDI tracks + 1, - so that this case is indistinguishable from the same - layout plus an additional audio track. - If we get an error for the regular case, we assume - a CDI without additional audio tracks. In this case - the readable TOC is empty (CDI tracks are not included) - and only holds the Leadout entry. Heiko Eißfeldt */ - ntracks = 0; - stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0, - (char *)&toc->hdr, - sizeof(struct atapi_toc_header) + - (ntracks + 1) * - sizeof(struct atapi_toc_entry), - sense); - if (stat) { - return stat; - } -#if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) { - toc->hdr.first_track = bin2bcd(CDROM_LEADOUT); - toc->hdr.last_track = bin2bcd(CDROM_LEADOUT); - } else -#endif /* not STANDARD_ATAPI */ - { - toc->hdr.first_track = CDROM_LEADOUT; - toc->hdr.last_track = CDROM_LEADOUT; - } - } - - if (stat) - return stat; - - toc->hdr.toc_length = ntohs (toc->hdr.toc_length); - -#if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) { - toc->hdr.first_track = bcd2bin (toc->hdr.first_track); - toc->hdr.last_track = bcd2bin (toc->hdr.last_track); - } -#endif /* not STANDARD_ATAPI */ - - for (i=0; i<=ntracks; i++) { -#if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd) { - if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) - toc->ent[i].track = bcd2bin (toc->ent[i].track); - msf_from_bcd (&toc->ent[i].addr.msf); - } -#endif /* not STANDARD_ATAPI */ - toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute, - toc->ent[i].addr.msf.second, - toc->ent[i].addr.msf.frame); - } - - /* Read the multisession information. */ - if (toc->hdr.first_track != CDROM_LEADOUT) { - /* Read the multisession information. */ - stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp, - sizeof(ms_tmp), sense); - if (stat) return stat; - } else { - ms_tmp.ent.addr.msf.minute = 0; - ms_tmp.ent.addr.msf.second = 2; - ms_tmp.ent.addr.msf.frame = 0; - ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT; - } - -#if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd) - msf_from_bcd (&ms_tmp.ent.addr.msf); -#endif /* not STANDARD_ATAPI */ - - toc->last_session_lba = msf_to_lba (ms_tmp.ent.addr.msf.minute, - ms_tmp.ent.addr.msf.second, - ms_tmp.ent.addr.msf.frame); - - toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track); - - /* Now try to get the total cdrom capacity. */ - minor = (drive->select.b.unit) << PARTN_BITS; - dev = MKDEV(HWIF(drive)->major, minor); - stat = cdrom_get_last_written(dev, &toc->capacity); - if (stat) - stat = cdrom_read_capacity(drive, &toc->capacity, sense); - if (stat) - toc->capacity = 0x1fffff; - - HWIF(drive)->gd->sizes[drive->select.b.unit << PARTN_BITS] = (toc->capacity * SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9); - drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME; - - /* Remember that we've read this stuff. */ - CDROM_STATE_FLAGS (drive)->toc_valid = 1; - - return 0; -} - - -static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf, - int buflen, struct request_sense *sense) -{ - struct packet_command pc; - - memset(&pc, 0, sizeof(pc)); - pc.sense = sense; - - pc.buffer = buf; - pc.buflen = buflen; - pc.c[0] = GPCMD_READ_SUBCHANNEL; - pc.c[1] = 2; /* MSF addressing */ - pc.c[2] = 0x40; /* request subQ data */ - pc.c[3] = format; - pc.c[7] = (buflen >> 8); - pc.c[8] = (buflen & 0xff); - return cdrom_queue_packet_command(drive, &pc); -} - -/* ATAPI cdrom drives are free to select the speed you request or any slower - rate :-( Requesting too fast a speed will _not_ produce an error. */ -static int cdrom_select_speed(ide_drive_t *drive, int speed, - struct request_sense *sense) -{ - struct packet_command pc; - memset(&pc, 0, sizeof(pc)); - pc.sense = sense; - - if (speed == 0) - speed = 0xffff; /* set to max */ - else - speed *= 177; /* Nx to kbytes/s */ - - pc.c[0] = GPCMD_SET_SPEED; - /* Read Drive speed in kbytes/second MSB */ - pc.c[2] = (speed >> 8) & 0xff; - /* Read Drive speed in kbytes/second LSB */ - pc.c[3] = speed & 0xff; - if (CDROM_CONFIG_FLAGS(drive)->cd_r || - CDROM_CONFIG_FLAGS(drive)->cd_rw || - CDROM_CONFIG_FLAGS(drive)->dvd_r) { - /* Write Drive speed in kbytes/second MSB */ - pc.c[4] = (speed >> 8) & 0xff; - /* Write Drive speed in kbytes/second LSB */ - pc.c[5] = speed & 0xff; - } - - return cdrom_queue_packet_command(drive, &pc); -} - -static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end) -{ - struct request_sense sense; - struct packet_command pc; - - memset(&pc, 0, sizeof (pc)); - pc.sense = &sense; - - pc.c[0] = GPCMD_PLAY_AUDIO_MSF; - lba_to_msf(lba_start, &pc.c[3], &pc.c[4], &pc.c[5]); - lba_to_msf(lba_end-1, &pc.c[6], &pc.c[7], &pc.c[8]); - - return cdrom_queue_packet_command(drive, &pc); -} - -static int cdrom_get_toc_entry(ide_drive_t *drive, int track, - struct atapi_toc_entry **ent) -{ - struct cdrom_info *info = drive->driver_data; - struct atapi_toc *toc = info->toc; - int ntracks; - - /* - * don't serve cached data, if the toc isn't valid - */ - if (!CDROM_STATE_FLAGS(drive)->toc_valid) - return -EINVAL; - - /* Check validity of requested track number. */ - ntracks = toc->hdr.last_track - toc->hdr.first_track + 1; - if (toc->hdr.first_track == CDROM_LEADOUT) ntracks = 0; - if (track == CDROM_LEADOUT) - *ent = &toc->ent[ntracks]; - else if (track < toc->hdr.first_track || - track > toc->hdr.last_track) - return -EINVAL; - else - *ent = &toc->ent[track - toc->hdr.first_track]; - - return 0; -} - -/* the generic packet interface to cdrom.c */ -static int ide_cdrom_packet(struct cdrom_device_info *cdi, - struct cdrom_generic_command *cgc) -{ - struct packet_command pc; - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - - if (cgc->timeout <= 0) - cgc->timeout = WAIT_CMD; - - /* here we queue the commands from the uniform CD-ROM - layer. the packet must be complete, as we do not - touch it at all. */ - memset(&pc, 0, sizeof(pc)); - memcpy(pc.c, cgc->cmd, CDROM_PACKET_SIZE); - pc.buffer = cgc->buffer; - pc.buflen = cgc->buflen; - pc.quiet = cgc->quiet; - pc.timeout = cgc->timeout; - pc.sense = cgc->sense; - return cgc->stat = cdrom_queue_packet_command(drive, &pc); -} - -static -int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi, - unsigned int cmd, unsigned long arg) -{ - struct cdrom_generic_command cgc; - char buffer[16]; - int stat; - - init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN); - - /* These will be moved into the Uniform layer shortly... */ - switch (cmd) { - case CDROMSETSPINDOWN: { - char spindown; - - if (copy_from_user(&spindown, (void *) arg, sizeof(char))) - return -EFAULT; - - if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0))) - return stat; - - buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f); - - return cdrom_mode_select(cdi, &cgc); - } - - case CDROMGETSPINDOWN: { - char spindown; - - if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0))) - return stat; - - spindown = buffer[11] & 0x0f; - - if (copy_to_user((void *) arg, &spindown, sizeof (char))) - return -EFAULT; - - return 0; - } - - default: - return -EINVAL; - } - -} - -static -int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi, - unsigned int cmd, void *arg) - -{ - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - struct cdrom_info *info = drive->driver_data; - int stat; - - switch (cmd) { - /* - * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since - * atapi doesn't support it - */ - case CDROMPLAYTRKIND: { - unsigned long lba_start, lba_end; - struct cdrom_ti *ti = (struct cdrom_ti *)arg; - struct atapi_toc_entry *first_toc, *last_toc; - - stat = cdrom_get_toc_entry(drive, ti->cdti_trk0, &first_toc); - if (stat) - return stat; - - stat = cdrom_get_toc_entry(drive, ti->cdti_trk1, &last_toc); - if (stat) - return stat; - - if (ti->cdti_trk1 != CDROM_LEADOUT) - ++last_toc; - lba_start = first_toc->addr.lba; - lba_end = last_toc->addr.lba; - - if (lba_end <= lba_start) - return -EINVAL; - - return cdrom_play_audio(drive, lba_start, lba_end); - } - - case CDROMREADTOCHDR: { - struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg; - struct atapi_toc *toc; - - /* Make sure our saved TOC is valid. */ - stat = cdrom_read_toc(drive, NULL); - if (stat) return stat; - - toc = info->toc; - tochdr->cdth_trk0 = toc->hdr.first_track; - tochdr->cdth_trk1 = toc->hdr.last_track; - - return 0; - } - - case CDROMREADTOCENTRY: { - struct cdrom_tocentry *tocentry = (struct cdrom_tocentry*) arg; - struct atapi_toc_entry *toce; - - stat = cdrom_get_toc_entry (drive, tocentry->cdte_track, &toce); - if (stat) return stat; - - tocentry->cdte_ctrl = toce->control; - tocentry->cdte_adr = toce->adr; - if (tocentry->cdte_format == CDROM_MSF) { - lba_to_msf (toce->addr.lba, - &tocentry->cdte_addr.msf.minute, - &tocentry->cdte_addr.msf.second, - &tocentry->cdte_addr.msf.frame); - } else - tocentry->cdte_addr.lba = toce->addr.lba; - - return 0; - } - - default: - return -EINVAL; - } -} - -static -int ide_cdrom_reset (struct cdrom_device_info *cdi) -{ - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - struct request_sense sense; - struct request req; - int ret; - - ide_init_drive_cmd (&req); - req.cmd = RESET_DRIVE_COMMAND; - ret = ide_do_drive_cmd(drive, &req, ide_wait); - - /* - * A reset will unlock the door. If it was previously locked, - * lock it again. - */ - if (CDROM_STATE_FLAGS(drive)->door_locked) - (void) cdrom_lockdoor(drive, 1, &sense); - - return ret; -} - - -static -int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position) -{ - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - struct request_sense sense; - - if (position) { - int stat = cdrom_lockdoor(drive, 0, &sense); - if (stat) return stat; - } - - return cdrom_eject(drive, !position, &sense); -} - -static -int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock) -{ - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - return cdrom_lockdoor(drive, lock, NULL); -} - -static -int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed) -{ - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - struct request_sense sense; - int stat; - - if ((stat = cdrom_select_speed (drive, speed, &sense)) < 0) - return stat; - - cdi->speed = CDROM_STATE_FLAGS (drive)->current_speed; - return 0; -} - -static -int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr) -{ - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - - if (slot_nr == CDSL_CURRENT) { - struct request_sense sense; - int stat = cdrom_check_status(drive, &sense); - if (stat == 0 || sense.sense_key == UNIT_ATTENTION) - return CDS_DISC_OK; - - if (sense.sense_key == NOT_READY && sense.asc == 0x04 && - sense.ascq == 0x04) - return CDS_DISC_OK; - - - /* - * If not using Mt Fuji extended media tray reports, - * just return TRAY_OPEN since ATAPI doesn't provide - * any other way to detect this... - */ - if (sense.sense_key == NOT_READY) { - if (sense.asc == 0x3a && sense.ascq == 1) - return CDS_NO_DISC; - else - return CDS_TRAY_OPEN; - } - - return CDS_DRIVE_NOT_READY; - } - return -EINVAL; -} - -static -int ide_cdrom_get_last_session (struct cdrom_device_info *cdi, - struct cdrom_multisession *ms_info) -{ - struct atapi_toc *toc; - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - struct cdrom_info *info = drive->driver_data; - struct request_sense sense; - int ret; - - if (!CDROM_STATE_FLAGS(drive)->toc_valid || info->toc == NULL) - if ((ret = cdrom_read_toc(drive, &sense))) - return ret; - - toc = info->toc; - ms_info->addr.lba = toc->last_session_lba; - ms_info->xa_flag = toc->xa_flag; - - return 0; -} - -static -int ide_cdrom_get_mcn (struct cdrom_device_info *cdi, - struct cdrom_mcn *mcn_info) -{ - int stat; - char mcnbuf[24]; - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - -/* get MCN */ - if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf), NULL))) - return stat; - - memcpy (mcn_info->medium_catalog_number, mcnbuf+9, - sizeof (mcn_info->medium_catalog_number)-1); - mcn_info->medium_catalog_number[sizeof (mcn_info->medium_catalog_number)-1] - = '\0'; - - return 0; -} - - - -/**************************************************************************** - * Other driver requests (open, close, check media change). - */ - -static -int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi, - int slot_nr) -{ - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - int retval; - - if (slot_nr == CDSL_CURRENT) { - (void) cdrom_check_status(drive, NULL); - retval = CDROM_STATE_FLAGS (drive)->media_changed; - CDROM_STATE_FLAGS (drive)->media_changed = 0; - return retval; - } else { - return -EINVAL; - } -} - - -static -int ide_cdrom_open_real (struct cdrom_device_info *cdi, int purpose) -{ - return 0; -} - - -/* - * Close down the device. Invalidate all cached blocks. - */ - -static -void ide_cdrom_release_real (struct cdrom_device_info *cdi) -{ -} - - - -/**************************************************************************** - * Device initialization. - */ -static struct cdrom_device_ops ide_cdrom_dops = { - open: ide_cdrom_open_real, - release: ide_cdrom_release_real, - drive_status: ide_cdrom_drive_status, - media_changed: ide_cdrom_check_media_change_real, - tray_move: ide_cdrom_tray_move, - lock_door: ide_cdrom_lock_door, - select_speed: ide_cdrom_select_speed, - get_last_session: ide_cdrom_get_last_session, - get_mcn: ide_cdrom_get_mcn, - reset: ide_cdrom_reset, - audio_ioctl: ide_cdrom_audio_ioctl, - dev_ioctl: ide_cdrom_dev_ioctl, - capability: CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | - CDC_SELECT_SPEED | CDC_SELECT_DISC | - CDC_MULTI_SESSION | CDC_MCN | - CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | - CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_CD_R | - CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM | - CDC_GENERIC_PACKET, - generic_packet: ide_cdrom_packet, -}; - -static int ide_cdrom_register (ide_drive_t *drive, int nslots) -{ - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *devinfo = &info->devinfo; - int minor = (drive->select.b.unit) << PARTN_BITS; - - devinfo->dev = MKDEV (HWIF(drive)->major, minor); - devinfo->ops = &ide_cdrom_dops; - devinfo->mask = 0; - *(int *)&devinfo->speed = CDROM_STATE_FLAGS (drive)->current_speed; - *(int *)&devinfo->capacity = nslots; - devinfo->handle = (void *) drive; - strcpy(devinfo->name, drive->name); - - /* set capability mask to match the probe. */ - if (!CDROM_CONFIG_FLAGS (drive)->cd_r) - devinfo->mask |= CDC_CD_R; - if (!CDROM_CONFIG_FLAGS (drive)->cd_rw) - devinfo->mask |= CDC_CD_RW; - if (!CDROM_CONFIG_FLAGS (drive)->dvd) - devinfo->mask |= CDC_DVD; - if (!CDROM_CONFIG_FLAGS (drive)->dvd_r) - devinfo->mask |= CDC_DVD_R; - if (!CDROM_CONFIG_FLAGS (drive)->dvd_ram) - devinfo->mask |= CDC_DVD_RAM; - if (!CDROM_CONFIG_FLAGS (drive)->is_changer) - devinfo->mask |= CDC_SELECT_DISC; - if (!CDROM_CONFIG_FLAGS (drive)->audio_play) - devinfo->mask |= CDC_PLAY_AUDIO; - if (!CDROM_CONFIG_FLAGS (drive)->close_tray) - devinfo->mask |= CDC_CLOSE_TRAY; - -#if 0 - devinfo->de = devfs_register(drive->de, "cd", DEVFS_FL_DEFAULT, - HWIF(drive)->major, minor, - S_IFBLK | S_IRUGO | S_IWUGO, - ide_fops, NULL); -#endif - - return register_cdrom(devinfo); -} - -static -int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_page *cap) -{ - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *cdi = &info->devinfo; - struct cdrom_generic_command cgc; - int stat, attempts = 3, size = sizeof(*cap); - - /* - * ACER50 (and others?) require the full spec length mode sense - * page capabilities size, but older drives break. - */ - if (drive->id) { - if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") || - !strcmp(drive->id->model, "WPI CDS-32X"))) - size -= sizeof(cap->pad); - } - - /* we have to cheat a little here. the packet will eventually - * be queued with ide_cdrom_packet(), which extracts the - * drive from cdi->handle. Since this device hasn't been - * registered with the Uniform layer yet, it can't do this. - * Same goes for cdi->ops. - */ - cdi->handle = (ide_drive_t *) drive; - cdi->ops = &ide_cdrom_dops; - init_cdrom_command(&cgc, cap, size, CGC_DATA_UNKNOWN); - do { /* we seem to get stat=0x01,err=0x00 the first time (??) */ - stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0); - if (!stat) - break; - } while (--attempts); - return stat; -} - -static -int ide_cdrom_probe_capabilities (ide_drive_t *drive) -{ - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *cdi = &info->devinfo; - struct atapi_capabilities_page cap; - int nslots = 1; - - if (CDROM_CONFIG_FLAGS (drive)->nec260) { - CDROM_CONFIG_FLAGS (drive)->no_eject = 0; - CDROM_CONFIG_FLAGS (drive)->audio_play = 1; - return nslots; - } - - if (ide_cdrom_get_capabilities(drive, &cap)) - return 0; - - if (cap.lock == 0) - CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1; - if (cap.eject) - CDROM_CONFIG_FLAGS (drive)->no_eject = 0; - if (cap.cd_r_write) - CDROM_CONFIG_FLAGS (drive)->cd_r = 1; - if (cap.cd_rw_write) - CDROM_CONFIG_FLAGS (drive)->cd_rw = 1; - if (cap.test_write) - CDROM_CONFIG_FLAGS (drive)->test_write = 1; - if (cap.dvd_ram_read || cap.dvd_r_read || cap.dvd_rom) - CDROM_CONFIG_FLAGS (drive)->dvd = 1; - if (cap.dvd_ram_write) - CDROM_CONFIG_FLAGS (drive)->dvd_ram = 1; - if (cap.dvd_r_write) - CDROM_CONFIG_FLAGS (drive)->dvd_r = 1; - if (cap.audio_play) - CDROM_CONFIG_FLAGS (drive)->audio_play = 1; - if (cap.mechtype == mechtype_caddy || cap.mechtype == mechtype_popup) - CDROM_CONFIG_FLAGS (drive)->close_tray = 0; - -#if ! STANDARD_ATAPI - if (cdi->sanyo_slot > 0) { - CDROM_CONFIG_FLAGS (drive)->is_changer = 1; - nslots = 3; - } - - else -#endif /* not STANDARD_ATAPI */ - if (cap.mechtype == mechtype_individual_changer || - cap.mechtype == mechtype_cartridge_changer) { - if ((nslots = cdrom_number_of_slots(cdi)) > 1) { - CDROM_CONFIG_FLAGS (drive)->is_changer = 1; - CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 1; - } - } - - /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */ - if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) { - CDROM_STATE_FLAGS (drive)->current_speed = - (((unsigned int)cap.curspeed) + (176/2)) / 176; - CDROM_CONFIG_FLAGS (drive)->max_speed = - (((unsigned int)cap.maxspeed) + (176/2)) / 176; - } else { - CDROM_STATE_FLAGS (drive)->current_speed = - (ntohs(cap.curspeed) + (176/2)) / 176; - CDROM_CONFIG_FLAGS (drive)->max_speed = - (ntohs(cap.maxspeed) + (176/2)) / 176; - } - - /* don't print speed if the drive reported 0. - */ - printk("%s: ATAPI", drive->name); - if (CDROM_CONFIG_FLAGS(drive)->max_speed) - printk(" %dX", CDROM_CONFIG_FLAGS(drive)->max_speed); - printk(" %s", CDROM_CONFIG_FLAGS(drive)->dvd ? "DVD-ROM" : "CD-ROM"); - - if (CDROM_CONFIG_FLAGS (drive)->dvd_r|CDROM_CONFIG_FLAGS (drive)->dvd_ram) - printk (" DVD%s%s", - (CDROM_CONFIG_FLAGS (drive)->dvd_r)? "-R" : "", - (CDROM_CONFIG_FLAGS (drive)->dvd_ram)? "-RAM" : ""); - - if (CDROM_CONFIG_FLAGS (drive)->cd_r|CDROM_CONFIG_FLAGS (drive)->cd_rw) - printk (" CD%s%s", - (CDROM_CONFIG_FLAGS (drive)->cd_r)? "-R" : "", - (CDROM_CONFIG_FLAGS (drive)->cd_rw)? "/RW" : ""); - - if (CDROM_CONFIG_FLAGS (drive)->is_changer) - printk (" changer w/%d slots", nslots); - else - printk (" drive"); - - printk (", %dkB Cache", be16_to_cpu(cap.buffer_size)); - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (drive->using_dma) - (void) HWIF(drive)->dmaproc(ide_dma_verbose, drive); -#endif /* CONFIG_BLK_DEV_IDEDMA */ - printk("\n"); - - return nslots; -} - -static void ide_cdrom_add_settings(ide_drive_t *drive) -{ -#if 0 - int major = HWIF(drive)->major; - int minor = drive->select.b.unit << PARTN_BITS; - - ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 2, &read_ahead[major], NULL); - ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor], NULL); - ide_add_setting(drive, "max_kb_per_request", SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL); -#endif - ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); -} - -static -int ide_cdrom_setup (ide_drive_t *drive) -{ - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *cdi = &info->devinfo; - int minor = drive->select.b.unit << PARTN_BITS; - int nslots; - - /* - * default to read-only always and fix latter at the bottom - */ - set_device_ro(MKDEV(HWIF(drive)->major, minor), 1); -#if 0 - set_blocksize(MKDEV(HWIF(drive)->major, minor), CD_FRAMESIZE); -#endif - - drive->special.all = 0; - drive->ready_stat = 0; - - CDROM_STATE_FLAGS (drive)->media_changed = 1; - CDROM_STATE_FLAGS (drive)->toc_valid = 0; - CDROM_STATE_FLAGS (drive)->door_locked = 0; - -#if NO_DOOR_LOCKING - CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1; -#else - CDROM_CONFIG_FLAGS (drive)->no_doorlock = 0; -#endif - - if (drive->id != NULL) - CDROM_CONFIG_FLAGS (drive)->drq_interrupt = - ((drive->id->config & 0x0060) == 0x20); - else - CDROM_CONFIG_FLAGS (drive)->drq_interrupt = 0; - - CDROM_CONFIG_FLAGS (drive)->is_changer = 0; - CDROM_CONFIG_FLAGS (drive)->cd_r = 0; - CDROM_CONFIG_FLAGS (drive)->cd_rw = 0; - CDROM_CONFIG_FLAGS (drive)->test_write = 0; - CDROM_CONFIG_FLAGS (drive)->dvd = 0; - CDROM_CONFIG_FLAGS (drive)->dvd_r = 0; - CDROM_CONFIG_FLAGS (drive)->dvd_ram = 0; - CDROM_CONFIG_FLAGS (drive)->no_eject = 1; - CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 0; - CDROM_CONFIG_FLAGS (drive)->audio_play = 0; - CDROM_CONFIG_FLAGS (drive)->close_tray = 1; - - /* limit transfer size per interrupt. */ - CDROM_CONFIG_FLAGS (drive)->limit_nframes = 0; - if (drive->id != NULL) { - /* a testament to the nice quality of Samsung drives... */ - if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430")) - CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1; - else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432")) - CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1; - /* the 3231 model does not support the SET_CD_SPEED command */ - else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-3231")) - cdi->mask |= CDC_SELECT_SPEED; - } - -#if ! STANDARD_ATAPI - /* by default Sanyo 3 CD changer support is turned off and - ATAPI Rev 2.2+ standard support for CD changers is used */ - cdi->sanyo_slot = 0; - - CDROM_CONFIG_FLAGS (drive)->nec260 = 0; - CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd = 0; - CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd = 0; - CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 0; - CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 0; - - if (drive->id != NULL) { - if (strcmp (drive->id->model, "V003S0DS") == 0 && - drive->id->fw_rev[4] == '1' && - drive->id->fw_rev[6] <= '2') { - /* Vertos 300. - Some versions of this drive like to talk BCD. */ - CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1; - } - - else if (strcmp (drive->id->model, "V006E0DS") == 0 && - drive->id->fw_rev[4] == '1' && - drive->id->fw_rev[6] <= '2') { - /* Vertos 600 ESD. */ - CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd = 1; - } - - else if (strcmp (drive->id->model, - "NEC CD-ROM DRIVE:260") == 0 && - strncmp (drive->id->fw_rev, "1.01", 4) == 0) { /* FIXME */ - /* Old NEC260 (not R). - This drive was released before the 1.2 version - of the spec. */ - CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->nec260 = 1; - } - - else if (strcmp (drive->id->model, "WEARNES CDD-120") == 0 && - strncmp (drive->id->fw_rev, "A1.1", 4) == 0) { /* FIXME */ - /* Wearnes */ - CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1; - } - - /* Sanyo 3 CD changer uses a non-standard command - for CD changing */ - else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) || - (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0) || - (strcmp(drive->id->model, "CD-ROM CDR_C36") == 0)) { - /* uses CD in slot 0 when value is set to 3 */ - cdi->sanyo_slot = 3; - } - - - } -#endif /* not STANDARD_ATAPI */ - - info->toc = NULL; - info->buffer = NULL; - info->sector_buffered = 0; - info->nsectors_buffered = 0; - info->changer_info = NULL; - info->last_block = 0; - info->start_seek = 0; - - nslots = ide_cdrom_probe_capabilities (drive); - - if (CDROM_CONFIG_FLAGS(drive)->dvd_ram) - set_device_ro(MKDEV(HWIF(drive)->major, minor), 0); - - if (ide_cdrom_register (drive, nslots)) { - printk ("%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name); - info->devinfo.handle = NULL; - return 1; - } - ide_cdrom_add_settings(drive); - return 0; -} - -/* Forwarding functions to generic routines. */ -static -int ide_cdrom_ioctl (ide_drive_t *drive, - struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return cdrom_ioctl (inode, file, cmd, arg); -} - -static -int ide_cdrom_open (struct inode *ip, struct file *fp, ide_drive_t *drive) -{ - struct cdrom_info *info = drive->driver_data; - int rc = -ENOMEM; - - MOD_INC_USE_COUNT; - if (info->buffer == NULL) - info->buffer = (char *) kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL); - if ((info->buffer == NULL) || (rc = cdrom_open(ip, fp))) { - drive->usage--; - MOD_DEC_USE_COUNT; - } - return rc; -} - -static -void ide_cdrom_release (struct inode *inode, struct file *file, - ide_drive_t *drive) -{ - cdrom_release (inode, file); - MOD_DEC_USE_COUNT; -} - -static -int ide_cdrom_check_media_change (ide_drive_t *drive) -{ - return cdrom_media_changed(MKDEV (HWIF (drive)->major, - (drive->select.b.unit) << PARTN_BITS)); -} - -static -void ide_cdrom_revalidate (ide_drive_t *drive) -{ - struct cdrom_info *info = drive->driver_data; - struct atapi_toc *toc; - int minor = drive->select.b.unit << PARTN_BITS; - struct request_sense sense; - - cdrom_read_toc(drive, &sense); - - if (!CDROM_STATE_FLAGS(drive)->toc_valid) - return; - - toc = info->toc; - - /* for general /dev/cdrom like mounting, one big disc */ - drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME; - HWIF(drive)->gd->sizes[minor] = toc->capacity * BLOCKS_PER_FRAME; - - /* - * reset block size, ide_revalidate_disk incorrectly sets it to - * 1024 even for CDROM's - */ - blk_size[HWIF(drive)->major] = HWIF(drive)->gd->sizes; -#if 0 - set_blocksize(MKDEV(HWIF(drive)->major, minor), CD_FRAMESIZE); -#endif -} - -static -unsigned long ide_cdrom_capacity (ide_drive_t *drive) -{ - unsigned long capacity; - - if (cdrom_read_capacity(drive, &capacity, NULL)) - return 0; - - return capacity * SECTORS_PER_FRAME; -} - -static -int ide_cdrom_cleanup(ide_drive_t *drive) -{ - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *devinfo = &info->devinfo; - - if (ide_unregister_subdriver (drive)) - return 1; - if (info->buffer != NULL) - kfree(info->buffer); - if (info->toc != NULL) - kfree(info->toc); - if (info->changer_info != NULL) - kfree(info->changer_info); - if (devinfo->handle == drive && unregister_cdrom (devinfo)) - printk ("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name); - kfree(info); - drive->driver_data = NULL; - return 0; -} - -#if 0 -static -int ide_cdrom_reinit (ide_drive_t *drive) -{ - return 0; -} -#endif /* 0 */ - -static ide_driver_t ide_cdrom_driver = { - name: "ide-cdrom", - version: IDECD_VERSION, - media: ide_cdrom, - busy: 0, - supports_dma: 1, - supports_dsc_overlap: 1, - cleanup: ide_cdrom_cleanup, - do_request: ide_do_rw_cdrom, - end_request: NULL, - ioctl: ide_cdrom_ioctl, - open: ide_cdrom_open, - release: ide_cdrom_release, - media_change: ide_cdrom_check_media_change, - revalidate: ide_cdrom_revalidate, - pre_reset: NULL, - capacity: ide_cdrom_capacity, - special: NULL, -#if 0 - proc: NULL, - driver_reinit: ide_cdrom_reinit, -#endif -}; - -int ide_cdrom_init(void); -static ide_module_t ide_cdrom_module = { - IDE_DRIVER_MODULE, - ide_cdrom_init, - &ide_cdrom_driver, - NULL -}; - -/* options */ -char *ignore = NULL; - -MODULE_PARM(ignore, "s"); -MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); - -static void __exit ide_cdrom_exit(void) -{ - ide_drive_t *drive; - int failed = 0; - - while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, &ide_cdrom_driver, failed)) != NULL) - if (ide_cdrom_cleanup (drive)) { - printk ("%s: cleanup_module() called while still busy\n", drive->name); - failed++; - } - ide_unregister_module (&ide_cdrom_module); -} - -int ide_cdrom_init(void) -{ - ide_drive_t *drive; - struct cdrom_info *info; - int failed = 0; - - MOD_INC_USE_COUNT; - while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, NULL, failed++)) != NULL) { - /* skip drives that we were told to ignore */ - if (ignore != NULL) { - if (strstr(ignore, drive->name)) { - printk("ide-cd: ignoring drive %s\n", drive->name); - continue; - } - } - if (drive->scsi) { - printk("ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name); - continue; - } - info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL); - if (info == NULL) { - printk ("%s: Can't allocate a cdrom structure\n", drive->name); - continue; - } - if (ide_register_subdriver (drive, &ide_cdrom_driver, IDE_SUBDRIVER_VERSION)) { - printk ("%s: Failed to register the driver with ide.c\n", drive->name); - kfree (info); - continue; - } - memset (info, 0, sizeof (struct cdrom_info)); - drive->driver_data = info; - DRIVER(drive)->busy++; - if (ide_cdrom_setup (drive)) { - DRIVER(drive)->busy--; - if (ide_cdrom_cleanup (drive)) - printk ("%s: ide_cdrom_cleanup failed in ide_cdrom_init\n", drive->name); - continue; - } - DRIVER(drive)->busy--; - failed--; - } - ide_register_module(&ide_cdrom_module); - MOD_DEC_USE_COUNT; - return 0; -} - -module_init(ide_cdrom_init); -module_exit(ide_cdrom_exit); -MODULE_LICENSE("GPL"); diff --git a/xen/drivers/ide/ide-cd.h b/xen/drivers/ide/ide-cd.h deleted file mode 100644 index 41db4722c5..0000000000 --- a/xen/drivers/ide/ide-cd.h +++ /dev/null @@ -1,746 +0,0 @@ -/* - * linux/drivers/ide/ide_cd.h - * - * Copyright (C) 1996-98 Erik Andersen - * Copyright (C) 1998-2000 Jens Axboe - */ -#ifndef _IDE_CD_H -#define _IDE_CD_H - -#include -#include - -/* Turn this on to have the driver print out the meanings of the - ATAPI error codes. This will use up additional kernel-space - memory, though. */ - -#ifndef VERBOSE_IDE_CD_ERRORS -#define VERBOSE_IDE_CD_ERRORS 1 -#endif - - -/* Turning this on will remove code to work around various nonstandard - ATAPI implementations. If you know your drive follows the standard, - this will give you a slightly smaller kernel. */ - -#ifndef STANDARD_ATAPI -#define STANDARD_ATAPI 0 -#endif - - -/* Turning this on will disable the door-locking functionality. - This is apparently needed for supermount. */ - -#ifndef NO_DOOR_LOCKING -#define NO_DOOR_LOCKING 0 -#endif - -/************************************************************************/ - -#define SECTOR_BITS 9 -// XXX SMH: already defined in ide.h -#ifdef SECTOR_SIZE -#undef SECTOR_SIZE -#endif -#define SECTOR_SIZE (1 << SECTOR_BITS) -#define SECTORS_PER_FRAME (CD_FRAMESIZE >> SECTOR_BITS) -#define SECTOR_BUFFER_SIZE (CD_FRAMESIZE * 32) -#define SECTORS_BUFFER (SECTOR_BUFFER_SIZE >> SECTOR_BITS) -#define SECTORS_MAX (131072 >> SECTOR_BITS) - -#define BLOCKS_PER_FRAME (CD_FRAMESIZE / BLOCK_SIZE) - -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - -/* special command codes for strategy routine. */ -#define PACKET_COMMAND 4315 -#define REQUEST_SENSE_COMMAND 4316 -#define RESET_DRIVE_COMMAND 4317 - - -/* Configuration flags. These describe the capabilities of the drive. - They generally do not change after initialization, unless we learn - more about the drive from stuff failing. */ -struct ide_cd_config_flags { - __u8 drq_interrupt : 1; /* Device sends an interrupt when ready - for a packet command. */ - __u8 no_doorlock : 1; /* Drive cannot lock the door. */ - __u8 no_eject : 1; /* Drive cannot eject the disc. */ - __u8 nec260 : 1; /* Drive is a pre-1.2 NEC 260 drive. */ - __u8 playmsf_as_bcd : 1; /* PLAYMSF command takes BCD args. */ - __u8 tocaddr_as_bcd : 1; /* TOC addresses are in BCD. */ - __u8 toctracks_as_bcd : 1; /* TOC track numbers are in BCD. */ - __u8 subchan_as_bcd : 1; /* Subchannel info is in BCD. */ - __u8 is_changer : 1; /* Drive is a changer. */ - __u8 cd_r : 1; /* Drive can write to CD-R media . */ - __u8 cd_rw : 1; /* Drive can write to CD-R/W media . */ - __u8 dvd : 1; /* Drive is a DVD-ROM */ - __u8 dvd_r : 1; /* Drive can write DVD-R */ - __u8 dvd_ram : 1; /* Drive can write DVD-RAM */ - __u8 test_write : 1; /* Drive can fake writes */ - __u8 supp_disc_present : 1; /* Changer can report exact contents - of slots. */ - __u8 limit_nframes : 1; /* Drive does not provide data in - multiples of SECTOR_SIZE when more - than one interrupt is needed. */ - __u8 seeking : 1; /* Seeking in progress */ - __u8 audio_play : 1; /* can do audio related commands */ - __u8 close_tray : 1; /* can close the tray */ - __u8 writing : 1; /* pseudo write in progress */ - __u8 reserved : 3; - byte max_speed; /* Max speed of the drive */ -}; -#define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags)) - - -/* State flags. These give information about the current state of the - drive, and will change during normal operation. */ -struct ide_cd_state_flags { - __u8 media_changed : 1; /* Driver has noticed a media change. */ - __u8 toc_valid : 1; /* Saved TOC information is current. */ - __u8 door_locked : 1; /* We think that the drive door is locked. */ - __u8 writing : 1; /* the drive is currently writing */ - __u8 reserved : 4; - byte current_speed; /* Current speed of the drive */ -}; - -#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags)) - -struct packet_command { - char *buffer; - int buflen; - int stat; - int quiet; - int timeout; - struct request_sense *sense; - unsigned char c[12]; -}; - -/* Structure of a MSF cdrom address. */ -struct atapi_msf { - byte reserved; - byte minute; - byte second; - byte frame; -}; - -/* Space to hold the disk TOC. */ -#define MAX_TRACKS 99 -struct atapi_toc_header { - unsigned short toc_length; - byte first_track; - byte last_track; -}; - -struct atapi_toc_entry { - byte reserved1; -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 adr : 4; - __u8 control : 4; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - __u8 control : 4; - __u8 adr : 4; -#else -#error "Please fix " -#endif - byte track; - byte reserved2; - union { - unsigned lba; - struct atapi_msf msf; - } addr; -}; - -struct atapi_toc { - int last_session_lba; - int xa_flag; - unsigned long capacity; - struct atapi_toc_header hdr; - struct atapi_toc_entry ent[MAX_TRACKS+1]; - /* One extra for the leadout. */ -}; - - -/* This structure is annoyingly close to, but not identical with, - the cdrom_subchnl structure from cdrom.h. */ -struct atapi_cdrom_subchnl { - u_char acdsc_reserved; - u_char acdsc_audiostatus; - u_short acdsc_length; - u_char acdsc_format; - -#if defined(__BIG_ENDIAN_BITFIELD) - u_char acdsc_ctrl: 4; - u_char acdsc_adr: 4; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - u_char acdsc_adr: 4; - u_char acdsc_ctrl: 4; -#else -#error "Please fix " -#endif - u_char acdsc_trk; - u_char acdsc_ind; - union { - struct atapi_msf msf; - int lba; - } acdsc_absaddr; - union { - struct atapi_msf msf; - int lba; - } acdsc_reladdr; -}; - - - -/* This should probably go into cdrom.h along with the other - * generic stuff now in the Mt. Fuji spec. - */ -struct atapi_capabilities_page { - struct mode_page_header header; -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 parameters_saveable : 1; - __u8 reserved1 : 1; - __u8 page_code : 6; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - __u8 page_code : 6; - __u8 reserved1 : 1; - __u8 parameters_saveable : 1; -#else -#error "Please fix " -#endif - - byte page_length; - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 reserved2 : 2; - /* Drive supports reading of DVD-RAM discs */ - __u8 dvd_ram_read : 1; - /* Drive supports reading of DVD-R discs */ - __u8 dvd_r_read : 1; - /* Drive supports reading of DVD-ROM discs */ - __u8 dvd_rom : 1; - /* Drive supports reading CD-R discs with addressing method 2 */ - __u8 method2 : 1; /* reserved in 1.2 */ - /* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */ - __u8 cd_rw_read : 1; /* reserved in 1.2 */ - /* Drive supports read from CD-R discs (orange book, part II) */ - __u8 cd_r_read : 1; /* reserved in 1.2 */ -#elif defined(__LITTLE_ENDIAN_BITFIELD) - /* Drive supports read from CD-R discs (orange book, part II) */ - __u8 cd_r_read : 1; /* reserved in 1.2 */ - /* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */ - __u8 cd_rw_read : 1; /* reserved in 1.2 */ - /* Drive supports reading CD-R discs with addressing method 2 */ - __u8 method2 : 1; - /* Drive supports reading of DVD-ROM discs */ - __u8 dvd_rom : 1; - /* Drive supports reading of DVD-R discs */ - __u8 dvd_r_read : 1; - /* Drive supports reading of DVD-RAM discs */ - __u8 dvd_ram_read : 1; - __u8 reserved2 : 2; -#else -#error "Please fix " -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 reserved3 : 2; - /* Drive can write DVD-RAM discs */ - __u8 dvd_ram_write : 1; - /* Drive can write DVD-R discs */ - __u8 dvd_r_write : 1; - __u8 reserved3a : 1; - /* Drive can fake writes */ - __u8 test_write : 1; - /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */ - __u8 cd_rw_write : 1; /* reserved in 1.2 */ - /* Drive supports write to CD-R discs (orange book, part II) */ - __u8 cd_r_write : 1; /* reserved in 1.2 */ -#elif defined(__LITTLE_ENDIAN_BITFIELD) - /* Drive can write to CD-R discs (orange book, part II) */ - __u8 cd_r_write : 1; /* reserved in 1.2 */ - /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */ - __u8 cd_rw_write : 1; /* reserved in 1.2 */ - /* Drive can fake writes */ - __u8 test_write : 1; - __u8 reserved3a : 1; - /* Drive can write DVD-R discs */ - __u8 dvd_r_write : 1; - /* Drive can write DVD-RAM discs */ - __u8 dvd_ram_write : 1; - __u8 reserved3 : 2; -#else -#error "Please fix " -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 reserved4 : 1; - /* Drive can read multisession discs. */ - __u8 multisession : 1; - /* Drive can read mode 2, form 2 data. */ - __u8 mode2_form2 : 1; - /* Drive can read mode 2, form 1 (XA) data. */ - __u8 mode2_form1 : 1; - /* Drive supports digital output on port 2. */ - __u8 digport2 : 1; - /* Drive supports digital output on port 1. */ - __u8 digport1 : 1; - /* Drive can deliver a composite audio/video data stream. */ - __u8 composite : 1; - /* Drive supports audio play operations. */ - __u8 audio_play : 1; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - /* Drive supports audio play operations. */ - __u8 audio_play : 1; - /* Drive can deliver a composite audio/video data stream. */ - __u8 composite : 1; - /* Drive supports digital output on port 1. */ - __u8 digport1 : 1; - /* Drive supports digital output on port 2. */ - __u8 digport2 : 1; - /* Drive can read mode 2, form 1 (XA) data. */ - __u8 mode2_form1 : 1; - /* Drive can read mode 2, form 2 data. */ - __u8 mode2_form2 : 1; - /* Drive can read multisession discs. */ - __u8 multisession : 1; - __u8 reserved4 : 1; -#else -#error "Please fix " -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 reserved5 : 1; - /* Drive can return Media Catalog Number (UPC) info. */ - __u8 upc : 1; - /* Drive can return International Standard Recording Code info. */ - __u8 isrc : 1; - /* Drive supports C2 error pointers. */ - __u8 c2_pointers : 1; - /* R-W data will be returned deinterleaved and error corrected. */ - __u8 rw_corr : 1; - /* Subchannel reads can return combined R-W information. */ - __u8 rw_supported : 1; - /* Drive can continue a read cdda operation from a loss of streaming.*/ - __u8 cdda_accurate : 1; - /* Drive can read Red Book audio data. */ - __u8 cdda : 1; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - /* Drive can read Red Book audio data. */ - __u8 cdda : 1; - /* Drive can continue a read cdda operation from a loss of streaming.*/ - __u8 cdda_accurate : 1; - /* Subchannel reads can return combined R-W information. */ - __u8 rw_supported : 1; - /* R-W data will be returned deinterleaved and error corrected. */ - __u8 rw_corr : 1; - /* Drive supports C2 error pointers. */ - __u8 c2_pointers : 1; - /* Drive can return International Standard Recording Code info. */ - __u8 isrc : 1; - /* Drive can return Media Catalog Number (UPC) info. */ - __u8 upc : 1; - __u8 reserved5 : 1; -#else -#error "Please fix " -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - /* Drive mechanism types. */ - mechtype_t mechtype : 3; - __u8 reserved6 : 1; - /* Drive can eject a disc or changer cartridge. */ - __u8 eject : 1; - /* State of prevent/allow jumper. */ - __u8 prevent_jumper : 1; - /* Present state of door lock. */ - __u8 lock_state : 1; - /* Drive can lock the door. */ - __u8 lock : 1; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - - /* Drive can lock the door. */ - __u8 lock : 1; - /* Present state of door lock. */ - __u8 lock_state : 1; - /* State of prevent/allow jumper. */ - __u8 prevent_jumper : 1; - /* Drive can eject a disc or changer cartridge. */ - __u8 eject : 1; - __u8 reserved6 : 1; - /* Drive mechanism types. */ - mechtype_t mechtype : 3; -#else -#error "Please fix " -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 reserved7 : 4; - /* Drive supports software slot selection. */ - __u8 sss : 1; /* reserved in 1.2 */ - /* Changer can report exact contents of slots. */ - __u8 disc_present : 1; /* reserved in 1.2 */ - /* Audio for each channel can be muted independently. */ - __u8 separate_mute : 1; - /* Audio level for each channel can be controlled independently. */ - __u8 separate_volume : 1; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - - /* Audio level for each channel can be controlled independently. */ - __u8 separate_volume : 1; - /* Audio for each channel can be muted independently. */ - __u8 separate_mute : 1; - /* Changer can report exact contents of slots. */ - __u8 disc_present : 1; /* reserved in 1.2 */ - /* Drive supports software slot selection. */ - __u8 sss : 1; /* reserved in 1.2 */ - __u8 reserved7 : 4; -#else -#error "Please fix " -#endif - - /* Note: the following four fields are returned in big-endian form. */ - /* Maximum speed (in kB/s). */ - unsigned short maxspeed; - /* Number of discrete volume levels. */ - unsigned short n_vol_levels; - /* Size of cache in drive, in kB. */ - unsigned short buffer_size; - /* Current speed (in kB/s). */ - unsigned short curspeed; - char pad[4]; -}; - - -struct atapi_mechstat_header { -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 fault : 1; - __u8 changer_state : 2; - __u8 curslot : 5; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - __u8 curslot : 5; - __u8 changer_state : 2; - __u8 fault : 1; -#else -#error "Please fix " -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 mech_state : 3; - __u8 door_open : 1; - __u8 reserved1 : 4; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - __u8 reserved1 : 4; - __u8 door_open : 1; - __u8 mech_state : 3; -#else -#error "Please fix " -#endif - - byte curlba[3]; - byte nslots; - __u16 slot_tablelen; -}; - - -struct atapi_slot { -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 disc_present : 1; - __u8 reserved1 : 6; - __u8 change : 1; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - __u8 change : 1; - __u8 reserved1 : 6; - __u8 disc_present : 1; -#else -#error "Please fix " -#endif - - byte reserved2[3]; -}; - -struct atapi_changer_info { - struct atapi_mechstat_header hdr; - struct atapi_slot slots[0]; -}; - -/* Extra per-device info for cdrom drives. */ -struct cdrom_info { - - /* Buffer for table of contents. NULL if we haven't allocated - a TOC buffer for this device yet. */ - - struct atapi_toc *toc; - - unsigned long sector_buffered; - unsigned long nsectors_buffered; - unsigned char *buffer; - - /* The result of the last successful request sense command - on this device. */ - struct request_sense sense_data; - - struct request request_sense_request; - struct packet_command request_sense_pc; - int dma; - int cmd; - unsigned long last_block; - unsigned long start_seek; - /* Buffer to hold mechanism status and changer slot table. */ - struct atapi_changer_info *changer_info; - - struct ide_cd_config_flags config_flags; - struct ide_cd_state_flags state_flags; - - /* Per-device info needed by cdrom.c generic driver. */ - struct cdrom_device_info devinfo; -}; - -/**************************************************************************** - * Descriptions of ATAPI error codes. - */ - -#define ARY_LEN(a) ((sizeof(a) / sizeof(a[0]))) - -/* This stuff should be in cdrom.h, since it is now generic... */ - -/* ATAPI sense keys (from table 140 of ATAPI 2.6) */ -#define NO_SENSE 0x00 -#define RECOVERED_ERROR 0x01 -#define NOT_READY 0x02 -#define MEDIUM_ERROR 0x03 -#define HARDWARE_ERROR 0x04 -#define ILLEGAL_REQUEST 0x05 -#define UNIT_ATTENTION 0x06 -#define DATA_PROTECT 0x07 -#define ABORTED_COMMAND 0x0b -#define MISCOMPARE 0x0e - - - -/* This stuff should be in cdrom.h, since it is now generic... */ -#if VERBOSE_IDE_CD_ERRORS - - /* The generic packet command opcodes for CD/DVD Logical Units, - * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -const struct { - unsigned short packet_command; - const char * const text; -} packet_command_texts[] = { - { GPCMD_TEST_UNIT_READY, "Test Unit Ready" }, - { GPCMD_REQUEST_SENSE, "Request Sense" }, - { GPCMD_FORMAT_UNIT, "Format Unit" }, - { GPCMD_INQUIRY, "Inquiry" }, - { GPCMD_START_STOP_UNIT, "Start/Stop Unit" }, - { GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" }, - { GPCMD_READ_FORMAT_CAPACITIES, "Read Format Capacities" }, - { GPCMD_READ_CDVD_CAPACITY, "Read Cd/Dvd Capacity" }, - { GPCMD_READ_10, "Read 10" }, - { GPCMD_WRITE_10, "Write 10" }, - { GPCMD_SEEK, "Seek" }, - { GPCMD_WRITE_AND_VERIFY_10, "Write and Verify 10" }, - { GPCMD_VERIFY_10, "Verify 10" }, - { GPCMD_FLUSH_CACHE, "Flush Cache" }, - { GPCMD_READ_SUBCHANNEL, "Read Subchannel" }, - { GPCMD_READ_TOC_PMA_ATIP, "Read Table of Contents" }, - { GPCMD_READ_HEADER, "Read Header" }, - { GPCMD_PLAY_AUDIO_10, "Play Audio 10" }, - { GPCMD_GET_CONFIGURATION, "Get Configuration" }, - { GPCMD_PLAY_AUDIO_MSF, "Play Audio MSF" }, - { GPCMD_PLAYAUDIO_TI, "Play Audio TrackIndex" }, - { GPCMD_GET_EVENT_STATUS_NOTIFICATION, "Get Event Status Notification" }, - { GPCMD_PAUSE_RESUME, "Pause/Resume" }, - { GPCMD_STOP_PLAY_SCAN, "Stop Play/Scan" }, - { GPCMD_READ_DISC_INFO, "Read Disc Info" }, - { GPCMD_READ_TRACK_RZONE_INFO, "Read Track Rzone Info" }, - { GPCMD_RESERVE_RZONE_TRACK, "Reserve Rzone Track" }, - { GPCMD_SEND_OPC, "Send OPC" }, - { GPCMD_MODE_SELECT_10, "Mode Select 10" }, - { GPCMD_REPAIR_RZONE_TRACK, "Repair Rzone Track" }, - { GPCMD_MODE_SENSE_10, "Mode Sense 10" }, - { GPCMD_CLOSE_TRACK, "Close Track" }, - { GPCMD_BLANK, "Blank" }, - { GPCMD_SEND_EVENT, "Send Event" }, - { GPCMD_SEND_KEY, "Send Key" }, - { GPCMD_REPORT_KEY, "Report Key" }, - { GPCMD_LOAD_UNLOAD, "Load/Unload" }, - { GPCMD_SET_READ_AHEAD, "Set Read-ahead" }, - { GPCMD_READ_12, "Read 12" }, - { GPCMD_GET_PERFORMANCE, "Get Performance" }, - { GPCMD_SEND_DVD_STRUCTURE, "Send DVD Structure" }, - { GPCMD_READ_DVD_STRUCTURE, "Read DVD Structure" }, - { GPCMD_SET_STREAMING, "Set Streaming" }, - { GPCMD_READ_CD_MSF, "Read CD MSF" }, - { GPCMD_SCAN, "Scan" }, - { GPCMD_SET_SPEED, "Set Speed" }, - { GPCMD_PLAY_CD, "Play CD" }, - { GPCMD_MECHANISM_STATUS, "Mechanism Status" }, - { GPCMD_READ_CD, "Read CD" }, -}; - - - -/* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -const char * const sense_key_texts[16] = { - "No sense data", - "Recovered error", - "Not ready", - "Medium error", - "Hardware error", - "Illegal request", - "Unit attention", - "Data protect", - "(reserved)", - "(reserved)", - "(reserved)", - "Aborted command", - "(reserved)", - "(reserved)", - "Miscompare", - "(reserved)", -}; - -/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -const struct { - unsigned long asc_ascq; - const char * const text; -} sense_data_texts[] = { - { 0x000000, "No additional sense information" }, - { 0x000011, "Play operation in progress" }, - { 0x000012, "Play operation paused" }, - { 0x000013, "Play operation successfully completed" }, - { 0x000014, "Play operation stopped due to error" }, - { 0x000015, "No current audio status to return" }, - { 0x010c0a, "Write error - padding blocks added" }, - { 0x011700, "Recovered data with no error correction applied" }, - { 0x011701, "Recovered data with retries" }, - { 0x011702, "Recovered data with positive head offset" }, - { 0x011703, "Recovered data with negative head offset" }, - { 0x011704, "Recovered data with retries and/or CIRC applied" }, - { 0x011705, "Recovered data using previous sector ID" }, - { 0x011800, "Recovered data with error correction applied" }, - { 0x011801, "Recovered data with error correction and retries applied"}, - { 0x011802, "Recovered data - the data was auto-reallocated" }, - { 0x011803, "Recovered data with CIRC" }, - { 0x011804, "Recovered data with L-EC" }, - { 0x015d00, - "Failure prediction threshold exceeded - Predicted logical unit failure" }, - { 0x015d01, - "Failure prediction threshold exceeded - Predicted media failure" }, - { 0x015dff, "Failure prediction threshold exceeded - False" }, - { 0x017301, "Power calibration area almost full" }, - { 0x020400, "Logical unit not ready - cause not reportable" }, - /* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */ - { 0x020401, - "Logical unit not ready - in progress [sic] of becoming ready" }, - { 0x020402, "Logical unit not ready - initializing command required" }, - { 0x020403, "Logical unit not ready - manual intervention required" }, - { 0x020404, "Logical unit not ready - format in progress" }, - { 0x020407, "Logical unit not ready - operation in progress" }, - { 0x020408, "Logical unit not ready - long write in progress" }, - { 0x020600, "No reference position found (media may be upside down)" }, - { 0x023000, "Incompatible medium installed" }, - { 0x023a00, "Medium not present" }, - { 0x025300, "Media load or eject failed" }, - { 0x025700, "Unable to recover table of contents" }, - { 0x030300, "Peripheral device write fault" }, - { 0x030301, "No write current" }, - { 0x030302, "Excessive write errors" }, - { 0x030c00, "Write error" }, - { 0x030c01, "Write error - Recovered with auto reallocation" }, - { 0x030c02, "Write error - auto reallocation failed" }, - { 0x030c03, "Write error - recommend reassignment" }, - { 0x030c04, "Compression check miscompare error" }, - { 0x030c05, "Data expansion occurred during compress" }, - { 0x030c06, "Block not compressible" }, - { 0x030c07, "Write error - recovery needed" }, - { 0x030c08, "Write error - recovery failed" }, - { 0x030c09, "Write error - loss of streaming" }, - { 0x031100, "Unrecovered read error" }, - { 0x031106, "CIRC unrecovered error" }, - { 0x033101, "Format command failed" }, - { 0x033200, "No defect spare location available" }, - { 0x033201, "Defect list update failure" }, - { 0x035100, "Erase failure" }, - { 0x037200, "Session fixation error" }, - { 0x037201, "Session fixation error writin lead-in" }, - { 0x037202, "Session fixation error writin lead-out" }, - { 0x037300, "CD control error" }, - { 0x037302, "Power calibration area is full" }, - { 0x037303, "Power calibration area error" }, - { 0x037304, "Program memory area / RMA update failure" }, - { 0x037305, "Program memory area / RMA is full" }, - { 0x037306, "Program memory area / RMA is (almost) full" }, - - { 0x040200, "No seek complete" }, - { 0x040300, "Write fault" }, - { 0x040900, "Track following error" }, - { 0x040901, "Tracking servo failure" }, - { 0x040902, "Focus servo failure" }, - { 0x040903, "Spindle servo failure" }, - { 0x041500, "Random positioning error" }, - { 0x041501, "Mechanical positioning or changer error" }, - { 0x041502, "Positioning error detected by read of medium" }, - { 0x043c00, "Mechanical positioning or changer error" }, - { 0x044000, "Diagnostic failure on component (ASCQ)" }, - { 0x044400, "Internal CD/DVD logical unit failure" }, - { 0x04b600, "Media load mechanism failed" }, - { 0x051a00, "Parameter list length error" }, - { 0x052000, "Invalid command operation code" }, - { 0x052100, "Logical block address out of range" }, - { 0x052102, "Invalid address for write" }, - { 0x052400, "Invalid field in command packet" }, - { 0x052600, "Invalid field in parameter list" }, - { 0x052601, "Parameter not supported" }, - { 0x052602, "Parameter value invalid" }, - { 0x052700, "Write protected media" }, - { 0x052c00, "Command sequence error" }, - { 0x052c03, "Current program area is not empty" }, - { 0x052c04, "Current program area is empty" }, - { 0x053001, "Cannot read medium - unknown format" }, - { 0x053002, "Cannot read medium - incompatible format" }, - { 0x053900, "Saving parameters not supported" }, - { 0x054e00, "Overlapped commands attempted" }, - { 0x055302, "Medium removal prevented" }, - { 0x055500, "System resource failure" }, - { 0x056300, "End of user area encountered on this track" }, - { 0x056400, "Illegal mode for this track or incompatible medium" }, - { 0x056f00, "Copy protection key exchange failure - Authentication failure" }, - { 0x056f01, "Copy protection key exchange failure - Key not present" }, - { 0x056f02, "Copy protection key exchange failure - Key not established" }, - { 0x056f03, "Read of scrambled sector without authentication" }, - { 0x056f04, "Media region code is mismatched to logical unit" }, - { 0x056f05, "Drive region must be permanent / region reset count error" }, - { 0x057203, "Session fixation error - incomplete track in session" }, - { 0x057204, "Empty or partially written reserved track" }, - { 0x057205, "No more RZONE reservations are allowed" }, - { 0x05bf00, "Loss of streaming" }, - { 0x062800, "Not ready to ready transition, medium may have changed" }, - { 0x062900, "Power on, reset or hardware reset occurred" }, - { 0x062a00, "Parameters changed" }, - { 0x062a01, "Mode parameters changed" }, - { 0x062e00, "Insufficient time for operation" }, - { 0x063f00, "Logical unit operating conditions have changed" }, - { 0x063f01, "Microcode has been changed" }, - { 0x065a00, "Operator request or state change input (unspecified)" }, - { 0x065a01, "Operator medium removal request" }, - { 0x0bb900, "Play operation aborted" }, - - /* Here we use 0xff for the key (not a valid key) to signify - * that these can have _any_ key value associated with them... */ - { 0xff0401, "Logical unit is in process of becoming ready" }, - { 0xff0400, "Logical unit not ready, cause not reportable" }, - { 0xff0402, "Logical unit not ready, initializing command required" }, - { 0xff0403, "Logical unit not ready, manual intervention required" }, - { 0xff0500, "Logical unit does not respond to selection" }, - { 0xff0800, "Logical unit communication failure" }, - { 0xff0802, "Logical unit communication parity error" }, - { 0xff0801, "Logical unit communication time-out" }, - { 0xff2500, "Logical unit not supported" }, - { 0xff4c00, "Logical unit failed self-configuration" }, - { 0xff3e00, "Logical unit has not self-configured yet" }, -}; -#endif - - -#endif /* _IDE_CD_H */ diff --git a/xen/drivers/ide/ide-disk.c b/xen/drivers/ide/ide-disk.c deleted file mode 100644 index 42fe5313f3..0000000000 --- a/xen/drivers/ide/ide-disk.c +++ /dev/null @@ -1,1553 +0,0 @@ -/* - * linux/drivers/ide/ide-disk.c Version 1.10 June 9, 2000 - * - * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) - */ - -/* - * Mostly written by Mark Lord - * and Gadi Oxman - * and Andre Hedrick - * - * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c. - * - * Version 1.00 move disk only code from ide.c to ide-disk.c - * support optional byte-swapping of all data - * Version 1.01 fix previous byte-swapping code - * Version 1.02 remove ", LBA" from drive identification msgs - * Version 1.03 fix display of id->buf_size for big-endian - * Version 1.04 add /proc configurable settings and S.M.A.R.T support - * Version 1.05 add capacity support for ATA3 >= 8GB - * Version 1.06 get boot-up messages to show full cyl count - * Version 1.07 disable door-locking if it fails - * Version 1.08 fixed CHS/LBA translations for ATA4 > 8GB, - * process of adding new ATA4 compliance. - * fixed problems in allowing fdisk to see - * the entire disk. - * Version 1.09 added increment of rq->sector in ide_multwrite - * added UDMA 3/4 reporting - * Version 1.10 request queue changes, Ultra DMA 100 - * Version 1.11 added 48-bit lba - * Version 1.12 adding taskfile io access method - */ - -#define IDEDISK_VERSION "1.12" - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifdef CONFIG_BLK_DEV_PDC4030 -#define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030) -#else -#define IS_PDC4030_DRIVE (0) /* auto-NULLs out pdc4030 code */ -#endif - -#ifdef CONFIG_IDE_TASKFILE_IO -# undef __TASKFILE__IO /* define __TASKFILE__IO */ -#else /* CONFIG_IDE_TASKFILE_IO */ -# undef __TASKFILE__IO -#endif /* CONFIG_IDE_TASKFILE_IO */ - -#ifndef __TASKFILE__IO - -static void idedisk_bswap_data (void *buffer, int wcount) -{ - u16 *p = buffer; - - while (wcount--) { - *p = *p << 8 | *p >> 8; p++; - *p = *p << 8 | *p >> 8; p++; - } -} - -static inline void idedisk_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - ide_input_data(drive, buffer, wcount); - if (drive->bswap) - idedisk_bswap_data(buffer, wcount); -} - -static inline void idedisk_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - if (drive->bswap) { - idedisk_bswap_data(buffer, wcount); - ide_output_data(drive, buffer, wcount); - idedisk_bswap_data(buffer, wcount); - } else - ide_output_data(drive, buffer, wcount); -} - -#endif /* __TASKFILE__IO */ - -/* - * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity" - * value for this drive (from its reported identification information). - * - * Returns: 1 if lba_capacity looks sensible - * 0 otherwise - * - * It is called only once for each drive. - */ -static int lba_capacity_is_ok (struct hd_driveid *id) -{ - unsigned long lba_sects, chs_sects, head, tail; - - if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) { - printk("48-bit Drive: %llu \n", id->lba_capacity_2); - return 1; - } - - /* - * The ATA spec tells large drives to return - * C/H/S = 16383/16/63 independent of their size. - * Some drives can be jumpered to use 15 heads instead of 16. - * Some drives can be jumpered to use 4092 cyls instead of 16383. - */ - if ((id->cyls == 16383 - || (id->cyls == 4092 && id->cur_cyls == 16383)) && - id->sectors == 63 && - (id->heads == 15 || id->heads == 16) && - id->lba_capacity >= 16383*63*id->heads) - return 1; - - lba_sects = id->lba_capacity; - chs_sects = id->cyls * id->heads * id->sectors; - - /* perform a rough sanity check on lba_sects: within 10% is OK */ - if ((lba_sects - chs_sects) < chs_sects/10) - return 1; - - /* some drives have the word order reversed */ - head = ((lba_sects >> 16) & 0xffff); - tail = (lba_sects & 0xffff); - lba_sects = (head | (tail << 16)); - if ((lba_sects - chs_sects) < chs_sects/10) { - id->lba_capacity = lba_sects; - return 1; /* lba_capacity is (now) good */ - } - - return 0; /* lba_capacity value may be bad */ -} - -#ifndef __TASKFILE__IO - -/* - * read_intr() is the handler for disk read/multread interrupts - */ -static ide_startstop_t read_intr (ide_drive_t *drive) -{ - byte stat; - int i; - unsigned int msect, nsect; - struct request *rq; - - /* new way for dealing with premature shared PCI interrupts */ - if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) { - if (stat & (ERR_STAT|DRQ_STAT)) { - return ide_error(drive, "read_intr", stat); - } - /* no data yet, so wait for another interrupt */ - ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); - return ide_started; - } - msect = drive->mult_count; - -read_next: - rq = HWGROUP(drive)->rq; - if (msect) { - if ((nsect = rq->current_nr_sectors) > msect) - nsect = msect; - msect -= nsect; - } else - nsect = 1; - idedisk_input_data(drive, rq->buffer, nsect * SECTOR_WORDS); -#ifdef DEBUG - printk("%s: read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n", - drive->name, rq->sector, rq->sector+nsect-1, - (unsigned long) rq->buffer+(nsect<<9), rq->nr_sectors-nsect); -#endif - rq->sector += nsect; - rq->buffer += nsect<<9; - rq->errors = 0; - i = (rq->nr_sectors -= nsect); - if (((long)(rq->current_nr_sectors -= nsect)) <= 0) - ide_end_request(1, HWGROUP(drive)); - if (i > 0) { - if (msect) - goto read_next; - ide_set_handler (drive, &read_intr, WAIT_CMD, NULL); - return ide_started; - } - return ide_stopped; -} - -/* - * write_intr() is the handler for disk write interrupts - */ -static ide_startstop_t write_intr (ide_drive_t *drive) -{ - byte stat; - int i; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct request *rq = hwgroup->rq; - - if (!OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) { - printk("%s: write_intr error1: nr_sectors=%ld, stat=0x%02x\n", drive->name, rq->nr_sectors, stat); - } else { -#ifdef DEBUG - printk("%s: write: sector %ld, buffer=0x%08lx, remaining=%ld\n", - drive->name, rq->sector, (unsigned long) rq->buffer, - rq->nr_sectors-1); -#endif - if ((rq->nr_sectors == 1) ^ ((stat & DRQ_STAT) != 0)) { - rq->sector++; - rq->buffer += 512; - rq->errors = 0; - i = --rq->nr_sectors; - --rq->current_nr_sectors; - if (((long)rq->current_nr_sectors) <= 0) - ide_end_request(1, hwgroup); - if (i > 0) { - idedisk_output_data (drive, rq->buffer, SECTOR_WORDS); - ide_set_handler (drive, &write_intr, WAIT_CMD, NULL); - return ide_started; - } - return ide_stopped; - } - return ide_stopped; /* the original code did this here (?) */ - } - return ide_error(drive, "write_intr", stat); -} - -/* - * ide_multwrite() transfers a block of up to mcount sectors of data - * to a drive as part of a disk multiple-sector write operation. - * - * Returns 0 on success. - * - * Note that we may be called from two contexts - the do_rw_disk context - * and IRQ context. The IRQ can happen any time after we've output the - * full "mcount" number of sectors, so we must make sure we update the - * state _before_ we output the final part of the data! - */ -int ide_multwrite (ide_drive_t *drive, unsigned int mcount) -{ - ide_hwgroup_t *hwgroup= HWGROUP(drive); - struct request *rq = &hwgroup->wrq; - - do { - char *buffer; - int nsect = rq->current_nr_sectors; - - if (nsect > mcount) - nsect = mcount; - mcount -= nsect; - buffer = rq->buffer; - - rq->sector += nsect; - rq->buffer += nsect << 9; - rq->nr_sectors -= nsect; - rq->current_nr_sectors -= nsect; - - /* Do we move to the next bh after this? */ - if (!rq->current_nr_sectors) { - struct buffer_head *bh = rq->bh->b_reqnext; - - /* end early early we ran out of requests */ - if (!bh) { - mcount = 0; - } else { - rq->bh = bh; - rq->current_nr_sectors = bh->b_size >> 9; - rq->buffer = bh->b_data; - } - } - - /* - * Ok, we're all setup for the interrupt - * re-entering us on the last transfer. - */ - idedisk_output_data(drive, buffer, nsect<<7); - } while (mcount); - - return 0; -} - -/* - * multwrite_intr() is the handler for disk multwrite interrupts - */ -static ide_startstop_t multwrite_intr (ide_drive_t *drive) -{ - byte stat; - int i; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct request *rq = &hwgroup->wrq; - - if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) { - if (stat & DRQ_STAT) { - /* - * The drive wants data. Remember rq is the copy - * of the request - */ - if (rq->nr_sectors) { - if (ide_multwrite(drive, drive->mult_count)) - return ide_stopped; - ide_set_handler (drive, &multwrite_intr, WAIT_CMD, NULL); - return ide_started; - } - } else { - /* - * If the copy has all the blocks completed then - * we can end the original request. - */ - if (!rq->nr_sectors) { /* all done? */ - rq = hwgroup->rq; - for (i = rq->nr_sectors; i > 0;){ - i -= rq->current_nr_sectors; - ide_end_request(1, hwgroup); - } - return ide_stopped; - } - } - return ide_stopped; /* the original code did this here (?) */ - } - return ide_error(drive, "multwrite_intr", stat); -} -#endif /* __TASKFILE__IO */ - -#ifdef __TASKFILE__IO - -static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block); -static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block); -static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long long block); - -/* - * do_rw_disk() issues READ and WRITE commands to a disk, - * using LBA if supported, or CHS otherwise, to address sectors. - * It also takes care of issuing special DRIVE_CMDs. - */ -static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) -{ - if (rq->cmd == READ) - goto good_command; - if (rq->cmd == WRITE) - goto good_command; - - printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd); - ide_end_request(0, HWGROUP(drive)); - return ide_stopped; - -good_command: - -#ifdef CONFIG_BLK_DEV_PDC4030 - if (IS_PDC4030_DRIVE) { - extern ide_startstop_t promise_rw_disk(ide_drive_t *, struct request *, unsigned long); - return promise_rw_disk(drive, rq, block); - } -#endif /* CONFIG_BLK_DEV_PDC4030 */ - - if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) /* 48-bit LBA */ - return lba_48_rw_disk(drive, rq, (unsigned long long) block); - if (drive->select.b.lba) /* 28-bit LBA */ - return lba_28_rw_disk(drive, rq, (unsigned long) block); - - /* 28-bit CHS : DIE DIE DIE piece of legacy crap!!! */ - return chs_rw_disk(drive, rq, (unsigned long) block); -} - -static task_ioreg_t get_command (ide_drive_t *drive, int cmd) -{ - int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0; - -#if 1 - lba48bit = drive->addressing; -#endif - - if ((cmd == READ) && (drive->using_dma)) - return (lba48bit) ? WIN_READDMA_EXT : WIN_READDMA; - else if ((cmd == READ) && (drive->mult_count)) - return (lba48bit) ? WIN_MULTREAD_EXT : WIN_MULTREAD; - else if (cmd == READ) - return (lba48bit) ? WIN_READ_EXT : WIN_READ; - else if ((cmd == WRITE) && (drive->using_dma)) - return (lba48bit) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; - else if ((cmd == WRITE) && (drive->mult_count)) - return (lba48bit) ? WIN_MULTWRITE_EXT : WIN_MULTWRITE; - else if (cmd == WRITE) - return (lba48bit) ? WIN_WRITE_EXT : WIN_WRITE; - else - return WIN_NOP; -} - -static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) -{ - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - ide_task_t args; - - task_ioreg_t command = get_command(drive, rq->cmd); - unsigned int track = (block / drive->sect); - unsigned int sect = (block % drive->sect) + 1; - unsigned int head = (track % drive->head); - unsigned int cyl = (track / drive->head); - - memset(&taskfile, 0, sizeof(task_struct_t)); - memset(&hobfile, 0, sizeof(hob_struct_t)); - - taskfile.sector_count = (rq->nr_sectors==256)?0x00:rq->nr_sectors; - taskfile.sector_number = sect; - taskfile.low_cylinder = cyl; - taskfile.high_cylinder = (cyl>>8); - taskfile.device_head = head; - taskfile.device_head |= drive->select.all; - taskfile.command = command; - -#ifdef DEBUG - printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ"); - if (lba) printk("LBAsect=%lld, ", block); - else printk("CHS=%d/%d/%d, ", cyl, head, sect); - printk("sectors=%ld, ", rq->nr_sectors); - printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); -#endif - - memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr)); - memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr)); - args.command_type = ide_cmd_type_parser(&args); - args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile); - args.handler = ide_handler_parser(&taskfile, &hobfile); - args.posthandler = NULL; - args.rq = (struct request *) rq; - args.block = block; - rq->special = NULL; - rq->special = (ide_task_t *)&args; - - return do_rw_taskfile(drive, &args); -} - -static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) -{ - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - ide_task_t args; - - task_ioreg_t command = get_command(drive, rq->cmd); - - memset(&taskfile, 0, sizeof(task_struct_t)); - memset(&hobfile, 0, sizeof(hob_struct_t)); - - taskfile.sector_count = (rq->nr_sectors==256)?0x00:rq->nr_sectors; - taskfile.sector_number = block; - taskfile.low_cylinder = (block>>=8); - taskfile.high_cylinder = (block>>=8); - taskfile.device_head = ((block>>8)&0x0f); - taskfile.device_head |= drive->select.all; - taskfile.command = command; - - -#ifdef DEBUG - printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ"); - if (lba) printk("LBAsect=%lld, ", block); - else printk("CHS=%d/%d/%d, ", cyl, head, sect); - printk("sectors=%ld, ", rq->nr_sectors); - printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); -#endif - - memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr)); - memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr)); - args.command_type = ide_cmd_type_parser(&args); - args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile); - args.handler = ide_handler_parser(&taskfile, &hobfile); - args.posthandler = NULL; - args.rq = (struct request *) rq; - args.block = block; - rq->special = NULL; - rq->special = (ide_task_t *)&args; - - return do_rw_taskfile(drive, &args); -} - -/* - * 268435455 == 137439 MB or 28bit limit - * 320173056 == 163929 MB or 48bit addressing - * 1073741822 == 549756 MB or 48bit addressing fake drive - */ - -static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long long block) -{ - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - ide_task_t args; - - task_ioreg_t command = get_command(drive, rq->cmd); - - memset(&taskfile, 0, sizeof(task_struct_t)); - memset(&hobfile, 0, sizeof(hob_struct_t)); - - taskfile.sector_count = rq->nr_sectors; - hobfile.sector_count = (rq->nr_sectors>>8); - - if (rq->nr_sectors == 65536) { - taskfile.sector_count = 0x00; - hobfile.sector_count = 0x00; - } - - taskfile.sector_number = block; /* low lba */ - taskfile.low_cylinder = (block>>=8); /* mid lba */ - taskfile.high_cylinder = (block>>=8); /* hi lba */ - hobfile.sector_number = (block>>=8); /* low lba */ - hobfile.low_cylinder = (block>>=8); /* mid lba */ - hobfile.high_cylinder = (block>>=8); /* hi lba */ - taskfile.device_head = drive->select.all; - hobfile.device_head = taskfile.device_head; - hobfile.control = (drive->ctl|0x80); - taskfile.command = command; - -#ifdef DEBUG - printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ"); - if (lba) printk("LBAsect=%lld, ", block); - else printk("CHS=%d/%d/%d, ", cyl, head, sect); - printk("sectors=%ld, ", rq->nr_sectors); - printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); -#endif - - memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr)); - memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr)); - args.command_type = ide_cmd_type_parser(&args); - args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile); - args.handler = ide_handler_parser(&taskfile, &hobfile); - args.posthandler = NULL; - args.rq = (struct request *) rq; - args.block = block; - rq->special = NULL; - rq->special = (ide_task_t *)&args; - - return do_rw_taskfile(drive, &args); -} - -#else /* !__TASKFILE__IO */ -/* - * do_rw_disk() issues READ and WRITE commands to a disk, - * using LBA if supported, or CHS otherwise, to address sectors. - * It also takes care of issuing special DRIVE_CMDs. - */ -static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) -{ - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); - -#ifdef CONFIG_BLK_DEV_PDC4030 - if (drive->select.b.lba || IS_PDC4030_DRIVE) { -#else /* !CONFIG_BLK_DEV_PDC4030 */ - if (drive->select.b.lba) { -#endif /* CONFIG_BLK_DEV_PDC4030 */ - - if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) { - task_ioreg_t tasklets[10]; - - tasklets[0] = 0; - tasklets[1] = 0; - tasklets[2] = rq->nr_sectors; - tasklets[3] = (rq->nr_sectors>>8); - if (rq->nr_sectors == 65536) { - tasklets[2] = 0x00; - tasklets[3] = 0x00; - } - tasklets[4] = (task_ioreg_t) block; - tasklets[5] = (task_ioreg_t) (block>>8); - tasklets[6] = (task_ioreg_t) (block>>16); - tasklets[7] = (task_ioreg_t) (block>>24); - tasklets[8] = (task_ioreg_t) 0; - tasklets[9] = (task_ioreg_t) 0; -// tasklets[8] = (task_ioreg_t) (block>>32); -// tasklets[9] = (task_ioreg_t) (block>>40); -#ifdef DEBUG - printk("[A]\n"); - printk("%s: %sing: LBAsect=%lu, sectors=%ld, buffer=0x%08lx, LBAsect=0x%012lx\n", - drive->name, - (rq->cmd==READ)?"read":"writ", - block, - rq->nr_sectors, - (unsigned long) rq->buffer, - block); - printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n", - drive->name, tasklets[3], tasklets[2], - tasklets[9], tasklets[8], tasklets[7], - tasklets[6], tasklets[5], tasklets[4]); -#endif - OUT_BYTE(tasklets[1], IDE_FEATURE_REG); - OUT_BYTE(tasklets[3], IDE_NSECTOR_REG); - OUT_BYTE(tasklets[7], IDE_SECTOR_REG); - OUT_BYTE(tasklets[8], IDE_LCYL_REG); - OUT_BYTE(tasklets[9], IDE_HCYL_REG); - - OUT_BYTE(tasklets[0], IDE_FEATURE_REG); - OUT_BYTE(tasklets[2], IDE_NSECTOR_REG); - OUT_BYTE(tasklets[4], IDE_SECTOR_REG); - OUT_BYTE(tasklets[5], IDE_LCYL_REG); - OUT_BYTE(tasklets[6], IDE_HCYL_REG); - OUT_BYTE(0x00|drive->select.all,IDE_SELECT_REG); - } else { -#ifdef DEBUG - printk("%s: %sing: LBAsect=%ld, sectors=%ld, buffer=0x%08lx\n", - drive->name, (rq->cmd==READ)?"read":"writ", - block, rq->nr_sectors, (unsigned long) rq->buffer); -#endif - OUT_BYTE(0x00, IDE_FEATURE_REG); - OUT_BYTE((rq->nr_sectors==256)?0x00:rq->nr_sectors,IDE_NSECTOR_REG); - OUT_BYTE(block,IDE_SECTOR_REG); - OUT_BYTE(block>>=8,IDE_LCYL_REG); - OUT_BYTE(block>>=8,IDE_HCYL_REG); - OUT_BYTE(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG); - } - } else { - unsigned int sect,head,cyl,track; - track = block / drive->sect; - sect = block % drive->sect + 1; - OUT_BYTE(sect,IDE_SECTOR_REG); - head = track % drive->head; - cyl = track / drive->head; - - OUT_BYTE(0x00, IDE_FEATURE_REG); - OUT_BYTE((rq->nr_sectors==256)?0x00:rq->nr_sectors,IDE_NSECTOR_REG); - OUT_BYTE(cyl,IDE_LCYL_REG); - OUT_BYTE(cyl>>8,IDE_HCYL_REG); - OUT_BYTE(head|drive->select.all,IDE_SELECT_REG); -#ifdef DEBUG - printk("%s: %sing: CHS=%d/%d/%d, sectors=%ld, buffer=0x%08lx\n", - drive->name, (rq->cmd==READ)?"read":"writ", cyl, - head, sect, rq->nr_sectors, (unsigned long) rq->buffer); -#endif - } -#ifdef CONFIG_BLK_DEV_PDC4030 - if (IS_PDC4030_DRIVE) { - extern ide_startstop_t do_pdc4030_io(ide_drive_t *, struct request *); - return do_pdc4030_io (drive, rq); - } -#endif /* CONFIG_BLK_DEV_PDC4030 */ - if (rq->cmd == READ) { -#ifdef CONFIG_BLK_DEV_IDEDMA - if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive))) - return ide_started; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); - if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) { - OUT_BYTE(drive->mult_count ? WIN_MULTREAD_EXT : WIN_READ_EXT, IDE_COMMAND_REG); - } else { - OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG); - } - return ide_started; - } - if (rq->cmd == WRITE) { - ide_startstop_t startstop; -#ifdef CONFIG_BLK_DEV_IDEDMA - if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive))) - return ide_started; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) { - OUT_BYTE(drive->mult_count ? WIN_MULTWRITE_EXT : WIN_WRITE_EXT, IDE_COMMAND_REG); - } else { - OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, IDE_COMMAND_REG); - } - if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing %s\n", drive->name, - drive->mult_count ? "MULTWRITE" : "WRITE"); - return startstop; - } - if (!drive->unmask) - __cli(); /* local CPU only */ - if (drive->mult_count) { - ide_hwgroup_t *hwgroup = HWGROUP(drive); - /* - * Ugh.. this part looks ugly because we MUST set up - * the interrupt handler before outputting the first block - * of data to be written. If we hit an error (corrupted buffer list) - * in ide_multwrite(), then we need to remove the handler/timer - * before returning. Fortunately, this NEVER happens (right?). - * - * Except when you get an error it seems... - */ - hwgroup->wrq = *rq; /* scratchpad */ - ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL); - if (ide_multwrite(drive, drive->mult_count)) { - unsigned long flags; - spin_lock_irqsave(&io_request_lock, flags); - hwgroup->handler = NULL; - del_timer(&hwgroup->timer); - spin_unlock_irqrestore(&io_request_lock, flags); - return ide_stopped; - } - } else { - ide_set_handler (drive, &write_intr, WAIT_CMD, NULL); - idedisk_output_data(drive, rq->buffer, SECTOR_WORDS); - } - return ide_started; - } - printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd); - ide_end_request(0, HWGROUP(drive)); - return ide_stopped; -} - -#endif /* __TASKFILE__IO */ - -static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive) -{ - MOD_INC_USE_COUNT; - if (drive->removable && drive->usage == 1) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.command = WIN_DOORLOCK; - check_disk_change(inode->i_rdev); - /* - * Ignore the return code from door_lock, - * since the open() has already succeeded, - * and the door_lock is irrelevant at this point. - */ - if (drive->doorlocking && ide_wait_taskfile(drive, &taskfile, &hobfile, NULL)) - drive->doorlocking = 0; - } - return 0; -} - -static int do_idedisk_flushcache(ide_drive_t *drive); - -static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive) -{ - if (drive->removable && !drive->usage) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.command = WIN_DOORUNLOCK; - invalidate_bdev(inode->i_bdev, 0); - if (drive->doorlocking && ide_wait_taskfile(drive, &taskfile, &hobfile, NULL)) - drive->doorlocking = 0; - } - if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) - if (do_idedisk_flushcache(drive)) - printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", - drive->name); - MOD_DEC_USE_COUNT; -} - -static int idedisk_media_change (ide_drive_t *drive) -{ - return drive->removable; /* if removable, always assume it was changed */ -} - -static void idedisk_revalidate (ide_drive_t *drive) -{ - grok_partitions(HWIF(drive)->gd, drive->select.b.unit, - 1< 0) of the drive, 0 if failed. - */ -static unsigned long idedisk_read_native_max_address(ide_drive_t *drive) -{ - ide_task_t args; - unsigned long addr = 0; - - if (!(drive->id->command_set_1 & 0x0400) && - !(drive->id->cfs_enable_2 & 0x0100)) - return addr; - - /* Create IDE/ATA command request structure */ - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_SELECT_OFFSET] = 0x40; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX; - args.handler = task_no_data_intr; - - /* submit command request */ - ide_raw_taskfile(drive, &args, NULL); - - /* if OK, compute maximum address value */ - if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { - addr = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24) - | ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16) - | ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8) - | ((args.tfRegister[IDE_SECTOR_OFFSET] )); - } - addr++; /* since the return value is (maxlba - 1), we add 1 */ - return addr; -} - -static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive) -{ - ide_task_t args; - unsigned long long addr = 0; - - /* Create IDE/ATA command request structure */ - memset(&args, 0, sizeof(ide_task_t)); - - args.tfRegister[IDE_SELECT_OFFSET] = 0x40; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX_EXT; - args.handler = task_no_data_intr; - - /* submit command request */ - ide_raw_taskfile(drive, &args, NULL); - - /* if OK, compute maximum address value */ - if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { - u32 high = ((args.hobRegister[IDE_HCYL_OFFSET_HOB])<<16) | - ((args.hobRegister[IDE_LCYL_OFFSET_HOB])<<8) | - (args.hobRegister[IDE_SECTOR_OFFSET_HOB]); - u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) | - ((args.tfRegister[IDE_LCYL_OFFSET])<<8) | - (args.tfRegister[IDE_SECTOR_OFFSET]); - addr = ((__u64)high << 24) | low; - } - addr++; /* since the return value is (maxlba - 1), we add 1 */ - return addr; -} - -#ifdef CONFIG_IDEDISK_STROKE -/* - * Sets maximum virtual LBA address of the drive. - * Returns new maximum virtual LBA address (> 0) or 0 on failure. - */ -static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req) -{ - ide_task_t args; - unsigned long addr_set = 0; - - addr_req--; - /* Create IDE/ATA command request structure */ - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff); - args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >> 8) & 0xff); - args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >> 16) & 0xff); - args.tfRegister[IDE_SELECT_OFFSET] = ((addr_req >> 24) & 0x0f) | 0x40; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX; - args.handler = task_no_data_intr; - /* submit command request */ - ide_raw_taskfile(drive, &args, NULL); - /* if OK, read new maximum address value */ - if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { - addr_set = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24) - | ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16) - | ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8) - | ((args.tfRegister[IDE_SECTOR_OFFSET] )); - } - addr_set++; - return addr_set; -} - -static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req) -{ - ide_task_t args; - unsigned long long addr_set = 0; - - addr_req--; - /* Create IDE/ATA command request structure */ - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff); - args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >>= 8) & 0xff); - args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >>= 8) & 0xff); - args.tfRegister[IDE_SELECT_OFFSET] = 0x40; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX_EXT; - args.hobRegister[IDE_SECTOR_OFFSET_HOB] = ((addr_req >>= 8) & 0xff); - args.hobRegister[IDE_LCYL_OFFSET_HOB] = ((addr_req >>= 8) & 0xff); - args.hobRegister[IDE_HCYL_OFFSET_HOB] = ((addr_req >>= 8) & 0xff); - args.hobRegister[IDE_SELECT_OFFSET_HOB] = 0x40; - args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80); - args.handler = task_no_data_intr; - /* submit command request */ - ide_raw_taskfile(drive, &args, NULL); - /* if OK, compute maximum address value */ - if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { - u32 high = ((args.hobRegister[IDE_HCYL_OFFSET_HOB])<<16) | - ((args.hobRegister[IDE_LCYL_OFFSET_HOB])<<8) | - (args.hobRegister[IDE_SECTOR_OFFSET_HOB]); - u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) | - ((args.tfRegister[IDE_LCYL_OFFSET])<<8) | - (args.tfRegister[IDE_SECTOR_OFFSET]); - addr_set = ((__u64)high << 24) | low; - } - return addr_set; -} - -/* - * Tests if the drive supports Host Protected Area feature. - * Returns true if supported, false otherwise. - */ -static inline int idedisk_supports_host_protected_area(ide_drive_t *drive) -{ - int flag = (drive->id->cfs_enable_1 & 0x0400) ? 1 : 0; - printk("%s: host protected area => %d\n", drive->name, flag); - return flag; -} - -#endif /* CONFIG_IDEDISK_STROKE */ - -/* - * Compute drive->capacity, the full capacity of the drive - * Called with drive->id != NULL. - * - * To compute capacity, this uses either of - * - * 1. CHS value set by user (whatever user sets will be trusted) - * 2. LBA value from target drive (require new ATA feature) - * 3. LBA value from system BIOS (new one is OK, old one may break) - * 4. CHS value from system BIOS (traditional style) - * - * in above order (i.e., if value of higher priority is available, - * reset will be ignored). - */ -static void init_idedisk_capacity (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - unsigned long capacity = drive->cyl * drive->head * drive->sect; - unsigned long set_max = idedisk_read_native_max_address(drive); - unsigned long long capacity_2 = capacity; - unsigned long long set_max_ext; - - drive->capacity48 = 0; - drive->select.b.lba = 0; - - if (id->cfs_enable_2 & 0x0400) { - capacity_2 = id->lba_capacity_2; - drive->head = drive->bios_head = 255; - drive->sect = drive->bios_sect = 63; - drive->cyl = (unsigned int) capacity_2 / (drive->head * drive->sect); - drive->select.b.lba = 1; - set_max_ext = idedisk_read_native_max_address_ext(drive); - if (set_max_ext > capacity_2) { -#ifdef CONFIG_IDEDISK_STROKE - set_max_ext = idedisk_read_native_max_address_ext(drive); - set_max_ext = idedisk_set_max_address_ext(drive, set_max_ext); - if (set_max_ext) { - drive->capacity48 = capacity_2 = set_max_ext; - drive->cyl = (unsigned int) set_max_ext / (drive->head * drive->sect); - drive->select.b.lba = 1; - drive->id->lba_capacity_2 = capacity_2; - } -#else /* !CONFIG_IDEDISK_STROKE */ - printk("%s: setmax_ext LBA %llu, native %llu\n", - drive->name, set_max_ext, capacity_2); -#endif /* CONFIG_IDEDISK_STROKE */ - } - drive->bios_cyl = drive->cyl; - drive->capacity48 = capacity_2; - drive->capacity = (unsigned long) capacity_2; - return; - /* Determine capacity, and use LBA if the drive properly supports it */ - } else if ((id->capability & 2) && lba_capacity_is_ok(id)) { - capacity = id->lba_capacity; - drive->cyl = capacity / (drive->head * drive->sect); - drive->select.b.lba = 1; - } - - if (set_max > capacity) { -#ifdef CONFIG_IDEDISK_STROKE - set_max = idedisk_read_native_max_address(drive); - set_max = idedisk_set_max_address(drive, set_max); - if (set_max) { - drive->capacity = capacity = set_max; - drive->cyl = set_max / (drive->head * drive->sect); - drive->select.b.lba = 1; - drive->id->lba_capacity = capacity; - } -#else /* !CONFIG_IDEDISK_STROKE */ - printk("%s: setmax LBA %lu, native %lu\n", - drive->name, set_max, capacity); -#endif /* CONFIG_IDEDISK_STROKE */ - } - - drive->capacity = capacity; - - if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) { - drive->capacity48 = id->lba_capacity_2; - drive->head = 255; - drive->sect = 63; - drive->cyl = (unsigned long)(drive->capacity48) / (drive->head * drive->sect); - } -} - -static unsigned long idedisk_capacity (ide_drive_t *drive) -{ - if (drive->id->cfs_enable_2 & 0x0400) - return (drive->capacity48 - drive->sect0); - return (drive->capacity - drive->sect0); -} - -static ide_startstop_t idedisk_special (ide_drive_t *drive) -{ - special_t *s = &drive->special; - - if (s->b.set_geometry) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - ide_handler_t *handler = NULL; - - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - - s->b.set_geometry = 0; - taskfile.sector_number = drive->sect; - taskfile.low_cylinder = drive->cyl; - taskfile.high_cylinder = drive->cyl>>8; - taskfile.device_head = ((drive->head-1)|drive->select.all)&0xBF; - if (!IS_PDC4030_DRIVE) { - taskfile.sector_count = drive->sect; - taskfile.command = WIN_SPECIFY; - handler = ide_handler_parser(&taskfile, &hobfile); - } - do_taskfile(drive, &taskfile, &hobfile, handler); - } else if (s->b.recalibrate) { - s->b.recalibrate = 0; - if (!IS_PDC4030_DRIVE) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.sector_count = drive->sect; - taskfile.command = WIN_RESTORE; - do_taskfile(drive, &taskfile, &hobfile, ide_handler_parser(&taskfile, &hobfile)); - } - } else if (s->b.set_multmode) { - s->b.set_multmode = 0; - if (drive->id && drive->mult_req > drive->id->max_multsect) - drive->mult_req = drive->id->max_multsect; - if (!IS_PDC4030_DRIVE) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.sector_count = drive->mult_req; - taskfile.command = WIN_SETMULT; - do_taskfile(drive, &taskfile, &hobfile, ide_handler_parser(&taskfile, &hobfile)); - } - } else if (s->all) { - int special = s->all; - s->all = 0; - printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special); - return ide_stopped; - } - return IS_PDC4030_DRIVE ? ide_stopped : ide_started; -} - -static void idedisk_pre_reset (ide_drive_t *drive) -{ - int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1; - - drive->special.all = 0; - drive->special.b.set_geometry = legacy; - drive->special.b.recalibrate = legacy; - if (OK_TO_RESET_CONTROLLER) - drive->mult_count = 0; - if (!drive->keep_settings && !drive->using_dma) - drive->mult_req = 0; - if (drive->mult_req != drive->mult_count) - drive->special.b.set_multmode = 1; -} - -#ifdef CONFIG_PROC_FS - -static int smart_enable(ide_drive_t *drive) -{ - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.feature = SMART_ENABLE; - taskfile.low_cylinder = SMART_LCYL_PASS; - taskfile.high_cylinder = SMART_HCYL_PASS; - taskfile.command = WIN_SMART; - return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); -} - -static int get_smart_values(ide_drive_t *drive, byte *buf) -{ - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.feature = SMART_READ_VALUES; - taskfile.sector_count = 0x01; - taskfile.low_cylinder = SMART_LCYL_PASS; - taskfile.high_cylinder = SMART_HCYL_PASS; - taskfile.command = WIN_SMART; - (void) smart_enable(drive); - return ide_wait_taskfile(drive, &taskfile, &hobfile, buf); -} - -static int get_smart_thresholds(ide_drive_t *drive, byte *buf) -{ - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.feature = SMART_READ_THRESHOLDS; - taskfile.sector_count = 0x01; - taskfile.low_cylinder = SMART_LCYL_PASS; - taskfile.high_cylinder = SMART_HCYL_PASS; - taskfile.command = WIN_SMART; - (void) smart_enable(drive); - return ide_wait_taskfile(drive, &taskfile, &hobfile, buf); -} - -static int proc_idedisk_read_cache - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - char *out = page; - int len; - - if (drive->id) - len = sprintf(out,"%i\n", drive->id->buf_size / 2); - else - len = sprintf(out,"(none)\n"); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static int proc_idedisk_read_smart_thresholds - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *)data; - int len = 0, i = 0; - - if (!get_smart_thresholds(drive, page)) { - unsigned short *val = (unsigned short *) page; - char *out = ((char *)val) + (SECTOR_WORDS * 4); - page = out; - do { - out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n'); - val += 1; - } while (i < (SECTOR_WORDS * 2)); - len = out - page; - } - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static int proc_idedisk_read_smart_values - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *)data; - int len = 0, i = 0; - - if (!get_smart_values(drive, page)) { - unsigned short *val = (unsigned short *) page; - char *out = ((char *)val) + (SECTOR_WORDS * 4); - page = out; - do { - out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n'); - val += 1; - } while (i < (SECTOR_WORDS * 2)); - len = out - page; - } - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static ide_proc_entry_t idedisk_proc[] = { - { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL }, - { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, - { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_smart_values, NULL }, - { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_smart_thresholds, NULL }, - { NULL, 0, NULL, NULL } -}; - -#else - -#define idedisk_proc NULL - -#endif /* CONFIG_PROC_FS */ - -static int set_multcount(ide_drive_t *drive, int arg) -{ -#ifdef __TASKFILE__IO - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - - if (drive->special.b.set_multmode) - return -EBUSY; - - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.sector_count = drive->mult_req; - taskfile.command = WIN_SETMULT; - drive->mult_req = arg; - drive->special.b.set_multmode = 1; - ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); -#else /* !__TASKFILE__IO */ - struct request rq; - - if (drive->special.b.set_multmode) - return -EBUSY; - ide_init_drive_cmd (&rq); - rq.cmd = IDE_DRIVE_CMD; - drive->mult_req = arg; - drive->special.b.set_multmode = 1; - (void) ide_do_drive_cmd (drive, &rq, ide_wait); -#endif /* __TASKFILE__IO */ - return (drive->mult_count == arg) ? 0 : -EIO; -} - -static int set_nowerr(ide_drive_t *drive, int arg) -{ - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - drive->nowerr = arg; - drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT; - spin_unlock_irq(&io_request_lock); - return 0; -} - -static int write_cache (ide_drive_t *drive, int arg) -{ - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.feature = (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE; - taskfile.command = WIN_SETFEATURES; - - if (!(drive->id->cfs_enable_2 & 0x3000)) - return 1; - - (void) ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); - drive->wcache = arg; - return 0; -} - -static int do_idedisk_standby (ide_drive_t *drive) -{ - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.command = WIN_STANDBYNOW1; - return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); -} - -static int do_idedisk_flushcache (ide_drive_t *drive) -{ - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - if (drive->id->cfs_enable_2 & 0x2400) { - taskfile.command = WIN_FLUSH_CACHE_EXT; - } else { - taskfile.command = WIN_FLUSH_CACHE; - } - return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); -} - -static int set_acoustic (ide_drive_t *drive, int arg) -{ - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - - taskfile.feature = (arg)?SETFEATURES_EN_AAM:SETFEATURES_DIS_AAM; - taskfile.sector_count = arg; - - taskfile.command = WIN_SETFEATURES; - (void) ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); - drive->acoustic = arg; - return 0; -} - -static int probe_lba_addressing (ide_drive_t *drive, int arg) -{ - drive->addressing = 0; - - if (!(drive->id->cfs_enable_2 & 0x0400)) - return -EIO; - - drive->addressing = arg; - return 0; -} - -static int set_lba_addressing (ide_drive_t *drive, int arg) -{ - return (probe_lba_addressing(drive, arg)); -} - -static void idedisk_add_settings(ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; -#if 0 - int major = HWIF(drive)->major; - int minor = drive->select.b.unit << PARTN_BITS; -#endif - - ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL); - ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); - ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); - ide_add_setting(drive, "address", SETTING_RW, HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, TYPE_INTA, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); - ide_add_setting(drive, "bswap", SETTING_READ, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL); - ide_add_setting(drive, "multcount", id ? SETTING_RW : SETTING_READ, HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, TYPE_BYTE, 0, id ? id->max_multsect : 0, 1, 1, &drive->mult_count, set_multcount); - ide_add_setting(drive, "nowerr", SETTING_RW, HDIO_GET_NOWERR, HDIO_SET_NOWERR, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); -#if 0 - ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 1, &read_ahead[major], NULL); - ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, 4096, PAGE_SIZE, 1024, &max_readahead[major][minor], NULL); - ide_add_setting(drive, "max_kb_per_request", SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 1, &max_sectors[major][minor], NULL); -#endif - ide_add_setting(drive, "lun", SETTING_RW, -1, -1, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL); - ide_add_setting(drive, "wcache", SETTING_RW, HDIO_GET_WCACHE, HDIO_SET_WCACHE, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache); - ide_add_setting(drive, "acoustic", SETTING_RW, HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic); - ide_add_setting(drive, "failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL); - ide_add_setting(drive, "max_failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); -} - -static void idedisk_setup (ide_drive_t *drive) -{ - int i; - - struct hd_driveid *id = drive->id; - unsigned long capacity; - - idedisk_add_settings(drive); - - if (id == NULL) - return; - - /* - * CompactFlash cards and their brethern look just like hard drives - * to us, but they are removable and don't have a doorlock mechanism. - */ - if (drive->removable && !drive_is_flashcard(drive)) { - /* - * Removable disks (eg. SYQUEST); ignore 'WD' drives - */ - if (id->model[0] != 'W' || id->model[1] != 'D') { - drive->doorlocking = 1; - } - } - for (i = 0; i < MAX_DRIVES; ++i) { - ide_hwif_t *hwif = HWIF(drive); - - if (drive != &hwif->drives[i]) continue; -#ifdef DEVFS_MUST_DIE - hwif->gd->de_arr[i] = drive->de; -#endif - if (drive->removable) - hwif->gd->flags[i] |= GENHD_FL_REMOVABLE; - break; - } - - /* Extract geometry if we did not already have one for the drive */ - if (!drive->cyl || !drive->head || !drive->sect) { - drive->cyl = drive->bios_cyl = id->cyls; - drive->head = drive->bios_head = id->heads; - drive->sect = drive->bios_sect = id->sectors; - } - - /* Handle logical geometry translation by the drive */ - if ((id->field_valid & 1) && id->cur_cyls && - id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) { - drive->cyl = id->cur_cyls; - drive->head = id->cur_heads; - drive->sect = id->cur_sectors; - } - - /* Use physical geometry if what we have still makes no sense */ - if (drive->head > 16 && id->heads && id->heads <= 16) { - drive->cyl = id->cyls; - drive->head = id->heads; - drive->sect = id->sectors; - } - - /* calculate drive capacity, and select LBA if possible */ - init_idedisk_capacity (drive); - - /* - * if possible, give fdisk access to more of the drive, - * by correcting bios_cyls: - */ - capacity = idedisk_capacity (drive); - if ((capacity >= (drive->bios_cyl * drive->bios_sect * drive->bios_head)) && - (!drive->forced_geom) && drive->bios_sect && drive->bios_head) - drive->bios_cyl = (capacity / drive->bios_sect) / drive->bios_head; - printk (KERN_INFO "%s: %ld sectors", drive->name, capacity); - - /* Give size in megabytes (MB), not mebibytes (MiB). */ - /* We compute the exact rounded value, avoiding overflow. */ - printk (" (%ld MB)", (capacity - capacity/625 + 974)/1950); - - /* Only print cache size when it was specified */ - if (id->buf_size) - printk (" w/%dKiB Cache", id->buf_size/2); - - printk(", CHS=%d/%d/%d", - drive->bios_cyl, drive->bios_head, drive->bios_sect); -#ifdef CONFIG_BLK_DEV_IDEDMA - if (drive->using_dma) - (void) HWIF(drive)->dmaproc(ide_dma_verbose, drive); - else -#endif /* CONFIG_BLK_DEV_IDEDMA */ - printk(" PIO (slow!)"); - printk("\n"); - - drive->mult_count = 0; - if (id->max_multsect) { -#ifdef CONFIG_IDEDISK_MULTI_MODE - id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0; - id->multsect_valid = id->multsect ? 1 : 0; - drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT; - drive->special.b.set_multmode = drive->mult_req ? 1 : 0; -#else /* original, pre IDE-NFG, per request of AC */ - drive->mult_req = INITIAL_MULT_COUNT; - if (drive->mult_req > id->max_multsect) - drive->mult_req = id->max_multsect; - if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect)) - drive->special.b.set_multmode = 1; -#endif /* CONFIG_IDEDISK_MULTI_MODE */ - } - drive->no_io_32bit = id->dword_io ? 1 : 0; - if (drive->id->cfs_enable_2 & 0x3000) - write_cache(drive, (id->cfs_enable_2 & 0x3000)); - (void) probe_lba_addressing(drive, 1); -} - -static int idedisk_cleanup (ide_drive_t *drive) -{ - if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) - if (do_idedisk_flushcache(drive)) - printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", - drive->name); - return ide_unregister_subdriver(drive); -} - -int idedisk_reinit(ide_drive_t *drive); - -/* - * IDE subdriver functions, registered with ide.c - */ -static ide_driver_t idedisk_driver = { - name: "ide-disk", - version: IDEDISK_VERSION, - media: ide_disk, - busy: 0, - supports_dma: 1, - supports_dsc_overlap: 0, - cleanup: idedisk_cleanup, - standby: do_idedisk_standby, - flushcache: do_idedisk_flushcache, - do_request: do_rw_disk, - end_request: NULL, - ioctl: NULL, - open: idedisk_open, - release: idedisk_release, - media_change: idedisk_media_change, - revalidate: idedisk_revalidate, - pre_reset: idedisk_pre_reset, - capacity: idedisk_capacity, - special: idedisk_special, - /*proc: idedisk_proc,*/ - reinit: idedisk_reinit, - ata_prebuilder: NULL, - atapi_prebuilder: NULL, -}; - -int idedisk_init (void); -static ide_module_t idedisk_module = { - IDE_DRIVER_MODULE, - idedisk_init, - &idedisk_driver, - NULL -}; - -MODULE_DESCRIPTION("ATA DISK Driver"); - -int idedisk_reinit (ide_drive_t *drive) -{ - int failed = 0; - - MOD_INC_USE_COUNT; - - if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) { - printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name); - return 1; - } - DRIVER(drive)->busy++; - idedisk_setup(drive); - if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { - printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head); - (void) idedisk_cleanup(drive); - DRIVER(drive)->busy--; - return 1; - } - DRIVER(drive)->busy--; - failed--; - - ide_register_module(&idedisk_module); - MOD_DEC_USE_COUNT; - return 0; -} - -static void __exit idedisk_exit (void) -{ - ide_drive_t *drive; - int failed = 0; - - while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL) { - if (idedisk_cleanup (drive)) { - printk (KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name); - failed++; - } - /* We must remove proc entries defined in this module. - Otherwise we oops while accessing these entries */ -#ifdef CONFIG_PROC_FS - if (drive->proc) - ide_remove_proc_entries(drive->proc, idedisk_proc); -#endif - } - ide_unregister_module(&idedisk_module); -} - -int idedisk_init (void) -{ - ide_drive_t *drive; - int failed = 0; - - MOD_INC_USE_COUNT; - while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, NULL, failed++)) != NULL) { - if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) { - printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name); - continue; - } - DRIVER(drive)->busy++; - idedisk_setup(drive); - if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { - printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head); - (void) idedisk_cleanup(drive); - DRIVER(drive)->busy--; - continue; - } - DRIVER(drive)->busy--; - failed--; - } - ide_register_module(&idedisk_module); - MOD_DEC_USE_COUNT; - return 0; -} - -module_init(idedisk_init); -module_exit(idedisk_exit); -MODULE_LICENSE("GPL"); diff --git a/xen/drivers/ide/ide-dma.c b/xen/drivers/ide/ide-dma.c deleted file mode 100644 index 80fe970284..0000000000 --- a/xen/drivers/ide/ide-dma.c +++ /dev/null @@ -1,897 +0,0 @@ -/* - * linux/drivers/ide/ide-dma.c Version 4.10 June 9, 2000 - * - * Copyright (c) 1999-2000 Andre Hedrick - * May be copied or modified under the terms of the GNU General Public License - */ - -/* - * Special Thanks to Mark for his Six years of work. - * - * Copyright (c) 1995-1998 Mark Lord - * May be copied or modified under the terms of the GNU General Public License - */ - -/* - * This module provides support for the bus-master IDE DMA functions - * of various PCI chipsets, including the Intel PIIX (i82371FB for - * the 430 FX chipset), the PIIX3 (i82371SB for the 430 HX/VX and - * 440 chipsets), and the PIIX4 (i82371AB for the 430 TX chipset) - * ("PIIX" stands for "PCI ISA IDE Xcellerator"). - * - * Pretty much the same code works for other IDE PCI bus-mastering chipsets. - * - * DMA is supported for all IDE devices (disk drives, cdroms, tapes, floppies). - * - * By default, DMA support is prepared for use, but is currently enabled only - * for drives which already have DMA enabled (UltraDMA or mode 2 multi/single), - * or which are recognized as "good" (see table below). Drives with only mode0 - * or mode1 (multi/single) DMA should also work with this chipset/driver - * (eg. MC2112A) but are not enabled by default. - * - * Use "hdparm -i" to view modes supported by a given drive. - * - * The hdparm-3.5 (or later) utility can be used for manually enabling/disabling - * DMA support, but must be (re-)compiled against this kernel version or later. - * - * To enable DMA, use "hdparm -d1 /dev/hd?" on a per-drive basis after booting. - * If problems arise, ide.c will disable DMA operation after a few retries. - * This error recovery mechanism works and has been extremely well exercised. - * - * IDE drives, depending on their vintage, may support several different modes - * of DMA operation. The boot-time modes are indicated with a "*" in - * the "hdparm -i" listing, and can be changed with *knowledgeable* use of - * the "hdparm -X" feature. There is seldom a need to do this, as drives - * normally power-up with their "best" PIO/DMA modes enabled. - * - * Testing has been done with a rather extensive number of drives, - * with Quantum & Western Digital models generally outperforming the pack, - * and Fujitsu & Conner (and some Seagate which are really Conner) drives - * showing more lackluster throughput. - * - * Keep an eye on /var/adm/messages for "DMA disabled" messages. - * - * Some people have reported trouble with Intel Zappa motherboards. - * This can be fixed by upgrading the AMI BIOS to version 1.00.04.BS0, - * available from ftp://ftp.intel.com/pub/bios/10004bs0.exe - * (thanks to Glen Morrell for researching this). - * - * Thanks to "Christopher J. Reimer" for - * fixing the problem with the BIOS on some Acer motherboards. - * - * Thanks to "Benoit Poulot-Cazajous" for testing - * "TX" chipset compatibility and for providing patches for the "TX" chipset. - * - * Thanks to Christian Brunner for taking a good first crack - * at generic DMA -- his patches were referred to when preparing this code. - * - * Most importantly, thanks to Robert Bringman - * for supplying a Promise UDMA board & WD UDMA drive for this work! - * - * And, yes, Intel Zappa boards really *do* use both PIIX IDE ports. - * - * check_drive_lists(ide_drive_t *drive, int good_bad) - * - * ATA-66/100 and recovery functions, I forgot the rest...... - * SELECT_READ_WRITE(hwif,drive,func) for active tuning based on IO direction. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* - * Long lost data from 2.0.34 that is now in 2.0.39 - * - * This was used in ./drivers/block/triton.c to do DMA Base address setup - * when PnP failed. Oh the things we forget. I believe this was part - * of SFF-8038i that has been withdrawn from public access... :-(( - */ -#define DEFAULT_BMIBA 0xe800 /* in case BIOS did not init it */ -#define DEFAULT_BMCRBA 0xcc00 /* VIA's default value */ -#define DEFAULT_BMALIBA 0xd400 /* ALI's default value */ - -extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc); - -#ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS - -struct drive_list_entry { - char * id_model; - char * id_firmware; -}; - -struct drive_list_entry drive_whitelist [] = { - - { "Micropolis 2112A" , "ALL" }, - { "CONNER CTMA 4000" , "ALL" }, - { "CONNER CTT8000-A" , "ALL" }, - { "ST34342A" , "ALL" }, - { 0 , 0 } -}; - -struct drive_list_entry drive_blacklist [] = { - - { "WDC AC11000H" , "ALL" }, - { "WDC AC22100H" , "ALL" }, - { "WDC AC31000H" , "ALL" }, - { "WDC AC32500H" , "ALL" }, - { "WDC AC33100H" , "ALL" }, - { "WDC AC31600H" , "ALL" }, - { "WDC AC32100H" , "24.09P07" }, - { "WDC AC23200L" , "21.10N21" }, - { "Compaq CRD-8241B" , "ALL" }, - { "CRD-8400B" , "ALL" }, - { "CRD-8480B", "ALL" }, - { "CRD-8480C", "ALL" }, - { "CRD-8482B", "ALL" }, - { "CRD-84" , "ALL" }, - { "SanDisk SDP3B" , "ALL" }, - { "SanDisk SDP3B-64" , "ALL" }, - { "SANYO CD-ROM CRD" , "ALL" }, - { "HITACHI CDR-8" , "ALL" }, - { "HITACHI CDR-8335" , "ALL" }, - { "HITACHI CDR-8435" , "ALL" }, - { "Toshiba CD-ROM XM-6202B" , "ALL" }, - { "CD-532E-A" , "ALL" }, - { "E-IDE CD-ROM CR-840", "ALL" }, - { "CD-ROM Drive/F5A", "ALL" }, - { "RICOH CD-R/RW MP7083A", "ALL" }, - { "WPI CDD-820", "ALL" }, - { "SAMSUNG CD-ROM SC-148C", "ALL" }, - { "SAMSUNG CD-ROM SC-148F", "ALL" }, - { "SAMSUNG CD-ROM SC", "ALL" }, - { "SanDisk SDP3B-64" , "ALL" }, - { "SAMSUNG CD-ROM SN-124", "ALL" }, - { "PLEXTOR CD-R PX-W8432T", "ALL" }, - { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" }, - { "_NEC DV5800A", "ALL" }, - { 0 , 0 } - -}; - -int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table) -{ - for ( ; drive_table->id_model ; drive_table++) - if ((!strcmp(drive_table->id_model, id->model)) && - ((!strstr(drive_table->id_firmware, id->fw_rev)) || - (!strcmp(drive_table->id_firmware, "ALL")))) - return 1; - return 0; -} - -#else /* !CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ - -/* - * good_dma_drives() lists the model names (from "hdparm -i") - * of drives which do not support mode2 DMA but which are - * known to work fine with this interface under Linux. - */ -const char *good_dma_drives[] = {"Micropolis 2112A", - "CONNER CTMA 4000", - "CONNER CTT8000-A", - "ST34342A", /* for Sun Ultra */ - NULL}; - -/* - * bad_dma_drives() lists the model names (from "hdparm -i") - * of drives which supposedly support (U)DMA but which are - * known to corrupt data with this interface under Linux. - * - * This is an empirical list. Its generated from bug reports. That means - * while it reflects actual problem distributions it doesn't answer whether - * the drive or the controller, or cabling, or software, or some combination - * thereof is the fault. If you don't happen to agree with the kernel's - * opinion of your drive - use hdparm to turn DMA on. - */ -const char *bad_dma_drives[] = {"WDC AC11000H", - "WDC AC22100H", - "WDC AC32100H", - "WDC AC32500H", - "WDC AC33100H", - "WDC AC31600H", - NULL}; - -#endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ - -/* - * Our Physical Region Descriptor (PRD) table should be large enough - * to handle the biggest I/O request we are likely to see. Since requests - * can have no more than 256 sectors, and since the typical blocksize is - * two or more sectors, we could get by with a limit of 128 entries here for - * the usual worst case. Most requests seem to include some contiguous blocks, - * further reducing the number of table entries required. - * - * The driver reverts to PIO mode for individual requests that exceed - * this limit (possible with 512 byte blocksizes, eg. MSDOS f/s), so handling - * 100% of all crazy scenarios here is not necessary. - * - * As it turns out though, we must allocate a full 4KB page for this, - * so the two PRD tables (ide0 & ide1) will each get half of that, - * allowing each to have about 256 entries (8 bytes each) from this. - */ -#define PRD_BYTES 8 -#define PRD_ENTRIES (PAGE_SIZE / (2 * PRD_BYTES)) - -/* - * dma_intr() is the handler for disk read/write DMA interrupts - */ -ide_startstop_t ide_dma_intr (ide_drive_t *drive) -{ - int i; - byte stat, dma_stat; - - dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive); - stat = GET_STAT(); /* get drive status */ - if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { - if (!dma_stat) { - struct request *rq = HWGROUP(drive)->rq; - rq = HWGROUP(drive)->rq; - for (i = rq->nr_sectors; i > 0;) { - i -= rq->current_nr_sectors; - ide_end_request(1, HWGROUP(drive)); - } - return ide_stopped; - } - printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", - drive->name, dma_stat); - } - return ide_error(drive, "dma_intr", stat); -} - -static int ide_build_sglist (ide_hwif_t *hwif, struct request *rq) -{ - struct buffer_head *bh; - struct scatterlist *sg = hwif->sg_table; - unsigned long lastdataend = ~0UL; - int nents = 0; - - if (hwif->sg_dma_active) - BUG(); - - if (rq->cmd == READ) - hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; - else - hwif->sg_dma_direction = PCI_DMA_TODEVICE; - - bh = rq->bh; - do { - struct scatterlist *sge; - - /* - * continue segment from before? - */ - if (virt_to_phys(bh->b_data) == lastdataend) { - sg[nents - 1].length += bh->b_size; - lastdataend += bh->b_size; - continue; - } - - /* - * start new segment - */ - if (nents >= PRD_ENTRIES) - return 0; - - sge = &sg[nents]; - memset(sge, 0, sizeof(*sge)); - sge->address = bh->b_data; - sge->length = bh->b_size; - lastdataend = virt_to_phys(bh->b_data) + bh->b_size; - nents++; - } while ((bh = bh->b_reqnext) != NULL); - - return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction); -} - -static int ide_raw_build_sglist (ide_hwif_t *hwif, struct request *rq) -{ - struct scatterlist *sg = hwif->sg_table; - int nents = 0; - ide_task_t *args = rq->special; - unsigned char *virt_addr = rq->buffer; - int sector_count = rq->nr_sectors; - -// if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_WRITEDMA) || -// (args->tfRegister[IDE_COMMAND_OFFSET] == WIN_WRITEDMA_EXT)) - if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) - hwif->sg_dma_direction = PCI_DMA_TODEVICE; - else - hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; - - if (sector_count > 128) { - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].address = virt_addr; - sg[nents].length = 128 * SECTOR_SIZE; - nents++; - virt_addr = virt_addr + (128 * SECTOR_SIZE); - sector_count -= 128; - } - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].address = virt_addr; - sg[nents].length = sector_count * SECTOR_SIZE; - nents++; - - return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction); -} - -/* - * ide_build_dmatable() prepares a dma request. - * Returns 0 if all went okay, returns 1 otherwise. - * May also be invoked from trm290.c - */ -int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func) -{ - unsigned int *table = HWIF(drive)->dmatable_cpu; -#ifdef CONFIG_BLK_DEV_TRM290 - unsigned int is_trm290_chipset = (HWIF(drive)->chipset == ide_trm290); -#else - const int is_trm290_chipset = 0; -#endif - unsigned int count = 0; - int i; - struct scatterlist *sg; - - if (HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) - HWIF(drive)->sg_nents = i = ide_raw_build_sglist(HWIF(drive), HWGROUP(drive)->rq); - else - HWIF(drive)->sg_nents = i = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq); - - if (!i) - return 0; - - sg = HWIF(drive)->sg_table; - while (i) { - u32 cur_addr; - u32 cur_len; - - cur_addr = sg_dma_address(sg); - cur_len = sg_dma_len(sg); - - /* - * Fill in the dma table, without crossing any 64kB boundaries. - * Most hardware requires 16-bit alignment of all blocks, - * but the trm290 requires 32-bit alignment. - */ - - while (cur_len) { - u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff); - - if (count++ >= PRD_ENTRIES) - BUG(); - - if (bcount > cur_len) - bcount = cur_len; - *table++ = cpu_to_le32(cur_addr); - xcount = bcount & 0xffff; - if (is_trm290_chipset) - xcount = ((xcount >> 2) - 1) << 16; - if (xcount == 0x0000) { - /* - * Most chipsets correctly interpret a length - * of 0x0000 as 64KB, but at least one - * (e.g. CS5530) misinterprets it as zero (!). - * So here we break the 64KB entry into two - * 32KB entries instead. - */ - if (count++ >= PRD_ENTRIES) - goto use_pio_instead; - - *table++ = cpu_to_le32(0x8000); - *table++ = cpu_to_le32(cur_addr + 0x8000); - xcount = 0x8000; - } - *table++ = cpu_to_le32(xcount); - cur_addr += bcount; - cur_len -= bcount; - } - - sg++; - i--; - } - - if (count) { - if (!is_trm290_chipset) - *--table |= cpu_to_le32(0x80000000); - return count; - } - printk("%s: empty DMA table?\n", drive->name); -use_pio_instead: - pci_unmap_sg(HWIF(drive)->pci_dev, - HWIF(drive)->sg_table, - HWIF(drive)->sg_nents, - HWIF(drive)->sg_dma_direction); - HWIF(drive)->sg_dma_active = 0; - return 0; /* revert to PIO for this request */ -} - -/* Teardown mappings after DMA has completed. */ -void ide_destroy_dmatable (ide_drive_t *drive) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - struct scatterlist *sg = HWIF(drive)->sg_table; - int nents = HWIF(drive)->sg_nents; - - pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction); - HWIF(drive)->sg_dma_active = 0; -} - -/* - * For both Blacklisted and Whitelisted drives. - * This is setup to be called as an extern for future support - * to other special driver code. - */ -int check_drive_lists (ide_drive_t *drive, int good_bad) -{ - struct hd_driveid *id = drive->id; - -#ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS - if (good_bad) { - return in_drive_list(id, drive_whitelist); - } else { - int blacklist = in_drive_list(id, drive_blacklist); - if (blacklist) - printk("%s: Disabling (U)DMA for %s\n", drive->name, id->model); - return(blacklist); - } -#else /* !CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ - const char **list; - - if (good_bad) { - /* Consult the list of known "good" drives */ - list = good_dma_drives; - while (*list) { - if (!strcmp(*list++,id->model)) - return 1; - } - } else { - /* Consult the list of known "bad" drives */ - list = bad_dma_drives; - while (*list) { - if (!strcmp(*list++,id->model)) { - printk("%s: Disabling (U)DMA for %s\n", - drive->name, id->model); - return 1; - } - } - } -#endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ - return 0; -} - -int report_drive_dmaing (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - - if ((id->field_valid & 4) && (eighty_ninty_three(drive)) && - (id->dma_ultra & (id->dma_ultra >> 14) & 3)) { - if ((id->dma_ultra >> 15) & 1) { - printk(", UDMA(mode 7)"); /* UDMA BIOS-enabled! */ - } else { - printk(", UDMA(133)"); /* UDMA BIOS-enabled! */ - } - } else if ((id->field_valid & 4) && (eighty_ninty_three(drive)) && - (id->dma_ultra & (id->dma_ultra >> 11) & 7)) { - if ((id->dma_ultra >> 13) & 1) { - printk(", UDMA(100)"); /* UDMA BIOS-enabled! */ - } else if ((id->dma_ultra >> 12) & 1) { - printk(", UDMA(66)"); /* UDMA BIOS-enabled! */ - } else { - printk(", UDMA(44)"); /* UDMA BIOS-enabled! */ - } - } else if ((id->field_valid & 4) && - (id->dma_ultra & (id->dma_ultra >> 8) & 7)) { - if ((id->dma_ultra >> 10) & 1) { - printk(", UDMA(33)"); /* UDMA BIOS-enabled! */ - } else if ((id->dma_ultra >> 9) & 1) { - printk(", UDMA(25)"); /* UDMA BIOS-enabled! */ - } else { - printk(", UDMA(16)"); /* UDMA BIOS-enabled! */ - } - } else if (id->field_valid & 4) { - printk(", (U)DMA"); /* Can be BIOS-enabled! */ - } else { - printk(", DMA"); - } - return 1; -} - -static int config_drive_for_dma (ide_drive_t *drive) -{ - int config_allows_dma = 1; - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - -#ifdef CONFIG_IDEDMA_ONLYDISK - if (drive->media != ide_disk) - config_allows_dma = 0; -#endif - - if (id && (id->capability & 1) && hwif->autodma && config_allows_dma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) - return hwif->dmaproc(ide_dma_off, drive); - - /* Enable DMA on any drive that has UltraDMA (mode 6/7/?) enabled */ - if ((id->field_valid & 4) && (eighty_ninty_three(drive))) - if ((id->dma_ultra & (id->dma_ultra >> 14) & 2)) - return hwif->dmaproc(ide_dma_on, drive); - /* Enable DMA on any drive that has UltraDMA (mode 3/4/5) enabled */ - if ((id->field_valid & 4) && (eighty_ninty_three(drive))) - if ((id->dma_ultra & (id->dma_ultra >> 11) & 7)) - return hwif->dmaproc(ide_dma_on, drive); - /* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */ - if (id->field_valid & 4) /* UltraDMA */ - if ((id->dma_ultra & (id->dma_ultra >> 8) & 7)) - return hwif->dmaproc(ide_dma_on, drive); - /* Enable DMA on any drive that has mode2 DMA (multi or single) enabled */ - if (id->field_valid & 2) /* regular DMA */ - if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404) - return hwif->dmaproc(ide_dma_on, drive); - /* Consult the list of known "good" drives */ - if (ide_dmaproc(ide_dma_good_drive, drive)) - return hwif->dmaproc(ide_dma_on, drive); - } - return hwif->dmaproc(ide_dma_off_quietly, drive); -} - -#ifndef CONFIG_BLK_DEV_IDEDMA_TIMEOUT -/* - * 1 dmaing, 2 error, 4 intr - */ -static int dma_timer_expiry (ide_drive_t *drive) -{ - byte dma_stat = inb(HWIF(drive)->dma_base+2); - -#ifdef DEBUG - printk("%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat); -#endif /* DEBUG */ - -#if 0 - HWGROUP(drive)->expiry = NULL; /* one free ride for now */ -#endif - - if (dma_stat & 2) { /* ERROR */ - byte stat = GET_STAT(); - return ide_error(drive, "dma_timer_expiry", stat); - } - if (dma_stat & 1) /* DMAing */ - return WAIT_CMD; - return 0; -} -#else /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ -static ide_startstop_t ide_dma_timeout_revovery (ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - ide_hwif_t *hwif = HWIF(drive); - int enable_dma = drive->using_dma; - unsigned long flags; - ide_startstop_t startstop; - - spin_lock_irqsave(&io_request_lock, flags); - hwgroup->handler = NULL; - del_timer(&hwgroup->timer); - spin_unlock_irqrestore(&io_request_lock, flags); - - drive->waiting_for_dma = 0; - - startstop = ide_do_reset(drive); - - if ((enable_dma) && !(drive->using_dma)) - (void) hwif->dmaproc(ide_dma_on, drive); - - return startstop; -} -#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ - -#if 0 -static inline void ide_toggle_bounce(ide_drive_t *drive, int on) -{ - dma64_addr_t addr = BLK_BOUNCE_HIGH; - - if (HWIF(drive)->no_highio || HWIF(drive)->pci_dev == NULL) - return; - - if (on && drive->media == ide_disk) { - if (!PCI_DMA_BUS_IS_PHYS) - addr = BLK_BOUNCE_ANY; - else - addr = HWIF(drive)->pci_dev->dma_mask; - } - - blk_queue_bounce_limit(&drive->queue, addr); -} -#endif - -/* - * ide_dmaproc() initiates/aborts DMA read/write operations on a drive. - * - * The caller is assumed to have selected the drive and programmed the drive's - * sector address using CHS or LBA. All that remains is to prepare for DMA - * and then issue the actual read/write DMA/PIO command to the drive. - * - * For ATAPI devices, we just prepare for DMA and return. The caller should - * then issue the packet command to the drive and call us again with - * ide_dma_begin afterwards. - * - * Returns 0 if all went well. - * Returns 1 if DMA read/write could not be started, in which case - * the caller should revert to PIO for the current request. - * May also be invoked from trm290.c - */ -int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ -// ide_hwgroup_t *hwgroup = HWGROUP(drive); - ide_hwif_t *hwif = HWIF(drive); - unsigned long dma_base = hwif->dma_base; - byte unit = (drive->select.b.unit & 0x01); - unsigned int count, reading = 0/*, set_high = 1*/; - byte dma_stat; - - switch (func) { - case ide_dma_off: - printk("%s: DMA disabled\n", drive->name); - case ide_dma_off_quietly: - /*set_high = 0;*/ - outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); - case ide_dma_on: - drive->using_dma = (func == ide_dma_on); - if (drive->using_dma) - outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); - /*ide_toggle_bounce(drive, set_high);*/ - return 0; - case ide_dma_check: - return config_drive_for_dma (drive); - case ide_dma_read: - reading = 1 << 3; - case ide_dma_write: - SELECT_READ_WRITE(hwif,drive,func); - if (!(count = ide_build_dmatable(drive, func))) - return 1; /* try PIO instead of DMA */ - outl(hwif->dmatable_dma, dma_base + 4); /* PRD table */ - outb(reading, dma_base); /* specify r/w */ - outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ - drive->waiting_for_dma = 1; - if (drive->media != ide_disk) - return 0; -#ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT - ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, NULL); /* issue cmd to drive */ -#else /* !CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, dma_timer_expiry); /* issue cmd to drive */ -#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ - if ((HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) && - (drive->addressing == 1)) { - ide_task_t *args = HWGROUP(drive)->rq->special; - OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); - } else if (drive->addressing) { - OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); - } else { - OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); - } - return HWIF(drive)->dmaproc(ide_dma_begin, drive); - case ide_dma_begin: - /* Note that this is done *after* the cmd has - * been issued to the drive, as per the BM-IDE spec. - * The Promise Ultra33 doesn't work correctly when - * we do this part before issuing the drive cmd. - */ - outb(inb(dma_base)|1, dma_base); /* start DMA */ - return 0; - case ide_dma_end: /* returns 1 on error, 0 otherwise */ - drive->waiting_for_dma = 0; - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - ide_destroy_dmatable(drive); /* purge DMA mappings */ - return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */ - case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ - dma_stat = inb(dma_base+2); -#if 0 /* do not set unless you know what you are doing */ - if (dma_stat & 4) { - byte stat = GET_STAT(); - outb(dma_base+2, dma_stat & 0xE4); - } -#endif - return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ - case ide_dma_bad_drive: - case ide_dma_good_drive: - return check_drive_lists(drive, (func == ide_dma_good_drive)); - case ide_dma_verbose: - return report_drive_dmaing(drive); - case ide_dma_timeout: - // FIXME: Many IDE chipsets do not permit command file register access - // FIXME: while the bus-master function is still active. - // FIXME: To prevent deadlock with those chipsets, we must be extremely - // FIXME: careful here (and in ide_intr() as well) to NOT access any - // FIXME: registers from the 0x1Fx/0x17x sets before terminating the - // FIXME: bus-master operation via the bus-master control reg. - // FIXME: Otherwise, chipset deadlock will occur, and some systems will - // FIXME: lock up completely!! -#ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT - /* - * Have to issue an abort and requeue the request - * DMA engine got turned off by a goofy ASIC, and - * we have to clean up the mess, and here is as good - * as any. Do it globally for all chipsets. - */ - outb(0x00, dma_base); /* stop DMA */ - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - printk("%s: %s: Lets do it again!" \ - "stat = 0x%02x, dma_stat = 0x%02x\n", - drive->name, ide_dmafunc_verbose(func), - GET_STAT(), dma_stat); - - if (dma_stat & 0xF0) - return ide_dma_timeout_revovery(drive); - - printk("%s: %s: (restart_request) Lets do it again!" \ - "stat = 0x%02x, dma_stat = 0x%02x\n", - drive->name, ide_dmafunc_verbose(func), - GET_STAT(), dma_stat); - - return restart_request(drive); // BUG: return types do not match!! -//#else -// return HWGROUP(drive)->handler(drive); -#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ - case ide_dma_retune: - case ide_dma_lostirq: - printk("ide_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func), func); - return 1; - default: - printk("ide_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func); - return 1; - } -} - -/* - * Needed for allowing full modular support of ide-driver - */ -int ide_release_dma (ide_hwif_t *hwif) -{ - if (hwif->dmatable_cpu) { - pci_free_consistent(hwif->pci_dev, - PRD_ENTRIES * PRD_BYTES, - hwif->dmatable_cpu, - hwif->dmatable_dma); - hwif->dmatable_cpu = NULL; - } - if (hwif->sg_table) { - kfree(hwif->sg_table); - hwif->sg_table = NULL; - } - if ((hwif->dma_extra) && (hwif->channel == 0)) - release_region((hwif->dma_base + 16), hwif->dma_extra); - release_region(hwif->dma_base, 8); - return 1; -} - -/* - * This can be called for a dynamically installed interface. Don't __init it - */ - -void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports) -{ - printk(" %s: BM-DMA at 0x%04lx-0x%04lx", hwif->name, dma_base, dma_base + num_ports - 1); - if (check_region(dma_base, num_ports)) { - printk(" -- ERROR, PORT ADDRESSES ALREADY IN USE\n"); - return; - } - request_region(dma_base, num_ports, hwif->name); - hwif->dma_base = dma_base; - hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev, - PRD_ENTRIES * PRD_BYTES, - &hwif->dmatable_dma); - if (hwif->dmatable_cpu == NULL) - goto dma_alloc_failure; - - hwif->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES, - GFP_KERNEL); - if (hwif->sg_table == NULL) { - pci_free_consistent(hwif->pci_dev, PRD_ENTRIES * PRD_BYTES, - hwif->dmatable_cpu, hwif->dmatable_dma); - goto dma_alloc_failure; - } - - hwif->dmaproc = &ide_dmaproc; - - if (hwif->chipset != ide_trm290) { - byte dma_stat = inb(dma_base+2); - printk(", BIOS settings: %s:%s, %s:%s", - hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio", - hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio"); - } - printk("\n"); - return; - -dma_alloc_failure: - printk(" -- ERROR, UNABLE TO ALLOCATE DMA TABLES\n"); -} - -/* - * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space: - */ -unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) -{ - unsigned long dma_base = 0; - struct pci_dev *dev = hwif->pci_dev; - -#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED - int second_chance = 0; - -second_chance_to_dma: -#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */ - - if (hwif->mate && hwif->mate->dma_base) { - dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8); - } else { - dma_base = pci_resource_start(dev, 4); - if (!dma_base) { - printk("%s: dma_base is invalid (0x%04lx)\n", name, dma_base); - dma_base = 0; - } - } - -#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED - if ((!dma_base) && (!second_chance)) { - unsigned long set_bmiba = 0; - second_chance++; - switch(dev->vendor) { - case PCI_VENDOR_ID_AL: - set_bmiba = DEFAULT_BMALIBA; break; - case PCI_VENDOR_ID_VIA: - set_bmiba = DEFAULT_BMCRBA; break; - case PCI_VENDOR_ID_INTEL: - set_bmiba = DEFAULT_BMIBA; break; - default: - return dma_base; - } - pci_write_config_dword(dev, 0x20, set_bmiba|1); - goto second_chance_to_dma; - } -#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */ - - if (dma_base) { - if (extra) /* PDC20246, PDC20262, HPT343, & HPT366 */ - request_region(dma_base+16, extra, name); - dma_base += hwif->channel ? 8 : 0; - hwif->dma_extra = extra; - - switch(dev->device) { - case PCI_DEVICE_ID_AL_M5219: - case PCI_DEVICE_ID_AMD_VIPER_7409: - case PCI_DEVICE_ID_CMD_643: - outb(inb(dma_base+2) & 0x60, dma_base+2); - if (inb(dma_base+2) & 0x80) { - printk("%s: simplex device: DMA forced\n", name); - } - break; - default: - /* - * If the device claims "simplex" DMA, - * this means only one of the two interfaces - * can be trusted with DMA at any point in time. - * So we should enable DMA only on one of the - * two interfaces. - */ - if ((inb(dma_base+2) & 0x80)) { /* simplex device? */ - if ((!hwif->drives[0].present && !hwif->drives[1].present) || - (hwif->mate && hwif->mate->dma_base)) { - printk("%s: simplex device: DMA disabled\n", name); - dma_base = 0; - } - } - } - } - return dma_base; -} diff --git a/xen/drivers/ide/ide-features.c b/xen/drivers/ide/ide-features.c deleted file mode 100644 index 97c7b1c403..0000000000 --- a/xen/drivers/ide/ide-features.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * linux/drivers/block/ide-features.c Version 0.04 June 9, 2000 - * - * Copyright (C) 1999-2000 Linus Torvalds & authors (see below) - * - * Copyright (C) 1999-2000 Andre Hedrick - * - * Extracts if ide.c to address the evolving transfer rate code for - * the SETFEATURES_XFER callouts. Various parts of any given function - * are credited to previous ATA-IDE maintainers. - * - * Auto-CRC downgrade for Ultra DMA(ing) - * - * May be copied or modified under the terms of the GNU General Public License - */ - -#include -#define __NO_VERSION__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * A Verbose noise maker for debugging on the attempted transfer rates. - */ -char *ide_xfer_verbose (byte xfer_rate) -{ - switch(xfer_rate) { - case XFER_UDMA_7: return("UDMA 7"); - case XFER_UDMA_6: return("UDMA 6"); - case XFER_UDMA_5: return("UDMA 5"); - case XFER_UDMA_4: return("UDMA 4"); - case XFER_UDMA_3: return("UDMA 3"); - case XFER_UDMA_2: return("UDMA 2"); - case XFER_UDMA_1: return("UDMA 1"); - case XFER_UDMA_0: return("UDMA 0"); - case XFER_MW_DMA_2: return("MW DMA 2"); - case XFER_MW_DMA_1: return("MW DMA 1"); - case XFER_MW_DMA_0: return("MW DMA 0"); - case XFER_SW_DMA_2: return("SW DMA 2"); - case XFER_SW_DMA_1: return("SW DMA 1"); - case XFER_SW_DMA_0: return("SW DMA 0"); - case XFER_PIO_4: return("PIO 4"); - case XFER_PIO_3: return("PIO 3"); - case XFER_PIO_2: return("PIO 2"); - case XFER_PIO_1: return("PIO 1"); - case XFER_PIO_0: return("PIO 0"); - case XFER_PIO_SLOW: return("PIO SLOW"); - default: return("XFER ERROR"); - } -} - -/* - * - */ -char *ide_media_verbose (ide_drive_t *drive) -{ - switch (drive->media) { - case ide_scsi: return("scsi "); - case ide_disk: return("disk "); - case ide_optical: return("optical"); - case ide_cdrom: return("cdrom "); - case ide_tape: return("tape "); - case ide_floppy: return("floppy "); - default: return("???????"); - } -} - -/* - * A Verbose noise maker for debugging on the attempted dmaing calls. - */ -char *ide_dmafunc_verbose (ide_dma_action_t dmafunc) -{ - switch (dmafunc) { - case ide_dma_read: return("ide_dma_read"); - case ide_dma_write: return("ide_dma_write"); - case ide_dma_begin: return("ide_dma_begin"); - case ide_dma_end: return("ide_dma_end:"); - case ide_dma_check: return("ide_dma_check"); - case ide_dma_on: return("ide_dma_on"); - case ide_dma_off: return("ide_dma_off"); - case ide_dma_off_quietly: return("ide_dma_off_quietly"); - case ide_dma_test_irq: return("ide_dma_test_irq"); - case ide_dma_bad_drive: return("ide_dma_bad_drive"); - case ide_dma_good_drive: return("ide_dma_good_drive"); - case ide_dma_verbose: return("ide_dma_verbose"); - case ide_dma_retune: return("ide_dma_retune"); - case ide_dma_lostirq: return("ide_dma_lostirq"); - case ide_dma_timeout: return("ide_dma_timeout"); - default: return("unknown"); - } -} - -/* - * - */ -byte ide_auto_reduce_xfer (ide_drive_t *drive) -{ - if (!drive->crc_count) - return drive->current_speed; - drive->crc_count = 0; - - switch(drive->current_speed) { - case XFER_UDMA_7: return XFER_UDMA_6; - case XFER_UDMA_6: return XFER_UDMA_5; - case XFER_UDMA_5: return XFER_UDMA_4; - case XFER_UDMA_4: return XFER_UDMA_3; - case XFER_UDMA_3: return XFER_UDMA_2; - case XFER_UDMA_2: return XFER_UDMA_1; - case XFER_UDMA_1: return XFER_UDMA_0; - /* - * OOPS we do not goto non Ultra DMA modes - * without iCRC's available we force - * the system to PIO and make the user - * invoke the ATA-1 ATA-2 DMA modes. - */ - case XFER_UDMA_0: - default: return XFER_PIO_4; - } -} - -/* - * Update the - */ -int ide_driveid_update (ide_drive_t *drive) -{ - /* - * Re-read drive->id for possible DMA mode - * change (copied from ide-probe.c) - */ - struct hd_driveid *id; - unsigned long timeout, flags; - - SELECT_MASK(HWIF(drive), drive, 1); - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); - ide_delay_50ms(); - OUT_BYTE(WIN_IDENTIFY, IDE_COMMAND_REG); - timeout = jiffies + WAIT_WORSTCASE; - do { - if (0 < (signed long)(jiffies - timeout)) { - SELECT_MASK(HWIF(drive), drive, 0); - return 0; /* drive timed-out */ - } - ide_delay_50ms(); /* give drive a breather */ - } while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT); - ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */ - if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) { - SELECT_MASK(HWIF(drive), drive, 0); - printk("%s: CHECK for good STATUS\n", drive->name); - return 0; - } - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only; some systems need this */ - SELECT_MASK(HWIF(drive), drive, 0); - id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); - if (!id) { - __restore_flags(flags); /* local CPU only */ - return 0; - } - ide_input_data(drive, id, SECTOR_WORDS); - (void) GET_STAT(); /* clear drive IRQ */ - ide__sti(); /* local CPU only */ - __restore_flags(flags); /* local CPU only */ - ide_fix_driveid(id); - if (id) { - drive->id->dma_ultra = id->dma_ultra; - drive->id->dma_mword = id->dma_mword; - drive->id->dma_1word = id->dma_1word; - /* anything more ? */ - kfree(id); - } - - return 1; -} - -/* - * Verify that we are doing an approved SETFEATURES_XFER with respect - * to the hardware being able to support request. Since some hardware - * can improperly report capabilties, we check to see if the host adapter - * in combination with the device (usually a disk) properly detect - * and acknowledge each end of the ribbon. - */ -int ide_ata66_check (ide_drive_t *drive, ide_task_t *args) -{ - if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && - (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) && - (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) { - if (!HWIF(drive)->udma_four) { - printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", HWIF(drive)->name); - return 1; - } -#ifndef CONFIG_IDEDMA_IVB - if ((drive->id->hw_config & 0x6000) == 0) { -#else /* !CONFIG_IDEDMA_IVB */ - if (((drive->id->hw_config & 0x2000) == 0) || - ((drive->id->hw_config & 0x4000) == 0)) { -#endif /* CONFIG_IDEDMA_IVB */ - printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", drive->name); - return 1; - } - } - return 0; -} - -/* - * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER. - * 1 : Safe to update drive->id DMA registers. - * 0 : OOPs not allowed. - */ -int set_transfer (ide_drive_t *drive, ide_task_t *args) -{ - if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && - (args->tfRegister[IDE_SECTOR_OFFSET] >= XFER_SW_DMA_0) && - (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER) && - (drive->id->dma_ultra || - drive->id->dma_mword || - drive->id->dma_1word)) - return 1; - - return 0; -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -/* - * All hosts that use the 80c ribbon mus use! - */ -byte eighty_ninty_three (ide_drive_t *drive) -{ -#ifdef CONFIG_BLK_DEV_IDEPCI - if (HWIF(drive)->pci_devid.vid==0x105a) - return(HWIF(drive)->udma_four); -#endif - /* PDC202XX: that's because some HDD will return wrong info */ - return ((byte) ((HWIF(drive)->udma_four) && -#ifndef CONFIG_IDEDMA_IVB - (drive->id->hw_config & 0x4000) && -#endif /* CONFIG_IDEDMA_IVB */ - (drive->id->hw_config & 0x6000)) ? 1 : 0); -} -#endif // CONFIG_BLK_DEV_IDEDMA - -/* - * Similar to ide_wait_stat(), except it never calls ide_error internally. - * This is a kludge to handle the new ide_config_drive_speed() function, - * and should not otherwise be used anywhere. Eventually, the tuneproc's - * should be updated to return ide_startstop_t, in which case we can get - * rid of this abomination again. :) -ml - * - * It is gone.......... - * - * const char *msg == consider adding for verbose errors. - */ -int ide_config_drive_speed (ide_drive_t *drive, byte speed) -{ - ide_hwif_t *hwif = HWIF(drive); - int i, error = 1; - byte stat; - -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) - byte unit = (drive->select.b.unit & 0x01); - outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2); -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ - - /* - * Don't use ide_wait_cmd here - it will - * attempt to set_geometry and recalibrate, - * but for some reason these don't work at - * this point (lost interrupt). - */ - /* - * Select the drive, and issue the SETFEATURES command - */ - disable_irq(hwif->irq); /* disable_irq_nosync ?? */ - udelay(1); - SELECT_DRIVE(HWIF(drive), drive); - SELECT_MASK(HWIF(drive), drive, 0); - udelay(1); - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG); - OUT_BYTE(speed, IDE_NSECTOR_REG); - OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); - OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); - if ((IDE_CONTROL_REG) && (drive->quirk_list == 2)) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); - udelay(1); - /* - * Wait for drive to become non-BUSY - */ - if ((stat = GET_STAT()) & BUSY_STAT) { - unsigned long flags, timeout; - __save_flags(flags); /* local CPU only */ - ide__sti(); /* local CPU only -- for jiffies */ - timeout = jiffies + WAIT_CMD; - while ((stat = GET_STAT()) & BUSY_STAT) { - if (0 < (signed long)(jiffies - timeout)) - break; - } - __restore_flags(flags); /* local CPU only */ - } - - /* - * Allow status to settle, then read it again. - * A few rare drives vastly violate the 400ns spec here, - * so we'll wait up to 10usec for a "good" status - * rather than expensively fail things immediately. - * This fix courtesy of Matthew Faupel & Niccolo Rigacci. - */ - for (i = 0; i < 10; i++) { - udelay(1); - if (OK_STAT((stat = GET_STAT()), DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT)) { - error = 0; - break; - } - } - - SELECT_MASK(HWIF(drive), drive, 0); - - enable_irq(hwif->irq); - - if (error) { - (void) ide_dump_status(drive, "set_drive_speed_status", stat); - return error; - } - - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) - if (speed > XFER_PIO_4) { - outb(inb(hwif->dma_base+2)|(1<<(5+unit)), hwif->dma_base+2); - } else { - outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2); - } -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ - - switch(speed) { - case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; - case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break; - case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break; - case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break; - case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break; - case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break; - case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break; - case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break; - case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break; - case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break; - case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break; - case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break; - case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break; - case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break; - default: break; - } - return error; -} - -EXPORT_SYMBOL(ide_auto_reduce_xfer); -EXPORT_SYMBOL(ide_driveid_update); -EXPORT_SYMBOL(ide_ata66_check); -EXPORT_SYMBOL(set_transfer); -#ifdef CONFIG_BLK_DEV_IDEDMA -EXPORT_SYMBOL(eighty_ninty_three); -#endif // CONFIG_BLK_DEV_IDEDMA -EXPORT_SYMBOL(ide_config_drive_speed); - diff --git a/xen/drivers/ide/ide-geometry.c b/xen/drivers/ide/ide-geometry.c deleted file mode 100644 index 1413d26fdc..0000000000 --- a/xen/drivers/ide/ide-geometry.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * linux/drivers/ide/ide-geometry.c - */ -#include -#include -#include -#include - -#ifdef CONFIG_BLK_DEV_IDE - -/* - * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc - * controller that is BIOS compatible with ST-506, and thus showing up in our - * BIOS table, but not register compatible, and therefore not present in CMOS. - * - * Furthermore, we will assume that our ST-506 drives are the primary - * drives in the system -- the ones reflected as drive 1 or 2. The first - * drive is stored in the high nibble of CMOS byte 0x12, the second in the low - * nibble. This will be either a 4 bit drive type or 0xf indicating use byte - * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. A non-zero value - * means we have an AT controller hard disk for that drive. - * - * Of course, there is no guarantee that either drive is actually on the - * "primary" IDE interface, but we don't bother trying to sort that out here. - * If a drive is not actually on the primary interface, then these parameters - * will be ignored. This results in the user having to supply the logical - * drive geometry as a boot parameter for each drive not on the primary i/f. - */ -/* - * The only "perfect" way to handle this would be to modify the setup.[cS] code - * to do BIOS calls Int13h/Fn08h and Int13h/Fn48h to get all of the drive info - * for us during initialization. I have the necessary docs -- any takers? -ml - */ -/* - * I did this, but it doesnt work - there is no reasonable way to find the - * correspondence between the BIOS numbering of the disks and the Linux - * numbering. -aeb - * - * The code below is bad. One of the problems is that drives 1 and 2 - * may be SCSI disks (even when IDE disks are present), so that - * the geometry we read here from BIOS is attributed to the wrong disks. - * Consequently, also the former "drive->present = 1" below was a mistake. - * - * Eventually the entire routine below should be removed. - * - * 17-OCT-2000 rjohnson@analogic.com Added spin-locks for reading CMOS - * chip. - */ - -void probe_cmos_for_drives (ide_hwif_t *hwif) -{ -#ifdef __i386__ - extern struct drive_info_struct drive_info; - byte cmos_disks, *BIOS = (byte *) &drive_info; - int unit; - unsigned long flags; - -#ifdef CONFIG_BLK_DEV_PDC4030 - if (hwif->chipset == ide_pdc4030 && hwif->channel != 0) - return; -#endif /* CONFIG_BLK_DEV_PDC4030 */ - spin_lock_irqsave(&rtc_lock, flags); - cmos_disks = CMOS_READ(0x12); - spin_unlock_irqrestore(&rtc_lock, flags); - /* Extract drive geometry from CMOS+BIOS if not already setup */ - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - if ((cmos_disks & (0xf0 >> (unit*4))) - && !drive->present && !drive->nobios) { - unsigned short cyl = *(unsigned short *)BIOS; - unsigned char head = *(BIOS+2); - unsigned char sect = *(BIOS+14); - if (cyl > 0 && head > 0 && sect > 0 && sect < 64) { - drive->cyl = drive->bios_cyl = cyl; - drive->head = drive->bios_head = head; - drive->sect = drive->bios_sect = sect; - drive->ctl = *(BIOS+8); - } else { - printk("hd%c: C/H/S=%d/%d/%d from BIOS ignored\n", - unit+'a', cyl, head, sect); - } - } - BIOS += 16; - } -#endif -} -#endif /* CONFIG_BLK_DEV_IDE */ - - -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) - -/* - * If heads is nonzero: find a translation with this many heads and S=63. - * Otherwise: find out how OnTrack Disk Manager would translate the disk. - */ -static void -ontrack(ide_drive_t *drive, int heads, unsigned int *c, int *h, int *s) { - static const byte dm_head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0}; - const byte *headp = dm_head_vals; - unsigned long total; - - /* - * The specs say: take geometry as obtained from Identify, - * compute total capacity C*H*S from that, and truncate to - * 1024*255*63. Now take S=63, H the first in the sequence - * 4, 8, 16, 32, 64, 128, 255 such that 63*H*1024 >= total. - * [Please tell aeb@cwi.nl in case this computes a - * geometry different from what OnTrack uses.] - */ - total = DRIVER(drive)->capacity(drive); - - *s = 63; - - if (heads) { - *h = heads; - *c = total / (63 * heads); - return; - } - - while (63 * headp[0] * 1024 < total && headp[1] != 0) - headp++; - *h = headp[0]; - *c = total / (63 * headp[0]); -} - -/* - * This routine is called from the partition-table code in pt/msdos.c. - * It has two tasks: - * (i) to handle Ontrack DiskManager by offsetting everything by 63 sectors, - * or to handle EZdrive by remapping sector 0 to sector 1. - * (ii) to invent a translated geometry. - * Part (i) is suppressed if the user specifies the "noremap" option - * on the command line. - * Part (ii) is suppressed if the user specifies an explicit geometry. - * - * The ptheads parameter is either 0 or tells about the number of - * heads shown by the end of the first nonempty partition. - * If this is either 16, 32, 64, 128, 240 or 255 we'll believe it. - * - * The xparm parameter has the following meaning: - * 0 = convert to CHS with fewer than 1024 cyls - * using the same method as Ontrack DiskManager. - * 1 = same as "0", plus offset everything by 63 sectors. - * -1 = similar to "0", plus redirect sector 0 to sector 1. - * 2 = convert to a CHS geometry with "ptheads" heads. - * - * Returns 0 if the translation was not possible, if the device was not - * an IDE disk drive, or if a geometry was "forced" on the commandline. - * Returns 1 if the geometry translation was successful. - */ -int ide_xlate_1024 (kdev_t i_rdev, int xparm, int ptheads, const char *msg) -{ - ide_drive_t *drive; - const char *msg1 = ""; - int heads = 0; - int c, h, s; - int transl = 1; /* try translation */ - int ret = 0; - - drive = get_info_ptr(i_rdev); - if (!drive) - return 0; - - /* remap? */ - if (drive->remap_0_to_1 != 2) { - if (xparm == 1) { /* DM */ - drive->sect0 = 63; - msg1 = " [remap +63]"; - ret = 1; - } else if (xparm == -1) { /* EZ-Drive */ - if (drive->remap_0_to_1 == 0) { - drive->remap_0_to_1 = 1; - msg1 = " [remap 0->1]"; - ret = 1; - } - } - } - - /* There used to be code here that assigned drive->id->CHS - to drive->CHS and that to drive->bios_CHS. However, - some disks have id->C/H/S = 4092/16/63 but are larger than 2.1 GB. - In such cases that code was wrong. Moreover, - there seems to be no reason to do any of these things. */ - - /* translate? */ - if (drive->forced_geom) - transl = 0; - - /* does ptheads look reasonable? */ - if (ptheads == 32 || ptheads == 64 || ptheads == 128 || - ptheads == 240 || ptheads == 255) - heads = ptheads; - - if (xparm == 2) { - if (!heads || - (drive->bios_head >= heads && drive->bios_sect == 63)) - transl = 0; - } - if (xparm == -1) { - if (drive->bios_head > 16) - transl = 0; /* we already have a translation */ - } - - if (transl) { - ontrack(drive, heads, &c, &h, &s); - drive->bios_cyl = c; - drive->bios_head = h; - drive->bios_sect = s; - ret = 1; - } - - drive->part[0].nr_sects = current_capacity(drive); - - if (ret) - printk("%s%s [%d/%d/%d]", msg, msg1, - drive->bios_cyl, drive->bios_head, drive->bios_sect); - return ret; -} -#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */ diff --git a/xen/drivers/ide/ide-pci.c b/xen/drivers/ide/ide-pci.c deleted file mode 100644 index 3196a37949..0000000000 --- a/xen/drivers/ide/ide-pci.c +++ /dev/null @@ -1,1016 +0,0 @@ -/* - * linux/drivers/ide/ide-pci.c Version 1.05 June 9, 2000 - * - * Copyright (c) 1998-2000 Andre Hedrick - * - * Copyright (c) 1995-1998 Mark Lord - * May be copied or modified under the terms of the GNU General Public License - */ - -/* - * This module provides support for automatic detection and - * configuration of all PCI IDE interfaces present in a system. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define DEVID_PIIXa ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0}) -#define DEVID_PIIXb ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1}) -#define DEVID_MPIIX ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX}) -#define DEVID_PIIX3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1}) -#define DEVID_PIIX4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB}) -#define DEVID_ICH0 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1}) -#define DEVID_PIIX4E2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_1}) -#define DEVID_ICH ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1}) -#define DEVID_PIIX4U2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1}) -#define DEVID_PIIX4NX ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX}) -#define DEVID_ICH2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_9}) -#define DEVID_ICH2M ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_8}) -#define DEVID_ICH3M ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10}) -#define DEVID_ICH3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11}) -#define DEVID_ICH4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_11}) -#define DEVID_CICH ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11}) -#define DEVID_VIA_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561}) -#define DEVID_MR_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1}) -#define DEVID_VP_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1}) -#define DEVID_PDC20246 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246}) -#define DEVID_PDC20262 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262}) -#define DEVID_PDC20265 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265}) -#define DEVID_PDC20267 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267}) -#define DEVID_PDC20268 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268}) -#define DEVID_PDC20270 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20270}) -#define DEVID_PDC20269 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269}) -#define DEVID_PDC20275 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275}) -#define DEVID_PDC20276 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20276}) -#define DEVID_RZ1000 ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000}) -#define DEVID_RZ1001 ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001}) -#define DEVID_SAMURAI ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE}) -#define DEVID_CMD640 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_640}) -#define DEVID_CMD643 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_643}) -#define DEVID_CMD646 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646}) -#define DEVID_CMD648 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_648}) -#define DEVID_CMD649 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_649}) -#define DEVID_CMD680 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680}) -#define DEVID_SIS5513 ((ide_pci_devid_t){PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513}) -#define DEVID_OPTI621 ((ide_pci_devid_t){PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621}) -#define DEVID_OPTI621V ((ide_pci_devid_t){PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558}) -#define DEVID_OPTI621X ((ide_pci_devid_t){PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C825}) -#define DEVID_TRM290 ((ide_pci_devid_t){PCI_VENDOR_ID_TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290}) -#define DEVID_NS87410 ((ide_pci_devid_t){PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410}) -#define DEVID_NS87415 ((ide_pci_devid_t){PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415}) -#define DEVID_HT6565 ((ide_pci_devid_t){PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565}) -#define DEVID_AEC6210 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF}) -#define DEVID_AEC6260 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860}) -#define DEVID_AEC6260R ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R}) -#define DEVID_W82C105 ((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105}) -#define DEVID_UM8673F ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F}) -#define DEVID_UM8886A ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A}) -#define DEVID_UM8886BF ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF}) -#define DEVID_HPT34X ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343}) -#define DEVID_HPT366 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366}) -#define DEVID_ALI15X3 ((ide_pci_devid_t){PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229}) -#define DEVID_CY82C693 ((ide_pci_devid_t){PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693}) -#define DEVID_HINT ((ide_pci_devid_t){0x3388, 0x8013}) -#define DEVID_CS5530 ((ide_pci_devid_t){PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE}) -#define DEVID_AMD7401 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_COBRA_7401}) -#define DEVID_AMD7409 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409}) -#define DEVID_AMD7411 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411}) -#define DEVID_AMD7441 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7441}) -#define DEVID_PDCADMA ((ide_pci_devid_t){PCI_VENDOR_ID_PDC, PCI_DEVICE_ID_PDC_ADMA100}) -#define DEVID_SLC90E66 ((ide_pci_devid_t){PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1}) -#define DEVID_OSB4 ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE}) -#define DEVID_CSB5 ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE}) -#define DEVID_ITE8172G ((ide_pci_devid_t){PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8172G}) - -#define IDE_IGNORE ((void *)-1) -#define IDE_NO_DRIVER ((void *)-2) - -#ifdef CONFIG_BLK_DEV_AEC62XX -extern unsigned int pci_init_aec62xx(struct pci_dev *, const char *); -extern unsigned int ata66_aec62xx(ide_hwif_t *); -extern void ide_init_aec62xx(ide_hwif_t *); -extern void ide_dmacapable_aec62xx(ide_hwif_t *, unsigned long); -#define PCI_AEC62XX &pci_init_aec62xx -#define ATA66_AEC62XX &ata66_aec62xx -#define INIT_AEC62XX &ide_init_aec62xx -#define DMA_AEC62XX &ide_dmacapable_aec62xx -#else -#define PCI_AEC62XX NULL -#define ATA66_AEC62XX NULL -#define INIT_AEC62XX IDE_NO_DRIVER -#define DMA_AEC62XX NULL -#endif - -#ifdef CONFIG_BLK_DEV_ALI15X3 -extern unsigned int pci_init_ali15x3(struct pci_dev *, const char *); -extern unsigned int ata66_ali15x3(ide_hwif_t *); -extern void ide_init_ali15x3(ide_hwif_t *); -extern void ide_dmacapable_ali15x3(ide_hwif_t *, unsigned long); -#define PCI_ALI15X3 &pci_init_ali15x3 -#define ATA66_ALI15X3 &ata66_ali15x3 -#define INIT_ALI15X3 &ide_init_ali15x3 -#define DMA_ALI15X3 &ide_dmacapable_ali15x3 -#else -#define PCI_ALI15X3 NULL -#define ATA66_ALI15X3 NULL -#define INIT_ALI15X3 IDE_NO_DRIVER -#define DMA_ALI15X3 NULL -#endif - -#ifdef CONFIG_BLK_DEV_AMD74XX -extern unsigned int pci_init_amd74xx(struct pci_dev *, const char *); -extern unsigned int ata66_amd74xx(ide_hwif_t *); -extern void ide_init_amd74xx(ide_hwif_t *); -extern void ide_dmacapable_amd74xx(ide_hwif_t *, unsigned long); -#define PCI_AMD74XX &pci_init_amd74xx -#define ATA66_AMD74XX &ata66_amd74xx -#define INIT_AMD74XX &ide_init_amd74xx -#define DMA_AMD74XX &ide_dmacapable_amd74xx -#else -#define PCI_AMD74XX NULL -#define ATA66_AMD74XX NULL -#define INIT_AMD74XX IDE_NO_DRIVER -#define DMA_AMD74XX NULL -#endif - -#ifdef CONFIG_BLK_DEV_CMD64X -extern unsigned int pci_init_cmd64x(struct pci_dev *, const char *); -extern unsigned int ata66_cmd64x(ide_hwif_t *); -extern void ide_init_cmd64x(ide_hwif_t *); -extern void ide_dmacapable_cmd64x(ide_hwif_t *, unsigned long); -#define PCI_CMD64X &pci_init_cmd64x -#define ATA66_CMD64X &ata66_cmd64x -#define INIT_CMD64X &ide_init_cmd64x -#else -#define PCI_CMD64X NULL -#define ATA66_CMD64X NULL -#ifdef __sparc_v9__ -#define INIT_CMD64X IDE_IGNORE -#else -#define INIT_CMD64X IDE_NO_DRIVER -#endif -#endif - -#ifdef CONFIG_BLK_DEV_CY82C693 -extern unsigned int pci_init_cy82c693(struct pci_dev *, const char *); -extern void ide_init_cy82c693(ide_hwif_t *); -#define PCI_CY82C693 &pci_init_cy82c693 -#define INIT_CY82C693 &ide_init_cy82c693 -#else -#define PCI_CY82C693 NULL -#define INIT_CY82C693 IDE_NO_DRIVER -#endif - -#ifdef CONFIG_BLK_DEV_CS5530 -extern unsigned int pci_init_cs5530(struct pci_dev *, const char *); -extern void ide_init_cs5530(ide_hwif_t *); -#define PCI_CS5530 &pci_init_cs5530 -#define INIT_CS5530 &ide_init_cs5530 -#else -#define PCI_CS5530 NULL -#define INIT_CS5530 IDE_NO_DRIVER -#endif - -#ifdef CONFIG_BLK_DEV_HPT34X -extern unsigned int pci_init_hpt34x(struct pci_dev *, const char *); -extern void ide_init_hpt34x(ide_hwif_t *); -#define PCI_HPT34X &pci_init_hpt34x -#define INIT_HPT34X &ide_init_hpt34x -#else -#define PCI_HPT34X NULL -#define INIT_HPT34X IDE_IGNORE -#endif - -#ifdef CONFIG_BLK_DEV_HPT366 -extern byte hpt363_shared_irq; -extern byte hpt363_shared_pin; -extern unsigned int pci_init_hpt366(struct pci_dev *, const char *); -extern unsigned int ata66_hpt366(ide_hwif_t *); -extern void ide_init_hpt366(ide_hwif_t *); -extern void ide_dmacapable_hpt366(ide_hwif_t *, unsigned long); -#define PCI_HPT366 &pci_init_hpt366 -#define ATA66_HPT366 &ata66_hpt366 -#define INIT_HPT366 &ide_init_hpt366 -#define DMA_HPT366 &ide_dmacapable_hpt366 -#else -static byte hpt363_shared_irq; -static byte hpt363_shared_pin; -#define PCI_HPT366 NULL -#define ATA66_HPT366 NULL -#define INIT_HPT366 IDE_NO_DRIVER -#define DMA_HPT366 NULL -#endif - -#ifdef CONFIG_BLK_DEV_NS87415 -extern void ide_init_ns87415(ide_hwif_t *); -#define INIT_NS87415 &ide_init_ns87415 -#else -#define INIT_NS87415 IDE_IGNORE -#endif - -#ifdef CONFIG_BLK_DEV_OPTI621 -extern void ide_init_opti621(ide_hwif_t *); -#define INIT_OPTI621 &ide_init_opti621 -#else -#define INIT_OPTI621 IDE_NO_DRIVER -#endif - -#ifdef CONFIG_BLK_DEV_PDC_ADMA -extern unsigned int pci_init_pdcadma(struct pci_dev *, const char *); -extern unsigned int ata66_pdcadma(ide_hwif_t *); -extern void ide_init_pdcadma(ide_hwif_t *); -extern void ide_dmacapable_pdcadma(ide_hwif_t *, unsigned long); -#define PCI_PDCADMA &pci_init_pdcadma -#define ATA66_PDCADMA &ata66_pdcadma -#define INIT_PDCADMA &ide_init_pdcadma -#define DMA_PDCADMA &ide_dmacapable_pdcadma -#else -#define PCI_PDCADMA IDE_IGNORE -#define ATA66_PDCADMA IDE_IGNORE -#define INIT_PDCADMA IDE_IGNORE -#define DMA_PDCADMA IDE_IGNORE -#endif - -#ifdef CONFIG_BLK_DEV_PDC202XX -extern unsigned int pci_init_pdc202xx(struct pci_dev *, const char *); -extern unsigned int ata66_pdc202xx(ide_hwif_t *); -extern void ide_init_pdc202xx(ide_hwif_t *); -#define PCI_PDC202XX &pci_init_pdc202xx -#define ATA66_PDC202XX &ata66_pdc202xx -#define INIT_PDC202XX &ide_init_pdc202xx -#else -#define PCI_PDC202XX NULL -#define ATA66_PDC202XX NULL -#define INIT_PDC202XX NULL -#endif - -#ifdef CONFIG_BLK_DEV_PIIX -extern unsigned int pci_init_piix(struct pci_dev *, const char *); -extern unsigned int ata66_piix(ide_hwif_t *); -extern void ide_init_piix(ide_hwif_t *); -#define PCI_PIIX &pci_init_piix -#define ATA66_PIIX &ata66_piix -#define INIT_PIIX &ide_init_piix -#else -#define PCI_PIIX NULL -#define ATA66_PIIX NULL -#define INIT_PIIX IDE_NO_DRIVER -#endif - -#ifdef CONFIG_BLK_DEV_IT8172 -extern unsigned int pci_init_it8172(struct pci_dev *, const char *); -extern unsigned int ata66_it8172(ide_hwif_t *); -extern void ide_init_it8172(ide_hwif_t *); -#define PCI_IT8172 &pci_init_it8172 -#define INIT_IT8172 &ide_init_it8172 -#else -#define PCI_IT8172 NULL -#define ATA66_IT8172 NULL -#define INIT_IT8172 NULL -#endif - -#ifdef CONFIG_BLK_DEV_RZ1000 -extern void ide_init_rz1000(ide_hwif_t *); -#define INIT_RZ1000 &ide_init_rz1000 -#else -#define INIT_RZ1000 IDE_IGNORE -#endif - -#define INIT_SAMURAI NULL - -#ifdef CONFIG_BLK_DEV_SVWKS -extern unsigned int pci_init_svwks(struct pci_dev *, const char *); -extern unsigned int ata66_svwks(ide_hwif_t *); -extern void ide_init_svwks(ide_hwif_t *); -#define PCI_SVWKS &pci_init_svwks -#define ATA66_SVWKS &ata66_svwks -#define INIT_SVWKS &ide_init_svwks -#else -#define PCI_SVWKS NULL -#define ATA66_SVWKS NULL -#define INIT_SVWKS IDE_NO_DRIVER -#endif - -#ifdef CONFIG_BLK_DEV_SIS5513 -extern unsigned int pci_init_sis5513(struct pci_dev *, const char *); -extern unsigned int ata66_sis5513(ide_hwif_t *); -extern void ide_init_sis5513(ide_hwif_t *); -#define PCI_SIS5513 &pci_init_sis5513 -#define ATA66_SIS5513 &ata66_sis5513 -#define INIT_SIS5513 &ide_init_sis5513 -#else -#define PCI_SIS5513 NULL -#define ATA66_SIS5513 NULL -#define INIT_SIS5513 IDE_NO_DRIVER -#endif - -#ifdef CONFIG_BLK_DEV_SLC90E66 -extern unsigned int pci_init_slc90e66(struct pci_dev *, const char *); -extern unsigned int ata66_slc90e66(ide_hwif_t *); -extern void ide_init_slc90e66(ide_hwif_t *); -#define PCI_SLC90E66 &pci_init_slc90e66 -#define ATA66_SLC90E66 &ata66_slc90e66 -#define INIT_SLC90E66 &ide_init_slc90e66 -#else -#define PCI_SLC90E66 NULL -#define ATA66_SLC90E66 NULL -#define INIT_SLC90E66 IDE_NO_DRIVER -#endif - -#ifdef CONFIG_BLK_DEV_SL82C105 -extern unsigned int pci_init_sl82c105(struct pci_dev *, const char *); -extern void dma_init_sl82c105(ide_hwif_t *, unsigned long); -extern void ide_init_sl82c105(ide_hwif_t *); -#define PCI_W82C105 &pci_init_sl82c105 -#define DMA_W82C105 &dma_init_sl82c105 -#define INIT_W82C105 &ide_init_sl82c105 -#else -#define PCI_W82C105 NULL -#define DMA_W82C105 NULL -#define INIT_W82C105 IDE_IGNORE -#endif - -#ifdef CONFIG_BLK_DEV_TRM290 -extern void ide_init_trm290(ide_hwif_t *); -#define INIT_TRM290 &ide_init_trm290 -#else -#define INIT_TRM290 IDE_IGNORE -#endif - -#ifdef CONFIG_BLK_DEV_VIA82CXXX -extern unsigned int pci_init_via82cxxx(struct pci_dev *, const char *); -extern unsigned int ata66_via82cxxx(ide_hwif_t *); -extern void ide_init_via82cxxx(ide_hwif_t *); -extern void ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long); -#define PCI_VIA82CXXX &pci_init_via82cxxx -#define ATA66_VIA82CXXX &ata66_via82cxxx -#define INIT_VIA82CXXX &ide_init_via82cxxx -#define DMA_VIA82CXXX &ide_dmacapable_via82cxxx -#else -#define PCI_VIA82CXXX NULL -#define ATA66_VIA82CXXX NULL -#define INIT_VIA82CXXX IDE_NO_DRIVER -#define DMA_VIA82CXXX NULL -#endif - -typedef struct ide_pci_enablebit_s { - byte reg; /* byte pci reg holding the enable-bit */ - byte mask; /* mask to isolate the enable-bit */ - byte val; /* value of masked reg when "enabled" */ -} ide_pci_enablebit_t; - -typedef struct ide_pci_device_s { - ide_pci_devid_t devid; - char *name; - unsigned int (*init_chipset)(struct pci_dev *dev, const char *name); - unsigned int (*ata66_check)(ide_hwif_t *hwif); - void (*init_hwif)(ide_hwif_t *hwif); - void (*dma_init)(ide_hwif_t *hwif, unsigned long dmabase); - ide_pci_enablebit_t enablebits[2]; - byte bootable; - unsigned int extra; -} ide_pci_device_t; - -static ide_pci_device_t ide_pci_chipsets[] __initdata = { - {DEVID_PIIXa, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIXb, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_MPIIX, "MPIIX", NULL, NULL, INIT_PIIX, NULL, {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX3, "PIIX3", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH0, "ICH0", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4E2, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH, "ICH", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4U2, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4NX, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH2, "ICH2", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH2M, "ICH2M", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH3M, "ICH3M", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH3, "ICH3", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH4, "ICH4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_CICH, "C-ICH", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_MR_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, - {DEVID_VP_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, -#ifndef CONFIG_PDC202XX_FORCE - {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 16 }, - {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, - {DEVID_PDC20265,"PDC20265", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, - {DEVID_PDC20267,"PDC20267", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, -#else /* !CONFIG_PDC202XX_FORCE */ - {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, - {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, - {DEVID_PDC20265,"PDC20265", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, - {DEVID_PDC20267,"PDC20267", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, -#endif - {DEVID_PDC20268,"PDC20268", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - /* Promise used a different PCI ident for the raid card apparently to try and - prevent Linux detecting it and using our own raid code. We want to detect - it for the ataraid drivers, so we have to list both here.. */ - {DEVID_PDC20270,"PDC20270", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_PDC20269,"PDC20269", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_PDC20275,"PDC20275", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_PDC20276,"PDC20276", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_RZ1000, "RZ1000", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_RZ1001, "RZ1001", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_SAMURAI, "SAMURAI", NULL, NULL, INIT_SAMURAI, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD640, "CMD640", NULL, NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_NS87410, "NS87410", NULL, NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0 }, - {DEVID_SIS5513, "SIS5513", PCI_SIS5513, ATA66_SIS5513, INIT_SIS5513, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0 }, - {DEVID_CMD643, "CMD643", PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD646, "CMD646", PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_CMD648, "CMD648", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD649, "CMD649", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, -#ifndef CONFIG_BLK_DEV_CMD680 - {DEVID_CMD680, "CMD680", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, -#else /* CONFIG_BLK_DEV_CMD680 */ - {DEVID_CMD680, "CMD680", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, -#endif /* !CONFIG_BLK_DEV_CMD680 */ - {DEVID_HT6565, "HT6565", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_OPTI621, "OPTI621", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, - {DEVID_OPTI621X,"OPTI621X", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, - {DEVID_TRM290, "TRM290", NULL, NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_NS87415, "NS87415", NULL, NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_AEC6210, "AEC6210", PCI_AEC62XX, NULL, INIT_AEC62XX, DMA_AEC62XX, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, - {DEVID_AEC6260, "AEC6260", PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0 }, - {DEVID_AEC6260R,"AEC6260R", PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, - {DEVID_W82C105, "W82C105", PCI_W82C105, NULL, INIT_W82C105, DMA_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 }, - {DEVID_UM8673F, "UM8673F", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_HPT34X, "HPT34X", PCI_HPT34X, NULL, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 }, - {DEVID_HPT366, "HPT366", PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 240 }, - {DEVID_ALI15X3, "ALI15X3", PCI_ALI15X3, ATA66_ALI15X3, INIT_ALI15X3, DMA_ALI15X3, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CY82C693,"CY82C693", PCI_CY82C693, NULL, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CS5530, "CS5530", PCI_CS5530, NULL, INIT_CS5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_AMD7401, "AMD7401", NULL, NULL, NULL, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_AMD7409, "AMD7409", PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_AMD7411, "AMD7411", PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_AMD7441, "AMD7441", PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_PDCADMA, "PDCADMA", PCI_PDCADMA, ATA66_PDCADMA, INIT_PDCADMA, DMA_PDCADMA, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_SLC90E66,"SLC90E66", PCI_SLC90E66, ATA66_SLC90E66, INIT_SLC90E66, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_OSB4, "ServerWorks OSB4", PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CSB5, "ServerWorks CSB5", PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_ITE8172G,"IT8172G", PCI_IT8172, NULL, INIT_IT8172, NULL, {{0x00,0x00,0x00}, {0x40,0x00,0x01}}, ON_BOARD, 0 }, - {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }}; - -/* - * This allows offboard ide-pci cards the enable a BIOS, verify interrupt - * settings of split-mirror pci-config space, place chipset into init-mode, - * and/or preserve an interrupt if the card is not native ide support. - */ -static unsigned int __init ide_special_settings (struct pci_dev *dev, const char *name) -{ - switch(dev->device) { - case PCI_DEVICE_ID_TTI_HPT366: - case PCI_DEVICE_ID_PROMISE_20246: - case PCI_DEVICE_ID_PROMISE_20262: - case PCI_DEVICE_ID_PROMISE_20265: - case PCI_DEVICE_ID_PROMISE_20267: - case PCI_DEVICE_ID_PROMISE_20268: - case PCI_DEVICE_ID_PROMISE_20270: - case PCI_DEVICE_ID_PROMISE_20269: - case PCI_DEVICE_ID_PROMISE_20275: - case PCI_DEVICE_ID_PROMISE_20276: - case PCI_DEVICE_ID_ARTOP_ATP850UF: - case PCI_DEVICE_ID_ARTOP_ATP860: - case PCI_DEVICE_ID_ARTOP_ATP860R: - return dev->irq; - default: - break; - } - return 0; -} - -/* - * Match a PCI IDE port against an entry in ide_hwifs[], - * based on io_base port if possible. - */ -static ide_hwif_t __init *ide_match_hwif (unsigned long io_base, byte bootable, const char *name) -{ - int h; - ide_hwif_t *hwif; - - /* - * Look for a hwif with matching io_base specified using - * parameters to ide_setup(). - */ - for (h = 0; h < MAX_HWIFS; ++h) { - hwif = &ide_hwifs[h]; - if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) { - if (hwif->chipset == ide_generic) - return hwif; /* a perfect match */ - } - } - /* - * Look for a hwif with matching io_base default value. - * If chipset is "ide_unknown", then claim that hwif slot. - * Otherwise, some other chipset has already claimed it.. :( - */ - for (h = 0; h < MAX_HWIFS; ++h) { - hwif = &ide_hwifs[h]; - if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) { - if (hwif->chipset == ide_unknown) - return hwif; /* match */ - printk("%s: port 0x%04lx already claimed by %s\n", name, io_base, hwif->name); - return NULL; /* already claimed */ - } - } - /* - * Okay, there is no hwif matching our io_base, - * so we'll just claim an unassigned slot. - * Give preference to claiming other slots before claiming ide0/ide1, - * just in case there's another interface yet-to-be-scanned - * which uses ports 1f0/170 (the ide0/ide1 defaults). - * - * Unless there is a bootable card that does not use the standard - * ports 1f0/170 (the ide0/ide1 defaults). The (bootable) flag. - */ - if (bootable) { - for (h = 0; h < MAX_HWIFS; ++h) { - hwif = &ide_hwifs[h]; - if (hwif->chipset == ide_unknown) - return hwif; /* pick an unused entry */ - } - } else { - for (h = 2; h < MAX_HWIFS; ++h) { - hwif = ide_hwifs + h; - if (hwif->chipset == ide_unknown) - return hwif; /* pick an unused entry */ - } - } - for (h = 0; h < 2; ++h) { - hwif = ide_hwifs + h; - if (hwif->chipset == ide_unknown) - return hwif; /* pick an unused entry */ - } - printk("%s: too many IDE interfaces, no room in table\n", name); - return NULL; -} - -static int __init ide_setup_pci_baseregs (struct pci_dev *dev, const char *name) -{ - byte reg, progif = 0; - - /* - * Place both IDE interfaces into PCI "native" mode: - */ - if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) { - if ((progif & 0xa) != 0xa) { - printk("%s: device not capable of full native PCI mode\n", name); - return 1; - } - printk("%s: placing both ports into native PCI mode\n", name); - (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5); - if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) { - printk("%s: rewrite of PROGIF failed, wanted 0x%04x, got 0x%04x\n", name, progif|5, progif); - return 1; - } - } - /* - * Setup base registers for IDE command/control spaces for each interface: - */ - for (reg = 0; reg < 4; reg++) { - struct resource *res = dev->resource + reg; - if ((res->flags & IORESOURCE_IO) == 0) - continue; - if (!res->start) { - printk("%s: Missing I/O address #%d\n", name, reg); - return 1; - } - } - return 0; -} - -/* - * ide_setup_pci_device() looks at the primary/secondary interfaces - * on a PCI IDE device and, if they are enabled, prepares the IDE driver - * for use with them. This generic code works for most PCI chipsets. - * - * One thing that is not standardized is the location of the - * primary/secondary interface "enable/disable" bits. For chipsets that - * we "know" about, this information is in the ide_pci_device_t struct; - * for all other chipsets, we just assume both interfaces are enabled. - */ -static void __init ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d) -{ - unsigned int port, at_least_one_hwif_enabled = 0, autodma = 0, pciirq = 0; - unsigned short pcicmd = 0, tried_config = 0; - byte tmp = 0; - ide_hwif_t *hwif, *mate = NULL; - unsigned int class_rev; - static int secondpdc = 0; - -#ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - autodma = 1; -#endif - - if (d->init_hwif == IDE_NO_DRIVER) { - printk(KERN_WARNING "%s: detected chipset, but driver not compiled in!\n", d->name); - d->init_hwif = NULL; - } - - if (pci_enable_device(dev)) { - if(pci_enable_device_bars(dev, 1<<4)) - { - printk(KERN_WARNING "%s: (ide_setup_pci_device:) Could not enable device.\n", d->name); - return; - } - printk(KERN_INFO "%s: BIOS setup was incomplete.\n", d->name); - } - -check_if_enabled: - if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) { - printk("%s: error accessing PCI regs\n", d->name); - return; - } - if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */ - /* - * PnP BIOS was *supposed* to have set this device up for us, - * but we can do it ourselves, so long as the BIOS has assigned an IRQ - * (or possibly the device is using a "legacy header" for IRQs). - * Maybe the user deliberately *disabled* the device, - * but we'll eventually ignore it again if no drives respond. - */ - if (tried_config++ - || ide_setup_pci_baseregs(dev, d->name) - || pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) { - printk("%s: device disabled (BIOS)\n", d->name); - return; - } - autodma = 0; /* default DMA off if we had to configure it here */ - goto check_if_enabled; - } - if (tried_config) - printk("%s: device enabled (Linux)\n", d->name); - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)) { - /* see comments in hpt34x.c on why..... */ - char *chipset_names[] = {"HPT343", "HPT345"}; - strcpy(d->name, chipset_names[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0]); - d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD; - } - - printk("%s: chipset revision %d\n", d->name, class_rev); - - /* - * Can we trust the reported IRQ? - */ - pciirq = dev->irq; - - if (dev->class >> 8 == PCI_CLASS_STORAGE_RAID) - { - /* By rights we want to ignore these, but the Promise Fastrak - * people have some strange ideas about proprietary so we have - * to act otherwise on those. The supertrak however we need - * to skip - */ - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265)) - { - printk(KERN_INFO "ide: Found promise 20265 in RAID mode.\n"); - if(dev->bus->self && dev->bus->self->vendor == PCI_VENDOR_ID_INTEL && - dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960) - { - printk(KERN_INFO "ide: Skipping Promise PDC20265 attached to I2O RAID controller.\n"); - return; - } - } - /* Its attached to something else, just a random bridge. - Suspect a fastrak and fall through */ - } - - if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) { - printk("%s: not 100%% native mode: will probe irqs later\n", d->name); - /* - * This allows offboard ide-pci cards the enable a BIOS, - * verify interrupt settings of split-mirror pci-config - * space, place chipset into init-mode, and/or preserve - * an interrupt if the card is not native ide support. - */ - pciirq = (d->init_chipset) ? d->init_chipset(dev, d->name) : ide_special_settings(dev, d->name); - } else if (tried_config) { - printk("%s: will probe irqs later\n", d->name); - pciirq = 0; - } else if (!pciirq) { - printk("%s: bad irq (%d): will probe later\n", d->name, pciirq); - pciirq = 0; - } else { - if (d->init_chipset) - (void) d->init_chipset(dev, d->name); -#ifdef __sparc__ - printk("%s: 100%% native mode on irq %s\n", - d->name, __irq_itoa(pciirq)); -#else - printk("%s: 100%% native mode on irq %d\n", d->name, pciirq); -#endif - } - - /* - * Set up the IDE ports - */ - for (port = 0; port <= 1; ++port) { - unsigned long base = 0, ctl = 0; - ide_pci_enablebit_t *e = &(d->enablebits[port]); - - /* - * If this is a Promise FakeRaid controller, the 2nd controller will be marked as - * disabled while it is actually there and enabled by the bios for raid purposes. - * Skip the normal "is it enabled" test for those. - */ - if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265)) && (secondpdc++==1) && (port==1) ) - goto controller_ok; - if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262)) && (secondpdc++==1) && (port==1) ) - goto controller_ok; - - if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val)) - continue; /* port not enabled */ -controller_ok: - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port) && (class_rev < 0x03)) - return; - if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) { - ctl = dev->resource[(2*port)+1].start; - base = dev->resource[2*port].start; - if (!(ctl & PCI_BASE_ADDRESS_IO_MASK) || - !(base & PCI_BASE_ADDRESS_IO_MASK)) { - printk("%s: IO baseregs (BIOS) are reported as MEM, report to .\n", d->name); -#if 0 - /* FIXME! This really should check that it really gets the IO/MEM part right! */ - continue; -#endif - } - } - if ((ctl && !base) || (base && !ctl)) { - printk("%s: inconsistent baseregs (BIOS) for port %d, skipping\n", d->name, port); - continue; - } - if (!ctl) - ctl = port ? 0x374 : 0x3f4; /* use default value */ - if (!base) - base = port ? 0x170 : 0x1f0; /* use default value */ - if ((hwif = ide_match_hwif(base, d->bootable, d->name)) == NULL) - continue; /* no room in ide_hwifs[] */ - if (hwif->io_ports[IDE_DATA_OFFSET] != base) { - ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); - hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; - } - hwif->chipset = ide_pci; - hwif->pci_dev = dev; - hwif->pci_devid = d->devid; - hwif->channel = port; - if (!hwif->irq) - hwif->irq = pciirq; - if (mate) { - hwif->mate = mate; - mate->mate = hwif; - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210)) { - hwif->serialized = 1; - mate->serialized = 1; - } - } - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886BF) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8673F)) { - hwif->irq = hwif->channel ? 15 : 14; - goto bypass_umc_dma; - } - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_MPIIX)) - goto bypass_piix_dma; - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDCADMA)) - goto bypass_legacy_dma; - if (hwif->udma_four) { - printk("%s: ATA-66/100 forced bit set (WARNING)!!\n", d->name); - } else { - hwif->udma_four = (d->ata66_check) ? d->ata66_check(hwif) : 0; - } -#ifdef CONFIG_BLK_DEV_IDEDMA - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PIIX4NX) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_VIA_IDE) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_MR_IDE) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_VP_IDE)) - autodma = 0; - if (autodma) - hwif->autodma = 1; - - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20267) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20268) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20270) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20269) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20275) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20276) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260R) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD646) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD648) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD649) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD680) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_OSB4) || - ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) { - unsigned long dma_base = ide_get_or_set_dma_base(hwif, (!mate && d->extra) ? d->extra : 0, d->name); - if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) { - /* - * Set up BM-DMA capability (PnP BIOS should have done this) - */ - if (!IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530)) - hwif->autodma = 0; /* default DMA off if we had to configure it here */ - (void) pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER); - if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) { - printk("%s: %s error updating PCICMD\n", hwif->name, d->name); - dma_base = 0; - } - } - if (dma_base) { - if (d->dma_init) { - d->dma_init(hwif, dma_base); - } else { - ide_setup_dma(hwif, dma_base, 8); - } - } else { - printk("%s: %s Bus-Master DMA disabled (BIOS)\n", hwif->name, d->name); - } - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ -bypass_legacy_dma: -bypass_piix_dma: -bypass_umc_dma: - if (d->init_hwif) /* Call chipset-specific routine for each enabled hwif */ - d->init_hwif(hwif); - mate = hwif; - at_least_one_hwif_enabled = 1; - } - if (!at_least_one_hwif_enabled) - printk("%s: neither IDE port enabled (BIOS)\n", d->name); -} - -static void __init pdc20270_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) -{ - struct pci_dev *dev2 = NULL, *findev; - ide_pci_device_t *d2; - - if ((dev->bus->self && - dev->bus->self->vendor == PCI_VENDOR_ID_DEC) && - (dev->bus->self->device == PCI_DEVICE_ID_DEC_21150)) { - if (PCI_SLOT(dev->devfn) & 2) { - return; - } - d->extra = 0; - pci_for_each_dev(findev) { - if ((findev->vendor == dev->vendor) && - (findev->device == dev->device) && - (PCI_SLOT(findev->devfn) & 2)) { - byte irq = 0, irq2 = 0; - dev2 = findev; - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); - pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2); - if (irq != irq2) { - dev2->irq = dev->irq; - pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, irq); - } - - } - } - } - - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); - if (!dev2) - return; - d2 = d; - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn); - ide_setup_pci_device(dev2, d2); -} - -static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) -{ - struct pci_dev *dev2 = NULL, *findev; - ide_pci_device_t *d2; - unsigned char pin1 = 0, pin2 = 0; - unsigned int class_rev; - char *chipset_names[] = {"HPT366", "HPT366", "HPT368", "HPT370", "HPT370A", "HPT372"}; - - if (PCI_FUNC(dev->devfn) & 1) - return; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - if (class_rev > 5) - class_rev = 5; - - strcpy(d->name, chipset_names[class_rev]); - - switch(class_rev) { - case 4: - case 3: printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); - return; - default: break; - } - - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); - pci_for_each_dev(findev) { - if ((findev->vendor == dev->vendor) && - (findev->device == dev->device) && - ((findev->devfn - dev->devfn) == 1) && - (PCI_FUNC(findev->devfn) & 1)) { - dev2 = findev; - pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); - hpt363_shared_pin = (pin1 != pin2) ? 1 : 0; - hpt363_shared_irq = (dev->irq == dev2->irq) ? 1 : 0; - if (hpt363_shared_pin && hpt363_shared_irq) { - d->bootable = ON_BOARD; - printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", d->name, pin1, pin2); -#if 0 - /* I forgot why I did this once, but it fixed something. */ - pci_write_config_byte(dev2, PCI_INTERRUPT_PIN, dev->irq); - printk("PCI: %s: Fixing interrupt %d pin %d to ZERO \n", d->name, dev2->irq, pin2); - pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, 0); -#endif - } - break; - } - } - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); - if (!dev2) - return; - d2 = d; - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn); - ide_setup_pci_device(dev2, d2); -} - -/* - * ide_scan_pcibus() gets invoked at boot time from ide.c. - * It finds all PCI IDE controllers and calls ide_setup_pci_device for them. - */ -void __init ide_scan_pcidev (struct pci_dev *dev) -{ - ide_pci_devid_t devid; - ide_pci_device_t *d; - - devid.vid = dev->vendor; - devid.did = dev->device; - for (d = ide_pci_chipsets; d->devid.vid && !IDE_PCI_DEVID_EQ(d->devid, devid); ++d); - if (d->init_hwif == IDE_IGNORE) - printk("%s: ignored by ide_scan_pci_device() (uses own driver)\n", d->name); - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_OPTI621V) && !(PCI_FUNC(dev->devfn) & 1)) - return; - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) - return; /* CY82C693 is more than only a IDE controller */ - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_ITE8172G) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) - return; /* IT8172G is also more than only an IDE controller */ - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && !(PCI_FUNC(dev->devfn) & 1)) - return; /* UM8886A/BF pair */ - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366)) - hpt366_device_order_fixup(dev, d); - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20270)) - pdc20270_device_order_fixup(dev, d); - else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { - if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL)) - printk("%s: unknown IDE controller on PCI bus %02x device %02x, VID=%04x, DID=%04x\n", - d->name, dev->bus->number, dev->devfn, devid.vid, devid.did); - else - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); - } -} - -void __init ide_scan_pcibus (int scan_direction) -{ - struct pci_dev *dev; - - if (!scan_direction) { - pci_for_each_dev(dev) { - ide_scan_pcidev(dev); - } - } else { - pci_for_each_dev_reverse(dev) { - ide_scan_pcidev(dev); - } - } -} diff --git a/xen/drivers/ide/ide-probe.c b/xen/drivers/ide/ide-probe.c deleted file mode 100644 index f6d77e4e7a..0000000000 --- a/xen/drivers/ide/ide-probe.c +++ /dev/null @@ -1,1066 +0,0 @@ -/* - * linux/drivers/ide/ide-probe.c Version 1.07 March 18, 2001 - * - * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) - */ - -/* - * Mostly written by Mark Lord - * and Gadi Oxman - * and Andre Hedrick - * - * See linux/MAINTAINERS for address of current maintainer. - * - * This is the IDE probe module, as evolved from hd.c and ide.c. - * - * Version 1.00 move drive probing code from ide.c to ide-probe.c - * Version 1.01 fix compilation problem for m68k - * Version 1.02 increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot - * by Andrea Arcangeli - * Version 1.03 fix for (hwif->chipset == ide_4drives) - * Version 1.04 fixed buggy treatments of known flash memory cards - * - * Version 1.05 fix for (hwif->chipset == ide_pdc4030) - * added ide6/7/8/9 - * allowed for secondary flash card to be detectable - * with new flag : drive->ata_flash : 1; - * Version 1.06 stream line request queue and prep for cascade project. - * Version 1.07 max_sect <= 255; slower disks would get behind and - * then fall over when they get to 256. Paul G. - */ - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define IDE_PROBE_TRACE 0 - -static inline void do_identify (ide_drive_t *drive, byte cmd) -{ - int bswap = 1; - struct hd_driveid *id; - - if (IDE_PROBE_TRACE) - { - printk (KERN_ALERT "ide-probe::do_identify\n"); - } - - id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_ATOMIC); /* called with interrupts disabled! */ - if (!id) { - printk(KERN_WARNING "(ide-probe::do_identify) Out of memory.\n"); - goto err_kmalloc; - } - - ide_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */ - ide__sti(); /* local CPU only */ - ide_fix_driveid(id); - - if (id->word156 == 0x4d42) { - printk("%s: drive->id->word156 == 0x%04x \n", drive->name, drive->id->word156); - } - - if (!drive->forced_lun) - drive->last_lun = id->last_lun & 0x7; -#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA) - /* - * EATA SCSI controllers do a hardware ATA emulation: - * Ignore them if there is a driver for them available. - */ - if ((id->model[0] == 'P' && id->model[1] == 'M') - || (id->model[0] == 'S' && id->model[1] == 'K')) { - printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model); - goto err_misc; - } -#endif /* CONFIG_SCSI_EATA_DMA || CONFIG_SCSI_EATA_PIO */ - - /* - * WIN_IDENTIFY returns little-endian info, - * WIN_PIDENTIFY *usually* returns little-endian info. - */ - if (cmd == WIN_PIDENTIFY) { - if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */ - || (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */ - || (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */ - bswap ^= 1; /* Vertos drives may still be weird */ - } - ide_fixstring (id->model, sizeof(id->model), bswap); - ide_fixstring (id->fw_rev, sizeof(id->fw_rev), bswap); - ide_fixstring (id->serial_no, sizeof(id->serial_no), bswap); - - if (strstr(id->model, "E X A B Y T E N E S T")) - goto err_misc; - - id->model[sizeof(id->model)-1] = '\0'; /* we depend on this a lot! */ - printk("%s: %s, ", drive->name, id->model); - drive->present = 1; - - /* - * Check for an ATAPI device - */ - if (cmd == WIN_PIDENTIFY) { - byte type = (id->config >> 8) & 0x1f; - printk("ATAPI "); -#ifdef CONFIG_BLK_DEV_PDC4030 - if (HWIF(drive)->channel == 1 && HWIF(drive)->chipset == ide_pdc4030) { - printk(" -- not supported on 2nd Promise port\n"); - goto err_misc; - } -#endif /* CONFIG_BLK_DEV_PDC4030 */ - switch (type) { - case ide_floppy: - if (!strstr(id->model, "CD-ROM")) { - if (!strstr(id->model, "oppy") && !strstr(id->model, "poyp") && !strstr(id->model, "ZIP")) - printk("cdrom or floppy?, assuming "); - if (drive->media != ide_cdrom) { - printk ("FLOPPY"); - break; - } - } - type = ide_cdrom; /* Early cdrom models used zero */ - case ide_cdrom: - drive->removable = 1; -#ifdef CONFIG_PPC - /* kludge for Apple PowerBook internal zip */ - if (!strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) { - printk ("FLOPPY"); - type = ide_floppy; - break; - } -#endif - printk ("CD/DVD-ROM"); - break; - case ide_tape: - printk ("TAPE"); - break; - case ide_optical: - printk ("OPTICAL"); - drive->removable = 1; - break; - default: - printk("UNKNOWN (type %d)", type); - break; - } - printk (" drive\n"); - drive->media = type; - return; - } - - /* - * Not an ATAPI device: looks like a "regular" hard disk - */ - if (id->config & (1<<7)) - drive->removable = 1; - /* - * Prevent long system lockup probing later for non-existant - * slave drive if the hwif is actually a flash memory card of some variety: - */ - if (drive_is_flashcard(drive)) { - ide_drive_t *mate = &HWIF(drive)->drives[1^drive->select.b.unit]; - if (!mate->ata_flash) { - mate->present = 0; - mate->noprobe = 1; - } - } - drive->media = ide_disk; - printk("ATA DISK drive\n"); - QUIRK_LIST(HWIF(drive),drive); - return; - -err_misc: - kfree(id); -err_kmalloc: - drive->present = 0; - return; -} - -/* - * try_to_identify() sends an ATA(PI) IDENTIFY request to a drive - * and waits for a response. It also monitors irqs while this is - * happening, in hope of automatically determining which one is - * being used by the interface. - * - * Returns: 0 device was identified - * 1 device timed-out (no response to identify request) - * 2 device aborted the command (refused to identify itself) - */ -static int actual_try_to_identify (ide_drive_t *drive, byte cmd) -{ - int rc; - ide_ioreg_t hd_status; - unsigned long timeout; - byte s, a; - - if (IDE_PROBE_TRACE) - { - printk (KERN_ALERT "ide-probe::actual_try_to_identify\n"); - } - - if (IDE_CONTROL_REG) { - /* take a deep breath */ - ide_delay_50ms(); - a = IN_BYTE(IDE_ALTSTATUS_REG); - s = IN_BYTE(IDE_STATUS_REG); - if ((a ^ s) & ~INDEX_STAT) { - printk("%s: probing with STATUS(0x%02x) instead of ALTSTATUS(0x%02x)\n", drive->name, s, a); - hd_status = IDE_STATUS_REG; /* ancient Seagate drives, broken interfaces */ - } else { - hd_status = IDE_ALTSTATUS_REG; /* use non-intrusive polling */ - } - } else { - ide_delay_50ms(); - hd_status = IDE_STATUS_REG; - } - - /* set features register for atapi identify command to be sure of reply */ - if ((cmd == WIN_PIDENTIFY)) - OUT_BYTE(0,IDE_FEATURE_REG); /* disable dma & overlap */ - -#if CONFIG_BLK_DEV_PDC4030 - if (HWIF(drive)->chipset == ide_pdc4030) { - /* DC4030 hosted drives need their own identify... */ - extern int pdc4030_identify(ide_drive_t *); - if (pdc4030_identify(drive)) { - return 1; - } - } else -#endif /* CONFIG_BLK_DEV_PDC4030 */ - OUT_BYTE(cmd,IDE_COMMAND_REG); /* ask drive for ID */ - timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; - timeout += jiffies; - do { - if (0 < (signed long)(jiffies - timeout)) { - return 1; /* drive timed-out */ - } - ide_delay_50ms(); /* give drive a breather */ - } while (IN_BYTE(hd_status) & BUSY_STAT); - - ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */ - if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) { - unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only; some systems need this */ - do_identify(drive, cmd); /* drive returned ID */ - rc = 0; /* drive responded with ID */ - (void) GET_STAT(); /* clear drive IRQ */ - __restore_flags(flags); /* local CPU only */ - } else - rc = 2; /* drive refused ID */ - return rc; -} - -static int try_to_identify (ide_drive_t *drive, byte cmd) -{ - int retval; - int autoprobe = 0; - unsigned long cookie = 0; - - if (IDE_PROBE_TRACE) - { - printk (KERN_ALERT "ide-probe::try_to_identify\n"); - } - - if (IDE_CONTROL_REG && !HWIF(drive)->irq) { - autoprobe = 1; - cookie = probe_irq_on(); - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* enable device irq */ - } - - retval = actual_try_to_identify(drive, cmd); - - if (autoprobe) { - int irq; - OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* mask device irq */ - (void) GET_STAT(); /* clear drive IRQ */ - udelay(5); - irq = probe_irq_off(cookie); - if (!HWIF(drive)->irq) { - if (irq > 0) { - HWIF(drive)->irq = irq; - } else { /* Mmmm.. multiple IRQs.. don't know which was ours */ - printk("%s: IRQ probe failed (0x%lx)\n", drive->name, cookie); -#ifdef CONFIG_BLK_DEV_CMD640 -#ifdef CMD640_DUMP_REGS - if (HWIF(drive)->chipset == ide_cmd640) { - printk("%s: Hmmm.. probably a driver problem.\n", drive->name); - CMD640_DUMP_REGS; - } -#endif /* CMD640_DUMP_REGS */ -#endif /* CONFIG_BLK_DEV_CMD640 */ - } - } - } - return retval; -} - - -/* - * do_probe() has the difficult job of finding a drive if it exists, - * without getting hung up if it doesn't exist, without trampling on - * ethernet cards, and without leaving any IRQs dangling to haunt us later. - * - * If a drive is "known" to exist (from CMOS or kernel parameters), - * but does not respond right away, the probe will "hang in there" - * for the maximum wait time (about 30 seconds), otherwise it will - * exit much more quickly. - * - * Returns: 0 device was identified - * 1 device timed-out (no response to identify request) - * 2 device aborted the command (refused to identify itself) - * 3 bad status from device (possible for ATAPI drives) - * 4 probe was not attempted because failure was obvious - */ -static int do_probe (ide_drive_t *drive, byte cmd) -{ - int rc; - ide_hwif_t *hwif = HWIF(drive); - - if (IDE_PROBE_TRACE) - { - printk (KERN_ALERT "ide-probe::do_probe\n"); - } - - if (drive->present) { /* avoid waiting for inappropriate probes */ - if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY)) - return 4; - } -#ifdef DEBUG - printk("probing for %s: present=%d, media=%d, probetype=%s\n", - drive->name, drive->present, drive->media, - (cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI"); -#endif - ide_delay_50ms(); /* needed for some systems (e.g. crw9624 as drive0 with disk as slave) */ - SELECT_DRIVE(hwif,drive); - ide_delay_50ms(); - if (IN_BYTE(IDE_SELECT_REG) != drive->select.all && !drive->present) { - if (drive->select.b.unit != 0) { - SELECT_DRIVE(hwif,&hwif->drives[0]); /* exit with drive0 selected */ - ide_delay_50ms(); /* allow BUSY_STAT to assert & clear */ - } - return 3; /* no i/f present: mmm.. this should be a 4 -ml */ - } - - if (OK_STAT(GET_STAT(),READY_STAT,BUSY_STAT) - || drive->present || cmd == WIN_PIDENTIFY) - { - if ((rc = try_to_identify(drive,cmd))) /* send cmd and wait */ - rc = try_to_identify(drive,cmd); /* failed: try again */ - if (rc == 1 && cmd == WIN_PIDENTIFY && drive->autotune != 2) { - unsigned long timeout; - printk("%s: no response (status = 0x%02x), resetting drive\n", drive->name, GET_STAT()); - ide_delay_50ms(); - OUT_BYTE (drive->select.all, IDE_SELECT_REG); - ide_delay_50ms(); - OUT_BYTE(WIN_SRST, IDE_COMMAND_REG); - timeout = jiffies; - while ((GET_STAT() & BUSY_STAT) && time_before(jiffies, timeout + WAIT_WORSTCASE)) - ide_delay_50ms(); - rc = try_to_identify(drive, cmd); - } - if (rc == 1) - printk("%s: no response (status = 0x%02x)\n", drive->name, GET_STAT()); - (void) GET_STAT(); /* ensure drive irq is clear */ - } else { - rc = 3; /* not present or maybe ATAPI */ - } - if (drive->select.b.unit != 0) { - SELECT_DRIVE(hwif,&hwif->drives[0]); /* exit with drive0 selected */ - ide_delay_50ms(); - (void) GET_STAT(); /* ensure drive irq is clear */ - } - return rc; -} - -/* - * - */ -static void enable_nest (ide_drive_t *drive) -{ - unsigned long timeout; - - if (IDE_PROBE_TRACE) - { - printk (KERN_ALERT "ide-probe::enable_nest\n"); - } - - printk("%s: enabling %s -- ", HWIF(drive)->name, drive->id->model); - SELECT_DRIVE(HWIF(drive), drive); - ide_delay_50ms(); - OUT_BYTE(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG); - timeout = jiffies + WAIT_WORSTCASE; - do { - if (time_after(jiffies, timeout)) { - printk("failed (timeout)\n"); - return; - } - ide_delay_50ms(); - } while (GET_STAT() & BUSY_STAT); - ide_delay_50ms(); - if (!OK_STAT(GET_STAT(), 0, BAD_STAT)) - printk("failed (status = 0x%02x)\n", GET_STAT()); - else - printk("success\n"); - if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */ - (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */ - } -} - -/* - * probe_for_drive() tests for existence of a given drive using do_probe(). - * - * Returns: 0 no device was found - * 1 device was found (note: drive->present might still be 0) - */ -static inline byte probe_for_drive (ide_drive_t *drive) -{ - if (IDE_PROBE_TRACE) - { - printk (KERN_ALERT "ide-probe::probe_for_drive\n"); - } - - if (drive->noprobe) /* skip probing? */ - return drive->present; - if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */ - (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */ - } - if (drive->id && strstr(drive->id->model, "E X A B Y T E N E S T")) - enable_nest(drive); - if (!drive->present) - return 0; /* drive not found */ - if (drive->id == NULL) { /* identification failed? */ - if (drive->media == ide_disk) { - printk ("%s: non-IDE drive, CHS=%d/%d/%d\n", - drive->name, drive->cyl, drive->head, drive->sect); - } else if (drive->media == ide_cdrom) { - printk("%s: ATAPI cdrom (?)\n", drive->name); - } else { - drive->present = 0; /* nuke it */ - } - } - return 1; /* drive was found */ -} - -/* - * Calculate the region that this interface occupies, - * handling interfaces where the registers may not be - * ordered sanely. We deal with the CONTROL register - * separately. - */ -static int hwif_check_regions (ide_hwif_t *hwif) -{ - int region_errors = 0; - - hwif->straight8 = 0; - region_errors = ide_check_region(hwif->io_ports[IDE_DATA_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_ERROR_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_LCYL_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_HCYL_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_SELECT_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_STATUS_OFFSET], 1); - - if (hwif->io_ports[IDE_CONTROL_OFFSET]) - region_errors += ide_check_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1); -#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) - if (hwif->io_ports[IDE_IRQ_OFFSET]) - region_errors += ide_check_region(hwif->io_ports[IDE_IRQ_OFFSET], 1); -#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ - /* - * If any errors are return, we drop the hwif interface. - */ - return(region_errors); -} - -static void hwif_register (ide_hwif_t *hwif) -{ - if (((unsigned long)hwif->io_ports[IDE_DATA_OFFSET] | 7) == - ((unsigned long)hwif->io_ports[IDE_STATUS_OFFSET])) { - ide_request_region(hwif->io_ports[IDE_DATA_OFFSET], 8, hwif->name); - hwif->straight8 = 1; - goto jump_straight8; - } - - if (hwif->io_ports[IDE_DATA_OFFSET]) - ide_request_region(hwif->io_ports[IDE_DATA_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_ERROR_OFFSET]) - ide_request_region(hwif->io_ports[IDE_ERROR_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_NSECTOR_OFFSET]) - ide_request_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_SECTOR_OFFSET]) - ide_request_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_LCYL_OFFSET]) - ide_request_region(hwif->io_ports[IDE_LCYL_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_HCYL_OFFSET]) - ide_request_region(hwif->io_ports[IDE_HCYL_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_SELECT_OFFSET]) - ide_request_region(hwif->io_ports[IDE_SELECT_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_STATUS_OFFSET]) - ide_request_region(hwif->io_ports[IDE_STATUS_OFFSET], 1, hwif->name); - -jump_straight8: - if (hwif->io_ports[IDE_CONTROL_OFFSET]) - ide_request_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1, hwif->name); -#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) - if (hwif->io_ports[IDE_IRQ_OFFSET]) - ide_request_region(hwif->io_ports[IDE_IRQ_OFFSET], 1, hwif->name); -#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ -} - -/* - * This routine only knows how to look for drive units 0 and 1 - * on an interface, so any setting of MAX_DRIVES > 2 won't work here. - */ -static void probe_hwif (ide_hwif_t *hwif) -{ - unsigned int unit; - unsigned long flags; - - if (IDE_PROBE_TRACE) - { - printk (KERN_ALERT "ide-probe::probe_hwif\n"); - } - - if (hwif->noprobe) - return; -#ifdef CONFIG_BLK_DEV_IDE - if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) { - extern void probe_cmos_for_drives(ide_hwif_t *); - - probe_cmos_for_drives (hwif); - } -#endif - - if ((hwif->chipset != ide_4drives || !hwif->mate->present) && -#if CONFIG_BLK_DEV_PDC4030 - (hwif->chipset != ide_pdc4030 || hwif->channel == 0) && -#endif /* CONFIG_BLK_DEV_PDC4030 */ - (hwif_check_regions(hwif))) { - int msgout = 0; - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - if (drive->present) { - drive->present = 0; - printk("%s: ERROR, PORTS ALREADY IN USE\n", drive->name); - msgout = 1; - } - } - if (!msgout) - printk("%s: ports already in use, skipping probe\n", hwif->name); - return; - } - - __save_flags(flags); /* local CPU only */ - __sti(); /* local CPU only; needed for jiffies and irq probing */ - /* - * Second drive should only exist if first drive was found, - * but a lot of cdrom drives are configured as single slaves. - */ - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - (void) probe_for_drive (drive); - if (drive->present && !hwif->present) { - hwif->present = 1; - if (hwif->chipset != ide_4drives || !hwif->mate->present) { - hwif_register(hwif); - } - } - } - if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) { - unsigned long timeout = jiffies + WAIT_WORSTCASE; - byte stat; - - printk("%s: reset\n", hwif->name); - OUT_BYTE(12, hwif->io_ports[IDE_CONTROL_OFFSET]); - udelay(10); - OUT_BYTE(8, hwif->io_ports[IDE_CONTROL_OFFSET]); - do { - ide_delay_50ms(); - stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); - } while ((stat & BUSY_STAT) && 0 < (signed long)(timeout - jiffies)); - - } - __restore_flags(flags); /* local CPU only */ - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - if (drive->present) { - ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc; - if (tuneproc != NULL && drive->autotune == 1) - tuneproc(drive, 255); /* auto-tune PIO mode */ - } - } -} - -#if MAX_HWIFS > 1 -/* - * save_match() is used to simplify logic in init_irq() below. - * - * A loophole here is that we may not know about a particular - * hwif's irq until after that hwif is actually probed/initialized.. - * This could be a problem for the case where an hwif is on a - * dual interface that requires serialization (eg. cmd640) and another - * hwif using one of the same irqs is initialized beforehand. - * - * This routine detects and reports such situations, but does not fix them. - */ -static void save_match (ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match) -{ - ide_hwif_t *m = *match; - - if (m && m->hwgroup && m->hwgroup != new->hwgroup) { - if (!new->hwgroup) - return; - printk("%s: potential irq problem with %s and %s\n", hwif->name, new->name, m->name); - } - if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */ - *match = new; -} -#endif /* MAX_HWIFS > 1 */ - -/* - * init request queue - */ -static void ide_init_queue(ide_drive_t *drive) -{ - request_queue_t *q = &drive->queue; - - q->queuedata = HWGROUP(drive); - blk_init_queue(q, do_ide_request); - - if (drive->media == ide_disk) { -#ifdef CONFIG_BLK_DEV_ELEVATOR_NOOP - elevator_init(&q->elevator, ELEVATOR_NOOP); -#endif - } -} - -/* - * This routine sets up the irq for an ide interface, and creates a new - * hwgroup for the irq/hwif if none was previously assigned. - * - * Much of the code is for correctly detecting/handling irq sharing - * and irq serialization situations. This is somewhat complex because - * it handles static as well as dynamic (PCMCIA) IDE interfaces. - * - * The SA_INTERRUPT in sa_flags means ide_intr() is always entered with - * interrupts completely disabled. This can be bad for interrupt latency, - * but anything else has led to problems on some machines. We re-enable - * interrupts as much as we can safely do in most places. - */ -static int init_irq (ide_hwif_t *hwif) -{ - unsigned long flags; - unsigned int index; - ide_hwgroup_t *hwgroup, *new_hwgroup; - ide_hwif_t *match = NULL; - - - /* Allocate the buffer and potentially sleep first */ - - new_hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL); - - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - - hwif->hwgroup = NULL; -#if MAX_HWIFS > 1 - /* - * Group up with any other hwifs that share our irq(s). - */ - for (index = 0; index < MAX_HWIFS; index++) { - ide_hwif_t *h = &ide_hwifs[index]; - if (h->hwgroup) { /* scan only initialized hwif's */ - if (hwif->irq == h->irq) { - hwif->sharing_irq = h->sharing_irq = 1; - if (hwif->chipset != ide_pci || h->chipset != ide_pci) { - save_match(hwif, h, &match); - } - } - if (hwif->serialized) { - if (hwif->mate && hwif->mate->irq == h->irq) - save_match(hwif, h, &match); - } - if (h->serialized) { - if (h->mate && hwif->irq == h->mate->irq) - save_match(hwif, h, &match); - } - } - } -#endif /* MAX_HWIFS > 1 */ - /* - * If we are still without a hwgroup, then form a new one - */ - if (match) { - hwgroup = match->hwgroup; - if(new_hwgroup) - kfree(new_hwgroup); - } else { - hwgroup = new_hwgroup; - if (!hwgroup) { - restore_flags(flags); /* all CPUs */ - return 1; - } - memset(hwgroup, 0, sizeof(ide_hwgroup_t)); - hwgroup->hwif = hwif->next = hwif; - hwgroup->rq = NULL; - hwgroup->handler = NULL; - hwgroup->drive = NULL; - hwgroup->busy = 0; - init_timer(&hwgroup->timer); - hwgroup->timer.function = &ide_timer_expiry; - hwgroup->timer.data = (unsigned long) hwgroup; - } - - /* - * Allocate the irq, if not already obtained for another hwif - */ - if (!match || match->irq != hwif->irq) { -#ifdef CONFIG_IDEPCI_SHARE_IRQ - int sa = IDE_CHIPSET_IS_PCI(hwif->chipset) ? SA_SHIRQ : SA_INTERRUPT; -#else /* !CONFIG_IDEPCI_SHARE_IRQ */ - int sa = IDE_CHIPSET_IS_PCI(hwif->chipset) ? SA_INTERRUPT|SA_SHIRQ : SA_INTERRUPT; -#endif /* CONFIG_IDEPCI_SHARE_IRQ */ - - if (hwif->io_ports[IDE_CONTROL_OFFSET]) - OUT_BYTE(0x08, hwif->io_ports[IDE_CONTROL_OFFSET]); /* clear nIEN */ - - if (ide_request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwgroup)) { - if (!match) - kfree(hwgroup); - restore_flags(flags); /* all CPUs */ - return 1; - } - } - - /* - * Everything is okay, so link us into the hwgroup - */ - hwif->hwgroup = hwgroup; - hwif->next = hwgroup->hwif->next; - hwgroup->hwif->next = hwif; - - for (index = 0; index < MAX_DRIVES; ++index) { - ide_drive_t *drive = &hwif->drives[index]; - if (!drive->present) - continue; - if (!hwgroup->drive) - hwgroup->drive = drive; - drive->next = hwgroup->drive->next; - hwgroup->drive->next = drive; - ide_init_queue(drive); - } - if (!hwgroup->hwif) { - hwgroup->hwif = HWIF(hwgroup->drive); -#ifdef DEBUG - printk("%s : Adding missed hwif to hwgroup!!\n", hwif->name); -#endif - } - restore_flags(flags); /* all CPUs; safe now that hwif->hwgroup is set up */ - -#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__) - printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name, - hwif->io_ports[IDE_DATA_OFFSET], - hwif->io_ports[IDE_DATA_OFFSET]+7, - hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq); -#elif defined(__sparc__) - printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %s", hwif->name, - hwif->io_ports[IDE_DATA_OFFSET], - hwif->io_ports[IDE_DATA_OFFSET]+7, - hwif->io_ports[IDE_CONTROL_OFFSET], __irq_itoa(hwif->irq)); -#else - printk("%s at %p on irq 0x%08x", hwif->name, - hwif->io_ports[IDE_DATA_OFFSET], hwif->irq); -#endif /* __mc68000__ && CONFIG_APUS */ - if (match) - printk(" (%sed with %s)", - hwif->sharing_irq ? "shar" : "serializ", match->name); - printk("\n"); - return 0; -} - -/* - * init_gendisk() (as opposed to ide_geninit) is called for each major device, - * after probing for drives, to allocate partition tables and other data - * structures needed for the routines in genhd.c. ide_geninit() gets called - * somewhat later, during the partition check. - */ -static void init_gendisk (ide_hwif_t *hwif) -{ - struct gendisk *gd; - unsigned int unit, units, minors; - int *bs, *max_sect; /* , *max_ra; */ -#ifdef DEVFS_MUST_DIE - extern devfs_handle_t ide_devfs_handle; -#endif - -#if 1 - units = MAX_DRIVES; -#else - /* figure out maximum drive number on the interface */ - for (units = MAX_DRIVES; units > 0; --units) { - if (hwif->drives[units-1].present) - break; - } -#endif - - minors = units * (1<sizes = kmalloc (minors * sizeof(int), GFP_KERNEL); - if (!gd->sizes) - goto err_kmalloc_gd_sizes; - gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL); - if (!gd->part) - goto err_kmalloc_gd_part; - bs = kmalloc (minors*sizeof(int), GFP_KERNEL); - if (!bs) - goto err_kmalloc_bs; - max_sect = kmalloc (minors*sizeof(int), GFP_KERNEL); - if (!max_sect) - goto err_kmalloc_max_sect; -#if 0 - max_ra = kmalloc (minors*sizeof(int), GFP_KERNEL); - if (!max_ra) - goto err_kmalloc_max_ra; -#endif - - memset(gd->part, 0, minors * sizeof(struct hd_struct)); - - /* cdroms and msdos f/s are examples of non-1024 blocksizes */ - blksize_size[hwif->major] = bs; - max_sectors[hwif->major] = max_sect; - /*max_readahead[hwif->major] = max_ra;*/ - for (unit = 0; unit < minors; ++unit) { - *bs++ = BLOCK_SIZE; - /* - * IDE can do up to 128K per request == 256 - */ - *max_sect++ = ((hwif->chipset == ide_pdc4030) ? 127 : 128); - /* *max_ra++ = vm_max_readahead; */ - } - - for (unit = 0; unit < units; ++unit) - hwif->drives[unit].part = &gd->part[unit << PARTN_BITS]; - - gd->major = hwif->major; /* our major device number */ - gd->major_name = IDE_MAJOR_NAME; /* treated special in genhd.c */ - gd->minor_shift = PARTN_BITS; /* num bits for partitions */ - gd->max_p = 1<nr_real = units; /* current num real drives */ - gd->real_devices= hwif; /* ptr to internal data */ - gd->next = NULL; /* linked list of major devs */ - gd->fops = ide_fops; /* file operations */ - gd->flags = kmalloc (sizeof *gd->flags * units, GFP_KERNEL); - if (gd->flags) - memset (gd->flags, 0, sizeof *gd->flags * units); -#ifdef DEVFS_MUST_DIE - gd->de_arr = kmalloc (sizeof *gd->de_arr * units, GFP_KERNEL); - if (gd->de_arr) - memset (gd->de_arr, 0, sizeof *gd->de_arr * units); -#endif - - hwif->gd = gd; - add_gendisk(gd); - - for (unit = 0; unit < units; ++unit) { -#if 1 - char name[64]; - ide_add_generic_settings(hwif->drives + unit); - hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit); - sprintf (name, "host%d/bus%d/target%d/lun%d", - (hwif->channel && hwif->mate) ? - hwif->mate->index : hwif->index, - hwif->channel, unit, hwif->drives[unit].lun); -#ifdef DEVFS_MUST_DIE - if (hwif->drives[unit].present) - hwif->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL); -#endif -#else - if (hwif->drives[unit].present) { - char name[64]; - - ide_add_generic_settings(hwif->drives + unit); - hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit); - sprintf (name, "host%d/bus%d/target%d/lun%d", - (hwif->channel && hwif->mate) ? hwif->mate->index : hwif->index, - hwif->channel, unit, hwif->drives[unit].lun); - hwif->drives[unit].de = - devfs_mk_dir (ide_devfs_handle, name, NULL); - } -#endif - } - return; - -#if 0 -err_kmalloc_max_ra: - kfree(max_sect); -#endif -err_kmalloc_max_sect: - kfree(bs); -err_kmalloc_bs: - kfree(gd->part); -err_kmalloc_gd_part: - kfree(gd->sizes); -err_kmalloc_gd_sizes: - kfree(gd); -err_kmalloc_gd: - printk(KERN_WARNING "(ide::init_gendisk) Out of memory\n"); - return; -} - -static int hwif_init (ide_hwif_t *hwif) -{ - if (!hwif->present) - return 0; - if (!hwif->irq) { - if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) - { - printk("%s: DISABLED, NO IRQ\n", hwif->name); - return (hwif->present = 0); - } - } -#ifdef CONFIG_BLK_DEV_HD - if (hwif->irq == HD_IRQ && hwif->io_ports[IDE_DATA_OFFSET] != HD_DATA) { - printk("%s: CANNOT SHARE IRQ WITH OLD HARDDISK DRIVER (hd.c)\n", hwif->name); - return (hwif->present = 0); - } -#endif /* CONFIG_BLK_DEV_HD */ - - hwif->present = 0; /* we set it back to 1 if all is ok below */ - -#ifdef DEVFS_MUST_DIE - if (devfs_register_blkdev (hwif->major, hwif->name, ide_fops)) { - printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major); - return (hwif->present = 0); - } -#endif - - if (init_irq(hwif)) { - int i = hwif->irq; - /* - * It failed to initialise. Find the default IRQ for - * this port and try that. - */ - if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) { - printk("%s: Disabled unable to get IRQ %d.\n", hwif->name, i); - (void) unregister_blkdev (hwif->major, hwif->name); - return (hwif->present = 0); - } - if (init_irq(hwif)) { - printk("%s: probed IRQ %d and default IRQ %d failed.\n", - hwif->name, i, hwif->irq); - (void) unregister_blkdev (hwif->major, hwif->name); - return (hwif->present = 0); - } - printk("%s: probed IRQ %d failed, using default.\n", - hwif->name, hwif->irq); - } - - init_gendisk(hwif); - blk_dev[hwif->major].data = hwif; - blk_dev[hwif->major].queue = ide_get_queue; -#if 0 - read_ahead[hwif->major] = 8; /* (4kB) */ -#endif - hwif->present = 1; /* success */ - -#if (DEBUG_SPINLOCK > 0) -{ - static int done = 0; - if (!done++) - printk("io_request_lock is %p\n", &io_request_lock); /* FIXME */ -} -#endif - return hwif->present; -} - -void export_ide_init_queue (ide_drive_t *drive) -{ - ide_init_queue(drive); -} - -byte export_probe_for_drive (ide_drive_t *drive) -{ - return probe_for_drive(drive); -} - -EXPORT_SYMBOL(export_ide_init_queue); -EXPORT_SYMBOL(export_probe_for_drive); - -int ideprobe_init (void); -static ide_module_t ideprobe_module = { - IDE_PROBE_MODULE, - ideprobe_init, - NULL -}; - -int ideprobe_init (void) -{ - unsigned int index; - int probe[MAX_HWIFS]; - - if (IDE_PROBE_TRACE) - { - printk (KERN_ALERT "ide-probe::ideprobe_init\n"); - } - - MOD_INC_USE_COUNT; - memset(probe, 0, MAX_HWIFS * sizeof(int)); - for (index = 0; index < MAX_HWIFS; ++index) - probe[index] = !ide_hwifs[index].present; - - /* - * Probe for drives in the usual way.. CMOS/BIOS, then poke at ports - */ - for (index = 0; index < MAX_HWIFS; ++index) - if (probe[index]) - probe_hwif(&ide_hwifs[index]); - for (index = 0; index < MAX_HWIFS; ++index) - if (probe[index]) - hwif_init(&ide_hwifs[index]); - if (!ide_probe) - ide_probe = &ideprobe_module; - MOD_DEC_USE_COUNT; - return 0; -} - -#ifdef MODULE -extern int (*ide_xlate_1024_hook)(kdev_t, int, int, const char *); - -int init_module (void) -{ - unsigned int index; - - for (index = 0; index < MAX_HWIFS; ++index) - ide_unregister(index); - ideprobe_init(); - create_proc_ide_interfaces(); - ide_xlate_1024_hook = ide_xlate_1024; - return 0; -} - -void cleanup_module (void) -{ - ide_probe = NULL; - ide_xlate_1024_hook = 0; -} -MODULE_LICENSE("GPL"); -#endif /* MODULE */ diff --git a/xen/drivers/ide/ide-taskfile.c b/xen/drivers/ide/ide-taskfile.c deleted file mode 100644 index 2cfeaf6ba6..0000000000 --- a/xen/drivers/ide/ide-taskfile.c +++ /dev/null @@ -1,1733 +0,0 @@ -/* - * linux/drivers/ide/ide-taskfile.c Version 0.20 Oct 11, 2000 - * - * Copyright (C) 2000 Michael Cornwell - * Copyright (C) 2000 Andre Hedrick - * - * May be copied or modified under the terms of the GNU General Public License - * - * IDE_DEBUG(__LINE__); - */ - -#include -#define __NO_VERSION__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_IDE_TASKFILE_IO -# define __TASKFILE__IO -#else /* CONFIG_IDE_TASKFILE_IO */ -# undef __TASKFILE__IO -#endif /* CONFIG_IDE_TASKFILE_IO */ - -#define DEBUG_TASKFILE 0 /* unset when fixed */ - -#if DEBUG_TASKFILE -#define DTF(x...) printk(##x) -#else -#define DTF(x...) -#endif - -inline u32 task_read_24 (ide_drive_t *drive) -{ - return (IN_BYTE(IDE_HCYL_REG)<<16) | - (IN_BYTE(IDE_LCYL_REG)<<8) | - IN_BYTE(IDE_SECTOR_REG); -} - -static void ata_bswap_data (void *buffer, int wcount) -{ - u16 *p = buffer; - - while (wcount--) { - *p = *p << 8 | *p >> 8; p++; - *p = *p << 8 | *p >> 8; p++; - } -} - -#if SUPPORT_VLB_SYNC -/* - * Some localbus EIDE interfaces require a special access sequence - * when using 32-bit I/O instructions to transfer data. We call this - * the "vlb_sync" sequence, which consists of three successive reads - * of the sector count register location, with interrupts disabled - * to ensure that the reads all happen together. - */ -static inline void task_vlb_sync (ide_ioreg_t port) { - (void) inb (port); - (void) inb (port); - (void) inb (port); -} -#endif /* SUPPORT_VLB_SYNC */ - -/* - * This is used for most PIO data transfers *from* the IDE interface - */ -void ata_input_data (ide_drive_t *drive, void *vbuffer, unsigned int wcount) -{ - byte io_32bit = drive->io_32bit; - - void *buffer = map_domain_mem(virt_to_phys(vbuffer)); - - if (io_32bit) { -#if SUPPORT_VLB_SYNC - if (io_32bit & 2) { - unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - task_vlb_sync(IDE_NSECTOR_REG); - insl(IDE_DATA_REG, buffer, wcount); - __restore_flags(flags); /* local CPU only */ - } else -#endif /* SUPPORT_VLB_SYNC */ - insl(IDE_DATA_REG, buffer, wcount); - } else { -#if SUPPORT_SLOW_DATA_PORTS - if (drive->slow) { - unsigned short *ptr = (unsigned short *) buffer; - while (wcount--) { - *ptr++ = inw_p(IDE_DATA_REG); - *ptr++ = inw_p(IDE_DATA_REG); - } - } else -#endif /* SUPPORT_SLOW_DATA_PORTS */ - insw(IDE_DATA_REG, buffer, wcount<<1); - } - - unmap_domain_mem(buffer); -} - -/* - * This is used for most PIO data transfers *to* the IDE interface - */ -void ata_output_data (ide_drive_t *drive, void *vbuffer, unsigned int wcount) -{ - byte io_32bit = drive->io_32bit; - - void *buffer = map_domain_mem(virt_to_phys(vbuffer)); - - if (io_32bit) { -#if SUPPORT_VLB_SYNC - if (io_32bit & 2) { - unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - task_vlb_sync(IDE_NSECTOR_REG); - outsl(IDE_DATA_REG, buffer, wcount); - __restore_flags(flags); /* local CPU only */ - } else -#endif /* SUPPORT_VLB_SYNC */ - outsl(IDE_DATA_REG, buffer, wcount); - } else { -#if SUPPORT_SLOW_DATA_PORTS - if (drive->slow) { - unsigned short *ptr = (unsigned short *) buffer; - while (wcount--) { - outw_p(*ptr++, IDE_DATA_REG); - outw_p(*ptr++, IDE_DATA_REG); - } - } else -#endif /* SUPPORT_SLOW_DATA_PORTS */ - outsw(IDE_DATA_REG, buffer, wcount<<1); - } - - unmap_domain_mem(buffer); -} - - -static inline void taskfile_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - ata_input_data(drive, buffer, wcount); - if (drive->bswap) - ata_bswap_data(buffer, wcount); -} - -static inline void taskfile_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - if (drive->bswap) { - ata_bswap_data(buffer, wcount); - ata_output_data(drive, buffer, wcount); - ata_bswap_data(buffer, wcount); - } else { - ata_output_data(drive, buffer, wcount); - } -} - -ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) -{ - task_struct_t *taskfile = (task_struct_t *) task->tfRegister; - hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; - struct hd_driveid *id = drive->id; - byte HIHI = (drive->addressing) ? 0xE0 : 0xEF; - - printk(KERN_ALERT "do_rw_taskfile\n"); - - /* (ks/hs): Moved to start, do not use for multiple out commands */ - if (task->handler != task_mulout_intr) { - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(HWIF(drive), drive, 0); - } - - if ((id->command_set_2 & 0x0400) && - (id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - OUT_BYTE(hobfile->feature, IDE_FEATURE_REG); - OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG); - OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG); - OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG); - OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG); - } - - OUT_BYTE(taskfile->feature, IDE_FEATURE_REG); - OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG); - /* refers to number of sectors to transfer */ - OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG); - /* refers to sector offset or start sector */ - OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG); - OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG); - - OUT_BYTE((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG); - if (task->handler != NULL) { -#if 0 - ide_set_handler (drive, task->handler, WAIT_CMD, NULL); - OUT_BYTE(taskfile->command, IDE_COMMAND_REG); - /* - * warning check for race between handler and prehandler for - * writing first block of data. however since we are well - * inside the boundaries of the seek, we should be okay. - */ - if (task->prehandler != NULL) { - return task->prehandler(drive, task->rq); - } -#else - ide_startstop_t startstop; - - ide_set_handler (drive, task->handler, WAIT_CMD, NULL); - OUT_BYTE(taskfile->command, IDE_COMMAND_REG); - - if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing %s\n", - drive->name, - drive->mult_count ? "MULTWRITE" : "WRITE"); - return startstop; - } - /* (ks/hs): Fixed Multi Write */ - if ((taskfile->command != WIN_MULTWRITE) && - (taskfile->command != WIN_MULTWRITE_EXT)) { - struct request *rq = HWGROUP(drive)->rq; - /* For Write_sectors we need to stuff the first sector */ - taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); - rq->current_nr_sectors--; - } else { - /* Stuff first sector(s) by implicitly calling the handler */ - if (!(drive_is_ready(drive))) { - /* FIXME: Replace hard-coded 100, error handling? */ - int i; - for (i=0; i<100; i++) { - if (drive_is_ready(drive)) - break; - } - } - return task->handler(drive); - } -#endif - } else { - /* for dma commands we down set the handler */ - if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive))); - } - - return ide_started; -} - -void do_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, ide_handler_t *handler) -{ - struct hd_driveid *id = drive->id; - byte HIHI = (drive->addressing) ? 0xE0 : 0xEF; - - /* (ks/hs): Moved to start, do not use for multiple out commands */ - if (*handler != task_mulout_intr) { - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(HWIF(drive), drive, 0); - } - - if ((id->command_set_2 & 0x0400) && - (id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - OUT_BYTE(hobfile->feature, IDE_FEATURE_REG); - OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG); - OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG); - OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG); - OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG); - } - - OUT_BYTE(taskfile->feature, IDE_FEATURE_REG); - OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG); - /* refers to number of sectors to transfer */ - OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG); - /* refers to sector offset or start sector */ - OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG); - OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG); - - OUT_BYTE((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG); - if (handler != NULL) { - ide_set_handler (drive, handler, WAIT_CMD, NULL); - OUT_BYTE(taskfile->command, IDE_COMMAND_REG); - } else { - /* for dma commands we down set the handler */ - if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive))); - } -} - -#if 0 -ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) -{ - task_struct_t *taskfile = (task_struct_t *) task->tfRegister; - hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; - struct hd_driveid *id = drive->id; - - /* - * (KS) Check taskfile in/out flags. - * If set, then execute as it is defined. - * If not set, then define default settings. - * The default values are: - * write and read all taskfile registers (except data) - * write and read the hob registers (sector,nsector,lcyl,hcyl) - */ - if (task->tf_out_flags.all == 0) { - task->tf_out_flags.all = IDE_TASKFILE_STD_OUT_FLAGS; - if ((id->command_set_2 & 0x0400) && - (id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - task->tf_out_flags.all != (IDE_HOB_STD_OUT_FLAGS << 8); - } - } - - if (task->tf_in_flags.all == 0) { - task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS; - if ((id->command_set_2 & 0x0400) && - (id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - task->tf_in_flags.all != (IDE_HOB_STD_IN_FLAGS << 8); - } - } - - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(HWIF(drive), drive, 0); - - if (task->tf_out_flags.b.data) { - unsigned short data = taskfile->data + (hobfile->data << 8); - OUT_WORD (data, IDE_DATA_REG); - } - - /* (KS) send hob registers first */ - if (task->tf_out_flags.b.nsector_hob) - OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG); - if (task->tf_out_flags.b.sector_hob) - OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG); - if (task->tf_out_flags.b.lcyl_hob) - OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG); - if (task->tf_out_flags.b.hcyl_hob) - OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG); - - - /* (KS) Send now the standard registers */ - if (task->tf_out_flags.b.error_feature) - OUT_BYTE(taskfile->feature, IDE_FEATURE_REG); - /* refers to number of sectors to transfer */ - if (task->tf_out_flags.b.nsector) - OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG); - /* refers to sector offset or start sector */ - if (task->tf_out_flags.b.sector) - OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG); - if (task->tf_out_flags.b.lcyl) - OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG); - if (task->tf_out_flags.b.hcyl) - OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG); - - /* - * (KS) Do not modify the specified taskfile. We want to have a - * universal pass through, so we must execute ALL specified values. - * - * (KS) The drive head register is mandatory. - * Don't care about the out flags ! - */ - OUT_BYTE(taskfile->device_head | drive->select.all, IDE_SELECT_REG); - if (task->handler != NULL) { -#if 0 - ide_set_handler (drive, task->handler, WAIT_CMD, NULL); - OUT_BYTE(taskfile->command, IDE_COMMAND_REG); - /* - * warning check for race between handler and prehandler for - * writing first block of data. however since we are well - * inside the boundaries of the seek, we should be okay. - */ - if (task->prehandler != NULL) { - return task->prehandler(drive, task->rq); - } -#else - ide_startstop_t startstop; - - ide_set_handler (drive, task->handler, WAIT_CMD, NULL); - - /* - * (KS) The drive command register is also mandatory. - * Don't care about the out flags ! - */ - OUT_BYTE(taskfile->command, IDE_COMMAND_REG); - - if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing %s\n", - drive->name, - drive->mult_count ? "MULTWRITE" : "WRITE"); - return startstop; - } - /* (ks/hs): Fixed Multi Write */ - if ((taskfile->command != WIN_MULTWRITE) && - (taskfile->command != WIN_MULTWRITE_EXT)) { - struct request *rq = HWGROUP(drive)->rq; - /* For Write_sectors we need to stuff the first sector */ - taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); - rq->current_nr_sectors--; - } else { - /* Stuff first sector(s) by implicitly calling the handler */ - if (!(drive_is_ready(drive))) { - /* FIXME: Replace hard-coded 100, error handling? */ - int i; - for (i=0; i<100; i++) { - if (drive_is_ready(drive)) - break; - } - } - return task->handler(drive); - } -#endif - } else { - /* for dma commands we down set the handler */ - if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive))); - } - - return ide_started; -} -#endif - -#if 0 -/* - * Error reporting, in human readable form (luxurious, but a memory hog). - */ -byte taskfile_dump_status (ide_drive_t *drive, const char *msg, byte stat) -{ - unsigned long flags; - byte err = 0; - - __save_flags (flags); /* local CPU only */ - ide__sti(); /* local CPU only */ - printk("%s: %s: status=0x%02x", drive->name, msg, stat); -#if FANCY_STATUS_DUMPS - printk(" { "); - if (stat & BUSY_STAT) - printk("Busy "); - else { - if (stat & READY_STAT) printk("DriveReady "); - if (stat & WRERR_STAT) printk("DeviceFault "); - if (stat & SEEK_STAT) printk("SeekComplete "); - if (stat & DRQ_STAT) printk("DataRequest "); - if (stat & ECC_STAT) printk("CorrectedError "); - if (stat & INDEX_STAT) printk("Index "); - if (stat & ERR_STAT) printk("Error "); - } - printk("}"); -#endif /* FANCY_STATUS_DUMPS */ - printk("\n"); - if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { - err = GET_ERR(); - printk("%s: %s: error=0x%02x", drive->name, msg, err); -#if FANCY_STATUS_DUMPS - if (drive->media == ide_disk) { - printk(" { "); - if (err & ABRT_ERR) printk("DriveStatusError "); - if (err & ICRC_ERR) printk("%s", (err & ABRT_ERR) ? "BadCRC " : "BadSector "); - if (err & ECC_ERR) printk("UncorrectableError "); - if (err & ID_ERR) printk("SectorIdNotFound "); - if (err & TRK0_ERR) printk("TrackZeroNotFound "); - if (err & MARK_ERR) printk("AddrMarkNotFound "); - printk("}"); - if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || (err & (ECC_ERR|ID_ERR|MARK_ERR))) { - if ((drive->id->command_set_2 & 0x0400) && - (drive->id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - __u64 sectors = 0; - u32 low = 0, high = 0; - low = task_read_24(drive); - OUT_BYTE(0x80, IDE_CONTROL_REG); - high = task_read_24(drive); - sectors = ((__u64)high << 24) | low; - printk(", LBAsect=%lld", sectors); - } else { - byte cur = IN_BYTE(IDE_SELECT_REG); - if (cur & 0x40) { /* using LBA? */ - printk(", LBAsect=%ld", (unsigned long) - ((cur&0xf)<<24) - |(IN_BYTE(IDE_HCYL_REG)<<16) - |(IN_BYTE(IDE_LCYL_REG)<<8) - | IN_BYTE(IDE_SECTOR_REG)); - } else { - printk(", CHS=%d/%d/%d", - (IN_BYTE(IDE_HCYL_REG)<<8) + - IN_BYTE(IDE_LCYL_REG), - cur & 0xf, - IN_BYTE(IDE_SECTOR_REG)); - } - } - if (HWGROUP(drive)->rq) - printk(", sector=%llu", (__u64) HWGROUP(drive)->rq->sector); - } - } -#endif /* FANCY_STATUS_DUMPS */ - printk("\n"); - } - __restore_flags (flags); /* local CPU only */ - return err; -} - -/* - * Clean up after success/failure of an explicit taskfile operation. - */ -void ide_end_taskfile (ide_drive_t *drive, byte stat, byte err) -{ - unsigned long flags; - struct request *rq; - ide_task_t *args; - task_ioreg_t command; - - spin_lock_irqsave(&io_request_lock, flags); - rq = HWGROUP(drive)->rq; - spin_unlock_irqrestore(&io_request_lock, flags); - args = (ide_task_t *) rq->special; - - command = args->tfRegister[IDE_COMMAND_OFFSET]; - - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - - args->tfRegister[IDE_ERROR_OFFSET] = err; - args->tfRegister[IDE_NSECTOR_OFFSET] = IN_BYTE(IDE_NSECTOR_REG); - args->tfRegister[IDE_SECTOR_OFFSET] = IN_BYTE(IDE_SECTOR_REG); - args->tfRegister[IDE_LCYL_OFFSET] = IN_BYTE(IDE_LCYL_REG); - args->tfRegister[IDE_HCYL_OFFSET] = IN_BYTE(IDE_HCYL_REG); - args->tfRegister[IDE_SELECT_OFFSET] = IN_BYTE(IDE_SELECT_REG); - args->tfRegister[IDE_STATUS_OFFSET] = stat; - if ((drive->id->command_set_2 & 0x0400) && - (drive->id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG_HOB); - args->hobRegister[IDE_FEATURE_OFFSET_HOB] = IN_BYTE(IDE_FEATURE_REG); - args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = IN_BYTE(IDE_NSECTOR_REG); - args->hobRegister[IDE_SECTOR_OFFSET_HOB] = IN_BYTE(IDE_SECTOR_REG); - args->hobRegister[IDE_LCYL_OFFSET_HOB] = IN_BYTE(IDE_LCYL_REG); - args->hobRegister[IDE_HCYL_OFFSET_HOB] = IN_BYTE(IDE_HCYL_REG); - } - -/* taskfile_settings_update(drive, args, command); */ - - spin_lock_irqsave(&io_request_lock, flags); - blkdev_dequeue_request(rq); - HWGROUP(drive)->rq = NULL; - end_that_request_last(rq); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * try_to_flush_leftover_data() is invoked in response to a drive - * unexpectedly having its DRQ_STAT bit set. As an alternative to - * resetting the drive, this routine tries to clear the condition - * by read a sector's worth of data from the drive. Of course, - * this may not help if the drive is *waiting* for data from *us*. - */ -void task_try_to_flush_leftover_data (ide_drive_t *drive) -{ - int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS; - - if (drive->media != ide_disk) - return; - while (i > 0) { - u32 buffer[16]; - unsigned int wcount = (i > 16) ? 16 : i; - i -= wcount; - taskfile_input_data (drive, buffer, wcount); - } -} - -/* - * taskfile_error() takes action based on the error returned by the drive. - */ -ide_startstop_t taskfile_error (ide_drive_t *drive, const char *msg, byte stat) -{ - struct request *rq; - byte err; - - err = taskfile_dump_status(drive, msg, stat); - if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) - return ide_stopped; - /* retry only "normal" I/O: */ - if (rq->cmd == IDE_DRIVE_TASKFILE) { - rq->errors = 1; - ide_end_taskfile(drive, stat, err); - return ide_stopped; - } - if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */ - rq->errors |= ERROR_RESET; - } else { - if (drive->media == ide_disk && (stat & ERR_STAT)) { - /* err has different meaning on cdrom and tape */ - if (err == ABRT_ERR) { - if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY) - return ide_stopped; /* some newer drives don't support WIN_SPECIFY */ - } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR)) { - drive->crc_count++; /* UDMA crc error -- just retry the operation */ - } else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */ - rq->errors = ERROR_MAX; - else if (err & TRK0_ERR) /* help it find track zero */ - rq->errors |= ERROR_RECAL; - } - if ((stat & DRQ_STAT) && rq->cmd != WRITE) - task_try_to_flush_leftover_data(drive); - } - if (GET_STAT() & (BUSY_STAT|DRQ_STAT)) - OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); /* force an abort */ - - if (rq->errors >= ERROR_MAX) { - if (drive->driver != NULL) - DRIVER(drive)->end_request(0, HWGROUP(drive)); - else - ide_end_request(0, HWGROUP(drive)); - } else { - if ((rq->errors & ERROR_RESET) == ERROR_RESET) { - ++rq->errors; - return ide_do_reset(drive); - } - if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) - drive->special.b.recalibrate = 1; - ++rq->errors; - } - return ide_stopped; -} -#endif - -/* - * Handler for special commands without a data phase from ide-disk - */ - -/* - * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd. - */ -ide_startstop_t set_multmode_intr (ide_drive_t *drive) -{ - byte stat; - - if (OK_STAT(stat=GET_STAT(),READY_STAT,BAD_STAT)) { - drive->mult_count = drive->mult_req; - } else { - drive->mult_req = drive->mult_count = 0; - drive->special.b.recalibrate = 1; - (void) ide_dump_status(drive, "set_multmode", stat); - } - return ide_stopped; -} - -/* - * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd. - */ -ide_startstop_t set_geometry_intr (ide_drive_t *drive) -{ - byte stat; - - if (OK_STAT(stat=GET_STAT(),READY_STAT,BAD_STAT)) - return ide_stopped; - - if (stat & (ERR_STAT|DRQ_STAT)) - return ide_error(drive, "set_geometry_intr", stat); - - ide_set_handler(drive, &set_geometry_intr, WAIT_CMD, NULL); - return ide_started; -} - -/* - * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd. - */ -ide_startstop_t recal_intr (ide_drive_t *drive) -{ - byte stat = GET_STAT(); - - if (!OK_STAT(stat,READY_STAT,BAD_STAT)) - return ide_error(drive, "recal_intr", stat); - return ide_stopped; -} - -/* - * Handler for commands without a data phase - */ -ide_startstop_t task_no_data_intr (ide_drive_t *drive) -{ - ide_task_t *args = HWGROUP(drive)->rq->special; - byte stat = GET_STAT(); - - ide__sti(); /* local CPU only */ - - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) - return ide_error(drive, "task_no_data_intr", stat); /* calls ide_end_drive_cmd */ - - if (args) - ide_end_drive_cmd (drive, stat, GET_ERR()); - - return ide_stopped; -} - -/* - * Handler for command with PIO data-in phase - */ -ide_startstop_t task_in_intr (ide_drive_t *drive) -{ - byte stat = GET_STAT(); - byte io_32bit = drive->io_32bit; - struct request *rq = HWGROUP(drive)->rq; - char *pBuf = NULL; - - if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) { - if (stat & (ERR_STAT|DRQ_STAT)) { - return ide_error(drive, "task_in_intr", stat); - } - if (!(stat & BUSY_STAT)) { - DTF("task_in_intr to Soon wait for next interrupt\n"); - ide_set_handler(drive, &task_in_intr, WAIT_CMD, NULL); - return ide_started; - } - } - DTF("stat: %02x\n", stat); - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("Read: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors); - - drive->io_32bit = 0; - taskfile_input_data(drive, pBuf, SECTOR_WORDS); - drive->io_32bit = io_32bit; - - if (--rq->current_nr_sectors <= 0) { - /* (hs): swapped next 2 lines */ - DTF("Request Ended stat: %02x\n", GET_STAT()); - ide_end_request(1, HWGROUP(drive)); - } else { - ide_set_handler(drive, &task_in_intr, WAIT_CMD, NULL); - return ide_started; - } - return ide_stopped; -} - -#undef ALTSTAT_SCREW_UP - -#ifdef ALTSTAT_SCREW_UP -/* - * (ks/hs): Poll Alternate Status Register to ensure - * that drive is not busy. - */ -byte altstat_multi_busy (ide_drive_t *drive, byte stat, const char *msg) -{ - int i; - - DTF("multi%s: ASR = %x\n", msg, stat); - if (stat & BUSY_STAT) { - /* (ks/hs): FIXME: Replace hard-coded 100, error handling? */ - for (i=0; i<100; i++) { - stat = GET_ALTSTAT(); - if ((stat & BUSY_STAT) == 0) - break; - } - } - /* - * (ks/hs): Read Status AFTER Alternate Status Register - */ - return(GET_STAT()); -} - -/* - * (ks/hs): Poll Alternate status register to wait for drive - * to become ready for next transfer - */ -byte altstat_multi_poll (ide_drive_t *drive, byte stat, const char *msg) -{ - /* (ks/hs): FIXME: Error handling, time-out? */ - while (stat & BUSY_STAT) - stat = GET_ALTSTAT(); - DTF("multi%s: nsect=1, ASR = %x\n", msg, stat); - return(GET_STAT()); /* (ks/hs): Clear pending IRQ */ -} -#endif /* ALTSTAT_SCREW_UP */ - -/* - * Handler for command with Read Multiple - */ -ide_startstop_t task_mulin_intr (ide_drive_t *drive) -{ - unsigned int msect, nsect; - -#ifdef ALTSTAT_SCREW_UP - byte stat = altstat_multi_busy(drive, GET_ALTSTAT(), "read"); -#else - byte stat = GET_STAT(); -#endif /* ALTSTAT_SCREW_UP */ - - byte io_32bit = drive->io_32bit; - struct request *rq = HWGROUP(drive)->rq; - char *pBuf = NULL; - - if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) { - if (stat & (ERR_STAT|DRQ_STAT)) { - return ide_error(drive, "task_mulin_intr", stat); - } - /* no data yet, so wait for another interrupt */ - ide_set_handler(drive, &task_mulin_intr, WAIT_CMD, NULL); - return ide_started; - } - - /* (ks/hs): Fixed Multi-Sector transfer */ - msect = drive->mult_count; - -#ifdef ALTSTAT_SCREW_UP - /* - * Screw the request we do not support bad data-phase setups! - * Either read and learn the ATA standard or crash yourself! - */ - if (!msect) { - /* - * (ks/hs): Drive supports multi-sector transfer, - * drive->mult_count was not set - */ - nsect = 1; - while (rq->current_nr_sectors) { - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("Multiread: %p, nsect: %d, rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors); - drive->io_32bit = 0; - taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); - drive->io_32bit = io_32bit; - rq->errors = 0; - rq->current_nr_sectors -= nsect; - stat = altstat_multi_poll(drive, GET_ALTSTAT(), "read"); - } - ide_end_request(1, HWGROUP(drive)); - return ide_stopped; - } -#endif /* ALTSTAT_SCREW_UP */ - - nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - - DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %ld\n", - pBuf, nsect, rq->current_nr_sectors); - drive->io_32bit = 0; - taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); - drive->io_32bit = io_32bit; - rq->errors = 0; - rq->current_nr_sectors -= nsect; - if (rq->current_nr_sectors != 0) { - ide_set_handler(drive, &task_mulin_intr, WAIT_CMD, NULL); - return ide_started; - } - ide_end_request(1, HWGROUP(drive)); - return ide_stopped; -} - -ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq) -{ - ide_task_t *args = rq->special; - ide_startstop_t startstop; - - if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing %s\n", drive->name, drive->mult_count ? "MULTWRITE" : "WRITE"); - return startstop; - } - - /* (ks/hs): Fixed Multi Write */ - if ((args->tfRegister[IDE_COMMAND_OFFSET] != WIN_MULTWRITE) && - (args->tfRegister[IDE_COMMAND_OFFSET] != WIN_MULTWRITE_EXT)) { - /* For Write_sectors we need to stuff the first sector */ - taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); - rq->current_nr_sectors--; - return ide_started; - } else { - /* - * (ks/hs): Stuff the first sector(s) - * by implicitly calling the handler - */ - if (!(drive_is_ready(drive))) { - int i; - /* - * (ks/hs): FIXME: Replace hard-coded - * 100, error handling? - */ - for (i=0; i<100; i++) { - if (drive_is_ready(drive)) - break; - } - } - return args->handler(drive); - } - return ide_started; -} - -/* - * Handler for command with PIO data-out phase - */ -ide_startstop_t task_out_intr (ide_drive_t *drive) -{ - byte stat = GET_STAT(); - byte io_32bit = drive->io_32bit; - struct request *rq = HWGROUP(drive)->rq; - char *pBuf = NULL; - - if (!rq->current_nr_sectors) { - ide_end_request(1, HWGROUP(drive)); - return ide_stopped; - } - - if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat)) { - return ide_error(drive, "task_out_intr", stat); - } - if ((rq->current_nr_sectors==1) ^ (stat & DRQ_STAT)) { - rq = HWGROUP(drive)->rq; - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("write: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors); - drive->io_32bit = 0; - taskfile_output_data(drive, pBuf, SECTOR_WORDS); - drive->io_32bit = io_32bit; - rq->errors = 0; - rq->current_nr_sectors--; - } - - if (rq->current_nr_sectors <= 0) { - ide_end_request(1, HWGROUP(drive)); - } else { - ide_set_handler(drive, &task_out_intr, WAIT_CMD, NULL); - return ide_started; - } - return ide_stopped; -} - -/* - * Handler for command write multiple - * Called directly from execute_drive_cmd for the first bunch of sectors, - * afterwards only by the ISR - */ -ide_startstop_t task_mulout_intr (ide_drive_t *drive) -{ - unsigned int msect, nsect; - -#ifdef ALTSTAT_SCREW_UP - byte stat = altstat_multi_busy(drive, GET_ALTSTAT(), "write"); -#else - byte stat = GET_STAT(); -#endif /* ALTSTAT_SCREW_UP */ - - byte io_32bit = drive->io_32bit; - struct request *rq = HWGROUP(drive)->rq; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - char *pBuf = NULL; - - /* - * (ks/hs): Handle last IRQ on multi-sector transfer, - * occurs after all data was sent - */ - if (rq->current_nr_sectors == 0) { - if (stat & (ERR_STAT|DRQ_STAT)) - return ide_error(drive, "task_mulout_intr", stat); - ide_end_request(1, HWGROUP(drive)); - return ide_stopped; - } - - if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) { - if (stat & (ERR_STAT|DRQ_STAT)) { - return ide_error(drive, "task_mulout_intr", stat); - } - /* no data yet, so wait for another interrupt */ - if (hwgroup->handler == NULL) - ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL); - return ide_started; - } - - /* (ks/hs): See task_mulin_intr */ - msect = drive->mult_count; - -#ifdef ALTSTAT_SCREW_UP - /* - * Screw the request we do not support bad data-phase setups! - * Either read and learn the ATA standard or crash yourself! - */ - if (!msect) { - nsect = 1; - while (rq->current_nr_sectors) { - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("Multiwrite: %p, nsect: %d, rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors); - drive->io_32bit = 0; - taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); - drive->io_32bit = io_32bit; - rq->errors = 0; - rq->current_nr_sectors -= nsect; - stat = altstat_multi_poll(drive, GET_ALTSTAT(), "write"); - } - ide_end_request(1, HWGROUP(drive)); - return ide_stopped; - } -#endif /* ALTSTAT_SCREW_UP */ - - nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n", - pBuf, nsect, rq->current_nr_sectors); - drive->io_32bit = 0; - taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); - drive->io_32bit = io_32bit; - rq->errors = 0; - rq->current_nr_sectors -= nsect; - if (hwgroup->handler == NULL) - ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL); - return ide_started; -} - -/* Called by internal to feature out type of command being called */ -ide_pre_handler_t * ide_pre_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile) -{ - switch(taskfile->command) { - /* IDE_DRIVE_TASK_RAW_WRITE */ - case CFA_WRITE_MULTI_WO_ERASE: - case WIN_MULTWRITE: - case WIN_MULTWRITE_EXT: -// case WIN_WRITEDMA: -// case WIN_WRITEDMA_QUEUED: -// case WIN_WRITEDMA_EXT: -// case WIN_WRITEDMA_QUEUED_EXT: - /* IDE_DRIVE_TASK_OUT */ - case WIN_WRITE: - case WIN_WRITE_VERIFY: - case WIN_WRITE_BUFFER: - case CFA_WRITE_SECT_WO_ERASE: - case WIN_DOWNLOAD_MICROCODE: - return &pre_task_out_intr; - /* IDE_DRIVE_TASK_OUT */ - case WIN_SMART: - if (taskfile->feature == SMART_WRITE_LOG_SECTOR) - return &pre_task_out_intr; - default: - break; - } - return(NULL); -} - -/* Called by internal to feature out type of command being called */ -ide_handler_t * ide_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile) -{ - switch(taskfile->command) { - case WIN_IDENTIFY: - case WIN_PIDENTIFY: - case CFA_TRANSLATE_SECTOR: - case WIN_READ_BUFFER: - case WIN_READ: - case WIN_READ_EXT: - return &task_in_intr; - case WIN_SECURITY_DISABLE: - case WIN_SECURITY_ERASE_UNIT: - case WIN_SECURITY_SET_PASS: - case WIN_SECURITY_UNLOCK: - case WIN_DOWNLOAD_MICROCODE: - case CFA_WRITE_SECT_WO_ERASE: - case WIN_WRITE_BUFFER: - case WIN_WRITE_VERIFY: - case WIN_WRITE: - case WIN_WRITE_EXT: - return &task_out_intr; - case WIN_MULTREAD: - case WIN_MULTREAD_EXT: - return &task_mulin_intr; - case CFA_WRITE_MULTI_WO_ERASE: - case WIN_MULTWRITE: - case WIN_MULTWRITE_EXT: - return &task_mulout_intr; - case WIN_SMART: - switch(taskfile->feature) { - case SMART_READ_VALUES: - case SMART_READ_THRESHOLDS: - case SMART_READ_LOG_SECTOR: - return &task_in_intr; - case SMART_WRITE_LOG_SECTOR: - return &task_out_intr; - default: - return &task_no_data_intr; - } - case CFA_REQ_EXT_ERROR_CODE: - case CFA_ERASE_SECTORS: - case WIN_VERIFY: - case WIN_VERIFY_EXT: - case WIN_SEEK: - return &task_no_data_intr; - case WIN_SPECIFY: - return &set_geometry_intr; - case WIN_RESTORE: - return &recal_intr; - case WIN_DIAGNOSE: - case WIN_FLUSH_CACHE: - case WIN_FLUSH_CACHE_EXT: - case WIN_STANDBYNOW1: - case WIN_STANDBYNOW2: - case WIN_SLEEPNOW1: - case WIN_SLEEPNOW2: - case WIN_SETIDLE1: - case WIN_CHECKPOWERMODE1: - case WIN_CHECKPOWERMODE2: - case WIN_GETMEDIASTATUS: - case WIN_MEDIAEJECT: - return &task_no_data_intr; - case WIN_SETMULT: - return &set_multmode_intr; - case WIN_READ_NATIVE_MAX: - case WIN_SET_MAX: - case WIN_READ_NATIVE_MAX_EXT: - case WIN_SET_MAX_EXT: - case WIN_SECURITY_ERASE_PREPARE: - case WIN_SECURITY_FREEZE_LOCK: - case WIN_DOORLOCK: - case WIN_DOORUNLOCK: - case WIN_SETFEATURES: - return &task_no_data_intr; - case DISABLE_SEAGATE: - case EXABYTE_ENABLE_NEST: - return &task_no_data_intr; -#ifdef CONFIG_BLK_DEV_IDEDMA - case WIN_READDMA: - case WIN_IDENTIFY_DMA: - case WIN_READDMA_QUEUED: - case WIN_READDMA_EXT: - case WIN_READDMA_QUEUED_EXT: - case WIN_WRITEDMA: - case WIN_WRITEDMA_QUEUED: - case WIN_WRITEDMA_EXT: - case WIN_WRITEDMA_QUEUED_EXT: -#endif - case WIN_FORMAT: - case WIN_INIT: - case WIN_DEVICE_RESET: - case WIN_QUEUED_SERVICE: - case WIN_PACKETCMD: - default: - return(NULL); - } -} - -/* Called by ioctl to feature out type of command being called */ -int ide_cmd_type_parser (ide_task_t *args) -{ - struct hd_drive_task_hdr *taskfile = (struct hd_drive_task_hdr *) args->tfRegister; - struct hd_drive_hob_hdr *hobfile = (struct hd_drive_hob_hdr *) args->hobRegister; - - args->prehandler = ide_pre_handler_parser(taskfile, hobfile); - args->handler = ide_handler_parser(taskfile, hobfile); - - switch(args->tfRegister[IDE_COMMAND_OFFSET]) { - case WIN_IDENTIFY: - case WIN_PIDENTIFY: - return IDE_DRIVE_TASK_IN; - case CFA_TRANSLATE_SECTOR: - case WIN_READ: - case WIN_READ_BUFFER: - return IDE_DRIVE_TASK_IN; - case WIN_WRITE: - case WIN_WRITE_VERIFY: - case WIN_WRITE_BUFFER: - case CFA_WRITE_SECT_WO_ERASE: - case WIN_DOWNLOAD_MICROCODE: - return IDE_DRIVE_TASK_RAW_WRITE; - case WIN_MULTREAD: - return IDE_DRIVE_TASK_IN; - case CFA_WRITE_MULTI_WO_ERASE: - case WIN_MULTWRITE: - return IDE_DRIVE_TASK_RAW_WRITE; - case WIN_SECURITY_DISABLE: - case WIN_SECURITY_ERASE_UNIT: - case WIN_SECURITY_SET_PASS: - case WIN_SECURITY_UNLOCK: - return IDE_DRIVE_TASK_OUT; - case WIN_SMART: - args->tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS; - args->tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; - switch(args->tfRegister[IDE_FEATURE_OFFSET]) { - case SMART_READ_VALUES: - case SMART_READ_THRESHOLDS: - case SMART_READ_LOG_SECTOR: - return IDE_DRIVE_TASK_IN; - case SMART_WRITE_LOG_SECTOR: - return IDE_DRIVE_TASK_OUT; - default: - return IDE_DRIVE_TASK_NO_DATA; - } -#ifdef CONFIG_BLK_DEV_IDEDMA - case WIN_READDMA: - case WIN_IDENTIFY_DMA: - case WIN_READDMA_QUEUED: - case WIN_READDMA_EXT: - case WIN_READDMA_QUEUED_EXT: - return IDE_DRIVE_TASK_IN; - case WIN_WRITEDMA: - case WIN_WRITEDMA_QUEUED: - case WIN_WRITEDMA_EXT: - case WIN_WRITEDMA_QUEUED_EXT: - return IDE_DRIVE_TASK_RAW_WRITE; -#endif - case WIN_SETFEATURES: - switch(args->tfRegister[IDE_FEATURE_OFFSET]) { - case SETFEATURES_XFER: - return IDE_DRIVE_TASK_SET_XFER; - case SETFEATURES_DIS_DEFECT: - case SETFEATURES_EN_APM: - case SETFEATURES_DIS_MSN: - case SETFEATURES_EN_RI: - case SETFEATURES_EN_SI: - case SETFEATURES_DIS_RPOD: - case SETFEATURES_DIS_WCACHE: - case SETFEATURES_EN_DEFECT: - case SETFEATURES_DIS_APM: - case SETFEATURES_EN_MSN: - case SETFEATURES_EN_RLA: - case SETFEATURES_PREFETCH: - case SETFEATURES_EN_RPOD: - case SETFEATURES_DIS_RI: - case SETFEATURES_DIS_SI: - default: - return IDE_DRIVE_TASK_NO_DATA; - } - case WIN_NOP: - case CFA_REQ_EXT_ERROR_CODE: - case CFA_ERASE_SECTORS: - case WIN_VERIFY: - case WIN_VERIFY_EXT: - case WIN_SEEK: - case WIN_SPECIFY: - case WIN_RESTORE: - case WIN_DIAGNOSE: - case WIN_FLUSH_CACHE: - case WIN_FLUSH_CACHE_EXT: - case WIN_STANDBYNOW1: - case WIN_STANDBYNOW2: - case WIN_SLEEPNOW1: - case WIN_SLEEPNOW2: - case WIN_SETIDLE1: - case DISABLE_SEAGATE: - case WIN_CHECKPOWERMODE1: - case WIN_CHECKPOWERMODE2: - case WIN_GETMEDIASTATUS: - case WIN_MEDIAEJECT: - case WIN_SETMULT: - case WIN_READ_NATIVE_MAX: - case WIN_SET_MAX: - case WIN_READ_NATIVE_MAX_EXT: - case WIN_SET_MAX_EXT: - case WIN_SECURITY_ERASE_PREPARE: - case WIN_SECURITY_FREEZE_LOCK: - case EXABYTE_ENABLE_NEST: - case WIN_DOORLOCK: - case WIN_DOORUNLOCK: - return IDE_DRIVE_TASK_NO_DATA; - case WIN_FORMAT: - case WIN_INIT: - case WIN_DEVICE_RESET: - case WIN_QUEUED_SERVICE: - case WIN_PACKETCMD: - default: - return IDE_DRIVE_TASK_INVALID; - } -} - -/* - * This function is intended to be used prior to invoking ide_do_drive_cmd(). - */ -void ide_init_drive_taskfile (struct request *rq) -{ - memset(rq, 0, sizeof(*rq)); - rq->cmd = IDE_DRIVE_TASK_NO_DATA; -} - -/* - * This is kept for internal use only !!! - * This is an internal call and nobody in user-space has a damn - * reason to call this taskfile. - * - * ide_raw_taskfile is the one that user-space executes. - */ -int ide_wait_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, byte *buf) -{ - struct request rq; - ide_task_t args; - - memset(&args, 0, sizeof(ide_task_t)); - - args.tfRegister[IDE_DATA_OFFSET] = taskfile->data; - args.tfRegister[IDE_FEATURE_OFFSET] = taskfile->feature; - args.tfRegister[IDE_NSECTOR_OFFSET] = taskfile->sector_count; - args.tfRegister[IDE_SECTOR_OFFSET] = taskfile->sector_number; - args.tfRegister[IDE_LCYL_OFFSET] = taskfile->low_cylinder; - args.tfRegister[IDE_HCYL_OFFSET] = taskfile->high_cylinder; - args.tfRegister[IDE_SELECT_OFFSET] = taskfile->device_head; - args.tfRegister[IDE_COMMAND_OFFSET] = taskfile->command; - - args.hobRegister[IDE_DATA_OFFSET_HOB] = hobfile->data; - args.hobRegister[IDE_FEATURE_OFFSET_HOB] = hobfile->feature; - args.hobRegister[IDE_NSECTOR_OFFSET_HOB] = hobfile->sector_count; - args.hobRegister[IDE_SECTOR_OFFSET_HOB] = hobfile->sector_number; - args.hobRegister[IDE_LCYL_OFFSET_HOB] = hobfile->low_cylinder; - args.hobRegister[IDE_HCYL_OFFSET_HOB] = hobfile->high_cylinder; - args.hobRegister[IDE_SELECT_OFFSET_HOB] = hobfile->device_head; - args.hobRegister[IDE_CONTROL_OFFSET_HOB] = hobfile->control; - - ide_init_drive_taskfile(&rq); - /* This is kept for internal use only !!! */ - args.command_type = ide_cmd_type_parser (&args); - if (args.command_type != IDE_DRIVE_TASK_NO_DATA) - rq.current_nr_sectors = rq.nr_sectors = (hobfile->sector_count << 8) | taskfile->sector_count; - - rq.cmd = IDE_DRIVE_TASKFILE; - rq.buffer = buf; - rq.special = &args; - return ide_do_drive_cmd(drive, &rq, ide_wait); -} - -int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, byte *buf) -{ - struct request rq; - ide_init_drive_taskfile(&rq); - rq.cmd = IDE_DRIVE_TASKFILE; - rq.buffer = buf; - - if (args->command_type != IDE_DRIVE_TASK_NO_DATA) - rq.current_nr_sectors = rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET_HOB] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET]; - - rq.special = args; - return ide_do_drive_cmd(drive, &rq, ide_wait); -} - - -#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG -char * ide_ioctl_verbose (unsigned int cmd) -{ - return("unknown"); -} - -char * ide_task_cmd_verbose (byte task) -{ - return("unknown"); -} -#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ - -/* - * The taskfile glue table - * - * reqtask.data_phase reqtask.req_cmd - * args.command_type args.handler - * - * TASKFILE_P_OUT_DMAQ ?? ?? - * TASKFILE_P_IN_DMAQ ?? ?? - * TASKFILE_P_OUT_DMA ?? ?? - * TASKFILE_P_IN_DMA ?? ?? - * TASKFILE_P_OUT ?? ?? - * TASKFILE_P_IN ?? ?? - * - * TASKFILE_OUT_DMAQ IDE_DRIVE_TASK_RAW_WRITE NULL - * TASKFILE_IN_DMAQ IDE_DRIVE_TASK_IN NULL - * - * TASKFILE_OUT_DMA IDE_DRIVE_TASK_RAW_WRITE NULL - * TASKFILE_IN_DMA IDE_DRIVE_TASK_IN NULL - * - * TASKFILE_IN_OUT ?? ?? - * - * TASKFILE_MULTI_OUT IDE_DRIVE_TASK_RAW_WRITE task_mulout_intr - * TASKFILE_MULTI_IN IDE_DRIVE_TASK_IN task_mulin_intr - * - * TASKFILE_OUT IDE_DRIVE_TASK_RAW_WRITE task_out_intr - * TASKFILE_OUT IDE_DRIVE_TASK_OUT task_out_intr - * - * TASKFILE_IN IDE_DRIVE_TASK_IN task_in_intr - * TASKFILE_NO_DATA IDE_DRIVE_TASK_NO_DATA task_no_data_intr - * - * IDE_DRIVE_TASK_SET_XFER task_no_data_intr - * IDE_DRIVE_TASK_INVALID - * - */ - -#define MAX_DMA (256*SECTOR_WORDS) - -int ide_taskfile_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - ide_task_request_t *req_task; - ide_task_t args; - - byte *outbuf = NULL; - byte *inbuf = NULL; - task_ioreg_t *argsptr = args.tfRegister; - task_ioreg_t *hobsptr = args.hobRegister; - int err = 0; - int tasksize = sizeof(struct ide_task_request_s); - int taskin = 0; - int taskout = 0; - - req_task = kmalloc(tasksize, GFP_KERNEL); - if (req_task == NULL) return -ENOMEM; - memset(req_task, 0, tasksize); - if (copy_from_user(req_task, (void *) arg, tasksize)) { - kfree(req_task); - return -EFAULT; - } - - taskout = (int) req_task->out_size; - taskin = (int) req_task->in_size; - - if (taskout) { - int outtotal = tasksize; - outbuf = kmalloc(taskout, GFP_KERNEL); - if (outbuf == NULL) { - err = -ENOMEM; - goto abort; - } - memset(outbuf, 0, taskout); - if (copy_from_user(outbuf, (void *)arg + outtotal, taskout)) { - err = -EFAULT; - goto abort; - } - } - - if (taskin) { - int intotal = tasksize + taskout; - inbuf = kmalloc(taskin, GFP_KERNEL); - if (inbuf == NULL) { - err = -ENOMEM; - goto abort; - } - memset(inbuf, 0, taskin); - if (copy_from_user(inbuf, (void *)arg + intotal , taskin)) { - err = -EFAULT; - goto abort; - } - } - - memset(argsptr, 0, HDIO_DRIVE_TASK_HDR_SIZE); - memset(hobsptr, 0, HDIO_DRIVE_HOB_HDR_SIZE); - memcpy(argsptr, req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE); - memcpy(hobsptr, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE); - - args.tf_in_flags = req_task->in_flags; - args.tf_out_flags = req_task->out_flags; - args.data_phase = req_task->data_phase; - args.command_type = req_task->req_cmd; - -#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG - DTF("%s: ide_ioctl_cmd %s: ide_task_cmd %s\n", - drive->name, - ide_ioctl_verbose(cmd), - ide_task_cmd_verbose(args.tfRegister[IDE_COMMAND_OFFSET])); -#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ - - switch(req_task->data_phase) { - case TASKFILE_OUT_DMAQ: - case TASKFILE_OUT_DMA: - args.prehandler = NULL; - args.handler = NULL; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, outbuf); - break; - case TASKFILE_IN_DMAQ: - case TASKFILE_IN_DMA: - args.prehandler = NULL; - args.handler = NULL; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, inbuf); - break; - case TASKFILE_IN_OUT: -#if 0 - args.prehandler = &pre_task_out_intr; - args.handler = &task_out_intr; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, outbuf); - args.prehandler = NULL; - args.handler = &task_in_intr; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, inbuf); - break; -#else - err = -EFAULT; - goto abort; -#endif - case TASKFILE_MULTI_OUT: - if (drive->mult_count) { - args.prehandler = &pre_task_out_intr; - args.handler = &task_mulout_intr; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, outbuf); - } else { - /* (hs): give up if multcount is not set */ - printk("%s: %s Multimode Write " \ - "multcount is not set\n", - drive->name, __FUNCTION__); - err = -EPERM; - goto abort; - } - break; - case TASKFILE_OUT: - args.prehandler = &pre_task_out_intr; - args.handler = &task_out_intr; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, outbuf); - break; - case TASKFILE_MULTI_IN: - if (drive->mult_count) { - args.prehandler = NULL; - args.handler = &task_mulin_intr; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, inbuf); - } else { - /* (hs): give up if multcount is not set */ - printk("%s: %s Multimode Read failure " \ - "multcount is not set\n", - drive->name, __FUNCTION__); - err = -EPERM; - goto abort; - } - break; - case TASKFILE_IN: - args.prehandler = NULL; - args.handler = &task_in_intr; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, inbuf); - break; - case TASKFILE_NO_DATA: - args.prehandler = NULL; - args.handler = &task_no_data_intr; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, NULL); - break; - default: - args.prehandler = NULL; - args.handler = NULL; - args.posthandler = NULL; - err = -EFAULT; - goto abort; - } - - memcpy(req_task->io_ports, &(args.tfRegister), HDIO_DRIVE_TASK_HDR_SIZE); - memcpy(req_task->hob_ports, &(args.hobRegister), HDIO_DRIVE_HOB_HDR_SIZE); - req_task->in_flags = args.tf_in_flags; - req_task->out_flags = args.tf_out_flags; - - if (copy_to_user((void *)arg, req_task, tasksize)) { - err = -EFAULT; - goto abort; - } - if (taskout) { - int outtotal = tasksize; - if (copy_to_user((void *)arg+outtotal, outbuf, taskout)) { - err = -EFAULT; - goto abort; - } - } - if (taskin) { - int intotal = tasksize + taskout; - if (copy_to_user((void *)arg+intotal, inbuf, taskin)) { - err = -EFAULT; - goto abort; - } - } -abort: - kfree(req_task); - if (outbuf != NULL) - kfree(outbuf); - if (inbuf != NULL) - kfree(inbuf); - return err; -} - -EXPORT_SYMBOL(task_read_24); -EXPORT_SYMBOL(do_rw_taskfile); -EXPORT_SYMBOL(do_taskfile); -// EXPORT_SYMBOL(flagged_taskfile); - -//EXPORT_SYMBOL(ide_end_taskfile); - -EXPORT_SYMBOL(set_multmode_intr); -EXPORT_SYMBOL(set_geometry_intr); -EXPORT_SYMBOL(recal_intr); - -EXPORT_SYMBOL(task_no_data_intr); -EXPORT_SYMBOL(task_in_intr); -EXPORT_SYMBOL(task_mulin_intr); -EXPORT_SYMBOL(pre_task_out_intr); -EXPORT_SYMBOL(task_out_intr); -EXPORT_SYMBOL(task_mulout_intr); - -EXPORT_SYMBOL(ide_init_drive_taskfile); -EXPORT_SYMBOL(ide_wait_taskfile); -EXPORT_SYMBOL(ide_raw_taskfile); -EXPORT_SYMBOL(ide_pre_handler_parser); -EXPORT_SYMBOL(ide_handler_parser); -EXPORT_SYMBOL(ide_cmd_type_parser); -EXPORT_SYMBOL(ide_taskfile_ioctl); - -#ifdef CONFIG_PKT_TASK_IOCTL - -#if 0 -{ - -{ /* start cdrom */ - - struct cdrom_info *info = drive->driver_data; - - if (info->dma) { - if (info->cmd == READ) { - info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive); - } else if (info->cmd == WRITE) { - info->dma = !HWIF(drive)->dmaproc(ide_dma_write, drive); - } else { - printk("ide-cd: DMA set, but not allowed\n"); - } - } - - /* Set up the controller registers. */ - OUT_BYTE (info->dma, IDE_FEATURE_REG); - OUT_BYTE (0, IDE_NSECTOR_REG); - OUT_BYTE (0, IDE_SECTOR_REG); - - OUT_BYTE (xferlen & 0xff, IDE_LCYL_REG); - OUT_BYTE (xferlen >> 8 , IDE_HCYL_REG); - if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl, IDE_CONTROL_REG); - - if (info->dma) - (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); - - if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { - ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry); - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ - return ide_started; - } else { - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ - return (*handler) (drive); - } - -} /* end cdrom */ - -{ /* start floppy */ - - idefloppy_floppy_t *floppy = drive->driver_data; - idefloppy_bcount_reg_t bcount; - int dma_ok = 0; - - floppy->pc=pc; /* Set the current packet command */ - - pc->retries++; - pc->actually_transferred=0; /* We haven't transferred any data yet */ - pc->current_position=pc->buffer; - bcount.all = IDE_MIN(pc->request_transfer, 63 * 1024); - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) { - (void) HWIF(drive)->dmaproc(ide_dma_off, drive); - } - if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) - dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive); -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl,IDE_CONTROL_REG); - OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */ - OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG); - OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG); - OUT_BYTE (drive->select.all,IDE_SELECT_REG); - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (dma_ok) { /* Begin DMA, if necessary */ - set_bit (PC_DMA_IN_PROGRESS, &pc->flags); - (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -} /* end floppy */ - -{ /* start tape */ - - idetape_tape_t *tape = drive->driver_data; - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) { - printk (KERN_WARNING "ide-tape: DMA disabled, reverting to PIO\n"); - (void) HWIF(drive)->dmaproc(ide_dma_off, drive); - } - if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) - dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive); -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl,IDE_CONTROL_REG); - OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */ - OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG); - OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG); - OUT_BYTE (drive->select.all,IDE_SELECT_REG); -#ifdef CONFIG_BLK_DEV_IDEDMA - if (dma_ok) { /* Begin DMA, if necessary */ - set_bit (PC_DMA_IN_PROGRESS, &pc->flags); - (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { - ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL); - OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); - return ide_started; - } else { - OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); - return idetape_transfer_pc(drive); - } - -} /* end tape */ - -} -#endif - -int pkt_taskfile_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ -#if 0 - switch(req_task->data_phase) { - case TASKFILE_P_OUT_DMAQ: - case TASKFILE_P_IN_DMAQ: - case TASKFILE_P_OUT_DMA: - case TASKFILE_P_IN_DMA: - case TASKFILE_P_OUT: - case TASKFILE_P_IN: - } -#endif - return -ENOMSG; -} - -EXPORT_SYMBOL(pkt_taskfile_ioctl); - -#endif /* CONFIG_PKT_TASK_IOCTL */ diff --git a/xen/drivers/ide/ide-xen.c b/xen/drivers/ide/ide-xen.c deleted file mode 100644 index c925ab0c36..0000000000 --- a/xen/drivers/ide/ide-xen.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -static kdev_t ide_devs[] = { - MKDEV(IDE0_MAJOR, 0), MKDEV(IDE0_MAJOR, 64), /* hda, hdb */ - MKDEV(IDE1_MAJOR, 0), MKDEV(IDE1_MAJOR, 64), /* hdc, hdd */ - MKDEV(IDE2_MAJOR, 0), MKDEV(IDE2_MAJOR, 64), /* hde, hdf */ - MKDEV(IDE3_MAJOR, 0), MKDEV(IDE3_MAJOR, 64), /* hdg, hdh */ - MKDEV(IDE4_MAJOR, 0), MKDEV(IDE4_MAJOR, 64), /* hdi, hdj */ - MKDEV(IDE5_MAJOR, 0), MKDEV(IDE5_MAJOR, 64), /* hdk, hdl */ - MKDEV(IDE6_MAJOR, 0), MKDEV(IDE6_MAJOR, 64), /* hdm, hdn */ - MKDEV(IDE7_MAJOR, 0), MKDEV(IDE7_MAJOR, 64), /* hdo, hdp */ - MKDEV(IDE8_MAJOR, 0), MKDEV(IDE8_MAJOR, 64), /* hdq, hdr */ - MKDEV(IDE9_MAJOR, 0), MKDEV(IDE9_MAJOR, 64) /* hds, hdt */ -}; - -void ide_probe_devices(xen_disk_info_t* xdi) -{ - int i, unit; - ide_drive_t *drive; - xen_disk_t *xd = &xdi->disks[xdi->count]; - - for ( i = 0; i < MAX_HWIFS; i++ ) - { - ide_hwif_t *hwif = &ide_hwifs[i]; - if ( !hwif->present ) continue; - - for ( unit = 0; unit < MAX_DRIVES; unit++ ) - { - drive = &hwif->drives[unit]; - - if ( !drive->present ) - continue; - - if ( xdi->count == xdi->max ) - BUG(); - - /* We export 'raw' linux device numbers to domain 0. */ - xd->device = ide_devs[(i * MAX_DRIVES) + unit]; - - /* - * NB: we use the ide 'media' field (ide_disk, ide_cdrom, etc) as - * our 'type' field (XD_TYPE_DISK, XD_TYPE_CDROM, etc). Hence must - * ensure these are kept in sync. - */ - if ( (xd->info = drive->media) == XD_TYPE_CDROM ) - xd->info |= XD_FLAG_RO; - - xd->capacity = current_capacity(drive); - xd->domain = 0; - - xdi->count++; - xd++; - } - } -} diff --git a/xen/drivers/ide/ide.c b/xen/drivers/ide/ide.c deleted file mode 100644 index e7e278255e..0000000000 --- a/xen/drivers/ide/ide.c +++ /dev/null @@ -1,4211 +0,0 @@ -/* - * linux/drivers/ide/ide.c Version 6.31 June 9, 2000 - * - * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) - */ - -/* - * Mostly written by Mark Lord - * and Gadi Oxman - * and Andre Hedrick - * - * See linux/MAINTAINERS for address of current maintainer. - * - * This is the multiple IDE interface driver, as evolved from hd.c. - * It supports up to MAX_HWIFS IDE interfaces, on one or more IRQs (usually 14 & 15). - * There can be up to two drives per interface, as per the ATA-2 spec. - * - * Primary: ide0, port 0x1f0; major=3; hda is minor=0; hdb is minor=64 - * Secondary: ide1, port 0x170; major=22; hdc is minor=0; hdd is minor=64 - * Tertiary: ide2, port 0x???; major=33; hde is minor=0; hdf is minor=64 - * Quaternary: ide3, port 0x???; major=34; hdg is minor=0; hdh is minor=64 - * ... - * - * From hd.c: - * | - * | It traverses the request-list, using interrupts to jump between functions. - * | As nearly all functions can be called within interrupts, we may not sleep. - * | Special care is recommended. Have Fun! - * | - * | modified by Drew Eckhardt to check nr of hd's from the CMOS. - * | - * | Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug - * | in the early extended-partition checks and added DM partitions. - * | - * | Early work on error handling by Mika Liljeberg (liljeber@cs.Helsinki.FI). - * | - * | IRQ-unmask, drive-id, multiple-mode, support for ">16 heads", - * | and general streamlining by Mark Lord (mlord@pobox.com). - * - * October, 1994 -- Complete line-by-line overhaul for linux 1.1.x, by: - * - * Mark Lord (mlord@pobox.com) (IDE Perf.Pkg) - * Delman Lee (delman@ieee.org) ("Mr. atdisk2") - * Scott Snyder (snyder@fnald0.fnal.gov) (ATAPI IDE cd-rom) - * - * This was a rewrite of just about everything from hd.c, though some original - * code is still sprinkled about. Think of it as a major evolution, with - * inspiration from lots of linux users, esp. hamish@zot.apana.org.au - * - * Version 1.0 ALPHA initial code, primary i/f working okay - * Version 1.3 BETA dual i/f on shared irq tested & working! - * Version 1.4 BETA added auto probing for irq(s) - * Version 1.5 BETA added ALPHA (untested) support for IDE cd-roms, - * ... - * Version 5.50 allow values as small as 20 for idebus= - * Version 5.51 force non io_32bit in drive_cmd_intr() - * change delay_10ms() to delay_50ms() to fix problems - * Version 5.52 fix incorrect invalidation of removable devices - * add "hdx=slow" command line option - * Version 5.60 start to modularize the driver; the disk and ATAPI - * drivers can be compiled as loadable modules. - * move IDE probe code to ide-probe.c - * move IDE disk code to ide-disk.c - * add support for generic IDE device subdrivers - * add m68k code from Geert Uytterhoeven - * probe all interfaces by default - * add ioctl to (re)probe an interface - * Version 6.00 use per device request queues - * attempt to optimize shared hwgroup performance - * add ioctl to manually adjust bandwidth algorithms - * add kerneld support for the probe module - * fix bug in ide_error() - * fix bug in the first ide_get_lock() call for Atari - * don't flush leftover data for ATAPI devices - * Version 6.01 clear hwgroup->active while the hwgroup sleeps - * support HDIO_GETGEO for floppies - * Version 6.02 fix ide_ack_intr() call - * check partition table on floppies - * Version 6.03 handle bad status bit sequencing in ide_wait_stat() - * Version 6.10 deleted old entries from this list of updates - * replaced triton.c with ide-dma.c generic PCI DMA - * added support for BIOS-enabled UltraDMA - * rename all "promise" things to "pdc4030" - * fix EZ-DRIVE handling on small disks - * Version 6.11 fix probe error in ide_scan_devices() - * fix ancient "jiffies" polling bugs - * mask all hwgroup interrupts on each irq entry - * Version 6.12 integrate ioctl and proc interfaces - * fix parsing of "idex=" command line parameter - * Version 6.13 add support for ide4/ide5 courtesy rjones@orchestream.com - * Version 6.14 fixed IRQ sharing among PCI devices - * Version 6.15 added SMP awareness to IDE drivers - * Version 6.16 fixed various bugs; even more SMP friendly - * Version 6.17 fix for newest EZ-Drive problem - * Version 6.18 default unpartitioned-disk translation now "BIOS LBA" - * Version 6.19 Re-design for a UNIFORM driver for all platforms, - * model based on suggestions from Russell King and - * Geert Uytterhoeven - * Promise DC4030VL now supported. - * add support for ide6/ide7 - * delay_50ms() changed to ide_delay_50ms() and exported. - * Version 6.20 Added/Fixed Generic ATA-66 support and hwif detection. - * Added hdx=flash to allow for second flash disk - * detection w/o the hang loop. - * Added support for ide8/ide9 - * Added idex=ata66 for the quirky chipsets that are - * ATA-66 compliant, but have yet to determine a method - * of verification of the 80c cable presence. - * Specifically Promise's PDC20262 chipset. - * Version 6.21 Fixing/Fixed SMP spinlock issue with insight from an old - * hat that clarified original low level driver design. - * Version 6.30 Added SMP support; fixed multmode issues. -ml - * Version 6.31 Debug Share INTR's and request queue streaming - * Native ATA-100 support - * Prep for Cascades Project - * - * Some additional driver compile-time options are in ./include/linux/ide.h - * - * To do, in likely order of completion: - * - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f - * - */ - -#define REVISION "Revision: 6.31" -#define VERSION "Id: ide.c 6.31 2000/06/09" - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - -#define _IDE_C /* Tell ide.h it's really us */ - -#include -#include -#include -#include -/*#include */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/*#include */ -/*#include */ -/*#include */ - -#include -#include -#include -#include -#include -#include - -#include "ide_modes.h" - -#ifdef CONFIG_KMOD -#include -#endif /* CONFIG_KMOD */ - -#ifdef CONFIG_IDE_TASKFILE_IO -# define __TASKFILE__IO -#else /* CONFIG_IDE_TASKFILE_IO */ -# undef __TASKFILE__IO -#endif /* CONFIG_IDE_TASKFILE_IO */ - -#ifdef __TASKFILE__IO -#else /* !__TASKFILE__IO */ -#endif /* __TASKFILE__IO */ - - - - -/* XXXXXXXXXXXX This may be replaced by fs/block_dev.c versions!!! XXXXX */ -/* (only included here so the hypervisor will link :-) */ -int check_disk_change(kdev_t dev) { return 0; } -int unregister_blkdev(unsigned int major, const char * name) { return 0; } -/* And these ones are from fs/inode.c... */ -int invalidate_device(kdev_t dev, int do_sync) { return 0; } -/* fs/buffer.c... */ -void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers) { } -/* fs/devices.c... */ -const char * kdevname(kdev_t dev) { return NULL; } -/* End of XXXXXX region */ - - - - -/* default maximum number of failures */ -#define IDE_DEFAULT_MAX_FAILURES 1 - -static const byte ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR }; - -static int idebus_parameter; /* holds the "idebus=" parameter */ -static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ -static int initializing; /* set while initializing built-in drivers */ - -#ifdef CONFIG_BLK_DEV_IDEPCI -static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */ -#endif /* CONFIG_BLK_DEV_IDEPCI */ - -#if defined(__mc68000__) || defined(CONFIG_APUS) -/* - * ide_lock is used by the Atari code to obtain access to the IDE interrupt, - * which is shared between several drivers. - */ -static int ide_lock; -#endif /* __mc68000__ || CONFIG_APUS */ - -int noautodma = 0; - -/* - * ide_modules keeps track of the available IDE chipset/probe/driver modules. - */ -ide_module_t *ide_modules; -ide_module_t *ide_probe; - -/* - * This is declared extern in ide.h, for access by other IDE modules: - */ -ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */ - -#if (DISK_RECOVERY_TIME > 0) -/* - * For really screwy hardware (hey, at least it *can* be used with Linux) - * we can enforce a minimum delay time between successive operations. - */ -static unsigned long read_timer (void) -{ - unsigned long t, flags; - int i; - - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - t = jiffies * 11932; - outb_p(0, 0x43); - i = inb_p(0x40); - i |= inb(0x40) << 8; - __restore_flags(flags); /* local CPU only */ - return (t - i); -} -#endif /* DISK_RECOVERY_TIME */ - -static inline void set_recovery_timer (ide_hwif_t *hwif) -{ -#if (DISK_RECOVERY_TIME > 0) - hwif->last_time = read_timer(); -#endif /* DISK_RECOVERY_TIME */ -} - -/* - * Do not even *think* about calling this! - */ -static void init_hwif_data (unsigned int index) -{ - unsigned int unit; - hw_regs_t hw; - ide_hwif_t *hwif = &ide_hwifs[index]; - - /* bulk initialize hwif & drive info with zeros */ - memset(hwif, 0, sizeof(ide_hwif_t)); - memset(&hw, 0, sizeof(hw_regs_t)); - - /* fill in any non-zero initial values */ - hwif->index = index; - ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq); - memcpy(&hwif->hw, &hw, sizeof(hw)); - memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports)); - hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; -#ifdef CONFIG_BLK_DEV_HD - if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) - hwif->noprobe = 1; /* may be overridden by ide_setup() */ -#endif /* CONFIG_BLK_DEV_HD */ - hwif->major = ide_hwif_to_major[index]; - hwif->name[0] = 'i'; - hwif->name[1] = 'd'; - hwif->name[2] = 'e'; - hwif->name[3] = '0' + index; - hwif->bus_state = BUSSTATE_ON; - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - - drive->media = ide_disk; - drive->select.all = (unit<<4)|0xa0; - drive->hwif = hwif; - drive->ctl = 0x08; - drive->ready_stat = READY_STAT; - drive->bad_wstat = BAD_W_STAT; - drive->special.b.recalibrate = 1; - drive->special.b.set_geometry = 1; - drive->name[0] = 'h'; - drive->name[1] = 'd'; - drive->name[2] = 'a' + (index * MAX_DRIVES) + unit; - drive->max_failures = IDE_DEFAULT_MAX_FAILURES; - /*init_waitqueue_head(&drive->wqueue);*/ - } -} - -/* - * init_ide_data() sets reasonable default values into all fields - * of all instances of the hwifs and drives, but only on the first call. - * Subsequent calls have no effect (they don't wipe out anything). - * - * This routine is normally called at driver initialization time, - * but may also be called MUCH earlier during kernel "command-line" - * parameter processing. As such, we cannot depend on any other parts - * of the kernel (such as memory allocation) to be functioning yet. - * - * This is too bad, as otherwise we could dynamically allocate the - * ide_drive_t structs as needed, rather than always consuming memory - * for the max possible number (MAX_HWIFS * MAX_DRIVES) of them. - */ -#define MAGIC_COOKIE 0x12345678 -static void __init init_ide_data (void) -{ - unsigned int index; - static unsigned long magic_cookie = MAGIC_COOKIE; - - if (magic_cookie != MAGIC_COOKIE) - return; /* already initialized */ - magic_cookie = 0; - - /* Initialise all interface structures */ - for (index = 0; index < MAX_HWIFS; ++index) - init_hwif_data(index); - - /* Add default hw interfaces */ - ide_init_default_hwifs(); - - idebus_parameter = 0; - system_bus_speed = 0; -} - -/* - * CompactFlash cards and their brethern pretend to be removable hard disks, except: - * (1) they never have a slave unit, and - * (2) they don't have doorlock mechanisms. - * This test catches them, and is invoked elsewhere when setting appropriate config bits. - * - * FIXME: This treatment is probably applicable for *all* PCMCIA (PC CARD) devices, - * so in linux 2.3.x we should change this to just treat all PCMCIA drives this way, - * and get rid of the model-name tests below (too big of an interface change for 2.2.x). - * At that time, we might also consider parameterizing the timeouts and retries, - * since these are MUCH faster than mechanical drives. -M.Lord - */ -int drive_is_flashcard (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - - if (drive->removable && id != NULL) { - if (id->config == 0x848a) return 1; /* CompactFlash */ - if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */ - || !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */ - || !strncmp(id->model, "SunDisk SDCFB", 13) /* SunDisk */ - || !strncmp(id->model, "HAGIWARA HPC", 12) /* Hagiwara */ - || !strncmp(id->model, "LEXAR ATA_FLASH", 15) /* Lexar */ - || !strncmp(id->model, "ATA_FLASH", 9)) /* Simple Tech */ - { - return 1; /* yes, it is a flash memory card */ - } - } - return 0; /* no, it is not a flash memory card */ -} - -/* - * ide_system_bus_speed() returns what we think is the system VESA/PCI - * bus speed (in MHz). This is used for calculating interface PIO timings. - * The default is 40 for known PCI systems, 50 otherwise. - * The "idebus=xx" parameter can be used to override this value. - * The actual value to be used is computed/displayed the first time through. - */ -int ide_system_bus_speed (void) -{ - if (!system_bus_speed) { - if (idebus_parameter) - system_bus_speed = idebus_parameter; /* user supplied value */ -#ifdef CONFIG_PCI - else if (pci_present()) - system_bus_speed = 33; /* safe default value for PCI */ -#endif /* CONFIG_PCI */ - else - system_bus_speed = 50; /* safe default value for VESA and PCI */ - printk("ide: Assuming %dMHz system bus speed for PIO modes%s\n", system_bus_speed, - idebus_parameter ? "" : "; override with idebus=xx"); - } - return system_bus_speed; -} - -#if SUPPORT_VLB_SYNC -/* - * Some localbus EIDE interfaces require a special access sequence - * when using 32-bit I/O instructions to transfer data. We call this - * the "vlb_sync" sequence, which consists of three successive reads - * of the sector count register location, with interrupts disabled - * to ensure that the reads all happen together. - */ -static inline void do_vlb_sync (ide_ioreg_t port) { - (void) inb (port); - (void) inb (port); - (void) inb (port); -} -#endif /* SUPPORT_VLB_SYNC */ - -/* - * This is used for most PIO data transfers *from* the IDE interface - */ -void ide_input_data (ide_drive_t *drive, void *vbuffer, unsigned int wcount) -{ - void *buffer; - byte io_32bit; - - /* first check if this controller has defined a special function - * for handling polled ide transfers - */ - - if(HWIF(drive)->ideproc) { - HWIF(drive)->ideproc(ideproc_ide_input_data, - drive, vbuffer, wcount); - return; - } - - /* We assume controllers own functions will make their own - * arrangemnets for mapping/unmaping the destination mem if - * required (or not if DMA) - */ - - buffer = map_domain_mem(virt_to_phys(vbuffer)); - - io_32bit = drive->io_32bit; - - if (io_32bit) { -#if SUPPORT_VLB_SYNC - if (io_32bit & 2) { - unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - do_vlb_sync(IDE_NSECTOR_REG); - insl(IDE_DATA_REG, buffer, wcount); - __restore_flags(flags); /* local CPU only */ - } else -#endif /* SUPPORT_VLB_SYNC */ - insl(IDE_DATA_REG, buffer, wcount); - } else { -#if SUPPORT_SLOW_DATA_PORTS - if (drive->slow) { - unsigned short *ptr = (unsigned short *) buffer; - while (wcount--) { - *ptr++ = inw_p(IDE_DATA_REG); - *ptr++ = inw_p(IDE_DATA_REG); - } - } else -#endif /* SUPPORT_SLOW_DATA_PORTS */ - insw(IDE_DATA_REG, buffer, wcount<<1); - } - - unmap_domain_mem(buffer); -} - -/* - * This is used for most PIO data transfers *to* the IDE interface - */ -void ide_output_data (ide_drive_t *drive, void *vbuffer, unsigned int wcount) -{ - void *buffer; - byte io_32bit; - - if(HWIF(drive)->ideproc) { - HWIF(drive)->ideproc(ideproc_ide_output_data, - drive, vbuffer, wcount); - return; - } - - buffer = map_domain_mem(virt_to_phys(vbuffer)); - - io_32bit = drive->io_32bit; - - if (io_32bit) { -#if SUPPORT_VLB_SYNC - if (io_32bit & 2) { - unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - do_vlb_sync(IDE_NSECTOR_REG); - outsl(IDE_DATA_REG, buffer, wcount); - __restore_flags(flags); /* local CPU only */ - } else -#endif /* SUPPORT_VLB_SYNC */ - outsl(IDE_DATA_REG, buffer, wcount); - } else { -#if SUPPORT_SLOW_DATA_PORTS - if (drive->slow) { - unsigned short *ptr = (unsigned short *) buffer; - while (wcount--) { - outw_p(*ptr++, IDE_DATA_REG); - outw_p(*ptr++, IDE_DATA_REG); - } - } else -#endif /* SUPPORT_SLOW_DATA_PORTS */ - outsw(IDE_DATA_REG, buffer, wcount<<1); - } - - unmap_domain_mem(buffer); -} - -/* - * The following routines are mainly used by the ATAPI drivers. - * - * These routines will round up any request for an odd number of bytes, - * so if an odd bytecount is specified, be sure that there's at least one - * extra byte allocated for the buffer. - */ -void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) -{ - if(HWIF(drive)->ideproc) { - HWIF(drive)->ideproc(ideproc_atapi_input_bytes, - drive, buffer, bytecount); - return; - } - ++bytecount; -#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) - if (MACH_IS_ATARI || MACH_IS_Q40) { - /* Atari has a byte-swapped IDE interface */ - insw_swapw(IDE_DATA_REG, buffer, bytecount / 2); - return; - } -#endif /* CONFIG_ATARI */ - ide_input_data (drive, buffer, bytecount / 4); - if ((bytecount & 0x03) >= 2) - insw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1); -} - -void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) -{ - if(HWIF(drive)->ideproc) { - HWIF(drive)->ideproc(ideproc_atapi_output_bytes, - drive, buffer, bytecount); - return; - } - - ++bytecount; -#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) - if (MACH_IS_ATARI || MACH_IS_Q40) { - /* Atari has a byte-swapped IDE interface */ - outsw_swapw(IDE_DATA_REG, buffer, bytecount / 2); - return; - } -#endif /* CONFIG_ATARI */ - ide_output_data (drive, buffer, bytecount / 4); - if ((bytecount & 0x03) >= 2) - outsw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1); -} - -/* - * Needed for PCI irq sharing - */ -//static inline -int drive_is_ready (ide_drive_t *drive) -{ - byte stat = 0; - if (drive->waiting_for_dma) - return HWIF(drive)->dmaproc(ide_dma_test_irq, drive); -#if 0 - udelay(1); /* need to guarantee 400ns since last command was issued */ -#endif - -#ifdef CONFIG_IDEPCI_SHARE_IRQ - /* - * We do a passive status test under shared PCI interrupts on - * cards that truly share the ATA side interrupt, but may also share - * an interrupt with another pci card/device. We make no assumptions - * about possible isa-pnp and pci-pnp issues yet. - */ - if (IDE_CONTROL_REG) - stat = GET_ALTSTAT(); - else -#endif /* CONFIG_IDEPCI_SHARE_IRQ */ - stat = GET_STAT(); /* Note: this may clear a pending IRQ!! */ - - if (stat & BUSY_STAT) - return 0; /* drive busy: definitely not interrupting */ - return 1; /* drive ready: *might* be interrupting */ -} - -/* - * This is our end_request replacement function. - */ -void ide_end_request (byte uptodate, ide_hwgroup_t *hwgroup) -{ - struct request *rq; - unsigned long flags; - ide_drive_t *drive = hwgroup->drive; - - spin_lock_irqsave(&io_request_lock, flags); - rq = hwgroup->rq; - - /* - * decide whether to reenable DMA -- 3 is a random magic for now, - * if we DMA timeout more than 3 times, just stay in PIO - */ - if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { - drive->state = 0; - hwgroup->hwif->dmaproc(ide_dma_on, drive); - } - - if (!end_that_request_first(rq, uptodate, hwgroup->drive->name)) { - add_blkdev_randomness(MAJOR(rq->rq_dev)); - blkdev_dequeue_request(rq); - hwgroup->rq = NULL; - end_that_request_last(rq); - } - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * This should get invoked any time we exit the driver to - * wait for an interrupt response from a drive. handler() points - * at the appropriate code to handle the next interrupt, and a - * timer is started to prevent us from waiting forever in case - * something goes wrong (see the ide_timer_expiry() handler later on). - */ -void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, - unsigned int timeout, ide_expiry_t *expiry) -{ - unsigned long flags; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - - spin_lock_irqsave(&io_request_lock, flags); - if (hwgroup->handler != NULL) { - printk("%s: ide_set_handler: handler not null; old=%p, new=%p\n", - drive->name, hwgroup->handler, handler); - } - hwgroup->handler = handler; - hwgroup->expiry = expiry; - hwgroup->timer.expires = jiffies + timeout; - add_timer(&hwgroup->timer); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * current_capacity() returns the capacity (in sectors) of a drive - * according to its current geometry/LBA settings. - */ -unsigned long current_capacity (ide_drive_t *drive) -{ - if (!drive->present) - return 0; - if (drive->driver != NULL) - return DRIVER(drive)->capacity(drive); - return 0; -} - -extern struct block_device_operations ide_fops[]; -/* - * ide_geninit() is called exactly *once* for each interface. - */ -void ide_geninit (ide_hwif_t *hwif) -{ - unsigned int unit; - struct gendisk *gd = hwif->gd; - - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - - if (!drive->present) - continue; - if (drive->media!=ide_disk && drive->media!=ide_floppy) - continue; - register_disk(gd,MKDEV(hwif->major,unit<forced_geom && drive->noprobe) ? 1 : -#endif /* CONFIG_BLK_DEV_ISAPNP */ - 1<name); - } else { - if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) { - ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL); - return ide_started; /* continue polling */ - } - hwgroup->poll_timeout = 0; /* end of polling */ - printk("%s: ATAPI reset timed-out, status=0x%02x\n", drive->name, stat); - return do_reset1 (drive, 1); /* do it the old fashioned way */ - } - hwgroup->poll_timeout = 0; /* done polling */ - return ide_stopped; -} - -/* - * reset_pollfunc() gets invoked to poll the interface for completion every 50ms - * during an ide reset operation. If the drives have not yet responded, - * and we have not yet hit our maximum waiting time, then the timer is restarted - * for another 50ms. - */ -static ide_startstop_t reset_pollfunc (ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - ide_hwif_t *hwif = HWIF(drive); - byte tmp; - - if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) { - if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) { - ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL); - return ide_started; /* continue polling */ - } - printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp); - drive->failures++; - } else { - printk("%s: reset: ", hwif->name); - if ((tmp = GET_ERR()) == 1) { - printk("success\n"); - drive->failures = 0; - } else { - drive->failures++; -#if FANCY_STATUS_DUMPS - printk("master: "); - switch (tmp & 0x7f) { - case 1: printk("passed"); - break; - case 2: printk("formatter device error"); - break; - case 3: printk("sector buffer error"); - break; - case 4: printk("ECC circuitry error"); - break; - case 5: printk("controlling MPU error"); - break; - default:printk("error (0x%02x?)", tmp); - } - if (tmp & 0x80) - printk("; slave: failed"); - printk("\n"); -#else - printk("failed\n"); -#endif /* FANCY_STATUS_DUMPS */ - } - } - hwgroup->poll_timeout = 0; /* done polling */ - return ide_stopped; -} - -static void check_dma_crc (ide_drive_t *drive) -{ - if (drive->crc_count) { - (void) HWIF(drive)->dmaproc(ide_dma_off_quietly, drive); - if ((HWIF(drive)->speedproc) != NULL) - HWIF(drive)->speedproc(drive, ide_auto_reduce_xfer(drive)); - if (drive->current_speed >= XFER_SW_DMA_0) - (void) HWIF(drive)->dmaproc(ide_dma_on, drive); - } else { - (void) HWIF(drive)->dmaproc(ide_dma_off, drive); - } -} - -static void pre_reset (ide_drive_t *drive) -{ - if (drive->driver != NULL) - DRIVER(drive)->pre_reset(drive); - - if (!drive->keep_settings) { - if (drive->using_dma) { - check_dma_crc(drive); - } else { - drive->unmask = 0; - drive->io_32bit = 0; - } - return; - } - if (drive->using_dma) - check_dma_crc(drive); -} - -/* - * do_reset1() attempts to recover a confused drive by resetting it. - * Unfortunately, resetting a disk drive actually resets all devices on - * the same interface, so it can really be thought of as resetting the - * interface rather than resetting the drive. - * - * ATAPI devices have their own reset mechanism which allows them to be - * individually reset without clobbering other devices on the same interface. - * - * Unfortunately, the IDE interface does not generate an interrupt to let - * us know when the reset operation has finished, so we must poll for this. - * Equally poor, though, is the fact that this may a very long time to complete, - * (up to 30 seconds worstcase). So, instead of busy-waiting here for it, - * we set a timer to poll at 50ms intervals. - */ -static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) -{ - unsigned int unit; - unsigned long flags; - ide_hwif_t *hwif = HWIF(drive); - ide_hwgroup_t *hwgroup = HWGROUP(drive); - - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - - /* For an ATAPI device, first try an ATAPI SRST. */ - if (drive->media != ide_disk && !do_not_try_atapi) { - pre_reset(drive); - SELECT_DRIVE(hwif,drive); - udelay (20); - OUT_BYTE (WIN_SRST, IDE_COMMAND_REG); - hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL); - __restore_flags (flags); /* local CPU only */ - return ide_started; - } - - /* - * First, reset any device state data we were maintaining - * for any of the drives on this interface. - */ - for (unit = 0; unit < MAX_DRIVES; ++unit) - pre_reset(&hwif->drives[unit]); - -#if OK_TO_RESET_CONTROLLER - if (!IDE_CONTROL_REG) { - __restore_flags(flags); - return ide_stopped; - } - /* - * Note that we also set nIEN while resetting the device, - * to mask unwanted interrupts from the interface during the reset. - * However, due to the design of PC hardware, this will cause an - * immediate interrupt due to the edge transition it produces. - * This single interrupt gives us a "fast poll" for drives that - * recover from reset very quickly, saving us the first 50ms wait time. - */ - OUT_BYTE(drive->ctl|6,IDE_CONTROL_REG); /* set SRST and nIEN */ - udelay(10); /* more than enough time */ - if (drive->quirk_list == 2) { - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear SRST and nIEN */ - } else { - OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* clear SRST, leave nIEN */ - } - udelay(10); /* more than enough time */ - hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL); - - /* - * Some weird controller like resetting themselves to a strange - * state when the disks are reset this way. At least, the Winbond - * 553 documentation says that - */ - if (hwif->resetproc != NULL) - hwif->resetproc(drive); - -#endif /* OK_TO_RESET_CONTROLLER */ - - __restore_flags (flags); /* local CPU only */ - return ide_started; -} - -/* - * ide_do_reset() is the entry point to the drive/interface reset code. - */ -ide_startstop_t ide_do_reset (ide_drive_t *drive) -{ - return do_reset1 (drive, 0); -} - -static inline u32 read_24 (ide_drive_t *drive) -{ - return (IN_BYTE(IDE_HCYL_REG)<<16) | - (IN_BYTE(IDE_LCYL_REG)<<8) | - IN_BYTE(IDE_SECTOR_REG); -} - -/* - * Clean up after success/failure of an explicit drive cmd - */ -void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err) -{ - unsigned long flags; - struct request *rq; - - spin_lock_irqsave(&io_request_lock, flags); - rq = HWGROUP(drive)->rq; - spin_unlock_irqrestore(&io_request_lock, flags); - - switch(rq->cmd) { - case IDE_DRIVE_CMD: - { - byte *args = (byte *) rq->buffer; - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - if (args) { - args[0] = stat; - args[1] = err; - args[2] = IN_BYTE(IDE_NSECTOR_REG); - } - break; - } - case IDE_DRIVE_TASK: - { - byte *args = (byte *) rq->buffer; - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - if (args) { - args[0] = stat; - args[1] = err; - args[2] = IN_BYTE(IDE_NSECTOR_REG); - args[3] = IN_BYTE(IDE_SECTOR_REG); - args[4] = IN_BYTE(IDE_LCYL_REG); - args[5] = IN_BYTE(IDE_HCYL_REG); - args[6] = IN_BYTE(IDE_SELECT_REG); - } - break; - } - case IDE_DRIVE_TASKFILE: - { - ide_task_t *args = (ide_task_t *) rq->special; - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - if (args) { - if (args->tf_in_flags.b.data) { - unsigned short data = IN_WORD(IDE_DATA_REG); - args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF; - args->hobRegister[IDE_DATA_OFFSET_HOB] = (data >> 8) & 0xFF; - } - args->tfRegister[IDE_ERROR_OFFSET] = err; - args->tfRegister[IDE_NSECTOR_OFFSET] = IN_BYTE(IDE_NSECTOR_REG); - args->tfRegister[IDE_SECTOR_OFFSET] = IN_BYTE(IDE_SECTOR_REG); - args->tfRegister[IDE_LCYL_OFFSET] = IN_BYTE(IDE_LCYL_REG); - args->tfRegister[IDE_HCYL_OFFSET] = IN_BYTE(IDE_HCYL_REG); - args->tfRegister[IDE_SELECT_OFFSET] = IN_BYTE(IDE_SELECT_REG); - args->tfRegister[IDE_STATUS_OFFSET] = stat; - - if ((drive->id->command_set_2 & 0x0400) && - (drive->id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG_HOB); - args->hobRegister[IDE_FEATURE_OFFSET_HOB] = IN_BYTE(IDE_FEATURE_REG); - args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = IN_BYTE(IDE_NSECTOR_REG); - args->hobRegister[IDE_SECTOR_OFFSET_HOB] = IN_BYTE(IDE_SECTOR_REG); - args->hobRegister[IDE_LCYL_OFFSET_HOB] = IN_BYTE(IDE_LCYL_REG); - args->hobRegister[IDE_HCYL_OFFSET_HOB] = IN_BYTE(IDE_HCYL_REG); - } - } - break; - } - default: - break; - } - spin_lock_irqsave(&io_request_lock, flags); - blkdev_dequeue_request(rq); - HWGROUP(drive)->rq = NULL; - end_that_request_last(rq); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * Error reporting, in human readable form (luxurious, but a memory hog). - */ -byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat) -{ - unsigned long flags; - byte err = 0; - - __save_flags (flags); /* local CPU only */ - ide__sti(); /* local CPU only */ - printk("%s: %s: status=0x%02x", drive->name, msg, stat); -#if FANCY_STATUS_DUMPS - printk(" { "); - if (stat & BUSY_STAT) - printk("Busy "); - else { - if (stat & READY_STAT) printk("DriveReady "); - if (stat & WRERR_STAT) printk("DeviceFault "); - if (stat & SEEK_STAT) printk("SeekComplete "); - if (stat & DRQ_STAT) printk("DataRequest "); - if (stat & ECC_STAT) printk("CorrectedError "); - if (stat & INDEX_STAT) printk("Index "); - if (stat & ERR_STAT) printk("Error "); - } - printk("}"); -#endif /* FANCY_STATUS_DUMPS */ - printk("\n"); - if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { - err = GET_ERR(); - printk("%s: %s: error=0x%02x", drive->name, msg, err); -#if FANCY_STATUS_DUMPS - if (drive->media == ide_disk) { - printk(" { "); - if (err & ABRT_ERR) printk("DriveStatusError "); - if (err & ICRC_ERR) printk("%s", (err & ABRT_ERR) ? "BadCRC " : "BadSector "); - if (err & ECC_ERR) printk("UncorrectableError "); - if (err & ID_ERR) printk("SectorIdNotFound "); - if (err & TRK0_ERR) printk("TrackZeroNotFound "); - if (err & MARK_ERR) printk("AddrMarkNotFound "); - printk("}"); - if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || (err & (ECC_ERR|ID_ERR|MARK_ERR))) { - if ((drive->id->command_set_2 & 0x0400) && - (drive->id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - __u64 sectors = 0; - u32 low = 0, high = 0; - low = read_24(drive); - OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG); - high = read_24(drive); - - sectors = ((__u64)high << 24) | low; - printk(", LBAsect=%llu, high=%d, low=%d", - (unsigned long long) sectors, - high, low); - } else { - byte cur = IN_BYTE(IDE_SELECT_REG); - if (cur & 0x40) { /* using LBA? */ - printk(", LBAsect=%ld", (unsigned long) - ((cur&0xf)<<24) - |(IN_BYTE(IDE_HCYL_REG)<<16) - |(IN_BYTE(IDE_LCYL_REG)<<8) - | IN_BYTE(IDE_SECTOR_REG)); - } else { - printk(", CHS=%d/%d/%d", - (IN_BYTE(IDE_HCYL_REG)<<8) + - IN_BYTE(IDE_LCYL_REG), - cur & 0xf, - IN_BYTE(IDE_SECTOR_REG)); - } - } - if (HWGROUP(drive) && HWGROUP(drive)->rq) - printk(", sector=%ld", HWGROUP(drive)->rq->sector); - } - } -#endif /* FANCY_STATUS_DUMPS */ - printk("\n"); - } - __restore_flags (flags); /* local CPU only */ - return err; -} - -/* - * try_to_flush_leftover_data() is invoked in response to a drive - * unexpectedly having its DRQ_STAT bit set. As an alternative to - * resetting the drive, this routine tries to clear the condition - * by read a sector's worth of data from the drive. Of course, - * this may not help if the drive is *waiting* for data from *us*. - */ -static void try_to_flush_leftover_data (ide_drive_t *drive) -{ - int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS; - - if (drive->media != ide_disk) - return; - while (i > 0) { - u32 buffer[16]; - unsigned int wcount = (i > 16) ? 16 : i; - i -= wcount; - ide_input_data (drive, buffer, wcount); - } -} - -/* - * ide_error() takes action based on the error returned by the drive. - */ -ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat) -{ - struct request *rq; - byte err; - - err = ide_dump_status(drive, msg, stat); - if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) - return ide_stopped; - /* retry only "normal" I/O: */ - if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) { - rq->errors = 1; - ide_end_drive_cmd(drive, stat, err); - return ide_stopped; - } - if (rq->cmd == IDE_DRIVE_TASKFILE) { - rq->errors = 1; - ide_end_drive_cmd(drive, stat, err); -// ide_end_taskfile(drive, stat, err); - return ide_stopped; - } - - if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */ - rq->errors |= ERROR_RESET; - } else { - if (drive->media == ide_disk && (stat & ERR_STAT)) { - /* err has different meaning on cdrom and tape */ - if (err == ABRT_ERR) { - if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY) - return ide_stopped; /* some newer drives don't support WIN_SPECIFY */ - } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR)) { - drive->crc_count++; /* UDMA crc error -- just retry the operation */ - } else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */ - rq->errors = ERROR_MAX; - else if (err & TRK0_ERR) /* help it find track zero */ - rq->errors |= ERROR_RECAL; - } - if ((stat & DRQ_STAT) && rq->cmd != WRITE) - try_to_flush_leftover_data(drive); - } - if (GET_STAT() & (BUSY_STAT|DRQ_STAT)) - OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); /* force an abort */ - - if (rq->errors >= ERROR_MAX) { - if (drive->driver != NULL) - DRIVER(drive)->end_request(0, HWGROUP(drive)); - else - ide_end_request(0, HWGROUP(drive)); - } else { - if ((rq->errors & ERROR_RESET) == ERROR_RESET) { - ++rq->errors; - return ide_do_reset(drive); - } - if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) - drive->special.b.recalibrate = 1; - ++rq->errors; - } - return ide_stopped; -} - -/* - * Issue a simple drive command - * The drive must be selected beforehand. - */ -void ide_cmd (ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler) -{ - ide_set_handler (drive, handler, WAIT_CMD, NULL); - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(HWIF(drive),drive,0); - OUT_BYTE(nsect,IDE_NSECTOR_REG); - OUT_BYTE(cmd,IDE_COMMAND_REG); -} - -/* - * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD. - */ -static ide_startstop_t drive_cmd_intr (ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - byte *args = (byte *) rq->buffer; - byte stat = GET_STAT(); - int retries = 10; - - ide__sti(); /* local CPU only */ - if ((stat & DRQ_STAT) && args && args[3]) { - byte io_32bit = drive->io_32bit; - drive->io_32bit = 0; - ide_input_data(drive, &args[4], args[3] * SECTOR_WORDS); - drive->io_32bit = io_32bit; - while (((stat = GET_STAT()) & BUSY_STAT) && retries--) - udelay(100); - } - - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) - return ide_error(drive, "drive_cmd", stat); /* calls ide_end_drive_cmd */ - ide_end_drive_cmd (drive, stat, GET_ERR()); - return ide_stopped; -} - -/* - * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT - * commands to a drive. It used to do much more, but has been scaled back. - */ -static ide_startstop_t do_special (ide_drive_t *drive) -{ - special_t *s = &drive->special; - -#ifdef DEBUG - printk("%s: do_special: 0x%02x\n", drive->name, s->all); -#endif - if (s->b.set_tune) { - ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc; - s->b.set_tune = 0; - if (tuneproc != NULL) - tuneproc(drive, drive->tune_req); - } else if (drive->driver != NULL) { - return DRIVER(drive)->special(drive); - } else if (s->all) { - printk("%s: bad special flag: 0x%02x\n", drive->name, s->all); - s->all = 0; - } - return ide_stopped; -} - -/* - * This routine busy-waits for the drive status to be not "busy". - * It then checks the status for all of the "good" bits and none - * of the "bad" bits, and if all is okay it returns 0. All other - * cases return 1 after invoking ide_error() -- caller should just return. - * - * This routine should get fixed to not hog the cpu during extra long waits.. - * That could be done by busy-waiting for the first jiffy or two, and then - * setting a timer to wake up at half second intervals thereafter, - * until timeout is achieved, before timing out. - */ -int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout) { - byte stat; - int i; - unsigned long flags; - - /* bail early if we've exceeded max_failures */ - if (drive->max_failures && (drive->failures > drive->max_failures)) { - *startstop = ide_stopped; - return 1; - } - - udelay(1); /* spec allows drive 400ns to assert "BUSY" */ - if ((stat = GET_STAT()) & BUSY_STAT) { - __save_flags(flags); /* local CPU only */ - ide__sti(); /* local CPU only */ - timeout += jiffies; - while ((stat = GET_STAT()) & BUSY_STAT) { - if (0 < (signed long)(jiffies - timeout)) { - __restore_flags(flags); /* local CPU only */ - *startstop = ide_error(drive, "status timeout", stat); - return 1; - } - } - __restore_flags(flags); /* local CPU only */ - } - /* - * Allow status to settle, then read it again. - * A few rare drives vastly violate the 400ns spec here, - * so we'll wait up to 10usec for a "good" status - * rather than expensively fail things immediately. - * This fix courtesy of Matthew Faupel & Niccolo Rigacci. - */ - for (i = 0; i < 10; i++) { - udelay(1); - if (OK_STAT((stat = GET_STAT()), good, bad)) - return 0; - } - *startstop = ide_error(drive, "status error", stat); - return 1; -} - -/* - * execute_drive_cmd() issues a special drive command, - * usually initiated by ioctl() from the external hdparm program. - */ -static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq) -{ - switch(rq->cmd) { - case IDE_DRIVE_TASKFILE: - { - ide_task_t *args = rq->special; - - if (!(args)) break; - -#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG - { - printk(KERN_INFO "%s: ", drive->name); -// printk("TF.0=x%02x ", args->tfRegister[IDE_DATA_OFFSET]); - printk("TF.1=x%02x ", args->tfRegister[IDE_FEATURE_OFFSET]); - printk("TF.2=x%02x ", args->tfRegister[IDE_NSECTOR_OFFSET]); - printk("TF.3=x%02x ", args->tfRegister[IDE_SECTOR_OFFSET]); - printk("TF.4=x%02x ", args->tfRegister[IDE_LCYL_OFFSET]); - printk("TF.5=x%02x ", args->tfRegister[IDE_HCYL_OFFSET]); - printk("TF.6=x%02x ", args->tfRegister[IDE_SELECT_OFFSET]); - printk("TF.7=x%02x\n", args->tfRegister[IDE_COMMAND_OFFSET]); - printk(KERN_INFO "%s: ", drive->name); -// printk("HTF.0=x%02x ", args->hobRegister[IDE_DATA_OFFSET_HOB]); - printk("HTF.1=x%02x ", args->hobRegister[IDE_FEATURE_OFFSET_HOB]); - printk("HTF.2=x%02x ", args->hobRegister[IDE_NSECTOR_OFFSET_HOB]); - printk("HTF.3=x%02x ", args->hobRegister[IDE_SECTOR_OFFSET_HOB]); - printk("HTF.4=x%02x ", args->hobRegister[IDE_LCYL_OFFSET_HOB]); - printk("HTF.5=x%02x ", args->hobRegister[IDE_HCYL_OFFSET_HOB]); - printk("HTF.6=x%02x ", args->hobRegister[IDE_SELECT_OFFSET_HOB]); - printk("HTF.7=x%02x\n", args->hobRegister[IDE_CONTROL_OFFSET_HOB]); - } -#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ - -// if (args->tf_out_flags.all == 0) { - do_taskfile(drive, - (struct hd_drive_task_hdr *)&args->tfRegister, - (struct hd_drive_hob_hdr *)&args->hobRegister, - args->handler); -// } else { -// return flagged_taskfile(drive, args); -// } - - if (((args->command_type == IDE_DRIVE_TASK_RAW_WRITE) || - (args->command_type == IDE_DRIVE_TASK_OUT)) && - args->prehandler && args->handler) - return args->prehandler(drive, rq); - return ide_started; - } - case IDE_DRIVE_TASK: - { - byte *args = rq->buffer; - byte sel; - - if (!(args)) break; -#ifdef DEBUG - printk("%s: DRIVE_TASK_CMD ", drive->name); - printk("cmd=0x%02x ", args[0]); - printk("fr=0x%02x ", args[1]); - printk("ns=0x%02x ", args[2]); - printk("sc=0x%02x ", args[3]); - printk("lcyl=0x%02x ", args[4]); - printk("hcyl=0x%02x ", args[5]); - printk("sel=0x%02x\n", args[6]); -#endif - OUT_BYTE(args[1], IDE_FEATURE_REG); - OUT_BYTE(args[3], IDE_SECTOR_REG); - OUT_BYTE(args[4], IDE_LCYL_REG); - OUT_BYTE(args[5], IDE_HCYL_REG); - sel = (args[6] & ~0x10); - if (drive->select.b.unit) - sel |= 0x10; - OUT_BYTE(sel, IDE_SELECT_REG); - ide_cmd(drive, args[0], args[2], &drive_cmd_intr); - return ide_started; - } - case IDE_DRIVE_CMD: - { - byte *args = rq->buffer; - - if (!(args)) break; -#ifdef DEBUG - printk("%s: DRIVE_CMD ", drive->name); - printk("cmd=0x%02x ", args[0]); - printk("sc=0x%02x ", args[1]); - printk("fr=0x%02x ", args[2]); - printk("xx=0x%02x\n", args[3]); -#endif - if (args[0] == WIN_SMART) { - OUT_BYTE(0x4f, IDE_LCYL_REG); - OUT_BYTE(0xc2, IDE_HCYL_REG); - OUT_BYTE(args[2],IDE_FEATURE_REG); - OUT_BYTE(args[1],IDE_SECTOR_REG); - ide_cmd(drive, args[0], args[3], &drive_cmd_intr); - return ide_started; - } - OUT_BYTE(args[2],IDE_FEATURE_REG); - ide_cmd(drive, args[0], args[1], &drive_cmd_intr); - return ide_started; - } - default: - break; - } - /* - * NULL is actually a valid way of waiting for - * all current requests to be flushed from the queue. - */ -#ifdef DEBUG - printk("%s: DRIVE_CMD (null)\n", drive->name); -#endif - ide_end_drive_cmd(drive, GET_STAT(), GET_ERR()); - return ide_stopped; -} - -/* - * start_request() initiates handling of a new I/O request - * needed to reverse the perverted changes anonymously made back - * 2.3.99-pre6 - */ -static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) -{ - ide_startstop_t startstop; - unsigned long block, blockend; - unsigned int minor = MINOR(rq->rq_dev), unit = minor >> PARTN_BITS; - ide_hwif_t *hwif = HWIF(drive); - -#ifdef DEBUG - printk("%s: start_request: current=0x%08lx\n", hwif->name, (unsigned long) rq); -#endif - /* bail early if we've exceeded max_failures */ - if (drive->max_failures && (drive->failures > drive->max_failures)) { - goto kill_rq; - } - - if (unit >= MAX_DRIVES) { - printk("%s: bad device number: %s\n", hwif->name, kdevname(rq->rq_dev)); - goto kill_rq; - } -#ifdef DEBUG - if (rq->bh && !buffer_locked(rq->bh)) { - printk("%s: block not locked\n", drive->name); - goto kill_rq; - } -#endif - block = rq->sector; - blockend = block + rq->nr_sectors; - - -#ifdef NEVER - if ((rq->cmd == READ || rq->cmd == WRITE) && - (drive->media == ide_disk || drive->media == ide_floppy)) { - if ((blockend < block) || (blockend > drive->part[minor&PARTN_MASK].nr_sects)) { - printk("%s%c: bad access: block=%ld, count=%ld\n", drive->name, - (minor&PARTN_MASK)?'0'+(minor&PARTN_MASK):' ', block, rq->nr_sectors); - goto kill_rq; - } - block += drive->part[minor&PARTN_MASK].start_sect + drive->sect0; - } - /* Yecch - this will shift the entire interval, - possibly killing some innocent following sector */ - if (block == 0 && drive->remap_0_to_1 == 1) - block = 1; /* redirect MBR access to EZ-Drive partn table */ -#endif - -#ifdef NEVER_DEBUG - { - printk(" ide::start_request %lx %lx %lx %lx %lx\n", - rq->sector, rq->nr_sectors, block, - drive->part[minor&PARTN_MASK].start_sect, drive->sect0); - } -#endif - -#if (DISK_RECOVERY_TIME > 0) - while ((read_timer() - hwif->last_time) < DISK_RECOVERY_TIME); -#endif - - SELECT_DRIVE(hwif, drive); - if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) { - printk("%s: drive not ready for command\n", drive->name); - return startstop; - } - drive->special.all = 0; - if (!drive->special.all) { - switch(rq->cmd) { - case IDE_DRIVE_CMD: - case IDE_DRIVE_TASK: - case IDE_DRIVE_TASKFILE: - return execute_drive_cmd(drive, rq); - default: - break; - } - if (drive->driver != NULL) { - return (DRIVER(drive)->do_request(drive, rq, block)); - } - printk("%s: media type %d not supported\n", drive->name, drive->media); - goto kill_rq; - } - return do_special(drive); -kill_rq: - if (drive->driver != NULL) - DRIVER(drive)->end_request(0, HWGROUP(drive)); - else - ide_end_request(0, HWGROUP(drive)); - return ide_stopped; -} - -ide_startstop_t restart_request (ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - unsigned long flags; - struct request *rq; - - spin_lock_irqsave(&io_request_lock, flags); - hwgroup->handler = NULL; - del_timer(&hwgroup->timer); - rq = hwgroup->rq; - spin_unlock_irqrestore(&io_request_lock, flags); - - return start_request(drive, rq); -} - -/* - * ide_stall_queue() can be used by a drive to give excess bandwidth back - * to the hwgroup by sleeping for timeout jiffies. - */ -void ide_stall_queue (ide_drive_t *drive, unsigned long timeout) -{ - if (timeout > WAIT_WORSTCASE) - timeout = WAIT_WORSTCASE; - drive->sleep = timeout + jiffies; -} - -#define WAKEUP(drive) ((drive)->service_start + 2 * (drive)->service_time) - -/* - * choose_drive() selects the next drive which will be serviced. - */ -static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup) -{ - ide_drive_t *drive, *best; - -repeat: - best = NULL; - drive = hwgroup->drive; - do { - if (!list_empty(&drive->queue.queue_head) && (!drive->sleep || 0 <= (signed long)(jiffies - drive->sleep))) { - if (!best - || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep))) - || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive)))) - { - if( !drive->queue.plugged ) - best = drive; - } - } - } while ((drive = drive->next) != hwgroup->drive); - if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) { - long t = (signed long)(WAKEUP(best) - jiffies); - if (t >= WAIT_MIN_SLEEP) { - /* - * We *may* have some time to spare, but first let's see if - * someone can potentially benefit from our nice mood today.. - */ - drive = best->next; - do { - if (!drive->sleep - && 0 < (signed long)(WAKEUP(drive) - (jiffies - best->service_time)) - && 0 < (signed long)((jiffies + t) - WAKEUP(drive))) - { - ide_stall_queue(best, IDE_MIN(t, 10 * WAIT_MIN_SLEEP)); - goto repeat; - } - } while ((drive = drive->next) != best); - } - } - return best; -} - -/* - * Issue a new request to a drive from hwgroup - * Caller must have already done spin_lock_irqsave(&io_request_lock, ..); - * - * A hwgroup is a serialized group of IDE interfaces. Usually there is - * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640) - * may have both interfaces in a single hwgroup to "serialize" access. - * Or possibly multiple ISA interfaces can share a common IRQ by being grouped - * together into one hwgroup for serialized access. - * - * Note also that several hwgroups can end up sharing a single IRQ, - * possibly along with many other devices. This is especially common in - * PCI-based systems with off-board IDE controller cards. - * - * The IDE driver uses the single global io_request_lock spinlock to protect - * access to the request queues, and to protect the hwgroup->busy flag. - * - * The first thread into the driver for a particular hwgroup sets the - * hwgroup->busy flag to indicate that this hwgroup is now active, - * and then initiates processing of the top request from the request queue. - * - * Other threads attempting entry notice the busy setting, and will simply - * queue their new requests and exit immediately. Note that hwgroup->busy - * remains set even when the driver is merely awaiting the next interrupt. - * Thus, the meaning is "this hwgroup is busy processing a request". - * - * When processing of a request completes, the completing thread or IRQ-handler - * will start the next request from the queue. If no more work remains, - * the driver will clear the hwgroup->busy flag and exit. - * - * The io_request_lock (spinlock) is used to protect all access to the - * hwgroup->busy flag, but is otherwise not needed for most processing in - * the driver. This makes the driver much more friendlier to shared IRQs - * than previous designs, while remaining 100% (?) SMP safe and capable. - */ -/* --BenH: made non-static as ide-pmac.c uses it to kick the hwgroup back - * into life on wakeup from machine sleep. - */ -void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) -{ - ide_drive_t *drive; - ide_hwif_t *hwif; - struct request *rq; - ide_startstop_t startstop; - - ide_get_lock(&ide_lock, ide_intr, hwgroup); /* for atari only: POSSIBLY BROKEN HERE(?) */ - - __cli(); /* necessary paranoia: ensure IRQs are masked on local CPU */ - - while (!hwgroup->busy) { - hwgroup->busy = 1; - drive = choose_drive(hwgroup); - if (drive == NULL) { - unsigned long sleep = 0; - hwgroup->rq = NULL; - drive = hwgroup->drive; - do { - if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep))) - sleep = drive->sleep; - } while ((drive = drive->next) != hwgroup->drive); - if (sleep) { - /* - * Take a short snooze, and then wake up this hwgroup again. - * This gives other hwgroups on the same a chance to - * play fairly with us, just in case there are big differences - * in relative throughputs.. don't want to hog the cpu too much. - */ - if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep)) - sleep = jiffies + WAIT_MIN_SLEEP; -#if 1 - if (timer_pending(&hwgroup->timer)) - printk("ide_set_handler: timer already active\n"); -#endif - hwgroup->sleeping = 1; /* so that ide_timer_expiry knows what to do */ - mod_timer(&hwgroup->timer, sleep); - /* we purposely leave hwgroup->busy==1 while sleeping */ - } else { - /* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_disk? */ - ide_release_lock(&ide_lock); /* for atari only */ - hwgroup->busy = 0; - } - return; /* no more work for this hwgroup (for now) */ - } - hwif = HWIF(drive); - if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif && hwif->io_ports[IDE_CONTROL_OFFSET]) { - /* set nIEN for previous hwif */ - SELECT_INTERRUPT(hwif, drive); - } - hwgroup->hwif = hwif; - hwgroup->drive = drive; - drive->sleep = 0; - drive->service_start = jiffies; - - if ( drive->queue.plugged ) /* paranoia */ - printk("%s: Huh? nuking plugged queue\n", drive->name); - - rq = hwgroup->rq = blkdev_entry_next_request(&drive->queue.queue_head); - /* - * Some systems have trouble with IDE IRQs arriving while - * the driver is still setting things up. So, here we disable - * the IRQ used by this interface while the request is being started. - * This may look bad at first, but pretty much the same thing - * happens anyway when any interrupt comes in, IDE or otherwise - * -- the kernel masks the IRQ while it is being handled. - */ - if (masked_irq && hwif->irq != masked_irq) - disable_irq_nosync(hwif->irq); - spin_unlock(&io_request_lock); - ide__sti(); /* allow other IRQs while we start this request */ - startstop = start_request(drive, rq); - spin_lock_irq(&io_request_lock); - if (masked_irq && hwif->irq != masked_irq) - enable_irq(hwif->irq); - if (startstop == ide_stopped) - hwgroup->busy = 0; - } -} - -/* - * ide_get_queue() returns the queue which corresponds to a given device. - */ -request_queue_t *ide_get_queue (kdev_t dev) -{ - ide_hwif_t *hwif = (ide_hwif_t *)blk_dev[MAJOR(dev)].data; - - return &hwif->drives[DEVICE_NR(dev) & 1].queue; -} - -/* - * Passes the stuff to ide_do_request - */ -void do_ide_request(request_queue_t *q) -{ - ide_do_request(q->queuedata, 0); -} - -/* - * un-busy the hwgroup etc, and clear any pending DMA status. we want to - * retry the current request in pio mode instead of risking tossing it - * all away - */ -void ide_dma_timeout_retry(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct request *rq; - - /* - * end current dma transaction - */ - (void) hwif->dmaproc(ide_dma_end, drive); - - /* - * complain a little, later we might remove some of this verbosity - */ - printk("%s: timeout waiting for DMA\n", drive->name); - (void) hwif->dmaproc(ide_dma_timeout, drive); - - /* - * disable dma for now, but remember that we did so because of - * a timeout -- we'll reenable after we finish this next request - * (or rather the first chunk of it) in pio. - */ - drive->retry_pio++; - drive->state = DMA_PIO_RETRY; - (void) hwif->dmaproc(ide_dma_off_quietly, drive); - - /* - * un-busy drive etc (hwgroup->busy is cleared on return) and - * make sure request is sane - */ - rq = HWGROUP(drive)->rq; - HWGROUP(drive)->rq = NULL; - - rq->errors = 0; - rq->sector = rq->bh->b_rsector; - rq->current_nr_sectors = rq->bh->b_size >> 9; - rq->buffer = rq->bh->b_data; -} - -/* - * ide_timer_expiry() is our timeout function for all drive operations. - * But note that it can also be invoked as a result of a "sleep" operation - * triggered by the mod_timer() call in ide_do_request. - */ -void ide_timer_expiry (unsigned long data) -{ - ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data; - ide_handler_t *handler; - ide_expiry_t *expiry; - unsigned long flags; - unsigned long wait; - - spin_lock_irqsave(&io_request_lock, flags); - del_timer(&hwgroup->timer); - - if ((handler = hwgroup->handler) == NULL) { - /* - * Either a marginal timeout occurred - * (got the interrupt just as timer expired), - * or we were "sleeping" to give other devices a chance. - * Either way, we don't really want to complain about anything. - */ - if (hwgroup->sleeping) { - hwgroup->sleeping = 0; - hwgroup->busy = 0; - } - } else { - ide_drive_t *drive = hwgroup->drive; - if (!drive) { - printk("ide_timer_expiry: hwgroup->drive was NULL\n"); - hwgroup->handler = NULL; - } else { - ide_hwif_t *hwif; - ide_startstop_t startstop; - if (!hwgroup->busy) { - hwgroup->busy = 1; /* paranoia */ - printk("%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name); - } - if ((expiry = hwgroup->expiry) != NULL) { - /* continue */ - if ((wait = expiry(drive)) != 0) { - /* reset timer */ - hwgroup->timer.expires = jiffies + wait; - add_timer(&hwgroup->timer); - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - } - hwgroup->handler = NULL; - /* - * We need to simulate a real interrupt when invoking - * the handler() function, which means we need to globally - * mask the specific IRQ: - */ - spin_unlock(&io_request_lock); - hwif = HWIF(drive); -#if DISABLE_IRQ_NOSYNC - disable_irq_nosync(hwif->irq); -#else - disable_irq(hwif->irq); /* disable_irq_nosync ?? */ -#endif /* DISABLE_IRQ_NOSYNC */ - __cli(); /* local CPU only, as if we were handling an interrupt */ - if (hwgroup->poll_timeout != 0) { - startstop = handler(drive); - } else if (drive_is_ready(drive)) { - if (drive->waiting_for_dma) - (void) hwgroup->hwif->dmaproc(ide_dma_lostirq, drive); - (void)ide_ack_intr(hwif); - printk("%s: lost interrupt\n", drive->name); - startstop = handler(drive); - } else { - if (drive->waiting_for_dma) { - startstop = ide_stopped; - ide_dma_timeout_retry(drive); - } else - startstop = ide_error(drive, "irq timeout", GET_STAT()); - } - set_recovery_timer(hwif); - drive->service_time = jiffies - drive->service_start; - enable_irq(hwif->irq); - spin_lock_irq(&io_request_lock); - if (startstop == ide_stopped) - hwgroup->busy = 0; - } - } - ide_do_request(hwgroup, 0); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * There's nothing really useful we can do with an unexpected interrupt, - * other than reading the status register (to clear it), and logging it. - * There should be no way that an irq can happen before we're ready for it, - * so we needn't worry much about losing an "important" interrupt here. - * - * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the - * drive enters "idle", "standby", or "sleep" mode, so if the status looks - * "good", we just ignore the interrupt completely. - * - * This routine assumes __cli() is in effect when called. - * - * If an unexpected interrupt happens on irq15 while we are handling irq14 - * and if the two interfaces are "serialized" (CMD640), then it looks like - * we could screw up by interfering with a new request being set up for irq15. - * - * In reality, this is a non-issue. The new command is not sent unless the - * drive is ready to accept one, in which case we know the drive is not - * trying to interrupt us. And ide_set_handler() is always invoked before - * completing the issuance of any new drive command, so we will not be - * accidentally invoked as a result of any valid command completion interrupt. - * - */ -static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup) -{ - byte stat; - ide_hwif_t *hwif = hwgroup->hwif; - - /* - * handle the unexpected interrupt - */ - do { - if (hwif->irq == irq) { - stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { - /* Try to not flood the console with msgs */ - static unsigned long last_msgtime, count; - ++count; - if (0 < (signed long)(jiffies - (last_msgtime + HZ))) { - last_msgtime = jiffies; - printk("%s%s: unexpected interrupt, status=0x%02x, count=%ld\n", - hwif->name, (hwif->next == hwgroup->hwif) ? "" : "(?)", stat, count); - } - } - } - } while ((hwif = hwif->next) != hwgroup->hwif); -} - -/* - * entry point for all interrupts, caller does __cli() for us - */ -void ide_intr (int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; - ide_hwif_t *hwif; - ide_drive_t *drive; - ide_handler_t *handler; - ide_startstop_t startstop; - - spin_lock_irqsave(&io_request_lock, flags); - hwif = hwgroup->hwif; - - if (!ide_ack_intr(hwif)) { - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - - if ((handler = hwgroup->handler) == NULL || hwgroup->poll_timeout != 0) { - /* - * Not expecting an interrupt from this drive. - * That means this could be: - * (1) an interrupt from another PCI device - * sharing the same PCI INT# as us. - * or (2) a drive just entered sleep or standby mode, - * and is interrupting to let us know. - * or (3) a spurious interrupt of unknown origin. - * - * For PCI, we cannot tell the difference, - * so in that case we just ignore it and hope it goes away. - */ -#ifdef CONFIG_BLK_DEV_IDEPCI - if (IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL)) -#endif /* CONFIG_BLK_DEV_IDEPCI */ - { - /* - * Probably not a shared PCI interrupt, - * so we can safely try to do something about it: - */ - unexpected_intr(irq, hwgroup); -#ifdef CONFIG_BLK_DEV_IDEPCI - } else { - /* - * Whack the status register, just in case we have a leftover pending IRQ. - */ - (void) IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); -#endif /* CONFIG_BLK_DEV_IDEPCI */ - } - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - drive = hwgroup->drive; - if (!drive) { - /* - * This should NEVER happen, and there isn't much we could do about it here. - */ - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - if (!drive_is_ready(drive)) { - /* - * This happens regularly when we share a PCI IRQ with another device. - * Unfortunately, it can also happen with some buggy drives that trigger - * the IRQ before their status register is up to date. Hopefully we have - * enough advance overhead that the latter isn't a problem. - */ - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - if (!hwgroup->busy) { - hwgroup->busy = 1; /* paranoia */ - printk("%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name); - } - hwgroup->handler = NULL; - del_timer(&hwgroup->timer); - spin_unlock(&io_request_lock); - - if (drive->unmask) - ide__sti(); /* local CPU only */ - startstop = handler(drive); /* service this interrupt, may set handler for next interrupt */ - spin_lock_irq(&io_request_lock); - - /* - * Note that handler() may have set things up for another - * interrupt to occur soon, but it cannot happen until - * we exit from this routine, because it will be the - * same irq as is currently being serviced here, and Linux - * won't allow another of the same (on any CPU) until we return. - */ - set_recovery_timer(HWIF(drive)); - drive->service_time = jiffies - drive->service_start; - if (startstop == ide_stopped) { - if (hwgroup->handler == NULL) { /* paranoia */ - hwgroup->busy = 0; - ide_do_request(hwgroup, hwif->irq); - } else { - printk("%s: ide_intr: huh? expected NULL handler on exit\n", drive->name); - } - } - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * get_info_ptr() returns the (ide_drive_t *) for a given device number. - * It returns NULL if the given device number does not match any present drives. - */ -ide_drive_t *get_info_ptr (kdev_t i_rdev) -{ - int major = MAJOR(i_rdev); -#if 0 - int minor = MINOR(i_rdev) & PARTN_MASK; -#endif - unsigned int h; - - for (h = 0; h < MAX_HWIFS; ++h) { - ide_hwif_t *hwif = &ide_hwifs[h]; - if (hwif->present && major == hwif->major) { - unsigned unit = DEVICE_NR(i_rdev); - if (unit < MAX_DRIVES) { - ide_drive_t *drive = &hwif->drives[unit]; -#if 0 - if ((drive->present) && (drive->part[minor].nr_sects)) -#else - if (drive->present) -#endif - return drive; - } - break; - } - } - return NULL; -} - -/* - * This function is intended to be used prior to invoking ide_do_drive_cmd(). - */ -void ide_init_drive_cmd (struct request *rq) -{ - memset(rq, 0, sizeof(*rq)); - rq->cmd = IDE_DRIVE_CMD; -} - -/* - * This function issues a special IDE device request - * onto the request queue. - * - * If action is ide_wait, then the rq is queued at the end of the - * request queue, and the function sleeps until it has been processed. - * This is for use when invoked from an ioctl handler. - * - * If action is ide_preempt, then the rq is queued at the head of - * the request queue, displacing the currently-being-processed - * request and this function returns immediately without waiting - * for the new rq to be completed. This is VERY DANGEROUS, and is - * intended for careful use by the ATAPI tape/cdrom driver code. - * - * If action is ide_next, then the rq is queued immediately after - * the currently-being-processed-request (if any), and the function - * returns without waiting for the new rq to be completed. As above, - * This is VERY DANGEROUS, and is intended for careful use by the - * ATAPI tape/cdrom driver code. - * - * If action is ide_end, then the rq is queued at the end of the - * request queue, and the function returns immediately without waiting - * for the new rq to be completed. This is again intended for careful - * use by the ATAPI tape/cdrom driver code. - */ -int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action) -{ - unsigned long flags; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - unsigned int major = HWIF(drive)->major; - struct list_head *queue_head = &drive->queue.queue_head; -#if 0 - DECLARE_COMPLETION(wait); -#else - int wait = 1; - int usecs = 0; -#endif - - -#ifdef CONFIG_BLK_DEV_PDC4030 - if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL) - return -ENOSYS; /* special drive cmds not supported */ -#endif - rq->errors = 0; - rq->rq_status = RQ_ACTIVE; - rq->rq_dev = MKDEV(major,(drive->select.b.unit)< we'll spin instead */ - rq->waiting = (void *)&wait; - } - - spin_lock_irqsave(&io_request_lock, flags); - if (list_empty(queue_head) || action == ide_preempt) { - if (action == ide_preempt) - hwgroup->rq = NULL; - } else { - if (action == ide_wait || action == ide_end) { - queue_head = queue_head->prev; - } else - queue_head = queue_head->next; - } - list_add(&rq->queue, queue_head); - ide_do_request(hwgroup, 0); - spin_unlock_irqrestore(&io_request_lock, flags); - - /* XXX SMH: spin waiting for response */ - if (action == ide_wait) { - - while(wait) { - udelay(500); - usecs += 500; - if(usecs > 1000000) { - printk("ide_do_drive_cmd [ide_wait]: still waiting\n"); - usecs = 0; - } - } - } - - return 0; - -} - -/* - * This routine is called to flush all partitions and partition tables - * for a changed disk, and then re-read the new partition table. - * If we are revalidating a disk because of a media change, then we - * enter with usage == 0. If we are using an ioctl, we automatically have - * usage == 1 (we need an open channel to use an ioctl :-), so this - * is our limit. - */ -int ide_revalidate_disk (kdev_t i_rdev) -{ - ide_drive_t *drive; - ide_hwgroup_t *hwgroup; - unsigned int p, major, minor; - unsigned long flags; - - if ((drive = get_info_ptr(i_rdev)) == NULL) - return -ENODEV; - major = MAJOR(i_rdev); - minor = drive->select.b.unit << PARTN_BITS; - hwgroup = HWGROUP(drive); - spin_lock_irqsave(&io_request_lock, flags); - if (drive->busy || (drive->usage > 1)) { - spin_unlock_irqrestore(&io_request_lock, flags); - return -EBUSY; - }; - drive->busy = 1; - MOD_INC_USE_COUNT; - spin_unlock_irqrestore(&io_request_lock, flags); - - for (p = 0; p < (1<part[p].nr_sects > 0) { - kdev_t devp = MKDEV(major, minor+p); - invalidate_device(devp, 1); - } - drive->part[p].start_sect = 0; - drive->part[p].nr_sects = 0; - }; - - if (DRIVER(drive)->revalidate) - DRIVER(drive)->revalidate(drive); - - drive->busy = 0; - /*wake_up(&drive->wqueue);*/ - MOD_DEC_USE_COUNT; - return 0; -} - -static void revalidate_drives (void) -{ - ide_hwif_t *hwif; - ide_drive_t *drive; - int index, unit; - - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = &ide_hwifs[index]; - for (unit = 0; unit < MAX_DRIVES; ++unit) { - drive = &ide_hwifs[index].drives[unit]; - if (drive->revalidate) { - drive->revalidate = 0; - if (!initializing) - (void) ide_revalidate_disk(MKDEV(hwif->major, unit<init(); - } - revalidate_drives(); -} - -static void ide_driver_module (void) -{ - int index; - ide_module_t *module = ide_modules; - - for (index = 0; index < MAX_HWIFS; ++index) - if (ide_hwifs[index].present) - goto search; - ide_probe_module(); -search: - while (module) { - (void) module->init(); - module = module->next; - } - revalidate_drives(); -} - -static int ide_open (struct inode * inode, struct file * filp) -{ - ide_drive_t *drive; - - if ((drive = get_info_ptr(inode->i_rdev)) == NULL) - return -ENXIO; - if (drive->driver == NULL) - ide_driver_module(); -#ifdef CONFIG_KMOD - if (drive->driver == NULL) { - if (drive->media == ide_disk) - (void) request_module("ide-disk"); - if (drive->media == ide_cdrom) - (void) request_module("ide-cd"); - if (drive->media == ide_tape) - (void) request_module("ide-tape"); - if (drive->media == ide_floppy) - (void) request_module("ide-floppy"); -#if defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) - if (drive->media == ide_scsi) - (void) request_module("ide-scsi"); -#endif /* defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) */ - } -#endif /* CONFIG_KMOD */ -#if 0 - while (drive->busy) - sleep_on(&drive->wqueue); -#endif - drive->usage++; - if (drive->driver != NULL) - return DRIVER(drive)->open(inode, filp, drive); - printk ("%s: driver not present\n", drive->name); - drive->usage--; - return -ENXIO; -} - -/* - * Releasing a block device means we sync() it, so that it can safely - * be forgotten about... - */ -static int ide_release (struct inode * inode, struct file * file) -{ - ide_drive_t *drive; - - if ((drive = get_info_ptr(inode->i_rdev)) != NULL) { - drive->usage--; - if (drive->driver != NULL) - DRIVER(drive)->release(inode, file, drive); - } - return 0; -} - -int ide_replace_subdriver (ide_drive_t *drive, const char *driver) -{ - if (!drive->present || drive->busy || drive->usage) - goto abort; - if (drive->driver != NULL && DRIVER(drive)->cleanup(drive)) - goto abort; - strncpy(drive->driver_req, driver, 9); - ide_driver_module(); - drive->driver_req[0] = 0; - ide_driver_module(); - if (DRIVER(drive) && !strcmp(DRIVER(drive)->name, driver)) - return 0; -abort: - return 1; -} - -#ifdef CONFIG_PROC_FS -ide_proc_entry_t generic_subdriver_entries[] = { - { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, - { NULL, 0, NULL, NULL } -}; -#endif - -/* - * Note that we only release the standard ports, - * and do not even try to handle any extra ports - * allocated for weird IDE interface chipsets. - */ -void hwif_unregister (ide_hwif_t *hwif) -{ - if (hwif->straight8) { - ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 8); - goto jump_eight; - } - if (hwif->io_ports[IDE_DATA_OFFSET]) - ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 1); - if (hwif->io_ports[IDE_ERROR_OFFSET]) - ide_release_region(hwif->io_ports[IDE_ERROR_OFFSET], 1); - if (hwif->io_ports[IDE_NSECTOR_OFFSET]) - ide_release_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1); - if (hwif->io_ports[IDE_SECTOR_OFFSET]) - ide_release_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1); - if (hwif->io_ports[IDE_LCYL_OFFSET]) - ide_release_region(hwif->io_ports[IDE_LCYL_OFFSET], 1); - if (hwif->io_ports[IDE_HCYL_OFFSET]) - ide_release_region(hwif->io_ports[IDE_HCYL_OFFSET], 1); - if (hwif->io_ports[IDE_SELECT_OFFSET]) - ide_release_region(hwif->io_ports[IDE_SELECT_OFFSET], 1); - if (hwif->io_ports[IDE_STATUS_OFFSET]) - ide_release_region(hwif->io_ports[IDE_STATUS_OFFSET], 1); -jump_eight: - if (hwif->io_ports[IDE_CONTROL_OFFSET]) - ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1); -#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) - if (hwif->io_ports[IDE_IRQ_OFFSET]) - ide_release_region(hwif->io_ports[IDE_IRQ_OFFSET], 1); -#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ -} - -void ide_unregister (unsigned int index) -{ - struct gendisk *gd; - ide_drive_t *drive, *d; - ide_hwif_t *hwif, *g; - ide_hwgroup_t *hwgroup; - int irq_count = 0, unit, i; - unsigned long flags; - unsigned int p, minor; - ide_hwif_t old_hwif; - - if (index >= MAX_HWIFS) - return; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - hwif = &ide_hwifs[index]; - if (!hwif->present) - goto abort; - for (unit = 0; unit < MAX_DRIVES; ++unit) { - drive = &hwif->drives[unit]; - if (!drive->present) - continue; - if (drive->busy || drive->usage) - goto abort; - if (drive->driver != NULL && DRIVER(drive)->cleanup(drive)) - goto abort; - } - hwif->present = 0; - - /* - * All clear? Then blow away the buffer cache - */ - sti(); - for (unit = 0; unit < MAX_DRIVES; ++unit) { - drive = &hwif->drives[unit]; - if (!drive->present) - continue; - minor = drive->select.b.unit << PARTN_BITS; - for (p = 0; p < (1<part[p].nr_sects > 0) { - kdev_t devp = MKDEV(hwif->major, minor+p); - invalidate_device(devp, 0); - } - } -#ifdef CONFIG_PROC_FS - destroy_proc_ide_drives(hwif); -#endif - } - cli(); - hwgroup = hwif->hwgroup; - - /* - * free the irq if we were the only hwif using it - */ - g = hwgroup->hwif; - do { - if (g->irq == hwif->irq) - ++irq_count; - g = g->next; - } while (g != hwgroup->hwif); - if (irq_count == 1) - free_irq(hwif->irq, hwgroup); - - /* - * Note that we only release the standard ports, - * and do not even try to handle any extra ports - * allocated for weird IDE interface chipsets. - */ - hwif_unregister(hwif); - - /* - * Remove us from the hwgroup, and free - * the hwgroup if we were the only member - */ - d = hwgroup->drive; - for (i = 0; i < MAX_DRIVES; ++i) { - drive = &hwif->drives[i]; -#ifdef DEVFS_MUST_DIE - if (drive->de) { - devfs_unregister (drive->de); - drive->de = NULL; - } -#endif - if (!drive->present) - continue; - while (hwgroup->drive->next != drive) - hwgroup->drive = hwgroup->drive->next; - hwgroup->drive->next = drive->next; - if (hwgroup->drive == drive) - hwgroup->drive = NULL; - if (drive->id != NULL) { - kfree(drive->id); - drive->id = NULL; - } - drive->present = 0; - blk_cleanup_queue(&drive->queue); - } - if (d->present) - hwgroup->drive = d; - while (hwgroup->hwif->next != hwif) - hwgroup->hwif = hwgroup->hwif->next; - hwgroup->hwif->next = hwif->next; - if (hwgroup->hwif == hwif) - kfree(hwgroup); - else - hwgroup->hwif = HWIF(hwgroup->drive); - -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) - if (hwif->dma_base) { - (void) ide_release_dma(hwif); - hwif->dma_base = 0; - } -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ - - /* - * Remove us from the kernel's knowledge - */ - unregister_blkdev(hwif->major, hwif->name); - kfree(blksize_size[hwif->major]); - kfree(max_sectors[hwif->major]); - /*kfree(max_readahead[hwif->major]);*/ - blk_dev[hwif->major].data = NULL; - blk_dev[hwif->major].queue = NULL; - blksize_size[hwif->major] = NULL; - gd = hwif->gd; - if (gd) { - del_gendisk(gd); - kfree(gd->sizes); - kfree(gd->part); -#ifdef DEVFS_MUST_DIE - if (gd->de_arr) - kfree (gd->de_arr); -#endif - if (gd->flags) - kfree (gd->flags); - kfree(gd); - hwif->gd = NULL; - } - old_hwif = *hwif; - init_hwif_data (index); /* restore hwif data to pristine status */ - hwif->hwgroup = old_hwif.hwgroup; - hwif->tuneproc = old_hwif.tuneproc; - hwif->speedproc = old_hwif.speedproc; - hwif->selectproc = old_hwif.selectproc; - hwif->resetproc = old_hwif.resetproc; - hwif->intrproc = old_hwif.intrproc; - hwif->maskproc = old_hwif.maskproc; - hwif->quirkproc = old_hwif.quirkproc; - hwif->rwproc = old_hwif.rwproc; - hwif->ideproc = old_hwif.ideproc; - hwif->dmaproc = old_hwif.dmaproc; - hwif->busproc = old_hwif.busproc; - hwif->bus_state = old_hwif.bus_state; - hwif->dma_base = old_hwif.dma_base; - hwif->dma_extra = old_hwif.dma_extra; - hwif->config_data = old_hwif.config_data; - hwif->select_data = old_hwif.select_data; - hwif->proc = old_hwif.proc; -#ifndef CONFIG_BLK_DEV_IDECS - hwif->irq = old_hwif.irq; -#endif /* CONFIG_BLK_DEV_IDECS */ - hwif->major = old_hwif.major; - hwif->chipset = old_hwif.chipset; - hwif->autodma = old_hwif.autodma; - hwif->udma_four = old_hwif.udma_four; -#ifdef CONFIG_BLK_DEV_IDEPCI - hwif->pci_dev = old_hwif.pci_dev; - hwif->pci_devid = old_hwif.pci_devid; -#endif /* CONFIG_BLK_DEV_IDEPCI */ - hwif->straight8 = old_hwif.straight8; - hwif->hwif_data = old_hwif.hwif_data; -abort: - restore_flags(flags); /* all CPUs */ -} - -/* - * Setup hw_regs_t structure described by parameters. You - * may set up the hw structure yourself OR use this routine to - * do it for you. - */ -void ide_setup_ports ( hw_regs_t *hw, - ide_ioreg_t base, int *offsets, - ide_ioreg_t ctrl, ide_ioreg_t intr, - ide_ack_intr_t *ack_intr, int irq) -{ - int i; - - for (i = 0; i < IDE_NR_PORTS; i++) { - if (offsets[i] == -1) { - switch(i) { - case IDE_CONTROL_OFFSET: - hw->io_ports[i] = ctrl; - break; -#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) - case IDE_IRQ_OFFSET: - hw->io_ports[i] = intr; - break; -#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ - default: - hw->io_ports[i] = 0; - break; - } - } else { - hw->io_ports[i] = base + offsets[i]; - } - } - hw->irq = irq; - hw->dma = NO_DMA; - hw->ack_intr = ack_intr; -} - -/* - * Register an IDE interface, specifing exactly the registers etc - * Set init=1 iff calling before probes have taken place. - */ -int ide_register_hw (hw_regs_t *hw, ide_hwif_t **hwifp) -{ - int index, retry = 1; - ide_hwif_t *hwif; - - do { - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = &ide_hwifs[index]; - if (hwif->hw.io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET]) - goto found; - } - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = &ide_hwifs[index]; - if ((!hwif->present && !hwif->mate && !initializing) || - (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing)) - goto found; - } - for (index = 0; index < MAX_HWIFS; index++) - ide_unregister(index); - } while (retry--); - return -1; -found: - if (hwif->present) - ide_unregister(index); - if (hwif->present) - return -1; - memcpy(&hwif->hw, hw, sizeof(*hw)); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports)); - hwif->irq = hw->irq; - hwif->noprobe = 0; - hwif->chipset = hw->chipset; - - if (!initializing) { - ide_probe_module(); -#ifdef CONFIG_PROC_FS - create_proc_ide_interfaces(); -#endif - ide_driver_module(); - } - - if (hwifp) - *hwifp = hwif; - - return (initializing || hwif->present) ? index : -1; -} - -/* - * Compatability function with existing drivers. If you want - * something different, use the function above. - */ -int ide_register (int arg1, int arg2, int irq) -{ - hw_regs_t hw; - ide_init_hwif_ports(&hw, (ide_ioreg_t) arg1, (ide_ioreg_t) arg2, NULL); - hw.irq = irq; - return ide_register_hw(&hw, NULL); -} - -void ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) -{ - ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; - - while ((*p) && strcmp((*p)->name, name) < 0) - p = &((*p)->next); - if ((setting = kmalloc(sizeof(*setting), GFP_KERNEL)) == NULL) - goto abort; - memset(setting, 0, sizeof(*setting)); - if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL) - goto abort; - strcpy(setting->name, name); setting->rw = rw; - setting->read_ioctl = read_ioctl; setting->write_ioctl = write_ioctl; - setting->data_type = data_type; setting->min = min; - setting->max = max; setting->mul_factor = mul_factor; - setting->div_factor = div_factor; setting->data = data; - setting->set = set; setting->next = *p; - if (drive->driver) - setting->auto_remove = 1; - *p = setting; - return; -abort: - if (setting) - kfree(setting); -} - -void ide_remove_setting (ide_drive_t *drive, char *name) -{ - ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting; - - while ((*p) && strcmp((*p)->name, name)) - p = &((*p)->next); - if ((setting = (*p)) == NULL) - return; - (*p) = setting->next; - kfree(setting->name); - kfree(setting); -} - -static ide_settings_t *ide_find_setting_by_ioctl (ide_drive_t *drive, int cmd) -{ - ide_settings_t *setting = drive->settings; - - while (setting) { - if (setting->read_ioctl == cmd || setting->write_ioctl == cmd) - break; - setting = setting->next; - } - return setting; -} - -ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name) -{ - ide_settings_t *setting = drive->settings; - - while (setting) { - if (strcmp(setting->name, name) == 0) - break; - setting = setting->next; - } - return setting; -} - -static void auto_remove_settings (ide_drive_t *drive) -{ - ide_settings_t *setting; -repeat: - setting = drive->settings; - while (setting) { - if (setting->auto_remove) { - ide_remove_setting(drive, setting->name); - goto repeat; - } - setting = setting->next; - } -} - -int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting) -{ - int val = -EINVAL; - unsigned long flags; - - if ((setting->rw & SETTING_READ)) { - spin_lock_irqsave(&io_request_lock, flags); - switch(setting->data_type) { - case TYPE_BYTE: - val = *((u8 *) setting->data); - break; - case TYPE_SHORT: - val = *((u16 *) setting->data); - break; - case TYPE_INT: - case TYPE_INTA: - val = *((u32 *) setting->data); - break; - } - spin_unlock_irqrestore(&io_request_lock, flags); - } - return val; -} - -int ide_spin_wait_hwgroup (ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - unsigned long timeout = jiffies + (3 * HZ); - - spin_lock_irq(&io_request_lock); - - while (hwgroup->busy) { - unsigned long lflags; - spin_unlock_irq(&io_request_lock); - __save_flags(lflags); /* local CPU only */ - __sti(); /* local CPU only; needed for jiffies */ - if (0 < (signed long)(jiffies - timeout)) { - __restore_flags(lflags); /* local CPU only */ - printk("%s: channel busy\n", drive->name); - return -EBUSY; - } - __restore_flags(lflags); /* local CPU only */ - spin_lock_irq(&io_request_lock); - } - return 0; -} - -/* - * FIXME: This should be changed to enqueue a special request - * to the driver to change settings, and then wait on a sema for completion. - * The current scheme of polling is kludgey, though safe enough. - */ -int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) -{ - int i; - u32 *p; - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (!(setting->rw & SETTING_WRITE)) - return -EPERM; - if (val < setting->min || val > setting->max) - return -EINVAL; - if (setting->set) - return setting->set(drive, val); - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - switch (setting->data_type) { - case TYPE_BYTE: - *((u8 *) setting->data) = val; - break; - case TYPE_SHORT: - *((u16 *) setting->data) = val; - break; - case TYPE_INT: - *((u32 *) setting->data) = val; - break; - case TYPE_INTA: - p = (u32 *) setting->data; - for (i = 0; i < 1 << PARTN_BITS; i++, p++) - *p = val; - break; - } - spin_unlock_irq(&io_request_lock); - return 0; -} - -static int set_io_32bit(ide_drive_t *drive, int arg) -{ - drive->io_32bit = arg; -#ifdef CONFIG_BLK_DEV_DTC2278 - if (HWIF(drive)->chipset == ide_dtc2278) - HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg; -#endif /* CONFIG_BLK_DEV_DTC2278 */ - return 0; -} - -static int set_using_dma (ide_drive_t *drive, int arg) -{ - if (!drive->driver || !DRIVER(drive)->supports_dma) - return -EPERM; - if (!drive->id || !(drive->id->capability & 1) || !HWIF(drive)->dmaproc) - return -EPERM; - if (HWIF(drive)->dmaproc(arg ? ide_dma_on : ide_dma_off, drive)) - return -EIO; - return 0; -} - -static int set_pio_mode (ide_drive_t *drive, int arg) -{ - struct request rq; - - if (!HWIF(drive)->tuneproc) - return -ENOSYS; - if (drive->special.b.set_tune) - return -EBUSY; - ide_init_drive_cmd(&rq); - drive->tune_req = (byte) arg; - drive->special.b.set_tune = 1; - (void) ide_do_drive_cmd (drive, &rq, ide_wait); - return 0; -} - -void ide_add_generic_settings (ide_drive_t *drive) -{ -/* - * drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function - */ - ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT, HDIO_SET_32BIT, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit); - ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL); - ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL); - ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode); - ide_add_setting(drive, "slow", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->slow, NULL); - ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL); - ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma); - ide_add_setting(drive, "ide_scsi", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->scsi, NULL); - ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 69, 1, 1, &drive->init_speed, NULL); - ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 69, 1, 1, &drive->current_speed, NULL); - ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL); -} - -int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf) -{ - struct request rq; - byte buffer[4]; - - if (!buf) - buf = buffer; - memset(buf, 0, 4 + SECTOR_WORDS * 4 * sectors); - ide_init_drive_cmd(&rq); - rq.buffer = buf; - *buf++ = cmd; - *buf++ = nsect; - *buf++ = feature; - *buf++ = sectors; - return ide_do_drive_cmd(drive, &rq, ide_wait); -} - -int ide_wait_cmd_task (ide_drive_t *drive, byte *buf) -{ - struct request rq; - - ide_init_drive_cmd(&rq); - rq.cmd = IDE_DRIVE_TASK; - rq.buffer = buf; - return ide_do_drive_cmd(drive, &rq, ide_wait); -} - -/* - * Delay for *at least* 50ms. As we don't know how much time is left - * until the next tick occurs, we wait an extra tick to be safe. - * This is used only during the probing/polling for drives at boot time. - * - * However, its usefullness may be needed in other places, thus we export it now. - * The future may change this to a millisecond setable delay. - */ -void ide_delay_50ms (void) -{ -#ifndef CONFIG_BLK_DEV_IDECS - mdelay(50); -#else - __set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/20); -#endif /* CONFIG_BLK_DEV_IDECS */ -} - -int system_bus_clock (void) -{ - return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed )); -} - -int ide_reinit_drive (ide_drive_t *drive) -{ - switch (drive->media) { -#ifdef CONFIG_BLK_DEV_IDECD - case ide_cdrom: - { - extern int ide_cdrom_reinit(ide_drive_t *drive); - if (ide_cdrom_reinit(drive)) - return 1; - break; - } -#endif /* CONFIG_BLK_DEV_IDECD */ -#ifdef CONFIG_BLK_DEV_IDEDISK - case ide_disk: - { - extern int idedisk_reinit(ide_drive_t *drive); - if (idedisk_reinit(drive)) - return 1; - break; - } -#endif /* CONFIG_BLK_DEV_IDEDISK */ -#ifdef CONFIG_BLK_DEV_IDEFLOPPY - case ide_floppy: - { - extern int idefloppy_reinit(ide_drive_t *drive); - if (idefloppy_reinit(drive)) - return 1; - break; - } -#endif /* CONFIG_BLK_DEV_IDEFLOPPY */ -#ifdef CONFIG_BLK_DEV_IDETAPE - case ide_tape: - { - extern int idetape_reinit(ide_drive_t *drive); - if (idetape_reinit(drive)) - return 1; - break; - } -#endif /* CONFIG_BLK_DEV_IDETAPE */ -#ifdef CONFIG_BLK_DEV_IDESCSI -/* - * { - * extern int idescsi_reinit(ide_drive_t *drive); - * if (idescsi_reinit(drive)) - * return 1; - * break; - * } - */ -#endif /* CONFIG_BLK_DEV_IDESCSI */ - default: - return 1; - } - return 0; -} - -static int ide_ioctl (struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int err = 0, major, minor; - ide_drive_t *drive; - struct request rq; - kdev_t dev; - ide_settings_t *setting; - - if (!inode || !(dev = inode->i_rdev)) - return -EINVAL; - major = MAJOR(dev); minor = MINOR(dev); - if ((drive = get_info_ptr(inode->i_rdev)) == NULL) - return -ENODEV; - - if ((setting = ide_find_setting_by_ioctl(drive, cmd)) != NULL) { - if (cmd == setting->read_ioctl) { - err = ide_read_setting(drive, setting); - return err >= 0 ? put_user(err, (long *) arg) : err; - } else { - if ((MINOR(inode->i_rdev) & PARTN_MASK)) - return -EINVAL; - return ide_write_setting(drive, setting, arg); - } - } - - ide_init_drive_cmd (&rq); - switch (cmd) { - case HDIO_GETGEO: - { - struct hd_geometry *loc = (struct hd_geometry *) arg; - unsigned short bios_cyl = drive->bios_cyl; /* truncate */ - if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL; - if (put_user(drive->bios_head, (byte *) &loc->heads)) return -EFAULT; - if (put_user(drive->bios_sect, (byte *) &loc->sectors)) return -EFAULT; - if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT; - if (put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect, - (unsigned long *) &loc->start)) return -EFAULT; - return 0; - } - - case HDIO_GETGEO_BIG: - { - struct hd_big_geometry *loc = (struct hd_big_geometry *) arg; - if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL; - if (put_user(drive->bios_head, (byte *) &loc->heads)) return -EFAULT; - if (put_user(drive->bios_sect, (byte *) &loc->sectors)) return -EFAULT; - if (put_user(drive->bios_cyl, (unsigned int *) &loc->cylinders)) return -EFAULT; - if (put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect, - (unsigned long *) &loc->start)) return -EFAULT; - return 0; - } - - case HDIO_GETGEO_BIG_RAW: - { - struct hd_big_geometry *loc = (struct hd_big_geometry *) arg; - if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL; - if (put_user(drive->head, (byte *) &loc->heads)) return -EFAULT; - if (put_user(drive->sect, (byte *) &loc->sectors)) return -EFAULT; - if (put_user(drive->cyl, (unsigned int *) &loc->cylinders)) return -EFAULT; - if (put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect, - (unsigned long *) &loc->start)) return -EFAULT; - return 0; - } - -#if 0 - case BLKGETSIZE: /* Return device size */ - return put_user(drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects, (unsigned long *) arg); - case BLKGETSIZE64: - return put_user((u64)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects << 9, (u64 *) arg); - - case BLKRRPART: /* Re-read partition tables */ - if (!capable(CAP_SYS_ADMIN)) return -EACCES; - return ide_revalidate_disk(inode->i_rdev); -#endif - - case HDIO_OBSOLETE_IDENTITY: - case HDIO_GET_IDENTITY: - if (MINOR(inode->i_rdev) & PARTN_MASK) - return -EINVAL; - if (drive->id == NULL) - return -ENOMSG; - if (copy_to_user((char *)arg, (char *)drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142)) - return -EFAULT; - return 0; - - case HDIO_GET_NICE: - return put_user(drive->dsc_overlap << IDE_NICE_DSC_OVERLAP | - drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP | - drive->nice0 << IDE_NICE_0 | - drive->nice1 << IDE_NICE_1 | - drive->nice2 << IDE_NICE_2, - (long *) arg); - -#ifdef CONFIG_IDE_TASK_IOCTL - case HDIO_DRIVE_TASKFILE: - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) - return -EACCES; - switch(drive->media) { - case ide_disk: - return ide_taskfile_ioctl(drive, inode, file, cmd, arg); -#ifdef CONFIG_PKT_TASK_IOCTL - case ide_cdrom: - case ide_tape: - case ide_floppy: - return pkt_taskfile_ioctl(drive, inode, file, cmd, arg); -#endif /* CONFIG_PKT_TASK_IOCTL */ - default: - return -ENOMSG; - } -#endif /* CONFIG_IDE_TASK_IOCTL */ - - case HDIO_DRIVE_CMD: - { - byte args[4], *argbuf = args; - byte xfer_rate = 0; - int argsize = 4; - ide_task_t tfargs; - - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) - return -EACCES; - if (NULL == (void *) arg) - return ide_do_drive_cmd(drive, &rq, ide_wait); - if (copy_from_user(args, (void *)arg, 4)) - return -EFAULT; - - tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2]; - tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3]; - tfargs.tfRegister[IDE_SECTOR_OFFSET] = args[1]; - tfargs.tfRegister[IDE_LCYL_OFFSET] = 0x00; - tfargs.tfRegister[IDE_HCYL_OFFSET] = 0x00; - tfargs.tfRegister[IDE_SELECT_OFFSET] = 0x00; - tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0]; - - if (args[3]) { - argsize = 4 + (SECTOR_WORDS * 4 * args[3]); - argbuf = kmalloc(argsize, GFP_KERNEL); - if (argbuf == NULL) - return -ENOMEM; - memcpy(argbuf, args, 4); - } - - if (set_transfer(drive, &tfargs)) { - xfer_rate = args[1]; - if (ide_ata66_check(drive, &tfargs)) - goto abort; - } - - err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf); - - if (!err && xfer_rate) { - /* active-retuning-calls future */ - if ((HWIF(drive)->speedproc) != NULL) - HWIF(drive)->speedproc(drive, xfer_rate); - ide_driveid_update(drive); - } - abort: - if (copy_to_user((void *)arg, argbuf, argsize)) - err = -EFAULT; - if (argsize > 4) - kfree(argbuf); - return err; - } - case HDIO_DRIVE_TASK: - { - byte args[7], *argbuf = args; - int argsize = 7; - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; - if (copy_from_user(args, (void *)arg, 7)) - return -EFAULT; - err = ide_wait_cmd_task(drive, argbuf); - if (copy_to_user((void *)arg, argbuf, argsize)) - err = -EFAULT; - return err; - } - case HDIO_SCAN_HWIF: - { - int args[3]; - if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (copy_from_user(args, (void *)arg, 3 * sizeof(int))) - return -EFAULT; - if (ide_register(args[0], args[1], args[2]) == -1) - return -EIO; - return 0; - } - case HDIO_UNREGISTER_HWIF: - if (!capable(CAP_SYS_ADMIN)) return -EACCES; - /* (arg > MAX_HWIFS) checked in function */ - ide_unregister(arg); - return 0; - case HDIO_SET_NICE: - if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (drive->driver == NULL) - return -EPERM; - if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1)))) - return -EPERM; - drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1; - if (drive->dsc_overlap && !DRIVER(drive)->supports_dsc_overlap) { - drive->dsc_overlap = 0; - return -EPERM; - } - drive->nice1 = (arg >> IDE_NICE_1) & 1; - return 0; - case HDIO_DRIVE_RESET: - { - unsigned long flags; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - - if (!capable(CAP_SYS_ADMIN)) return -EACCES; -#if 1 - spin_lock_irqsave(&io_request_lock, flags); - if (hwgroup->handler != NULL) { - printk("%s: ide_set_handler: handler not null; %p\n", drive->name, hwgroup->handler); - (void) hwgroup->handler(drive); -// hwgroup->handler = NULL; -// hwgroup->expiry = NULL; - hwgroup->timer.expires = jiffies + 0;; - del_timer(&hwgroup->timer); - } - spin_unlock_irqrestore(&io_request_lock, flags); - -#endif - (void) ide_do_reset(drive); - if (drive->suspend_reset) { -/* - * APM WAKE UP todo !! - * int nogoodpower = 1; - * while(nogoodpower) { - * check_power1() or check_power2() - * nogoodpower = 0; - * } - * HWIF(drive)->multiproc(drive); - */ - return ide_revalidate_disk(inode->i_rdev); - } - return 0; - } -#if 0 - case BLKROSET: - case BLKROGET: - case BLKFLSBUF: - case BLKSSZGET: - case BLKPG: - case BLKELVGET: - case BLKELVSET: - case BLKBSZGET: - case BLKBSZSET: - return blk_ioctl(inode->i_rdev, cmd, arg); -#endif - - case HDIO_GET_BUSSTATE: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (put_user(HWIF(drive)->bus_state, (long *)arg)) - return -EFAULT; - return 0; - - case HDIO_SET_BUSSTATE: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (HWIF(drive)->busproc) - HWIF(drive)->busproc(drive, (int)arg); - return 0; - - default: - if (drive->driver != NULL) - return DRIVER(drive)->ioctl(drive, inode, file, cmd, arg); - return -EPERM; - } -} - -static int ide_check_media_change (kdev_t i_rdev) -{ - ide_drive_t *drive; - - if ((drive = get_info_ptr(i_rdev)) == NULL) - return -ENODEV; - if (drive->driver != NULL) - return DRIVER(drive)->media_change(drive); - return 0; -} - -void ide_fixstring (byte *s, const int bytecount, const int byteswap) -{ - byte *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */ - - if (byteswap) { - /* convert from big-endian to host byte order */ - for (p = end ; p != s;) { - unsigned short *pp = (unsigned short *) (p -= 2); - *pp = ntohs(*pp); - } - } - - /* strip leading blanks */ - while (s != end && *s == ' ') - ++s; - - /* compress internal blanks and strip trailing blanks */ - while (s != end && *s) { - if (*s++ != ' ' || (s != end && *s && *s != ' ')) - *p++ = *(s-1); - } - - /* wipe out trailing garbage */ - while (p != end) - *p++ = '\0'; -} - -/* - * stridx() returns the offset of c within s, - * or -1 if c is '\0' or not found within s. - */ -static int __init stridx (const char *s, char c) -{ - char *i = strchr(s, c); - return (i && c) ? i - s : -1; -} - -/* - * match_parm() does parsing for ide_setup(): - * - * 1. the first char of s must be '='. - * 2. if the remainder matches one of the supplied keywords, - * the index (1 based) of the keyword is negated and returned. - * 3. if the remainder is a series of no more than max_vals numbers - * separated by commas, the numbers are saved in vals[] and a - * count of how many were saved is returned. Base10 is assumed, - * and base16 is allowed when prefixed with "0x". - * 4. otherwise, zero is returned. - */ -static int __init match_parm (char *s, const char *keywords[], int vals[], int max_vals) -{ - static const char *decimal = "0123456789"; - static const char *hex = "0123456789abcdef"; - int i, n; - - if (*s++ == '=') { - /* - * Try matching against the supplied keywords, - * and return -(index+1) if we match one - */ - if (keywords != NULL) { - for (i = 0; *keywords != NULL; ++i) { - if (!strcmp(s, *keywords++)) - return -(i+1); - } - } - /* - * Look for a series of no more than "max_vals" - * numeric values separated by commas, in base10, - * or base16 when prefixed with "0x". - * Return a count of how many were found. - */ - for (n = 0; (i = stridx(decimal, *s)) >= 0;) { - vals[n] = i; - while ((i = stridx(decimal, *++s)) >= 0) - vals[n] = (vals[n] * 10) + i; - if (*s == 'x' && !vals[n]) { - while ((i = stridx(hex, *++s)) >= 0) - vals[n] = (vals[n] * 0x10) + i; - } - if (++n == max_vals) - break; - if (*s == ',' || *s == ';') - ++s; - } - if (!*s) - return n; - } - return 0; /* zero = nothing matched */ -} - -/* - * ide_setup() gets called VERY EARLY during initialization, - * to handle kernel "command line" strings beginning with "hdx=" - * or "ide". Here is the complete set currently supported: - * - * "hdx=" is recognized for all "x" from "a" to "h", such as "hdc". - * "idex=" is recognized for all "x" from "0" to "3", such as "ide1". - * - * "hdx=noprobe" : drive may be present, but do not probe for it - * "hdx=none" : drive is NOT present, ignore cmos and do not probe - * "hdx=nowerr" : ignore the WRERR_STAT bit on this drive - * "hdx=cdrom" : drive is present, and is a cdrom drive - * "hdx=cyl,head,sect" : disk drive is present, with specified geometry - * "hdx=noremap" : do not remap 0->1 even though EZD was detected - * "hdx=autotune" : driver will attempt to tune interface speed - * to the fastest PIO mode supported, - * if possible for this drive only. - * Not fully supported by all chipset types, - * and quite likely to cause trouble with - * older/odd IDE drives. - * - * "hdx=slow" : insert a huge pause after each access to the data - * port. Should be used only as a last resort. - * - * "hdx=swapdata" : when the drive is a disk, byte swap all data - * "hdx=bswap" : same as above.......... - * "hdxlun=xx" : set the drive last logical unit. - * "hdx=flash" : allows for more than one ata_flash disk to be - * registered. In most cases, only one device - * will be present. - * "hdx=scsi" : the return of the ide-scsi flag, this is useful for - * allowwing ide-floppy, ide-tape, and ide-cdrom|writers - * to use ide-scsi emulation on a device specific option. - * "idebus=xx" : inform IDE driver of VESA/PCI bus speed in MHz, - * where "xx" is between 20 and 66 inclusive, - * used when tuning chipset PIO modes. - * For PCI bus, 25 is correct for a P75 system, - * 30 is correct for P90,P120,P180 systems, - * and 33 is used for P100,P133,P166 systems. - * If in doubt, use idebus=33 for PCI. - * As for VLB, it is safest to not specify it. - * - * "idex=noprobe" : do not attempt to access/use this interface - * "idex=base" : probe for an interface at the addr specified, - * where "base" is usually 0x1f0 or 0x170 - * and "ctl" is assumed to be "base"+0x206 - * "idex=base,ctl" : specify both base and ctl - * "idex=base,ctl,irq" : specify base, ctl, and irq number - * "idex=autotune" : driver will attempt to tune interface speed - * to the fastest PIO mode supported, - * for all drives on this interface. - * Not fully supported by all chipset types, - * and quite likely to cause trouble with - * older/odd IDE drives. - * "idex=noautotune" : driver will NOT attempt to tune interface speed - * This is the default for most chipsets, - * except the cmd640. - * "idex=serialize" : do not overlap operations on idex and ide(x^1) - * "idex=four" : four drives on idex and ide(x^1) share same ports - * "idex=reset" : reset interface before first use - * "idex=dma" : enable DMA by default on both drives if possible - * "idex=ata66" : informs the interface that it has an 80c cable - * for chipsets that are ATA-66 capable, but - * the ablity to bit test for detection is - * currently unknown. - * "ide=reverse" : Formerly called to pci sub-system, but now local. - * - * The following are valid ONLY on ide0, (except dc4030) - * and the defaults for the base,ctl ports must not be altered. - * - * "ide0=dtc2278" : probe/support DTC2278 interface - * "ide0=ht6560b" : probe/support HT6560B interface - * "ide0=cmd640_vlb" : *REQUIRED* for VLB cards with the CMD640 chip - * (not for PCI -- automatically detected) - * "ide0=qd65xx" : probe/support qd65xx interface - * "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439, M1443, M1445) - * "ide0=umc8672" : probe/support umc8672 chipsets - * "idex=dc4030" : probe/support Promise DC4030VL interface - * "ide=doubler" : probe/support IDE doublers on Amiga - */ -int __init ide_setup (char *s) -{ - int i, vals[3]; - ide_hwif_t *hwif; - ide_drive_t *drive; - unsigned int hw, unit; - const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1); - const char max_hwif = '0' + (MAX_HWIFS - 1); - - - if (strncmp(s,"hd",2) == 0 && s[2] == '=') /* hd= is for hd.c */ - return 0; /* driver and not us */ - - if (strncmp(s,"ide",3) && - strncmp(s,"idebus",6) && - strncmp(s,"hd",2)) /* hdx= & hdxlun= */ - return 0; - - printk("ide_setup: %s", s); - init_ide_data (); - -#ifdef CONFIG_BLK_DEV_IDEDOUBLER - if (!strcmp(s, "ide=doubler")) { - extern int ide_doubler; - - printk(" : Enabled support for IDE doublers\n"); - ide_doubler = 1; - return 1; - } -#endif /* CONFIG_BLK_DEV_IDEDOUBLER */ - - if (!strcmp(s, "ide=nodma")) { - printk("IDE: Prevented DMA\n"); - noautodma = 1; - return 1; - } - -#ifdef CONFIG_BLK_DEV_IDEPCI - if (!strcmp(s, "ide=reverse")) { - ide_scan_direction = 1; - printk(" : Enabled support for IDE inverse scan order.\n"); - return 1; - } -#endif /* CONFIG_BLK_DEV_IDEPCI */ - - /* - * Look for drive options: "hdx=" - */ - if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) { - const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom", - "serialize", "autotune", "noautotune", - "slow", "swapdata", "bswap", "flash", - "remap", "noremap", "scsi", NULL}; - unit = s[2] - 'a'; - hw = unit / MAX_DRIVES; - unit = unit % MAX_DRIVES; - hwif = &ide_hwifs[hw]; - drive = &hwif->drives[unit]; - if (strncmp(s + 4, "ide-", 4) == 0) { - strncpy(drive->driver_req, s + 4, 9); - goto done; - } - /* - * Look for last lun option: "hdxlun=" - */ - if (s[3] == 'l' && s[4] == 'u' && s[5] == 'n') { - if (match_parm(&s[6], NULL, vals, 1) != 1) - goto bad_option; - if (vals[0] >= 0 && vals[0] <= 7) { - drive->last_lun = vals[0]; - drive->forced_lun = 1; - } else - printk(" -- BAD LAST LUN! Expected value from 0 to 7"); - goto done; - } - switch (match_parm(&s[3], hd_words, vals, 3)) { - case -1: /* "none" */ - drive->nobios = 1; /* drop into "noprobe" */ - case -2: /* "noprobe" */ - drive->noprobe = 1; - goto done; - case -3: /* "nowerr" */ - drive->bad_wstat = BAD_R_STAT; - hwif->noprobe = 0; - goto done; - case -4: /* "cdrom" */ - drive->present = 1; - drive->media = ide_cdrom; - hwif->noprobe = 0; - goto done; - case -5: /* "serialize" */ - printk(" -- USE \"ide%d=serialize\" INSTEAD", hw); - goto do_serialize; - case -6: /* "autotune" */ - drive->autotune = 1; - goto done; - case -7: /* "noautotune" */ - drive->autotune = 2; - goto done; - case -8: /* "slow" */ - drive->slow = 1; - goto done; - case -9: /* "swapdata" or "bswap" */ - case -10: - drive->bswap = 1; - goto done; - case -11: /* "flash" */ - drive->ata_flash = 1; - goto done; - case -12: /* "remap" */ - drive->remap_0_to_1 = 1; - goto done; - case -13: /* "noremap" */ - drive->remap_0_to_1 = 2; - goto done; - case -14: /* "scsi" */ -#if defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) - drive->scsi = 1; - goto done; -#else - drive->scsi = 0; - goto bad_option; -#endif /* defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) */ - case 3: /* cyl,head,sect */ - drive->media = ide_disk; - drive->cyl = drive->bios_cyl = vals[0]; - drive->head = drive->bios_head = vals[1]; - drive->sect = drive->bios_sect = vals[2]; - drive->present = 1; - drive->forced_geom = 1; - hwif->noprobe = 0; - goto done; - default: - goto bad_option; - } - } - - if (s[0] != 'i' || s[1] != 'd' || s[2] != 'e') - goto bad_option; - /* - * Look for bus speed option: "idebus=" - */ - if (s[3] == 'b' && s[4] == 'u' && s[5] == 's') { - if (match_parm(&s[6], NULL, vals, 1) != 1) - goto bad_option; - if (vals[0] >= 20 && vals[0] <= 66) { - idebus_parameter = vals[0]; - } else - printk(" -- BAD BUS SPEED! Expected value from 20 to 66"); - goto done; - } - /* - * Look for interface options: "idex=" - */ - if (s[3] >= '0' && s[3] <= max_hwif) { - /* - * Be VERY CAREFUL changing this: note hardcoded indexes below - * -8,-9,-10 : are reserved for future idex calls to ease the hardcoding. - */ - const char *ide_words[] = { - "noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66", - "minus8", "minus9", "minus10", - "four", "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL }; - hw = s[3] - '0'; - hwif = &ide_hwifs[hw]; - i = match_parm(&s[4], ide_words, vals, 3); - - /* - * Cryptic check to ensure chipset not already set for hwif: - */ - if (i > 0 || i <= -11) { /* is parameter a chipset name? */ - if (hwif->chipset != ide_unknown) - goto bad_option; /* chipset already specified */ - if (i <= -11 && i != -18 && hw != 0) - goto bad_hwif; /* chipset drivers are for "ide0=" only */ - if (i <= -11 && i != -18 && ide_hwifs[hw+1].chipset != ide_unknown) - goto bad_option; /* chipset for 2nd port already specified */ - printk("\n"); - } - - switch (i) { -#ifdef CONFIG_BLK_DEV_PDC4030 - case -18: /* "dc4030" */ - { - extern void init_pdc4030(void); - init_pdc4030(); - goto done; - } -#endif /* CONFIG_BLK_DEV_PDC4030 */ -#ifdef CONFIG_BLK_DEV_ALI14XX - case -17: /* "ali14xx" */ - { - extern void init_ali14xx (void); - init_ali14xx(); - goto done; - } -#endif /* CONFIG_BLK_DEV_ALI14XX */ -#ifdef CONFIG_BLK_DEV_UMC8672 - case -16: /* "umc8672" */ - { - extern void init_umc8672 (void); - init_umc8672(); - goto done; - } -#endif /* CONFIG_BLK_DEV_UMC8672 */ -#ifdef CONFIG_BLK_DEV_DTC2278 - case -15: /* "dtc2278" */ - { - extern void init_dtc2278 (void); - init_dtc2278(); - goto done; - } -#endif /* CONFIG_BLK_DEV_DTC2278 */ -#ifdef CONFIG_BLK_DEV_CMD640 - case -14: /* "cmd640_vlb" */ - { - extern int cmd640_vlb; /* flag for cmd640.c */ - cmd640_vlb = 1; - goto done; - } -#endif /* CONFIG_BLK_DEV_CMD640 */ -#ifdef CONFIG_BLK_DEV_HT6560B - case -13: /* "ht6560b" */ - { - extern void init_ht6560b (void); - init_ht6560b(); - goto done; - } -#endif /* CONFIG_BLK_DEV_HT6560B */ -#if CONFIG_BLK_DEV_QD65XX - case -12: /* "qd65xx" */ - { - extern void init_qd65xx (void); - init_qd65xx(); - goto done; - } -#endif /* CONFIG_BLK_DEV_QD65XX */ -#ifdef CONFIG_BLK_DEV_4DRIVES - case -11: /* "four" drives on one set of ports */ - { - ide_hwif_t *mate = &ide_hwifs[hw^1]; - mate->drives[0].select.all ^= 0x20; - mate->drives[1].select.all ^= 0x20; - hwif->chipset = mate->chipset = ide_4drives; - mate->irq = hwif->irq; - memcpy(mate->io_ports, hwif->io_ports, sizeof(hwif->io_ports)); - goto do_serialize; - } -#endif /* CONFIG_BLK_DEV_4DRIVES */ - case -10: /* minus10 */ - case -9: /* minus9 */ - case -8: /* minus8 */ - goto bad_option; - case -7: /* ata66 */ -#ifdef CONFIG_BLK_DEV_IDEPCI - hwif->udma_four = 1; - goto done; -#else /* !CONFIG_BLK_DEV_IDEPCI */ - hwif->udma_four = 0; - goto bad_hwif; -#endif /* CONFIG_BLK_DEV_IDEPCI */ - case -6: /* dma */ - hwif->autodma = 1; - goto done; - case -5: /* "reset" */ - hwif->reset = 1; - goto done; - case -4: /* "noautotune" */ - hwif->drives[0].autotune = 2; - hwif->drives[1].autotune = 2; - goto done; - case -3: /* "autotune" */ - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - goto done; - case -2: /* "serialize" */ - do_serialize: - hwif->mate = &ide_hwifs[hw^1]; - hwif->mate->mate = hwif; - hwif->serialized = hwif->mate->serialized = 1; - goto done; - - case -1: /* "noprobe" */ - hwif->noprobe = 1; - goto done; - - case 1: /* base */ - vals[1] = vals[0] + 0x206; /* default ctl */ - case 2: /* base,ctl */ - vals[2] = 0; /* default irq = probe for it */ - case 3: /* base,ctl,irq */ - hwif->hw.irq = vals[2]; - ide_init_hwif_ports(&hwif->hw, (ide_ioreg_t) vals[0], (ide_ioreg_t) vals[1], &hwif->irq); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); - hwif->irq = vals[2]; - hwif->noprobe = 0; - hwif->chipset = ide_generic; - goto done; - - case 0: goto bad_option; - default: - printk(" -- SUPPORT NOT CONFIGURED IN THIS KERNEL\n"); - return 1; - } - } -bad_option: - printk(" -- BAD OPTION\n"); - return 1; -bad_hwif: - printk("-- NOT SUPPORTED ON ide%d", hw); -done: - printk("\n"); - return 1; -} - -/* - * probe_for_hwifs() finds/initializes "known" IDE interfaces - */ -static void __init probe_for_hwifs (void) -{ -#ifdef CONFIG_PCI - if (pci_present()) - { -#ifdef CONFIG_BLK_DEV_IDEPCI - ide_scan_pcibus(ide_scan_direction); -#else -#ifdef CONFIG_BLK_DEV_RZ1000 - { - extern void ide_probe_for_rz100x(void); - ide_probe_for_rz100x(); - } -#endif /* CONFIG_BLK_DEV_RZ1000 */ -#endif /* CONFIG_BLK_DEV_IDEPCI */ - } -#endif /* CONFIG_PCI */ - -#ifdef CONFIG_ETRAX_IDE - { - extern void init_e100_ide(void); - init_e100_ide(); - } -#endif /* CONFIG_ETRAX_IDE */ -#ifdef CONFIG_BLK_DEV_CMD640 - { - extern void ide_probe_for_cmd640x(void); - ide_probe_for_cmd640x(); - } -#endif /* CONFIG_BLK_DEV_CMD640 */ -#ifdef CONFIG_BLK_DEV_PDC4030 - { - extern int ide_probe_for_pdc4030(void); - (void) ide_probe_for_pdc4030(); - } -#endif /* CONFIG_BLK_DEV_PDC4030 */ -#ifdef CONFIG_BLK_DEV_IDE_PMAC - { - extern void pmac_ide_probe(void); - pmac_ide_probe(); - } -#endif /* CONFIG_BLK_DEV_IDE_PMAC */ -#ifdef CONFIG_BLK_DEV_IDE_SWARM - { - extern void swarm_ide_probe(void); - swarm_ide_probe(); - } -#endif /* CONFIG_BLK_DEV_IDE_SWARM */ -#ifdef CONFIG_BLK_DEV_IDE_ICSIDE - { - extern void icside_init(void); - icside_init(); - } -#endif /* CONFIG_BLK_DEV_IDE_ICSIDE */ -#ifdef CONFIG_BLK_DEV_IDE_RAPIDE - { - extern void rapide_init(void); - rapide_init(); - } -#endif /* CONFIG_BLK_DEV_IDE_RAPIDE */ -#ifdef CONFIG_BLK_DEV_GAYLE - { - extern void gayle_init(void); - gayle_init(); - } -#endif /* CONFIG_BLK_DEV_GAYLE */ -#ifdef CONFIG_BLK_DEV_FALCON_IDE - { - extern void falconide_init(void); - falconide_init(); - } -#endif /* CONFIG_BLK_DEV_FALCON_IDE */ -#ifdef CONFIG_BLK_DEV_MAC_IDE - { - extern void macide_init(void); - macide_init(); - } -#endif /* CONFIG_BLK_DEV_MAC_IDE */ -#ifdef CONFIG_BLK_DEV_Q40IDE - { - extern void q40ide_init(void); - q40ide_init(); - } -#endif /* CONFIG_BLK_DEV_Q40IDE */ -#ifdef CONFIG_BLK_DEV_BUDDHA - { - extern void buddha_init(void); - buddha_init(); - } -#endif /* CONFIG_BLK_DEV_BUDDHA */ -#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) - { - extern void pnpide_init(int enable); - pnpide_init(1); - } -#endif /* CONFIG_BLK_DEV_ISAPNP */ -} - -void __init ide_init_builtin_drivers (void) -{ - /* - * Probe for special PCI and other "known" interface chipsets - */ - probe_for_hwifs (); - -#ifdef CONFIG_BLK_DEV_IDE -#if defined(__mc68000__) || defined(CONFIG_APUS) - if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) { - ide_get_lock(&ide_lock, NULL, NULL); /* for atari only */ - disable_irq(ide_hwifs[0].irq); /* disable_irq_nosync ?? */ -// disable_irq_nosync(ide_hwifs[0].irq); - } -#endif /* __mc68000__ || CONFIG_APUS */ - - (void) ideprobe_init(); - -#if defined(__mc68000__) || defined(CONFIG_APUS) - if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) { - enable_irq(ide_hwifs[0].irq); - ide_release_lock(&ide_lock); /* for atari only */ - } -#endif /* __mc68000__ || CONFIG_APUS */ -#endif /* CONFIG_BLK_DEV_IDE */ - -#ifdef CONFIG_PROC_FS - proc_ide_create(); -#endif - - /* - * Attempt to match drivers for the available drives - */ -#ifdef CONFIG_BLK_DEV_IDEDISK - (void) idedisk_init(); -#endif /* CONFIG_BLK_DEV_IDEDISK */ -#ifdef CONFIG_BLK_DEV_IDECD - (void) ide_cdrom_init(); -#endif /* CONFIG_BLK_DEV_IDECD */ -#ifdef CONFIG_BLK_DEV_IDETAPE - (void) idetape_init(); -#endif /* CONFIG_BLK_DEV_IDETAPE */ -#ifdef CONFIG_BLK_DEV_IDEFLOPPY - (void) idefloppy_init(); -#endif /* CONFIG_BLK_DEV_IDEFLOPPY */ -#ifdef CONFIG_BLK_DEV_IDESCSI - #ifdef CONFIG_SCSI - (void) idescsi_init(); - #else - #warning ide scsi-emulation selected but no SCSI-subsystem in kernel - #endif -#endif /* CONFIG_BLK_DEV_IDESCSI */ -} - -static int default_cleanup (ide_drive_t *drive) -{ - return ide_unregister_subdriver(drive); -} - -static int default_standby (ide_drive_t *drive) -{ - return 0; -} - -static int default_flushcache (ide_drive_t *drive) -{ - return 0; -} - -static ide_startstop_t default_do_request(ide_drive_t *drive, struct request *rq, unsigned long block) -{ - ide_end_request(0, HWGROUP(drive)); - return ide_stopped; -} - -static void default_end_request (byte uptodate, ide_hwgroup_t *hwgroup) -{ - ide_end_request(uptodate, hwgroup); -} - -static int default_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return -EIO; -} - -static int default_open (struct inode *inode, struct file *filp, ide_drive_t *drive) -{ - drive->usage--; - return -EIO; -} - -static void default_release (struct inode *inode, struct file *filp, ide_drive_t *drive) -{ -} - -static int default_check_media_change (ide_drive_t *drive) -{ - return 1; -} - -static void default_pre_reset (ide_drive_t *drive) -{ -} - -static unsigned long default_capacity (ide_drive_t *drive) -{ - return 0x7fffffff; -} - -static ide_startstop_t default_special (ide_drive_t *drive) -{ - special_t *s = &drive->special; - - s->all = 0; - drive->mult_req = 0; - return ide_stopped; -} - -static int default_reinit (ide_drive_t *drive) -{ - printk(KERN_ERR "%s: does not support hotswap of device class !\n", drive->name); - - return 0; -} - -static void setup_driver_defaults (ide_drive_t *drive) -{ - ide_driver_t *d = drive->driver; - - if (d->cleanup == NULL) d->cleanup = default_cleanup; - if (d->standby == NULL) d->standby = default_standby; - if (d->flushcache == NULL) d->flushcache = default_flushcache; - if (d->do_request == NULL) d->do_request = default_do_request; - if (d->end_request == NULL) d->end_request = default_end_request; - if (d->ioctl == NULL) d->ioctl = default_ioctl; - if (d->open == NULL) d->open = default_open; - if (d->release == NULL) d->release = default_release; - if (d->media_change == NULL) d->media_change = default_check_media_change; - if (d->pre_reset == NULL) d->pre_reset = default_pre_reset; - if (d->capacity == NULL) d->capacity = default_capacity; - if (d->special == NULL) d->special = default_special; - if (d->reinit == NULL) d->reinit = default_reinit; -} - -ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n) -{ - unsigned int unit, index, i; - - for (index = 0, i = 0; index < MAX_HWIFS; ++index) { - ide_hwif_t *hwif = &ide_hwifs[index]; - if (!hwif->present) - continue; - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - char *req = drive->driver_req; - if (*req && !strstr(name, req)) - continue; - if (drive->present && drive->media == media && drive->driver == driver && ++i > n) - return drive; - } - } - return NULL; -} - -int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version) -{ - unsigned long flags; - - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - if (version != IDE_SUBDRIVER_VERSION || !drive->present || drive->driver != NULL || drive->busy || drive->usage) { - restore_flags(flags); /* all CPUs */ - return 1; - } - drive->driver = driver; - setup_driver_defaults(drive); - restore_flags(flags); /* all CPUs */ - if (drive->autotune != 2) { - if (driver->supports_dma && HWIF(drive)->dmaproc != NULL) { - /* - * Force DMAing for the beginning of the check. - * Some chipsets appear to do interesting things, - * if not checked and cleared. - * PARANOIA!!! - */ - (void) (HWIF(drive)->dmaproc(ide_dma_off_quietly, drive)); - (void) (HWIF(drive)->dmaproc(ide_dma_check, drive)); - } - drive->dsc_overlap = (drive->next != drive && driver->supports_dsc_overlap); - drive->nice1 = 1; - } - drive->revalidate = 1; - drive->suspend_reset = 0; -#ifdef CONFIG_PROC_FS - ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive); - ide_add_proc_entries(drive->proc, driver->proc, drive); -#endif - return 0; -} - -int ide_unregister_subdriver (ide_drive_t *drive) -{ - unsigned long flags; - - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - if (drive->usage || drive->busy || drive->driver == NULL || DRIVER(drive)->busy) { - restore_flags(flags); /* all CPUs */ - return 1; - } -#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) && defined(MODULE) - pnpide_init(0); -#endif /* CONFIG_BLK_DEV_ISAPNP */ -#ifdef CONFIG_PROC_FS - ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc); - ide_remove_proc_entries(drive->proc, generic_subdriver_entries); -#endif - auto_remove_settings(drive); - drive->driver = NULL; - restore_flags(flags); /* all CPUs */ - return 0; -} - -int ide_register_module (ide_module_t *module) -{ - ide_module_t *p = ide_modules; - - while (p) { - if (p == module) - return 1; - p = p->next; - } - module->next = ide_modules; - ide_modules = module; - revalidate_drives(); - return 0; -} - -void ide_unregister_module (ide_module_t *module) -{ - ide_module_t **p; - - for (p = &ide_modules; (*p) && (*p) != module; p = &((*p)->next)); - if (*p) - *p = (*p)->next; -} - -struct block_device_operations ide_fops[] = {{ - open: ide_open, - release: ide_release, - ioctl: ide_ioctl, - check_media_change: ide_check_media_change, - revalidate: ide_revalidate_disk -}}; - -EXPORT_SYMBOL(ide_hwifs); -EXPORT_SYMBOL(ide_register_module); -EXPORT_SYMBOL(ide_unregister_module); -EXPORT_SYMBOL(ide_spin_wait_hwgroup); - -/* - * Probe module - */ -#ifdef DEVFS_MUST_DIE -devfs_handle_t ide_devfs_handle; -#endif - -EXPORT_SYMBOL(ide_probe); -EXPORT_SYMBOL(drive_is_flashcard); -EXPORT_SYMBOL(ide_timer_expiry); -EXPORT_SYMBOL(ide_intr); -EXPORT_SYMBOL(ide_fops); -EXPORT_SYMBOL(ide_get_queue); -EXPORT_SYMBOL(ide_add_generic_settings); -#ifdef DEVFS_MUST_DIE -EXPORT_SYMBOL(ide_devfs_handle); -#endif -EXPORT_SYMBOL(do_ide_request); -/* - * Driver module - */ -EXPORT_SYMBOL(ide_scan_devices); -EXPORT_SYMBOL(ide_register_subdriver); -EXPORT_SYMBOL(ide_unregister_subdriver); -EXPORT_SYMBOL(ide_replace_subdriver); -EXPORT_SYMBOL(ide_input_data); -EXPORT_SYMBOL(ide_output_data); -EXPORT_SYMBOL(atapi_input_bytes); -EXPORT_SYMBOL(atapi_output_bytes); -EXPORT_SYMBOL(drive_is_ready); -EXPORT_SYMBOL(ide_set_handler); -EXPORT_SYMBOL(ide_dump_status); -EXPORT_SYMBOL(ide_error); -EXPORT_SYMBOL(ide_fixstring); -EXPORT_SYMBOL(ide_wait_stat); -EXPORT_SYMBOL(ide_do_reset); -EXPORT_SYMBOL(restart_request); -EXPORT_SYMBOL(ide_init_drive_cmd); -EXPORT_SYMBOL(ide_do_drive_cmd); -EXPORT_SYMBOL(ide_end_drive_cmd); -EXPORT_SYMBOL(ide_end_request); -EXPORT_SYMBOL(ide_revalidate_disk); -EXPORT_SYMBOL(ide_cmd); -EXPORT_SYMBOL(ide_wait_cmd); -EXPORT_SYMBOL(ide_wait_cmd_task); -EXPORT_SYMBOL(ide_delay_50ms); -EXPORT_SYMBOL(ide_stall_queue); -#ifdef CONFIG_PROC_FS -EXPORT_SYMBOL(ide_add_proc_entries); -EXPORT_SYMBOL(ide_remove_proc_entries); -EXPORT_SYMBOL(proc_ide_read_geometry); -EXPORT_SYMBOL(create_proc_ide_interfaces); -EXPORT_SYMBOL(recreate_proc_ide_device); -EXPORT_SYMBOL(destroy_proc_ide_device); -#endif -EXPORT_SYMBOL(ide_add_setting); -EXPORT_SYMBOL(ide_remove_setting); - -EXPORT_SYMBOL(ide_register_hw); -EXPORT_SYMBOL(ide_register); -EXPORT_SYMBOL(ide_unregister); -EXPORT_SYMBOL(ide_setup_ports); -EXPORT_SYMBOL(hwif_unregister); -EXPORT_SYMBOL(get_info_ptr); -EXPORT_SYMBOL(current_capacity); - -EXPORT_SYMBOL(system_bus_clock); - -EXPORT_SYMBOL(ide_reinit_drive); - -#if 0 -static int ide_notify_reboot (struct notifier_block *this, unsigned long event, void *x) -{ - ide_hwif_t *hwif; - ide_drive_t *drive; - int i, unit; - - switch (event) { - case SYS_HALT: - case SYS_POWER_OFF: - case SYS_RESTART: - break; - default: - return NOTIFY_DONE; - } - - printk("flushing ide devices: "); - - for (i = 0; i < MAX_HWIFS; i++) { - hwif = &ide_hwifs[i]; - if (!hwif->present) - continue; - for (unit = 0; unit < MAX_DRIVES; ++unit) { - drive = &hwif->drives[unit]; - if (!drive->present) - continue; - - /* set the drive to standby */ - printk("%s ", drive->name); - if (event != SYS_RESTART) - if (drive->driver != NULL && DRIVER(drive)->standby(drive)) - continue; - - if (drive->driver != NULL && DRIVER(drive)->cleanup(drive)) - continue; - } - } - printk("\n"); - return NOTIFY_DONE; -} - -static struct notifier_block ide_notifier = { - ide_notify_reboot, - NULL, - 5 -}; -#endif - -/* - * This is gets invoked once during initialization, to set *everything* up - */ -int __init ide_init (void) -{ - static char banner_printed; - int i; - - if (!banner_printed) { - printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n"); -#ifdef DEVFS_MUST_DIE - ide_devfs_handle = devfs_mk_dir (NULL, "ide", NULL); -#endif - system_bus_speed = ide_system_bus_speed(); - banner_printed = 1; - } - - init_ide_data (); - - initializing = 1; - ide_init_builtin_drivers(); - initializing = 0; - - for (i = 0; i < MAX_HWIFS; ++i) { - ide_hwif_t *hwif = &ide_hwifs[i]; - if (hwif->present) - ide_geninit(hwif); - } - - /*register_reboot_notifier(&ide_notifier);*/ - return 0; -} - -#ifdef MODULE -char *options = NULL; -MODULE_PARM(options,"s"); -MODULE_LICENSE("GPL"); - -static void __init parse_options (char *line) -{ - char *next = line; - - if (line == NULL || !*line) - return; - while ((line = next) != NULL) { - if ((next = strchr(line,' ')) != NULL) - *next++ = 0; - if (!ide_setup(line)) - printk ("Unknown option '%s'\n", line); - } -} - -int init_module (void) -{ - parse_options(options); - return ide_init(); -} - -void cleanup_module (void) -{ - int index; - - /*unregister_reboot_notifier(&ide_notifier);*/ - for (index = 0; index < MAX_HWIFS; ++index) { - ide_unregister(index); -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) - if (ide_hwifs[index].dma_base) - (void) ide_release_dma(&ide_hwifs[index]); -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ - } - -#ifdef CONFIG_PROC_FS - proc_ide_destroy(); -#endif -#ifdef DEVFS_MUST_DIE - devfs_unregister (ide_devfs_handle); -#endif -} - -#else /* !MODULE */ - -__setup("", ide_setup); - -#endif /* MODULE */ diff --git a/xen/drivers/ide/ide_modes.h b/xen/drivers/ide/ide_modes.h deleted file mode 100644 index c848380b13..0000000000 --- a/xen/drivers/ide/ide_modes.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * linux/drivers/ide/ide_modes.h - * - * Copyright (C) 1996 Linus Torvalds, Igor Abramov, and Mark Lord - */ - -#ifndef _IDE_MODES_H -#define _IDE_MODES_H - -#include - -/* - * Shared data/functions for determining best PIO mode for an IDE drive. - * Most of this stuff originally lived in cmd640.c, and changes to the - * ide_pio_blacklist[] table should be made with EXTREME CAUTION to avoid - * breaking the fragile cmd640.c support. - */ - -#ifdef CONFIG_BLK_DEV_IDE_MODES - -/* - * Standard (generic) timings for PIO modes, from ATA2 specification. - * These timings are for access to the IDE data port register *only*. - * Some drives may specify a mode, while also specifying a different - * value for cycle_time (from drive identification data). - */ -typedef struct ide_pio_timings_s { - int setup_time; /* Address setup (ns) minimum */ - int active_time; /* Active pulse (ns) minimum */ - int cycle_time; /* Cycle time (ns) minimum = (setup + active + recovery) */ -} ide_pio_timings_t; - -typedef struct ide_pio_data_s { - byte pio_mode; - byte use_iordy; - byte overridden; - byte blacklisted; - unsigned int cycle_time; -} ide_pio_data_t; - -#ifndef _IDE_C - -int ide_scan_pio_blacklist (char *model); -byte ide_get_best_pio_mode (ide_drive_t *drive, byte mode_wanted, byte max_mode, ide_pio_data_t *d); -extern const ide_pio_timings_t ide_pio_timings[6]; - -#else /* _IDE_C */ - -const ide_pio_timings_t ide_pio_timings[6] = { - { 70, 165, 600 }, /* PIO Mode 0 */ - { 50, 125, 383 }, /* PIO Mode 1 */ - { 30, 100, 240 }, /* PIO Mode 2 */ - { 30, 80, 180 }, /* PIO Mode 3 with IORDY */ - { 25, 70, 120 }, /* PIO Mode 4 with IORDY */ - { 20, 50, 100 } /* PIO Mode 5 with IORDY (nonstandard) */ -}; - -/* - * Black list. Some drives incorrectly report their maximal PIO mode, - * at least in respect to CMD640. Here we keep info on some known drives. - */ -static struct ide_pio_info { - const char *name; - int pio; -} ide_pio_blacklist [] = { -/* { "Conner Peripherals 1275MB - CFS1275A", 4 }, */ - { "Conner Peripherals 540MB - CFS540A", 3 }, - - { "WDC AC2700", 3 }, - { "WDC AC2540", 3 }, - { "WDC AC2420", 3 }, - { "WDC AC2340", 3 }, - { "WDC AC2250", 0 }, - { "WDC AC2200", 0 }, - { "WDC AC21200", 4 }, - { "WDC AC2120", 0 }, - { "WDC AC2850", 3 }, - { "WDC AC1270", 3 }, - { "WDC AC1170", 1 }, - { "WDC AC1210", 1 }, - { "WDC AC280", 0 }, -/* { "WDC AC21000", 4 }, */ - { "WDC AC31000", 3 }, - { "WDC AC31200", 3 }, -/* { "WDC AC31600", 4 }, */ - - { "Maxtor 7131 AT", 1 }, - { "Maxtor 7171 AT", 1 }, - { "Maxtor 7213 AT", 1 }, - { "Maxtor 7245 AT", 1 }, - { "Maxtor 7345 AT", 1 }, - { "Maxtor 7546 AT", 3 }, - { "Maxtor 7540 AV", 3 }, - - { "SAMSUNG SHD-3121A", 1 }, - { "SAMSUNG SHD-3122A", 1 }, - { "SAMSUNG SHD-3172A", 1 }, - -/* { "ST51080A", 4 }, - * { "ST51270A", 4 }, - * { "ST31220A", 4 }, - * { "ST31640A", 4 }, - * { "ST32140A", 4 }, - * { "ST3780A", 4 }, - */ - { "ST5660A", 3 }, - { "ST3660A", 3 }, - { "ST3630A", 3 }, - { "ST3655A", 3 }, - { "ST3391A", 3 }, - { "ST3390A", 1 }, - { "ST3600A", 1 }, - { "ST3290A", 0 }, - { "ST3144A", 0 }, - { "ST3491A", 1 }, /* reports 3, should be 1 or 2 (depending on */ - /* drive) according to Seagates FIND-ATA program */ - - { "QUANTUM ELS127A", 0 }, - { "QUANTUM ELS170A", 0 }, - { "QUANTUM LPS240A", 0 }, - { "QUANTUM LPS210A", 3 }, - { "QUANTUM LPS270A", 3 }, - { "QUANTUM LPS365A", 3 }, - { "QUANTUM LPS540A", 3 }, - { "QUANTUM LIGHTNING 540A", 3 }, - { "QUANTUM LIGHTNING 730A", 3 }, - - { "QUANTUM FIREBALL_540", 3 }, /* Older Quantum Fireballs don't work */ - { "QUANTUM FIREBALL_640", 3 }, - { "QUANTUM FIREBALL_1080", 3 }, - { "QUANTUM FIREBALL_1280", 3 }, - { NULL, 0 } -}; - -/* - * This routine searches the ide_pio_blacklist for an entry - * matching the start/whole of the supplied model name. - * - * Returns -1 if no match found. - * Otherwise returns the recommended PIO mode from ide_pio_blacklist[]. - */ -int ide_scan_pio_blacklist (char *model) -{ - struct ide_pio_info *p; - - for (p = ide_pio_blacklist; p->name != NULL; p++) { - if (strncmp(p->name, model, strlen(p->name)) == 0) - return p->pio; - } - return -1; -} - -/* - * This routine returns the recommended PIO settings for a given drive, - * based on the drive->id information and the ide_pio_blacklist[]. - * This is used by most chipset support modules when "auto-tuning". - */ - -/* - * Drive PIO mode auto selection - */ -byte ide_get_best_pio_mode (ide_drive_t *drive, byte mode_wanted, byte max_mode, ide_pio_data_t *d) -{ - int pio_mode; - int cycle_time = 0; - int use_iordy = 0; - struct hd_driveid* id = drive->id; - int overridden = 0; - int blacklisted = 0; - - if (mode_wanted != 255) { - pio_mode = mode_wanted; - } else if (!drive->id) { - pio_mode = 0; - } else if ((pio_mode = ide_scan_pio_blacklist(id->model)) != -1) { - overridden = 1; - blacklisted = 1; - use_iordy = (pio_mode > 2); - } else { - pio_mode = id->tPIO; - if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ - pio_mode = 2; - overridden = 1; - } - if (id->field_valid & 2) { /* drive implements ATA2? */ - if (id->capability & 8) { /* drive supports use_iordy? */ - use_iordy = 1; - cycle_time = id->eide_pio_iordy; - if (id->eide_pio_modes & 7) { - overridden = 0; - if (id->eide_pio_modes & 4) - pio_mode = 5; - else if (id->eide_pio_modes & 2) - pio_mode = 4; - else - pio_mode = 3; - } - } else { - cycle_time = id->eide_pio; - } - } - -#if 0 - if (drive->id->major_rev_num & 0x0004) printk("ATA-2 "); -#endif - - /* - * Conservative "downgrade" for all pre-ATA2 drives - */ - if (pio_mode && pio_mode < 4) { - pio_mode--; - overridden = 1; -#if 0 - use_iordy = (pio_mode > 2); -#endif - if (cycle_time && cycle_time < ide_pio_timings[pio_mode].cycle_time) - cycle_time = 0; /* use standard timing */ - } - } - if (pio_mode > max_mode) { - pio_mode = max_mode; - cycle_time = 0; - } - if (d) { - d->pio_mode = pio_mode; - d->cycle_time = cycle_time ? cycle_time : ide_pio_timings[pio_mode].cycle_time; - d->use_iordy = use_iordy; - d->overridden = overridden; - d->blacklisted = blacklisted; - } - return pio_mode; -} - -#endif /* _IDE_C */ -#endif /* CONFIG_BLK_DEV_IDE_MODES */ -#endif /* _IDE_MODES_H */ diff --git a/xen/drivers/ide/piix.c b/xen/drivers/ide/piix.c deleted file mode 100644 index e68deef9ba..0000000000 --- a/xen/drivers/ide/piix.c +++ /dev/null @@ -1,542 +0,0 @@ -/* - * linux/drivers/ide/piix.c Version 0.32 June 9, 2000 - * - * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer - * Copyright (C) 1998-2000 Andre Hedrick - * May be copied or modified under the terms of the GNU General Public License - * - * PIO mode setting function for Intel chipsets. - * For use instead of BIOS settings. - * - * 40-41 - * 42-43 - * - * 41 - * 43 - * - * | PIO 0 | c0 | 80 | 0 | piix_tune_drive(drive, 0); - * | PIO 2 | SW2 | d0 | 90 | 4 | piix_tune_drive(drive, 2); - * | PIO 3 | MW1 | e1 | a1 | 9 | piix_tune_drive(drive, 3); - * | PIO 4 | MW2 | e3 | a3 | b | piix_tune_drive(drive, 4); - * - * sitre = word40 & 0x4000; primary - * sitre = word42 & 0x4000; secondary - * - * 44 8421|8421 hdd|hdb - * - * 48 8421 hdd|hdc|hdb|hda udma enabled - * - * 0001 hda - * 0010 hdb - * 0100 hdc - * 1000 hdd - * - * 4a 84|21 hdb|hda - * 4b 84|21 hdd|hdc - * - * ata-33/82371AB - * ata-33/82371EB - * ata-33/82801AB ata-66/82801AA - * 00|00 udma 0 00|00 reserved - * 01|01 udma 1 01|01 udma 3 - * 10|10 udma 2 10|10 udma 4 - * 11|11 reserved 11|11 reserved - * - * 54 8421|8421 ata66 drive|ata66 enable - * - * pci_read_config_word(HWIF(drive)->pci_dev, 0x40, ®40); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, ®42); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, ®44); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x48, ®48); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, ®4a); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x54, ®54); - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ide_modes.h" - -#define PIIX_DEBUG_DRIVE_INFO 0 - -#define DISPLAY_PIIX_TIMINGS - -#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int piix_get_info(char *, char **, off_t, int); -extern int (*piix_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; - -static int piix_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); - u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0; - u8 c0 = 0, c1 = 0; - u8 reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0, reg54 = 0, reg55 = 0; - - switch(bmide_dev->device) { - case PCI_DEVICE_ID_INTEL_82801BA_8: - case PCI_DEVICE_ID_INTEL_82801BA_9: - case PCI_DEVICE_ID_INTEL_82801CA_10: - case PCI_DEVICE_ID_INTEL_82801CA_11: - case PCI_DEVICE_ID_INTEL_82801DB_11: - case PCI_DEVICE_ID_INTEL_82801E_11: - p += sprintf(p, "\n Intel PIIX4 Ultra 100 Chipset.\n"); - break; - case PCI_DEVICE_ID_INTEL_82372FB_1: - case PCI_DEVICE_ID_INTEL_82801AA_1: - p += sprintf(p, "\n Intel PIIX4 Ultra 66 Chipset.\n"); - break; - case PCI_DEVICE_ID_INTEL_82451NX: - case PCI_DEVICE_ID_INTEL_82801AB_1: - case PCI_DEVICE_ID_INTEL_82443MX_1: - case PCI_DEVICE_ID_INTEL_82371AB: - p += sprintf(p, "\n Intel PIIX4 Ultra 33 Chipset.\n"); - break; - case PCI_DEVICE_ID_INTEL_82371SB_1: - p += sprintf(p, "\n Intel PIIX3 Chipset.\n"); - break; - case PCI_DEVICE_ID_INTEL_82371MX: - p += sprintf(p, "\n Intel MPIIX Chipset.\n"); - return p-buffer; /* => must be less than 4k! */ - case PCI_DEVICE_ID_INTEL_82371FB_1: - case PCI_DEVICE_ID_INTEL_82371FB_0: - default: - p += sprintf(p, "\n Intel PIIX Chipset.\n"); - break; - } - - pci_read_config_word(bmide_dev, 0x40, ®40); - pci_read_config_word(bmide_dev, 0x42, ®42); - pci_read_config_byte(bmide_dev, 0x44, ®44); - pci_read_config_byte(bmide_dev, 0x48, ®48); - pci_read_config_byte(bmide_dev, 0x4a, ®4a); - pci_read_config_byte(bmide_dev, 0x4b, ®4b); - pci_read_config_byte(bmide_dev, 0x54, ®54); - pci_read_config_byte(bmide_dev, 0x55, ®55); - - psitre = (reg40 & 0x4000) ? 1 : 0; - ssitre = (reg42 & 0x4000) ? 1 : 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "yes" : "no ", - (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", - (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s %s %s\n", - (reg48&0x01) ? "yes" : "no ", - (reg48&0x02) ? "yes" : "no ", - (reg48&0x04) ? "yes" : "no ", - (reg48&0x08) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s %s %s\n", - ((reg54&0x11) && (reg55&0x10) && (reg4a&0x01)) ? "5" : - ((reg54&0x11) && (reg4a&0x02)) ? "4" : - ((reg54&0x11) && (reg4a&0x01)) ? "3" : - (reg4a&0x02) ? "2" : - (reg4a&0x01) ? "1" : - (reg4a&0x00) ? "0" : "X", - ((reg54&0x22) && (reg55&0x20) && (reg4a&0x10)) ? "5" : - ((reg54&0x22) && (reg4a&0x20)) ? "4" : - ((reg54&0x22) && (reg4a&0x10)) ? "3" : - (reg4a&0x20) ? "2" : - (reg4a&0x10) ? "1" : - (reg4a&0x00) ? "0" : "X", - ((reg54&0x44) && (reg55&0x40) && (reg4b&0x03)) ? "5" : - ((reg54&0x44) && (reg4b&0x02)) ? "4" : - ((reg54&0x44) && (reg4b&0x01)) ? "3" : - (reg4b&0x02) ? "2" : - (reg4b&0x01) ? "1" : - (reg4b&0x00) ? "0" : "X", - ((reg54&0x88) && (reg55&0x80) && (reg4b&0x30)) ? "5" : - ((reg54&0x88) && (reg4b&0x20)) ? "4" : - ((reg54&0x88) && (reg4b&0x10)) ? "3" : - (reg4b&0x20) ? "2" : - (reg4b&0x10) ? "1" : - (reg4b&0x00) ? "0" : "X"); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - -/* - * FIXME.... Add configuration junk data....blah blah...... - */ - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */ - -/* - * Used to set Fifo configuration via kernel command line: - */ - -byte piix_proc = 0; - -extern char *ide_xfer_verbose (byte xfer_rate); - -#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_PIIX_TUNING) -/* - * - */ -static byte piix_dma_2_pio (byte xfer_rate) { - switch(xfer_rate) { - case XFER_UDMA_5: - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - case XFER_MW_DMA_2: - case XFER_PIO_4: - return 4; - case XFER_MW_DMA_1: - case XFER_PIO_3: - return 3; - case XFER_SW_DMA_2: - case XFER_PIO_2: - return 2; - case XFER_MW_DMA_0: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: - case XFER_PIO_1: - case XFER_PIO_0: - case XFER_PIO_SLOW: - default: - return 0; - } -} -#endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_PIIX_TUNING) */ - -/* - * Based on settings done by AMI BIOS - * (might be useful if drive is not registered in CMOS for any reason). - */ -static void piix_tune_drive (ide_drive_t *drive, byte pio) -{ - unsigned long flags; - u16 master_data; - byte slave_data; - int is_slave = (&HWIF(drive)->drives[1] == drive); - int master_port = HWIF(drive)->index ? 0x42 : 0x40; - int slave_port = 0x44; - /* ISP RTC */ - byte timings[][2] = { { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; - - pio = ide_get_best_pio_mode(drive, pio, 5, NULL); - pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data); - if (is_slave) { - master_data = master_data | 0x4000; - if (pio > 1) - /* enable PPE, IE and TIME */ - master_data = master_data | 0x0070; - pci_read_config_byte(HWIF(drive)->pci_dev, slave_port, &slave_data); - slave_data = slave_data & (HWIF(drive)->index ? 0x0f : 0xf0); - slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) - << (HWIF(drive)->index ? 4 : 0)); - } else { - master_data = master_data & 0xccf8; - if (pio > 1) - /* enable PPE, IE and TIME */ - master_data = master_data | 0x0007; - master_data = master_data | (timings[pio][0] << 12) | - (timings[pio][1] << 8); - } - save_flags(flags); - cli(); - pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data); - if (is_slave) - pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data); - restore_flags(flags); -} - -#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_PIIX_TUNING) -static int piix_tune_chipset (ide_drive_t *drive, byte speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - byte maslave = hwif->channel ? 0x42 : 0x40; - int a_speed = 3 << (drive->dn * 4); - int u_flag = 1 << drive->dn; - int v_flag = 0x01 << drive->dn; - int w_flag = 0x10 << drive->dn; - int u_speed = 0; - int err = 0; - int sitre; - short reg4042, reg44, reg48, reg4a, reg54; - byte reg55; - - pci_read_config_word(dev, maslave, ®4042); - sitre = (reg4042 & 0x4000) ? 1 : 0; - pci_read_config_word(dev, 0x44, ®44); - pci_read_config_word(dev, 0x48, ®48); - pci_read_config_word(dev, 0x4a, ®4a); - pci_read_config_word(dev, 0x54, ®54); - pci_read_config_byte(dev, 0x55, ®55); - - switch(speed) { - case XFER_UDMA_4: - case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; - case XFER_UDMA_5: - case XFER_UDMA_3: - case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break; - case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_SW_DMA_2: break; - default: return -1; - } - - if (speed >= XFER_UDMA_0) { - if (!(reg48 & u_flag)) - pci_write_config_word(dev, 0x48, reg48|u_flag); - if (speed == XFER_UDMA_5) { - pci_write_config_byte(dev, 0x55, (byte) reg55|w_flag); - } else { - pci_write_config_byte(dev, 0x55, (byte) reg55 & ~w_flag); - } - if (!(reg4a & u_speed)) { - pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - pci_write_config_word(dev, 0x4a, reg4a|u_speed); - } - if (speed > XFER_UDMA_2) { - if (!(reg54 & v_flag)) { - pci_write_config_word(dev, 0x54, reg54|v_flag); - } - } else { - pci_write_config_word(dev, 0x54, reg54 & ~v_flag); - } - } - if (speed < XFER_UDMA_0) { - if (reg48 & u_flag) - pci_write_config_word(dev, 0x48, reg48 & ~u_flag); - if (reg4a & a_speed) - pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - if (reg54 & v_flag) - pci_write_config_word(dev, 0x54, reg54 & ~v_flag); - if (reg55 & w_flag) - pci_write_config_byte(dev, 0x55, (byte) reg55 & ~w_flag); - } - - piix_tune_drive(drive, piix_dma_2_pio(speed)); - -#if PIIX_DEBUG_DRIVE_INFO - printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn); -#endif /* PIIX_DEBUG_DRIVE_INFO */ - if (!drive->init_speed) - drive->init_speed = speed; - err = ide_config_drive_speed(drive, speed); - drive->current_speed = speed; - return err; -} - -static int piix_config_drive_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - byte speed; - - byte udma_66 = eighty_ninty_three(drive); - int ultra100 = ((dev->device == PCI_DEVICE_ID_INTEL_82801BA_8) || - (dev->device == PCI_DEVICE_ID_INTEL_82801BA_9) || - (dev->device == PCI_DEVICE_ID_INTEL_82801CA_10) || - (dev->device == PCI_DEVICE_ID_INTEL_82801CA_11) || - (dev->device == PCI_DEVICE_ID_INTEL_82801DB_11) || - (dev->device == PCI_DEVICE_ID_INTEL_82801E_11)) ? 1 : 0; - int ultra66 = ((ultra100) || - (dev->device == PCI_DEVICE_ID_INTEL_82801AA_1) || - (dev->device == PCI_DEVICE_ID_INTEL_82372FB_1)) ? 1 : 0; - int ultra = ((ultra66) || - (dev->device == PCI_DEVICE_ID_INTEL_82371AB) || - (dev->device == PCI_DEVICE_ID_INTEL_82443MX_1) || - (dev->device == PCI_DEVICE_ID_INTEL_82451NX) || - (dev->device == PCI_DEVICE_ID_INTEL_82801AB_1)) ? 1 : 0; - - if ((id->dma_ultra & 0x0020) && (udma_66) && (ultra100)) { - speed = XFER_UDMA_5; - } else if ((id->dma_ultra & 0x0010) && (ultra)) { - speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0008) && (ultra)) { - speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0004) && (ultra)) { - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && (ultra)) { - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && (ultra)) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else { - speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); - } - - (void) piix_tune_chipset(drive, speed); - - return ((int) ((id->dma_ultra >> 11) & 7) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -} - -static void config_chipset_for_pio (ide_drive_t *drive) -{ - piix_tune_drive(drive, ide_get_best_pio_mode(drive, 255, 5, NULL)); -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_dma_action_t dma_func = ide_dma_on; - - if (id && (id->capability & 1) && HWIF(drive)->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x003F) { - /* Force if Capable UltraDMA */ - dma_func = piix_config_drive_for_dma(drive); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x007)) { - /* Force if Capable regular DMA modes */ - dma_func = piix_config_drive_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = piix_config_drive_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - config_chipset_for_pio(drive); - } - return HWIF(drive)->dmaproc(dma_func, drive); -} - -static int piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - default : - break; - } - /* Other cases are done by generic IDE-DMA code. */ - return ide_dmaproc(func, drive); -} -#endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_PIIX_TUNING) */ - -unsigned int __init pci_init_piix (struct pci_dev *dev, const char *name) -{ -#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) - if (!piix_proc) { - piix_proc = 1; - bmide_dev = dev; - piix_display_info = &piix_get_info; - } -#endif /* DISPLAY_PIIX_TIMINGS && CONFIG_PROC_FS */ - return 0; -} - -/* - * Sheesh, someone at Intel needs to go read the ATA-4/5 T13 standards. - * It does not specify device detection, but channel!!! - * You determine later if bit 13 of word93 is set... - */ -unsigned int __init ata66_piix (ide_hwif_t *hwif) -{ - byte reg54h = 0, reg55h = 0, ata66 = 0; - byte mask = hwif->channel ? 0xc0 : 0x30; - - pci_read_config_byte(hwif->pci_dev, 0x54, ®54h); - pci_read_config_byte(hwif->pci_dev, 0x55, ®55h); - - ata66 = (reg54h & mask) ? 1 : 0; - - return ata66; -} - -void __init ide_init_piix (ide_hwif_t *hwif) -{ -#ifndef CONFIG_IA64 - if (!hwif->irq) - hwif->irq = hwif->channel ? 15 : 14; -#endif /* CONFIG_IA64 */ - - if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_82371MX) { - /* This is a painful system best to let it self tune for now */ - return; - } - - hwif->tuneproc = &piix_tune_drive; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - - if (!hwif->dma_base) - return; - -#ifndef CONFIG_BLK_DEV_IDEDMA - hwif->autodma = 0; -#else /* CONFIG_BLK_DEV_IDEDMA */ -#ifdef CONFIG_PIIX_TUNING - if (!noautodma) - hwif->autodma = 1; - hwif->dmaproc = &piix_dmaproc; - hwif->speedproc = &piix_tune_chipset; -#endif /* CONFIG_PIIX_TUNING */ -#endif /* !CONFIG_BLK_DEV_IDEDMA */ -} diff --git a/xen/drivers/message/fusion/Config.in b/xen/drivers/message/fusion/Config.in deleted file mode 100644 index 39274207f6..0000000000 --- a/xen/drivers/message/fusion/Config.in +++ /dev/null @@ -1,38 +0,0 @@ -mainmenu_option next_comment -comment 'Fusion MPT device support' - -dep_tristate "Fusion MPT (base + ScsiHost) drivers" CONFIG_FUSION $CONFIG_SCSI $CONFIG_BLK_DEV_SD - -if [ "$CONFIG_FUSION" = "y" -o "$CONFIG_FUSION" = "m" ]; then - - if [ "$CONFIG_BLK_DEV_SD" = "y" -a "$CONFIG_FUSION" = "y" ]; then - define_bool CONFIG_FUSION_BOOT y - else - define_bool CONFIG_FUSION_BOOT n - fi - int " Maximum number of scatter gather entries" CONFIG_FUSION_MAX_SGE 40 - - if [ "$CONFIG_MODULES" = "y" ]; then - # How can we force these options to module or nothing? - dep_tristate " Enhanced SCSI error reporting" CONFIG_FUSION_ISENSE $CONFIG_FUSION m - dep_tristate " Fusion MPT misc device (ioctl) driver" CONFIG_FUSION_CTL $CONFIG_FUSION m - fi - - dep_tristate " Fusion MPT LAN driver" CONFIG_FUSION_LAN $CONFIG_FUSION $CONFIG_NET - if [ "$CONFIG_FUSION_LAN" != "n" ]; then - define_bool CONFIG_NET_FC y - fi - -else - - define_bool CONFIG_FUSION_BOOT n - # These be define_tristate, but we leave them define_bool - # for backward compatibility with pre-linux-2.2.15 kernels. - # (Bugzilla:fibrebugs, #384) - define_bool CONFIG_FUSION_ISENSE n - define_bool CONFIG_FUSION_CTL n - define_bool CONFIG_FUSION_LAN n - -fi - -endmenu diff --git a/xen/drivers/message/fusion/Makefile b/xen/drivers/message/fusion/Makefile deleted file mode 100644 index 3e30f33875..0000000000 --- a/xen/drivers/message/fusion/Makefile +++ /dev/null @@ -1,11 +0,0 @@ - -include $(BASEDIR)/Rules.mk - -# naive OBJS rule gets link order wrong -FUSIONOBJS := mptbase.o mptscsih.o - -default: $(OBJS) - $(LD) -r -o driver.o $(FUSIONOBJS) - -clean: - rm -f *.o *~ core diff --git a/xen/drivers/message/fusion/isense.h b/xen/drivers/message/fusion/isense.h deleted file mode 100644 index 07eae226c9..0000000000 --- a/xen/drivers/message/fusion/isense.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef ISENSE_H_INCLUDED -#define ISENSE_H_INCLUDED -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#ifdef __KERNEL__ -#include /* needed for u8, etc. */ -#include /* needed for strcat */ -#include /* needed for sprintf */ -#else - #ifndef U_STUFF_DEFINED - #define U_STUFF_DEFINED - typedef unsigned char u8; - typedef unsigned short u16; - typedef unsigned int u32; - #endif -#endif - -#include "scsi3.h" /* needed for all things SCSI */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Defines and typedefs... - */ - -#ifdef __KERNEL__ -#define PrintF(x) printk x -#else -#define PrintF(x) printf x -#endif - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -#define RETRY_STATUS ((int) 1) -#define PUT_STATUS ((int) 0) - -/* - * A generic structure to hold info about IO request that caused - * a Request Sense to be performed, and the resulting Sense Data. - */ -typedef struct IO_Info -{ - char *DevIDStr; /* String of chars which identifies the device. */ - u8 *cdbPtr; /* Pointer (Virtual/Logical addr) to CDB bytes of - IO request that caused ContAllegianceCond. */ - u8 *sensePtr; /* Pointer (Virtual/Logical addr) to Sense Data - returned by Request Sense operation. */ - u8 *dataPtr; /* Pointer (Virtual/Logical addr) to Data buffer - of IO request caused ContAllegianceCondition. */ - u8 *inqPtr; /* Pointer (Virtual/Logical addr) to Inquiry Data for - IO *Device* that caused ContAllegianceCondition. */ - u8 SCSIStatus; /* SCSI status byte of IO request that caused - Contingent Allegiance Condition. */ - u8 DoDisplay; /* Shall we display any messages? */ - u16 rsvd_align1; - u32 ComplCode; /* Four-byte OS-dependent completion code. */ - u32 NotifyL; /* Four-byte OS-dependent notification field. */ -} IO_Info_t; - -/* - * SCSI Additional Sense Code and Additional Sense Code Qualifier table. - */ -typedef struct ASCQ_Table -{ - u8 ASC; - u8 ASCQ; - char *DevTypes; - char *Description; -} ASCQ_Table_t; - -#if 0 -/* - * SCSI Opcodes table. - */ -typedef struct SCSI_OPS_Table -{ - u8 OpCode; - char *DevTypes; - char *ScsiCmndStr; -} SCSI_OPS_Table_t; -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Public entry point prototypes - */ - -/* in scsiherr.c, needed by mptscsih.c */ -extern int mpt_ScsiHost_ErrorReport(IO_Info_t *ioop); - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#endif - diff --git a/xen/drivers/message/fusion/linux_compat.h b/xen/drivers/message/fusion/linux_compat.h deleted file mode 100644 index 7662decb6a..0000000000 --- a/xen/drivers/message/fusion/linux_compat.h +++ /dev/null @@ -1,295 +0,0 @@ -/* drivers/message/fusion/linux_compat.h */ - -#ifndef FUSION_LINUX_COMPAT_H -#define FUSION_LINUX_COMPAT_H -/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#include -#include -#include -#include - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#ifndef rwlock_init -#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -#define SET_NICE(current,x) do {(current)->nice = (x);} while (0) -#else -#define SET_NICE(current,x) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -#define pci_enable_device(pdev) (0) -#define SCSI_DATA_UNKNOWN 0 -#define SCSI_DATA_WRITE 1 -#define SCSI_DATA_READ 2 -#define SCSI_DATA_NONE 3 -#endif - - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4) -#define pci_set_dma_mask(pdev, mask) (0) -#define scsi_set_pci_device(sh, pdev) (0) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -# if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) - typedef unsigned int dma_addr_t; -# endif -#else -# if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,42) - typedef unsigned int dma_addr_t; -# endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) -/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -/* This block snipped from lk-2.2.18/include/linux/init.h { */ -/* - * Used for initialization calls.. - */ -typedef int (*initcall_t)(void); -typedef void (*exitcall_t)(void); - -#define __init_call __attribute__ ((unused,__section__ (".initcall.init"))) -#define __exit_call __attribute__ ((unused,__section__ (".exitcall.exit"))) - -extern initcall_t __initcall_start, __initcall_end; - -#define __initcall(fn) \ - static initcall_t __initcall_##fn __init_call = fn -#define __exitcall(fn) \ - static exitcall_t __exitcall_##fn __exit_call = fn - -#ifdef MODULE -/* These macros create a dummy inline: gcc 2.9x does not count alias - as usage, hence the `unused function' warning when __init functions - are declared static. We use the dummy __*_module_inline functions - both to kill the warning and check the type of the init/cleanup - function. */ -typedef int (*__init_module_func_t)(void); -typedef void (*__cleanup_module_func_t)(void); -#define module_init(x) \ - int init_module(void) __attribute__((alias(#x))); \ - static inline __init_module_func_t __init_module_inline(void) \ - { return x; } -#define module_exit(x) \ - void cleanup_module(void) __attribute__((alias(#x))); \ - static inline __cleanup_module_func_t __cleanup_module_inline(void) \ - { return x; } - -#else -#define module_init(x) __initcall(x); -#define module_exit(x) __exitcall(x); -#endif -/* } block snipped from lk-2.2.18/include/linux/init.h */ - -/* This block snipped from lk-2.2.18/include/linux/sched.h { */ -/* - * Used prior to schedule_timeout calls.. - */ -#define __set_current_state(state_value) do { current->state = state_value; } while (0) -#ifdef __SMP__ -#define set_current_state(state_value) do { __set_current_state(state_value); mb(); } while (0) -#else -#define set_current_state(state_value) __set_current_state(state_value) -#endif -/* } block snipped from lk-2.2.18/include/linux/sched.h */ - -/* procfs compat stuff... */ -#define proc_mkdir(x,y) create_proc_entry(x, S_IFDIR, y) - -/* MUTEX compat stuff... */ -#define DECLARE_MUTEX(name) struct semaphore name=MUTEX -#define DECLARE_MUTEX_LOCKED(name) struct semaphore name=MUTEX_LOCKED -#define init_MUTEX(x) *(x)=MUTEX -#define init_MUTEX_LOCKED(x) *(x)=MUTEX_LOCKED - -/* Wait queues. */ -#define DECLARE_WAIT_QUEUE_HEAD(name) \ - struct wait_queue * (name) = NULL -#define DECLARE_WAITQUEUE(name, task) \ - struct wait_queue (name) = { (task), NULL } - -#if defined(__sparc__) && defined(__sparc_v9__) -/* The sparc64 ioremap implementation is wrong in 2.2.x, - * but fixing it would break all of the drivers which - * workaround it. Fixed in 2.3.x onward. -DaveM - */ -#define ARCH_IOREMAP(base) ((unsigned long) (base)) -#else -#define ARCH_IOREMAP(base) ioremap(base) -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#else /* LINUX_VERSION_CODE must be >= KERNEL_VERSION(2,2,18) */ - -/* No ioremap bugs in >2.3.x kernels. */ -#define ARCH_IOREMAP(base) ioremap(base) - -/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) */ - - -/* - * Inclined to use: - * #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) - * here, but MODULE_LICENSE defined in 2.4.9-6 and 2.4.9-13 - * breaks the rule:-( - */ -#ifndef MODULE_LICENSE -#define MODULE_LICENSE(license) -#endif - - -/* PCI/driver subsystem { */ -/* SAE: Why not just use Linux's PCI stuff */ -#if XEN_KILLED -/*#ifndef pci_for_each_dev*/ -#define pci_for_each_dev(dev) for((dev)=pci_devices; (dev)!=NULL; (dev)=(dev)->next) -#define pci_peek_next_dev(dev) ((dev)->next ? (dev)->next : NULL) -#define DEVICE_COUNT_RESOURCE 6 -#define PCI_BASEADDR_FLAGS(idx) base_address[idx] -#define PCI_BASEADDR_START(idx) base_address[idx] & ~0xFUL -/* - * We have to keep track of the original value using - * a temporary, and not by just sticking pdev->base_address[x] - * back. pdev->base_address[x] is an opaque cookie that can - * be used by the PCI implementation on a given Linux port - * for any purpose. -DaveM - */ -#define PCI_BASEADDR_SIZE(__pdev, __idx) \ -({ unsigned int size, tmp; \ - pci_read_config_dword(__pdev, PCI_BASE_ADDRESS_0 + (4*(__idx)), &tmp); \ - pci_write_config_dword(__pdev, PCI_BASE_ADDRESS_0 + (4*(__idx)), 0xffffffff); \ - pci_read_config_dword(__pdev, PCI_BASE_ADDRESS_0 + (4*(__idx)), &size); \ - pci_write_config_dword(__pdev, PCI_BASE_ADDRESS_0 + (4*(__idx)), tmp); \ - (4 - size); \ -}) -#else -/* SAE: Is Linux's PCI stuff not good enough? */ -#if XEN_KILLED - -#define pci_peek_next_dev(dev) ((dev) != pci_dev_g(&pci_devices) ? pci_dev_g((dev)->global_list.next) : NULL) -#define PCI_BASEADDR_FLAGS(idx) resource[idx].flags -#define PCI_BASEADDR_START(idx) resource[idx].start -#define PCI_BASEADDR_SIZE(dev,idx) (dev)->resource[idx].end - (dev)->resource[idx].start + 1 - -#endif -#endif /* } ifndef pci_for_each_dev */ - - -/* Compatability for the 2.3.x PCI DMA API. */ -/* SAE: No need for this */ -#if XEN_KILLED -/*#ifndef PCI_DMA_BIDIRECTIONAL*/ -/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#define PCI_DMA_BIDIRECTIONAL 0 -#define PCI_DMA_TODEVICE 1 -#define PCI_DMA_FROMDEVICE 2 -#define PCI_DMA_NONE 3 - -#ifdef __KERNEL__ -#include -/* Pure 2^n version of get_order */ -static __inline__ int __get_order(unsigned long size) -{ - int order; - - size = (size-1) >> (PAGE_SHIFT-1); - order = -1; - do { - size >>= 1; - order++; - } while (size); - return order; -} -#endif - -#define pci_alloc_consistent(hwdev, size, dma_handle) \ -({ void *__ret = (void *)__get_free_pages(GFP_ATOMIC, __get_order(size)); \ - if (__ret != NULL) { \ - memset(__ret, 0, size); \ - *(dma_handle) = virt_to_bus(__ret); \ - } \ - __ret; \ -}) - -#define pci_free_consistent(hwdev, size, vaddr, dma_handle) \ - free_pages((unsigned long)vaddr, __get_order(size)) - -#define pci_map_single(hwdev, ptr, size, direction) \ - virt_to_bus(ptr); - -#define pci_unmap_single(hwdev, dma_addr, size, direction) \ - do { /* Nothing to do */ } while (0) - -#define pci_map_sg(hwdev, sg, nents, direction) (nents) -#define pci_unmap_sg(hwdev, sg, nents, direction) \ - do { /* Nothing to do */ } while(0) - -#define sg_dma_address(sg) (virt_to_bus((sg)->address)) -#define sg_dma_len(sg) ((sg)->length) - -/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#endif /* PCI_DMA_BIDIRECTIONAL */ - -/* - * With the new command queuing code in the SCSI mid-layer we no longer have - * to hold the io_request_lock spin lock when calling the scsi_done routine. - * For now we only do this with the 2.5.1 kernel or newer. - */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) - #define MPT_HOST_LOCK(flags) - #define MPT_HOST_UNLOCK(flags) -#else - #define MPT_HOST_LOCK(flags) \ - spin_lock_irqsave(&io_request_lock, flags) - #define MPT_HOST_UNLOCK(flags) \ - spin_unlock_irqrestore(&io_request_lock, flags) -#endif - -/* - * We use our new error handling code if the kernel version is 2.4.18 or newer. - * Remark: 5/5/03 use old EH code with 2.4 kernels as it runs in a background thread - * 2.4 kernels choke on a call to schedule via eh thread. - */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) - #define MPT_SCSI_USE_NEW_EH -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,41) -#define mpt_work_struct work_struct -#define MPT_INIT_WORK(_task, _func, _data) INIT_WORK(_task, _func, _data) -#else -#define mpt_work_struct tq_struct -#define MPT_INIT_WORK(_task, _func, _data) \ -({ (_task)->sync = 0; \ - (_task)->routine = (_func); \ - (_task)->data = (void *) (_data); \ -}) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28) -#define mptscsih_sync_irq(_irq) synchronize_irq(_irq) -#else -#define mptscsih_sync_irq(_irq) synchronize_irq() -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,58) -#define mpt_inc_use_count() -#define mpt_dec_use_count() -#else -#define mpt_inc_use_count() MOD_INC_USE_COUNT -#define mpt_dec_use_count() MOD_DEC_USE_COUNT -#endif - - -/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#endif /* _LINUX_COMPAT_H */ - diff --git a/xen/drivers/message/fusion/lsi/fc_log.h b/xen/drivers/message/fusion/lsi/fc_log.h deleted file mode 100644 index dc98d46f90..0000000000 --- a/xen/drivers/message/fusion/lsi/fc_log.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2000-2001 LSI Logic Corporation. All rights reserved. - * - * NAME: fc_log.h - * SUMMARY: MPI IocLogInfo definitions for the SYMFC9xx chips - * DESCRIPTION: Contains the enumerated list of values that may be returned - * in the IOCLogInfo field of a MPI Default Reply Message. - * - * CREATION DATE: 6/02/2000 - * ID: $Id: fc_log.h,v 4.6 2001/07/26 14:41:33 sschremm Exp $ - */ - - -/* - * MpiIocLogInfo_t enum - * - * These 32 bit values are used in the IOCLogInfo field of the MPI reply - * messages. - * The value is 0xabcccccc where - * a = The type of log info as per the MPI spec. Since these codes are - * all for Fibre Channel this value will always be 2. - * b = Specifies a subclass of the firmware where - * 0 = FCP Initiator - * 1 = FCP Target - * 2 = LAN - * 3 = MPI Message Layer - * 4 = FC Link - * 5 = Context Manager - * 6 = Invalid Field Offset - * 7 = State Change Info - * all others are reserved for future use - * c = A specific value within the subclass. - * - * NOTE: Any new values should be added to the end of each subclass so that the - * codes remain consistent across firmware releases. - */ -typedef enum _MpiIocLogInfoFc -{ - MPI_IOCLOGINFO_FC_INIT_BASE = 0x20000000, - MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME = 0x20000001, /* received an out of order frame - unsupported */ - MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primative */ - MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME = 0x20000003, /* Bad Rx Frame, bad end of frame primative */ - MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN = 0x20000004, /* Bad Rx Frame, overrun */ - MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER = 0x20000005, /* Other errors caught by IOC which require retries */ - MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD = 0x20000006, /* Main processor could not initialize sub-processor */ - MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OVERRUN = 0x20000007, /* Scatter Gather overrun */ - MPI_IOCLOGINFO_FC_INIT_ERROR_RX_BAD_STATUS = 0x20000008, /* Receiver detected context mismatch via invalid header */ - MPI_IOCLOGINFO_FC_INIT_ERROR_RX_UNEXPECTED_FRAME= 0x20000009, /* CtxMgr detected unsupported frame type */ - MPI_IOCLOGINFO_FC_INIT_ERROR_LINK_FAILURE = 0x2000000A, /* Link failure occurred */ - MPI_IOCLOGINFO_FC_INIT_ERROR_TX_TIMEOUT = 0x2000000B, /* Transmitter timeout error */ - - MPI_IOCLOGINFO_FC_TARGET_BASE = 0x21000000, - MPI_IOCLOGINFO_FC_TARGET_NO_PDISC = 0x21000001, /* not sent because we are waiting for a PDISC from the initiator */ - MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN = 0x21000002, /* not sent because we are not logged in to the remote node */ - MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP = 0x21000003, /* Data Out, Auto Response, not sent due to a LIP */ - MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP = 0x21000004, /* Data In, Auto Response, not sent due to a LIP */ - MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA = 0x21000005, /* Data In, Auto Response, missing data frames */ - MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP = 0x21000006, /* Data Out, No Response, not sent due to a LIP */ - MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP = 0x21000007, /* Auto-response after a write not sent due to a LIP */ - MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP = 0x21000008, /* Data In, No Response, not completed due to a LIP */ - MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA = 0x21000009, /* Data In, No Response, missing data frames */ - MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP = 0x2100000a, /* Manual Response not sent due to a LIP */ - MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3 = 0x2100000b, /* not sent because remote node does not support Class 3 */ - MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID = 0x2100000c, /* not sent because login to remote node not validated */ - MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND = 0x2100000e, /* cleared from the outbound queue after a logout */ - MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN = 0x2100000f, /* cleared waiting for data after a logout */ - - MPI_IOCLOGINFO_FC_LAN_BASE = 0x22000000, - MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING = 0x22000001, /* Transaction Context Sgl Missing */ - MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE = 0x22000002, /* Transaction Context found before an EOB */ - MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET = 0x22000003, /* Transaction Context value has reserved bits set */ - MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG = 0x22000004, /* Invalid SGL Flags */ - - MPI_IOCLOGINFO_FC_MSG_BASE = 0x23000000, - - MPI_IOCLOGINFO_FC_LINK_BASE = 0x24000000, - MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT = 0x24000001, /* Loop initialization timed out */ - MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED = 0x24000002, /* Another system controller already initialized the loop */ - MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED = 0x24000003, /* Not synchronized to signal or still negotiating (possible cable problem) */ - MPI_IOCLOGINFO_FC_LINK_CRC_ERROR = 0x24000004, /* CRC check detected error on received frame */ - - MPI_IOCLOGINFO_FC_CTX_BASE = 0x25000000, - - MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET = 0x26000000, /* The lower 24 bits give the byte offset of the field in the request message that is invalid */ - MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET = 0x26ffffff, - - MPI_IOCLOGINFO_FC_STATE_CHANGE = 0x27000000 /* The lower 24 bits give additional information concerning state change */ - -} MpiIocLogInfoFc_t; diff --git a/xen/drivers/message/fusion/lsi/mpi.h b/xen/drivers/message/fusion/lsi/mpi.h deleted file mode 100644 index 0a43905a73..0000000000 --- a/xen/drivers/message/fusion/lsi/mpi.h +++ /dev/null @@ -1,678 +0,0 @@ -/* - * Copyright (c) 2000-2002 LSI Logic Corporation. - * - * - * Name: MPI.H - * Title: MPI Message independent structures and definitions - * Creation Date: July 27, 2000 - * - * MPI.H Version: 01.02.07 - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. - * 05-24-00 00.10.02 Added MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH definition. - * 06-06-00 01.00.01 Update MPI_VERSION_MAJOR and MPI_VERSION_MINOR. - * 06-22-00 01.00.02 Added MPI_IOCSTATUS_LAN_ definitions. - * Removed LAN_SUSPEND function definition. - * Added MPI_MSGFLAGS_CONTINUATION_REPLY definition. - * 06-30-00 01.00.03 Added MPI_CONTEXT_REPLY_TYPE_LAN definition. - * Added MPI_GET/SET_CONTEXT_REPLY_TYPE macros. - * 07-27-00 01.00.04 Added MPI_FAULT_ definitions. - * Removed MPI_IOCSTATUS_MSG/DATA_XFER_ERROR definitions. - * Added MPI_IOCSTATUS_INTERNAL_ERROR definition. - * Added MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH. - * 11-02-00 01.01.01 Original release for post 1.0 work. - * 12-04-00 01.01.02 Added new function codes. - * 01-09-01 01.01.03 Added more definitions to the system interface section - * Added MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT. - * 01-25-01 01.01.04 Changed MPI_VERSION_MINOR from 0x00 to 0x01. - * 02-20-01 01.01.05 Started using MPI_POINTER. - * Fixed value for MPI_DIAG_RW_ENABLE. - * Added defines for MPI_DIAG_PREVENT_IOC_BOOT and - * MPI_DIAG_CLEAR_FLASH_BAD_SIG. - * Obsoleted MPI_IOCSTATUS_TARGET_FC_ defines. - * 02-27-01 01.01.06 Removed MPI_HOST_INDEX_REGISTER define. - * Added function codes for RAID. - * 04-09-01 01.01.07 Added alternate define for MPI_DOORBELL_ACTIVE, - * MPI_DOORBELL_USED, to better match the spec. - * 08-08-01 01.02.01 Original release for v1.2 work. - * Changed MPI_VERSION_MINOR from 0x01 to 0x02. - * Added define MPI_FUNCTION_TOOLBOX. - * 09-28-01 01.02.02 New function code MPI_SCSI_ENCLOSURE_PROCESSOR. - * 11-01-01 01.02.03 Changed name to MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR. - * 03-14-02 01.02.04 Added MPI_HEADER_VERSION_ defines. - * 05-31-02 01.02.05 Bumped MPI_HEADER_VERSION_UNIT. - * 07-12-02 01.02.06 Added define for MPI_FUNCTION_MAILBOX. - * 09-16-02 01.02.07 Bumped value for MPI_HEADER_VERSION_UNIT. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI_H -#define MPI_H - - -/***************************************************************************** -* -* M P I V e r s i o n D e f i n i t i o n s -* -*****************************************************************************/ - -#define MPI_VERSION_MAJOR (0x01) -#define MPI_VERSION_MINOR (0x02) -#define MPI_VERSION_MAJOR_MASK (0xFF00) -#define MPI_VERSION_MAJOR_SHIFT (8) -#define MPI_VERSION_MINOR_MASK (0x00FF) -#define MPI_VERSION_MINOR_SHIFT (0) -#define MPI_VERSION ((MPI_VERSION_MAJOR << MPI_VERSION_MAJOR_SHIFT) | \ - MPI_VERSION_MINOR) - -#define MPI_VERSION_01_00 (0x0100) -#define MPI_VERSION_01_01 (0x0101) -#define MPI_VERSION_01_02 (0x0102) -/* Note: The major versions of 0xe0 through 0xff are reserved */ - -/* versioning for this MPI header set */ -#define MPI_HEADER_VERSION_UNIT (0x09) -#define MPI_HEADER_VERSION_DEV (0x00) -#define MPI_HEADER_VERSION_UNIT_MASK (0xFF00) -#define MPI_HEADER_VERSION_UNIT_SHIFT (8) -#define MPI_HEADER_VERSION_DEV_MASK (0x00FF) -#define MPI_HEADER_VERSION_DEV_SHIFT (0) -#define MPI_HEADER_VERSION ((MPI_HEADER_VERSION_UNIT << 8) | MPI_HEADER_VERSION_DEV) - -/***************************************************************************** -* -* I O C S t a t e D e f i n i t i o n s -* -*****************************************************************************/ - -#define MPI_IOC_STATE_RESET (0x00000000) -#define MPI_IOC_STATE_READY (0x10000000) -#define MPI_IOC_STATE_OPERATIONAL (0x20000000) -#define MPI_IOC_STATE_FAULT (0x40000000) - -#define MPI_IOC_STATE_MASK (0xF0000000) -#define MPI_IOC_STATE_SHIFT (28) - -/* Fault state codes (product independent range 0x8000-0xFFFF) */ - -#define MPI_FAULT_REQUEST_MESSAGE_PCI_PARITY_ERROR (0x8111) -#define MPI_FAULT_REQUEST_MESSAGE_PCI_BUS_FAULT (0x8112) -#define MPI_FAULT_REPLY_MESSAGE_PCI_PARITY_ERROR (0x8113) -#define MPI_FAULT_REPLY_MESSAGE_PCI_BUS_FAULT (0x8114) -#define MPI_FAULT_DATA_SEND_PCI_PARITY_ERROR (0x8115) -#define MPI_FAULT_DATA_SEND_PCI_BUS_FAULT (0x8116) -#define MPI_FAULT_DATA_RECEIVE_PCI_PARITY_ERROR (0x8117) -#define MPI_FAULT_DATA_RECEIVE_PCI_BUS_FAULT (0x8118) - - -/***************************************************************************** -* -* P C I S y s t e m I n t e r f a c e R e g i s t e r s -* -*****************************************************************************/ - -/* S y s t e m D o o r b e l l */ -#define MPI_DOORBELL_OFFSET (0x00000000) -#define MPI_DOORBELL_ACTIVE (0x08000000) /* DoorbellUsed */ -#define MPI_DOORBELL_USED (MPI_DOORBELL_ACTIVE) -#define MPI_DOORBELL_ACTIVE_SHIFT (27) -#define MPI_DOORBELL_WHO_INIT_MASK (0x07000000) -#define MPI_DOORBELL_WHO_INIT_SHIFT (24) -#define MPI_DOORBELL_FUNCTION_MASK (0xFF000000) -#define MPI_DOORBELL_FUNCTION_SHIFT (24) -#define MPI_DOORBELL_ADD_DWORDS_MASK (0x00FF0000) -#define MPI_DOORBELL_ADD_DWORDS_SHIFT (16) -#define MPI_DOORBELL_DATA_MASK (0x0000FFFF) - - -#define MPI_WRITE_SEQUENCE_OFFSET (0x00000004) -#define MPI_WRSEQ_KEY_VALUE_MASK (0x0000000F) -#define MPI_WRSEQ_1ST_KEY_VALUE (0x04) -#define MPI_WRSEQ_2ND_KEY_VALUE (0x0B) -#define MPI_WRSEQ_3RD_KEY_VALUE (0x02) -#define MPI_WRSEQ_4TH_KEY_VALUE (0x07) -#define MPI_WRSEQ_5TH_KEY_VALUE (0x0D) - -#define MPI_DIAGNOSTIC_OFFSET (0x00000008) -#define MPI_DIAG_CLEAR_FLASH_BAD_SIG (0x00000400) -#define MPI_DIAG_PREVENT_IOC_BOOT (0x00000200) -#define MPI_DIAG_DRWE (0x00000080) -#define MPI_DIAG_FLASH_BAD_SIG (0x00000040) -#define MPI_DIAG_RESET_HISTORY (0x00000020) -#define MPI_DIAG_RW_ENABLE (0x00000010) -#define MPI_DIAG_RESET_ADAPTER (0x00000004) -#define MPI_DIAG_DISABLE_ARM (0x00000002) -#define MPI_DIAG_MEM_ENABLE (0x00000001) - -#define MPI_TEST_BASE_ADDRESS_OFFSET (0x0000000C) - -#define MPI_DIAG_RW_DATA_OFFSET (0x00000010) - -#define MPI_DIAG_RW_ADDRESS_OFFSET (0x00000014) - -#define MPI_HOST_INTERRUPT_STATUS_OFFSET (0x00000030) -#define MPI_HIS_IOP_DOORBELL_STATUS (0x80000000) -#define MPI_HIS_REPLY_MESSAGE_INTERRUPT (0x00000008) -#define MPI_HIS_DOORBELL_INTERRUPT (0x00000001) - -#define MPI_HOST_INTERRUPT_MASK_OFFSET (0x00000034) -#define MPI_HIM_RIM (0x00000008) -#define MPI_HIM_DIM (0x00000001) - -#define MPI_REQUEST_QUEUE_OFFSET (0x00000040) -#define MPI_REQUEST_POST_FIFO_OFFSET (0x00000040) - -#define MPI_REPLY_QUEUE_OFFSET (0x00000044) -#define MPI_REPLY_POST_FIFO_OFFSET (0x00000044) -#define MPI_REPLY_FREE_FIFO_OFFSET (0x00000044) - - - -/***************************************************************************** -* -* M e s s a g e F r a m e D e s c r i p t o r s -* -*****************************************************************************/ - -#define MPI_REQ_MF_DESCRIPTOR_NB_MASK (0x00000003) -#define MPI_REQ_MF_DESCRIPTOR_F_BIT (0x00000004) -#define MPI_REQ_MF_DESCRIPTOR_ADDRESS_MASK (0xFFFFFFF8) - -#define MPI_ADDRESS_REPLY_A_BIT (0x80000000) -#define MPI_ADDRESS_REPLY_ADDRESS_MASK (0x7FFFFFFF) - -#define MPI_CONTEXT_REPLY_A_BIT (0x80000000) -#define MPI_CONTEXT_REPLY_TYPE_MASK (0x60000000) -#define MPI_CONTEXT_REPLY_TYPE_SCSI_INIT (0x00) -#define MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET (0x01) -#define MPI_CONTEXT_REPLY_TYPE_LAN (0x02) -#define MPI_CONTEXT_REPLY_TYPE_SHIFT (29) -#define MPI_CONTEXT_REPLY_CONTEXT_MASK (0x1FFFFFFF) - - -/****************************************************************************/ -/* Context Reply macros */ -/****************************************************************************/ - -#define MPI_GET_CONTEXT_REPLY_TYPE(x) (((x) & MPI_CONTEXT_REPLY_TYPE_MASK) \ - >> MPI_CONTEXT_REPLY_TYPE_SHIFT) - -#define MPI_SET_CONTEXT_REPLY_TYPE(x, typ) \ - ((x) = ((x) & ~MPI_CONTEXT_REPLY_TYPE_MASK) | \ - (((typ) << MPI_CONTEXT_REPLY_TYPE_SHIFT) & \ - MPI_CONTEXT_REPLY_TYPE_MASK)) - - -/***************************************************************************** -* -* M e s s a g e F u n c t i o n s -* 0x80 -> 0x8F reserved for private message use per product -* -* -*****************************************************************************/ - -#define MPI_FUNCTION_SCSI_IO_REQUEST (0x00) -#define MPI_FUNCTION_SCSI_TASK_MGMT (0x01) -#define MPI_FUNCTION_IOC_INIT (0x02) -#define MPI_FUNCTION_IOC_FACTS (0x03) -#define MPI_FUNCTION_CONFIG (0x04) -#define MPI_FUNCTION_PORT_FACTS (0x05) -#define MPI_FUNCTION_PORT_ENABLE (0x06) -#define MPI_FUNCTION_EVENT_NOTIFICATION (0x07) -#define MPI_FUNCTION_EVENT_ACK (0x08) -#define MPI_FUNCTION_FW_DOWNLOAD (0x09) -#define MPI_FUNCTION_TARGET_CMD_BUFFER_POST (0x0A) -#define MPI_FUNCTION_TARGET_ASSIST (0x0B) -#define MPI_FUNCTION_TARGET_STATUS_SEND (0x0C) -#define MPI_FUNCTION_TARGET_MODE_ABORT (0x0D) -#define MPI_FUNCTION_TARGET_FC_BUF_POST_LINK_SRVC (0x0E) /* obsolete name */ -#define MPI_FUNCTION_TARGET_FC_RSP_LINK_SRVC (0x0F) /* obsolete name */ -#define MPI_FUNCTION_TARGET_FC_EX_SEND_LINK_SRVC (0x10) /* obsolete name */ -#define MPI_FUNCTION_TARGET_FC_ABORT (0x11) /* obsolete name */ -#define MPI_FUNCTION_FC_LINK_SRVC_BUF_POST (0x0E) -#define MPI_FUNCTION_FC_LINK_SRVC_RSP (0x0F) -#define MPI_FUNCTION_FC_EX_LINK_SRVC_SEND (0x10) -#define MPI_FUNCTION_FC_ABORT (0x11) -#define MPI_FUNCTION_FW_UPLOAD (0x12) -#define MPI_FUNCTION_FC_COMMON_TRANSPORT_SEND (0x13) -#define MPI_FUNCTION_FC_PRIMITIVE_SEND (0x14) - -#define MPI_FUNCTION_RAID_ACTION (0x15) -#define MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH (0x16) - -#define MPI_FUNCTION_TOOLBOX (0x17) - -#define MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR (0x18) - -#define MPI_FUNCTION_MAILBOX (0x19) - -#define MPI_FUNCTION_LAN_SEND (0x20) -#define MPI_FUNCTION_LAN_RECEIVE (0x21) -#define MPI_FUNCTION_LAN_RESET (0x22) - -#define MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET (0x40) -#define MPI_FUNCTION_IO_UNIT_RESET (0x41) -#define MPI_FUNCTION_HANDSHAKE (0x42) -#define MPI_FUNCTION_REPLY_FRAME_REMOVAL (0x43) - - - -/***************************************************************************** -* -* S c a t t e r G a t h e r E l e m e n t s -* -*****************************************************************************/ - -/****************************************************************************/ -/* Simple element structures */ -/****************************************************************************/ - -typedef struct _SGE_SIMPLE32 -{ - U32 FlagsLength; - U32 Address; -} SGE_SIMPLE32, MPI_POINTER PTR_SGE_SIMPLE32, - SGESimple32_t, MPI_POINTER pSGESimple32_t; - -typedef struct _SGE_SIMPLE64 -{ - U32 FlagsLength; - U64 Address; -} SGE_SIMPLE64, MPI_POINTER PTR_SGE_SIMPLE64, - SGESimple64_t, MPI_POINTER pSGESimple64_t; - -typedef struct _SGE_SIMPLE_UNION -{ - U32 FlagsLength; - union - { - U32 Address32; - U64 Address64; - }u; -} SGESimpleUnion_t, MPI_POINTER pSGESimpleUnion_t, - SGE_SIMPLE_UNION, MPI_POINTER PTR_SGE_SIMPLE_UNION; - -/****************************************************************************/ -/* Chain element structures */ -/****************************************************************************/ - -typedef struct _SGE_CHAIN32 -{ - U16 Length; - U8 NextChainOffset; - U8 Flags; - U32 Address; -} SGE_CHAIN32, MPI_POINTER PTR_SGE_CHAIN32, - SGEChain32_t, MPI_POINTER pSGEChain32_t; - -typedef struct _SGE_CHAIN64 -{ - U16 Length; - U8 NextChainOffset; - U8 Flags; - U64 Address; -} SGE_CHAIN64, MPI_POINTER PTR_SGE_CHAIN64, - SGEChain64_t, MPI_POINTER pSGEChain64_t; - -typedef struct _SGE_CHAIN_UNION -{ - U16 Length; - U8 NextChainOffset; - U8 Flags; - union - { - U32 Address32; - U64 Address64; - }u; -} SGE_CHAIN_UNION, MPI_POINTER PTR_SGE_CHAIN_UNION, - SGEChainUnion_t, MPI_POINTER pSGEChainUnion_t; - -/****************************************************************************/ -/* Transaction Context element */ -/****************************************************************************/ - -typedef struct _SGE_TRANSACTION32 -{ - U8 Reserved; - U8 ContextSize; - U8 DetailsLength; - U8 Flags; - U32 TransactionContext[1]; - U32 TransactionDetails[1]; -} SGE_TRANSACTION32, MPI_POINTER PTR_SGE_TRANSACTION32, - SGETransaction32_t, MPI_POINTER pSGETransaction32_t; - -typedef struct _SGE_TRANSACTION64 -{ - U8 Reserved; - U8 ContextSize; - U8 DetailsLength; - U8 Flags; - U32 TransactionContext[2]; - U32 TransactionDetails[1]; -} SGE_TRANSACTION64, MPI_POINTER PTR_SGE_TRANSACTION64, - SGETransaction64_t, MPI_POINTER pSGETransaction64_t; - -typedef struct _SGE_TRANSACTION96 -{ - U8 Reserved; - U8 ContextSize; - U8 DetailsLength; - U8 Flags; - U32 TransactionContext[3]; - U32 TransactionDetails[1]; -} SGE_TRANSACTION96, MPI_POINTER PTR_SGE_TRANSACTION96, - SGETransaction96_t, MPI_POINTER pSGETransaction96_t; - -typedef struct _SGE_TRANSACTION128 -{ - U8 Reserved; - U8 ContextSize; - U8 DetailsLength; - U8 Flags; - U32 TransactionContext[4]; - U32 TransactionDetails[1]; -} SGE_TRANSACTION128, MPI_POINTER PTR_SGE_TRANSACTION128, - SGETransaction_t128, MPI_POINTER pSGETransaction_t128; - -typedef struct _SGE_TRANSACTION_UNION -{ - U8 Reserved; - U8 ContextSize; - U8 DetailsLength; - U8 Flags; - union - { - U32 TransactionContext32[1]; - U32 TransactionContext64[2]; - U32 TransactionContext96[3]; - U32 TransactionContext128[4]; - }u; - U32 TransactionDetails[1]; -} SGE_TRANSACTION_UNION, MPI_POINTER PTR_SGE_TRANSACTION_UNION, - SGETransactionUnion_t, MPI_POINTER pSGETransactionUnion_t; - - -/****************************************************************************/ -/* SGE IO types union for IO SGL's */ -/****************************************************************************/ - -typedef struct _SGE_IO_UNION -{ - union - { - SGE_SIMPLE_UNION Simple; - SGE_CHAIN_UNION Chain; - } u; -} SGE_IO_UNION, MPI_POINTER PTR_SGE_IO_UNION, - SGEIOUnion_t, MPI_POINTER pSGEIOUnion_t; - -/****************************************************************************/ -/* SGE union for SGL's with Simple and Transaction elements */ -/****************************************************************************/ - -typedef struct _SGE_TRANS_SIMPLE_UNION -{ - union - { - SGE_SIMPLE_UNION Simple; - SGE_TRANSACTION_UNION Transaction; - } u; -} SGE_TRANS_SIMPLE_UNION, MPI_POINTER PTR_SGE_TRANS_SIMPLE_UNION, - SGETransSimpleUnion_t, MPI_POINTER pSGETransSimpleUnion_t; - -/****************************************************************************/ -/* All SGE types union */ -/****************************************************************************/ - -typedef struct _SGE_MPI_UNION -{ - union - { - SGE_SIMPLE_UNION Simple; - SGE_CHAIN_UNION Chain; - SGE_TRANSACTION_UNION Transaction; - } u; -} SGE_MPI_UNION, MPI_POINTER PTR_SGE_MPI_UNION, - MPI_SGE_UNION_t, MPI_POINTER pMPI_SGE_UNION_t, - SGEAllUnion_t, MPI_POINTER pSGEAllUnion_t; - - -/****************************************************************************/ -/* SGE field definition and masks */ -/****************************************************************************/ - -/* Flags field bit definitions */ - -#define MPI_SGE_FLAGS_LAST_ELEMENT (0x80) -#define MPI_SGE_FLAGS_END_OF_BUFFER (0x40) -#define MPI_SGE_FLAGS_ELEMENT_TYPE_MASK (0x30) -#define MPI_SGE_FLAGS_LOCAL_ADDRESS (0x08) -#define MPI_SGE_FLAGS_DIRECTION (0x04) -#define MPI_SGE_FLAGS_ADDRESS_SIZE (0x02) -#define MPI_SGE_FLAGS_END_OF_LIST (0x01) - -#define MPI_SGE_FLAGS_SHIFT (24) - -#define MPI_SGE_LENGTH_MASK (0x00FFFFFF) -#define MPI_SGE_CHAIN_LENGTH_MASK (0x0000FFFF) - -/* Element Type */ - -#define MPI_SGE_FLAGS_TRANSACTION_ELEMENT (0x00) -#define MPI_SGE_FLAGS_SIMPLE_ELEMENT (0x10) -#define MPI_SGE_FLAGS_CHAIN_ELEMENT (0x30) -#define MPI_SGE_FLAGS_ELEMENT_MASK (0x30) - -/* Address location */ - -#define MPI_SGE_FLAGS_SYSTEM_ADDRESS (0x00) - -/* Direction */ - -#define MPI_SGE_FLAGS_IOC_TO_HOST (0x00) -#define MPI_SGE_FLAGS_HOST_TO_IOC (0x04) - -/* Address Size */ - -#define MPI_SGE_FLAGS_32_BIT_ADDRESSING (0x00) -#define MPI_SGE_FLAGS_64_BIT_ADDRESSING (0x02) - -/* Context Size */ - -#define MPI_SGE_FLAGS_32_BIT_CONTEXT (0x00) -#define MPI_SGE_FLAGS_64_BIT_CONTEXT (0x02) -#define MPI_SGE_FLAGS_96_BIT_CONTEXT (0x04) -#define MPI_SGE_FLAGS_128_BIT_CONTEXT (0x06) - -#define MPI_SGE_CHAIN_OFFSET_MASK (0x00FF0000) -#define MPI_SGE_CHAIN_OFFSET_SHIFT (16) - - -/****************************************************************************/ -/* SGE operation Macros */ -/****************************************************************************/ - - /* SIMPLE FlagsLength manipulations... */ -#define MPI_SGE_SET_FLAGS(f) ((U32)(f) << MPI_SGE_FLAGS_SHIFT) -#define MPI_SGE_GET_FLAGS(fl) (((fl) & ~MPI_SGE_LENGTH_MASK) >> MPI_SGE_FLAGS_SHIFT) -#define MPI_SGE_LENGTH(fl) ((fl) & MPI_SGE_LENGTH_MASK) -#define MPI_SGE_CHAIN_LENGTH(fl) ((fl) & MPI_SGE_CHAIN_LENGTH_MASK) - -#define MPI_SGE_SET_FLAGS_LENGTH(f,l) (MPI_SGE_SET_FLAGS(f) | MPI_SGE_LENGTH(l)) - -#define MPI_pSGE_GET_FLAGS(psg) MPI_SGE_GET_FLAGS((psg)->FlagsLength) -#define MPI_pSGE_GET_LENGTH(psg) MPI_SGE_LENGTH((psg)->FlagsLength) -#define MPI_pSGE_SET_FLAGS_LENGTH(psg,f,l) (psg)->FlagsLength = MPI_SGE_SET_FLAGS_LENGTH(f,l) - /* CAUTION - The following are READ-MODIFY-WRITE! */ -#define MPI_pSGE_SET_FLAGS(psg,f) (psg)->FlagsLength |= MPI_SGE_SET_FLAGS(f) -#define MPI_pSGE_SET_LENGTH(psg,l) (psg)->FlagsLength |= MPI_SGE_LENGTH(l) - -#define MPI_GET_CHAIN_OFFSET(x) ((x&MPI_SGE_CHAIN_OFFSET_MASK)>>MPI_SGE_CHAIN_OFFSET_SHIFT) - - - -/***************************************************************************** -* -* S t a n d a r d M e s s a g e S t r u c t u r e s -* -*****************************************************************************/ - -/****************************************************************************/ -/* Standard message request header for all request messages */ -/****************************************************************************/ - -typedef struct _MSG_REQUEST_HEADER -{ - U8 Reserved[2]; /* function specific */ - U8 ChainOffset; - U8 Function; - U8 Reserved1[3]; /* function specific */ - U8 MsgFlags; - U32 MsgContext; -} MSG_REQUEST_HEADER, MPI_POINTER PTR_MSG_REQUEST_HEADER, - MPIHeader_t, MPI_POINTER pMPIHeader_t; - - -/****************************************************************************/ -/* Default Reply */ -/****************************************************************************/ - -typedef struct _MSG_DEFAULT_REPLY -{ - U8 Reserved[2]; /* function specific */ - U8 MsgLength; - U8 Function; - U8 Reserved1[3]; /* function specific */ - U8 MsgFlags; - U32 MsgContext; - U8 Reserved2[2]; /* function specific */ - U16 IOCStatus; - U32 IOCLogInfo; -} MSG_DEFAULT_REPLY, MPI_POINTER PTR_MSG_DEFAULT_REPLY, - MPIDefaultReply_t, MPI_POINTER pMPIDefaultReply_t; - - -/* MsgFlags definition for all replies */ - -#define MPI_MSGFLAGS_CONTINUATION_REPLY (0x80) - - -/***************************************************************************** -* -* I O C S t a t u s V a l u e s -* -*****************************************************************************/ - -/****************************************************************************/ -/* Common IOCStatus values for all replies */ -/****************************************************************************/ - -#define MPI_IOCSTATUS_SUCCESS (0x0000) -#define MPI_IOCSTATUS_INVALID_FUNCTION (0x0001) -#define MPI_IOCSTATUS_BUSY (0x0002) -#define MPI_IOCSTATUS_INVALID_SGL (0x0003) -#define MPI_IOCSTATUS_INTERNAL_ERROR (0x0004) -#define MPI_IOCSTATUS_RESERVED (0x0005) -#define MPI_IOCSTATUS_INSUFFICIENT_RESOURCES (0x0006) -#define MPI_IOCSTATUS_INVALID_FIELD (0x0007) -#define MPI_IOCSTATUS_INVALID_STATE (0x0008) - -/****************************************************************************/ -/* Config IOCStatus values */ -/****************************************************************************/ - -#define MPI_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020) -#define MPI_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021) -#define MPI_IOCSTATUS_CONFIG_INVALID_PAGE (0x0022) -#define MPI_IOCSTATUS_CONFIG_INVALID_DATA (0x0023) -#define MPI_IOCSTATUS_CONFIG_NO_DEFAULTS (0x0024) -#define MPI_IOCSTATUS_CONFIG_CANT_COMMIT (0x0025) - -/****************************************************************************/ -/* SCSIIO Reply (SPI & FCP) initiator values */ -/****************************************************************************/ - -#define MPI_IOCSTATUS_SCSI_RECOVERED_ERROR (0x0040) -#define MPI_IOCSTATUS_SCSI_INVALID_BUS (0x0041) -#define MPI_IOCSTATUS_SCSI_INVALID_TARGETID (0x0042) -#define MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE (0x0043) -#define MPI_IOCSTATUS_SCSI_DATA_OVERRUN (0x0044) -#define MPI_IOCSTATUS_SCSI_DATA_UNDERRUN (0x0045) -#define MPI_IOCSTATUS_SCSI_IO_DATA_ERROR (0x0046) -#define MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR (0x0047) -#define MPI_IOCSTATUS_SCSI_TASK_TERMINATED (0x0048) -#define MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH (0x0049) -#define MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004A) -#define MPI_IOCSTATUS_SCSI_IOC_TERMINATED (0x004B) -#define MPI_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C) - -/****************************************************************************/ -/* SCSI (SPI & FCP) target values */ -/****************************************************************************/ - -#define MPI_IOCSTATUS_TARGET_PRIORITY_IO (0x0060) -#define MPI_IOCSTATUS_TARGET_INVALID_PORT (0x0061) -#define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX (0x0062) -#define MPI_IOCSTATUS_TARGET_ABORTED (0x0063) -#define MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064) -#define MPI_IOCSTATUS_TARGET_NO_CONNECTION (0x0065) -#define MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A) -#define MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT (0x006B) - -/****************************************************************************/ -/* Additional FCP target values */ -/****************************************************************************/ - -#define MPI_IOCSTATUS_TARGET_FC_ABORTED (0x0066) /* obsolete */ -#define MPI_IOCSTATUS_TARGET_FC_RX_ID_INVALID (0x0067) /* obsolete */ -#define MPI_IOCSTATUS_TARGET_FC_DID_INVALID (0x0068) /* obsolete */ -#define MPI_IOCSTATUS_TARGET_FC_NODE_LOGGED_OUT (0x0069) /* obsolete */ - -/****************************************************************************/ -/* Fibre Channel Direct Access values */ -/****************************************************************************/ - -#define MPI_IOCSTATUS_FC_ABORTED (0x0066) -#define MPI_IOCSTATUS_FC_RX_ID_INVALID (0x0067) -#define MPI_IOCSTATUS_FC_DID_INVALID (0x0068) -#define MPI_IOCSTATUS_FC_NODE_LOGGED_OUT (0x0069) - -/****************************************************************************/ -/* LAN values */ -/****************************************************************************/ - -#define MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND (0x0080) -#define MPI_IOCSTATUS_LAN_DEVICE_FAILURE (0x0081) -#define MPI_IOCSTATUS_LAN_TRANSMIT_ERROR (0x0082) -#define MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED (0x0083) -#define MPI_IOCSTATUS_LAN_RECEIVE_ERROR (0x0084) -#define MPI_IOCSTATUS_LAN_RECEIVE_ABORTED (0x0085) -#define MPI_IOCSTATUS_LAN_PARTIAL_PACKET (0x0086) -#define MPI_IOCSTATUS_LAN_CANCELED (0x0087) - - -/****************************************************************************/ -/* IOCStatus flag to indicate that log info is available */ -/****************************************************************************/ - -#define MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE (0x8000) -#define MPI_IOCSTATUS_MASK (0x7FFF) - -/****************************************************************************/ -/* LogInfo Types */ -/****************************************************************************/ - -#define MPI_IOCLOGINFO_TYPE_MASK (0xF0000000) -#define MPI_IOCLOGINFO_TYPE_NONE (0x0) -#define MPI_IOCLOGINFO_TYPE_SCSI (0x1) -#define MPI_IOCLOGINFO_TYPE_FC (0x2) -#define MPI_IOCLOGINFO_LOG_DATA_MASK (0x0FFFFFFF) - - -#endif diff --git a/xen/drivers/message/fusion/lsi/mpi_cnfg.h b/xen/drivers/message/fusion/lsi/mpi_cnfg.h deleted file mode 100644 index 47a5afcdc2..0000000000 --- a/xen/drivers/message/fusion/lsi/mpi_cnfg.h +++ /dev/null @@ -1,1569 +0,0 @@ -/* - * Copyright (c) 2000-2002 LSI Logic Corporation. - * - * - * Name: MPI_CNFG.H - * Title: MPI Config message, structures, and Pages - * Creation Date: July 27, 2000 - * - * MPI_CNFG.H Version: 01.02.09 - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. - * 06-06-00 01.00.01 Update version number for 1.0 release. - * 06-08-00 01.00.02 Added _PAGEVERSION definitions for all pages. - * Added FcPhLowestVersion, FcPhHighestVersion, Reserved2 - * fields to FC_DEVICE_0 page, updated the page version. - * Changed _FREE_RUNNING_CLOCK to _PACING_TRANSFERS in - * SCSI_PORT_0, SCSI_DEVICE_0 and SCSI_DEVICE_1 pages - * and updated the page versions. - * Added _RESPONSE_ID_MASK definition to SCSI_PORT_1 - * page and updated the page version. - * Added Information field and _INFO_PARAMS_NEGOTIATED - * definitionto SCSI_DEVICE_0 page. - * 06-22-00 01.00.03 Removed batch controls from LAN_0 page and updated the - * page version. - * Added BucketsRemaining to LAN_1 page, redefined the - * state values, and updated the page version. - * Revised bus width definitions in SCSI_PORT_0, - * SCSI_DEVICE_0 and SCSI_DEVICE_1 pages. - * 06-30-00 01.00.04 Added MaxReplySize to LAN_1 page and updated the page - * version. - * Moved FC_DEVICE_0 PageAddress description to spec. - * 07-27-00 01.00.05 Corrected the SubsystemVendorID and SubsystemID field - * widths in IOC_0 page and updated the page version. - * 11-02-00 01.01.01 Original release for post 1.0 work - * Added Manufacturing pages, IO Unit Page 2, SCSI SPI - * Port Page 2, FC Port Page 4, FC Port Page 5 - * 11-15-00 01.01.02 Interim changes to match proposals - * 12-04-00 01.01.03 Config page changes to match MPI rev 1.00.01. - * 12-05-00 01.01.04 Modified config page actions. - * 01-09-01 01.01.05 Added defines for page address formats. - * Data size for Manufacturing pages 2 and 3 no longer - * defined here. - * Io Unit Page 2 size is fixed at 4 adapters and some - * flags were changed. - * SCSI Port Page 2 Device Settings modified. - * New fields added to FC Port Page 0 and some flags - * cleaned up. - * Removed impedance flash from FC Port Page 1. - * Added FC Port pages 6 and 7. - * 01-25-01 01.01.06 Added MaxInitiators field to FcPortPage0. - * 01-29-01 01.01.07 Changed some defines to make them 32 character unique. - * Added some LinkType defines for FcPortPage0. - * 02-20-01 01.01.08 Started using MPI_POINTER. - * 02-27-01 01.01.09 Replaced MPI_CONFIG_PAGETYPE_SCSI_LUN with - * MPI_CONFIG_PAGETYPE_RAID_VOLUME. - * Added definitions and structures for IOC Page 2 and - * RAID Volume Page 2. - * 03-27-01 01.01.10 Added CONFIG_PAGE_FC_PORT_8 and CONFIG_PAGE_FC_PORT_9. - * CONFIG_PAGE_FC_PORT_3 now supports persistent by DID. - * Added VendorId and ProductRevLevel fields to - * RAIDVOL2_IM_PHYS_ID struct. - * Modified values for MPI_FCPORTPAGE0_FLAGS_ATTACH_ - * defines to make them compatible to MPI version 1.0. - * Added structure offset comments. - * 04-09-01 01.01.11 Added some new defines for the PageAddress field and - * removed some obsolete ones. - * Added IO Unit Page 3. - * Modified defines for Scsi Port Page 2. - * Modified RAID Volume Pages. - * 08-08-01 01.02.01 Original release for v1.2 work. - * Added SepID and SepBus to RVP2 IMPhysicalDisk struct. - * Added defines for the SEP bits in RVP2 VolumeSettings. - * Modified the DeviceSettings field in RVP2 to use the - * proper structure. - * Added defines for SES, SAF-TE, and cross channel for - * IOCPage2 CapabilitiesFlags. - * Removed define for MPI_IOUNITPAGE2_FLAGS_RAID_DISABLE. - * Removed define for - * MPI_SCSIPORTPAGE2_PORT_FLAGS_PARITY_ENABLE. - * Added define for MPI_CONFIG_PAGEATTR_RO_PERSISTENT. - * 08-29-01 01.02.02 Fixed value for MPI_MANUFACTPAGE_DEVID_53C1035. - * Added defines for MPI_FCPORTPAGE1_FLAGS_HARD_ALPA_ONLY - * and MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY. - * Removed MPI_SCSIPORTPAGE0_CAP_PACING_TRANSFERS, - * MPI_SCSIDEVPAGE0_NP_PACING_TRANSFERS, and - * MPI_SCSIDEVPAGE1_RP_PACING_TRANSFERS, and - * MPI_SCSIDEVPAGE1_CONF_PPR_ALLOWED. - * Added defines for MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED - * and MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED. - * Added OnBusTimerValue to CONFIG_PAGE_SCSI_PORT_1. - * Added rejected bits to SCSI Device Page 0 Information. - * Increased size of ALPA array in FC Port Page 2 by one - * and removed a one byte reserved field. - * 09-28-01 01.02.03 Swapped NegWireSpeedLow and NegWireSpeedLow in - * CONFIG_PAGE_LAN_1 to match preferred 64-bit ordering. - * Added structures for Manufacturing Page 4, IO Unit - * Page 3, IOC Page 3, IOC Page 4, RAID Volume Page 0, and - * RAID PhysDisk Page 0. - * 10-04-01 01.02.04 Added define for MPI_CONFIG_PAGETYPE_RAID_PHYSDISK. - * Modified some of the new defines to make them 32 - * character unique. - * Modified how variable length pages (arrays) are defined. - * Added generic defines for hot spare pools and RAID - * volume types. - * 11-01-01 01.02.05 Added define for MPI_IOUNITPAGE1_DISABLE_IR. - * 03-14-02 01.02.06 Added PCISlotNum field to CONFIG_PAGE_IOC_1 along with - * related define, and bumped the page version define. - * 05-31-02 01.02.07 Added a Flags field to CONFIG_PAGE_IOC_2_RAID_VOL in a - * reserved byte and added a define. - * Added define for - * MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE. - * Added new config page: CONFIG_PAGE_IOC_5. - * Added MaxAliases, MaxHardAliases, and NumCurrentAliases - * fields to CONFIG_PAGE_FC_PORT_0. - * Added AltConnector and NumRequestedAliases fields to - * CONFIG_PAGE_FC_PORT_1. - * Added new config page: CONFIG_PAGE_FC_PORT_10. - * 07-12-02 01.02.08 Added more MPI_MANUFACTPAGE_DEVID_ defines. - * Added additional MPI_SCSIDEVPAGE0_NP_ defines. - * Added more MPI_SCSIDEVPAGE1_RP_ defines. - * Added define for - * MPI_SCSIDEVPAGE1_CONF_EXTENDED_PARAMS_ENABLE. - * Added new config page: CONFIG_PAGE_SCSI_DEVICE_3. - * Modified MPI_FCPORTPAGE5_FLAGS_ defines. - * 09-16-02 01.02.09 Added more MPI_SCSIDEVPAGE1_CONF_FORCE_PPR_MSG define. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI_CNFG_H -#define MPI_CNFG_H - - -/***************************************************************************** -* -* C o n f i g M e s s a g e a n d S t r u c t u r e s -* -*****************************************************************************/ - -typedef struct _CONFIG_PAGE_HEADER -{ - U8 PageVersion; /* 00h */ - U8 PageLength; /* 01h */ - U8 PageNumber; /* 02h */ - U8 PageType; /* 03h */ -} fCONFIG_PAGE_HEADER, MPI_POINTER PTR_CONFIG_PAGE_HEADER, - ConfigPageHeader_t, MPI_POINTER pConfigPageHeader_t; - -typedef union _CONFIG_PAGE_HEADER_UNION -{ - ConfigPageHeader_t Struct; - U8 Bytes[4]; - U16 Word16[2]; - U32 Word32; -} ConfigPageHeaderUnion, MPI_POINTER pConfigPageHeaderUnion, - fCONFIG_PAGE_HEADER_UNION, MPI_POINTER PTR_CONFIG_PAGE_HEADER_UNION; - - -/**************************************************************************** -* PageType field values -****************************************************************************/ -#define MPI_CONFIG_PAGEATTR_READ_ONLY (0x00) -#define MPI_CONFIG_PAGEATTR_CHANGEABLE (0x10) -#define MPI_CONFIG_PAGEATTR_PERSISTENT (0x20) -#define MPI_CONFIG_PAGEATTR_RO_PERSISTENT (0x30) -#define MPI_CONFIG_PAGEATTR_MASK (0xF0) - -#define MPI_CONFIG_PAGETYPE_IO_UNIT (0x00) -#define MPI_CONFIG_PAGETYPE_IOC (0x01) -#define MPI_CONFIG_PAGETYPE_BIOS (0x02) -#define MPI_CONFIG_PAGETYPE_SCSI_PORT (0x03) -#define MPI_CONFIG_PAGETYPE_SCSI_DEVICE (0x04) -#define MPI_CONFIG_PAGETYPE_FC_PORT (0x05) -#define MPI_CONFIG_PAGETYPE_FC_DEVICE (0x06) -#define MPI_CONFIG_PAGETYPE_LAN (0x07) -#define MPI_CONFIG_PAGETYPE_RAID_VOLUME (0x08) -#define MPI_CONFIG_PAGETYPE_MANUFACTURING (0x09) -#define MPI_CONFIG_PAGETYPE_RAID_PHYSDISK (0x0A) -#define MPI_CONFIG_PAGETYPE_MASK (0x0F) - -#define MPI_CONFIG_TYPENUM_MASK (0x0FFF) - - -/**************************************************************************** -* PageAddress field values -****************************************************************************/ -#define MPI_SCSI_PORT_PGAD_PORT_MASK (0x000000FF) - -#define MPI_SCSI_DEVICE_TARGET_ID_MASK (0x000000FF) -#define MPI_SCSI_DEVICE_TARGET_ID_SHIFT (0) -#define MPI_SCSI_DEVICE_BUS_MASK (0x0000FF00) -#define MPI_SCSI_DEVICE_BUS_SHIFT (8) - -#define MPI_FC_PORT_PGAD_PORT_MASK (0xF0000000) -#define MPI_FC_PORT_PGAD_PORT_SHIFT (28) -#define MPI_FC_PORT_PGAD_FORM_MASK (0x0F000000) -#define MPI_FC_PORT_PGAD_FORM_INDEX (0x01000000) -#define MPI_FC_PORT_PGAD_INDEX_MASK (0x0000FFFF) -#define MPI_FC_PORT_PGAD_INDEX_SHIFT (0) - -#define MPI_FC_DEVICE_PGAD_PORT_MASK (0xF0000000) -#define MPI_FC_DEVICE_PGAD_PORT_SHIFT (28) -#define MPI_FC_DEVICE_PGAD_FORM_MASK (0x0F000000) -#define MPI_FC_DEVICE_PGAD_FORM_NEXT_DID (0x00000000) -#define MPI_FC_DEVICE_PGAD_ND_PORT_MASK (0xF0000000) -#define MPI_FC_DEVICE_PGAD_ND_PORT_SHIFT (28) -#define MPI_FC_DEVICE_PGAD_ND_DID_MASK (0x00FFFFFF) -#define MPI_FC_DEVICE_PGAD_ND_DID_SHIFT (0) -#define MPI_FC_DEVICE_PGAD_FORM_BUS_TID (0x01000000) -#define MPI_FC_DEVICE_PGAD_BT_BUS_MASK (0x0000FF00) -#define MPI_FC_DEVICE_PGAD_BT_BUS_SHIFT (8) -#define MPI_FC_DEVICE_PGAD_BT_TID_MASK (0x000000FF) -#define MPI_FC_DEVICE_PGAD_BT_TID_SHIFT (0) - -#define MPI_PHYSDISK_PGAD_PHYSDISKNUM_MASK (0x000000FF) -#define MPI_PHYSDISK_PGAD_PHYSDISKNUM_SHIFT (0) - - - -/**************************************************************************** -* Config Request Message -****************************************************************************/ -typedef struct _MSG_CONFIG -{ - U8 Action; /* 00h */ - U8 Reserved; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U8 Reserved1[3]; /* 04h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U8 Reserved2[8]; /* 0Ch */ - fCONFIG_PAGE_HEADER Header; /* 14h */ - U32 PageAddress; /* 18h */ - SGE_IO_UNION PageBufferSGE; /* 1Ch */ -} MSG_CONFIG, MPI_POINTER PTR_MSG_CONFIG, - Config_t, MPI_POINTER pConfig_t; - - -/**************************************************************************** -* Action field values -****************************************************************************/ -#define MPI_CONFIG_ACTION_PAGE_HEADER (0x00) -#define MPI_CONFIG_ACTION_PAGE_READ_CURRENT (0x01) -#define MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT (0x02) -#define MPI_CONFIG_ACTION_PAGE_DEFAULT (0x03) -#define MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM (0x04) -#define MPI_CONFIG_ACTION_PAGE_READ_DEFAULT (0x05) -#define MPI_CONFIG_ACTION_PAGE_READ_NVRAM (0x06) - - -/* Config Reply Message */ -typedef struct _MSG_CONFIG_REPLY -{ - U8 Action; /* 00h */ - U8 Reserved; /* 01h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U8 Reserved1[3]; /* 04h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U8 Reserved2[2]; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - fCONFIG_PAGE_HEADER Header; /* 14h */ -} MSG_CONFIG_REPLY, MPI_POINTER PTR_MSG_CONFIG_REPLY, - ConfigReply_t, MPI_POINTER pConfigReply_t; - - - -/***************************************************************************** -* -* C o n f i g u r a t i o n P a g e s -* -*****************************************************************************/ - -/**************************************************************************** -* Manufacturing Config pages -****************************************************************************/ -#define MPI_MANUFACTPAGE_DEVICEID_FC909 (0x0621) -#define MPI_MANUFACTPAGE_DEVICEID_FC919 (0x0624) -#define MPI_MANUFACTPAGE_DEVICEID_FC929 (0x0622) -#define MPI_MANUFACTPAGE_DEVICEID_FC919X (0x0628) -#define MPI_MANUFACTPAGE_DEVICEID_FC929X (0x0626) - -#define MPI_MANUFACTPAGE_DEVID_53C1030 (0x0030) -#define MPI_MANUFACTPAGE_DEVID_53C1030ZC (0x0031) -#define MPI_MANUFACTPAGE_DEVID_1030_53C1035 (0x0032) -#define MPI_MANUFACTPAGE_DEVID_1030ZC_53C1035 (0x0033) -#define MPI_MANUFACTPAGE_DEVID_53C1035 (0x0040) -#define MPI_MANUFACTPAGE_DEVID_53C1035ZC (0x0041) - -#define MPI_MANUFACTPAGE_DEVID_SA2010 (0x0804) -#define MPI_MANUFACTPAGE_DEVID_SA2010ZC (0x0805) -#define MPI_MANUFACTPAGE_DEVID_SA2020 (0x0806) -#define MPI_MANUFACTPAGE_DEVID_SA2020ZC (0x0807) - - -typedef struct _CONFIG_PAGE_MANUFACTURING_0 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U8 ChipName[16]; /* 04h */ - U8 ChipRevision[8]; /* 14h */ - U8 BoardName[16]; /* 1Ch */ - U8 BoardAssembly[16]; /* 2Ch */ - U8 BoardTracerNumber[16]; /* 3Ch */ - -} fCONFIG_PAGE_MANUFACTURING_0, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_0, - ManufacturingPage0_t, MPI_POINTER pManufacturingPage0_t; - -#define MPI_MANUFACTURING0_PAGEVERSION (0x00) - - -typedef struct _CONFIG_PAGE_MANUFACTURING_1 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U8 VPD[256]; /* 04h */ -} fCONFIG_PAGE_MANUFACTURING_1, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_1, - ManufacturingPage1_t, MPI_POINTER pManufacturingPage1_t; - -#define MPI_MANUFACTURING1_PAGEVERSION (0x00) - - -typedef struct _MPI_CHIP_REVISION_ID -{ - U16 DeviceID; /* 00h */ - U8 PCIRevisionID; /* 02h */ - U8 Reserved; /* 03h */ -} MPI_CHIP_REVISION_ID, MPI_POINTER PTR_MPI_CHIP_REVISION_ID, - MpiChipRevisionId_t, MPI_POINTER pMpiChipRevisionId_t; - - -/* - * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength at runtime. - */ -#ifndef MPI_MAN_PAGE_2_HW_SETTINGS_WORDS -#define MPI_MAN_PAGE_2_HW_SETTINGS_WORDS (1) -#endif - -typedef struct _CONFIG_PAGE_MANUFACTURING_2 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - MPI_CHIP_REVISION_ID ChipId; /* 04h */ - U32 HwSettings[MPI_MAN_PAGE_2_HW_SETTINGS_WORDS];/* 08h */ -} fCONFIG_PAGE_MANUFACTURING_2, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_2, - ManufacturingPage2_t, MPI_POINTER pManufacturingPage2_t; - -#define MPI_MANUFACTURING2_PAGEVERSION (0x00) - - -/* - * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength at runtime. - */ -#ifndef MPI_MAN_PAGE_3_INFO_WORDS -#define MPI_MAN_PAGE_3_INFO_WORDS (1) -#endif - -typedef struct _CONFIG_PAGE_MANUFACTURING_3 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - MPI_CHIP_REVISION_ID ChipId; /* 04h */ - U32 Info[MPI_MAN_PAGE_3_INFO_WORDS];/* 08h */ -} fCONFIG_PAGE_MANUFACTURING_3, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_3, - ManufacturingPage3_t, MPI_POINTER pManufacturingPage3_t; - -#define MPI_MANUFACTURING3_PAGEVERSION (0x00) - - -typedef struct _CONFIG_PAGE_MANUFACTURING_4 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 Reserved1; /* 04h */ - U8 InfoOffset0; /* 08h */ - U8 InfoSize0; /* 09h */ - U8 InfoOffset1; /* 0Ah */ - U8 InfoSize1; /* 0Bh */ - U8 InquirySize; /* 0Ch */ - U8 Reserved2; /* 0Dh */ - U16 Reserved3; /* 0Eh */ - U8 InquiryData[56]; /* 10h */ - U32 ISVolumeSettings; /* 48h */ - U32 IMEVolumeSettings; /* 4Ch */ - U32 IMVolumeSettings; /* 50h */ -} fCONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4, - ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t; - -#define MPI_MANUFACTURING4_PAGEVERSION (0x00) - - -/**************************************************************************** -* IO Unit Config Pages -****************************************************************************/ - -typedef struct _CONFIG_PAGE_IO_UNIT_0 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U64 UniqueValue; /* 04h */ -} fCONFIG_PAGE_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_0, - IOUnitPage0_t, MPI_POINTER pIOUnitPage0_t; - -#define MPI_IOUNITPAGE0_PAGEVERSION (0x00) - - -typedef struct _CONFIG_PAGE_IO_UNIT_1 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 Flags; /* 04h */ -} fCONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1, - IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t; - -#define MPI_IOUNITPAGE1_PAGEVERSION (0x00) - -/* IO Unit Page 1 Flags defines */ - -#define MPI_IOUNITPAGE1_MULTI_FUNCTION (0x00000000) -#define MPI_IOUNITPAGE1_SINGLE_FUNCTION (0x00000001) -#define MPI_IOUNITPAGE1_MULTI_PATHING (0x00000002) -#define MPI_IOUNITPAGE1_SINGLE_PATHING (0x00000000) -#define MPI_IOUNITPAGE1_DISABLE_IR (0x00000040) -#define MPI_IOUNITPAGE1_FORCE_32 (0x00000080) - - -typedef struct _MPI_ADAPTER_INFO -{ - U8 PciBusNumber; /* 00h */ - U8 PciDeviceAndFunctionNumber; /* 01h */ - U16 AdapterFlags; /* 02h */ -} MPI_ADAPTER_INFO, MPI_POINTER PTR_MPI_ADAPTER_INFO, - MpiAdapterInfo_t, MPI_POINTER pMpiAdapterInfo_t; - -#define MPI_ADAPTER_INFO_FLAGS_EMBEDDED (0x0001) -#define MPI_ADAPTER_INFO_FLAGS_INIT_STATUS (0x0002) - -typedef struct _CONFIG_PAGE_IO_UNIT_2 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 Flags; /* 04h */ - U32 BiosVersion; /* 08h */ - MPI_ADAPTER_INFO AdapterOrder[4]; /* 0Ch */ -} fCONFIG_PAGE_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_2, - IOUnitPage2_t, MPI_POINTER pIOUnitPage2_t; - -#define MPI_IOUNITPAGE2_PAGEVERSION (0x00) - -#define MPI_IOUNITPAGE2_FLAGS_PAUSE_ON_ERROR (0x00000002) -#define MPI_IOUNITPAGE2_FLAGS_VERBOSE_ENABLE (0x00000004) -#define MPI_IOUNITPAGE2_FLAGS_COLOR_VIDEO_DISABLE (0x00000008) -#define MPI_IOUNITPAGE2_FLAGS_DONT_HOOK_INT_40 (0x00000010) - - -/* - * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength at runtime. - */ -#ifndef MPI_IO_UNIT_PAGE_3_GPIO_VAL_MAX -#define MPI_IO_UNIT_PAGE_3_GPIO_VAL_MAX (1) -#endif - -typedef struct _CONFIG_PAGE_IO_UNIT_3 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U8 GPIOCount; /* 04h */ - U8 Reserved1; /* 05h */ - U16 Reserved2; /* 06h */ - U16 GPIOVal[MPI_IO_UNIT_PAGE_3_GPIO_VAL_MAX]; /* 08h */ -} fCONFIG_PAGE_IO_UNIT_3, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_3, - IOUnitPage3_t, MPI_POINTER pIOUnitPage3_t; - -#define MPI_IOUNITPAGE3_PAGEVERSION (0x01) - -#define MPI_IOUNITPAGE3_GPIO_FUNCTION_MASK (0xFC) -#define MPI_IOUNITPAGE3_GPIO_FUNCTION_SHIFT (2) -#define MPI_IOUNITPAGE3_GPIO_SETTING_OFF (0x00) -#define MPI_IOUNITPAGE3_GPIO_SETTING_ON (0x01) - - -/**************************************************************************** -* IOC Config Pages -****************************************************************************/ - -typedef struct _CONFIG_PAGE_IOC_0 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 TotalNVStore; /* 04h */ - U32 FreeNVStore; /* 08h */ - U16 VendorID; /* 0Ch */ - U16 DeviceID; /* 0Eh */ - U8 RevisionID; /* 10h */ - U8 Reserved[3]; /* 11h */ - U32 ClassCode; /* 14h */ - U16 SubsystemVendorID; /* 18h */ - U16 SubsystemID; /* 1Ah */ -} fCONFIG_PAGE_IOC_0, MPI_POINTER PTR_CONFIG_PAGE_IOC_0, - IOCPage0_t, MPI_POINTER pIOCPage0_t; - -#define MPI_IOCPAGE0_PAGEVERSION (0x01) - - -typedef struct _CONFIG_PAGE_IOC_1 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 Flags; /* 04h */ - U32 CoalescingTimeout; /* 08h */ - U8 CoalescingDepth; /* 0Ch */ - U8 PCISlotNum; /* 0Dh */ - U8 Reserved[2]; /* 0Eh */ -} fCONFIG_PAGE_IOC_1, MPI_POINTER PTR_CONFIG_PAGE_IOC_1, - IOCPage1_t, MPI_POINTER pIOCPage1_t; - -#define MPI_IOCPAGE1_PAGEVERSION (0x01) - -#define MPI_IOCPAGE1_REPLY_COALESCING (0x00000001) - -#define MPI_IOCPAGE1_PCISLOTNUM_UNKNOWN (0xFF) - - -typedef struct _CONFIG_PAGE_IOC_2_RAID_VOL -{ - U8 VolumeID; /* 00h */ - U8 VolumeBus; /* 01h */ - U8 VolumeIOC; /* 02h */ - U8 VolumePageNumber; /* 03h */ - U8 VolumeType; /* 04h */ - U8 Flags; /* 05h */ - U16 Reserved3; /* 06h */ -} fCONFIG_PAGE_IOC_2_RAID_VOL, MPI_POINTER PTR_CONFIG_PAGE_IOC_2_RAID_VOL, - ConfigPageIoc2RaidVol_t, MPI_POINTER pConfigPageIoc2RaidVol_t; - -/* IOC Page 2 Volume RAID Type values, also used in RAID Volume pages */ - -#define MPI_RAID_VOL_TYPE_IS (0x00) -#define MPI_RAID_VOL_TYPE_IME (0x01) -#define MPI_RAID_VOL_TYPE_IM (0x02) - -/* IOC Page 2 Volume Flags values */ - -#define MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE (0x08) - -/* - * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength at runtime. - */ -#ifndef MPI_IOC_PAGE_2_RAID_VOLUME_MAX -#define MPI_IOC_PAGE_2_RAID_VOLUME_MAX (1) -#endif - -typedef struct _CONFIG_PAGE_IOC_2 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 CapabilitiesFlags; /* 04h */ - U8 NumActiveVolumes; /* 08h */ - U8 MaxVolumes; /* 09h */ - U8 NumActivePhysDisks; /* 0Ah */ - U8 MaxPhysDisks; /* 0Bh */ - fCONFIG_PAGE_IOC_2_RAID_VOL RaidVolume[MPI_IOC_PAGE_2_RAID_VOLUME_MAX];/* 0Ch */ -} fCONFIG_PAGE_IOC_2, MPI_POINTER PTR_CONFIG_PAGE_IOC_2, - IOCPage2_t, MPI_POINTER pIOCPage2_t; - -#define MPI_IOCPAGE2_PAGEVERSION (0x02) - -/* IOC Page 2 Capabilities flags */ - -#define MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT (0x00000001) -#define MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT (0x00000002) -#define MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT (0x00000004) -#define MPI_IOCPAGE2_CAP_FLAGS_SES_SUPPORT (0x20000000) -#define MPI_IOCPAGE2_CAP_FLAGS_SAFTE_SUPPORT (0x40000000) -#define MPI_IOCPAGE2_CAP_FLAGS_CROSS_CHANNEL_SUPPORT (0x80000000) - - -typedef struct _IOC_3_PHYS_DISK -{ - U8 PhysDiskID; /* 00h */ - U8 PhysDiskBus; /* 01h */ - U8 PhysDiskIOC; /* 02h */ - U8 PhysDiskNum; /* 03h */ -} IOC_3_PHYS_DISK, MPI_POINTER PTR_IOC_3_PHYS_DISK, - Ioc3PhysDisk_t, MPI_POINTER pIoc3PhysDisk_t; - -/* - * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength at runtime. - */ -#ifndef MPI_IOC_PAGE_3_PHYSDISK_MAX -#define MPI_IOC_PAGE_3_PHYSDISK_MAX (1) -#endif - -typedef struct _CONFIG_PAGE_IOC_3 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U8 NumPhysDisks; /* 04h */ - U8 Reserved1; /* 05h */ - U16 Reserved2; /* 06h */ - IOC_3_PHYS_DISK PhysDisk[MPI_IOC_PAGE_3_PHYSDISK_MAX]; /* 08h */ -} fCONFIG_PAGE_IOC_3, MPI_POINTER PTR_CONFIG_PAGE_IOC_3, - IOCPage3_t, MPI_POINTER pIOCPage3_t; - -#define MPI_IOCPAGE3_PAGEVERSION (0x00) - - -typedef struct _IOC_4_SEP -{ - U8 SEPTargetID; /* 00h */ - U8 SEPBus; /* 01h */ - U16 Reserved; /* 02h */ -} IOC_4_SEP, MPI_POINTER PTR_IOC_4_SEP, - Ioc4Sep_t, MPI_POINTER pIoc4Sep_t; - -/* - * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength at runtime. - */ -#ifndef MPI_IOC_PAGE_4_SEP_MAX -#define MPI_IOC_PAGE_4_SEP_MAX (1) -#endif - -typedef struct _CONFIG_PAGE_IOC_4 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U8 ActiveSEP; /* 04h */ - U8 MaxSEP; /* 05h */ - U16 Reserved1; /* 06h */ - IOC_4_SEP SEP[MPI_IOC_PAGE_4_SEP_MAX]; /* 08h */ -} fCONFIG_PAGE_IOC_4, MPI_POINTER PTR_CONFIG_PAGE_IOC_4, - IOCPage4_t, MPI_POINTER pIOCPage4_t; - -#define MPI_IOCPAGE4_PAGEVERSION (0x00) - - -typedef struct _IOC_5_HOT_SPARE -{ - U8 PhysDiskNum; /* 00h */ - U8 Reserved; /* 01h */ - U8 HotSparePool; /* 02h */ - U8 Flags; /* 03h */ -} IOC_5_HOT_SPARE, MPI_POINTER PTR_IOC_5_HOT_SPARE, - Ioc5HotSpare_t, MPI_POINTER pIoc5HotSpare_t; - -/* IOC Page 5 HotSpare Flags */ -#define MPI_IOC_PAGE_5_HOT_SPARE_ACTIVE (0x01) - -/* - * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength at runtime. - */ -#ifndef MPI_IOC_PAGE_5_HOT_SPARE_MAX -#define MPI_IOC_PAGE_5_HOT_SPARE_MAX (1) -#endif - -typedef struct _CONFIG_PAGE_IOC_5 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 Reserved1; /* 04h */ - U8 NumHotSpares; /* 08h */ - U8 Reserved2; /* 09h */ - U16 Reserved3; /* 0Ah */ - IOC_5_HOT_SPARE HotSpare[MPI_IOC_PAGE_5_HOT_SPARE_MAX]; /* 0Ch */ -} fCONFIG_PAGE_IOC_5, MPI_POINTER PTR_CONFIG_PAGE_IOC_5, - IOCPage5_t, MPI_POINTER pIOCPage5_t; - -#define MPI_IOCPAGE5_PAGEVERSION (0x00) - - - -/**************************************************************************** -* SCSI Port Config Pages -****************************************************************************/ - -typedef struct _CONFIG_PAGE_SCSI_PORT_0 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 Capabilities; /* 04h */ - U32 PhysicalInterface; /* 08h */ -} fCONFIG_PAGE_SCSI_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_0, - SCSIPortPage0_t, MPI_POINTER pSCSIPortPage0_t; - -#define MPI_SCSIPORTPAGE0_PAGEVERSION (0x01) - -#define MPI_SCSIPORTPAGE0_CAP_IU (0x00000001) -#define MPI_SCSIPORTPAGE0_CAP_DT (0x00000002) -#define MPI_SCSIPORTPAGE0_CAP_QAS (0x00000004) -#define MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK (0x0000FF00) -#define MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK (0x00FF0000) -#define MPI_SCSIPORTPAGE0_CAP_WIDE (0x20000000) -#define MPI_SCSIPORTPAGE0_CAP_AIP (0x80000000) - -#define MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK (0x00000003) -#define MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD (0x01) -#define MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE (0x02) -#define MPI_SCSIPORTPAGE0_PHY_SIGNAL_LVD (0x03) - - -typedef struct _CONFIG_PAGE_SCSI_PORT_1 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 Configuration; /* 04h */ - U32 OnBusTimerValue; /* 08h */ -} fCONFIG_PAGE_SCSI_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_1, - SCSIPortPage1_t, MPI_POINTER pSCSIPortPage1_t; - -#define MPI_SCSIPORTPAGE1_PAGEVERSION (0x02) - -#define MPI_SCSIPORTPAGE1_CFG_PORT_SCSI_ID_MASK (0x000000FF) -#define MPI_SCSIPORTPAGE1_CFG_PORT_RESPONSE_ID_MASK (0xFFFF0000) - - -typedef struct _MPI_DEVICE_INFO -{ - U8 Timeout; /* 00h */ - U8 SyncFactor; /* 01h */ - U16 DeviceFlags; /* 02h */ -} MPI_DEVICE_INFO, MPI_POINTER PTR_MPI_DEVICE_INFO, - MpiDeviceInfo_t, MPI_POINTER pMpiDeviceInfo_t; - -typedef struct _CONFIG_PAGE_SCSI_PORT_2 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 PortFlags; /* 04h */ - U32 PortSettings; /* 08h */ - MPI_DEVICE_INFO DeviceSettings[16]; /* 0Ch */ -} fCONFIG_PAGE_SCSI_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_2, - SCSIPortPage2_t, MPI_POINTER pSCSIPortPage2_t; - -#define MPI_SCSIPORTPAGE2_PAGEVERSION (0x01) - -#define MPI_SCSIPORTPAGE2_PORT_FLAGS_SCAN_HIGH_TO_LOW (0x00000001) -#define MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET (0x00000004) -#define MPI_SCSIPORTPAGE2_PORT_FLAGS_ALTERNATE_CHS (0x00000008) -#define MPI_SCSIPORTPAGE2_PORT_FLAGS_TERMINATION_DISABLE (0x00000010) - -#define MPI_SCSIPORTPAGE2_PORT_HOST_ID_MASK (0x0000000F) -#define MPI_SCSIPORTPAGE2_PORT_MASK_INIT_HBA (0x00000030) -#define MPI_SCSIPORTPAGE2_PORT_DISABLE_INIT_HBA (0x00000000) -#define MPI_SCSIPORTPAGE2_PORT_BIOS_INIT_HBA (0x00000010) -#define MPI_SCSIPORTPAGE2_PORT_OS_INIT_HBA (0x00000020) -#define MPI_SCSIPORTPAGE2_PORT_BIOS_OS_INIT_HBA (0x00000030) -#define MPI_SCSIPORTPAGE2_PORT_REMOVABLE_MEDIA (0x000000C0) -#define MPI_SCSIPORTPAGE2_PORT_SPINUP_DELAY_MASK (0x00000F00) -#define MPI_SCSIPORTPAGE2_PORT_MASK_NEGO_MASTER_SETTINGS (0x00003000) -#define MPI_SCSIPORTPAGE2_PORT_NEGO_MASTER_SETTINGS (0x00000000) -#define MPI_SCSIPORTPAGE2_PORT_NONE_MASTER_SETTINGS (0x00001000) -#define MPI_SCSIPORTPAGE2_PORT_ALL_MASTER_SETTINGS (0x00003000) - -#define MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE (0x0001) -#define MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE (0x0002) -#define MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE (0x0004) -#define MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE (0x0008) -#define MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE (0x0010) -#define MPI_SCSIPORTPAGE2_DEVICE_BOOT_CHOICE (0x0020) - - -/**************************************************************************** -* SCSI Target Device Config Pages -****************************************************************************/ - -typedef struct _CONFIG_PAGE_SCSI_DEVICE_0 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 NegotiatedParameters; /* 04h */ - U32 Information; /* 08h */ -} fCONFIG_PAGE_SCSI_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_0, - SCSIDevicePage0_t, MPI_POINTER pSCSIDevicePage0_t; - -#define MPI_SCSIDEVPAGE0_PAGEVERSION (0x03) - -#define MPI_SCSIDEVPAGE0_NP_IU (0x00000001) -#define MPI_SCSIDEVPAGE0_NP_DT (0x00000002) -#define MPI_SCSIDEVPAGE0_NP_QAS (0x00000004) -#define MPI_SCSIDEVPAGE0_NP_HOLD_MCS (0x00000008) -#define MPI_SCSIDEVPAGE0_NP_WR_FLOW (0x00000010) -#define MPI_SCSIDEVPAGE0_NP_RD_STRM (0x00000020) -#define MPI_SCSIDEVPAGE0_NP_RTI (0x00000040) -#define MPI_SCSIDEVPAGE0_NP_PCOMP_EN (0x00000080) -#define MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK (0x0000FF00) -#define MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK (0x00FF0000) -#define MPI_SCSIDEVPAGE0_NP_WIDE (0x20000000) -#define MPI_SCSIDEVPAGE0_NP_AIP (0x80000000) - -#define MPI_SCSIDEVPAGE0_INFO_PARAMS_NEGOTIATED (0x00000001) -#define MPI_SCSIDEVPAGE0_INFO_SDTR_REJECTED (0x00000002) -#define MPI_SCSIDEVPAGE0_INFO_WDTR_REJECTED (0x00000004) -#define MPI_SCSIDEVPAGE0_INFO_PPR_REJECTED (0x00000008) - - -typedef struct _CONFIG_PAGE_SCSI_DEVICE_1 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 RequestedParameters; /* 04h */ - U32 Reserved; /* 08h */ - U32 Configuration; /* 0Ch */ -} fCONFIG_PAGE_SCSI_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_1, - SCSIDevicePage1_t, MPI_POINTER pSCSIDevicePage1_t; - -#define MPI_SCSIDEVPAGE1_PAGEVERSION (0x04) - -#define MPI_SCSIDEVPAGE1_RP_IU (0x00000001) -#define MPI_SCSIDEVPAGE1_RP_DT (0x00000002) -#define MPI_SCSIDEVPAGE1_RP_QAS (0x00000004) -#define MPI_SCSIDEVPAGE1_RP_HOLD_MCS (0x00000008) -#define MPI_SCSIDEVPAGE1_RP_WR_FLOW (0x00000010) -#define MPI_SCSIDEVPAGE1_RP_RD_STRM (0x00000020) -#define MPI_SCSIDEVPAGE1_RP_RTI (0x00000040) -#define MPI_SCSIDEVPAGE1_RP_PCOMP_EN (0x00000080) -#define MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK (0x0000FF00) -#define MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK (0x00FF0000) -#define MPI_SCSIDEVPAGE1_RP_WIDE (0x20000000) -#define MPI_SCSIDEVPAGE1_RP_AIP (0x80000000) - -#define MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED (0x00000002) -#define MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED (0x00000004) -#define MPI_SCSIDEVPAGE1_CONF_EXTENDED_PARAMS_ENABLE (0x00000008) -#define MPI_SCSIDEVPAGE1_CONF_FORCE_PPR_MSG (0x00000010) - - -typedef struct _CONFIG_PAGE_SCSI_DEVICE_2 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 DomainValidation; /* 04h */ - U32 ParityPipeSelect; /* 08h */ - U32 DataPipeSelect; /* 0Ch */ -} fCONFIG_PAGE_SCSI_DEVICE_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_2, - SCSIDevicePage2_t, MPI_POINTER pSCSIDevicePage2_t; - -#define MPI_SCSIDEVPAGE2_PAGEVERSION (0x01) - -#define MPI_SCSIDEVPAGE2_DV_ISI_ENABLE (0x00000010) -#define MPI_SCSIDEVPAGE2_DV_SECONDARY_DRIVER_ENABLE (0x00000020) -#define MPI_SCSIDEVPAGE2_DV_SLEW_RATE_CTRL (0x00000380) -#define MPI_SCSIDEVPAGE2_DV_PRIM_DRIVE_STR_CTRL (0x00001C00) -#define MPI_SCSIDEVPAGE2_DV_SECOND_DRIVE_STR_CTRL (0x0000E000) -#define MPI_SCSIDEVPAGE2_DV_XCLKH_ST (0x10000000) -#define MPI_SCSIDEVPAGE2_DV_XCLKS_ST (0x20000000) -#define MPI_SCSIDEVPAGE2_DV_XCLKH_DT (0x40000000) -#define MPI_SCSIDEVPAGE2_DV_XCLKS_DT (0x80000000) - -#define MPI_SCSIDEVPAGE2_PPS_PPS_MASK (0x00000003) - -#define MPI_SCSIDEVPAGE2_DPS_BIT_0_PL_SELECT_MASK (0x00000003) -#define MPI_SCSIDEVPAGE2_DPS_BIT_1_PL_SELECT_MASK (0x0000000C) -#define MPI_SCSIDEVPAGE2_DPS_BIT_2_PL_SELECT_MASK (0x00000030) -#define MPI_SCSIDEVPAGE2_DPS_BIT_3_PL_SELECT_MASK (0x000000C0) -#define MPI_SCSIDEVPAGE2_DPS_BIT_4_PL_SELECT_MASK (0x00000300) -#define MPI_SCSIDEVPAGE2_DPS_BIT_5_PL_SELECT_MASK (0x00000C00) -#define MPI_SCSIDEVPAGE2_DPS_BIT_6_PL_SELECT_MASK (0x00003000) -#define MPI_SCSIDEVPAGE2_DPS_BIT_7_PL_SELECT_MASK (0x0000C000) -#define MPI_SCSIDEVPAGE2_DPS_BIT_8_PL_SELECT_MASK (0x00030000) -#define MPI_SCSIDEVPAGE2_DPS_BIT_9_PL_SELECT_MASK (0x000C0000) -#define MPI_SCSIDEVPAGE2_DPS_BIT_10_PL_SELECT_MASK (0x00300000) -#define MPI_SCSIDEVPAGE2_DPS_BIT_11_PL_SELECT_MASK (0x00C00000) -#define MPI_SCSIDEVPAGE2_DPS_BIT_12_PL_SELECT_MASK (0x03000000) -#define MPI_SCSIDEVPAGE2_DPS_BIT_13_PL_SELECT_MASK (0x0C000000) -#define MPI_SCSIDEVPAGE2_DPS_BIT_14_PL_SELECT_MASK (0x30000000) -#define MPI_SCSIDEVPAGE2_DPS_BIT_15_PL_SELECT_MASK (0xC0000000) - - -typedef struct _CONFIG_PAGE_SCSI_DEVICE_3 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U16 MsgRejectCount; /* 04h */ - U16 PhaseErrorCount; /* 06h */ - U16 ParityErrorCount; /* 08h */ - U16 Reserved; /* 0Ah */ -} fCONFIG_PAGE_SCSI_DEVICE_3, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_3, - SCSIDevicePage3_t, MPI_POINTER pSCSIDevicePage3_t; - -#define MPI_SCSIDEVPAGE3_PAGEVERSION (0x00) - -#define MPI_SCSIDEVPAGE3_MAX_COUNTER (0xFFFE) -#define MPI_SCSIDEVPAGE3_UNSUPPORTED_COUNTER (0xFFFF) - - -/**************************************************************************** -* FC Port Config Pages -****************************************************************************/ - -typedef struct _CONFIG_PAGE_FC_PORT_0 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 Flags; /* 04h */ - U8 MPIPortNumber; /* 08h */ - U8 LinkType; /* 09h */ - U8 PortState; /* 0Ah */ - U8 Reserved; /* 0Bh */ - U32 PortIdentifier; /* 0Ch */ - U64 WWNN; /* 10h */ - U64 WWPN; /* 18h */ - U32 SupportedServiceClass; /* 20h */ - U32 SupportedSpeeds; /* 24h */ - U32 CurrentSpeed; /* 28h */ - U32 MaxFrameSize; /* 2Ch */ - U64 FabricWWNN; /* 30h */ - U64 FabricWWPN; /* 38h */ - U32 DiscoveredPortsCount; /* 40h */ - U32 MaxInitiators; /* 44h */ - U8 MaxAliasesSupported; /* 48h */ - U8 MaxHardAliasesSupported; /* 49h */ - U8 NumCurrentAliases; /* 4Ah */ - U8 Reserved1; /* 4Bh */ -} fCONFIG_PAGE_FC_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_0, - FCPortPage0_t, MPI_POINTER pFCPortPage0_t; - -#define MPI_FCPORTPAGE0_PAGEVERSION (0x02) - -#define MPI_FCPORTPAGE0_FLAGS_PROT_MASK (0x0000000F) -#define MPI_FCPORTPAGE0_FLAGS_PROT_FCP_INIT (MPI_PORTFACTS_PROTOCOL_INITIATOR) -#define MPI_FCPORTPAGE0_FLAGS_PROT_FCP_TARG (MPI_PORTFACTS_PROTOCOL_TARGET) -#define MPI_FCPORTPAGE0_FLAGS_PROT_LAN (MPI_PORTFACTS_PROTOCOL_LAN) -#define MPI_FCPORTPAGE0_FLAGS_PROT_LOGBUSADDR (MPI_PORTFACTS_PROTOCOL_LOGBUSADDR) - -#define MPI_FCPORTPAGE0_FLAGS_ALIAS_ALPA_SUPPORTED (0x00000010) -#define MPI_FCPORTPAGE0_FLAGS_ALIAS_WWN_SUPPORTED (0x00000020) -#define MPI_FCPORTPAGE0_FLAGS_FABRIC_WWN_VALID (0x00000030) - -#define MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK (0x00000F00) -#define MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT (0x00000000) -#define MPI_FCPORTPAGE0_FLAGS_ATTACH_POINT_TO_POINT (0x00000100) -#define MPI_FCPORTPAGE0_FLAGS_ATTACH_PRIVATE_LOOP (0x00000200) -#define MPI_FCPORTPAGE0_FLAGS_ATTACH_FABRIC_DIRECT (0x00000400) -#define MPI_FCPORTPAGE0_FLAGS_ATTACH_PUBLIC_LOOP (0x00000800) - -#define MPI_FCPORTPAGE0_LTYPE_RESERVED (0x00) -#define MPI_FCPORTPAGE0_LTYPE_OTHER (0x01) -#define MPI_FCPORTPAGE0_LTYPE_UNKNOWN (0x02) -#define MPI_FCPORTPAGE0_LTYPE_COPPER (0x03) -#define MPI_FCPORTPAGE0_LTYPE_SINGLE_1300 (0x04) -#define MPI_FCPORTPAGE0_LTYPE_SINGLE_1500 (0x05) -#define MPI_FCPORTPAGE0_LTYPE_50_LASER_MULTI (0x06) -#define MPI_FCPORTPAGE0_LTYPE_50_LED_MULTI (0x07) -#define MPI_FCPORTPAGE0_LTYPE_62_LASER_MULTI (0x08) -#define MPI_FCPORTPAGE0_LTYPE_62_LED_MULTI (0x09) -#define MPI_FCPORTPAGE0_LTYPE_MULTI_LONG_WAVE (0x0A) -#define MPI_FCPORTPAGE0_LTYPE_MULTI_SHORT_WAVE (0x0B) -#define MPI_FCPORTPAGE0_LTYPE_LASER_SHORT_WAVE (0x0C) -#define MPI_FCPORTPAGE0_LTYPE_LED_SHORT_WAVE (0x0D) -#define MPI_FCPORTPAGE0_LTYPE_1300_LONG_WAVE (0x0E) -#define MPI_FCPORTPAGE0_LTYPE_1500_LONG_WAVE (0x0F) - -#define MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN (0x01) /*(SNIA)HBA_PORTSTATE_UNKNOWN 1 Unknown */ -#define MPI_FCPORTPAGE0_PORTSTATE_ONLINE (0x02) /*(SNIA)HBA_PORTSTATE_ONLINE 2 Operational */ -#define MPI_FCPORTPAGE0_PORTSTATE_OFFLINE (0x03) /*(SNIA)HBA_PORTSTATE_OFFLINE 3 User Offline */ -#define MPI_FCPORTPAGE0_PORTSTATE_BYPASSED (0x04) /*(SNIA)HBA_PORTSTATE_BYPASSED 4 Bypassed */ -#define MPI_FCPORTPAGE0_PORTSTATE_DIAGNOST (0x05) /*(SNIA)HBA_PORTSTATE_DIAGNOSTICS 5 In diagnostics mode */ -#define MPI_FCPORTPAGE0_PORTSTATE_LINKDOWN (0x06) /*(SNIA)HBA_PORTSTATE_LINKDOWN 6 Link Down */ -#define MPI_FCPORTPAGE0_PORTSTATE_ERROR (0x07) /*(SNIA)HBA_PORTSTATE_ERROR 7 Port Error */ -#define MPI_FCPORTPAGE0_PORTSTATE_LOOPBACK (0x08) /*(SNIA)HBA_PORTSTATE_LOOPBACK 8 Loopback */ - -#define MPI_FCPORTPAGE0_SUPPORT_CLASS_1 (0x00000001) -#define MPI_FCPORTPAGE0_SUPPORT_CLASS_2 (0x00000002) -#define MPI_FCPORTPAGE0_SUPPORT_CLASS_3 (0x00000004) - -#define MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED (0x00000001) /* (SNIA)HBA_PORTSPEED_1GBIT 1 1 GBit/sec */ -#define MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED (0x00000002) /* (SNIA)HBA_PORTSPEED_2GBIT 2 2 GBit/sec */ -#define MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED (0x00000004) /* (SNIA)HBA_PORTSPEED_10GBIT 4 10 GBit/sec */ - -#define MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED -#define MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED -#define MPI_FCPORTPAGE0_CURRENT_SPEED_10GBIT MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED - - -typedef struct _CONFIG_PAGE_FC_PORT_1 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 Flags; /* 04h */ - U64 NoSEEPROMWWNN; /* 08h */ - U64 NoSEEPROMWWPN; /* 10h */ - U8 HardALPA; /* 18h */ - U8 LinkConfig; /* 19h */ - U8 TopologyConfig; /* 1Ah */ - U8 AltConnector; /* 1Bh */ - U8 NumRequestedAliases; /* 1Ch */ - U8 Reserved1; /* 1Dh */ - U16 Reserved2; /* 1Eh */ -} fCONFIG_PAGE_FC_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_1, - FCPortPage1_t, MPI_POINTER pFCPortPage1_t; - -#define MPI_FCPORTPAGE1_PAGEVERSION (0x04) - -#define MPI_FCPORTPAGE1_FLAGS_EXT_FCP_STATUS_EN (0x08000000) -#define MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY (0x04000000) -#define MPI_FCPORTPAGE1_FLAGS_SORT_BY_DID (0x00000001) -#define MPI_FCPORTPAGE1_FLAGS_SORT_BY_WWN (0x00000000) - -#define MPI_FCPORTPAGE1_FLAGS_PROT_MASK (0xF0000000) -#define MPI_FCPORTPAGE1_FLAGS_PROT_SHIFT (28) -#define MPI_FCPORTPAGE1_FLAGS_PROT_FCP_INIT ((U32)MPI_PORTFACTS_PROTOCOL_INITIATOR << MPI_FCPORTPAGE1_FLAGS_PROT_SHIFT) -#define MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG ((U32)MPI_PORTFACTS_PROTOCOL_TARGET << MPI_FCPORTPAGE1_FLAGS_PROT_SHIFT) -#define MPI_FCPORTPAGE1_FLAGS_PROT_LAN ((U32)MPI_PORTFACTS_PROTOCOL_LAN << MPI_FCPORTPAGE1_FLAGS_PROT_SHIFT) -#define MPI_FCPORTPAGE1_FLAGS_PROT_LOGBUSADDR ((U32)MPI_PORTFACTS_PROTOCOL_LOGBUSADDR << MPI_FCPORTPAGE1_FLAGS_PROT_SHIFT) - -#define MPI_FCPORTPAGE1_HARD_ALPA_NOT_USED (0xFF) - -#define MPI_FCPORTPAGE1_LCONFIG_SPEED_MASK (0x0F) -#define MPI_FCPORTPAGE1_LCONFIG_SPEED_1GIG (0x00) -#define MPI_FCPORTPAGE1_LCONFIG_SPEED_2GIG (0x01) -#define MPI_FCPORTPAGE1_LCONFIG_SPEED_4GIG (0x02) -#define MPI_FCPORTPAGE1_LCONFIG_SPEED_10GIG (0x03) -#define MPI_FCPORTPAGE1_LCONFIG_SPEED_AUTO (0x0F) - -#define MPI_FCPORTPAGE1_TOPOLOGY_MASK (0x0F) -#define MPI_FCPORTPAGE1_TOPOLOGY_NLPORT (0x01) -#define MPI_FCPORTPAGE1_TOPOLOGY_NPORT (0x02) -#define MPI_FCPORTPAGE1_TOPOLOGY_AUTO (0x0F) - -#define MPI_FCPORTPAGE1_ALT_CONN_UNKNOWN (0x00) - - -typedef struct _CONFIG_PAGE_FC_PORT_2 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U8 NumberActive; /* 04h */ - U8 ALPA[127]; /* 05h */ -} fCONFIG_PAGE_FC_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_2, - FCPortPage2_t, MPI_POINTER pFCPortPage2_t; - -#define MPI_FCPORTPAGE2_PAGEVERSION (0x01) - - -typedef struct _WWN_FORMAT -{ - U64 WWNN; /* 00h */ - U64 WWPN; /* 08h */ -} WWN_FORMAT, MPI_POINTER PTR_WWN_FORMAT, - WWNFormat, MPI_POINTER pWWNFormat; - -typedef union _FC_PORT_PERSISTENT_PHYSICAL_ID -{ - WWN_FORMAT WWN; - U32 Did; -} FC_PORT_PERSISTENT_PHYSICAL_ID, MPI_POINTER PTR_FC_PORT_PERSISTENT_PHYSICAL_ID, - PersistentPhysicalId_t, MPI_POINTER pPersistentPhysicalId_t; - -typedef struct _FC_PORT_PERSISTENT -{ - FC_PORT_PERSISTENT_PHYSICAL_ID PhysicalIdentifier; /* 00h */ - U8 TargetID; /* 10h */ - U8 Bus; /* 11h */ - U16 Flags; /* 12h */ -} FC_PORT_PERSISTENT, MPI_POINTER PTR_FC_PORT_PERSISTENT, - PersistentData_t, MPI_POINTER pPersistentData_t; - -#define MPI_PERSISTENT_FLAGS_SHIFT (16) -#define MPI_PERSISTENT_FLAGS_ENTRY_VALID (0x0001) -#define MPI_PERSISTENT_FLAGS_SCAN_ID (0x0002) -#define MPI_PERSISTENT_FLAGS_SCAN_LUNS (0x0004) -#define MPI_PERSISTENT_FLAGS_BOOT_DEVICE (0x0008) -#define MPI_PERSISTENT_FLAGS_BY_DID (0x0080) - -/* - * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength at runtime. - */ -#ifndef MPI_FC_PORT_PAGE_3_ENTRY_MAX -#define MPI_FC_PORT_PAGE_3_ENTRY_MAX (1) -#endif - -typedef struct _CONFIG_PAGE_FC_PORT_3 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - FC_PORT_PERSISTENT Entry[MPI_FC_PORT_PAGE_3_ENTRY_MAX]; /* 04h */ -} fCONFIG_PAGE_FC_PORT_3, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_3, - FCPortPage3_t, MPI_POINTER pFCPortPage3_t; - -#define MPI_FCPORTPAGE3_PAGEVERSION (0x01) - - -typedef struct _CONFIG_PAGE_FC_PORT_4 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 PortFlags; /* 04h */ - U32 PortSettings; /* 08h */ -} fCONFIG_PAGE_FC_PORT_4, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_4, - FCPortPage4_t, MPI_POINTER pFCPortPage4_t; - -#define MPI_FCPORTPAGE4_PAGEVERSION (0x00) - -#define MPI_FCPORTPAGE4_PORT_FLAGS_ALTERNATE_CHS (0x00000008) - -#define MPI_FCPORTPAGE4_PORT_MASK_INIT_HBA (0x00000030) -#define MPI_FCPORTPAGE4_PORT_DISABLE_INIT_HBA (0x00000000) -#define MPI_FCPORTPAGE4_PORT_BIOS_INIT_HBA (0x00000010) -#define MPI_FCPORTPAGE4_PORT_OS_INIT_HBA (0x00000020) -#define MPI_FCPORTPAGE4_PORT_BIOS_OS_INIT_HBA (0x00000030) -#define MPI_FCPORTPAGE4_PORT_REMOVABLE_MEDIA (0x000000C0) -#define MPI_FCPORTPAGE4_PORT_SPINUP_DELAY_MASK (0x00000F00) - - -typedef struct _CONFIG_PAGE_FC_PORT_5_ALIAS_INFO -{ - U8 Flags; /* 00h */ - U8 AliasAlpa; /* 01h */ - U16 Reserved; /* 02h */ - U64 AliasWWNN; /* 04h */ - U64 AliasWWPN; /* 0Ch */ -} fCONFIG_PAGE_FC_PORT_5_ALIAS_INFO, - MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5_ALIAS_INFO, - FcPortPage5AliasInfo_t, MPI_POINTER pFcPortPage5AliasInfo_t; - -typedef struct _CONFIG_PAGE_FC_PORT_5 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - fCONFIG_PAGE_FC_PORT_5_ALIAS_INFO AliasInfo; /* 04h */ -} fCONFIG_PAGE_FC_PORT_5, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5, - FCPortPage5_t, MPI_POINTER pFCPortPage5_t; - -#define MPI_FCPORTPAGE5_PAGEVERSION (0x01) - -#define MPI_FCPORTPAGE5_FLAGS_ALPA_ACQUIRED (0x01) -#define MPI_FCPORTPAGE5_FLAGS_HARD_ALPA (0x02) -#define MPI_FCPORTPAGE5_FLAGS_HARD_WWNN (0x04) -#define MPI_FCPORTPAGE5_FLAGS_HARD_WWPN (0x08) - -typedef struct _CONFIG_PAGE_FC_PORT_6 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 Reserved; /* 04h */ - U64 TimeSinceReset; /* 08h */ - U64 TxFrames; /* 10h */ - U64 RxFrames; /* 18h */ - U64 TxWords; /* 20h */ - U64 RxWords; /* 28h */ - U64 LipCount; /* 30h */ - U64 NosCount; /* 38h */ - U64 ErrorFrames; /* 40h */ - U64 DumpedFrames; /* 48h */ - U64 LinkFailureCount; /* 50h */ - U64 LossOfSyncCount; /* 58h */ - U64 LossOfSignalCount; /* 60h */ - U64 PrimativeSeqErrCount; /* 68h */ - U64 InvalidTxWordCount; /* 70h */ - U64 InvalidCrcCount; /* 78h */ - U64 FcpInitiatorIoCount; /* 80h */ -} fCONFIG_PAGE_FC_PORT_6, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_6, - FCPortPage6_t, MPI_POINTER pFCPortPage6_t; - -#define MPI_FCPORTPAGE6_PAGEVERSION (0x00) - - -typedef struct _CONFIG_PAGE_FC_PORT_7 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 Reserved; /* 04h */ - U8 PortSymbolicName[256]; /* 08h */ -} fCONFIG_PAGE_FC_PORT_7, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_7, - FCPortPage7_t, MPI_POINTER pFCPortPage7_t; - -#define MPI_FCPORTPAGE7_PAGEVERSION (0x00) - - -typedef struct _CONFIG_PAGE_FC_PORT_8 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 BitVector[8]; /* 04h */ -} fCONFIG_PAGE_FC_PORT_8, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_8, - FCPortPage8_t, MPI_POINTER pFCPortPage8_t; - -#define MPI_FCPORTPAGE8_PAGEVERSION (0x00) - - -typedef struct _CONFIG_PAGE_FC_PORT_9 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U32 Reserved; /* 04h */ - U64 GlobalWWPN; /* 08h */ - U64 GlobalWWNN; /* 10h */ - U32 UnitType; /* 18h */ - U32 PhysicalPortNumber; /* 1Ch */ - U32 NumAttachedNodes; /* 20h */ - U16 IPVersion; /* 24h */ - U16 UDPPortNumber; /* 26h */ - U8 IPAddress[16]; /* 28h */ - U16 Reserved1; /* 38h */ - U16 TopologyDiscoveryFlags; /* 3Ah */ -} fCONFIG_PAGE_FC_PORT_9, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_9, - FCPortPage9_t, MPI_POINTER pFCPortPage9_t; - -#define MPI_FCPORTPAGE9_PAGEVERSION (0x00) - - -typedef struct _CONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA -{ - U8 Id; /* 10h */ - U8 ExtId; /* 11h */ - U8 Connector; /* 12h */ - U8 Transceiver[8]; /* 13h */ - U8 Encoding; /* 1Bh */ - U8 BitRate_100mbs; /* 1Ch */ - U8 Reserved1; /* 1Dh */ - U8 Length9u_km; /* 1Eh */ - U8 Length9u_100m; /* 1Fh */ - U8 Length50u_10m; /* 20h */ - U8 Length62p5u_10m; /* 21h */ - U8 LengthCopper_m; /* 22h */ - U8 Reseverved2; /* 22h */ - U8 VendorName[16]; /* 24h */ - U8 Reserved3; /* 34h */ - U8 VendorOUI[3]; /* 35h */ - U8 VendorPN[16]; /* 38h */ - U8 VendorRev[4]; /* 48h */ - U16 Reserved4; /* 4Ch */ - U8 Reserved5; /* 4Eh */ - U8 CC_BASE; /* 4Fh */ -} fCONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA, - MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA, - FCPortPage10BaseSfpData_t, MPI_POINTER pFCPortPage10BaseSfpData_t; - -#define MPI_FCPORT10_BASE_ID_UNKNOWN (0x00) -#define MPI_FCPORT10_BASE_ID_GBIC (0x01) -#define MPI_FCPORT10_BASE_ID_FIXED (0x02) -#define MPI_FCPORT10_BASE_ID_SFP (0x03) -#define MPI_FCPORT10_BASE_ID_SFP_MIN (0x04) -#define MPI_FCPORT10_BASE_ID_SFP_MAX (0x7F) -#define MPI_FCPORT10_BASE_ID_VEND_SPEC_MASK (0x80) - -#define MPI_FCPORT10_BASE_EXTID_UNKNOWN (0x00) -#define MPI_FCPORT10_BASE_EXTID_MODDEF1 (0x01) -#define MPI_FCPORT10_BASE_EXTID_MODDEF2 (0x02) -#define MPI_FCPORT10_BASE_EXTID_MODDEF3 (0x03) -#define MPI_FCPORT10_BASE_EXTID_SEEPROM (0x04) -#define MPI_FCPORT10_BASE_EXTID_MODDEF5 (0x05) -#define MPI_FCPORT10_BASE_EXTID_MODDEF6 (0x06) -#define MPI_FCPORT10_BASE_EXTID_MODDEF7 (0x07) -#define MPI_FCPORT10_BASE_EXTID_VNDSPC_MASK (0x80) - -#define MPI_FCPORT10_BASE_CONN_UNKNOWN (0x00) -#define MPI_FCPORT10_BASE_CONN_SC (0x01) -#define MPI_FCPORT10_BASE_CONN_COPPER1 (0x02) -#define MPI_FCPORT10_BASE_CONN_COPPER2 (0x03) -#define MPI_FCPORT10_BASE_CONN_BNC_TNC (0x04) -#define MPI_FCPORT10_BASE_CONN_COAXIAL (0x05) -#define MPI_FCPORT10_BASE_CONN_FIBERJACK (0x06) -#define MPI_FCPORT10_BASE_CONN_LC (0x07) -#define MPI_FCPORT10_BASE_CONN_MT_RJ (0x08) -#define MPI_FCPORT10_BASE_CONN_MU (0x09) -#define MPI_FCPORT10_BASE_CONN_SG (0x0A) -#define MPI_FCPORT10_BASE_CONN_OPT_PIGT (0x0B) -#define MPI_FCPORT10_BASE_CONN_RSV1_MIN (0x0C) -#define MPI_FCPORT10_BASE_CONN_RSV1_MAX (0x1F) -#define MPI_FCPORT10_BASE_CONN_HSSDC_II (0x20) -#define MPI_FCPORT10_BASE_CONN_CPR_PIGT (0x21) -#define MPI_FCPORT10_BASE_CONN_RSV2_MIN (0x22) -#define MPI_FCPORT10_BASE_CONN_RSV2_MAX (0x7F) -#define MPI_FCPORT10_BASE_CONN_VNDSPC_MASK (0x80) - -#define MPI_FCPORT10_BASE_ENCODE_UNSPEC (0x00) -#define MPI_FCPORT10_BASE_ENCODE_8B10B (0x01) -#define MPI_FCPORT10_BASE_ENCODE_4B5B (0x02) -#define MPI_FCPORT10_BASE_ENCODE_NRZ (0x03) -#define MPI_FCPORT10_BASE_ENCODE_MANCHESTER (0x04) - - -typedef struct _CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA -{ - U8 Options[2]; /* 50h */ - U8 BitRateMax; /* 52h */ - U8 BitRateMin; /* 53h */ - U8 VendorSN[16]; /* 54h */ - U8 DateCode[8]; /* 64h */ - U8 Reserved5[3]; /* 6Ch */ - U8 CC_EXT; /* 6Fh */ -} fCONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA, - MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA, - FCPortPage10ExtendedSfpData_t, MPI_POINTER pFCPortPage10ExtendedSfpData_t; - -#define MPI_FCPORT10_EXT_OPTION1_RATESEL (0x20) -#define MPI_FCPORT10_EXT_OPTION1_TX_DISABLE (0x10) -#define MPI_FCPORT10_EXT_OPTION1_TX_FAULT (0x08) -#define MPI_FCPORT10_EXT_OPTION1_LOS_INVERT (0x04) -#define MPI_FCPORT10_EXT_OPTION1_LOS (0x02) - - -typedef struct _CONFIG_PAGE_FC_PORT_10 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U8 Flags; /* 04h */ - U8 Reserved1; /* 05h */ - U16 Reserved2; /* 06h */ - U32 HwConfig1; /* 08h */ - U32 HwConfig2; /* 0Ch */ - fCONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA Base; /* 10h */ - fCONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA Extended; /* 50h */ - U8 VendorSpecific[32]; /* 70h */ -} fCONFIG_PAGE_FC_PORT_10, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10, - FCPortPage10_t, MPI_POINTER pFCPortPage10_t; - -#define MPI_FCPORTPAGE10_PAGEVERSION (0x00) - -/* standard MODDEF pin definitions (from GBIC spec.) */ -#define MPI_FCPORTPAGE10_FLAGS_MODDEF_MASK (0x00000007) -#define MPI_FCPORTPAGE10_FLAGS_MODDEF2 (0x00000001) -#define MPI_FCPORTPAGE10_FLAGS_MODDEF1 (0x00000002) -#define MPI_FCPORTPAGE10_FLAGS_MODDEF0 (0x00000004) -#define MPI_FCPORTPAGE10_FLAGS_MODDEF_NOGBIC (0x00000007) -#define MPI_FCPORTPAGE10_FLAGS_MODDEF_CPR_IEEE_CX (0x00000006) -#define MPI_FCPORTPAGE10_FLAGS_MODDEF_COPPER (0x00000005) -#define MPI_FCPORTPAGE10_FLAGS_MODDEF_OPTICAL_LW (0x00000004) -#define MPI_FCPORTPAGE10_FLAGS_MODDEF_SEEPROM (0x00000003) -#define MPI_FCPORTPAGE10_FLAGS_MODDEF_SW_OPTICAL (0x00000002) -#define MPI_FCPORTPAGE10_FLAGS_MODDEF_LX_IEEE_OPT_LW (0x00000001) -#define MPI_FCPORTPAGE10_FLAGS_MODDEF_SX_IEEE_OPT_SW (0x00000000) - -#define MPI_FCPORTPAGE10_FLAGS_CC_BASE_OK (0x00000010) -#define MPI_FCPORTPAGE10_FLAGS_CC_EXT_OK (0x00000020) - - -/**************************************************************************** -* FC Device Config Pages -****************************************************************************/ - -typedef struct _CONFIG_PAGE_FC_DEVICE_0 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U64 WWNN; /* 04h */ - U64 WWPN; /* 0Ch */ - U32 PortIdentifier; /* 14h */ - U8 Protocol; /* 18h */ - U8 Flags; /* 19h */ - U16 BBCredit; /* 1Ah */ - U16 MaxRxFrameSize; /* 1Ch */ - U8 Reserved1; /* 1Eh */ - U8 PortNumber; /* 1Fh */ - U8 FcPhLowestVersion; /* 20h */ - U8 FcPhHighestVersion; /* 21h */ - U8 CurrentTargetID; /* 22h */ - U8 CurrentBus; /* 23h */ -} fCONFIG_PAGE_FC_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_FC_DEVICE_0, - FCDevicePage0_t, MPI_POINTER pFCDevicePage0_t; - -#define MPI_FC_DEVICE_PAGE0_PAGEVERSION (0x02) - -#define MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID (0x01) - -#define MPI_FC_DEVICE_PAGE0_PROT_IP (0x01) -#define MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET (0x02) -#define MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR (0x04) - -#define MPI_FC_DEVICE_PAGE0_PGAD_PORT_MASK (MPI_FC_DEVICE_PGAD_PORT_MASK) -#define MPI_FC_DEVICE_PAGE0_PGAD_FORM_MASK (MPI_FC_DEVICE_PGAD_FORM_MASK) -#define MPI_FC_DEVICE_PAGE0_PGAD_FORM_NEXT_DID (MPI_FC_DEVICE_PGAD_FORM_NEXT_DID) -#define MPI_FC_DEVICE_PAGE0_PGAD_FORM_BUS_TID (MPI_FC_DEVICE_PGAD_FORM_BUS_TID) -#define MPI_FC_DEVICE_PAGE0_PGAD_DID_MASK (MPI_FC_DEVICE_PGAD_ND_DID_MASK) -#define MPI_FC_DEVICE_PAGE0_PGAD_BUS_MASK (MPI_FC_DEVICE_PGAD_BT_BUS_MASK) -#define MPI_FC_DEVICE_PAGE0_PGAD_BUS_SHIFT (MPI_FC_DEVICE_PGAD_BT_BUS_SHIFT) -#define MPI_FC_DEVICE_PAGE0_PGAD_TID_MASK (MPI_FC_DEVICE_PGAD_BT_TID_MASK) - - -/**************************************************************************** -* RAID Volume Config Pages -****************************************************************************/ - -typedef struct _RAID_VOL0_PHYS_DISK -{ - U16 Reserved; /* 00h */ - U8 PhysDiskMap; /* 02h */ - U8 PhysDiskNum; /* 03h */ -} RAID_VOL0_PHYS_DISK, MPI_POINTER PTR_RAID_VOL0_PHYS_DISK, - RaidVol0PhysDisk_t, MPI_POINTER pRaidVol0PhysDisk_t; - -#define MPI_RAIDVOL0_PHYSDISK_PRIMARY (0x01) -#define MPI_RAIDVOL0_PHYSDISK_SECONDARY (0x02) - -typedef struct _RAID_VOL0_STATUS -{ - U8 Flags; /* 00h */ - U8 State; /* 01h */ - U16 Reserved; /* 02h */ -} RAID_VOL0_STATUS, MPI_POINTER PTR_RAID_VOL0_STATUS, - RaidVol0Status_t, MPI_POINTER pRaidVol0Status_t; - -/* RAID Volume Page 0 VolumeStatus defines */ - -#define MPI_RAIDVOL0_STATUS_FLAG_ENABLED (0x01) -#define MPI_RAIDVOL0_STATUS_FLAG_QUIESCED (0x02) -#define MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS (0x04) -#define MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE (0x08) - -#define MPI_RAIDVOL0_STATUS_STATE_OPTIMAL (0x00) -#define MPI_RAIDVOL0_STATUS_STATE_DEGRADED (0x01) -#define MPI_RAIDVOL0_STATUS_STATE_FAILED (0x02) - -typedef struct _RAID_VOL0_SETTINGS -{ - U16 Settings; /* 00h */ - U8 HotSparePool; /* 01h */ /* MPI_RAID_HOT_SPARE_POOL_ */ - U8 Reserved; /* 02h */ -} RAID_VOL0_SETTINGS, MPI_POINTER PTR_RAID_VOL0_SETTINGS, - RaidVol0Settings, MPI_POINTER pRaidVol0Settings; - -/* RAID Volume Page 0 VolumeSettings defines */ - -#define MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE (0x0001) -#define MPI_RAIDVOL0_SETTING_OFFLINE_ON_SMART (0x0002) -#define MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE (0x0004) -#define MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC (0x0008) -#define MPI_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX (0x0010) -#define MPI_RAIDVOL0_SETTING_USE_DEFAULTS (0x8000) - -/* RAID Volume Page 0 HotSparePool defines, also used in RAID Physical Disk */ -#define MPI_RAID_HOT_SPARE_POOL_0 (0x01) -#define MPI_RAID_HOT_SPARE_POOL_1 (0x02) -#define MPI_RAID_HOT_SPARE_POOL_2 (0x04) -#define MPI_RAID_HOT_SPARE_POOL_3 (0x08) -#define MPI_RAID_HOT_SPARE_POOL_4 (0x10) -#define MPI_RAID_HOT_SPARE_POOL_5 (0x20) -#define MPI_RAID_HOT_SPARE_POOL_6 (0x40) -#define MPI_RAID_HOT_SPARE_POOL_7 (0x80) - -/* - * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength at runtime. - */ -#ifndef MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX -#define MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX (1) -#endif - -typedef struct _CONFIG_PAGE_RAID_VOL_0 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U8 VolumeID; /* 04h */ - U8 VolumeBus; /* 05h */ - U8 VolumeIOC; /* 06h */ - U8 VolumeType; /* 07h */ /* MPI_RAID_VOL_TYPE_ */ - RAID_VOL0_STATUS VolumeStatus; /* 08h */ - RAID_VOL0_SETTINGS VolumeSettings; /* 0Ch */ - U32 MaxLBA; /* 10h */ - U32 Reserved1; /* 14h */ - U32 StripeSize; /* 18h */ - U32 Reserved2; /* 1Ch */ - U32 Reserved3; /* 20h */ - U8 NumPhysDisks; /* 24h */ - U8 Reserved4; /* 25h */ - U16 Reserved5; /* 26h */ - RAID_VOL0_PHYS_DISK PhysDisk[MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX];/* 28h */ -} fCONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0, - RaidVolumePage0_t, MPI_POINTER pRaidVolumePage0_t; - -#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x01) - - -/**************************************************************************** -* RAID Physical Disk Config Pages -****************************************************************************/ - -typedef struct _RAID_PHYS_DISK0_ERROR_DATA -{ - U8 ErrorCdbByte; /* 00h */ - U8 ErrorSenseKey; /* 01h */ - U16 Reserved; /* 02h */ - U16 ErrorCount; /* 04h */ - U8 ErrorASC; /* 06h */ - U8 ErrorASCQ; /* 07h */ - U16 SmartCount; /* 08h */ - U8 SmartASC; /* 0Ah */ - U8 SmartASCQ; /* 0Bh */ -} RAID_PHYS_DISK0_ERROR_DATA, MPI_POINTER PTR_RAID_PHYS_DISK0_ERROR_DATA, - RaidPhysDisk0ErrorData_t, MPI_POINTER pRaidPhysDisk0ErrorData_t; - -typedef struct _RAID_PHYS_DISK_INQUIRY_DATA -{ - U8 VendorID[8]; /* 00h */ - U8 ProductID[16]; /* 08h */ - U8 ProductRevLevel[4]; /* 18h */ - U8 Info[32]; /* 1Ch */ -} RAID_PHYS_DISK0_INQUIRY_DATA, MPI_POINTER PTR_RAID_PHYS_DISK0_INQUIRY_DATA, - RaidPhysDisk0InquiryData, MPI_POINTER pRaidPhysDisk0InquiryData; - -typedef struct _RAID_PHYS_DISK0_SETTINGS -{ - U8 SepID; /* 00h */ - U8 SepBus; /* 01h */ - U8 HotSparePool; /* 02h */ /* MPI_RAID_HOT_SPARE_POOL_ */ - U8 PhysDiskSettings; /* 03h */ -} RAID_PHYS_DISK0_SETTINGS, MPI_POINTER PTR_RAID_PHYS_DISK0_SETTINGS, - RaidPhysDiskSettings_t, MPI_POINTER pRaidPhysDiskSettings_t; - -typedef struct _RAID_PHYS_DISK0_STATUS -{ - U8 Flags; /* 00h */ - U8 State; /* 01h */ - U16 Reserved; /* 02h */ -} RAID_PHYS_DISK0_STATUS, MPI_POINTER PTR_RAID_PHYS_DISK0_STATUS, - RaidPhysDiskStatus_t, MPI_POINTER pRaidPhysDiskStatus_t; - -/* RAID Volume 2 IM Physical Disk DiskStatus flags */ - -#define MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC (0x01) -#define MPI_PHYSDISK0_STATUS_FLAG_QUIESCED (0x02) - -#define MPI_PHYSDISK0_STATUS_ONLINE (0x00) -#define MPI_PHYSDISK0_STATUS_MISSING (0x01) -#define MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE (0x02) -#define MPI_PHYSDISK0_STATUS_FAILED (0x03) -#define MPI_PHYSDISK0_STATUS_INITIALIZING (0x04) -#define MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED (0x05) -#define MPI_PHYSDISK0_STATUS_FAILED_REQUESTED (0x06) -#define MPI_PHYSDISK0_STATUS_OTHER_OFFLINE (0xFF) - -typedef struct _CONFIG_PAGE_RAID_PHYS_DISK_0 -{ - fCONFIG_PAGE_HEADER Header; /* 00h */ - U8 PhysDiskID; /* 04h */ - U8 PhysDiskBus; /* 05h */ - U8 PhysDiskIOC; /* 06h */ - U8 PhysDiskNum; /* 07h */ - RAID_PHYS_DISK0_SETTINGS PhysDiskSettings; /* 08h */ - U32 Reserved1; /* 0Ch */ - U32 Reserved2; /* 10h */ - U32 Reserved3; /* 14h */ - U8 DiskIdentifier[16]; /* 18h */ - RAID_PHYS_DISK0_INQUIRY_DATA InquiryData; /* 28h */ - RAID_PHYS_DISK0_STATUS PhysDiskStatus; /* 64h */ - U32 MaxLBA; /* 68h */ - RAID_PHYS_DISK0_ERROR_DATA ErrorData; /* 6Ch */ -} fCONFIG_PAGE_RAID_PHYS_DISK_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_0, - RaidPhysDiskPage0_t, MPI_POINTER pRaidPhysDiskPage0_t; - -#define MPI_RAIDPHYSDISKPAGE0_PAGEVERSION (0x00) - - -/**************************************************************************** -* LAN Config Pages -****************************************************************************/ - -typedef struct _CONFIG_PAGE_LAN_0 -{ - ConfigPageHeader_t Header; /* 00h */ - U16 TxRxModes; /* 04h */ - U16 Reserved; /* 06h */ - U32 PacketPrePad; /* 08h */ -} fCONFIG_PAGE_LAN_0, MPI_POINTER PTR_CONFIG_PAGE_LAN_0, - LANPage0_t, MPI_POINTER pLANPage0_t; - -#define MPI_LAN_PAGE0_PAGEVERSION (0x01) - -#define MPI_LAN_PAGE0_RETURN_LOOPBACK (0x0000) -#define MPI_LAN_PAGE0_SUPPRESS_LOOPBACK (0x0001) -#define MPI_LAN_PAGE0_LOOPBACK_MASK (0x0001) - -typedef struct _CONFIG_PAGE_LAN_1 -{ - ConfigPageHeader_t Header; /* 00h */ - U16 Reserved; /* 04h */ - U8 CurrentDeviceState; /* 06h */ - U8 Reserved1; /* 07h */ - U32 MinPacketSize; /* 08h */ - U32 MaxPacketSize; /* 0Ch */ - U32 HardwareAddressLow; /* 10h */ - U32 HardwareAddressHigh; /* 14h */ - U32 MaxWireSpeedLow; /* 18h */ - U32 MaxWireSpeedHigh; /* 1Ch */ - U32 BucketsRemaining; /* 20h */ - U32 MaxReplySize; /* 24h */ - U32 NegWireSpeedLow; /* 28h */ - U32 NegWireSpeedHigh; /* 2Ch */ -} fCONFIG_PAGE_LAN_1, MPI_POINTER PTR_CONFIG_PAGE_LAN_1, - LANPage1_t, MPI_POINTER pLANPage1_t; - -#define MPI_LAN_PAGE1_PAGEVERSION (0x03) - -#define MPI_LAN_PAGE1_DEV_STATE_RESET (0x00) -#define MPI_LAN_PAGE1_DEV_STATE_OPERATIONAL (0x01) - -#endif - diff --git a/xen/drivers/message/fusion/lsi/mpi_fc.h b/xen/drivers/message/fusion/lsi/mpi_fc.h deleted file mode 100644 index 7873657ba3..0000000000 --- a/xen/drivers/message/fusion/lsi/mpi_fc.h +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (c) 2000-2002 LSI Logic Corporation. - * - * - * Name: MPI_FC.H - * Title: MPI Fibre Channel messages and structures - * Creation Date: June 12, 2000 - * - * MPI_FC.H Version: 01.02.03 - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. - * 06-06-00 01.00.01 Update version number for 1.0 release. - * 06-12-00 01.00.02 Added _MSG_FC_ABORT_REPLY structure. - * 11-02-00 01.01.01 Original release for post 1.0 work - * 12-04-00 01.01.02 Added messages for Common Transport Send and - * Primitive Send. - * 01-09-01 01.01.03 Modifed some of the new flags to have an MPI prefix - * and modified the FcPrimitiveSend flags. - * 01-25-01 01.01.04 Move InitiatorIndex in LinkServiceRsp reply to a larger - * field. - * Added FC_ABORT_TYPE_CT_SEND_REQUEST and - * FC_ABORT_TYPE_EXLINKSEND_REQUEST for FcAbort request. - * Added MPI_FC_PRIM_SEND_FLAGS_STOP_SEND. - * 02-20-01 01.01.05 Started using MPI_POINTER. - * 03-27-01 01.01.06 Added Flags field to MSG_LINK_SERVICE_BUFFER_POST_REPLY - * and defined MPI_LS_BUF_POST_REPLY_FLAG_NO_RSP_NEEDED. - * Added MPI_FC_PRIM_SEND_FLAGS_RESET_LINK define. - * Added structure offset comments. - * 04-09-01 01.01.07 Added RspLength field to MSG_LINK_SERVICE_RSP_REQUEST. - * 08-08-01 01.02.01 Original release for v1.2 work. - * 09-28-01 01.02.02 Change name of reserved field in - * MSG_LINK_SERVICE_RSP_REPLY. - * 05-31-02 01.02.03 Adding AliasIndex to FC Direct Access requests. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI_FC_H -#define MPI_FC_H - - -/***************************************************************************** -* -* F C T a r g e t M o d e M e s s a g e s -* -*****************************************************************************/ - -/****************************************************************************/ -/* Link Service Buffer Post messages */ -/****************************************************************************/ - -typedef struct _MSG_LINK_SERVICE_BUFFER_POST_REQUEST -{ - U8 BufferPostFlags; /* 00h */ - U8 BufferCount; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved; /* 04h */ - U8 Reserved1; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - SGE_TRANS_SIMPLE_UNION SGL; -} MSG_LINK_SERVICE_BUFFER_POST_REQUEST, - MPI_POINTER PTR_MSG_LINK_SERVICE_BUFFER_POST_REQUEST, - LinkServiceBufferPostRequest_t, MPI_POINTER pLinkServiceBufferPostRequest_t; - -#define LINK_SERVICE_BUFFER_POST_FLAGS_PORT_MASK (0x01) - -typedef struct _WWNFORMAT -{ - U32 PortNameHigh; /* 00h */ - U32 PortNameLow; /* 04h */ - U32 NodeNameHigh; /* 08h */ - U32 NodeNameLow; /* 0Ch */ -} WWNFORMAT, - WwnFormat_t; - -/* Link Service Buffer Post Reply */ -typedef struct _MSG_LINK_SERVICE_BUFFER_POST_REPLY -{ - U8 Flags; /* 00h */ - U8 Reserved; /* 01h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved1; /* 04h */ - U8 PortNumber; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved2; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 TransferLength; /* 14h */ - U32 TransactionContext; /* 18h */ - U32 Rctl_Did; /* 1Ch */ - U32 Csctl_Sid; /* 20h */ - U32 Type_Fctl; /* 24h */ - U16 SeqCnt; /* 28h */ - U8 Dfctl; /* 2Ah */ - U8 SeqId; /* 2Bh */ - U16 Rxid; /* 2Ch */ - U16 Oxid; /* 2Eh */ - U32 Parameter; /* 30h */ - WWNFORMAT Wwn; /* 34h */ -} MSG_LINK_SERVICE_BUFFER_POST_REPLY, MPI_POINTER PTR_MSG_LINK_SERVICE_BUFFER_POST_REPLY, - LinkServiceBufferPostReply_t, MPI_POINTER pLinkServiceBufferPostReply_t; - -#define MPI_LS_BUF_POST_REPLY_FLAG_NO_RSP_NEEDED (0x80) - -#define MPI_FC_DID_MASK (0x00FFFFFF) -#define MPI_FC_DID_SHIFT (0) -#define MPI_FC_RCTL_MASK (0xFF000000) -#define MPI_FC_RCTL_SHIFT (24) -#define MPI_FC_SID_MASK (0x00FFFFFF) -#define MPI_FC_SID_SHIFT (0) -#define MPI_FC_CSCTL_MASK (0xFF000000) -#define MPI_FC_CSCTL_SHIFT (24) -#define MPI_FC_FCTL_MASK (0x00FFFFFF) -#define MPI_FC_FCTL_SHIFT (0) -#define MPI_FC_TYPE_MASK (0xFF000000) -#define MPI_FC_TYPE_SHIFT (24) - -/* obsolete name for the above */ -#define FCP_TARGET_DID_MASK (0x00FFFFFF) -#define FCP_TARGET_DID_SHIFT (0) -#define FCP_TARGET_RCTL_MASK (0xFF000000) -#define FCP_TARGET_RCTL_SHIFT (24) -#define FCP_TARGET_SID_MASK (0x00FFFFFF) -#define FCP_TARGET_SID_SHIFT (0) -#define FCP_TARGET_CSCTL_MASK (0xFF000000) -#define FCP_TARGET_CSCTL_SHIFT (24) -#define FCP_TARGET_FCTL_MASK (0x00FFFFFF) -#define FCP_TARGET_FCTL_SHIFT (0) -#define FCP_TARGET_TYPE_MASK (0xFF000000) -#define FCP_TARGET_TYPE_SHIFT (24) - - -/****************************************************************************/ -/* Link Service Response messages */ -/****************************************************************************/ - -typedef struct _MSG_LINK_SERVICE_RSP_REQUEST -{ - U8 RspFlags; /* 00h */ - U8 RspLength; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved1; /* 04h */ - U8 Reserved2; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U32 Rctl_Did; /* 0Ch */ - U32 Csctl_Sid; /* 10h */ - U32 Type_Fctl; /* 14h */ - U16 SeqCnt; /* 18h */ - U8 Dfctl; /* 1Ah */ - U8 SeqId; /* 1Bh */ - U16 Rxid; /* 1Ch */ - U16 Oxid; /* 1Eh */ - U32 Parameter; /* 20h */ - SGE_SIMPLE_UNION SGL; /* 24h */ -} MSG_LINK_SERVICE_RSP_REQUEST, MPI_POINTER PTR_MSG_LINK_SERVICE_RSP_REQUEST, - LinkServiceRspRequest_t, MPI_POINTER pLinkServiceRspRequest_t; - -#define LINK_SERVICE_RSP_FLAGS_IMMEDIATE (0x80) -#define LINK_SERVICE_RSP_FLAGS_PORT_MASK (0x01) - - -/* Link Service Response Reply */ -typedef struct _MSG_LINK_SERVICE_RSP_REPLY -{ - U16 Reserved; /* 00h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved1; /* 04h */ - U8 Reserved_0100_InitiatorIndex; /* 06h */ /* obsolete InitiatorIndex */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved3; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 InitiatorIndex; /* 14h */ -} MSG_LINK_SERVICE_RSP_REPLY, MPI_POINTER PTR_MSG_LINK_SERVICE_RSP_REPLY, - LinkServiceRspReply_t, MPI_POINTER pLinkServiceRspReply_t; - - -/****************************************************************************/ -/* Extended Link Service Send messages */ -/****************************************************************************/ - -typedef struct _MSG_EXLINK_SERVICE_SEND_REQUEST -{ - U8 SendFlags; /* 00h */ - U8 AliasIndex; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U32 MsgFlags_Did; /* 04h */ - U32 MsgContext; /* 08h */ - U32 ElsCommandCode; /* 0Ch */ - SGE_SIMPLE_UNION SGL; /* 10h */ -} MSG_EXLINK_SERVICE_SEND_REQUEST, MPI_POINTER PTR_MSG_EXLINK_SERVICE_SEND_REQUEST, - ExLinkServiceSendRequest_t, MPI_POINTER pExLinkServiceSendRequest_t; - -#define EX_LINK_SERVICE_SEND_DID_MASK (0x00FFFFFF) -#define EX_LINK_SERVICE_SEND_DID_SHIFT (0) -#define EX_LINK_SERVICE_SEND_MSGFLAGS_MASK (0xFF000000) -#define EX_LINK_SERVICE_SEND_MSGFLAGS_SHIFT (24) - - -/* Extended Link Service Send Reply */ -typedef struct _MSG_EXLINK_SERVICE_SEND_REPLY -{ - U8 Reserved; /* 00h */ - U8 AliasIndex; /* 01h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved1; /* 04h */ - U8 Reserved2; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved3; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 ResponseLength; /* 14h */ -} MSG_EXLINK_SERVICE_SEND_REPLY, MPI_POINTER PTR_MSG_EXLINK_SERVICE_SEND_REPLY, - ExLinkServiceSendReply_t, MPI_POINTER pExLinkServiceSendReply_t; - -/****************************************************************************/ -/* FC Abort messages */ -/****************************************************************************/ - -typedef struct _MSG_FC_ABORT_REQUEST -{ - U8 AbortFlags; /* 00h */ - U8 AbortType; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved1; /* 04h */ - U8 Reserved2; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U32 TransactionContextToAbort; /* 0Ch */ -} MSG_FC_ABORT_REQUEST, MPI_POINTER PTR_MSG_FC_ABORT_REQUEST, - FcAbortRequest_t, MPI_POINTER pFcAbortRequest_t; - -#define FC_ABORT_FLAG_PORT_MASK (0x01) - -#define FC_ABORT_TYPE_ALL_FC_BUFFERS (0x00) -#define FC_ABORT_TYPE_EXACT_FC_BUFFER (0x01) -#define FC_ABORT_TYPE_CT_SEND_REQUEST (0x02) -#define FC_ABORT_TYPE_EXLINKSEND_REQUEST (0x03) - -/* FC Abort Reply */ -typedef struct _MSG_FC_ABORT_REPLY -{ - U16 Reserved; /* 00h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved1; /* 04h */ - U8 Reserved2; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved3; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ -} MSG_FC_ABORT_REPLY, MPI_POINTER PTR_MSG_FC_ABORT_REPLY, - FcAbortReply_t, MPI_POINTER pFcAbortReply_t; - - -/****************************************************************************/ -/* FC Common Transport Send messages */ -/****************************************************************************/ - -typedef struct _MSG_FC_COMMON_TRANSPORT_SEND_REQUEST -{ - U8 SendFlags; /* 00h */ - U8 AliasIndex; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U32 MsgFlags_Did; /* 04h */ - U32 MsgContext; /* 08h */ - U16 CTCommandCode; /* 0Ch */ - U8 FsType; /* 0Eh */ - U8 Reserved1; /* 0Fh */ - SGE_SIMPLE_UNION SGL; /* 10h */ -} MSG_FC_COMMON_TRANSPORT_SEND_REQUEST, - MPI_POINTER PTR_MSG_FC_COMMON_TRANSPORT_SEND_REQUEST, - FcCommonTransportSendRequest_t, MPI_POINTER pFcCommonTransportSendRequest_t; - -#define MPI_FC_CT_SEND_DID_MASK (0x00FFFFFF) -#define MPI_FC_CT_SEND_DID_SHIFT (0) -#define MPI_FC_CT_SEND_MSGFLAGS_MASK (0xFF000000) -#define MPI_FC_CT_SEND_MSGFLAGS_SHIFT (24) - - -/* FC Common Transport Send Reply */ -typedef struct _MSG_FC_COMMON_TRANSPORT_SEND_REPLY -{ - U8 Reserved; /* 00h */ - U8 AliasIndex; /* 01h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved1; /* 04h */ - U8 Reserved2; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved3; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 ResponseLength; /* 14h */ -} MSG_FC_COMMON_TRANSPORT_SEND_REPLY, MPI_POINTER PTR_MSG_FC_COMMON_TRANSPORT_SEND_REPLY, - FcCommonTransportSendReply_t, MPI_POINTER pFcCommonTransportSendReply_t; - - -/****************************************************************************/ -/* FC Primitive Send messages */ -/****************************************************************************/ - -typedef struct _MSG_FC_PRIMITIVE_SEND_REQUEST -{ - U8 SendFlags; /* 00h */ - U8 Reserved; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved1; /* 04h */ - U8 Reserved2; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U8 FcPrimitive[4]; /* 0Ch */ -} MSG_FC_PRIMITIVE_SEND_REQUEST, MPI_POINTER PTR_MSG_FC_PRIMITIVE_SEND_REQUEST, - FcPrimitiveSendRequest_t, MPI_POINTER pFcPrimitiveSendRequest_t; - -#define MPI_FC_PRIM_SEND_FLAGS_PORT_MASK (0x01) -#define MPI_FC_PRIM_SEND_FLAGS_RESET_LINK (0x04) -#define MPI_FC_PRIM_SEND_FLAGS_STOP_SEND (0x08) -#define MPI_FC_PRIM_SEND_FLAGS_SEND_ONCE (0x10) -#define MPI_FC_PRIM_SEND_FLAGS_SEND_AROUND (0x20) -#define MPI_FC_PRIM_SEND_FLAGS_UNTIL_FULL (0x40) -#define MPI_FC_PRIM_SEND_FLAGS_FOREVER (0x80) - -/* FC Primitive Send Reply */ -typedef struct _MSG_FC_PRIMITIVE_SEND_REPLY -{ - U8 SendFlags; /* 00h */ - U8 Reserved; /* 01h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved1; /* 04h */ - U8 Reserved2; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved3; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ -} MSG_FC_PRIMITIVE_SEND_REPLY, MPI_POINTER PTR_MSG_FC_PRIMITIVE_SEND_REPLY, - FcPrimitiveSendReply_t, MPI_POINTER pFcPrimitiveSendReply_t; - -#endif - diff --git a/xen/drivers/message/fusion/lsi/mpi_history.txt b/xen/drivers/message/fusion/lsi/mpi_history.txt deleted file mode 100644 index 0deb7721e9..0000000000 --- a/xen/drivers/message/fusion/lsi/mpi_history.txt +++ /dev/null @@ -1,276 +0,0 @@ - - ============================== - MPI Header File Change History - ============================== - - Copyright (c) 2000-2001 LSI Logic Corporation. - - --------------------------------------- - Header Set Release Version: 01.01.10 - Header Set Release Date: 04-09-01 - --------------------------------------- - - Filename Current version Prior version - ---------- --------------- ------------- - mpi.h 01.01.07 01.01.06 - mpi_ioc.h 01.01.07 01.01.06 - mpi_cnfg.h 01.01.11 01.01.10 - mpi_init.h 01.01.05 01.01.04 - mpi_targ.h 01.01.04 01.01.04 - mpi_fc.h 01.01.07 01.01.06 - mpi_lan.h 01.01.03 01.01.03 - mpi_raid.h 01.01.02 01.01.02 - mpi_type.h 01.01.02 01.01.02 - mpi_history.txt 01.01.09 01.01.09 - - - * Date Version Description - * -------- -------- ------------------------------------------------------ - -mpi.h - * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. - * 05-24-00 00.10.02 Added MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH definition. - * 06-06-00 01.00.01 Update MPI_VERSION_MAJOR and MPI_VERSION_MINOR. - * 06-22-00 01.00.02 Added MPI_IOCSTATUS_LAN_ definitions. - * Removed LAN_SUSPEND function definition. - * Added MPI_MSGFLAGS_CONTINUATION_REPLY definition. - * 06-30-00 01.00.03 Added MPI_CONTEXT_REPLY_TYPE_LAN definition. - * Added MPI_GET/SET_CONTEXT_REPLY_TYPE macros. - * 07-27-00 01.00.04 Added MPI_FAULT_ definitions. - * Removed MPI_IOCSTATUS_MSG/DATA_XFER_ERROR definitions. - * Added MPI_IOCSTATUS_INTERNAL_ERROR definition. - * Added MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH. - * 11-02-00 01.01.01 Original release for post 1.0 work - * 12-04-00 01.01.02 Added new function codes. - * 01-09-01 01.01.03 Added more definitions to the system interface section - * Added MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT. - * 01-25-01 01.01.04 Changed MPI_VERSION_MINOR from 0x00 to 0x01. - * 02-20-01 01.01.05 Started using MPI_POINTER. - * Added defines for MPI_DIAG_PREVENT_IOC_BOOT and - * MPI_DIAG_CLEAR_FLASH_BAD_SIG. - * Obsoleted MPI_IOCSTATUS_TARGET_FC_ defines. - * 02-27-01 01.01.06 Removed MPI_HOST_INDEX_REGISTER define. - * Added function codes for RAID. - * 04-09-01 01.01.07 Added alternate define for MPI_DOORBELL_ACTIVE, - * MPI_DOORBELL_USED, to better match the spec. - * -------------------------------------------------------------------------- - -mpi_ioc.h - * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. - * 05-24-00 00.10.02 Added _MSG_IOC_INIT_REPLY structure. - * 06-06-00 01.00.01 Added CurReplyFrameSize field to _MSG_IOC_FACTS_REPLY. - * 06-12-00 01.00.02 Added _MSG_PORT_ENABLE_REPLY structure. - * Added _MSG_EVENT_ACK_REPLY structure. - * Added _MSG_FW_DOWNLOAD_REPLY structure. - * Added _MSG_TOOLBOX_REPLY structure. - * 06-30-00 01.00.03 Added MaxLanBuckets to _PORT_FACT_REPLY structure. - * 07-27-00 01.00.04 Added _EVENT_DATA structure definitions for _SCSI, - * _LINK_STATUS, _LOOP_STATE and _LOGOUT. - * 08-11-00 01.00.05 Switched positions of MsgLength and Function fields in - * _MSG_EVENT_ACK_REPLY structure to match specification. - * 11-02-00 01.01.01 Original release for post 1.0 work - * Added a value for Manufacturer to WhoInit - * 12-04-00 01.01.02 Modified IOCFacts reply, added FWUpload messages, and - * removed toolbox message. - * 01-09-01 01.01.03 Added event enabled and disabled defines. - * Added structures for FwHeader and DataHeader. - * Added ImageType to FwUpload reply. - * 02-20-01 01.01.04 Started using MPI_POINTER. - * 02-27-01 01.01.05 Added event for RAID status change and its event data. - * Added IocNumber field to MSG_IOC_FACTS_REPLY. - * 03-27-01 01.01.06 Added defines for ProductId field of MPI_FW_HEADER. - * Added structure offset comments. - * 04-09-01 01.01.07 Added structure EVENT_DATA_EVENT_CHANGE. - * -------------------------------------------------------------------------- - -mpi_cnfg.h - * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. - * 06-06-00 01.00.01 Update version number for 1.0 release. - * 06-08-00 01.00.02 Added _PAGEVERSION definitions for all pages. - * Added FcPhLowestVersion, FcPhHighestVersion, Reserved2 - * fields to FC_DEVICE_0 page, updated the page version. - * Changed _FREE_RUNNING_CLOCK to _PACING_TRANSFERS in - * SCSI_PORT_0, SCSI_DEVICE_0 and SCSI_DEVICE_1 pages - * and updated the page versions. - * Added _RESPONSE_ID_MASK definition to SCSI_PORT_1 - * page and updated the page version. - * Added Information field and _INFO_PARAMS_NEGOTIATED - * definitionto SCSI_DEVICE_0 page. - * 06-22-00 01.00.03 Removed batch controls from LAN_0 page and updated the - * page version. - * Added BucketsRemaining to LAN_1 page, redefined the - * state values, and updated the page version. - * Revised bus width definitions in SCSI_PORT_0, - * SCSI_DEVICE_0 and SCSI_DEVICE_1 pages. - * 06-30-00 01.00.04 Added MaxReplySize to LAN_1 page and updated the page - * version. - * Moved FC_DEVICE_0 PageAddress description to spec. - * 07-27-00 01.00.05 Corrected the SubsystemVendorID and SubsystemID field - * widths in IOC_0 page and updated the page version. - * 11-02-00 01.01.01 Original release for post 1.0 work - * Added Manufacturing pages, IO Unit Page 2, SCSI SPI - * Port Page 2, FC Port Page 4, FC Port Page 5 - * 12-04-00 01.01.03 Config page changes to match MPI rev 1.00.01. - * 12-05-00 01.01.04 Modified config page actions. - * 01-09-01 01.01.05 Added defines for page address formats. - * Data size for Manufacturing pages 2 and 3 no longer - * defined here. - * Io Unit Page 2 size is fixed at 4 adapters and some - * flags were changed. - * SCSI Port Page 2 Device Settings modified. - * New fields added to FC Port Page 0 and some flags - * cleaned up. - * Removed impedance flash from FC Port Page 1. - * Added FC Port pages 6 and 7. - * 01-25-01 01.01.06 Added MaxInitiators field to FcPortPage0. - * 01-29-01 01.01.07 Changed some defines to make them 32 character unique. - * Added some LinkType defines for FcPortPage0. - * 02-20-01 01.01.08 Started using MPI_POINTER. - * 02-27-01 01.01.09 Replaced MPI_CONFIG_PAGETYPE_SCSI_LUN with - * MPI_CONFIG_PAGETYPE_RAID_VOLUME. - * Added definitions and structures for IOC Page 2 and - * RAID Volume Page 2. - * 03-27-01 01.01.10 Added CONFIG_PAGE_FC_PORT_8 and CONFIG_PAGE_FC_PORT_9. - * CONFIG_PAGE_FC_PORT_3 now supports persistent by DID. - * Added VendorId and ProductRevLevel fields to - * RAIDVOL2_IM_PHYS_ID struct. - * Modified values for MPI_FCPORTPAGE0_FLAGS_ATTACH_ - * defines to make them compatible to MPI version 1.0. - * Added structure offset comments. - * 04-09-01 01.01.11 Added some new defines for the PageAddress field and - * removed some obsolete ones. - * Added IO Unit Page 3. - * Modified defines for Scsi Port Page 2. - * Modified RAID Volume Pages. - * -------------------------------------------------------------------------- - -mpi_init.h - * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. - * 05-24-00 00.10.02 Added SenseBufferLength to _MSG_SCSI_IO_REPLY. - * 06-06-00 01.00.01 Update version number for 1.0 release. - * 06-08-00 01.00.02 Added MPI_SCSI_RSP_INFO_ definitions. - * 11-02-00 01.01.01 Original release for post 1.0 work - * 12-04-00 01.01.02 Added MPI_SCSIIO_CONTROL_NO_DISCONNECT. - * 02-20-01 01.01.03 Started using MPI_POINTER. - * 03-27-01 01.01.04 Added structure offset comments. - * 04-10-01 01.01.05 Added new MsgFlag for MSG_SCSI_TASK_MGMT. - * -------------------------------------------------------------------------- - -mpi_targ.h - * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. - * 06-06-00 01.00.01 Update version number for 1.0 release. - * 06-22-00 01.00.02 Added _MSG_TARGET_CMD_BUFFER_POST_REPLY structure. - * Corrected DECSRIPTOR typo to DESCRIPTOR. - * 11-02-00 01.01.01 Original release for post 1.0 work - * Modified target mode to use IoIndex instead of - * HostIndex and IocIndex. Added Alias. - * 01-09-01 01.01.02 Added defines for TARGET_ASSIST_FLAGS_REPOST_CMD_BUFFER - * and TARGET_STATUS_SEND_FLAGS_REPOST_CMD_BUFFER. - * 02-20-01 01.01.03 Started using MPI_POINTER. - * Added structures for MPI_TARGET_SCSI_SPI_CMD_BUFFER and - * MPI_TARGET_FCP_CMD_BUFFER. - * 03-27-01 01.01.04 Added structure offset comments. - * -------------------------------------------------------------------------- - -mpi_fc.h - * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. - * 06-06-00 01.00.01 Update version number for 1.0 release. - * 06-12-00 01.00.02 Added _MSG_FC_ABORT_REPLY structure. - * 11-02-00 01.01.01 Original release for post 1.0 work - * 12-04-00 01.01.02 Added messages for Common Transport Send and - * Primitive Send. - * 01-09-01 01.01.03 Modifed some of the new flags to have an MPI prefix - * and modified the FcPrimitiveSend flags. - * 01-25-01 01.01.04 Move InitiatorIndex in LinkServiceRsp reply to a larger - * field. - * Added FC_ABORT_TYPE_CT_SEND_REQUEST and - * FC_ABORT_TYPE_EXLINKSEND_REQUEST for FcAbort request. - * Added MPI_FC_PRIM_SEND_FLAGS_STOP_SEND. - * 02-20-01 01.01.05 Started using MPI_POINTER. - * 03-27-01 01.01.06 Added Flags field to MSG_LINK_SERVICE_BUFFER_POST_REPLY - * and defined MPI_LS_BUF_POST_REPLY_FLAG_NO_RSP_NEEDED. - * Added MPI_FC_PRIM_SEND_FLAGS_RESET_LINK define. - * Added structure offset comments. - * 04-09-01 01.01.07 Added RspLength field to MSG_LINK_SERVICE_RSP_REQUEST. - * -------------------------------------------------------------------------- - -mpi_lan.h - * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. - * 05-24-00 00.10.02 Added LANStatus field to _MSG_LAN_SEND_REPLY. - * Added LANStatus field to _MSG_LAN_RECEIVE_POST_REPLY. - * Moved ListCount field in _MSG_LAN_RECEIVE_POST_REPLY. - * 06-06-00 01.00.01 Update version number for 1.0 release. - * 06-12-00 01.00.02 Added MPI_ to BUCKETSTATUS_ definitions. - * 06-22-00 01.00.03 Major changes to match new LAN definition in 1.0 spec. - * 06-30-00 01.00.04 Added Context Reply definitions per revised proposal. - * Changed transaction context usage to bucket/buffer. - * 07-05-00 01.00.05 Removed LAN_RECEIVE_POST_BUCKET_CONTEXT_MASK definition - * to lan private header file - * 11-02-00 01.01.01 Original release for post 1.0 work - * 02-20-01 01.01.02 Started using MPI_POINTER. - * 03-27-01 01.01.03 Added structure offset comments. - * -------------------------------------------------------------------------- - -mpi_raid.h - * 02-27-01 01.01.01 Original release for this file. - * 03-27-01 01.01.02 Added structure offset comments. - * -------------------------------------------------------------------------- - -mpi_type.h - * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. - * 06-06-00 01.00.01 Update version number for 1.0 release. - * 11-02-00 01.01.01 Original release for post 1.0 work - * 02-20-01 01.01.02 Added define and ifdef for MPI_POINTER. - * -------------------------------------------------------------------------- - -mpi_history.txt Parts list history - -Filename 01.01.10 ----------- -------- -mpi.h 01.01.07 -mpi_ioc.h 01.01.07 -mpi_cnfg.h 01.01.11 -mpi_init.h 01.01.05 -mpi_targ.h 01.01.04 -mpi_fc.h 01.01.07 -mpi_lan.h 01.01.03 -mpi_raid.h 01.01.02 -mpi_type.h 01.01.02 - -Filename 01.01.09 01.01.08 01.01.07 01.01.06 01.01.05 01.01.04 ----------- -------- -------- -------- -------- -------- -------- -mpi.h 01.01.06 01.01.06 01.01.05 01.01.04 01.01.04 01.01.03 -mpi_ioc.h 01.01.06 01.01.05 01.01.04 01.01.03 01.01.03 01.01.03 -mpi_cnfg.h 01.01.10 01.01.09 01.01.08 01.01.07 01.01.06 01.01.05 -mpi_init.h 01.01.04 01.01.03 01.01.03 01.01.02 01.01.02 01.01.02 -mpi_targ.h 01.01.04 01.01.03 01.01.03 01.01.02 01.01.02 01.01.02 -mpi_fc.h 01.01.06 01.01.05 01.01.05 01.01.04 01.01.04 01.01.03 -mpi_lan.h 01.01.03 01.01.02 01.01.02 01.01.01 01.01.01 01.01.01 -mpi_raid.h 01.01.02 01.01.01 -mpi_type.h 01.01.02 01.01.02 01.01.02 01.01.01 01.01.01 01.01.01 - -Filename 01.01.03 01.01.02 01.01.01 01.00.07 01.00.06 01.00.05 ----------- -------- -------- -------- -------- -------- -------- -mpi.h 01.01.02 01.01.02 01.01.01 01.00.04 01.00.04 01.00.03 -mpi_ioc.h 01.01.02 01.01.02 01.01.01 01.00.05 01.00.04 01.00.03 -mpi_cnfg.h 01.01.04 01.01.03 01.01.01 01.00.05 01.00.05 01.00.04 -mpi_init.h 01.01.02 01.01.02 01.01.01 01.00.02 01.00.02 01.00.02 -mpi_targ.h 01.01.01 01.01.01 01.01.01 01.00.02 01.00.02 01.00.02 -mpi_fc.h 01.01.02 01.01.02 01.01.01 01.00.02 01.00.02 01.00.02 -mpi_lan.h 01.01.01 01.01.01 01.01.01 01.00.05 01.00.05 01.00.05 -mpi_type.h 01.01.01 01.01.01 01.01.01 01.00.01 01.00.01 01.00.01 - -Filename 01.00.04 01.00.03 01.00.02 01.00.01 00.10.02 00.10.01 ----------- -------- -------- -------- -------- -------- -------- -mpi.h 01.00.02 01.00.01 01.00.01 01.00.01 00.10.02 00.10.01 -mpi_ioc.h 01.00.02 01.00.02 01.00.01 01.00.01 00.10.02 00.10.01 -mpi_cnfg.h 01.00.03 01.00.02 01.00.02 01.00.01 00.10.01 00.10.01 -mpi_init.h 01.00.02 01.00.02 01.00.02 01.00.01 00.10.02 00.10.01 -mpi_targ.h 01.00.02 01.00.01 01.00.01 01.00.01 00.10.01 00.10.01 -mpi_fc.h 01.00.02 01.00.02 01.00.01 01.00.01 00.10.01 00.10.01 -mpi_lan.h 01.00.03 01.00.02 01.00.01 01.00.01 00.10.02 00.10.01 -mpi_type.h 01.00.01 01.00.01 01.00.01 01.00.01 00.10.01 00.10.01 - - - * -------------------------------------------------------------------------- - diff --git a/xen/drivers/message/fusion/lsi/mpi_init.h b/xen/drivers/message/fusion/lsi/mpi_init.h deleted file mode 100644 index 4b3256e4e7..0000000000 --- a/xen/drivers/message/fusion/lsi/mpi_init.h +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright (c) 2000-2002 LSI Logic Corporation. - * - * - * Name: MPI_INIT.H - * Title: MPI initiator mode messages and structures - * Creation Date: June 8, 2000 - * - * MPI_INIT.H Version: 01.02.05 - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. - * 05-24-00 00.10.02 Added SenseBufferLength to _MSG_SCSI_IO_REPLY. - * 06-06-00 01.00.01 Update version number for 1.0 release. - * 06-08-00 01.00.02 Added MPI_SCSI_RSP_INFO_ definitions. - * 11-02-00 01.01.01 Original release for post 1.0 work. - * 12-04-00 01.01.02 Added MPI_SCSIIO_CONTROL_NO_DISCONNECT. - * 02-20-01 01.01.03 Started using MPI_POINTER. - * 03-27-01 01.01.04 Added structure offset comments. - * 04-10-01 01.01.05 Added new MsgFlag for MSG_SCSI_TASK_MGMT. - * 08-08-01 01.02.01 Original release for v1.2 work. - * 08-29-01 01.02.02 Added MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET. - * Added MPI_SCSI_STATE_QUEUE_TAG_REJECTED for - * MSG_SCSI_IO_REPLY. - * 09-28-01 01.02.03 Added structures and defines for SCSI Enclosure - * Processor messages. - * 10-04-01 01.02.04 Added defines for SEP request Action field. - * 05-31-02 01.02.05 Added MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR define - * for SCSI IO requests. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI_INIT_H -#define MPI_INIT_H - - -/***************************************************************************** -* -* S C S I I n i t i a t o r M e s s a g e s -* -*****************************************************************************/ - -/****************************************************************************/ -/* SCSI IO messages and assocaited structures */ -/****************************************************************************/ - -typedef struct _MSG_SCSI_IO_REQUEST -{ - U8 TargetID; /* 00h */ - U8 Bus; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U8 CDBLength; /* 04h */ - U8 SenseBufferLength; /* 05h */ - U8 Reserved; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U8 LUN[8]; /* 0Ch */ - U32 Control; /* 14h */ - U8 CDB[16]; /* 18h */ - U32 DataLength; /* 28h */ - U32 SenseBufferLowAddr; /* 2Ch */ - SGE_IO_UNION SGL; /* 30h */ -} MSG_SCSI_IO_REQUEST, MPI_POINTER PTR_MSG_SCSI_IO_REQUEST, - SCSIIORequest_t, MPI_POINTER pSCSIIORequest_t; - - -/* SCSI IO MsgFlags bits */ - -#define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH (0x01) -#define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32 (0x00) -#define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 (0x01) -#define MPI_SCSIIO_MSGFLGS_SENSE_LOCATION (0x02) -#define MPI_SCSIIO_MSGFLGS_SENSE_LOC_HOST (0x00) -#define MPI_SCSIIO_MSGFLGS_SENSE_LOC_IOC (0x02) -#define MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR (0x04) - -/* SCSI IO LUN fields */ - -#define MPI_SCSIIO_LUN_FIRST_LEVEL_ADDRESSING (0x0000FFFF) -#define MPI_SCSIIO_LUN_SECOND_LEVEL_ADDRESSING (0xFFFF0000) -#define MPI_SCSIIO_LUN_THIRD_LEVEL_ADDRESSING (0x0000FFFF) -#define MPI_SCSIIO_LUN_FOURTH_LEVEL_ADDRESSING (0xFFFF0000) -#define MPI_SCSIIO_LUN_LEVEL_1_WORD (0xFF00) -#define MPI_SCSIIO_LUN_LEVEL_1_DWORD (0x0000FF00) - -/* SCSI IO Control bits */ - -#define MPI_SCSIIO_CONTROL_DATADIRECTION_MASK (0x03000000) -#define MPI_SCSIIO_CONTROL_NODATATRANSFER (0x00000000) -#define MPI_SCSIIO_CONTROL_WRITE (0x01000000) -#define MPI_SCSIIO_CONTROL_READ (0x02000000) - -#define MPI_SCSIIO_CONTROL_ADDCDBLEN_MASK (0x3C000000) -#define MPI_SCSIIO_CONTROL_ADDCDBLEN_SHIFT (26) - -#define MPI_SCSIIO_CONTROL_TASKATTRIBUTE_MASK (0x00000700) -#define MPI_SCSIIO_CONTROL_SIMPLEQ (0x00000000) -#define MPI_SCSIIO_CONTROL_HEADOFQ (0x00000100) -#define MPI_SCSIIO_CONTROL_ORDEREDQ (0x00000200) -#define MPI_SCSIIO_CONTROL_ACAQ (0x00000400) -#define MPI_SCSIIO_CONTROL_UNTAGGED (0x00000500) -#define MPI_SCSIIO_CONTROL_NO_DISCONNECT (0x00000700) - -#define MPI_SCSIIO_CONTROL_TASKMANAGE_MASK (0x00FF0000) -#define MPI_SCSIIO_CONTROL_OBSOLETE (0x00800000) -#define MPI_SCSIIO_CONTROL_CLEAR_ACA_RSV (0x00400000) -#define MPI_SCSIIO_CONTROL_TARGET_RESET (0x00200000) -#define MPI_SCSIIO_CONTROL_LUN_RESET_RSV (0x00100000) -#define MPI_SCSIIO_CONTROL_RESERVED (0x00080000) -#define MPI_SCSIIO_CONTROL_CLR_TASK_SET_RSV (0x00040000) -#define MPI_SCSIIO_CONTROL_ABORT_TASK_SET (0x00020000) -#define MPI_SCSIIO_CONTROL_RESERVED2 (0x00010000) - - -/* SCSI IO reply structure */ -typedef struct _MSG_SCSI_IO_REPLY -{ - U8 TargetID; /* 00h */ - U8 Bus; /* 01h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U8 CDBLength; /* 04h */ - U8 SenseBufferLength; /* 05h */ - U8 Reserved; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U8 SCSIStatus; /* 0Ch */ - U8 SCSIState; /* 0Dh */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 TransferCount; /* 14h */ - U32 SenseCount; /* 18h */ - U32 ResponseInfo; /* 1Ch */ -} MSG_SCSI_IO_REPLY, MPI_POINTER PTR_MSG_SCSI_IO_REPLY, - SCSIIOReply_t, MPI_POINTER pSCSIIOReply_t; - - -/* SCSI IO Reply SCSIStatus values (SAM-2 status codes) */ - -#define MPI_SCSI_STATUS_SUCCESS (0x00) -#define MPI_SCSI_STATUS_CHECK_CONDITION (0x02) -#define MPI_SCSI_STATUS_CONDITION_MET (0x04) -#define MPI_SCSI_STATUS_BUSY (0x08) -#define MPI_SCSI_STATUS_INTERMEDIATE (0x10) -#define MPI_SCSI_STATUS_INTERMEDIATE_CONDMET (0x14) -#define MPI_SCSI_STATUS_RESERVATION_CONFLICT (0x18) -#define MPI_SCSI_STATUS_COMMAND_TERMINATED (0x22) -#define MPI_SCSI_STATUS_TASK_SET_FULL (0x28) -#define MPI_SCSI_STATUS_ACA_ACTIVE (0x30) - - -/* SCSI IO Reply SCSIState values */ - -#define MPI_SCSI_STATE_AUTOSENSE_VALID (0x01) -#define MPI_SCSI_STATE_AUTOSENSE_FAILED (0x02) -#define MPI_SCSI_STATE_NO_SCSI_STATUS (0x04) -#define MPI_SCSI_STATE_TERMINATED (0x08) -#define MPI_SCSI_STATE_RESPONSE_INFO_VALID (0x10) -#define MPI_SCSI_STATE_QUEUE_TAG_REJECTED (0x20) - -/* SCSI IO Reply ResponseInfo values */ -/* (FCP-1 RSP_CODE values and SPI-3 Packetized Failure codes) */ - -#define MPI_SCSI_RSP_INFO_FUNCTION_COMPLETE (0x00000000) -#define MPI_SCSI_RSP_INFO_FCP_BURST_LEN_ERROR (0x01000000) -#define MPI_SCSI_RSP_INFO_CMND_FIELDS_INVALID (0x02000000) -#define MPI_SCSI_RSP_INFO_FCP_DATA_RO_ERROR (0x03000000) -#define MPI_SCSI_RSP_INFO_TASK_MGMT_UNSUPPORTED (0x04000000) -#define MPI_SCSI_RSP_INFO_TASK_MGMT_FAILED (0x05000000) -#define MPI_SCSI_RSP_INFO_SPI_LQ_INVALID_TYPE (0x06000000) - - -/****************************************************************************/ -/* SCSI Task Management messages */ -/****************************************************************************/ - -typedef struct _MSG_SCSI_TASK_MGMT -{ - U8 TargetID; /* 00h */ - U8 Bus; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U8 Reserved; /* 04h */ - U8 TaskType; /* 05h */ - U8 Reserved1; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U8 LUN[8]; /* 0Ch */ - U32 Reserved2[7]; /* 14h */ - U32 TaskMsgContext; /* 30h */ -} MSG_SCSI_TASK_MGMT, MPI_POINTER PTR_SCSI_TASK_MGMT, - SCSITaskMgmt_t, MPI_POINTER pSCSITaskMgmt_t; - -/* TaskType values */ - -#define MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x01) -#define MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET (0x02) -#define MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03) -#define MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS (0x04) -#define MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05) - -/* MsgFlags bits */ -#define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION (0x00) -#define MPI_SCSITASKMGMT_MSGFLAGS_LIP_RESET_OPTION (0x02) -#define MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION (0x04) - -/* SCSI Task Management Reply */ -typedef struct _MSG_SCSI_TASK_MGMT_REPLY -{ - U8 TargetID; /* 00h */ - U8 Bus; /* 01h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U8 Reserved; /* 04h */ - U8 TaskType; /* 05h */ - U8 Reserved1; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U8 Reserved2[2]; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 TerminationCount; /* 14h */ -} MSG_SCSI_TASK_MGMT_REPLY, MPI_POINTER PTR_MSG_SCSI_TASK_MGMT_REPLY, - SCSITaskMgmtReply_t, MPI_POINTER pSCSITaskMgmtReply_t; - - -/****************************************************************************/ -/* SCSI Enclosure Processor messages */ -/****************************************************************************/ - -typedef struct _MSG_SEP_REQUEST -{ - U8 TargetID; /* 00h */ - U8 Bus; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U8 Action; /* 04h */ - U8 Reserved1; /* 05h */ - U8 Reserved2; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U32 SlotStatus; /* 0Ch */ -} MSG_SEP_REQUEST, MPI_POINTER PTR_MSG_SEP_REQUEST, - SEPRequest_t, MPI_POINTER pSEPRequest_t; - -/* Action defines */ -#define MPI_SEP_REQ_ACTION_WRITE_STATUS (0x00) -#define MPI_SEP_REQ_ACTION_READ_STATUS (0x01) - -/* SlotStatus bits for MSG_SEP_REQUEST */ -#define MPI_SEP_REQ_SLOTSTATUS_NO_ERROR (0x00000001) -#define MPI_SEP_REQ_SLOTSTATUS_DEV_FAULTY (0x00000002) -#define MPI_SEP_REQ_SLOTSTATUS_DEV_REBUILDING (0x00000004) -#define MPI_SEP_REQ_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008) -#define MPI_SEP_REQ_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010) -#define MPI_SEP_REQ_SLOTSTATUS_PARITY_CHECK (0x00000020) -#define MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT (0x00000040) -#define MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED (0x00000080) -#define MPI_SEP_REQ_SLOTSTATUS_HOT_SPARE (0x00000100) -#define MPI_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED (0x00000200) -#define MPI_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) -#define MPI_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE (0x00040000) -#define MPI_SEP_REQ_SLOTSTATUS_REQUEST_INSERT (0x00080000) -#define MPI_SEP_REQ_SLOTSTATUS_DO_NOT_MOVE (0x00400000) -#define MPI_SEP_REQ_SLOTSTATUS_B_ENABLE_BYPASS (0x04000000) -#define MPI_SEP_REQ_SLOTSTATUS_A_ENABLE_BYPASS (0x08000000) -#define MPI_SEP_REQ_SLOTSTATUS_DEV_OFF (0x10000000) -#define MPI_SEP_REQ_SLOTSTATUS_SWAP_RESET (0x80000000) - - -typedef struct _MSG_SEP_REPLY -{ - U8 TargetID; /* 00h */ - U8 Bus; /* 01h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U8 Action; /* 04h */ - U8 Reserved1; /* 05h */ - U8 Reserved2; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved3; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 SlotStatus; /* 14h */ -} MSG_SEP_REPLY, MPI_POINTER PTR_MSG_SEP_REPLY, - SEPReply_t, MPI_POINTER pSEPReply_t; - -/* SlotStatus bits for MSG_SEP_REPLY */ -#define MPI_SEP_REPLY_SLOTSTATUS_NO_ERROR (0x00000001) -#define MPI_SEP_REPLY_SLOTSTATUS_DEV_FAULTY (0x00000002) -#define MPI_SEP_REPLY_SLOTSTATUS_DEV_REBUILDING (0x00000004) -#define MPI_SEP_REPLY_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008) -#define MPI_SEP_REPLY_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010) -#define MPI_SEP_REPLY_SLOTSTATUS_PARITY_CHECK (0x00000020) -#define MPI_SEP_REPLY_SLOTSTATUS_PREDICTED_FAULT (0x00000040) -#define MPI_SEP_REPLY_SLOTSTATUS_UNCONFIGURED (0x00000080) -#define MPI_SEP_REPLY_SLOTSTATUS_HOT_SPARE (0x00000100) -#define MPI_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED (0x00000200) -#define MPI_SEP_REPLY_SLOTSTATUS_REPORT (0x00010000) -#define MPI_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) -#define MPI_SEP_REPLY_SLOTSTATUS_REMOVE_READY (0x00040000) -#define MPI_SEP_REPLY_SLOTSTATUS_INSERT_READY (0x00080000) -#define MPI_SEP_REPLY_SLOTSTATUS_DO_NOT_REMOVE (0x00400000) -#define MPI_SEP_REPLY_SLOTSTATUS_B_BYPASS_ENABLED (0x01000000) -#define MPI_SEP_REPLY_SLOTSTATUS_A_BYPASS_ENABLED (0x02000000) -#define MPI_SEP_REPLY_SLOTSTATUS_B_ENABLE_BYPASS (0x04000000) -#define MPI_SEP_REPLY_SLOTSTATUS_A_ENABLE_BYPASS (0x08000000) -#define MPI_SEP_REPLY_SLOTSTATUS_DEV_OFF (0x10000000) -#define MPI_SEP_REPLY_SLOTSTATUS_FAULT_SENSED (0x40000000) -#define MPI_SEP_REPLY_SLOTSTATUS_SWAPPED (0x80000000) - -#endif diff --git a/xen/drivers/message/fusion/lsi/mpi_ioc.h b/xen/drivers/message/fusion/lsi/mpi_ioc.h deleted file mode 100644 index c58a4f4b83..0000000000 --- a/xen/drivers/message/fusion/lsi/mpi_ioc.h +++ /dev/null @@ -1,698 +0,0 @@ -/* - * Copyright (c) 2000-2002 LSI Logic Corporation. - * - * - * Name: MPI_IOC.H - * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages - * Creation Date: August 11, 2000 - * - * MPI_IOC.H Version: 01.02.06 - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. - * 05-24-00 00.10.02 Added _MSG_IOC_INIT_REPLY structure. - * 06-06-00 01.00.01 Added CurReplyFrameSize field to _MSG_IOC_FACTS_REPLY. - * 06-12-00 01.00.02 Added _MSG_PORT_ENABLE_REPLY structure. - * Added _MSG_EVENT_ACK_REPLY structure. - * Added _MSG_FW_DOWNLOAD_REPLY structure. - * Added _MSG_TOOLBOX_REPLY structure. - * 06-30-00 01.00.03 Added MaxLanBuckets to _PORT_FACT_REPLY structure. - * 07-27-00 01.00.04 Added _EVENT_DATA structure definitions for _SCSI, - * _LINK_STATUS, _LOOP_STATE and _LOGOUT. - * 08-11-00 01.00.05 Switched positions of MsgLength and Function fields in - * _MSG_EVENT_ACK_REPLY structure to match specification. - * 11-02-00 01.01.01 Original release for post 1.0 work. - * Added a value for Manufacturer to WhoInit. - * 12-04-00 01.01.02 Modified IOCFacts reply, added FWUpload messages, and - * removed toolbox message. - * 01-09-01 01.01.03 Added event enabled and disabled defines. - * Added structures for FwHeader and DataHeader. - * Added ImageType to FwUpload reply. - * 02-20-01 01.01.04 Started using MPI_POINTER. - * 02-27-01 01.01.05 Added event for RAID status change and its event data. - * Added IocNumber field to MSG_IOC_FACTS_REPLY. - * 03-27-01 01.01.06 Added defines for ProductId field of MPI_FW_HEADER. - * Added structure offset comments. - * 04-09-01 01.01.07 Added structure EVENT_DATA_EVENT_CHANGE. - * 08-08-01 01.02.01 Original release for v1.2 work. - * New format for FWVersion and ProductId in - * MSG_IOC_FACTS_REPLY and MPI_FW_HEADER. - * 08-31-01 01.02.02 Addded event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and - * related structure and defines. - * Added event MPI_EVENT_ON_BUS_TIMER_EXPIRED. - * Added MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE. - * Replaced a reserved field in MSG_IOC_FACTS_REPLY with - * IOCExceptions and changed DataImageSize to reserved. - * Added MPI_FW_DOWNLOAD_ITYPE_NVSTORE_DATA and - * MPI_FW_UPLOAD_ITYPE_NVDATA. - * 09-28-01 01.02.03 Modified Event Data for Integrated RAID. - * 11-01-01 01.02.04 Added defines for MPI_EXT_IMAGE_HEADER ImageType field. - * 03-14-02 01.02.05 Added HeaderVersion field to MSG_IOC_FACTS_REPLY. - * 05-31-02 01.02.06 Added define for - * MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID. - * Added AliasIndex to EVENT_DATA_LOGOUT structure. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI_IOC_H -#define MPI_IOC_H - - -/***************************************************************************** -* -* I O C M e s s a g e s -* -*****************************************************************************/ - -/****************************************************************************/ -/* IOCInit message */ -/****************************************************************************/ - -typedef struct _MSG_IOC_INIT -{ - U8 WhoInit; /* 00h */ - U8 Reserved; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U8 Flags; /* 04h */ - U8 MaxDevices; /* 05h */ - U8 MaxBuses; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 ReplyFrameSize; /* 0Ch */ - U8 Reserved1[2]; /* 0Eh */ - U32 HostMfaHighAddr; /* 10h */ - U32 SenseBufferHighAddr; /* 14h */ -} MSG_IOC_INIT, MPI_POINTER PTR_MSG_IOC_INIT, - IOCInit_t, MPI_POINTER pIOCInit_t; - -/* WhoInit values */ -#define MPI_WHOINIT_NO_ONE (0x00) -#define MPI_WHOINIT_SYSTEM_BIOS (0x01) -#define MPI_WHOINIT_ROM_BIOS (0x02) -#define MPI_WHOINIT_PCI_PEER (0x03) -#define MPI_WHOINIT_HOST_DRIVER (0x04) -#define MPI_WHOINIT_MANUFACTURER (0x05) - -/* Flags values */ -#define MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE (0x01) - -typedef struct _MSG_IOC_INIT_REPLY -{ - U8 WhoInit; /* 00h */ - U8 Reserved; /* 01h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U8 Flags; /* 04h */ - U8 MaxDevices; /* 05h */ - U8 MaxBuses; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved2; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ -} MSG_IOC_INIT_REPLY, MPI_POINTER PTR_MSG_IOC_INIT_REPLY, - IOCInitReply_t, MPI_POINTER pIOCInitReply_t; - - - -/****************************************************************************/ -/* IOC Facts message */ -/****************************************************************************/ - -typedef struct _MSG_IOC_FACTS -{ - U8 Reserved[2]; /* 00h */ - U8 ChainOffset; /* 01h */ - U8 Function; /* 02h */ - U8 Reserved1[3]; /* 03h */ - U8 MsgFlags; /* 04h */ - U32 MsgContext; /* 08h */ -} MSG_IOC_FACTS, MPI_POINTER PTR_IOC_FACTS, - IOCFacts_t, MPI_POINTER pIOCFacts_t; - -typedef struct _MPI_FW_VERSION_STRUCT -{ - U8 Dev; /* 00h */ - U8 Unit; /* 01h */ - U8 Minor; /* 02h */ - U8 Major; /* 03h */ -} MPI_FW_VERSION_STRUCT; - -typedef union _MPI_FW_VERSION -{ - MPI_FW_VERSION_STRUCT Struct; - U32 Word; -} MPI_FW_VERSION; - -/* IOC Facts Reply */ -typedef struct _MSG_IOC_FACTS_REPLY -{ - U16 MsgVersion; /* 00h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U16 HeaderVersion; /* 04h */ - U8 IOCNumber; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 IOCExceptions; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U8 MaxChainDepth; /* 14h */ - U8 WhoInit; /* 15h */ - U8 BlockSize; /* 16h */ - U8 Flags; /* 17h */ - U16 ReplyQueueDepth; /* 18h */ - U16 RequestFrameSize; /* 1Ah */ - U16 Reserved_0101_FWVersion; /* 1Ch */ /* obsolete 16-bit FWVersion */ - U16 ProductID; /* 1Eh */ - U32 CurrentHostMfaHighAddr; /* 20h */ - U16 GlobalCredits; /* 24h */ - U8 NumberOfPorts; /* 26h */ - U8 EventState; /* 27h */ - U32 CurrentSenseBufferHighAddr; /* 28h */ - U16 CurReplyFrameSize; /* 2Ch */ - U8 MaxDevices; /* 2Eh */ - U8 MaxBuses; /* 2Fh */ - U32 FWImageSize; /* 30h */ - U32 Reserved4; /* 34h */ - MPI_FW_VERSION FWVersion; /* 38h */ -} MSG_IOC_FACTS_REPLY, MPI_POINTER PTR_MSG_IOC_FACTS_REPLY, - IOCFactsReply_t, MPI_POINTER pIOCFactsReply_t; - -#define MPI_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00) -#define MPI_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF) - -#define MPI_IOCFACTS_HEADERVERSION_UNIT_MASK (0xFF00) -#define MPI_IOCFACTS_HEADERVERSION_DEV_MASK (0x00FF) - -#define MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0001) -#define MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002) - -#define MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT (0x01) - -#define MPI_IOCFACTS_EVENTSTATE_DISABLED (0x00) -#define MPI_IOCFACTS_EVENTSTATE_ENABLED (0x01) - - - -/***************************************************************************** -* -* P o r t M e s s a g e s -* -*****************************************************************************/ - -/****************************************************************************/ -/* Port Facts message and Reply */ -/****************************************************************************/ - -typedef struct _MSG_PORT_FACTS -{ - U8 Reserved[2]; /* 00h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U8 Reserved1[2]; /* 04h */ - U8 PortNumber; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ -} MSG_PORT_FACTS, MPI_POINTER PTR_MSG_PORT_FACTS, - PortFacts_t, MPI_POINTER pPortFacts_t; - -typedef struct _MSG_PORT_FACTS_REPLY -{ - U16 Reserved; /* 00h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved1; /* 04h */ - U8 PortNumber; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved2; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U8 Reserved3; /* 14h */ - U8 PortType; /* 15h */ - U16 MaxDevices; /* 16h */ - U16 PortSCSIID; /* 18h */ - U16 ProtocolFlags; /* 1Ah */ - U16 MaxPostedCmdBuffers; /* 1Ch */ - U16 MaxPersistentIDs; /* 1Eh */ - U16 MaxLanBuckets; /* 20h */ - U16 Reserved4; /* 22h */ - U32 Reserved5; /* 24h */ -} MSG_PORT_FACTS_REPLY, MPI_POINTER PTR_MSG_PORT_FACTS_REPLY, - PortFactsReply_t, MPI_POINTER pPortFactsReply_t; - - -/* PortTypes values */ - -#define MPI_PORTFACTS_PORTTYPE_INACTIVE (0x00) -#define MPI_PORTFACTS_PORTTYPE_SCSI (0x01) -#define MPI_PORTFACTS_PORTTYPE_FC (0x10) - -/* ProtocolFlags values */ - -#define MPI_PORTFACTS_PROTOCOL_LOGBUSADDR (0x01) -#define MPI_PORTFACTS_PROTOCOL_LAN (0x02) -#define MPI_PORTFACTS_PROTOCOL_TARGET (0x04) -#define MPI_PORTFACTS_PROTOCOL_INITIATOR (0x08) - - -/****************************************************************************/ -/* Port Enable Message */ -/****************************************************************************/ - -typedef struct _MSG_PORT_ENABLE -{ - U8 Reserved[2]; /* 00h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U8 Reserved1[2]; /* 04h */ - U8 PortNumber; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ -} MSG_PORT_ENABLE, MPI_POINTER PTR_MSG_PORT_ENABLE, - PortEnable_t, MPI_POINTER pPortEnable_t; - -typedef struct _MSG_PORT_ENABLE_REPLY -{ - U8 Reserved[2]; /* 00h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U8 Reserved1[2]; /* 04h */ - U8 PortNumber; /* 05h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved2; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ -} MSG_PORT_ENABLE_REPLY, MPI_POINTER PTR_MSG_PORT_ENABLE_REPLY, - PortEnableReply_t, MPI_POINTER pPortEnableReply_t; - - -/***************************************************************************** -* -* E v e n t M e s s a g e s -* -*****************************************************************************/ - -/****************************************************************************/ -/* Event Notification messages */ -/****************************************************************************/ - -typedef struct _MSG_EVENT_NOTIFY -{ - U8 Switch; /* 00h */ - U8 Reserved; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U8 Reserved1[3]; /* 04h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ -} MSG_EVENT_NOTIFY, MPI_POINTER PTR_MSG_EVENT_NOTIFY, - EventNotification_t, MPI_POINTER pEventNotification_t; - -/* Event Notification Reply */ - -typedef struct _MSG_EVENT_NOTIFY_REPLY -{ - U16 EventDataLength; /* 00h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U8 Reserved1[2]; /* 04h */ - U8 AckRequired; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U8 Reserved2[2]; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 Event; /* 14h */ - U32 EventContext; /* 18h */ - U32 Data[1]; /* 1Ch */ -} MSG_EVENT_NOTIFY_REPLY, MPI_POINTER PTR_MSG_EVENT_NOTIFY_REPLY, - EventNotificationReply_t, MPI_POINTER pEventNotificationReply_t; - -/* Event Acknowledge */ - -typedef struct _MSG_EVENT_ACK -{ - U8 Reserved[2]; /* 00h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U8 Reserved1[3]; /* 04h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U32 Event; /* 0Ch */ - U32 EventContext; /* 10h */ -} MSG_EVENT_ACK, MPI_POINTER PTR_MSG_EVENT_ACK, - EventAck_t, MPI_POINTER pEventAck_t; - -typedef struct _MSG_EVENT_ACK_REPLY -{ - U8 Reserved[2]; /* 00h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U8 Reserved1[3]; /* 04h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved2; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ -} MSG_EVENT_ACK_REPLY, MPI_POINTER PTR_MSG_EVENT_ACK_REPLY, - EventAckReply_t, MPI_POINTER pEventAckReply_t; - -/* Switch */ - -#define MPI_EVENT_NOTIFICATION_SWITCH_OFF (0x00) -#define MPI_EVENT_NOTIFICATION_SWITCH_ON (0x01) - -/* Event */ - -#define MPI_EVENT_NONE (0x00000000) -#define MPI_EVENT_LOG_DATA (0x00000001) -#define MPI_EVENT_STATE_CHANGE (0x00000002) -#define MPI_EVENT_UNIT_ATTENTION (0x00000003) -#define MPI_EVENT_IOC_BUS_RESET (0x00000004) -#define MPI_EVENT_EXT_BUS_RESET (0x00000005) -#define MPI_EVENT_RESCAN (0x00000006) -#define MPI_EVENT_LINK_STATUS_CHANGE (0x00000007) -#define MPI_EVENT_LOOP_STATE_CHANGE (0x00000008) -#define MPI_EVENT_LOGOUT (0x00000009) -#define MPI_EVENT_EVENT_CHANGE (0x0000000A) -#define MPI_EVENT_INTEGRATED_RAID (0x0000000B) -#define MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE (0x0000000C) -#define MPI_EVENT_ON_BUS_TIMER_EXPIRED (0x0000000D) - -/* AckRequired field values */ - -#define MPI_EVENT_NOTIFICATION_ACK_NOT_REQUIRED (0x00) -#define MPI_EVENT_NOTIFICATION_ACK_REQUIRED (0x01) - -/* EventChange Event data */ - -typedef struct _EVENT_DATA_EVENT_CHANGE -{ - U8 EventState; /* 00h */ - U8 Reserved; /* 01h */ - U16 Reserved1; /* 02h */ -} EVENT_DATA_EVENT_CHANGE, MPI_POINTER PTR_EVENT_DATA_EVENT_CHANGE, - EventDataEventChange_t, MPI_POINTER pEventDataEventChange_t; - -/* SCSI Event data for Port, Bus and Device forms */ - -typedef struct _EVENT_DATA_SCSI -{ - U8 TargetID; /* 00h */ - U8 BusPort; /* 01h */ - U16 Reserved; /* 02h */ -} EVENT_DATA_SCSI, MPI_POINTER PTR_EVENT_DATA_SCSI, - EventDataScsi_t, MPI_POINTER pEventDataScsi_t; - -/* SCSI Device Status Change Event data */ - -typedef struct _EVENT_DATA_SCSI_DEVICE_STATUS_CHANGE -{ - U8 TargetID; /* 00h */ - U8 Bus; /* 01h */ - U8 ReasonCode; /* 02h */ - U8 LUN; /* 03h */ - U8 ASC; /* 04h */ - U8 ASCQ; /* 05h */ - U16 Reserved; /* 06h */ -} EVENT_DATA_SCSI_DEVICE_STATUS_CHANGE, - MPI_POINTER PTR_EVENT_DATA_SCSI_DEVICE_STATUS_CHANGE, - MpiEventDataScsiDeviceStatusChange_t, - MPI_POINTER pMpiEventDataScsiDeviceStatusChange_t; - -/* MPI SCSI Device Status Change Event data ReasonCode values */ -#define MPI_EVENT_SCSI_DEV_STAT_RC_ADDED (0x03) -#define MPI_EVENT_SCSI_DEV_STAT_RC_NOT_RESPONDING (0x04) -#define MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA (0x05) - -/* MPI Link Status Change Event data */ - -typedef struct _EVENT_DATA_LINK_STATUS -{ - U8 State; /* 00h */ - U8 Reserved; /* 01h */ - U16 Reserved1; /* 02h */ - U8 Reserved2; /* 04h */ - U8 Port; /* 05h */ - U16 Reserved3; /* 06h */ -} EVENT_DATA_LINK_STATUS, MPI_POINTER PTR_EVENT_DATA_LINK_STATUS, - EventDataLinkStatus_t, MPI_POINTER pEventDataLinkStatus_t; - -#define MPI_EVENT_LINK_STATUS_FAILURE (0x00000000) -#define MPI_EVENT_LINK_STATUS_ACTIVE (0x00000001) - -/* MPI Loop State Change Event data */ - -typedef struct _EVENT_DATA_LOOP_STATE -{ - U8 Character4; /* 00h */ - U8 Character3; /* 01h */ - U8 Type; /* 02h */ - U8 Reserved; /* 03h */ - U8 Reserved1; /* 04h */ - U8 Port; /* 05h */ - U16 Reserved2; /* 06h */ -} EVENT_DATA_LOOP_STATE, MPI_POINTER PTR_EVENT_DATA_LOOP_STATE, - EventDataLoopState_t, MPI_POINTER pEventDataLoopState_t; - -#define MPI_EVENT_LOOP_STATE_CHANGE_LIP (0x0001) -#define MPI_EVENT_LOOP_STATE_CHANGE_LPE (0x0002) -#define MPI_EVENT_LOOP_STATE_CHANGE_LPB (0x0003) - -/* MPI LOGOUT Event data */ - -typedef struct _EVENT_DATA_LOGOUT -{ - U32 NPortID; /* 00h */ - U8 AliasIndex; /* 04h */ - U8 Port; /* 05h */ - U16 Reserved1; /* 06h */ -} EVENT_DATA_LOGOUT, MPI_POINTER PTR_EVENT_DATA_LOGOUT, - EventDataLogout_t, MPI_POINTER pEventDataLogout_t; - -#define MPI_EVENT_LOGOUT_ALL_ALIASES (0xFF) - - -/* MPI Integrated RAID Event data */ - -typedef struct _EVENT_DATA_RAID -{ - U8 VolumeID; /* 00h */ - U8 VolumeBus; /* 01h */ - U8 ReasonCode; /* 02h */ - U8 PhysDiskNum; /* 03h */ - U8 ASC; /* 04h */ - U8 ASCQ; /* 05h */ - U16 Reserved; /* 06h */ - U32 SettingsStatus; /* 08h */ -} EVENT_DATA_RAID, MPI_POINTER PTR_EVENT_DATA_RAID, - MpiEventDataRaid_t, MPI_POINTER pMpiEventDataRaid_t; - -/* MPI Integrated RAID Event data ReasonCode values */ -#define MPI_EVENT_RAID_RC_VOLUME_CREATED (0x00) -#define MPI_EVENT_RAID_RC_VOLUME_DELETED (0x01) -#define MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED (0x02) -#define MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED (0x03) -#define MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED (0x04) -#define MPI_EVENT_RAID_RC_PHYSDISK_CREATED (0x05) -#define MPI_EVENT_RAID_RC_PHYSDISK_DELETED (0x06) -#define MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED (0x07) -#define MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED (0x08) -#define MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED (0x09) -#define MPI_EVENT_RAID_RC_SMART_DATA (0x0A) -#define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED (0x0B) - - -/***************************************************************************** -* -* F i r m w a r e L o a d M e s s a g e s -* -*****************************************************************************/ - -/****************************************************************************/ -/* Firmware Download message and associated structures */ -/****************************************************************************/ - -typedef struct _MSG_FW_DOWNLOAD -{ - U8 ImageType; /* 00h */ - U8 Reserved; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U8 Reserved1[3]; /* 04h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - SGE_MPI_UNION SGL; /* 0Ch */ -} MSG_FW_DOWNLOAD, MPI_POINTER PTR_MSG_FW_DOWNLOAD, - FWDownload_t, MPI_POINTER pFWDownload_t; - -#define MPI_FW_DOWNLOAD_ITYPE_RESERVED (0x00) -#define MPI_FW_DOWNLOAD_ITYPE_FW (0x01) -#define MPI_FW_DOWNLOAD_ITYPE_BIOS (0x02) -#define MPI_FW_DOWNLOAD_ITYPE_NVDATA (0x03) - - -typedef struct _FWDownloadTCSGE -{ - U8 Reserved; /* 00h */ - U8 ContextSize; /* 01h */ - U8 DetailsLength; /* 02h */ - U8 Flags; /* 03h */ - U32 Reserved_0100_Checksum; /* 04h */ /* obsolete Checksum */ - U32 ImageOffset; /* 08h */ - U32 ImageSize; /* 0Ch */ -} FW_DOWNLOAD_TCSGE, MPI_POINTER PTR_FW_DOWNLOAD_TCSGE, - FWDownloadTCSGE_t, MPI_POINTER pFWDownloadTCSGE_t; - -/* Firmware Download reply */ -typedef struct _MSG_FW_DOWNLOAD_REPLY -{ - U8 ImageType; /* 00h */ - U8 Reserved; /* 01h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U8 Reserved1[3]; /* 04h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved2; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ -} MSG_FW_DOWNLOAD_REPLY, MPI_POINTER PTR_MSG_FW_DOWNLOAD_REPLY, - FWDownloadReply_t, MPI_POINTER pFWDownloadReply_t; - - -/****************************************************************************/ -/* Firmware Upload message and associated structures */ -/****************************************************************************/ - -typedef struct _MSG_FW_UPLOAD -{ - U8 ImageType; /* 00h */ - U8 Reserved; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U8 Reserved1[3]; /* 04h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - SGE_MPI_UNION SGL; /* 0Ch */ -} MSG_FW_UPLOAD, MPI_POINTER PTR_MSG_FW_UPLOAD, - FWUpload_t, MPI_POINTER pFWUpload_t; - -#define MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM (0x00) -#define MPI_FW_UPLOAD_ITYPE_FW_FLASH (0x01) -#define MPI_FW_UPLOAD_ITYPE_BIOS_FLASH (0x02) -#define MPI_FW_UPLOAD_ITYPE_NVDATA (0x03) - -typedef struct _FWUploadTCSGE -{ - U8 Reserved; /* 00h */ - U8 ContextSize; /* 01h */ - U8 DetailsLength; /* 02h */ - U8 Flags; /* 03h */ - U32 Reserved1; /* 04h */ - U32 ImageOffset; /* 08h */ - U32 ImageSize; /* 0Ch */ -} FW_UPLOAD_TCSGE, MPI_POINTER PTR_FW_UPLOAD_TCSGE, - FWUploadTCSGE_t, MPI_POINTER pFWUploadTCSGE_t; - -/* Firmware Upload reply */ -typedef struct _MSG_FW_UPLOAD_REPLY -{ - U8 ImageType; /* 00h */ - U8 Reserved; /* 01h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U8 Reserved1[3]; /* 04h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved2; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 ActualImageSize; /* 14h */ -} MSG_FW_UPLOAD_REPLY, MPI_POINTER PTR_MSG_FW_UPLOAD_REPLY, - FWUploadReply_t, MPI_POINTER pFWUploadReply_t; - - -typedef struct _MPI_FW_HEADER -{ - U32 ArmBranchInstruction0; /* 00h */ - U32 Signature0; /* 04h */ - U32 Signature1; /* 08h */ - U32 Signature2; /* 0Ch */ - U32 ArmBranchInstruction1; /* 10h */ - U32 ArmBranchInstruction2; /* 14h */ - U32 Reserved; /* 18h */ - U32 Checksum; /* 1Ch */ - U16 VendorId; /* 20h */ - U16 ProductId; /* 22h */ - MPI_FW_VERSION FWVersion; /* 24h */ - U32 SeqCodeVersion; /* 28h */ - U32 ImageSize; /* 2Ch */ - U32 NextImageHeaderOffset; /* 30h */ - U32 LoadStartAddress; /* 34h */ - U32 IopResetVectorValue; /* 38h */ - U32 IopResetRegAddr; /* 3Ch */ - U32 VersionNameWhat; /* 40h */ - U8 VersionName[32]; /* 44h */ - U32 VendorNameWhat; /* 64h */ - U8 VendorName[32]; /* 68h */ -} MPI_FW_HEADER, MPI_POINTER PTR_MPI_FW_HEADER, - MpiFwHeader_t, MPI_POINTER pMpiFwHeader_t; - -#define MPI_FW_HEADER_WHAT_SIGNATURE (0x29232840) - -/* defines for using the ProductId field */ -#define MPI_FW_HEADER_PID_TYPE_MASK (0xF000) -#define MPI_FW_HEADER_PID_TYPE_SCSI (0x0000) -#define MPI_FW_HEADER_PID_TYPE_FC (0x1000) - -#define MPI_FW_HEADER_PID_PROD_MASK (0x0F00) -#define MPI_FW_HEADER_PID_PROD_INITIATOR_SCSI (0x0100) -#define MPI_FW_HEADER_PID_PROD_TARGET_INITIATOR_SCSI (0x0200) -#define MPI_FW_HEADER_PID_PROD_TARGET_SCSI (0x0300) -#define MPI_FW_HEADER_PID_PROD_IM_SCSI (0x0400) -#define MPI_FW_HEADER_PID_PROD_IS_SCSI (0x0500) -#define MPI_FW_HEADER_PID_PROD_CTX_SCSI (0x0600) - -#define MPI_FW_HEADER_PID_FAMILY_MASK (0x00FF) -#define MPI_FW_HEADER_PID_FAMILY_1030A0_SCSI (0x0001) -#define MPI_FW_HEADER_PID_FAMILY_1030B0_SCSI (0x0002) -#define MPI_FW_HEADER_PID_FAMILY_1030B1_SCSI (0x0003) -#define MPI_FW_HEADER_PID_FAMILY_1030C0_SCSI (0x0004) -#define MPI_FW_HEADER_PID_FAMILY_1020A0_SCSI (0x0005) -#define MPI_FW_HEADER_PID_FAMILY_1020B0_SCSI (0x0006) -#define MPI_FW_HEADER_PID_FAMILY_1020B1_SCSI (0x0007) -#define MPI_FW_HEADER_PID_FAMILY_1020C0_SCSI (0x0008) -#define MPI_FW_HEADER_PID_FAMILY_1035A0_SCSI (0x0009) -#define MPI_FW_HEADER_PID_FAMILY_1035B0_SCSI (0x000A) -#define MPI_FW_HEADER_PID_FAMILY_909_FC (0x0000) -#define MPI_FW_HEADER_PID_FAMILY_919_FC (0x0001) -#define MPI_FW_HEADER_PID_FAMILY_919X_FC (0x0002) - -typedef struct _MPI_EXT_IMAGE_HEADER -{ - U8 ImageType; /* 00h */ - U8 Reserved; /* 01h */ - U16 Reserved1; /* 02h */ - U32 Checksum; /* 04h */ - U32 ImageSize; /* 08h */ - U32 NextImageHeaderOffset; /* 0Ch */ - U32 LoadStartAddress; /* 10h */ - U32 Reserved2; /* 14h */ -} MPI_EXT_IMAGE_HEADER, MPI_POINTER PTR_MPI_EXT_IMAGE_HEADER, - MpiExtImageHeader_t, MPI_POINTER pMpiExtImageHeader_t; - -/* defines for the ImageType field */ -#define MPI_EXT_IMAGE_TYPE_UNSPECIFIED (0x00) -#define MPI_EXT_IMAGE_TYPE_FW (0x01) -#define MPI_EXT_IMAGE_TYPE_NVDATA (0x03) - -#endif diff --git a/xen/drivers/message/fusion/lsi/mpi_lan.h b/xen/drivers/message/fusion/lsi/mpi_lan.h deleted file mode 100644 index 739c5cd717..0000000000 --- a/xen/drivers/message/fusion/lsi/mpi_lan.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2000-2002 LSI Logic Corporation. - * - * - * Name: MPI_LAN.H - * Title: MPI LAN messages and structures - * Creation Date: June 30, 2000 - * - * MPI_LAN.H Version: 01.02.01 - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. - * 05-24-00 00.10.02 Added LANStatus field to _MSG_LAN_SEND_REPLY. - * Added LANStatus field to _MSG_LAN_RECEIVE_POST_REPLY. - * Moved ListCount field in _MSG_LAN_RECEIVE_POST_REPLY. - * 06-06-00 01.00.01 Update version number for 1.0 release. - * 06-12-00 01.00.02 Added MPI_ to BUCKETSTATUS_ definitions. - * 06-22-00 01.00.03 Major changes to match new LAN definition in 1.0 spec. - * 06-30-00 01.00.04 Added Context Reply definitions per revised proposal. - * Changed transaction context usage to bucket/buffer. - * 07-05-00 01.00.05 Removed LAN_RECEIVE_POST_BUCKET_CONTEXT_MASK definition - * to lan private header file - * 11-02-00 01.01.01 Original release for post 1.0 work - * 02-20-01 01.01.02 Started using MPI_POINTER. - * 03-27-01 01.01.03 Added structure offset comments. - * 08-08-01 01.02.01 Original release for v1.2 work. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI_LAN_H -#define MPI_LAN_H - - -/****************************************************************************** -* -* L A N M e s s a g e s -* -*******************************************************************************/ - -/* LANSend messages */ - -typedef struct _MSG_LAN_SEND_REQUEST -{ - U16 Reserved; /* 00h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved2; /* 04h */ - U8 PortNumber; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - SGE_MPI_UNION SG_List[1]; /* 0Ch */ -} MSG_LAN_SEND_REQUEST, MPI_POINTER PTR_MSG_LAN_SEND_REQUEST, - LANSendRequest_t, MPI_POINTER pLANSendRequest_t; - - -typedef struct _MSG_LAN_SEND_REPLY -{ - U16 Reserved; /* 00h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U8 Reserved2; /* 04h */ - U8 NumberOfContexts; /* 05h */ - U8 PortNumber; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved3; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 BufferContext; /* 14h */ -} MSG_LAN_SEND_REPLY, MPI_POINTER PTR_MSG_LAN_SEND_REPLY, - LANSendReply_t, MPI_POINTER pLANSendReply_t; - - -/* LANReceivePost */ - -typedef struct _MSG_LAN_RECEIVE_POST_REQUEST -{ - U16 Reserved; /* 00h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved2; /* 04h */ - U8 PortNumber; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U32 BucketCount; /* 0Ch */ - SGE_MPI_UNION SG_List[1]; /* 10h */ -} MSG_LAN_RECEIVE_POST_REQUEST, MPI_POINTER PTR_MSG_LAN_RECEIVE_POST_REQUEST, - LANReceivePostRequest_t, MPI_POINTER pLANReceivePostRequest_t; - - -typedef struct _MSG_LAN_RECEIVE_POST_REPLY -{ - U16 Reserved; /* 00h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U8 Reserved2; /* 04h */ - U8 NumberOfContexts; /* 05h */ - U8 PortNumber; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved3; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 BucketsRemaining; /* 14h */ - U32 PacketOffset; /* 18h */ - U32 PacketLength; /* 1Ch */ - U32 BucketContext[1]; /* 20h */ -} MSG_LAN_RECEIVE_POST_REPLY, MPI_POINTER PTR_MSG_LAN_RECEIVE_POST_REPLY, - LANReceivePostReply_t, MPI_POINTER pLANReceivePostReply_t; - - -/* LANReset */ - -typedef struct _MSG_LAN_RESET_REQUEST -{ - U16 Reserved; /* 00h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved2; /* 04h */ - U8 PortNumber; /* 05h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ -} MSG_LAN_RESET_REQUEST, MPI_POINTER PTR_MSG_LAN_RESET_REQUEST, - LANResetRequest_t, MPI_POINTER pLANResetRequest_t; - - -typedef struct _MSG_LAN_RESET_REPLY -{ - U16 Reserved; /* 00h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved2; /* 04h */ - U8 PortNumber; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved3; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ -} MSG_LAN_RESET_REPLY, MPI_POINTER PTR_MSG_LAN_RESET_REPLY, - LANResetReply_t, MPI_POINTER pLANResetReply_t; - - -/****************************************************************************/ -/* LAN Context Reply defines and macros */ -/****************************************************************************/ - -#define LAN_REPLY_PACKET_LENGTH_MASK (0x0000FFFF) -#define LAN_REPLY_PACKET_LENGTH_SHIFT (0) -#define LAN_REPLY_BUCKET_CONTEXT_MASK (0x07FF0000) -#define LAN_REPLY_BUCKET_CONTEXT_SHIFT (16) -#define LAN_REPLY_BUFFER_CONTEXT_MASK (0x07FFFFFF) -#define LAN_REPLY_BUFFER_CONTEXT_SHIFT (0) -#define LAN_REPLY_FORM_MASK (0x18000000) -#define LAN_REPLY_FORM_RECEIVE_SINGLE (0x00) -#define LAN_REPLY_FORM_RECEIVE_MULTIPLE (0x01) -#define LAN_REPLY_FORM_SEND_SINGLE (0x02) -#define LAN_REPLY_FORM_MESSAGE_CONTEXT (0x03) -#define LAN_REPLY_FORM_SHIFT (27) - -#define GET_LAN_PACKET_LENGTH(x) (((x) & LAN_REPLY_PACKET_LENGTH_MASK) \ - >> LAN_REPLY_PACKET_LENGTH_SHIFT) - -#define SET_LAN_PACKET_LENGTH(x, lth) \ - ((x) = ((x) & ~LAN_REPLY_PACKET_LENGTH_MASK) | \ - (((lth) << LAN_REPLY_PACKET_LENGTH_SHIFT) & \ - LAN_REPLY_PACKET_LENGTH_MASK)) - -#define GET_LAN_BUCKET_CONTEXT(x) (((x) & LAN_REPLY_BUCKET_CONTEXT_MASK) \ - >> LAN_REPLY_BUCKET_CONTEXT_SHIFT) - -#define SET_LAN_BUCKET_CONTEXT(x, ctx) \ - ((x) = ((x) & ~LAN_REPLY_BUCKET_CONTEXT_MASK) | \ - (((ctx) << LAN_REPLY_BUCKET_CONTEXT_SHIFT) & \ - LAN_REPLY_BUCKET_CONTEXT_MASK)) - -#define GET_LAN_BUFFER_CONTEXT(x) (((x) & LAN_REPLY_BUFFER_CONTEXT_MASK) \ - >> LAN_REPLY_BUFFER_CONTEXT_SHIFT) - -#define SET_LAN_BUFFER_CONTEXT(x, ctx) \ - ((x) = ((x) & ~LAN_REPLY_BUFFER_CONTEXT_MASK) | \ - (((ctx) << LAN_REPLY_BUFFER_CONTEXT_SHIFT) & \ - LAN_REPLY_BUFFER_CONTEXT_MASK)) - -#define GET_LAN_FORM(x) (((x) & LAN_REPLY_FORM_MASK) \ - >> LAN_REPLY_FORM_SHIFT) - -#define SET_LAN_FORM(x, frm) \ - ((x) = ((x) & ~LAN_REPLY_FORM_MASK) | \ - (((frm) << LAN_REPLY_FORM_SHIFT) & \ - LAN_REPLY_FORM_MASK)) - - -/****************************************************************************/ -/* LAN Current Device State defines */ -/****************************************************************************/ - -#define MPI_LAN_DEVICE_STATE_RESET (0x00) -#define MPI_LAN_DEVICE_STATE_OPERATIONAL (0x01) - - -/****************************************************************************/ -/* LAN Loopback defines */ -/****************************************************************************/ - -#define MPI_LAN_TX_MODES_ENABLE_LOOPBACK_SUPPRESSION (0x01) - -#endif - diff --git a/xen/drivers/message/fusion/lsi/mpi_raid.h b/xen/drivers/message/fusion/lsi/mpi_raid.h deleted file mode 100644 index c120cfae0f..0000000000 --- a/xen/drivers/message/fusion/lsi/mpi_raid.h +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2001-2002 LSI Logic Corporation. - * - * - * Name: MPI_RAID.H - * Title: MPI RAID message and structures - * Creation Date: February 27, 2001 - * - * MPI_RAID.H Version: 01.02.07 - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 02-27-01 01.01.01 Original release for this file. - * 03-27-01 01.01.02 Added structure offset comments. - * 08-08-01 01.02.01 Original release for v1.2 work. - * 09-28-01 01.02.02 Major rework for MPI v1.2 Integrated RAID changes. - * 10-04-01 01.02.03 Added ActionData defines for - * MPI_RAID_ACTION_DELETE_VOLUME action. - * 11-01-01 01.02.04 Added define for MPI_RAID_ACTION_ADATA_DO_NOT_SYNC. - * 03-14-02 01.02.05 Added define for MPI_RAID_ACTION_ADATA_LOW_LEVEL_INIT. - * 05-07-02 01.02.06 Added define for MPI_RAID_ACTION_ACTIVATE_VOLUME, - * MPI_RAID_ACTION_INACTIVATE_VOLUME, and - * MPI_RAID_ACTION_ADATA_INACTIVATE_ALL. - * 07-12-02 01.02.07 Added structures for Mailbox request and reply. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI_RAID_H -#define MPI_RAID_H - - -/****************************************************************************** -* -* R A I D M e s s a g e s -* -*******************************************************************************/ - - -/****************************************************************************/ -/* RAID Volume Request */ -/****************************************************************************/ - -typedef struct _MSG_RAID_ACTION -{ - U8 Action; /* 00h */ - U8 Reserved1; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U8 VolumeID; /* 04h */ - U8 VolumeBus; /* 05h */ - U8 PhysDiskNum; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U32 Reserved2; /* 0Ch */ - U32 ActionDataWord; /* 10h */ - SGE_SIMPLE_UNION ActionDataSGE; /* 14h */ -} MSG_RAID_ACTION_REQUEST, MPI_POINTER PTR_MSG_RAID_ACTION_REQUEST, - MpiRaidActionRequest_t , MPI_POINTER pMpiRaidActionRequest_t; - - -/* RAID Action request Action values */ - -#define MPI_RAID_ACTION_STATUS (0x00) -#define MPI_RAID_ACTION_INDICATOR_STRUCT (0x01) -#define MPI_RAID_ACTION_CREATE_VOLUME (0x02) -#define MPI_RAID_ACTION_DELETE_VOLUME (0x03) -#define MPI_RAID_ACTION_DISABLE_VOLUME (0x04) -#define MPI_RAID_ACTION_ENABLE_VOLUME (0x05) -#define MPI_RAID_ACTION_QUIESCE_PHYS_IO (0x06) -#define MPI_RAID_ACTION_ENABLE_PHYS_IO (0x07) -#define MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS (0x08) -#define MPI_RAID_ACTION_PHYSDISK_OFFLINE (0x0A) -#define MPI_RAID_ACTION_PHYSDISK_ONLINE (0x0B) -#define MPI_RAID_ACTION_CHANGE_PHYSDISK_SETTINGS (0x0C) -#define MPI_RAID_ACTION_CREATE_PHYSDISK (0x0D) -#define MPI_RAID_ACTION_DELETE_PHYSDISK (0x0E) -#define MPI_RAID_ACTION_FAIL_PHYSDISK (0x0F) -#define MPI_RAID_ACTION_REPLACE_PHYSDISK (0x10) -#define MPI_RAID_ACTION_ACTIVATE_VOLUME (0x11) -#define MPI_RAID_ACTION_INACTIVATE_VOLUME (0x12) - -/* ActionDataWord defines for use with MPI_RAID_ACTION_CREATE_VOLUME action */ -#define MPI_RAID_ACTION_ADATA_DO_NOT_SYNC (0x00000001) -#define MPI_RAID_ACTION_ADATA_LOW_LEVEL_INIT (0x00000002) - -/* ActionDataWord defines for use with MPI_RAID_ACTION_DELETE_VOLUME action */ -#define MPI_RAID_ACTION_ADATA_KEEP_PHYS_DISKS (0x00000000) -#define MPI_RAID_ACTION_ADATA_DEL_PHYS_DISKS (0x00000001) - -/* ActionDataWord defines for use with MPI_RAID_ACTION_ACTIVATE_VOLUME action */ -#define MPI_RAID_ACTION_ADATA_INACTIVATE_ALL (0x00000001) - - -/* RAID Action reply message */ - -typedef struct _MSG_RAID_ACTION_REPLY -{ - U8 Action; /* 00h */ - U8 Reserved; /* 01h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U8 VolumeID; /* 04h */ - U8 VolumeBus; /* 05h */ - U8 PhysDiskNum; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 ActionStatus; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 VolumeStatus; /* 14h */ - U32 ActionData; /* 18h */ -} MSG_RAID_ACTION_REPLY, MPI_POINTER PTR_MSG_RAID_ACTION_REPLY, - MpiRaidActionReply_t, MPI_POINTER pMpiRaidActionReply_t; - - -/* RAID Volume reply ActionStatus values */ - -#define MPI_RAID_ACTION_ASTATUS_SUCCESS (0x0000) -#define MPI_RAID_ACTION_ASTATUS_INVALID_ACTION (0x0001) -#define MPI_RAID_ACTION_ASTATUS_FAILURE (0x0002) -#define MPI_RAID_ACTION_ASTATUS_IN_PROGRESS (0x0003) - - -/* RAID Volume reply RAID Volume Indicator structure */ - -typedef struct _MPI_RAID_VOL_INDICATOR -{ - U64 TotalBlocks; /* 00h */ - U64 BlocksRemaining; /* 08h */ -} MPI_RAID_VOL_INDICATOR, MPI_POINTER PTR_MPI_RAID_VOL_INDICATOR, - MpiRaidVolIndicator_t, MPI_POINTER pMpiRaidVolIndicator_t; - - -/****************************************************************************/ -/* SCSI IO RAID Passthrough Request */ -/****************************************************************************/ - -typedef struct _MSG_SCSI_IO_RAID_PT_REQUEST -{ - U8 PhysDiskNum; /* 00h */ - U8 Reserved1; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U8 CDBLength; /* 04h */ - U8 SenseBufferLength; /* 05h */ - U8 Reserved2; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U8 LUN[8]; /* 0Ch */ - U32 Control; /* 14h */ - U8 CDB[16]; /* 18h */ - U32 DataLength; /* 28h */ - U32 SenseBufferLowAddr; /* 2Ch */ - SGE_IO_UNION SGL; /* 30h */ -} MSG_SCSI_IO_RAID_PT_REQUEST, MPI_POINTER PTR_MSG_SCSI_IO_RAID_PT_REQUEST, - SCSIIORaidPassthroughRequest_t, MPI_POINTER pSCSIIORaidPassthroughRequest_t; - - -/* SCSI IO RAID Passthrough reply structure */ - -typedef struct _MSG_SCSI_IO_RAID_PT_REPLY -{ - U8 PhysDiskNum; /* 00h */ - U8 Reserved1; /* 01h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U8 CDBLength; /* 04h */ - U8 SenseBufferLength; /* 05h */ - U8 Reserved2; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U8 SCSIStatus; /* 0Ch */ - U8 SCSIState; /* 0Dh */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 TransferCount; /* 14h */ - U32 SenseCount; /* 18h */ - U32 ResponseInfo; /* 1Ch */ -} MSG_SCSI_IO_RAID_PT_REPLY, MPI_POINTER PTR_MSG_SCSI_IO_RAID_PT_REPLY, - SCSIIORaidPassthroughReply_t, MPI_POINTER pSCSIIORaidPassthroughReply_t; - - -/****************************************************************************/ -/* Mailbox reqeust structure */ -/****************************************************************************/ - -typedef struct _MSG_MAILBOX_REQUEST -{ - U16 Reserved1; - U8 ChainOffset; - U8 Function; - U16 Reserved2; - U8 Reserved3; - U8 MsgFlags; - U8 Command[10]; - U16 Reserved4; - SGE_IO_UNION SGL; -} MSG_MAILBOX_REQUEST, MPI_POINTER PTR_MSG_MAILBOX_REQUEST, - MailboxRequest_t, MPI_POINTER pMailboxRequest_t; - - -/* Mailbox reply structure */ -typedef struct _MSG_MAILBOX_REPLY -{ - U16 Reserved1; /* 00h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved2; /* 04h */ - U8 Reserved3; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 MailboxStatus; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 Reserved4; /* 14h */ -} MSG_MAILBOX_REPLY, MPI_POINTER PTR_MSG_MAILBOX_REPLY, - MailboxReply_t, MPI_POINTER pMailboxReply_t; - -#endif - - - diff --git a/xen/drivers/message/fusion/lsi/mpi_targ.h b/xen/drivers/message/fusion/lsi/mpi_targ.h deleted file mode 100644 index adc9b36d95..0000000000 --- a/xen/drivers/message/fusion/lsi/mpi_targ.h +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright (c) 2000-2002 LSI Logic Corporation. - * - * - * Name: MPI_TARG.H - * Title: MPI Target mode messages and structures - * Creation Date: June 22, 2000 - * - * MPI_TARG.H Version: 01.02.07 - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. - * 06-06-00 01.00.01 Update version number for 1.0 release. - * 06-22-00 01.00.02 Added _MSG_TARGET_CMD_BUFFER_POST_REPLY structure. - * Corrected DECSRIPTOR typo to DESCRIPTOR. - * 11-02-00 01.01.01 Original release for post 1.0 work - * Modified target mode to use IoIndex instead of - * HostIndex and IocIndex. Added Alias. - * 01-09-01 01.01.02 Added defines for TARGET_ASSIST_FLAGS_REPOST_CMD_BUFFER - * and TARGET_STATUS_SEND_FLAGS_REPOST_CMD_BUFFER. - * 02-20-01 01.01.03 Started using MPI_POINTER. - * Added structures for MPI_TARGET_SCSI_SPI_CMD_BUFFER and - * MPI_TARGET_FCP_CMD_BUFFER. - * 03-27-01 01.01.04 Added structure offset comments. - * 08-08-01 01.02.01 Original release for v1.2 work. - * 09-28-01 01.02.02 Added structure for MPI_TARGET_SCSI_SPI_STATUS_IU. - * Added PriorityReason field to some replies and - * defined more PriorityReason codes. - * Added some defines for to support previous version - * of MPI. - * 10-04-01 01.02.03 Added PriorityReason to MSG_TARGET_ERROR_REPLY. - * 11-01-01 01.02.04 Added define for TARGET_STATUS_SEND_FLAGS_HIGH_PRIORITY. - * 03-14-02 01.02.05 Modified MPI_TARGET_FCP_RSP_BUFFER to get the proper - * byte ordering. - * 05-31-02 01.02.06 Modified TARGET_MODE_REPLY_ALIAS_MASK to only include - * one bit. - * Added AliasIndex field to MPI_TARGET_FCP_CMD_BUFFER. - * 09-16-02 01.02.07 Added flags for confirmed completion. - * Added PRIORITY_REASON_TARGET_BUSY. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI_TARG_H -#define MPI_TARG_H - - -/****************************************************************************** -* -* S C S I T a r g e t M e s s a g e s -* -*******************************************************************************/ - -typedef struct _CMD_BUFFER_DESCRIPTOR -{ - U16 IoIndex; /* 00h */ - U16 Reserved; /* 02h */ - union /* 04h */ - { - U32 PhysicalAddress32; - U64 PhysicalAddress64; - } u; -} CMD_BUFFER_DESCRIPTOR, MPI_POINTER PTR_CMD_BUFFER_DESCRIPTOR, - CmdBufferDescriptor_t, MPI_POINTER pCmdBufferDescriptor_t; - - -/****************************************************************************/ -/* Target Command Buffer Post Request */ -/****************************************************************************/ - -typedef struct _MSG_TARGET_CMD_BUFFER_POST_REQUEST -{ - U8 BufferPostFlags; /* 00h */ - U8 BufferCount; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U8 BufferLength; /* 04h */ - U8 Reserved; /* 05h */ - U8 Reserved1; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - CMD_BUFFER_DESCRIPTOR Buffer[1]; /* 0Ch */ -} MSG_TARGET_CMD_BUFFER_POST_REQUEST, MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_REQUEST, - TargetCmdBufferPostRequest_t, MPI_POINTER pTargetCmdBufferPostRequest_t; - -#define CMD_BUFFER_POST_FLAGS_PORT_MASK (0x01) -#define CMD_BUFFER_POST_FLAGS_ADDR_MODE_MASK (0x80) -#define CMD_BUFFER_POST_FLAGS_ADDR_MODE_32 (0) -#define CMD_BUFFER_POST_FLAGS_ADDR_MODE_64 (1) -#define CMD_BUFFER_POST_FLAGS_64_BIT_ADDR (0x80) - -#define CMD_BUFFER_POST_IO_INDEX_MASK (0x00003FFF) -#define CMD_BUFFER_POST_IO_INDEX_MASK_0100 (0x000003FF) /* obsolete */ - - -typedef struct _MSG_TARGET_CMD_BUFFER_POST_REPLY -{ - U8 BufferPostFlags; /* 00h */ - U8 BufferCount; /* 01h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U8 BufferLength; /* 04h */ - U8 Reserved; /* 05h */ - U8 Reserved1; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved2; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ -} MSG_TARGET_CMD_BUFFER_POST_REPLY, MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_REPLY, - TargetCmdBufferPostReply_t, MPI_POINTER pTargetCmdBufferPostReply_t; - -/* the following structure is obsolete as of MPI v1.2 */ -typedef struct _MSG_PRIORITY_CMD_RECEIVED_REPLY -{ - U16 Reserved; /* 00h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved1; /* 04h */ - U8 Reserved2; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U8 PriorityReason; /* 0Ch */ - U8 Reserved3; /* 0Dh */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 ReplyWord; /* 14h */ -} MSG_PRIORITY_CMD_RECEIVED_REPLY, MPI_POINTER PTR_MSG_PRIORITY_CMD_RECEIVED_REPLY, - PriorityCommandReceivedReply_t, MPI_POINTER pPriorityCommandReceivedReply_t; - -#define PRIORITY_REASON_NO_DISCONNECT (0x00) -#define PRIORITY_REASON_SCSI_TASK_MANAGEMENT (0x01) -#define PRIORITY_REASON_CMD_PARITY_ERR (0x02) -#define PRIORITY_REASON_MSG_OUT_PARITY_ERR (0x03) -#define PRIORITY_REASON_LQ_CRC_ERR (0x04) -#define PRIORITY_REASON_CMD_CRC_ERR (0x05) -#define PRIORITY_REASON_PROTOCOL_ERR (0x06) -#define PRIORITY_REASON_DATA_OUT_PARITY_ERR (0x07) -#define PRIORITY_REASON_DATA_OUT_CRC_ERR (0x08) -#define PRIORITY_REASON_TARGET_BUSY (0x09) -#define PRIORITY_REASON_UNKNOWN (0xFF) - - -typedef struct _MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY -{ - U16 Reserved; /* 00h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved1; /* 04h */ - U8 Reserved2; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U8 PriorityReason; /* 0Ch */ - U8 Reserved3; /* 0Dh */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 ReplyWord; /* 14h */ -} MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY, - MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY, - TargetCmdBufferPostErrorReply_t, MPI_POINTER pTargetCmdBufferPostErrorReply_t; - - -typedef struct _MPI_TARGET_FCP_CMD_BUFFER -{ - U8 FcpLun[8]; /* 00h */ - U8 FcpCntl[4]; /* 08h */ - U8 FcpCdb[16]; /* 0Ch */ - U32 FcpDl; /* 1Ch */ - U8 AliasIndex; /* 20h */ - U8 Reserved1; /* 21h */ - U16 Reserved2; /* 22h */ -} MPI_TARGET_FCP_CMD_BUFFER, MPI_POINTER PTR_MPI_TARGET_FCP_CMD_BUFFER, - MpiTargetFcpCmdBuffer, MPI_POINTER pMpiTargetFcpCmdBuffer; - - -typedef struct _MPI_TARGET_SCSI_SPI_CMD_BUFFER -{ - /* SPI L_Q information unit */ - U8 L_QType; /* 00h */ - U8 Reserved; /* 01h */ - U16 Tag; /* 02h */ - U8 LogicalUnitNumber[8]; /* 04h */ - U32 DataLength; /* 0Ch */ - /* SPI command information unit */ - U8 ReservedFirstByteOfCommandIU; /* 10h */ - U8 TaskAttribute; /* 11h */ - U8 TaskManagementFlags; /* 12h */ - U8 AdditionalCDBLength; /* 13h */ - U8 CDB[16]; /* 14h */ -} MPI_TARGET_SCSI_SPI_CMD_BUFFER, - MPI_POINTER PTR_MPI_TARGET_SCSI_SPI_CMD_BUFFER, - MpiTargetScsiSpiCmdBuffer, MPI_POINTER pMpiTargetScsiSpiCmdBuffer; - - -/****************************************************************************/ -/* Target Assist Request */ -/****************************************************************************/ - -typedef struct _MSG_TARGET_ASSIST_REQUEST -{ - U8 StatusCode; /* 00h */ - U8 TargetAssistFlags; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U16 QueueTag; /* 04h */ - U8 Reserved; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U32 ReplyWord; /* 0Ch */ - U8 LUN[8]; /* 10h */ - U32 RelativeOffset; /* 18h */ - U32 DataLength; /* 1Ch */ - SGE_IO_UNION SGL[1]; /* 20h */ -} MSG_TARGET_ASSIST_REQUEST, MPI_POINTER PTR_MSG_TARGET_ASSIST_REQUEST, - TargetAssistRequest_t, MPI_POINTER pTargetAssistRequest_t; - -#define TARGET_ASSIST_FLAGS_DATA_DIRECTION (0x01) -#define TARGET_ASSIST_FLAGS_AUTO_STATUS (0x02) -#define TARGET_ASSIST_FLAGS_HIGH_PRIORITY (0x04) -#define TARGET_ASSIST_FLAGS_CONFIRMED (0x08) -#define TARGET_ASSIST_FLAGS_REPOST_CMD_BUFFER (0x80) - - -typedef struct _MSG_TARGET_ERROR_REPLY -{ - U16 Reserved; /* 00h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved1; /* 04h */ - U8 Reserved2; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U8 PriorityReason; /* 0Ch */ - U8 Reserved3; /* 0Dh */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 ReplyWord; /* 14h */ - U32 TransferCount; /* 18h */ -} MSG_TARGET_ERROR_REPLY, MPI_POINTER PTR_MSG_TARGET_ERROR_REPLY, - TargetErrorReply_t, MPI_POINTER pTargetErrorReply_t; - - -/****************************************************************************/ -/* Target Status Send Request */ -/****************************************************************************/ - -typedef struct _MSG_TARGET_STATUS_SEND_REQUEST -{ - U8 StatusCode; /* 00h */ - U8 StatusFlags; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U16 QueueTag; /* 04h */ - U8 Reserved; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U32 ReplyWord; /* 0Ch */ - U8 LUN[8]; /* 10h */ - SGE_SIMPLE_UNION StatusDataSGE; /* 18h */ -} MSG_TARGET_STATUS_SEND_REQUEST, MPI_POINTER PTR_MSG_TARGET_STATUS_SEND_REQUEST, - TargetStatusSendRequest_t, MPI_POINTER pTargetStatusSendRequest_t; - -#define TARGET_STATUS_SEND_FLAGS_AUTO_GOOD_STATUS (0x01) -#define TARGET_STATUS_SEND_FLAGS_HIGH_PRIORITY (0x04) -#define TARGET_STATUS_SEND_FLAGS_CONFIRMED (0x08) -#define TARGET_STATUS_SEND_FLAGS_REPOST_CMD_BUFFER (0x80) - -/* - * NOTE: FCP_RSP data is big-endian. When used on a little-endian system, this - * structure properly orders the bytes. - */ -typedef struct _MPI_TARGET_FCP_RSP_BUFFER -{ - U8 Reserved0[8]; /* 00h */ - U8 Reserved1[2]; /* 08h */ - U8 FcpFlags; /* 0Ah */ - U8 FcpStatus; /* 0Bh */ - U32 FcpResid; /* 0Ch */ - U32 FcpSenseLength; /* 10h */ - U32 FcpResponseLength; /* 14h */ - U8 FcpResponseData[8]; /* 18h */ - U8 FcpSenseData[32]; /* Pad to 64 bytes */ /* 20h */ -} MPI_TARGET_FCP_RSP_BUFFER, MPI_POINTER PTR_MPI_TARGET_FCP_RSP_BUFFER, - MpiTargetFcpRspBuffer, MPI_POINTER pMpiTargetFcpRspBuffer; - -/* - * NOTE: The SPI status IU is big-endian. When used on a little-endian system, - * this structure properly orders the bytes. - */ -typedef struct _MPI_TARGET_SCSI_SPI_STATUS_IU -{ - U8 Reserved0; /* 00h */ - U8 Reserved1; /* 01h */ - U8 Valid; /* 02h */ - U8 Status; /* 03h */ - U32 SenseDataListLength; /* 04h */ - U32 PktFailuresListLength; /* 08h */ - U8 SenseData[52]; /* Pad the IU to 64 bytes */ /* 0Ch */ -} MPI_TARGET_SCSI_SPI_STATUS_IU, MPI_POINTER PTR_MPI_TARGET_SCSI_SPI_STATUS_IU, - TargetScsiSpiStatusIU_t, MPI_POINTER pTargetScsiSpiStatusIU_t; - -/****************************************************************************/ -/* Target Mode Abort Request */ -/****************************************************************************/ - -typedef struct _MSG_TARGET_MODE_ABORT_REQUEST -{ - U8 AbortType; /* 00h */ - U8 Reserved; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved1; /* 04h */ - U8 Reserved2; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U32 ReplyWord; /* 0Ch */ - U32 MsgContextToAbort; /* 10h */ -} MSG_TARGET_MODE_ABORT, MPI_POINTER PTR_MSG_TARGET_MODE_ABORT, - TargetModeAbort_t, MPI_POINTER pTargetModeAbort_t; - -#define TARGET_MODE_ABORT_TYPE_ALL_CMD_BUFFERS (0x00) -#define TARGET_MODE_ABORT_TYPE_ALL_IO (0x01) -#define TARGET_MODE_ABORT_TYPE_EXACT_IO (0x02) -#define TARGET_MODE_ABORT_TYPE_EXACT_IO_REQUEST (0x03) - -/* Target Mode Abort Reply */ - -typedef struct _MSG_TARGET_MODE_ABORT_REPLY -{ - U16 Reserved; /* 00h */ - U8 MsgLength; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved1; /* 04h */ - U8 Reserved2; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ - U16 Reserved3; /* 0Ch */ - U16 IOCStatus; /* 0Eh */ - U32 IOCLogInfo; /* 10h */ - U32 AbortCount; /* 14h */ -} MSG_TARGET_MODE_ABORT_REPLY, MPI_POINTER PTR_MSG_TARGET_MODE_ABORT_REPLY, - TargetModeAbortReply_t, MPI_POINTER pTargetModeAbortReply_t; - - -/****************************************************************************/ -/* Target Mode Context Reply */ -/****************************************************************************/ - -#define TARGET_MODE_REPLY_IO_INDEX_MASK (0x00003FFF) -#define TARGET_MODE_REPLY_IO_INDEX_SHIFT (0) -#define TARGET_MODE_REPLY_INITIATOR_INDEX_MASK (0x03FFC000) -#define TARGET_MODE_REPLY_INITIATOR_INDEX_SHIFT (14) -#define TARGET_MODE_REPLY_ALIAS_MASK (0x04000000) -#define TARGET_MODE_REPLY_ALIAS_SHIFT (26) -#define TARGET_MODE_REPLY_PORT_MASK (0x10000000) -#define TARGET_MODE_REPLY_PORT_SHIFT (28) - - -#define GET_IO_INDEX(x) (((x) & TARGET_MODE_REPLY_IO_INDEX_MASK) \ - >> TARGET_MODE_REPLY_IO_INDEX_SHIFT) - -#define SET_IO_INDEX(t, i) \ - ((t) = ((t) & ~TARGET_MODE_REPLY_IO_INDEX_MASK) | \ - (((i) << TARGET_MODE_REPLY_IO_INDEX_SHIFT) & \ - TARGET_MODE_REPLY_IO_INDEX_MASK)) - -#define GET_INITIATOR_INDEX(x) (((x) & TARGET_MODE_REPLY_INITIATOR_INDEX_MASK) \ - >> TARGET_MODE_REPLY_INITIATOR_INDEX_SHIFT) - -#define SET_INITIATOR_INDEX(t, ii) \ - ((t) = ((t) & ~TARGET_MODE_REPLY_INITIATOR_INDEX_MASK) | \ - (((ii) << TARGET_MODE_REPLY_INITIATOR_INDEX_SHIFT) & \ - TARGET_MODE_REPLY_INITIATOR_INDEX_MASK)) - -#define GET_ALIAS(x) (((x) & TARGET_MODE_REPLY_ALIAS_MASK) \ - >> TARGET_MODE_REPLY_ALIAS_SHIFT) - -#define SET_ALIAS(t, a) ((t) = ((t) & ~TARGET_MODE_REPLY_ALIAS_MASK) | \ - (((a) << TARGET_MODE_REPLY_ALIAS_SHIFT) & \ - TARGET_MODE_REPLY_ALIAS_MASK)) - -#define GET_PORT(x) (((x) & TARGET_MODE_REPLY_PORT_MASK) \ - >> TARGET_MODE_REPLY_PORT_SHIFT) - -#define SET_PORT(t, p) ((t) = ((t) & ~TARGET_MODE_REPLY_PORT_MASK) | \ - (((p) << TARGET_MODE_REPLY_PORT_SHIFT) & \ - TARGET_MODE_REPLY_PORT_MASK)) - -/* the following obsolete values are for MPI v1.0 support */ -#define TARGET_MODE_REPLY_0100_MASK_HOST_INDEX (0x000003FF) -#define TARGET_MODE_REPLY_0100_SHIFT_HOST_INDEX (0) -#define TARGET_MODE_REPLY_0100_MASK_IOC_INDEX (0x001FF800) -#define TARGET_MODE_REPLY_0100_SHIFT_IOC_INDEX (11) -#define TARGET_MODE_REPLY_0100_PORT_MASK (0x00400000) -#define TARGET_MODE_REPLY_0100_PORT_SHIFT (22) -#define TARGET_MODE_REPLY_0100_MASK_INITIATOR_INDEX (0x1F800000) -#define TARGET_MODE_REPLY_0100_SHIFT_INITIATOR_INDEX (23) - -#define GET_HOST_INDEX_0100(x) (((x) & TARGET_MODE_REPLY_0100_MASK_HOST_INDEX) \ - >> TARGET_MODE_REPLY_0100_SHIFT_HOST_INDEX) - -#define SET_HOST_INDEX_0100(t, hi) \ - ((t) = ((t) & ~TARGET_MODE_REPLY_0100_MASK_HOST_INDEX) | \ - (((hi) << TARGET_MODE_REPLY_0100_SHIFT_HOST_INDEX) & \ - TARGET_MODE_REPLY_0100_MASK_HOST_INDEX)) - -#define GET_IOC_INDEX_0100(x) (((x) & TARGET_MODE_REPLY_0100_MASK_IOC_INDEX) \ - >> TARGET_MODE_REPLY_0100_SHIFT_IOC_INDEX) - -#define SET_IOC_INDEX_0100(t, ii) \ - ((t) = ((t) & ~TARGET_MODE_REPLY_0100_MASK_IOC_INDEX) | \ - (((ii) << TARGET_MODE_REPLY_0100_SHIFT_IOC_INDEX) & \ - TARGET_MODE_REPLY_0100_MASK_IOC_INDEX)) - -#define GET_INITIATOR_INDEX_0100(x) \ - (((x) & TARGET_MODE_REPLY_0100_MASK_INITIATOR_INDEX) \ - >> TARGET_MODE_REPLY_0100_SHIFT_INITIATOR_INDEX) - -#define SET_INITIATOR_INDEX_0100(t, ii) \ - ((t) = ((t) & ~TARGET_MODE_REPLY_0100_MASK_INITIATOR_INDEX) | \ - (((ii) << TARGET_MODE_REPLY_0100_SHIFT_INITIATOR_INDEX) & \ - TARGET_MODE_REPLY_0100_MASK_INITIATOR_INDEX)) - - -#endif - diff --git a/xen/drivers/message/fusion/lsi/mpi_type.h b/xen/drivers/message/fusion/lsi/mpi_type.h deleted file mode 100644 index 7e94ee9d36..0000000000 --- a/xen/drivers/message/fusion/lsi/mpi_type.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2000-2002 LSI Logic Corporation. - * - * - * Name: MPI_TYPE.H - * Title: MPI Basic type definitions - * Creation Date: June 6, 2000 - * - * MPI Version: 01.02.01 - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 05-08-00 00.10.01 Original release for 0.10 spec dated 4/26/2000. - * 06-06-00 01.00.01 Update version number for 1.0 release. - * 11-02-00 01.01.01 Original release for post 1.0 work - * 02-20-01 01.01.02 Added define and ifdef for MPI_POINTER. - * 08-08-01 01.02.01 Original release for v1.2 work. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI_TYPE_H -#define MPI_TYPE_H - - -/******************************************************************************* - * Define MPI_POINTER if it hasn't already been defined. By default MPI_POINTER - * is defined to be a near pointer. MPI_POINTER can be defined as a far pointer - * by defining MPI_POINTER as "far *" before this header file is included. - */ -#ifndef MPI_POINTER -#define MPI_POINTER * -#endif - - -/***************************************************************************** -* -* B a s i c T y p e s -* -*****************************************************************************/ - -typedef signed char S8; -typedef unsigned char U8; -typedef signed short S16; -typedef unsigned short U16; - - -#if defined(unix) || defined(__arm) || defined(ALPHA) - - typedef signed int S32; - typedef unsigned int U32; - -#else - - typedef signed long S32; - typedef unsigned long U32; - -#endif - - -typedef struct _S64 -{ - U32 Low; - S32 High; -} S64; - -typedef struct _U64 -{ - U32 Low; - U32 High; -} U64; - - -/****************************************************************************/ -/* Pointers */ -/****************************************************************************/ - -typedef S8 *PS8; -typedef U8 *PU8; -typedef S16 *PS16; -typedef U16 *PU16; -typedef S32 *PS32; -typedef U32 *PU32; -typedef S64 *PS64; -typedef U64 *PU64; - - -#endif - diff --git a/xen/drivers/message/fusion/mptbase.c b/xen/drivers/message/fusion/mptbase.c deleted file mode 100644 index 1d3232c654..0000000000 --- a/xen/drivers/message/fusion/mptbase.c +++ /dev/null @@ -1,6130 +0,0 @@ -/* - * linux/drivers/message/fusion/mptbase.c - * High performance SCSI + LAN / Fibre Channel device drivers. - * This is the Fusion MPT base driver which supports multiple - * (SCSI + LAN) specialized protocol drivers. - * For use with PCI chip/adapter(s): - * LSIFC9xx/LSI409xx Fibre Channel - * running LSI Logic Fusion MPT (Message Passing Technology) firmware. - * - * Credits: - * There are lots of people not mentioned below that deserve credit - * and thanks but won't get it here - sorry in advance that you - * got overlooked. - * - * This driver would not exist if not for Alan Cox's development - * of the linux i2o driver. - * - * A special thanks to Noah Romer (LSI Logic) for tons of work - * and tough debugging on the LAN driver, especially early on;-) - * And to Roger Hickerson (LSI Logic) for tirelessly supporting - * this driver project. - * - * A special thanks to Pamela Delaney (LSI Logic) for tons of work - * and countless enhancements while adding support for the 1030 - * chip family. Pam has been instrumental in the development of - * of the 2.xx.xx series fusion drivers, and her contributions are - * far too numerous to hope to list in one place. - * - * All manner of help from Stephen Shirron (LSI Logic): - * low-level FC analysis, debug + various fixes in FCxx firmware, - * initial port to alpha platform, various driver code optimizations, - * being a faithful sounding board on all sorts of issues & ideas, - * etc. - * - * A huge debt of gratitude is owed to David S. Miller (DaveM) - * for fixing much of the stupid and broken stuff in the early - * driver while porting to sparc64 platform. THANK YOU! - * - * Special thanks goes to the I2O LAN driver people at the - * University of Helsinki, who, unbeknownst to them, provided - * the inspiration and initial structure for this driver. - * - * A really huge debt of gratitude is owed to Eddie C. Dost - * for gobs of hard work fixing and optimizing LAN code. - * THANK YOU! - * - * Copyright (c) 1999-2002 LSI Logic Corporation - * Originally By: Steven J. Ralston - * (mailto:sjralston1@netscape.net) - * (mailto:lstephens@lsil.com) - * - * $Id: mptbase.c,v 1.130 2003/05/07 14:08:30 pdelaney Exp $ - */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - NO WARRANTY - THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - solely responsible for determining the appropriateness of using and - distributing the Program and assumes all risks associated with its - exercise of rights under this Agreement, including but not limited to - the risks and costs of program errors, damage to or loss of data, - programs or equipment, and unavailability or interruption of operations. - - DISCLAIMER OF LIABILITY - NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* needed for in_interrupt() proto */ -#include /* SAE: Necessary... */ -#include -#ifdef CONFIG_MTRR -#include -#endif -#ifdef __sparc__ -#include /* needed for __irq_itoa() proto */ -#endif - -#include "mptbase.h" - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#define my_NAME "Fusion MPT base driver" -#define my_VERSION MPT_LINUX_VERSION_COMMON -#define MYNAM "mptbase" - -MODULE_AUTHOR(MODULEAUTHOR); -MODULE_DESCRIPTION(my_NAME); -MODULE_LICENSE("GPL"); - -/* - * cmd line parameters - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,59) -MODULE_PARM(PortIo, "0-1i"); -MODULE_PARM_DESC(PortIo, "[0]=Use mmap, 1=Use port io"); -#endif -static int PortIo = 0; - -#ifdef MFCNT -static int mfcounter = 0; -#define PRINT_MF_COUNT 20000 -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Public data... - */ -int mpt_lan_index = -1; -int mpt_stm_index = -1; - -/* SAE: Xen doesn't have proc */ -#if defined(CONFIG_PROC_FS) - -struct proc_dir_entry *mpt_proc_root_dir; - -#endif - -DmpServices_t *DmpService; - -void *mpt_v_ASCQ_TablePtr; -const char **mpt_ScsiOpcodesPtr; -int mpt_ASCQ_TableSz; - - -#define WHOINIT_UNKNOWN 0xAA - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Private data... - */ - /* Adapter lookup table */ - MPT_ADAPTER *mpt_adapters[MPT_MAX_ADAPTERS]; -static MPT_ADAPTER_TRACKER MptAdapters; - /* Callback lookup table */ -static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS]; - /* Protocol driver class lookup table */ -static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS]; - /* Event handler lookup table */ -static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS]; - /* Reset handler lookup table */ -static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS]; - -static int FusionInitCalled = 0; -static int mpt_base_index = -1; -static int last_drv_idx = -1; -static int isense_idx = -1; - -/* SAE: No wait queues or threads */ -#ifdef XEN_KILLED -static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq); -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Forward protos... - */ -static void mpt_interrupt(int irq, void *bus_id, struct pt_regs *r); -static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply); - -static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag); -static int mpt_adapter_install(struct pci_dev *pdev); -static void mpt_detect_bound_ports(MPT_ADAPTER *this, struct pci_dev *pdev); -static void mpt_adapter_disable(MPT_ADAPTER *ioc, int freeup); -static void mpt_adapter_dispose(MPT_ADAPTER *ioc); - -static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc); -static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag); -//static u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked); -static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason); -static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag); -static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag); -static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag); -static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag); -static int mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag); -static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag); -static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag); -static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag); -static int PrimeIocFifos(MPT_ADAPTER *ioc); -static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag); -static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag); -static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag); -static int GetLanConfigPages(MPT_ADAPTER *ioc); -static int GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); -static int GetIoUnitPage2(MPT_ADAPTER *ioc); -static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum); -static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum); -static int mpt_findImVolumes(MPT_ADAPTER *ioc); -static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc); -static void mpt_timer_expired(unsigned long data); -static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch); -static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp); - -#if defined(CONFIG_PROC_FS) -static int procmpt_create(void); -static int procmpt_destroy(void); -static int procmpt_summary_read(char *buf, char **start, off_t offset, - int request, int *eof, void *data); -static int procmpt_version_read(char *buf, char **start, off_t offset, - int request, int *eof, void *data); -static int procmpt_iocinfo_read(char *buf, char **start, off_t offset, - int request, int *eof, void *data); -#endif -static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc); - -//int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag); -static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers); -static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); -static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info); - -int fusion_init(void); -static void fusion_exit(void); - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * more Private data... - */ -#if defined(CONFIG_PROC_FS) -struct _mpt_proc_list { - const char *name; - int (*f)(char *, char **, off_t, int, int *, void *); -} mpt_proc_list[] = { - { "summary", procmpt_summary_read}, - { "version", procmpt_version_read}, -}; -#define MPT_PROC_ENTRIES (sizeof(mpt_proc_list)/sizeof(mpt_proc_list[0])) - -struct _mpt_ioc_proc_list { - const char *name; - int (*f)(char *, char **, off_t, int, int *, void *); -} mpt_ioc_proc_list[] = { - { "info", procmpt_iocinfo_read}, - { "summary", procmpt_summary_read}, -}; -#define MPT_IOC_PROC_ENTRIES (sizeof(mpt_ioc_proc_list)/sizeof(mpt_ioc_proc_list[0])) - -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* 20000207 -sralston - * GRRRRR... IOSpace (port i/o) register access (for the 909) is back! - * 20000517 -sralston - * Let's trying going back to default mmap register access... - */ - -static inline u32 CHIPREG_READ32(volatile u32 *a) -{ - if (PortIo) - return inl((unsigned long)a); - else - return readl(a); -} - -static inline void CHIPREG_WRITE32(volatile u32 *a, u32 v) -{ - if (PortIo) - outl(v, (unsigned long)a); - else - writel(v, a); -} - -static inline void CHIPREG_PIO_WRITE32(volatile u32 *a, u32 v) -{ - outl(v, (unsigned long)a); -} - -static inline u32 CHIPREG_PIO_READ32(volatile u32 *a) -{ - return inl((unsigned long)a); -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_interrupt - MPT adapter (IOC) specific interrupt handler. - * @irq: irq number (not used) - * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure - * @r: pt_regs pointer (not used) - * - * This routine is registered via the request_irq() kernel API call, - * and handles all interrupts generated from a specific MPT adapter - * (also referred to as a IO Controller or IOC). - * This routine must clear the interrupt from the adapter and does - * so by reading the reply FIFO. Multiple replies may be processed - * per single call to this routine; up to MPT_MAX_REPLIES_PER_ISR - * which is currently set to 32 in mptbase.h. - * - * This routine handles register-level access of the adapter but - * dispatches (calls) a protocol-specific callback routine to handle - * the protocol-specific details of the MPT request completion. - */ -static void -mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) -{ - MPT_ADAPTER *ioc; - MPT_FRAME_HDR *mf; - MPT_FRAME_HDR *mr; - u32 pa; - int req_idx = -1; - int cb_idx; - int type; - int freeme; - int count = 0; - - ioc = bus_id; - - /* - * Verify ioc pointer is ok - */ - { - MPT_ADAPTER *iocCmp; - iocCmp = mpt_adapter_find_first(); - while ((ioc != iocCmp) && iocCmp) - iocCmp = mpt_adapter_find_next(iocCmp); - - if (!iocCmp) { - printk(KERN_WARNING "mpt_interrupt: Invalid ioc!\n"); - return; - } - } - - /* - * Drain the reply FIFO! - * - * NOTES: I've seen up to 10 replies processed in this loop, so far... - * Update: I've seen up to 9182 replies processed in this loop! ?? - * Update: Limit ourselves to processing max of N replies - * (bottom of loop). - */ - while (1) { - - if ((pa = CHIPREG_READ32(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF) - return; - - cb_idx = 0; - freeme = 0; - - /* - * Check for non-TURBO reply! - */ - if (pa & MPI_ADDRESS_REPLY_A_BIT) { - u32 reply_dma_low; - u16 ioc_stat; - - /* non-TURBO reply! Hmmm, something may be up... - * Newest turbo reply mechanism; get address - * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)! - */ - - /* Map DMA address of reply header to cpu address. - * pa is 32 bits - but the dma address may be 32 or 64 bits - * get offset based only only the low addresses - */ - reply_dma_low = (pa = (pa << 1)); - mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames + - (reply_dma_low - ioc->reply_frames_low_dma)); - - req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx); - cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx; - mf = MPT_INDEX_2_MFPTR(ioc, req_idx); - - dprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p\n", - ioc->name, mr)); - DBG_DUMP_REPLY_FRAME(mr) - - /* NEW! 20010301 -sralston - * Check/log IOC log info - */ - ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus); - if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { - u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo); - if ((int)ioc->chip_type <= (int)FC929) - mpt_fc_log_info(ioc, log_info); - else - mpt_sp_log_info(ioc, log_info); - } - } else { - /* - * Process turbo (context) reply... - */ - dirqprintk((MYIOC_s_INFO_FMT "Got TURBO reply(=%08x)\n", ioc->name, pa)); - type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT); - if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) { - cb_idx = mpt_stm_index; - mf = NULL; - mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); - } else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) { - cb_idx = mpt_lan_index; - /* - * BUG FIX! 20001218 -sralston - * Blind set of mf to NULL here was fatal - * after lan_reply says "freeme" - * Fix sort of combined with an optimization here; - * added explicit check for case where lan_reply - * was just returning 1 and doing nothing else. - * For this case skip the callback, but set up - * proper mf value first here:-) - */ - if ((pa & 0x58000000) == 0x58000000) { - req_idx = pa & 0x0000FFFF; - mf = MPT_INDEX_2_MFPTR(ioc, req_idx); - freeme = 1; - /* - * IMPORTANT! Invalidate the callback! - */ - cb_idx = 0; - } else { - mf = NULL; - } - mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); - } else { - req_idx = pa & 0x0000FFFF; - cb_idx = (pa & 0x00FF0000) >> 16; - mf = MPT_INDEX_2_MFPTR(ioc, req_idx); - mr = NULL; - } - pa = 0; /* No reply flush! */ - } - -#ifdef MPT_DEBUG_IRQ - if ((int)ioc->chip_type > (int)FC929) { - /* Verify mf, mr are reasonable. - */ - if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth)) - || (mf < ioc->req_frames)) ) { - printk(MYIOC_s_WARN_FMT - "mpt_interrupt: Invalid mf (%p) req_idx (%d)!\n", ioc->name, (void *)mf, req_idx); - cb_idx = 0; - pa = 0; - freeme = 0; - } - if ((pa) && (mr) && ((mr >= MPT_INDEX_2_RFPTR(ioc, ioc->req_depth)) - || (mr < ioc->reply_frames)) ) { - printk(MYIOC_s_WARN_FMT - "mpt_interrupt: Invalid rf (%p)!\n", ioc->name, (void *)mr); - cb_idx = 0; - pa = 0; - freeme = 0; - } - if (cb_idx > (MPT_MAX_PROTOCOL_DRIVERS-1)) { - printk(MYIOC_s_WARN_FMT - "mpt_interrupt: Invalid cb_idx (%d)!\n", ioc->name, cb_idx); - cb_idx = 0; - pa = 0; - freeme = 0; - } - } -#endif - - /* Check for (valid) IO callback! */ - if (cb_idx) { - /* Do the callback! */ - freeme = (*(MptCallbacks[cb_idx]))(ioc, mf, mr); - } - - if (pa) { - /* Flush (non-TURBO) reply with a WRITE! */ - CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa); - } - - if (freeme) { - unsigned long flags; - - /* Put Request back on FreeQ! */ - spin_lock_irqsave(&ioc->FreeQlock, flags); - Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR); -#ifdef MFCNT - ioc->mfcnt--; -#endif - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - } - - count++; - dirqprintk((MYIOC_s_INFO_FMT "ISR processed frame #%d\n", ioc->name, count)); - mb(); - - if (count >= MPT_MAX_REPLIES_PER_ISR) { - dirqprintk((MYIOC_s_INFO_FMT "ISR processed %d replies.", - ioc->name, count)); - dirqprintk((" Giving this ISR a break!\n")); - return; - } - - } /* drain reply FIFO */ -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_base_reply - MPT base driver's callback routine; all base driver - * "internal" request/reply processing is routed here. - * Currently used for EventNotification and EventAck handling. - * @ioc: Pointer to MPT_ADAPTER structure - * @mf: Pointer to original MPT request frame - * @reply: Pointer to MPT reply frame (NULL if TurboReply) - * - * Returns 1 indicating original alloc'd request frame ptr - * should be freed, or 0 if it shouldn't. - */ -static int -mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) -{ - int freereq = 1; - u8 func; - - dprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name)); - - if ((mf == NULL) || - (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) { - printk(MYIOC_s_ERR_FMT "NULL or BAD request frame ptr! (=%p)\n", - ioc->name, (void *)mf); - return 1; - } - - if (reply == NULL) { - dprintk((MYIOC_s_ERR_FMT "Unexpected NULL Event (turbo?) reply!\n", - ioc->name)); - return 1; - } - - if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) { - dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf)); - DBG_DUMP_REQUEST_FRAME_HDR(mf) - } - - func = reply->u.hdr.Function; - dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n", - ioc->name, func)); - - if (func == MPI_FUNCTION_EVENT_NOTIFICATION) { - EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply; - int evHandlers = 0; - int results; - - results = ProcessEventNotification(ioc, pEvReply, &evHandlers); - if (results != evHandlers) { - /* CHECKME! Any special handling needed here? */ - dprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n", - ioc->name, evHandlers, results)); - } - - /* - * Hmmm... It seems that EventNotificationReply is an exception - * to the rule of one reply per request. - */ - if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) - freereq = 0; - -#ifdef CONFIG_PROC_FS -// LogEvent(ioc, pEvReply); -#endif - - } else if (func == MPI_FUNCTION_EVENT_ACK) { - dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n", - ioc->name)); - } else if (func == MPI_FUNCTION_CONFIG) { - CONFIGPARMS *pCfg; - unsigned long flags; - - dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n", - ioc->name, mf, reply)); - - pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *))); - - if (pCfg) { - /* disable timer and remove from linked list */ - del_timer(&pCfg->timer); - - spin_lock_irqsave(&ioc->FreeQlock, flags); - Q_DEL_ITEM(&pCfg->linkage); - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - - /* - * If IOC Status is SUCCESS, save the header - * and set the status code to GOOD. - */ - pCfg->status = MPT_CONFIG_ERROR; - if (reply) { - ConfigReply_t *pReply = (ConfigReply_t *)reply; - u16 status; - - status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; - dcprintk((KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n", - status, le32_to_cpu(pReply->IOCLogInfo))); - - pCfg->status = status; - if (status == MPI_IOCSTATUS_SUCCESS) { - pCfg->hdr->PageVersion = pReply->Header.PageVersion; - pCfg->hdr->PageLength = pReply->Header.PageLength; - pCfg->hdr->PageNumber = pReply->Header.PageNumber; - pCfg->hdr->PageType = pReply->Header.PageType; - } - } - - /* - * Wake up the original calling thread - */ - pCfg->wait_done = 1; -#ifdef XEN_KILLED - wake_up(&mpt_waitq); -#else - mdelay(250); -#endif - } - } else { - printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n", - ioc->name, func); - } - - /* - * Conditionally tell caller to free the original - * EventNotification/EventAck/unexpected request frame! - */ - return freereq; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_register - Register protocol-specific main callback handler. - * @cbfunc: callback function pointer - * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value) - * - * This routine is called by a protocol-specific driver (SCSI host, - * LAN, SCSI target) to register it's reply callback routine. Each - * protocol-specific driver must do this before it will be able to - * use any IOC resources, such as obtaining request frames. - * - * NOTES: The SCSI protocol driver currently calls this routine thrice - * in order to register separate callbacks; one for "normal" SCSI IO; - * one for MptScsiTaskMgmt requests; one for Scan/DV requests. - * - * Returns a positive integer valued "handle" in the - * range (and S.O.D. order) {N,...,7,6,5,...,1} if successful. - * Any non-positive return value (including zero!) should be considered - * an error by the caller. - */ -int -mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass) -{ - int i; - - last_drv_idx = -1; - -#ifndef MODULE - /* - * Handle possibility of the mptscsih_detect() routine getting - * called *before* fusion_init! - */ - if (!FusionInitCalled) { - dprintk((KERN_INFO MYNAM ": Hmmm, calling fusion_init from mpt_register!\n")); - /* - * NOTE! We'll get recursion here, as fusion_init() - * calls mpt_register()! - */ - fusion_init(); - FusionInitCalled++; - } -#endif - - /* - * Search for empty callback slot in this order: {N,...,7,6,5,...,1} - * (slot/handle 0 is reserved!) - */ - for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) { - if (MptCallbacks[i] == NULL) { - MptCallbacks[i] = cbfunc; - MptDriverClass[i] = dclass; - MptEvHandlers[i] = NULL; - last_drv_idx = i; - if (cbfunc != mpt_base_reply) { - mpt_inc_use_count(); - } - break; - } - } - - return last_drv_idx; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_deregister - Deregister a protocol drivers resources. - * @cb_idx: previously registered callback handle - * - * Each protocol-specific driver should call this routine when it's - * module is unloaded. - */ -void -mpt_deregister(int cb_idx) -{ - if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) { - MptCallbacks[cb_idx] = NULL; - MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER; - MptEvHandlers[cb_idx] = NULL; - - last_drv_idx++; - if (isense_idx != -1 && isense_idx <= cb_idx) - isense_idx++; - - if (cb_idx != mpt_base_index) { - mpt_dec_use_count(); - } - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_event_register - Register protocol-specific event callback - * handler. - * @cb_idx: previously registered (via mpt_register) callback handle - * @ev_cbfunc: callback function - * - * This routine can be called by one or more protocol-specific drivers - * if/when they choose to be notified of MPT events. - * - * Returns 0 for success. - */ -int -mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc) -{ - if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) - return -1; - - MptEvHandlers[cb_idx] = ev_cbfunc; - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_event_deregister - Deregister protocol-specific event callback - * handler. - * @cb_idx: previously registered callback handle - * - * Each protocol-specific driver should call this routine - * when it does not (or can no longer) handle events, - * or when it's module is unloaded. - */ -void -mpt_event_deregister(int cb_idx) -{ - if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) - return; - - MptEvHandlers[cb_idx] = NULL; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_reset_register - Register protocol-specific IOC reset handler. - * @cb_idx: previously registered (via mpt_register) callback handle - * @reset_func: reset function - * - * This routine can be called by one or more protocol-specific drivers - * if/when they choose to be notified of IOC resets. - * - * Returns 0 for success. - */ -int -mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func) -{ - if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) - return -1; - - MptResetHandlers[cb_idx] = reset_func; - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_reset_deregister - Deregister protocol-specific IOC reset handler. - * @cb_idx: previously registered callback handle - * - * Each protocol-specific driver should call this routine - * when it does not (or can no longer) handle IOC reset handling, - * or when it's module is unloaded. - */ -void -mpt_reset_deregister(int cb_idx) -{ - if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) - return; - - MptResetHandlers[cb_idx] = NULL; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024) - * allocated per MPT adapter. - * @handle: Handle of registered MPT protocol driver - * @iocid: IOC unique identifier (integer) - * - * Returns pointer to a MPT request frame or %NULL if none are available - * or IOC is not active. - */ -MPT_FRAME_HDR* -mpt_get_msg_frame(int handle, int iocid) -{ - MPT_FRAME_HDR *mf = NULL; - MPT_ADAPTER *iocp; - unsigned long flags; - - /* validate handle and ioc identifier */ - iocp = mpt_adapters[iocid]; - -#ifdef MFCNT - if (!iocp->active) - printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n"); -#endif - - /* If interrupts are not attached, do not return a request frame */ - if (!iocp->active) - return NULL; - - spin_lock_irqsave(&iocp->FreeQlock, flags); - if (! Q_IS_EMPTY(&iocp->FreeQ)) { - int req_offset; - - mf = iocp->FreeQ.head; - Q_DEL_ITEM(&mf->u.frame.linkage); - mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ - req_offset = (u8 *)mf - (u8 *)iocp->req_frames; - /* u16! */ - mf->u.frame.hwhdr.msgctxu.fld.req_idx = - cpu_to_le16(req_offset / iocp->req_sz); - mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0; -#ifdef MFCNT - iocp->mfcnt++; -#endif - } - spin_unlock_irqrestore(&iocp->FreeQlock, flags); - -#ifdef MFCNT - if (mf == NULL) - printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", iocp->mfcnt, iocp->req_depth); - mfcounter++; - if (mfcounter == PRINT_MF_COUNT) - printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", iocp->mfcnt, iocp->req_depth); -#endif - - return mf; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_put_msg_frame - Send a protocol specific MPT request frame - * to a IOC. - * @handle: Handle of registered MPT protocol driver - * @iocid: IOC unique identifier (integer) - * @mf: Pointer to MPT request frame - * - * This routine posts a MPT request frame to the request post FIFO of a - * specific MPT adapter. - */ -void -mpt_put_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf) -{ - MPT_ADAPTER *iocp; - - iocp = mpt_adapters[iocid]; - if (iocp != NULL) { - u32 mf_dma_addr; - int req_offset; - - /* ensure values are reset properly! */ - mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ - req_offset = (u8 *)mf - (u8 *)iocp->req_frames; - /* u16! */ - mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_offset / iocp->req_sz); - mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0; - -#ifdef MPT_DEBUG_MSG_FRAME - { - u32 *m = mf->u.frame.hwhdr.__hdr; - int ii, n; - - printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ", - iocp->name, m); - n = iocp->req_sz/4 - 1; - while (m[n] == 0) - n--; - for (ii=0; ii<=n; ii++) { - if (ii && ((ii%8)==0)) - printk("\n" KERN_INFO " "); - printk(" %08x", le32_to_cpu(m[ii])); - } - printk("\n"); - } -#endif - - mf_dma_addr = iocp->req_frames_low_dma + req_offset; - CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr); - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_free_msg_frame - Place MPT request frame back on FreeQ. - * @handle: Handle of registered MPT protocol driver - * @iocid: IOC unique identifier (integer) - * @mf: Pointer to MPT request frame - * - * This routine places a MPT request frame back on the MPT adapter's - * FreeQ. - */ -void -mpt_free_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf) -{ - MPT_ADAPTER *iocp; - unsigned long flags; - - iocp = mpt_adapters[iocid]; - if (iocp != NULL) { - /* Put Request back on FreeQ! */ - spin_lock_irqsave(&iocp->FreeQlock, flags); - Q_ADD_TAIL(&iocp->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR); -#ifdef MFCNT - iocp->mfcnt--; -#endif - spin_unlock_irqrestore(&iocp->FreeQlock, flags); - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_add_sge - Place a simple SGE at address pAddr. - * @pAddr: virtual address for SGE - * @flagslength: SGE flags and data transfer length - * @dma_addr: Physical address - * - * This routine places a MPT request frame back on the MPT adapter's - * FreeQ. - */ -void -mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr) -{ - if (sizeof(dma_addr_t) == sizeof(u64)) { - SGESimple64_t *pSge = (SGESimple64_t *) pAddr; - u32 tmp = dma_addr & 0xFFFFFFFF; - - pSge->FlagsLength = cpu_to_le32(flagslength); - pSge->Address.Low = cpu_to_le32(tmp); - tmp = (u32) ((u64)dma_addr >> 32); - pSge->Address.High = cpu_to_le32(tmp); - - } else { - SGESimple32_t *pSge = (SGESimple32_t *) pAddr; - pSge->FlagsLength = cpu_to_le32(flagslength); - pSge->Address = cpu_to_le32(dma_addr); - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_add_chain - Place a chain SGE at address pAddr. - * @pAddr: virtual address for SGE - * @next: nextChainOffset value (u32's) - * @length: length of next SGL segment - * @dma_addr: Physical address - * - * This routine places a MPT request frame back on the MPT adapter's - * FreeQ. - */ -void -mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr) -{ - if (sizeof(dma_addr_t) == sizeof(u64)) { - SGEChain64_t *pChain = (SGEChain64_t *) pAddr; - u32 tmp = dma_addr & 0xFFFFFFFF; - - pChain->Length = cpu_to_le16(length); - pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size(); - - pChain->NextChainOffset = next; - - pChain->Address.Low = cpu_to_le32(tmp); - tmp = (u32) ((u64)dma_addr >> 32); - pChain->Address.High = cpu_to_le32(tmp); - } else { - SGEChain32_t *pChain = (SGEChain32_t *) pAddr; - pChain->Length = cpu_to_le16(length); - pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size(); - pChain->NextChainOffset = next; - pChain->Address = cpu_to_le32(dma_addr); - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_send_handshake_request - Send MPT request via doorbell - * handshake method. - * @handle: Handle of registered MPT protocol driver - * @iocid: IOC unique identifier (integer) - * @reqBytes: Size of the request in bytes - * @req: Pointer to MPT request frame - * @sleepFlag: Use schedule if CAN_SLEEP else use udelay. - * - * This routine is used exclusively to send MptScsiTaskMgmt - * requests since they are required to be sent via doorbell handshake. - * - * NOTE: It is the callers responsibility to byte-swap fields in the - * request which are greater than 1 byte in size. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt_send_handshake_request(int handle, int iocid, int reqBytes, u32 *req, int sleepFlag) -{ - MPT_ADAPTER *iocp; - int r = 0; - - iocp = mpt_adapters[iocid]; - if (iocp != NULL) { - u8 *req_as_bytes; - int ii; - - /* State is known to be good upon entering - * this function so issue the bus reset - * request. - */ - - /* - * Emulate what mpt_put_msg_frame() does /wrt to sanity - * setting cb_idx/req_idx. But ONLY if this request - * is in proper (pre-alloc'd) request buffer range... - */ - ii = MFPTR_2_MPT_INDEX(iocp,(MPT_FRAME_HDR*)req); - if (reqBytes >= 12 && ii >= 0 && ii < iocp->req_depth) { - MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req; - mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii); - mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; - } - - /* Make sure there are no doorbells */ - CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); - - CHIPREG_WRITE32(&iocp->chip->Doorbell, - ((MPI_FUNCTION_HANDSHAKE<chip->Doorbell) & MPI_DOORBELL_ACTIVE)) - return -5; - - dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n", - iocp->name, ii)); - - CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); - - if ((r = WaitForDoorbellAck(iocp, 2, sleepFlag)) < 0) { - return -2; - } - - /* Send request via doorbell handshake */ - req_as_bytes = (u8 *) req; - for (ii = 0; ii < reqBytes/4; ii++) { - u32 word; - - word = ((req_as_bytes[(ii*4) + 0] << 0) | - (req_as_bytes[(ii*4) + 1] << 8) | - (req_as_bytes[(ii*4) + 2] << 16) | - (req_as_bytes[(ii*4) + 3] << 24)); - CHIPREG_WRITE32(&iocp->chip->Doorbell, word); - if ((r = WaitForDoorbellAck(iocp, 2, sleepFlag)) < 0) { - r = -3; - break; - } - } - - if (r >= 0 && WaitForDoorbellInt(iocp, 10, sleepFlag) >= 0) - r = 0; - else - r = -4; - - /* Make sure there are no doorbells */ - CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); - } - - return r; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_adapter_find_first - Find first MPT adapter pointer. - * - * Returns first MPT adapter pointer or %NULL if no MPT adapters - * are present. - */ -MPT_ADAPTER * -mpt_adapter_find_first(void) -{ - MPT_ADAPTER *this = NULL; - - if (! Q_IS_EMPTY(&MptAdapters)) - this = MptAdapters.head; - - return this; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_adapter_find_next - Find next MPT adapter pointer. - * @prev: Pointer to previous MPT adapter - * - * Returns next MPT adapter pointer or %NULL if there are no more. - */ -MPT_ADAPTER * -mpt_adapter_find_next(MPT_ADAPTER *prev) -{ - MPT_ADAPTER *next = NULL; - - if (prev && (prev->forw != (MPT_ADAPTER*)&MptAdapters.head)) - next = prev->forw; - - return next; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_pci_scan - Scan PCI devices for MPT adapters. - * - * Returns count of MPT adapters found, keying off of PCI vendor and - * device_id's. - */ -static int __init -mpt_pci_scan(void) -{ - struct pci_dev *pdev; - struct pci_dev *pdev2; - int found = 0; - int count = 0; - int r; - - dprintk((KERN_INFO MYNAM ": Checking for MPT adapters...\n")); - - /* - * NOTE: The 929, 929X, 1030 and 1035 will appear as 2 separate PCI devices, - * one for each channel. - */ - pci_for_each_dev(pdev) { - pdev2 = NULL; - if (pdev->vendor != 0x1000) - continue; - - if ((pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC909) && - (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929) && - (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919) && - (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929X) && - (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919X) && - (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030) && - (pdev->device != MPI_MANUFACTPAGE_DEVID_1030_53C1035) && - 1) { - dprintk((KERN_INFO MYNAM ": Skipping LSI device=%04xh\n", pdev->device)); - continue; - } - - /* GRRRRR - * dual function devices (929, 929X, 1030, 1035) may be presented in Func 1,0 order, - * but we'd really really rather have them in Func 0,1 order. - * Do some kind of look ahead here... - */ - if (pdev->devfn & 1) { - /* SAE: Not a clear macro */ - pdev2 = NULL; - if(pdev != pci_dev_g(&pci_devices)) - pdev2 = pci_dev_g(pdev->global_list.next); - - if (pdev2 && (pdev2->vendor == 0x1000) && - (PCI_SLOT(pdev2->devfn) == PCI_SLOT(pdev->devfn)) && - (pdev2->device == pdev->device) && - (pdev2->bus->number == pdev->bus->number) && - !(pdev2->devfn & 1)) { - dprintk((KERN_INFO MYNAM ": MPT adapter found: PCI bus/dfn=%02x/%02xh, class=%08x, id=%xh\n", - pdev2->bus->number, pdev2->devfn, pdev2->class, pdev2->device)); - found++; - if ((r = mpt_adapter_install(pdev2)) == 0) - count++; - } else { - pdev2 = NULL; - } - } - - dprintk((KERN_INFO MYNAM ": MPT adapter found: PCI bus/dfn=%02x/%02xh, class=%08x, id=%xh\n", - pdev->bus->number, pdev->devfn, pdev->class, pdev->device)); - found++; - if ((r = mpt_adapter_install(pdev)) == 0) - count++; - - if (pdev2) - pdev = pdev2; - } - - if (!found || !count) { - fusion_exit(); - return -ENODEV; - } - - printk(KERN_INFO MYNAM ": %d MPT adapter%s found, %d installed.\n", - found, (found==1) ? "" : "s", count); - -#ifdef CONFIG_PROC_FS - (void) procmpt_create(); -#endif - - return count; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_verify_adapter - Given a unique IOC identifier, set pointer to - * the associated MPT adapter structure. - * @iocid: IOC unique identifier (integer) - * @iocpp: Pointer to pointer to IOC adapter - * - * Returns iocid and sets iocpp. - */ -int -mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) -{ - MPT_ADAPTER *p; - - *iocpp = NULL; - if (iocid >= MPT_MAX_ADAPTERS) - return -1; - - p = mpt_adapters[iocid]; - if (p == NULL) - return -1; - - *iocpp = p; - return iocid; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_adapter_install - Install a PCI intelligent MPT adapter. - * @pdev: Pointer to pci_dev structure - * - * This routine performs all the steps necessary to bring the IOC of - * a MPT adapter to a OPERATIONAL state. This includes registering - * memory regions, registering the interrupt, and allocating request - * and reply memory pools. - * - * This routine also pre-fetches the LAN MAC address of a Fibre Channel - * MPT adapter. - * - * Returns 0 for success, non-zero for failure. - * - * TODO: Add support for polled controllers - */ -static int __init -mpt_adapter_install(struct pci_dev *pdev) -{ - MPT_ADAPTER *ioc; - u8 *mem; - unsigned long mem_phys; - unsigned long port; - u32 msize; - u32 psize; - int ii; - int r = -ENODEV; - u64 mask = 0xffffffffffffffffULL; - - if (pci_enable_device(pdev)) - return r; - - if (!pci_set_dma_mask(pdev, mask)) { - dprintk((KERN_INFO MYNAM ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n")); - } else { - if (pci_set_dma_mask(pdev, (u64) 0xffffffff)) { - printk(KERN_WARNING MYNAM - ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n"); - return r; - } - } - - ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC); - if (ioc == NULL) { - printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n"); - return -ENOMEM; - } - memset(ioc, 0, sizeof(*ioc)); - ioc->alloc_total = sizeof(MPT_ADAPTER); - ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */ - ioc->reply_sz = ioc->req_sz; - - ioc->pcidev = pdev; - ioc->diagPending = 0; - spin_lock_init(&ioc->diagLock); - - /* Initialize the event logging. - */ - ioc->eventTypes = 0; /* None */ - ioc->eventContext = 0; - ioc->eventLogSize = 0; - ioc->events = NULL; - -#ifdef MFCNT - ioc->mfcnt = 0; -#endif - - ioc->cached_fw = NULL; - - /* Initilize SCSI Config Data structure - */ - memset(&ioc->spi_data, 0, sizeof(ScsiCfgData)); - - /* Initialize the running configQ head. - */ - Q_INIT(&ioc->configQ, Q_ITEM); - - /* Find lookup slot. */ - for (ii=0; ii < MPT_MAX_ADAPTERS; ii++) { - if (mpt_adapters[ii] == NULL) { - ioc->id = ii; /* Assign adapter unique id (lookup) */ - break; - } - } - if (ii == MPT_MAX_ADAPTERS) { - printk(KERN_ERR MYNAM ": ERROR - mpt_adapters[%d] table overflow!\n", ii); - kfree(ioc); - return -ENFILE; - } - - mem_phys = msize = 0; - port = psize = 0; - for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) { - /* SAE: Why not assume Linux 2.4? */ - if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) { - /* Get I/O space! */ - port = pci_resource_start(pdev, ii); - psize = pci_resource_len(pdev, ii); - } else { - /* Get memmap */ - mem_phys = pci_resource_start(pdev, ii); - msize = pci_resource_len(pdev, ii); - break; - } - } - ioc->mem_size = msize; - - if (ii == DEVICE_COUNT_RESOURCE) { - printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n"); - kfree(ioc); - return -EINVAL; - } - - dprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize)); - dprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize)); - dprintk((KERN_INFO MYNAM ": Using %s register access method\n", PortIo ? "PortIo" : "MemMap")); - - mem = NULL; - if (! PortIo) { - /* Get logical ptr for PciMem0 space */ - /*mem = ioremap(mem_phys, msize);*/ - mem = ioremap(mem_phys, 0x100); - if (mem == NULL) { - printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n"); - kfree(ioc); - return -EINVAL; - } - ioc->memmap = mem; - } - dprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys)); - - dprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n", - &ioc->facts, &ioc->pfacts[0])); - if (PortIo) { - u8 *pmem = (u8*)port; - ioc->mem_phys = port; - ioc->chip = (SYSIF_REGS*)pmem; - } else { - ioc->mem_phys = mem_phys; - ioc->chip = (SYSIF_REGS*)mem; - } - - /* Save Port IO values incase we need to do downloadboot */ - { - u8 *pmem = (u8*)port; - ioc->pio_mem_phys = port; - ioc->pio_chip = (SYSIF_REGS*)pmem; - } - - ioc->chip_type = FCUNK; - if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) { - ioc->chip_type = FC909; - ioc->prod_name = "LSIFC909"; - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) { - ioc->chip_type = FC929; - ioc->prod_name = "LSIFC929"; - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) { - ioc->chip_type = FC919; - ioc->prod_name = "LSIFC919"; - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) { - ioc->chip_type = FC929X; - ioc->prod_name = "LSIFC929X"; - { - /* 929X Chip Fix. Set Split transactions level - * for PCIX. Set bits 5 - 6 to zero, turn on bit 4. - */ - u16 pcixcmd = 0; - pci_read_config_word(pdev, 0x6a, &pcixcmd); - pcixcmd &= 0xFF9F; - pcixcmd |= 0x0010; - pci_write_config_word(pdev, 0x6a, pcixcmd); - } - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) { - ioc->chip_type = FC919X; - ioc->prod_name = "LSIFC919X"; - { - /* 919X Chip Fix. Set Split transactions level - * for PCIX. Set bits 5 - 6 to zero, turn on bit 4. - */ - u16 pcixcmd = 0; - pci_read_config_word(pdev, 0x6a, &pcixcmd); - pcixcmd &= 0xFF9F; - pcixcmd |= 0x0010; - pci_write_config_word(pdev, 0x6a, pcixcmd); - } - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) { - ioc->chip_type = C1030; - ioc->prod_name = "LSI53C1030"; - { - u8 revision; - - /* 1030 Chip Fix. Disable Split transactions - * for PCIX. Set bits 4 - 6 to zero if Rev < C0( = 8) - */ - pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); - if (revision < 0x08) { - u16 pcixcmd = 0; - pci_read_config_word(pdev, 0x6a, &pcixcmd); - pcixcmd &= 0xFF8F; - pci_write_config_word(pdev, 0x6a, pcixcmd); - } - } - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) { - ioc->chip_type = C1035; - ioc->prod_name = "LSI53C1035"; - } - - sprintf(ioc->name, "ioc%d", ioc->id); - - Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR); - spin_lock_init(&ioc->FreeQlock); - - /* Disable all! */ - CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); - ioc->active = 0; - CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - - /* tack onto tail of our MPT adapter list */ - Q_ADD_TAIL(&MptAdapters, ioc, MPT_ADAPTER); - - /* Set lookup ptr. */ - mpt_adapters[ioc->id] = ioc; - - ioc->pci_irq = -1; - if (pdev->irq) { - r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc); - - if (r < 0) { -#ifndef __sparc__ - printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n", - ioc->name, pdev->irq); -#else - printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n", - ioc->name, __irq_itoa(pdev->irq)); -#endif - Q_DEL_ITEM(ioc); - mpt_adapters[ioc->id] = NULL; - iounmap(mem); - kfree(ioc); - return -EBUSY; - } - - ioc->pci_irq = pdev->irq; - - pci_set_master(pdev); /* ?? */ - -#ifndef __sparc__ - dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq)); -#else - dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq))); -#endif - } - - /* NEW! 20010220 -sralston - * Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets. - */ - if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030) - || (ioc->chip_type == C1035) || (ioc->chip_type == FC929X)) - mpt_detect_bound_ports(ioc, pdev); - - if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) { - printk(KERN_WARNING MYNAM ": WARNING - %s did not initialize properly! (%d)\n", - ioc->name, r); - } - - return r; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_do_ioc_recovery - Initialize or recover MPT adapter. - * @ioc: Pointer to MPT adapter structure - * @reason: Event word / reason - * @sleepFlag: Use schedule if CAN_SLEEP else use udelay. - * - * This routine performs all the steps necessary to bring the IOC - * to a OPERATIONAL state. - * - * This routine also pre-fetches the LAN MAC address of a Fibre Channel - * MPT adapter. - * - * Returns: - * 0 for success - * -1 if failed to get board READY - * -2 if READY but IOCFacts Failed - * -3 if READY but PrimeIOCFifos Failed - * -4 if READY but IOCInit Failed - */ -static int -mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) -{ - int hard_reset_done = 0; - int alt_ioc_ready = 0; - int hard; - int r; - int ii; - int handlers; - int ret = 0; - int reset_alt_ioc_active = 0; - - printk(KERN_INFO MYNAM ": Initiating %s %s\n", - ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery"); - - /* Disable reply interrupts (also blocks FreeQ) */ - CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); - ioc->active = 0; - - if (ioc->alt_ioc) { - if (ioc->alt_ioc->active) - reset_alt_ioc_active = 1; - - /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */ - CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF); - ioc->alt_ioc->active = 0; - } - - hard = 1; - if (reason == MPT_HOSTEVENT_IOC_BRINGUP) - hard = 0; - - if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) { - if (hard_reset_done == -4) { - printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n", - ioc->name); - - if (reset_alt_ioc_active && ioc->alt_ioc) { - /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */ - dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", - ioc->alt_ioc->name)); - CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM)); - ioc->alt_ioc->active = 1; - } - - } else { - printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n", - ioc->name); - } - return -1; - } - - /* hard_reset_done = 0 if a soft reset was performed - * and 1 if a hard reset was performed. - */ - if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) { - if ((r = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0) - alt_ioc_ready = 1; - else - printk(KERN_WARNING MYNAM - ": alt-%s: (%d) Not ready WARNING!\n", - ioc->alt_ioc->name, r); - } - - /* Get IOC facts! Allow 1 retry */ - if ((r = GetIocFacts(ioc, sleepFlag, reason)) != 0) - r = GetIocFacts(ioc, sleepFlag, reason); - - if (r) { - ret = -2; - } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { - MptDisplayIocCapabilities(ioc); - } - - if (alt_ioc_ready) { - if ((r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) { - /* Retry - alt IOC was initialized once - */ - r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason); - } - if (r) { - alt_ioc_ready = 0; - reset_alt_ioc_active = 0; - } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { - MptDisplayIocCapabilities(ioc->alt_ioc); - } - } - - /* Prime reply & request queues! - * (mucho alloc's) Must be done prior to - * init as upper addresses are needed for init. - * If fails, continue with alt-ioc processing - */ - if ((ret == 0) && ((r = PrimeIocFifos(ioc)) != 0)) - ret = -3; - - /* May need to check/upload firmware & data here! - * If fails, continue with alt-ioc processing - */ - if ((ret == 0) && ((r = SendIocInit(ioc, sleepFlag)) != 0)) - ret = -4; -// NEW! - if (alt_ioc_ready && ((r = PrimeIocFifos(ioc->alt_ioc)) != 0)) { - printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n", - ioc->alt_ioc->name, r); - alt_ioc_ready = 0; - reset_alt_ioc_active = 0; - } - - if (alt_ioc_ready) { - if ((r = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) { - alt_ioc_ready = 0; - reset_alt_ioc_active = 0; - printk(KERN_WARNING MYNAM - ": alt-%s: (%d) init failure WARNING!\n", - ioc->alt_ioc->name, r); - } - } - - if (reason == MPT_HOSTEVENT_IOC_BRINGUP){ - if (ioc->upload_fw) { - ddlprintk((MYIOC_s_INFO_FMT - "firmware upload required!\n", ioc->name)); - - /* Controller is not operational, cannot do upload - */ - if (ret == 0) { - r = mpt_do_upload(ioc, sleepFlag); - if (r != 0) - printk(KERN_WARNING MYNAM ": firmware upload failure!\n"); - } - - /* Handle the alt IOC too */ - if ((alt_ioc_ready) && (ioc->alt_ioc->upload_fw)){ - ddlprintk((MYIOC_s_INFO_FMT - "Alt-ioc firmware upload required!\n", - ioc->name)); - r = mpt_do_upload(ioc->alt_ioc, sleepFlag); - if (r != 0) - printk(KERN_WARNING MYNAM ": firmware upload failure!\n"); - } - } - } - - if (ret == 0) { - /* Enable! (reply interrupt) */ - CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM)); - ioc->active = 1; - } - - if (reset_alt_ioc_active && ioc->alt_ioc) { - /* (re)Enable alt-IOC! (reply interrupt) */ - dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", - ioc->alt_ioc->name)); - CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM)); - ioc->alt_ioc->active = 1; - } - - /* NEW! 20010120 -sralston - * Enable MPT base driver management of EventNotification - * and EventAck handling. - */ - if ((ret == 0) && (!ioc->facts.EventState)) - (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */ - - if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState) - (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */ - - /* (Bugzilla:fibrebugs, #513) - * Bug fix (part 2)! 20010905 -sralston - * Add additional "reason" check before call to GetLanConfigPages - * (combined with GetIoUnitPage2 call). This prevents a somewhat - * recursive scenario; GetLanConfigPages times out, timer expired - * routine calls HardResetHandler, which calls into here again, - * and we try GetLanConfigPages again... - */ - if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { - if ((int)ioc->chip_type <= (int)FC929) { - /* - * Pre-fetch FC port WWN and stuff... - * (FCPortPage0_t stuff) - */ - for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { - (void) GetFcPortPage0(ioc, ii); - } - - if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) && - (ioc->lan_cnfg_page0.Header.PageLength == 0)) { - /* - * Pre-fetch the ports LAN MAC address! - * (LANPage1_t stuff) - */ - (void) GetLanConfigPages(ioc); -#ifdef MPT_DEBUG - { - u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; - dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", - ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] )); - } -#endif - } - } else { - /* Get NVRAM and adapter maximums from SPP 0 and 2 - */ - mpt_GetScsiPortSettings(ioc, 0); - - /* Get version and length of SDP 1 - */ - mpt_readScsiDevicePageHeaders(ioc, 0); - - /* Find IM volumes - */ - if (ioc->facts.MsgVersion >= 0x0102) - mpt_findImVolumes(ioc); - - /* Check, and possibly reset, the coalescing value - */ - mpt_read_ioc_pg_1(ioc); - } - - GetIoUnitPage2(ioc); - } - - /* - * Call each currently registered protocol IOC reset handler - * with post-reset indication. - * NOTE: If we're doing _IOC_BRINGUP, there can be no - * MptResetHandlers[] registered yet. - */ - if (hard_reset_done) { - r = handlers = 0; - for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { - if ((ret == 0) && MptResetHandlers[ii]) { - dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n", - ioc->name, ii)); - r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET); - handlers++; - } - - if (alt_ioc_ready && MptResetHandlers[ii]) { - dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n", - ioc->name, ioc->alt_ioc->name, ii)); - r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET); - handlers++; - } - } - /* FIXME? Examine results here? */ - } - - return ret; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_detect_bound_ports - Search for PCI bus/dev_function - * which matches PCI bus/dev_function (+/-1) for newly discovered 929, - * 929X, 1030 or 1035. - * @ioc: Pointer to MPT adapter structure - * @pdev: Pointer to (struct pci_dev) structure - * - * If match on PCI dev_function +/-1 is found, bind the two MPT adapters - * using alt_ioc pointer fields in their %MPT_ADAPTER structures. - */ -static void -mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev) -{ - MPT_ADAPTER *ioc_srch = mpt_adapter_find_first(); - unsigned int match_lo, match_hi; - - match_lo = pdev->devfn-1; - match_hi = pdev->devfn+1; - dprintk((MYIOC_s_INFO_FMT "PCI bus/devfn=%x/%x, searching for devfn match on %x or %x\n", - ioc->name, pdev->bus->number, pdev->devfn, match_lo, match_hi)); - - while (ioc_srch != NULL) { - struct pci_dev *_pcidev = ioc_srch->pcidev; - - if ((_pcidev->device == pdev->device) && - (_pcidev->bus->number == pdev->bus->number) && - (_pcidev->devfn == match_lo || _pcidev->devfn == match_hi) ) { - /* Paranoia checks */ - if (ioc->alt_ioc != NULL) { - printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n", - ioc->name, ioc->alt_ioc->name); - break; - } else if (ioc_srch->alt_ioc != NULL) { - printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n", - ioc_srch->name, ioc_srch->alt_ioc->name); - break; - } - dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n", - ioc->name, ioc_srch->name)); - ioc_srch->alt_ioc = ioc; - ioc->alt_ioc = ioc_srch; - break; - } - ioc_srch = mpt_adapter_find_next(ioc_srch); - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_adapter_disable - Disable misbehaving MPT adapter. - * @this: Pointer to MPT adapter structure - * @free: Free up alloc'd reply, request, etc. - */ -static void -mpt_adapter_disable(MPT_ADAPTER *this, int freeup) -{ - if (this != NULL) { - int sz; - u32 state; - int ret; - - /* Disable the FW */ - state = mpt_GetIocState(this, 1); - if (state == MPI_IOC_STATE_OPERATIONAL) { - SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP); - } - - if (this->cached_fw != NULL) { - ddlprintk((KERN_INFO MYNAM ": Pushing FW onto adapter\n")); - - if ((ret = mpt_downloadboot(this, NO_SLEEP)) < 0) { - printk(KERN_WARNING MYNAM - ": firmware downloadboot failure (%d)!\n", ret); - } - } - - /* Disable adapter interrupts! */ - CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF); - this->active = 0; - /* Clear any lingering interrupt */ - CHIPREG_WRITE32(&this->chip->IntStatus, 0); - - if (freeup && this->reply_alloc != NULL) { - sz = (this->reply_sz * this->reply_depth) + 128; - pci_free_consistent(this->pcidev, sz, - this->reply_alloc, this->reply_alloc_dma); - this->reply_frames = NULL; - this->reply_alloc = NULL; - this->alloc_total -= sz; - } - - if (freeup && this->req_alloc != NULL) { - sz = (this->req_sz * this->req_depth) + 128; - /* - * Rounding UP to nearest 4-kB boundary here... - */ - sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000; - pci_free_consistent(this->pcidev, sz, - this->req_alloc, this->req_alloc_dma); - this->req_frames = NULL; - this->req_alloc = NULL; - this->alloc_total -= sz; - } - - if (freeup && this->sense_buf_pool != NULL) { - sz = (this->req_depth * MPT_SENSE_BUFFER_ALLOC); - pci_free_consistent(this->pcidev, sz, - this->sense_buf_pool, this->sense_buf_pool_dma); - this->sense_buf_pool = NULL; - this->alloc_total -= sz; - } - - if (freeup && this->events != NULL){ - sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS); - kfree(this->events); - this->events = NULL; - this->alloc_total -= sz; - } - - if (freeup && this->cached_fw != NULL) { - int ii = 0; - - while ((ii < this->num_fw_frags) && (this->cached_fw[ii]!= NULL)) { - sz = this->cached_fw[ii]->size; - pci_free_consistent(this->pcidev, sz, - this->cached_fw[ii]->fw, this->cached_fw[ii]->fw_dma); - this->cached_fw[ii]->fw = NULL; - this->alloc_total -= sz; - - kfree(this->cached_fw[ii]); - this->cached_fw[ii] = NULL; - this->alloc_total -= sizeof(fw_image_t); - - ii++; - } - - kfree(this->cached_fw); - this->cached_fw = NULL; - sz = this->num_fw_frags * sizeof(void *); - this->alloc_total -= sz; - } - - if (freeup && this->spi_data.nvram != NULL) { - kfree(this->spi_data.nvram); - this->spi_data.nvram = NULL; - } - - if (freeup && this->spi_data.pIocPg3 != NULL) { - kfree(this->spi_data.pIocPg3); - this->spi_data.pIocPg3 = NULL; - } - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_adapter_dispose - Free all resources associated with a MPT - * adapter. - * @this: Pointer to MPT adapter structure - * - * This routine unregisters h/w resources and frees all alloc'd memory - * associated with a MPT adapter structure. - */ -static void -mpt_adapter_dispose(MPT_ADAPTER *this) -{ - if (this != NULL) { - int sz_first, sz_last; - - sz_first = this->alloc_total; - - if (this->alt_ioc != NULL) { - this->alt_ioc->alt_ioc = NULL; - this->alt_ioc = NULL; - } - - mpt_adapter_disable(this, 1); - - if (this->pci_irq != -1) { - free_irq(this->pci_irq, this); - this->pci_irq = -1; - } - - if (this->memmap != NULL) - iounmap((u8 *) this->memmap); - -#if defined(CONFIG_MTRR) && 0 - if (this->mtrr_reg > 0) { - mtrr_del(this->mtrr_reg, 0, 0); - dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", this->name)); - } -#endif - - /* Zap the adapter lookup ptr! */ - mpt_adapters[this->id] = NULL; - - sz_last = this->alloc_total; - dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n", - this->name, sz_first-sz_last+(int)sizeof(*this), sz_first)); - kfree(this); - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * MptDisplayIocCapabilities - Disply IOC's capacilities. - * @ioc: Pointer to MPT adapter structure - */ -static void -MptDisplayIocCapabilities(MPT_ADAPTER *ioc) -{ - int i = 0; - - printk(KERN_INFO "%s: ", ioc->name); - if (ioc->prod_name && strlen(ioc->prod_name) > 3) - printk("%s: ", ioc->prod_name+3); - printk("Capabilities={"); - - if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) { - printk("Initiator"); - i++; - } - - if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) { - printk("%sTarget", i ? "," : ""); - i++; - } - - if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { - printk("%sLAN", i ? "," : ""); - i++; - } - -#if 0 - /* - * This would probably evoke more questions than it's worth - */ - if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) { - printk("%sLogBusAddr", i ? "," : ""); - i++; - } -#endif - - printk("}\n"); -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * MakeIocReady - Get IOC to a READY state, using KickStart if needed. - * @ioc: Pointer to MPT_ADAPTER structure - * @force: Force hard KickStart of IOC - * @sleepFlag: Specifies whether the process can sleep - * - * Returns: - * 1 - DIAG reset and READY - * 0 - READY initially OR soft reset and READY - * -1 - Any failure on KickStart - * -2 - Msg Unit Reset Failed - * -3 - IO Unit Reset Failed - * -4 - IOC owned by a PEER - */ -static int -MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) -{ - u32 ioc_state; - int statefault = 0; - int cntdn; - int hard_reset_done = 0; - int r; - int ii; - int whoinit; - - /* Get current [raw] IOC state */ - ioc_state = mpt_GetIocState(ioc, 0); - dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state)); - - /* - * Check to see if IOC got left/stuck in doorbell handshake - * grip of death. If so, hard reset the IOC. - */ - if (ioc_state & MPI_DOORBELL_ACTIVE) { - statefault = 1; - printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n", - ioc->name); - } - - /* Is it already READY? */ - if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) { - if ((int)ioc->chip_type <= (int)FC929) - return 0; - else { - /* Workaround from broken 1030 FW. - * Force a diagnostic reset if fails. - */ - if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0) - return 0; - else - statefault = 4; - } - } - - /* - * Check to see if IOC is in FAULT state. - */ - if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) { - statefault = 2; - printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n", - ioc->name); - printk(KERN_WARNING " FAULT code = %04xh\n", - ioc_state & MPI_DOORBELL_DATA_MASK); - } - - /* - * Hmmm... Did it get left operational? - */ - if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) { - dprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n", - ioc->name)); - - /* Check WhoInit. - * If PCI Peer, exit. - * Else, if no fault conditions are present, issue a MessageUnitReset - * Else, fall through to KickStart case - */ - whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT; - dprintk((KERN_WARNING MYNAM - ": whoinit 0x%x\n statefault %d force %d\n", - whoinit, statefault, force)); - if (whoinit == MPI_WHOINIT_PCI_PEER) - return -4; - else { - if ((statefault == 0 ) && (force == 0)) { - if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0) - return 0; - } - statefault = 3; - } - } - - hard_reset_done = KickStart(ioc, statefault||force, sleepFlag); - if (hard_reset_done < 0) - return -1; - - /* - * Loop here waiting for IOC to come READY. - */ - ii = 0; - cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */ - - while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) { - if (ioc_state == MPI_IOC_STATE_OPERATIONAL) { - /* - * BIOS or previous driver load left IOC in OP state. - * Reset messaging FIFOs. - */ - if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) { - printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name); - return -2; - } - } else if (ioc_state == MPI_IOC_STATE_RESET) { - /* - * Something is wrong. Try to get IOC back - * to a known state. - */ - if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) { - printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name); - return -3; - } - } - - ii++; cntdn--; - if (!cntdn) { - printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n", - ioc->name, (ii+5)/HZ); - return -ETIME; - } - - if (sleepFlag == CAN_SLEEP) { -/* SAE: Can't do this in the hypervisor */ -#if XEN_KILLED - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); -#else - mdelay(1); -#endif - } else { - mdelay (1); /* 1 msec delay */ - } - - } - - if (statefault < 3) { - printk(MYIOC_s_INFO_FMT "Recovered from %s\n", - ioc->name, - statefault==1 ? "stuck handshake" : "IOC FAULT"); - } - - return hard_reset_done; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_GetIocState - Get the current state of a MPT adapter. - * @ioc: Pointer to MPT_ADAPTER structure - * @cooked: Request raw or cooked IOC state - * - * Returns all IOC Doorbell register bits if cooked==0, else just the - * Doorbell bits in MPI_IOC_STATE_MASK. - */ -u32 -mpt_GetIocState(MPT_ADAPTER *ioc, int cooked) -{ - u32 s, sc; - - /* Get! */ - s = CHIPREG_READ32(&ioc->chip->Doorbell); -// dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s)); - sc = s & MPI_IOC_STATE_MASK; - - /* Save! */ - ioc->last_state = sc; - - return cooked ? sc : s; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * GetIocFacts - Send IOCFacts request to MPT adapter. - * @ioc: Pointer to MPT_ADAPTER structure - * @sleepFlag: Specifies whether the process can sleep - * @reason: If recovery, only update facts. - * - * Returns 0 for success, non-zero for failure. - */ -static int -GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) -{ - IOCFacts_t get_facts; - IOCFactsReply_t *facts; - int r; - int req_sz; - int reply_sz; - u32 status; - - /* IOC *must* NOT be in RESET state! */ - if (ioc->last_state == MPI_IOC_STATE_RESET) { - printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n", - ioc->name, - ioc->last_state ); - return -44; - } - - facts = &ioc->facts; - - /* Destination (reply area)... */ - reply_sz = sizeof(*facts); - memset(facts, 0, reply_sz); - - /* Request area (get_facts on the stack right now!) */ - req_sz = sizeof(get_facts); - memset(&get_facts, 0, req_sz); - - get_facts.Function = MPI_FUNCTION_IOC_FACTS; - /* Assert: All other get_facts fields are zero! */ - - dprintk((MYIOC_s_INFO_FMT "Sending get IocFacts request\n", ioc->name)); - - /* No non-zero fields in the get_facts request are greater than - * 1 byte in size, so we can just fire it off as is. - */ - r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts, - reply_sz, (u16*)facts, 3 /*seconds*/, sleepFlag); - if (r != 0) - return r; - - /* - * Now byte swap (GRRR) the necessary fields before any further - * inspection of reply contents. - * - * But need to do some sanity checks on MsgLength (byte) field - * to make sure we don't zero IOC's req_sz! - */ - /* Did we get a valid reply? */ - if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) { - if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { - /* - * If not been here, done that, save off first WhoInit value - */ - if (ioc->FirstWhoInit == WHOINIT_UNKNOWN) - ioc->FirstWhoInit = facts->WhoInit; - } - - facts->MsgVersion = le16_to_cpu(facts->MsgVersion); - facts->MsgContext = le32_to_cpu(facts->MsgContext); - facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions); - facts->IOCStatus = le16_to_cpu(facts->IOCStatus); - facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo); - status = facts->IOCStatus & MPI_IOCSTATUS_MASK; - /* CHECKME! IOCStatus, IOCLogInfo */ - - facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth); - facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize); - - /* - * FC f/w version changed between 1.1 and 1.2 - * Old: u16{Major(4),Minor(4),SubMinor(8)} - * New: u32{Major(8),Minor(8),Unit(8),Dev(8)} - */ - if (facts->MsgVersion < 0x0102) { - /* - * Handle old FC f/w style, convert to new... - */ - u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion); - facts->FWVersion.Word = - ((oldv<<12) & 0xFF000000) | - ((oldv<<8) & 0x000FFF00); - } else - facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word); - - facts->ProductID = le16_to_cpu(facts->ProductID); - facts->CurrentHostMfaHighAddr = - le32_to_cpu(facts->CurrentHostMfaHighAddr); - facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits); - facts->CurrentSenseBufferHighAddr = - le32_to_cpu(facts->CurrentSenseBufferHighAddr); - facts->CurReplyFrameSize = - le16_to_cpu(facts->CurReplyFrameSize); - - /* - * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx - * Older MPI-1.00.xx struct had 13 dwords, and enlarged - * to 14 in MPI-1.01.0x. - */ - if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 && - facts->MsgVersion > 0x0100) { - facts->FWImageSize = le32_to_cpu(facts->FWImageSize); - } - - if (!facts->RequestFrameSize) { - /* Something is wrong! */ - printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n", - ioc->name); - return -55; - } - - if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { - /* - * Set values for this IOC's request & reply frame sizes, - * and request & reply queue depths... - */ - ioc->req_sz = MIN(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4); - ioc->req_depth = MIN(MPT_MAX_REQ_DEPTH, facts->GlobalCredits); - ioc->reply_sz = ioc->req_sz; - ioc->reply_depth = MIN(MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth); - - dprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n", - ioc->name, ioc->reply_sz, ioc->reply_depth)); - dprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n", - ioc->name, ioc->req_sz, ioc->req_depth)); - - /* Get port facts! */ - if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 ) - return r; - } - } else { - printk(MYIOC_s_ERR_FMT "Invalid IOC facts reply!\n", - ioc->name); - return -66; - } - - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * GetPortFacts - Send PortFacts request to MPT adapter. - * @ioc: Pointer to MPT_ADAPTER structure - * @portnum: Port number - * @sleepFlag: Specifies whether the process can sleep - * - * Returns 0 for success, non-zero for failure. - */ -static int -GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag) -{ - PortFacts_t get_pfacts; - PortFactsReply_t *pfacts; - int ii; - int req_sz; - int reply_sz; - - /* IOC *must* NOT be in RESET state! */ - if (ioc->last_state == MPI_IOC_STATE_RESET) { - printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n", - ioc->name, - ioc->last_state ); - return -4; - } - - pfacts = &ioc->pfacts[portnum]; - - /* Destination (reply area)... */ - reply_sz = sizeof(*pfacts); - memset(pfacts, 0, reply_sz); - - /* Request area (get_pfacts on the stack right now!) */ - req_sz = sizeof(get_pfacts); - memset(&get_pfacts, 0, req_sz); - - get_pfacts.Function = MPI_FUNCTION_PORT_FACTS; - get_pfacts.PortNumber = portnum; - /* Assert: All other get_pfacts fields are zero! */ - - dprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n", - ioc->name, portnum)); - - /* No non-zero fields in the get_pfacts request are greater than - * 1 byte in size, so we can just fire it off as is. - */ - ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts, - reply_sz, (u16*)pfacts, 3 /*seconds*/, sleepFlag); - if (ii != 0) - return ii; - - /* Did we get a valid reply? */ - - /* Now byte swap the necessary fields in the response. */ - pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext); - pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus); - pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo); - pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices); - pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID); - pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags); - pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers); - pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs); - pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets); - - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * SendIocInit - Send IOCInit request to MPT adapter. - * @ioc: Pointer to MPT_ADAPTER structure - * @sleepFlag: Specifies whether the process can sleep - * - * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state. - * - * Returns 0 for success, non-zero for failure. - */ -static int -SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) -{ - IOCInit_t ioc_init; - MPIDefaultReply_t init_reply; - u32 state; - int r; - int count; - int cntdn; - - memset(&ioc_init, 0, sizeof(ioc_init)); - memset(&init_reply, 0, sizeof(init_reply)); - - ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER; -/* ioc_init.ChainOffset = 0; */ - ioc_init.Function = MPI_FUNCTION_IOC_INIT; -/* ioc_init.Flags = 0; */ - - /* If we are in a recovery mode and we uploaded the FW image, - * then this pointer is not NULL. Skip the upload a second time. - * Set this flag if cached_fw set for either IOC. - */ - ioc->upload_fw = 0; - ioc_init.Flags = 0; - if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) { - if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) - ioc_init.Flags = MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE; - else - ioc->upload_fw = 1; - } - ddlprintk((MYIOC_s_INFO_FMT "flags %d, upload_fw %d \n", - ioc->name, ioc_init.Flags, ioc->upload_fw)); - - if ((int)ioc->chip_type <= (int)FC929) { - ioc_init.MaxDevices = MPT_MAX_FC_DEVICES; - } else { - ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES; - } - ioc_init.MaxBuses = MPT_MAX_BUS; - -/* ioc_init.MsgFlags = 0; */ -/* ioc_init.MsgContext = cpu_to_le32(0x00000000); */ - ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */ - - if (sizeof(dma_addr_t) == sizeof(u64)) { - /* Save the upper 32-bits of the request - * (reply) and sense buffers. - */ - ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->req_frames_dma >> 32)); - ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32)); - } else { - /* Force 32-bit addressing */ - ioc_init.HostMfaHighAddr = cpu_to_le32(0); - ioc_init.SenseBufferHighAddr = cpu_to_le32(0); - } - - dprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n", - ioc->name, &ioc_init)); - - r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init, - sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag); - if (r != 0) - return r; - - /* No need to byte swap the multibyte fields in the reply - * since we don't even look at it's contents. - */ - - if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) - return r; - - /* YIKES! SUPER IMPORTANT!!! - * Poll IocState until _OPERATIONAL while IOC is doing - * LoopInit and TargetDiscovery! - */ - count = 0; - cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */ - state = mpt_GetIocState(ioc, 1); - while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) { - if (sleepFlag == CAN_SLEEP) { -/* SAE: Can't do this in the hypervisor */ -#if XEN_KILLED - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); -#else - mdelay(1); -#endif - } else { - mdelay(1); - } - - if (!cntdn) { - printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n", - ioc->name, (count+5)/HZ); - return -9; - } - - state = mpt_GetIocState(ioc, 1); - count++; - } - dhsprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n", - ioc->name, count)); - - return r; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * SendPortEnable - Send PortEnable request to MPT adapter port. - * @ioc: Pointer to MPT_ADAPTER structure - * @portnum: Port number to enable - * @sleepFlag: Specifies whether the process can sleep - * - * Send PortEnable to bring IOC to OPERATIONAL state. - * - * Returns 0 for success, non-zero for failure. - */ -static int -SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) -{ - PortEnable_t port_enable; - MPIDefaultReply_t reply_buf; - int ii; - int req_sz; - int reply_sz; - - /* Destination... */ - reply_sz = sizeof(MPIDefaultReply_t); - memset(&reply_buf, 0, reply_sz); - - req_sz = sizeof(PortEnable_t); - memset(&port_enable, 0, req_sz); - - port_enable.Function = MPI_FUNCTION_PORT_ENABLE; - port_enable.PortNumber = portnum; -/* port_enable.ChainOffset = 0; */ -/* port_enable.MsgFlags = 0; */ -/* port_enable.MsgContext = 0; */ - - dprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n", - ioc->name, portnum, &port_enable)); - - /* RAID FW may take a long time to enable - */ - if ((int)ioc->chip_type <= (int)FC929) { - ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, - reply_sz, (u16*)&reply_buf, 65 /*seconds*/, sleepFlag); - } else { - ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, - reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag); - } - - if (ii != 0) - return ii; - - /* We do not even look at the reply, so we need not - * swap the multi-byte fields. - */ - - return 0; -} - -/* - * Inputs: size - total FW bytes - * Outputs: frags - number of fragments needed - * Return NULL if failed. - */ -void * -mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size, int *frags, int *alloc_sz) -{ - fw_image_t **cached_fw = NULL; - u8 *mem = NULL; - dma_addr_t fw_dma; - int alloc_total = 0; - int bytes_left, bytes, num_frags; - int sz, ii; - - /* cached_fw - */ - sz = ioc->num_fw_frags * sizeof(void *); - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) - return NULL; - - memset(mem, 0, sz); - cached_fw = (fw_image_t **)mem; - alloc_total += sz; - - /* malloc fragment memory - * fw_image_t struct and dma for fw data - */ - bytes_left = size; - ii = 0; - num_frags = 0; - bytes = bytes_left; - while((bytes_left) && (num_frags < ioc->num_fw_frags)) { - if (cached_fw[ii] == NULL) { - mem = kmalloc(sizeof(fw_image_t), GFP_ATOMIC); - if (mem == NULL) - break; - - memset(mem, 0, sizeof(fw_image_t)); - cached_fw[ii] = (fw_image_t *)mem; - alloc_total += sizeof(fw_image_t); - } - - mem = pci_alloc_consistent(ioc->pcidev, bytes, &fw_dma); - if (mem == NULL) { - if (bytes > 0x10000) - bytes = 0x10000; - else if (bytes > 0x8000) - bytes = 0x8000; - else if (bytes > 0x4000) - bytes = 0x4000; - else if (bytes > 0x2000) - bytes = 0x2000; - else if (bytes > 0x1000) - bytes = 0x1000; - else - break; - - continue; - } - - cached_fw[ii]->fw = mem; - cached_fw[ii]->fw_dma = fw_dma; - cached_fw[ii]->size = bytes; - memset(mem, 0, bytes); - alloc_total += bytes; - - bytes_left -= bytes; - - num_frags++; - ii++; - } - - if (bytes_left ) { - /* Major Failure. - */ - mpt_free_fw_memory(ioc, cached_fw); - return NULL; - } - - *frags = num_frags; - *alloc_sz = alloc_total; - - return (void *) cached_fw; -} - -/* - * If alt_img is NULL, delete from ioc structure. - * Else, delete a secondary image in same format. - */ -void -mpt_free_fw_memory(MPT_ADAPTER *ioc, fw_image_t **alt_img) -{ - fw_image_t **cached_fw; - int ii; - int sz; - int alloc_freed = 0; - - if (alt_img != NULL) - cached_fw = alt_img; - else - cached_fw = ioc->cached_fw; - - if (cached_fw == NULL) - return; - - ii = 0; - while ((ii < ioc->num_fw_frags) && (cached_fw[ii]!= NULL)) { - sz = cached_fw[ii]->size; - if (sz > 0) { - pci_free_consistent(ioc->pcidev, sz, - cached_fw[ii]->fw, cached_fw[ii]->fw_dma); - } - cached_fw[ii]->fw = NULL; - alloc_freed += sz; - - kfree(cached_fw[ii]); - cached_fw[ii] = NULL; - alloc_freed += sizeof(fw_image_t); - - ii++; - } - - kfree(cached_fw); - cached_fw = NULL; - sz = ioc->num_fw_frags * sizeof(void *); - alloc_freed += sz; - - if (alt_img == NULL) - ioc->alloc_total -= alloc_freed; - - return; -} - - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port. - * @ioc: Pointer to MPT_ADAPTER structure - * @sleepFlag: Specifies whether the process can sleep - * - * Returns 0 for success, >0 for handshake failure - * <0 for fw upload failure. - * - * Remark: If bound IOC and a successful FWUpload was performed - * on the bound IOC, the second image is discarded - * and memory is free'd. Both channels must upload to prevent - * IOC from running in degraded mode. - */ -static int -mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) -{ - u8 request[ioc->req_sz]; - u8 reply[sizeof(FWUploadReply_t)]; - FWUpload_t *prequest; - FWUploadReply_t *preply; - FWUploadTCSGE_t *ptcsge = NULL; - int sgeoffset; - int ii, sz, reply_sz; - int cmdStatus, freeMem = 0; - int num_frags, alloc_sz; - - /* If the image size is 0 or if the pointer is - * not NULL (error), we are done. - */ - if (((sz = ioc->facts.FWImageSize) == 0) || ioc->cached_fw) - return 0; - - ioc->num_fw_frags = ioc->req_sz - sizeof(FWUpload_t) + sizeof(dma_addr_t) + sizeof(u32) -1; - ioc->num_fw_frags /= sizeof(dma_addr_t) + sizeof(u32); - - ioc->cached_fw = (fw_image_t **) mpt_alloc_fw_memory(ioc, - ioc->facts.FWImageSize, &num_frags, &alloc_sz); - - if (ioc->cached_fw == NULL) { - /* Major Failure. - */ - mpt_free_fw_memory(ioc, NULL); - ioc->cached_fw = NULL; - - return -ENOMEM; - } - ioc->alloc_total += alloc_sz; - - ddlprintk((KERN_INFO MYNAM ": FW Image @ %p, sz=%d bytes\n", - (void *)(ulong)ioc->cached_fw, ioc->facts.FWImageSize)); - - prequest = (FWUpload_t *)&request; - preply = (FWUploadReply_t *)&reply; - - /* Destination... */ - memset(prequest, 0, ioc->req_sz); - - reply_sz = sizeof(reply); - memset(preply, 0, reply_sz); - - prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM; - prequest->Function = MPI_FUNCTION_FW_UPLOAD; - prequest->MsgContext = 0; /* anything */ - - ptcsge = (FWUploadTCSGE_t *) &prequest->SGL; - ptcsge->Reserved = 0; - ptcsge->ContextSize = 0; - ptcsge->DetailsLength = 12; - ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT; - ptcsge->Reserved1 = 0; - ptcsge->ImageOffset = 0; - ptcsge->ImageSize = cpu_to_le32(sz); - - sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t); - - for (ii = 0; ii < (num_frags-1); ii++) { - mpt_add_sge(&request[sgeoffset], MPT_SGE_FLAGS_SIMPLE_ELEMENT | - MPT_SGE_FLAGS_ADDRESSING | MPT_TRANSFER_IOC_TO_HOST | - (u32) ioc->cached_fw[ii]->size, ioc->cached_fw[ii]->fw_dma); - - sgeoffset += sizeof(u32) + sizeof(dma_addr_t); - } - - mpt_add_sge(&request[sgeoffset], - MPT_SGE_FLAGS_SSIMPLE_READ |(u32) ioc->cached_fw[ii]->size, - ioc->cached_fw[ii]->fw_dma); - - sgeoffset += sizeof(u32) + sizeof(dma_addr_t); - - dprintk((MYIOC_s_INFO_FMT "Sending FW Upload (req @ %p) size %d \n", - ioc->name, prequest, sgeoffset)); - - ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest, - reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag); - - cmdStatus = -EFAULT; - if (ii == 0) { - /* Handshake transfer was complete and successful. - * Check the Reply Frame. - */ - int status, transfer_sz; - status = le16_to_cpu(preply->IOCStatus); - if (status == MPI_IOCSTATUS_SUCCESS) { - transfer_sz = le32_to_cpu(preply->ActualImageSize); - if (transfer_sz == sz) - cmdStatus = 0; - } - } - ddlprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n", - ioc->name, cmdStatus)); - - /* Check to see if we have a copy of this image in - * host memory already. - */ - if (cmdStatus == 0) { - ioc->upload_fw = 0; - if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) - freeMem = 1; - } - - /* We already have a copy of this image or - * we had some type of an error - either the handshake - * failed (i != 0) or the command did not complete successfully. - */ - if (cmdStatus || freeMem) { - - ddlprintk((MYIOC_s_INFO_FMT ": do_upload freeing %s image \n", - ioc->name, cmdStatus ? "incomplete" : "duplicate")); - mpt_free_fw_memory(ioc, NULL); - ioc->cached_fw = NULL; - } - - return cmdStatus; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_downloadboot - DownloadBoot code - * @ioc: Pointer to MPT_ADAPTER structure - * @flag: Specify which part of IOC memory is to be uploaded. - * @sleepFlag: Specifies whether the process can sleep - * - * FwDownloadBoot requires Programmed IO access. - * - * Returns 0 for success - * -1 FW Image size is 0 - * -2 No valid cached_fw Pointer - * <0 for fw upload failure. - */ -static int -mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) -{ - MpiFwHeader_t *FwHdr = NULL; - MpiExtImageHeader_t *ExtHdr; - fw_image_t **pCached = NULL; - int fw_sz; - u32 diag0val; -#ifdef MPT_DEBUG - u32 diag1val = 0; -#endif - int count = 0; - u32 *ptru32 = NULL; - u32 diagRwData; - u32 nextImage; - u32 ext_offset; - u32 load_addr; - int max_idx, fw_idx, ext_idx; - int left_u32s; - - ddlprintk((MYIOC_s_INFO_FMT "DbGb0: downloadboot entered.\n", - ioc->name)); -#ifdef MPT_DEBUG - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - if (ioc->alt_ioc) - diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); - ddlprintk((MYIOC_s_INFO_FMT "DbGb1: diag0=%08x, diag1=%08x\n", - ioc->name, diag0val, diag1val)); -#endif - - ddlprintk((MYIOC_s_INFO_FMT "fw size 0x%x, ioc FW Ptr %p\n", - ioc->name, ioc->facts.FWImageSize, ioc->cached_fw)); - if (ioc->alt_ioc) - ddlprintk((MYIOC_s_INFO_FMT "alt ioc FW Ptr %p\n", - ioc->name, ioc->alt_ioc->cached_fw)); - - /* Get dma_addr and data transfer size. - */ - if ((fw_sz = ioc->facts.FWImageSize) == 0) - return -1; - - /* Get the DMA from ioc or ioc->alt_ioc */ - if (ioc->cached_fw != NULL) - pCached = (fw_image_t **)ioc->cached_fw; - else if (ioc->alt_ioc && (ioc->alt_ioc->cached_fw != NULL)) - pCached = (fw_image_t **)ioc->alt_ioc->cached_fw; - - ddlprintk((MYIOC_s_INFO_FMT "DbGb2: FW Image @ %p\n", - ioc->name, pCached)); - if (!pCached) - return -2; - - /* Write magic sequence to WriteSequence register - * until enter diagnostic mode - */ - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - while ((diag0val & MPI_DIAG_DRWE) == 0) { - CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE); - - /* wait 100 msec */ - if (sleepFlag == CAN_SLEEP) { -/* SAE: Can't do this in the hypervisor */ -#if XEN_KILLED - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(100 * HZ / 1000); -#else - mdelay(100); -#endif - } else { - mdelay (100); - } - - count++; - if (count > 20) { - printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n", - ioc->name, diag0val); - return -EFAULT; - - } - - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); -#ifdef MPT_DEBUG - if (ioc->alt_ioc) - diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); - ddlprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n", - ioc->name, diag0val, diag1val)); -#endif - ddlprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n", - ioc->name, diag0val)); - } - - /* Set the DiagRwEn and Disable ARM bits */ - diag0val |= (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM); - CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); - -#ifdef MPT_DEBUG - if (ioc->alt_ioc) - diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); - - ddlprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n", - ioc->name, diag0val, diag1val)); -#endif - - /* max_idx = 1 + maximum valid buffer index - */ - max_idx = 0; - while (pCached[max_idx]) - max_idx++; - - fw_idx = 0; - FwHdr = (MpiFwHeader_t *) pCached[fw_idx]->fw; - ptru32 = (u32 *) FwHdr; - count = (FwHdr->ImageSize + 3)/4; - nextImage = FwHdr->NextImageHeaderOffset; - - /* Write the LoadStartAddress to the DiagRw Address Register - * using Programmed IO - */ - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->LoadStartAddress); - ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n", - ioc->name, FwHdr->LoadStartAddress)); - - ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x u32's @ %p\n", - ioc->name, count, ptru32)); - left_u32s = pCached[fw_idx]->size/4; - while (count--) { - if (left_u32s == 0) { - fw_idx++; - if (fw_idx >= max_idx) { - /* FIXME - ERROR CASE - */ - ; - } - ptru32 = (u32 *) pCached[fw_idx]->fw; - left_u32s = pCached[fw_idx]->size / 4; - } - left_u32s--; - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32); - ptru32++; - } - - /* left_u32s, fw_idx and ptru32 are all valid - */ - while (nextImage) { - ext_idx = 0; - ext_offset = nextImage; - while (ext_offset > pCached[ext_idx]->size) { - ext_idx++; - if (ext_idx >= max_idx) { - /* FIXME - ERROR CASE - */ - ; - } - ext_offset -= pCached[ext_idx]->size; - } - ptru32 = (u32 *) ((char *)pCached[ext_idx]->fw + ext_offset); - left_u32s = pCached[ext_idx]->size - ext_offset; - - if ((left_u32s * 4) >= sizeof(MpiExtImageHeader_t)) { - ExtHdr = (MpiExtImageHeader_t *) ptru32; - count = (ExtHdr->ImageSize + 3 )/4; - nextImage = ExtHdr->NextImageHeaderOffset; - load_addr = ExtHdr->LoadStartAddress; - } else { - u32 * ptmp = (u32 *)pCached[ext_idx+1]->fw; - - switch (left_u32s) { - case 5: - count = *(ptru32 + 2); - nextImage = *(ptru32 + 3); - load_addr = *(ptru32 + 4); - break; - case 4: - count = *(ptru32 + 2); - nextImage = *(ptru32 + 3); - load_addr = *ptmp; - break; - case 3: - count = *(ptru32 + 2); - nextImage = *ptmp; - load_addr = *(ptmp + 1); - break; - case 2: - count = *ptmp; - nextImage = *(ptmp + 1); - load_addr = *(ptmp + 2); - break; - - case 1: - count = *(ptmp + 1); - nextImage = *(ptmp + 2); - load_addr = *(ptmp + 3); - break; - - default: - count = 0; - nextImage = 0; - load_addr = 0; - /* FIXME - ERROR CASE - */ - ; - - } - count = (count +3)/4; - } - - ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x u32's @ %p\n", - ioc->name, count, ptru32)); - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr); - - while (count--) { - if (left_u32s == 0) { - fw_idx++; - if (fw_idx >= max_idx) { - /* FIXME - ERROR CASE - */ - ; - } - ptru32 = (u32 *) pCached[fw_idx]->fw; - left_u32s = pCached[fw_idx]->size / 4; - } - left_u32s--; - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32); - ptru32++; - } - } - - /* Write the IopResetVectorRegAddr */ - ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr! \n", ioc->name)); - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->IopResetRegAddr); - - /* Write the IopResetVectorValue */ - ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value! \n", ioc->name)); - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, FwHdr->IopResetVectorValue); - - /* Clear the internal flash bad bit - autoincrementing register, - * so must do two writes. - */ - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); - diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData); - diagRwData |= 0x4000000; - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData); - - /* clear the RW enable and DISARM bits */ - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - diag0val &= ~(MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE | MPI_DIAG_FLASH_BAD_SIG); - CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); - - /* Write 0xFF to reset the sequencer */ - CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); - - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * KickStart - Perform hard reset of MPT adapter. - * @ioc: Pointer to MPT_ADAPTER structure - * @force: Force hard reset - * @sleepFlag: Specifies whether the process can sleep - * - * This routine places MPT adapter in diagnostic mode via the - * WriteSequence register, and then performs a hard reset of adapter - * via the Diagnostic register. - * - * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread) - * or NO_SLEEP (interrupt thread, use mdelay) - * force - 1 if doorbell active, board fault state - * board operational, IOC_RECOVERY or - * IOC_BRINGUP and there is an alt_ioc. - * 0 else - * - * Returns: - * 1 - hard reset, READY - * 0 - no reset due to History bit, READY - * -1 - no reset due to History bit but not READY - * OR reset but failed to come READY - * -2 - no reset, could not enter DIAG mode - * -3 - reset but bad FW bit - */ -static int -KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) -{ - int hard_reset_done = 0; - u32 ioc_state; - int cnt = 0; - - dprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name)); - if ((int)ioc->chip_type > (int)FC929) { - /* Always issue a Msg Unit Reset first. This will clear some - * SCSI bus hang conditions. - */ - SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag); - - if (sleepFlag == CAN_SLEEP) { -/* SAE: Can't do this in the hypervisor */ -#if XEN_KILLED - schedule_timeout(HZ); -#else - mdelay(1000); -#endif - } else { - mdelay (1000); - } - } - - hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag); - if (hard_reset_done < 0) - return hard_reset_done; - - dprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n", - ioc->name)); - - for (cnt=0; cntname, cnt)); - return hard_reset_done; - } - if (sleepFlag == CAN_SLEEP) { -/* SAE: Can't do this in the hypervisor */ -#if XEN_KILLED - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); -#else - mdelay(10); -#endif - } else { - mdelay (10); - } - } - - printk(MYIOC_s_ERR_FMT "Failed to come READY after reset!\n", - ioc->name); - return -1; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_diag_reset - Perform hard reset of the adapter. - * @ioc: Pointer to MPT_ADAPTER structure - * @ignore: Set if to honor and clear to ignore - * the reset history bit - * @sleepflag: CAN_SLEEP if called in a non-interrupt thread, - * else set to NO_SLEEP (use mdelay instead) - * - * This routine places the adapter in diagnostic mode via the - * WriteSequence register and then performs a hard reset of adapter - * via the Diagnostic register. Adapter should be in ready state - * upon successful completion. - * - * Returns: 1 hard reset successful - * 0 no reset performed because reset history bit set - * -2 enabling diagnostic mode failed - * -3 diagnostic reset failed - */ -static int -mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) -{ - u32 diag0val; - u32 doorbell; - int hard_reset_done = 0; - int count = 0; -#ifdef MPT_DEBUG - u32 diag1val = 0; -#endif - - /* Clear any existing interrupts */ - CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - - /* Use "Diagnostic reset" method! (only thing available!) */ - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - -#ifdef MPT_DEBUG - if (ioc->alt_ioc) - diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); - dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n", - ioc->name, diag0val, diag1val)); -#endif - - /* Do the reset if we are told to ignore the reset history - * or if the reset history is 0 - */ - if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) { - while ((diag0val & MPI_DIAG_DRWE) == 0) { - /* Write magic sequence to WriteSequence register - * Loop until in diagnostic mode - */ - CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE); - - /* wait 100 msec */ - if (sleepFlag == CAN_SLEEP) { -/* SAE: Can't do this in the hypervisor */ -#if XEN_KILLED - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(100 * HZ / 1000); -#else - mdelay(100); -#endif - } else { - mdelay (100); - } - - count++; - if (count > 20) { - printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n", - ioc->name, diag0val); - return -2; - - } - - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - - dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n", - ioc->name, diag0val)); - } - -#ifdef MPT_DEBUG - if (ioc->alt_ioc) - diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); - dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n", - ioc->name, diag0val, diag1val)); -#endif - /* Write the PreventIocBoot bit */ - if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) { - diag0val |= MPI_DIAG_PREVENT_IOC_BOOT; - CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); - } - - /* - * Disable the ARM (Bug fix) - * - */ - CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM); - mdelay (1); - - /* - * Now hit the reset bit in the Diagnostic register - * (THE BIG HAMMER!) (Clears DRWE bit). - */ - CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER); - hard_reset_done = 1; - dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n", - ioc->name)); - - /* - * Call each currently registered protocol IOC reset handler - * with pre-reset indication. - * NOTE: If we're doing _IOC_BRINGUP, there can be no - * MptResetHandlers[] registered yet. - */ - { - int ii; - int r = 0; - - for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { - if (MptResetHandlers[ii]) { - dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n", - ioc->name, ii)); - r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET); - if (ioc->alt_ioc) { - dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n", - ioc->name, ioc->alt_ioc->name, ii)); - r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET); - } - } - } - /* FIXME? Examine results here? */ - } - - if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) { - /* If the DownloadBoot operation fails, the - * IOC will be left unusable. This is a fatal error - * case. _diag_reset will return < 0 - */ - for (count = 0; count < 30; count ++) { - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); -#ifdef MPT_DEBUG - if (ioc->alt_ioc) - diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); - dprintk((MYIOC_s_INFO_FMT - "DbG2b: diag0=%08x, diag1=%08x\n", - ioc->name, diag0val, diag1val)); -#endif - if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) { - break; - } - - /* wait 1 sec */ - if (sleepFlag == CAN_SLEEP) { -/* SAE: Can't do this in the hypervisor */ -#if XEN_KILLED - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); -#else - mdelay(1000); -#endif - } else { - mdelay (1000); - } - } - if ((count = mpt_downloadboot(ioc, sleepFlag)) < 0) { - printk(KERN_WARNING MYNAM - ": firmware downloadboot failure (%d)!\n", count); - } - - } else { - /* Wait for FW to reload and for board - * to go to the READY state. - * Maximum wait is 60 seconds. - * If fail, no error will check again - * with calling program. - */ - for (count = 0; count < 60; count ++) { - doorbell = CHIPREG_READ32(&ioc->chip->Doorbell); - doorbell &= MPI_IOC_STATE_MASK; - - if (doorbell == MPI_IOC_STATE_READY) { - break; - } - - /* wait 1 sec */ - if (sleepFlag == CAN_SLEEP) { -/* SAE: Can't do this in the hypervisor */ -#if XEN_KILLED - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); -#else - mdelay(1000); -#endif - } else { - mdelay (1000); - } - } - } - } - - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); -#ifdef MPT_DEBUG - if (ioc->alt_ioc) - diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); - dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n", - ioc->name, diag0val, diag1val)); -#endif - - /* Clear RESET_HISTORY bit! Place board in the - * diagnostic mode to update the diag register. - */ - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - count = 0; - while ((diag0val & MPI_DIAG_DRWE) == 0) { - /* Write magic sequence to WriteSequence register - * Loop until in diagnostic mode - */ - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE); - - /* wait 100 msec */ - if (sleepFlag == CAN_SLEEP) { -/* SAE: Can't do this in the hypervisor */ -#if XEN_KILLED - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(100 * HZ / 1000); -#else - mdelay(100); -#endif - } else { - mdelay (100); - } - - count++; - if (count > 20) { - printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n", - ioc->name, diag0val); - break; - } - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - } - diag0val &= ~MPI_DIAG_RESET_HISTORY; - CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - if (diag0val & MPI_DIAG_RESET_HISTORY) { - printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n", - ioc->name); - } - - /* Disable Diagnostic Mode - */ - CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF); - - /* Check FW reload status flags. - */ - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) { - printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n", - ioc->name, diag0val); - return -3; - } - -#ifdef MPT_DEBUG - if (ioc->alt_ioc) - diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); - dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n", - ioc->name, diag0val, diag1val)); -#endif - - /* - * Reset flag that says we've enabled event notification - */ - ioc->facts.EventState = 0; - - if (ioc->alt_ioc) - ioc->alt_ioc->facts.EventState = 0; - - return hard_reset_done; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * SendIocReset - Send IOCReset request to MPT adapter. - * @ioc: Pointer to MPT_ADAPTER structure - * @reset_type: reset type, expected values are - * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET - * - * Send IOCReset request to the MPT adapter. - * - * Returns 0 for success, non-zero for failure. - */ -static int -SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) -{ - int r; - u32 state; - int cntdn, count; - - dprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n", - ioc->name, reset_type)); - CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<name, (count+5)/HZ); - return -ETIME; - } - - if (sleepFlag == CAN_SLEEP) { -/* SAE: Can't do this in the hypervisor */ -#if XEN_KILLED - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); -#else - mdelay(1); -#endif - } else { - mdelay (1); /* 1 msec delay */ - } - } - - /* TODO! - * Cleanup all event stuff for this IOC; re-issue EventNotification - * request if needed. - */ - if (ioc->facts.Function) - ioc->facts.EventState = 0; - - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * PrimeIocFifos - Initialize IOC request and reply FIFOs. - * @ioc: Pointer to MPT_ADAPTER structure - * - * This routine allocates memory for the MPT reply and request frame - * pools (if necessary), and primes the IOC reply FIFO with - * reply frames. - * - * Returns 0 for success, non-zero for failure. - */ -static int -PrimeIocFifos(MPT_ADAPTER *ioc) -{ - MPT_FRAME_HDR *mf; - unsigned long b; - unsigned long flags; - dma_addr_t aligned_mem_dma; - u8 *mem, *aligned_mem; - int i, sz; - - /* Prime reply FIFO... */ - - if (ioc->reply_frames == NULL) { - sz = (ioc->reply_sz * ioc->reply_depth) + 128; - mem = pci_alloc_consistent(ioc->pcidev, sz, &ioc->reply_alloc_dma); - if (mem == NULL) - goto out_fail; - - memset(mem, 0, sz); - ioc->alloc_total += sz; - ioc->reply_alloc = mem; - dprintk((KERN_INFO MYNAM ": %s.reply_alloc @ %p[%p], sz=%d bytes\n", - ioc->name, mem, (void *)(ulong)ioc->reply_alloc_dma, sz)); - - b = (unsigned long) mem; - b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */ - aligned_mem = (u8 *) b; - ioc->reply_frames = (MPT_FRAME_HDR *) aligned_mem; - ioc->reply_frames_dma = - (ioc->reply_alloc_dma + (aligned_mem - mem)); - - ioc->reply_frames_low_dma = (u32) (ioc->reply_frames_dma & 0xFFFFFFFF); - } - - /* Post Reply frames to FIFO - */ - aligned_mem_dma = ioc->reply_frames_dma; - dprintk((KERN_INFO MYNAM ": %s.reply_frames @ %p[%p]\n", - ioc->name, ioc->reply_frames, (void *)(ulong)aligned_mem_dma)); - - for (i = 0; i < ioc->reply_depth; i++) { - /* Write each address to the IOC! */ - CHIPREG_WRITE32(&ioc->chip->ReplyFifo, aligned_mem_dma); - aligned_mem_dma += ioc->reply_sz; - } - - - /* Request FIFO - WE manage this! */ - - if (ioc->req_frames == NULL) { - sz = (ioc->req_sz * ioc->req_depth) + 128; - /* - * Rounding UP to nearest 4-kB boundary here... - */ - sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000; - - mem = pci_alloc_consistent(ioc->pcidev, sz, &ioc->req_alloc_dma); - if (mem == NULL) - goto out_fail; - - memset(mem, 0, sz); - ioc->alloc_total += sz; - ioc->req_alloc = mem; - dprintk((KERN_INFO MYNAM ": %s.req_alloc @ %p[%p], sz=%d bytes\n", - ioc->name, mem, (void *)(ulong)ioc->req_alloc_dma, sz)); - - b = (unsigned long) mem; - b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */ - aligned_mem = (u8 *) b; - ioc->req_frames = (MPT_FRAME_HDR *) aligned_mem; - ioc->req_frames_dma = - (ioc->req_alloc_dma + (aligned_mem - mem)); - - ioc->req_frames_low_dma = (u32) (ioc->req_frames_dma & 0xFFFFFFFF); - - if (sizeof(dma_addr_t) == sizeof(u64)) { - /* Check: upper 32-bits of the request and reply frame - * physical addresses must be the same. - */ - if (((u64)ioc->req_frames_dma >> 32) != ((u64)ioc->reply_frames_dma >> 32)){ - goto out_fail; - } - } - -#if defined(CONFIG_MTRR) && 0 - /* - * Enable Write Combining MTRR for IOC's memory region. - * (at least as much as we can; "size and base must be - * multiples of 4 kiB" - */ - ioc->mtrr_reg = mtrr_add(ioc->req_alloc_dma, - sz, - MTRR_TYPE_WRCOMB, 1); - dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n", - ioc->name, ioc->req_alloc_dma, sz)); -#endif - } - - /* Initialize Request frames linked list - */ - aligned_mem_dma = ioc->req_frames_dma; - aligned_mem = (u8 *) ioc->req_frames; - dprintk((KERN_INFO MYNAM ": %s.req_frames @ %p[%p]\n", - ioc->name, aligned_mem, (void *)(ulong)aligned_mem_dma)); - - spin_lock_irqsave(&ioc->FreeQlock, flags); - Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR); - for (i = 0; i < ioc->req_depth; i++) { - mf = (MPT_FRAME_HDR *) aligned_mem; - - /* Queue REQUESTs *internally*! */ - Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR); - aligned_mem += ioc->req_sz; - } - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - - - if (ioc->sense_buf_pool == NULL) { - sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC); - ioc->sense_buf_pool = - pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma); - if (ioc->sense_buf_pool == NULL) - goto out_fail; - - ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF); - ioc->alloc_total += sz; - } - - return 0; - -out_fail: - if (ioc->reply_alloc != NULL) { - sz = (ioc->reply_sz * ioc->reply_depth) + 128; - pci_free_consistent(ioc->pcidev, - sz, - ioc->reply_alloc, ioc->reply_alloc_dma); - ioc->reply_frames = NULL; - ioc->reply_alloc = NULL; - ioc->alloc_total -= sz; - } - if (ioc->req_alloc != NULL) { - sz = (ioc->req_sz * ioc->req_depth) + 128; - /* - * Rounding UP to nearest 4-kB boundary here... - */ - sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000; - pci_free_consistent(ioc->pcidev, - sz, - ioc->req_alloc, ioc->req_alloc_dma); -#if defined(CONFIG_MTRR) && 0 - if (ioc->mtrr_reg > 0) { - mtrr_del(ioc->mtrr_reg, 0, 0); - dprintk((MYIOC_s_INFO_FMT "MTRR region de-registered\n", - ioc->name)); - } -#endif - ioc->req_frames = NULL; - ioc->req_alloc = NULL; - ioc->alloc_total -= sz; - } - if (ioc->sense_buf_pool != NULL) { - sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC); - pci_free_consistent(ioc->pcidev, - sz, - ioc->sense_buf_pool, ioc->sense_buf_pool_dma); - ioc->sense_buf_pool = NULL; - } - return -1; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_handshake_req_reply_wait - Send MPT request to and receive reply from - * IOC via doorbell handshake method. - * @ioc: Pointer to MPT_ADAPTER structure - * @reqBytes: Size of the request in bytes - * @req: Pointer to MPT request frame - * @replyBytes: Expected size of the reply in bytes - * @u16reply: Pointer to area where reply should be written - * @maxwait: Max wait time for a reply (in seconds) - * @sleepFlag: Specifies whether the process can sleep - * - * NOTES: It is the callers responsibility to byte-swap fields in the - * request which are greater than 1 byte in size. It is also the - * callers responsibility to byte-swap response fields which are - * greater than 1 byte in size. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, - int replyBytes, u16 *u16reply, int maxwait, int sleepFlag) -{ - MPIDefaultReply_t *mptReply; - int failcnt = 0; - int t; - - /* - * Get ready to cache a handshake reply - */ - ioc->hs_reply_idx = 0; - mptReply = (MPIDefaultReply_t *) ioc->hs_reply; - mptReply->MsgLength = 0; - - /* - * Make sure there are no doorbells (WRITE 0 to IntStatus reg), - * then tell IOC that we want to handshake a request of N words. - * (WRITE u32val to Doorbell reg). - */ - CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - CHIPREG_WRITE32(&ioc->chip->Doorbell, - ((MPI_FUNCTION_HANDSHAKE<name, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : "")); - - /* Read doorbell and check for active bit */ - if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE)) - return -1; - - /* - * Clear doorbell int (WRITE 0 to IntStatus reg), - * then wait for IOC to ACKnowledge that it's ready for - * our handshake request. - */ - CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - if (!failcnt && (t = WaitForDoorbellAck(ioc, 4, sleepFlag)) < 0) - failcnt++; - - if (!failcnt) { - int ii; - u8 *req_as_bytes = (u8 *) req; - - /* - * Stuff request words via doorbell handshake, - * with ACK from IOC for each. - */ - for (ii = 0; !failcnt && ii < reqBytes/4; ii++) { - u32 word = ((req_as_bytes[(ii*4) + 0] << 0) | - (req_as_bytes[(ii*4) + 1] << 8) | - (req_as_bytes[(ii*4) + 2] << 16) | - (req_as_bytes[(ii*4) + 3] << 24)); - - CHIPREG_WRITE32(&ioc->chip->Doorbell, word); - if ((t = WaitForDoorbellAck(ioc, 4, sleepFlag)) < 0) - failcnt++; - } - - dmfprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req)); - DBG_DUMP_REQUEST_FRAME_HDR(req) - - dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n", - ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : "")); - - /* - * Wait for completion of doorbell handshake reply from the IOC - */ - if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0) - failcnt++; - - /* - * Copy out the cached reply... - */ - for (ii=0; ii < MIN(replyBytes/2,mptReply->MsgLength*2); ii++) - u16reply[ii] = ioc->hs_reply[ii]; - } else { - return -99; - } - - return -failcnt; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit - * in it's IntStatus register. - * @ioc: Pointer to MPT_ADAPTER structure - * @howlong: How long to wait (in seconds) - * @sleepFlag: Specifies whether the process can sleep - * - * This routine waits (up to ~2 seconds max) for IOC doorbell - * handshake ACKnowledge. - * - * Returns a negative value on failure, else wait loop count. - */ -static int -WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) -{ - int cntdn; - int count = 0; - u32 intstat; - - cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong; - - if (sleepFlag == CAN_SLEEP) { - while (--cntdn) { - intstat = CHIPREG_READ32(&ioc->chip->IntStatus); - if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS)) - break; -/* SAE: Can't do this in the hypervisor */ -#if XEN_KILLED - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); -#else - mdelay(1); -#endif - count++; - } - } else { - while (--cntdn) { - intstat = CHIPREG_READ32(&ioc->chip->IntStatus); - if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS)) - break; - mdelay (1); - count++; - } - } - - if (cntdn) { - dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (cnt=%d)\n", - ioc->name, count)); - return count; - } - - printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout(%d)!\n", - ioc->name, (count+5)/HZ); - return -1; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit - * in it's IntStatus register. - * @ioc: Pointer to MPT_ADAPTER structure - * @howlong: How long to wait (in seconds) - * @sleepFlag: Specifies whether the process can sleep - * - * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt. - * - * Returns a negative value on failure, else wait loop count. - */ -static int -WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) -{ - int cntdn; - int count = 0; - u32 intstat; - - cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong; - if (sleepFlag == CAN_SLEEP) { - while (--cntdn) { - intstat = CHIPREG_READ32(&ioc->chip->IntStatus); - if (intstat & MPI_HIS_DOORBELL_INTERRUPT) - break; -/* SAE: Can't do this in the hypervisor */ -#if XEN_KILLED - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); -#else - mdelay(1); -#endif - count++; - } - } else { - while (--cntdn) { - intstat = CHIPREG_READ32(&ioc->chip->IntStatus); - if (intstat & MPI_HIS_DOORBELL_INTERRUPT) - break; - mdelay(1); - count++; - } - } - - if (cntdn) { - dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d)\n", - ioc->name, count)); - return count; - } - - printk(MYIOC_s_ERR_FMT "Doorbell INT timeout(%d)!\n", - ioc->name, (count+5)/HZ); - return -1; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * WaitForDoorbellReply - Wait for and capture a IOC handshake reply. - * @ioc: Pointer to MPT_ADAPTER structure - * @howlong: How long to wait (in seconds) - * @sleepFlag: Specifies whether the process can sleep - * - * This routine polls the IOC for a handshake reply, 16 bits at a time. - * Reply is cached to IOC private area large enough to hold a maximum - * of 128 bytes of reply data. - * - * Returns a negative value on failure, else size of reply in WORDS. - */ -static int -WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag) -{ - int u16cnt = 0; - int failcnt = 0; - int t; - u16 *hs_reply = ioc->hs_reply; - volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply; - u16 hword; - - hs_reply[0] = hs_reply[1] = hs_reply[7] = 0; - - /* - * Get first two u16's so we can look at IOC's intended reply MsgLength - */ - u16cnt=0; - if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) { - failcnt++; - } else { - hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF); - CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - if ((t = WaitForDoorbellInt(ioc, 2, sleepFlag)) < 0) - failcnt++; - else { - hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF); - CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - } - } - - dhsprintk((MYIOC_s_INFO_FMT "First handshake reply word=%08x%s\n", - ioc->name, le32_to_cpu(*(u32 *)hs_reply), - failcnt ? " - MISSING DOORBELL HANDSHAKE!" : "")); - - /* - * If no error (and IOC said MsgLength is > 0), piece together - * reply 16 bits at a time. - */ - for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) { - if ((t = WaitForDoorbellInt(ioc, 2, sleepFlag)) < 0) - failcnt++; - hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF); - /* don't overflow our IOC hs_reply[] buffer! */ - if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0])) - hs_reply[u16cnt] = hword; - CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - } - - if (!failcnt && (t = WaitForDoorbellInt(ioc, 2, sleepFlag)) < 0) - failcnt++; - CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - - if (failcnt) { - printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n", - ioc->name); - return -failcnt; - } -#if 0 - else if (u16cnt != (2 * mptReply->MsgLength)) { - return -101; - } - else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { - return -102; - } -#endif - - dmfprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name)); - DBG_DUMP_REPLY_FRAME(mptReply) - - dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY (sz=%d)\n", - ioc->name, u16cnt/2)); - return u16cnt/2; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * GetLanConfigPages - Fetch LANConfig pages. - * @ioc: Pointer to MPT_ADAPTER structure - * - * Return: 0 for success - * -ENOMEM if no memory available - * -EPERM if not allowed due to ISR context - * -EAGAIN if no msg frames currently available - * -EFAULT for non-successful reply or no reply (timeout) - */ -static int -GetLanConfigPages(MPT_ADAPTER *ioc) -{ - ConfigPageHeader_t hdr; - CONFIGPARMS cfg; - LANPage0_t *ppage0_alloc; - dma_addr_t page0_dma; - LANPage1_t *ppage1_alloc; - dma_addr_t page1_dma; - int rc = 0; - int data_sz; - int copy_sz; - - /* Get LAN Page 0 header */ - hdr.PageVersion = 0; - hdr.PageLength = 0; - hdr.PageNumber = 0; - hdr.PageType = MPI_CONFIG_PAGETYPE_LAN; - cfg.hdr = &hdr; - cfg.physAddr = -1; - cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; - cfg.dir = 0; - cfg.pageAddr = 0; - cfg.timeout = 0; - - if ((rc = mpt_config(ioc, &cfg)) != 0) - return rc; - - if (hdr.PageLength > 0) { - data_sz = hdr.PageLength * 4; - ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma); - rc = -ENOMEM; - if (ppage0_alloc) { - memset((u8 *)ppage0_alloc, 0, data_sz); - cfg.physAddr = page0_dma; - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - - if ((rc = mpt_config(ioc, &cfg)) == 0) { - /* save the data */ - copy_sz = MIN(sizeof(LANPage0_t), data_sz); - memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz); - - } - - pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); - - /* FIXME! - * Normalize endianness of structure data, - * by byte-swapping all > 1 byte fields! - */ - - } - - if (rc) - return rc; - } - - /* Get LAN Page 1 header */ - hdr.PageVersion = 0; - hdr.PageLength = 0; - hdr.PageNumber = 1; - hdr.PageType = MPI_CONFIG_PAGETYPE_LAN; - cfg.hdr = &hdr; - cfg.physAddr = -1; - cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; - cfg.dir = 0; - cfg.pageAddr = 0; - - if ((rc = mpt_config(ioc, &cfg)) != 0) - return rc; - - if (hdr.PageLength == 0) - return 0; - - data_sz = hdr.PageLength * 4; - rc = -ENOMEM; - ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma); - if (ppage1_alloc) { - memset((u8 *)ppage1_alloc, 0, data_sz); - cfg.physAddr = page1_dma; - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - - if ((rc = mpt_config(ioc, &cfg)) == 0) { - /* save the data */ - copy_sz = MIN(sizeof(LANPage1_t), data_sz); - memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz); - } - - pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma); - - /* FIXME! - * Normalize endianness of structure data, - * by byte-swapping all > 1 byte fields! - */ - - } - - return rc; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * GetFcPortPage0 - Fetch FCPort config Page0. - * @ioc: Pointer to MPT_ADAPTER structure - * @portnum: IOC Port number - * - * Return: 0 for success - * -ENOMEM if no memory available - * -EPERM if not allowed due to ISR context - * -EAGAIN if no msg frames currently available - * -EFAULT for non-successful reply or no reply (timeout) - */ -static int -GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) -{ - ConfigPageHeader_t hdr; - CONFIGPARMS cfg; - FCPortPage0_t *ppage0_alloc; - FCPortPage0_t *pp0dest; - dma_addr_t page0_dma; - int data_sz; - int copy_sz; - int rc; - - /* Get FCPort Page 0 header */ - hdr.PageVersion = 0; - hdr.PageLength = 0; - hdr.PageNumber = 0; - hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; - cfg.hdr = &hdr; - cfg.physAddr = -1; - cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; - cfg.dir = 0; - cfg.pageAddr = portnum; - cfg.timeout = 0; - - if ((rc = mpt_config(ioc, &cfg)) != 0) - return rc; - - if (hdr.PageLength == 0) - return 0; - - data_sz = hdr.PageLength * 4; - rc = -ENOMEM; - ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma); - if (ppage0_alloc) { - memset((u8 *)ppage0_alloc, 0, data_sz); - cfg.physAddr = page0_dma; - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - - if ((rc = mpt_config(ioc, &cfg)) == 0) { - /* save the data */ - pp0dest = &ioc->fc_port_page0[portnum]; - copy_sz = MIN(sizeof(FCPortPage0_t), data_sz); - memcpy(pp0dest, ppage0_alloc, copy_sz); - - /* - * Normalize endianness of structure data, - * by byte-swapping all > 1 byte fields! - */ - pp0dest->Flags = le32_to_cpu(pp0dest->Flags); - pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier); - pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low); - pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High); - pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low); - pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High); - pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass); - pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds); - pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed); - pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize); - pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low); - pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High); - pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low); - pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High); - pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount); - pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators); - - } - - pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); - } - - return rc; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * GetIoUnitPage2 - Retrieve BIOS version and boot order information. - * @ioc: Pointer to MPT_ADAPTER structure - * - * Returns: 0 for success - * -ENOMEM if no memory available - * -EPERM if not allowed due to ISR context - * -EAGAIN if no msg frames currently available - * -EFAULT for non-successful reply or no reply (timeout) - */ -static int -GetIoUnitPage2(MPT_ADAPTER *ioc) -{ - ConfigPageHeader_t hdr; - CONFIGPARMS cfg; - IOUnitPage2_t *ppage_alloc; - dma_addr_t page_dma; - int data_sz; - int rc; - - /* Get the page header */ - hdr.PageVersion = 0; - hdr.PageLength = 0; - hdr.PageNumber = 2; - hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT; - cfg.hdr = &hdr; - cfg.physAddr = -1; - cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; - cfg.dir = 0; - cfg.pageAddr = 0; - cfg.timeout = 0; - - if ((rc = mpt_config(ioc, &cfg)) != 0) - return rc; - - if (hdr.PageLength == 0) - return 0; - - /* Read the config page */ - data_sz = hdr.PageLength * 4; - rc = -ENOMEM; - ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma); - if (ppage_alloc) { - memset((u8 *)ppage_alloc, 0, data_sz); - cfg.physAddr = page_dma; - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - - /* If Good, save data */ - if ((rc = mpt_config(ioc, &cfg)) == 0) - ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion); - - pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma); - } - - return rc; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2 - * @ioc: Pointer to a Adapter Strucutre - * @portnum: IOC port number - * - * Return: -EFAULT if read of config page header fails - * or if no nvram - * If read of SCSI Port Page 0 fails, - * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF) - * Adapter settings: async, narrow - * Return 1 - * If read of SCSI Port Page 2 fails, - * Adapter settings valid - * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF) - * Return 1 - * Else - * Both valid - * Return 0 - * CHECK - what type of locking mechanisms should be used???? - */ -static int -mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) -{ - u8 *pbuf = NULL; - dma_addr_t buf_dma; - CONFIGPARMS cfg; - ConfigPageHeader_t header; - int ii; - int data, rc = 0; - - /* Allocate memory - */ - if (!ioc->spi_data.nvram) { - int sz; - u8 *mem; - sz = MPT_MAX_SCSI_DEVICES * sizeof(int); - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) - return -EFAULT; - - ioc->spi_data.nvram = (int *) mem; - - dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n", - ioc->name, ioc->spi_data.nvram, sz)); - } - - /* Invalidate NVRAM information - */ - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { - ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID; - } - - /* Read SPP0 header, allocate memory, then read page. - */ - header.PageVersion = 0; - header.PageLength = 0; - header.PageNumber = 0; - header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT; - cfg.hdr = &header; - cfg.physAddr = -1; - cfg.pageAddr = portnum; - cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; - cfg.dir = 0; - cfg.timeout = 0; /* use default */ - if (mpt_config(ioc, &cfg) != 0) - return -EFAULT; - - if (header.PageLength > 0) { - pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma); - if (pbuf) { - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - cfg.physAddr = buf_dma; - if (mpt_config(ioc, &cfg) != 0) { - ioc->spi_data.maxBusWidth = MPT_NARROW; - ioc->spi_data.maxSyncOffset = 0; - ioc->spi_data.minSyncFactor = MPT_ASYNC; - ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN; - rc = 1; - } else { - /* Save the Port Page 0 data - */ - SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf; - pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities); - pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface); - - ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0; - data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK; - if (data) { - ioc->spi_data.maxSyncOffset = (u8) (data >> 16); - data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK; - ioc->spi_data.minSyncFactor = (u8) (data >> 8); - } else { - ioc->spi_data.maxSyncOffset = 0; - ioc->spi_data.minSyncFactor = MPT_ASYNC; - } - - ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK; - - /* Update the minSyncFactor based on bus type. - */ - if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) || - (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) { - - if (ioc->spi_data.minSyncFactor < MPT_ULTRA) - ioc->spi_data.minSyncFactor = MPT_ULTRA; - } - } - if (pbuf) { - pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma); - pbuf = NULL; - } - } - } - - /* SCSI Port Page 2 - Read the header then the page. - */ - header.PageVersion = 0; - header.PageLength = 0; - header.PageNumber = 2; - header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT; - cfg.hdr = &header; - cfg.physAddr = -1; - cfg.pageAddr = portnum; - cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; - cfg.dir = 0; - if (mpt_config(ioc, &cfg) != 0) - return -EFAULT; - - if (header.PageLength > 0) { - /* Allocate memory and read SCSI Port Page 2 - */ - pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma); - if (pbuf) { - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM; - cfg.physAddr = buf_dma; - if (mpt_config(ioc, &cfg) != 0) { - /* Nvram data is left with INVALID mark - */ - rc = 1; - } else { - SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf; - MpiDeviceInfo_t *pdevice = NULL; - - /* Save the Port Page 2 data - * (reformat into a 32bit quantity) - */ - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { - pdevice = &pPP2->DeviceSettings[ii]; - data = (le16_to_cpu(pdevice->DeviceFlags) << 16) | - (pdevice->SyncFactor << 8) | pdevice->Timeout; - ioc->spi_data.nvram[ii] = data; - } - } - - pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma); - pbuf = NULL; - } - } - - /* Update Adapter limits with those from NVRAM - * Comment: Don't need to do this. Target performance - * parameters will never exceed the adapters limits. - */ - - return rc; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mpt_readScsiDevicePageHeaders - save version and length of SDP1 - * @ioc: Pointer to a Adapter Strucutre - * @portnum: IOC port number - * - * Return: -EFAULT if read of config page header fails - * or 0 if success. - */ -static int -mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) -{ - CONFIGPARMS cfg; - ConfigPageHeader_t header; - - /* Read the SCSI Device Page 1 header - */ - header.PageVersion = 0; - header.PageLength = 0; - header.PageNumber = 1; - header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; - cfg.hdr = &header; - cfg.physAddr = -1; - cfg.pageAddr = portnum; - cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; - cfg.dir = 0; - cfg.timeout = 0; - if (mpt_config(ioc, &cfg) != 0) - return -EFAULT; - - ioc->spi_data.sdp1version = cfg.hdr->PageVersion; - ioc->spi_data.sdp1length = cfg.hdr->PageLength; - - header.PageVersion = 0; - header.PageLength = 0; - header.PageNumber = 0; - header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; - if (mpt_config(ioc, &cfg) != 0) - return -EFAULT; - - ioc->spi_data.sdp0version = cfg.hdr->PageVersion; - ioc->spi_data.sdp0length = cfg.hdr->PageLength; - - dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n", - ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length)); - - dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n", - ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length)); - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes - * @ioc: Pointer to a Adapter Strucutre - * @portnum: IOC port number - * - * Return: - * 0 on success - * -EFAULT if read of config page header fails or data pointer not NULL - * -ENOMEM if pci_alloc failed - */ -static int -mpt_findImVolumes(MPT_ADAPTER *ioc) -{ - IOCPage2_t *pIoc2 = NULL; - ConfigPageIoc2RaidVol_t *pIocRv = NULL; - dma_addr_t ioc2_dma; - CONFIGPARMS cfg; - ConfigPageHeader_t header; - int jj; - int rc = 0; - int iocpage2sz; - u8 nVols, nPhys; - u8 vid, vbus, vioc; - - if (ioc->spi_data.pIocPg3) - return -EFAULT; - - /* Read IOCP2 header then the page. - */ - header.PageVersion = 0; - header.PageLength = 0; - header.PageNumber = 2; - header.PageType = MPI_CONFIG_PAGETYPE_IOC; - cfg.hdr = &header; - cfg.physAddr = -1; - cfg.pageAddr = 0; - cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; - cfg.dir = 0; - cfg.timeout = 0; - if (mpt_config(ioc, &cfg) != 0) - return -EFAULT; - - if (header.PageLength == 0) - return -EFAULT; - - iocpage2sz = header.PageLength * 4; - pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma); - if (!pIoc2) - return -ENOMEM; - - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - cfg.physAddr = ioc2_dma; - if (mpt_config(ioc, &cfg) != 0) - goto done_and_free; - - /* Identify RAID Volume Id's */ - nVols = pIoc2->NumActiveVolumes; - if ( nVols == 0) { - /* No RAID Volumes. Done. - */ - } else { - /* At least 1 RAID Volume - */ - pIocRv = pIoc2->RaidVolume; - ioc->spi_data.isRaid = 0; - for (jj = 0; jj < nVols; jj++, pIocRv++) { - vid = pIocRv->VolumeID; - vbus = pIocRv->VolumeBus; - vioc = pIocRv->VolumeIOC; - - /* find the match - */ - if (vbus == 0) { - ioc->spi_data.isRaid |= (1 << vid); - } else { - /* Error! Always bus 0 - */ - } - } - } - - /* Identify Hidden Physical Disk Id's */ - nPhys = pIoc2->NumActivePhysDisks; - if (nPhys == 0) { - /* No physical disks. Done. - */ - } else { - mpt_read_ioc_pg_3(ioc); - } - -done_and_free: - if (pIoc2) { - pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma); - pIoc2 = NULL; - } - - return rc; -} - -int -mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) -{ - IOCPage3_t *pIoc3 = NULL; - u8 *mem; - CONFIGPARMS cfg; - ConfigPageHeader_t header; - dma_addr_t ioc3_dma; - int iocpage3sz = 0; - - /* Free the old page - */ - if (ioc->spi_data.pIocPg3) { - kfree(ioc->spi_data.pIocPg3); - ioc->spi_data.pIocPg3 = NULL; - } - - /* There is at least one physical disk. - * Read and save IOC Page 3 - */ - header.PageVersion = 0; - header.PageLength = 0; - header.PageNumber = 3; - header.PageType = MPI_CONFIG_PAGETYPE_IOC; - cfg.hdr = &header; - cfg.physAddr = -1; - cfg.pageAddr = 0; - cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; - cfg.dir = 0; - cfg.timeout = 0; - if (mpt_config(ioc, &cfg) != 0) - return 0; - - if (header.PageLength == 0) - return 0; - - /* Read Header good, alloc memory - */ - iocpage3sz = header.PageLength * 4; - pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma); - if (!pIoc3) - return 0; - - /* Read the Page and save the data - * into malloc'd memory. - */ - cfg.physAddr = ioc3_dma; - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - if (mpt_config(ioc, &cfg) == 0) { - mem = kmalloc(iocpage3sz, GFP_ATOMIC); - if (mem) { - memcpy(mem, (u8 *)pIoc3, iocpage3sz); - ioc->spi_data.pIocPg3 = (IOCPage3_t *) mem; - } - } - - if (pIoc3) { - pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma); - pIoc3 = NULL; - } - - return 0; -} - -static void -mpt_read_ioc_pg_1(MPT_ADAPTER *ioc) -{ - IOCPage1_t *pIoc1 = NULL; - CONFIGPARMS cfg; - ConfigPageHeader_t header; - dma_addr_t ioc1_dma; - int iocpage1sz = 0; - u32 tmp; - - /* Check the Coalescing Timeout in IOC Page 1 - */ - header.PageVersion = 0; - header.PageLength = 0; - header.PageNumber = 1; - header.PageType = MPI_CONFIG_PAGETYPE_IOC; - cfg.hdr = &header; - cfg.physAddr = -1; - cfg.pageAddr = 0; - cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; - cfg.dir = 0; - cfg.timeout = 0; - if (mpt_config(ioc, &cfg) != 0) - return; - - if (header.PageLength == 0) - return; - - /* Read Header good, alloc memory - */ - iocpage1sz = header.PageLength * 4; - pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma); - if (!pIoc1) - return; - - /* Read the Page and check coalescing timeout - */ - cfg.physAddr = ioc1_dma; - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - if (mpt_config(ioc, &cfg) == 0) { - - tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING; - if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) { - tmp = le32_to_cpu(pIoc1->CoalescingTimeout); - - dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n", - ioc->name, tmp)); - - if (tmp > MPT_COALESCING_TIMEOUT) { - pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT); - - /* Write NVRAM and current - */ - cfg.dir = 1; - cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; - if (mpt_config(ioc, &cfg) == 0) { - dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n", - ioc->name, MPT_COALESCING_TIMEOUT)); - - cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM; - if (mpt_config(ioc, &cfg) == 0) { - dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n", - ioc->name, MPT_COALESCING_TIMEOUT)); - } else { - dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n", - ioc->name)); - } - - } else { - dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n", - ioc->name)); - } - } - - } else { - dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name)); - } - } - - if (pIoc1) { - pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma); - pIoc1 = NULL; - } - - return; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * SendEventNotification - Send EventNotification (on or off) request - * to MPT adapter. - * @ioc: Pointer to MPT_ADAPTER structure - * @EvSwitch: Event switch flags - */ -static int -SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch) -{ - EventNotification_t *evnp; - - evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc->id); - if (evnp == NULL) { - dprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n", - ioc->name)); - return 0; - } - memset(evnp, 0, sizeof(*evnp)); - - dprintk((MYIOC_s_INFO_FMT "Sending EventNotification(%d)\n", ioc->name, EvSwitch)); - - evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION; - evnp->ChainOffset = 0; - evnp->MsgFlags = 0; - evnp->Switch = EvSwitch; - - mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)evnp); - - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * SendEventAck - Send EventAck request to MPT adapter. - * @ioc: Pointer to MPT_ADAPTER structure - * @evnp: Pointer to original EventNotification request - */ -static int -SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp) -{ - EventAck_t *pAck; - - if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) { - printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK request frame!\n", - ioc->name); - return -1; - } - memset(pAck, 0, sizeof(*pAck)); - - dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name)); - - pAck->Function = MPI_FUNCTION_EVENT_ACK; - pAck->ChainOffset = 0; - pAck->MsgFlags = 0; - pAck->Event = evnp->Event; - pAck->EventContext = evnp->EventContext; - - mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)pAck); - - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_config - Generic function to issue config message - * @ioc - Pointer to an adapter structure - * @cfg - Pointer to a configuration structure. Struct contains - * action, page address, direction, physical address - * and pointer to a configuration page header - * Page header is updated. - * - * Returns 0 for success - * -EPERM if not allowed due to ISR context - * -EAGAIN if no msg frames currently available - * -EFAULT for non-successful reply or no reply (timeout) - */ -int -mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) -{ - Config_t *pReq; - MPT_FRAME_HDR *mf; - unsigned long flags; - int ii, rc; - int flagsLength; - int in_isr; - - /* (Bugzilla:fibrebugs, #513) - * Bug fix (part 1)! 20010905 -sralston - * Prevent calling wait_event() (below), if caller happens - * to be in ISR context, because that is fatal! - */ - in_isr = in_interrupt(); - if (in_isr) { - dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n", - ioc->name)); - return -EPERM; - } - - /* Get and Populate a free Frame - */ - if ((mf = mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) { - dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n", - ioc->name)); - return -EAGAIN; - } - pReq = (Config_t *)mf; - pReq->Action = pCfg->action; - pReq->Reserved = 0; - pReq->ChainOffset = 0; - pReq->Function = MPI_FUNCTION_CONFIG; - pReq->Reserved1[0] = 0; - pReq->Reserved1[1] = 0; - pReq->Reserved1[2] = 0; - pReq->MsgFlags = 0; - for (ii=0; ii < 8; ii++) - pReq->Reserved2[ii] = 0; - - pReq->Header.PageVersion = pCfg->hdr->PageVersion; - pReq->Header.PageLength = pCfg->hdr->PageLength; - pReq->Header.PageNumber = pCfg->hdr->PageNumber; - pReq->Header.PageType = (pCfg->hdr->PageType & MPI_CONFIG_PAGETYPE_MASK); - pReq->PageAddress = cpu_to_le32(pCfg->pageAddr); - - /* Add a SGE to the config request. - */ - if (pCfg->dir) - flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE; - else - flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; - - flagsLength |= pCfg->hdr->PageLength * 4; - - mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr); - - dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n", - ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action)); - - /* Append pCfg pointer to end of mf - */ - *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg; - - /* Initalize the timer - */ - init_timer(&pCfg->timer); - pCfg->timer.data = (unsigned long) ioc; - pCfg->timer.function = mpt_timer_expired; - pCfg->wait_done = 0; - - /* Set the timer; ensure 10 second minimum */ - if (pCfg->timeout < 10) - pCfg->timer.expires = jiffies + HZ*10; - else - pCfg->timer.expires = jiffies + HZ*pCfg->timeout; - - /* Add to end of Q, set timer and then issue this command */ - spin_lock_irqsave(&ioc->FreeQlock, flags); - Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM); - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - - add_timer(&pCfg->timer); - - mpt_put_msg_frame(mpt_base_index, ioc->id, mf); -/* SAE: No wait queues */ -#ifdef XEN_KILLED - wait_event(mpt_waitq, pCfg->wait_done); -#else - /* SAE: We'll just wait a bit */ - while(!pCfg->wait_done) { - mdelay(10); - } -#endif - - /* mf has been freed - do not access */ - - rc = pCfg->status; - - return rc; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_timer_expired - Call back for timer process. - * Used only internal config functionality. - * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long - */ -static void -mpt_timer_expired(unsigned long data) -{ - MPT_ADAPTER *ioc = (MPT_ADAPTER *) data; - - dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name)); - - /* Perform a FW reload */ - if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) - printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name); - - /* No more processing. - * Hard reset clean-up will wake up - * process and free all resources. - */ - dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name)); - - return; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_ioc_reset - Base cleanup for hard reset - * @ioc: Pointer to the adapter structure - * @reset_phase: Indicates pre- or post-reset functionality - * - * Remark: Free's resources with internally generated commands. - */ -static int -mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) -{ - CONFIGPARMS *pCfg; - unsigned long flags; - - dprintk((KERN_WARNING MYNAM - ": IOC %s_reset routed to MPT base driver!\n", - reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( - reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); - - if (reset_phase == MPT_IOC_SETUP_RESET) { - ; - } else if (reset_phase == MPT_IOC_PRE_RESET) { - /* If the internal config Q is not empty - - * delete timer. MF resources will be freed when - * the FIFO's are primed. - */ - spin_lock_irqsave(&ioc->FreeQlock, flags); - if (! Q_IS_EMPTY(&ioc->configQ)){ - pCfg = (CONFIGPARMS *)ioc->configQ.head; - do { - del_timer(&pCfg->timer); - pCfg = (CONFIGPARMS *) (pCfg->linkage.forw); - } while (pCfg != (CONFIGPARMS *)&ioc->configQ); - } - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - - } else { - CONFIGPARMS *pNext; - - /* Search the configQ for internal commands. - * Flush the Q, and wake up all suspended threads. - */ - spin_lock_irqsave(&ioc->FreeQlock, flags); - if (! Q_IS_EMPTY(&ioc->configQ)){ - pCfg = (CONFIGPARMS *)ioc->configQ.head; - do { - pNext = (CONFIGPARMS *) pCfg->linkage.forw; - - Q_DEL_ITEM(&pCfg->linkage); - - pCfg->status = MPT_CONFIG_ERROR; - pCfg->wait_done = 1; -#ifdef XEN_KILLED - wake_up(&mpt_waitq); -#else - mdelay(250); -#endif - - pCfg = pNext; - } while (pCfg != (CONFIGPARMS *)&ioc->configQ); - } - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - } - - return 1; /* currently means nothing really */ -} - - -#ifdef CONFIG_PROC_FS /* { */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff... - */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries. - * - * Returns 0 for success, non-zero for failure. - */ -static int -procmpt_create(void) -{ - MPT_ADAPTER *ioc; - struct proc_dir_entry *ent; - int ii; - - /* - * BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt" - * (single level) to multi level (e.g. "driver/message/fusion") - * something here needs to change. -sralston - */ - mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL); - if (mpt_proc_root_dir == NULL) - return -ENOTDIR; - - for (ii=0; ii < MPT_PROC_ENTRIES; ii++) { - ent = create_proc_entry(mpt_proc_list[ii].name, - S_IFREG|S_IRUGO, mpt_proc_root_dir); - if (!ent) { - printk(KERN_WARNING MYNAM - ": WARNING - Could not create /proc/mpt/%s entry\n", - mpt_proc_list[ii].name); - continue; - } - ent->read_proc = mpt_proc_list[ii].f; - ent->data = NULL; - } - - ioc = mpt_adapter_find_first(); - while (ioc != NULL) { - struct proc_dir_entry *dent; - /* - * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter. - */ - if ((dent = proc_mkdir(ioc->name, mpt_proc_root_dir)) != NULL) { - /* - * And populate it with mpt_ioc_proc_list[] entries. - */ - for (ii=0; ii < MPT_IOC_PROC_ENTRIES; ii++) { - ent = create_proc_entry(mpt_ioc_proc_list[ii].name, - S_IFREG|S_IRUGO, dent); - if (!ent) { - printk(KERN_WARNING MYNAM - ": WARNING - Could not create /proc/mpt/%s/%s entry!\n", - ioc->name, - mpt_ioc_proc_list[ii].name); - continue; - } - ent->read_proc = mpt_ioc_proc_list[ii].f; - ent->data = ioc; - } - } else { - printk(MYIOC_s_WARN_FMT "Could not create /proc/mpt/%s subdir entry!\n", - ioc->name, mpt_ioc_proc_list[ii].name); - } - ioc = mpt_adapter_find_next(ioc); - } - - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries. - * - * Returns 0 for success, non-zero for failure. - */ -static int -procmpt_destroy(void) -{ - MPT_ADAPTER *ioc; - int ii; - - if (!mpt_proc_root_dir) - return 0; - - /* - * BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt" - * (single level) to multi level (e.g. "driver/message/fusion") - * something here needs to change. -sralston - */ - - ioc = mpt_adapter_find_first(); - while (ioc != NULL) { - char pname[32]; - int namelen; - - namelen = sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name); - - /* - * Tear down each "/proc/mpt/iocN" subdirectory. - */ - for (ii=0; ii < MPT_IOC_PROC_ENTRIES; ii++) { - (void) sprintf(pname+namelen, "/%s", mpt_ioc_proc_list[ii].name); - remove_proc_entry(pname, NULL); - } - - remove_proc_entry(ioc->name, mpt_proc_root_dir); - - ioc = mpt_adapter_find_next(ioc); - } - - for (ii=0; ii < MPT_PROC_ENTRIES; ii++) - remove_proc_entry(mpt_proc_list[ii].name, mpt_proc_root_dir); - - if (atomic_read((atomic_t *)&mpt_proc_root_dir->count) == 0) { - remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL); - mpt_proc_root_dir = NULL; - return 0; - } - - return -1; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * procmpt_summary_read - Handle read request from /proc/mpt/summary - * or from /proc/mpt/iocN/summary. - * @buf: Pointer to area to write information - * @start: Pointer to start pointer - * @offset: Offset to start writing - * @request: - * @eof: Pointer to EOF integer - * @data: Pointer - * - * Returns number of characters written to process performing the read. - */ -static int -procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data) -{ - MPT_ADAPTER *ioc; - char *out = buf; - int len; - - if (data == NULL) - ioc = mpt_adapter_find_first(); - else - ioc = data; - - while (ioc) { - int more = 0; - - mpt_print_ioc_summary(ioc, out, &more, 0, 1); - - out += more; - if ((out-buf) >= request) { - break; - } - - if (data == NULL) - ioc = mpt_adapter_find_next(ioc); - else - ioc = NULL; /* force exit for iocN */ - } - len = out - buf; - - MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len); -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * procmpt_version_read - Handle read request from /proc/mpt/version. - * @buf: Pointer to area to write information - * @start: Pointer to start pointer - * @offset: Offset to start writing - * @request: - * @eof: Pointer to EOF integer - * @data: Pointer - * - * Returns number of characters written to process performing the read. - */ -static int -procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data) -{ - int ii; - int scsi, lan, ctl, targ, dmp; - char *drvname; - int len; - - len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON); - len += sprintf(buf+len, " Fusion MPT base driver\n"); - - scsi = lan = ctl = targ = dmp = 0; - for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { - drvname = NULL; - if (MptCallbacks[ii]) { - switch (MptDriverClass[ii]) { - case MPTSCSIH_DRIVER: - if (!scsi++) drvname = "SCSI host"; - break; - case MPTLAN_DRIVER: - if (!lan++) drvname = "LAN"; - break; - case MPTSTM_DRIVER: - if (!targ++) drvname = "SCSI target"; - break; - case MPTCTL_DRIVER: - if (!ctl++) drvname = "ioctl"; - break; - case MPTDMP_DRIVER: - if (!dmp++) drvname = "DMP"; - break; - } - - if (drvname) - len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname); - /* - * Handle isense special case, because it - * doesn't do a formal mpt_register call. - */ - if (isense_idx == ii) - len += sprintf(buf+len, " Fusion MPT isense driver\n"); - } - } - - MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len); -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info. - * @buf: Pointer to area to write information - * @start: Pointer to start pointer - * @offset: Offset to start writing - * @request: - * @eof: Pointer to EOF integer - * @data: Pointer - * - * Returns number of characters written to process performing the read. - */ -static int -procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data) -{ - MPT_ADAPTER *ioc = data; - int len; - char expVer[32]; - int sz; - int p; - - mpt_get_fw_exp_ver(expVer, ioc); - - len = sprintf(buf, "%s:", ioc->name); - if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) - len += sprintf(buf+len, " (f/w download boot flag set)"); -// if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL) -// len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!"); - - len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n", - ioc->facts.ProductID, - ioc->prod_name); - len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer); - if (ioc->facts.FWImageSize) - len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize); - len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion); - len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit); - len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState); - - len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n", - ioc->facts.CurrentHostMfaHighAddr); - len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n", - ioc->facts.CurrentSenseBufferHighAddr); - - len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth); - len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize); - - len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n", - (void *)ioc->req_alloc, (void *)(ulong)ioc->req_alloc_dma); - /* - * Rounding UP to nearest 4-kB boundary here... - */ - sz = (ioc->req_sz * ioc->req_depth) + 128; - sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000; - len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n", - ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz); - len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n", - 4*ioc->facts.RequestFrameSize, - ioc->facts.GlobalCredits); - - len += sprintf(buf+len, " ReplyFrames @ 0x%p (Dma @ 0x%p)\n", - (void *)ioc->reply_alloc, (void *)(ulong)ioc->reply_alloc_dma); - sz = (ioc->reply_sz * ioc->reply_depth) + 128; - len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n", - ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz); - len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n", - ioc->facts.CurReplyFrameSize, - ioc->facts.ReplyQueueDepth); - - len += sprintf(buf+len, " MaxDevices = %d\n", - (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices); - len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses); - - /* per-port info */ - for (p=0; p < ioc->facts.NumberOfPorts; p++) { - len += sprintf(buf+len, " PortNumber = %d (of %d)\n", - p+1, - ioc->facts.NumberOfPorts); - if ((int)ioc->chip_type <= (int)FC929) { - if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { - u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; - len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", - a[5], a[4], a[3], a[2], a[1], a[0]); - } - len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n", - ioc->fc_port_page0[p].WWNN.High, - ioc->fc_port_page0[p].WWNN.Low, - ioc->fc_port_page0[p].WWPN.High, - ioc->fc_port_page0[p].WWPN.Low); - } - } - - MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len); -} - -#endif /* CONFIG_PROC_FS } */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static void -mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc) -{ - buf[0] ='\0'; - if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) { - sprintf(buf, " (Exp %02d%02d)", - (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */ - (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */ - - /* insider hack! */ - if ((ioc->facts.FWVersion.Word >> 8) & 0x80) - strcat(buf, " [MDBG]"); - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer. - * @ioc: Pointer to MPT_ADAPTER structure - * @buffer: Pointer to buffer where IOC summary info should be written - * @size: Pointer to number of bytes we wrote (set by this routine) - * @len: Offset at which to start writing in buffer - * @showlan: Display LAN stuff? - * - * This routine writes (english readable) ASCII text, which represents - * a summary of IOC information, to a buffer. - */ -void -mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan) -{ - char expVer[32]; - int y; - - mpt_get_fw_exp_ver(expVer, ioc); - - /* - * Shorter summary of attached ioc's... - */ - y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d", - ioc->name, - ioc->prod_name, - MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */ - ioc->facts.FWVersion.Word, - expVer, - ioc->facts.NumberOfPorts, - ioc->req_depth); - - if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) { - u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; - y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X", - a[5], a[4], a[3], a[2], a[1], a[0]); - } - -#ifndef __sparc__ - y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq); -#else - y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq)); -#endif - - if (!ioc->active) - y += sprintf(buffer+len+y, " (disabled)"); - - y += sprintf(buffer+len+y, "\n"); - - *size = y; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Reset Handling - */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_HardResetHandler - Generic reset handler, issue SCSI Task - * Management call based on input arg values. If TaskMgmt fails, - * return associated SCSI request. - * @ioc: Pointer to MPT_ADAPTER structure - * @sleepFlag: Indicates if sleep or schedule must be called. - * - * Remark: _HardResetHandler can be invoked from an interrupt thread (timer) - * or a non-interrupt thread. In the former, must not call schedule(). - * - * Remark: A return of -1 is a FATAL error case, as it means a - * FW reload/initialization failed. - * - * Returns 0 for SUCCESS or -1 if FAILED. - */ -int -mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) -{ - int rc; - unsigned long flags; - - dprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name)); -#ifdef MFCNT - printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name); - printk("MF count 0x%x !\n", ioc->mfcnt); -#endif - - /* Reset the adapter. Prevent more than 1 call to - * mpt_do_ioc_recovery at any instant in time. - */ - spin_lock_irqsave(&ioc->diagLock, flags); - if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){ - spin_unlock_irqrestore(&ioc->diagLock, flags); - return 0; - } else { - ioc->diagPending = 1; - } - spin_unlock_irqrestore(&ioc->diagLock, flags); - - /* FIXME: If do_ioc_recovery fails, repeat.... - */ - - /* The SCSI driver needs to adjust timeouts on all current - * commands prior to the diagnostic reset being issued. - * Prevents timeouts occuring during a diagnostic reset...very bad. - * For all other protocol drivers, this is a no-op. - */ - { - int ii; - int r = 0; - - for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { - if (MptResetHandlers[ii]) { - dprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n", - ioc->name, ii)); - r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET); - if (ioc->alt_ioc) { - dprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n", - ioc->name, ioc->alt_ioc->name, ii)); - r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET); - } - } - } - } - - if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) { - printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n", - rc, ioc->name); - } - ioc->reload_fw = 0; - if (ioc->alt_ioc) - ioc->alt_ioc->reload_fw = 0; - - spin_lock_irqsave(&ioc->diagLock, flags); - ioc->diagPending = 0; - if (ioc->alt_ioc) - ioc->alt_ioc->diagPending = 0; - spin_unlock_irqrestore(&ioc->diagLock, flags); - - dprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc)); - - return rc; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static char * -EventDescriptionStr(u8 event, u32 evData0) -{ - char *ds = NULL; - - switch(event) { - case MPI_EVENT_NONE: - ds = "None"; - break; - case MPI_EVENT_LOG_DATA: - ds = "Log Data"; - break; - case MPI_EVENT_STATE_CHANGE: - ds = "State Change"; - break; - case MPI_EVENT_UNIT_ATTENTION: - ds = "Unit Attention"; - break; - case MPI_EVENT_IOC_BUS_RESET: - ds = "IOC Bus Reset"; - break; - case MPI_EVENT_EXT_BUS_RESET: - ds = "External Bus Reset"; - break; - case MPI_EVENT_RESCAN: - ds = "Bus Rescan Event"; - /* Ok, do we need to do anything here? As far as - I can tell, this is when a new device gets added - to the loop. */ - break; - case MPI_EVENT_LINK_STATUS_CHANGE: - if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE) - ds = "Link Status(FAILURE) Change"; - else - ds = "Link Status(ACTIVE) Change"; - break; - case MPI_EVENT_LOOP_STATE_CHANGE: - if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP) - ds = "Loop State(LIP) Change"; - else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE) - ds = "Loop State(LPE) Change"; /* ??? */ - else - ds = "Loop State(LPB) Change"; /* ??? */ - break; - case MPI_EVENT_LOGOUT: - ds = "Logout"; - break; - case MPI_EVENT_EVENT_CHANGE: - if (evData0) - ds = "Events(ON) Change"; - else - ds = "Events(OFF) Change"; - break; - case MPI_EVENT_INTEGRATED_RAID: - ds = "Integrated Raid"; - break; - /* - * MPT base "custom" events may be added here... - */ - default: - ds = "Unknown"; - break; - } - return ds; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * ProcessEventNotification - Route a received EventNotificationReply to - * all currently regeistered event handlers. - * @ioc: Pointer to MPT_ADAPTER structure - * @pEventReply: Pointer to EventNotification reply frame - * @evHandlers: Pointer to integer, number of event handlers - * - * Returns sum of event handlers return values. - */ -static int -ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers) -{ - u16 evDataLen; - u32 evData0 = 0; -// u32 evCtx; - int ii; - int r = 0; - int handlers = 0; - char *evStr; - u8 event; - - /* - * Do platform normalization of values - */ - event = le32_to_cpu(pEventReply->Event) & 0xFF; -// evCtx = le32_to_cpu(pEventReply->EventContext); - evDataLen = le16_to_cpu(pEventReply->EventDataLength); - if (evDataLen) { - evData0 = le32_to_cpu(pEventReply->Data[0]); - } - - evStr = EventDescriptionStr(event, evData0); - dprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n", - ioc->name, - evStr, - event)); - -#if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS) - printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO); - for (ii = 0; ii < evDataLen; ii++) - printk(" %08x", le32_to_cpu(pEventReply->Data[ii])); - printk("\n"); -#endif - - /* - * Do general / base driver event processing - */ - switch(event) { - case MPI_EVENT_NONE: /* 00 */ - case MPI_EVENT_LOG_DATA: /* 01 */ - case MPI_EVENT_STATE_CHANGE: /* 02 */ - case MPI_EVENT_UNIT_ATTENTION: /* 03 */ - case MPI_EVENT_IOC_BUS_RESET: /* 04 */ - case MPI_EVENT_EXT_BUS_RESET: /* 05 */ - case MPI_EVENT_RESCAN: /* 06 */ - case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */ - case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */ - case MPI_EVENT_LOGOUT: /* 09 */ - case MPI_EVENT_INTEGRATED_RAID: /* 0B */ - case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE: /* 0C */ - default: - break; - case MPI_EVENT_EVENT_CHANGE: /* 0A */ - if (evDataLen) { - u8 evState = evData0 & 0xFF; - - /* CHECKME! What if evState unexpectedly says OFF (0)? */ - - /* Update EventState field in cached IocFacts */ - if (ioc->facts.Function) { - ioc->facts.EventState = evState; - } - } - break; - } - - /* - * Should this event be logged? Events are written sequentially. - * When buffer is full, start again at the top. - */ - if (ioc->events && (ioc->eventTypes & ( 1 << event))) { - int idx; - - idx = ioc->eventContext % ioc->eventLogSize; - - ioc->events[idx].event = event; - ioc->events[idx].eventContext = ioc->eventContext; - - for (ii = 0; ii < 2; ii++) { - if (ii < evDataLen) - ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]); - else - ioc->events[idx].data[ii] = 0; - } - - ioc->eventContext++; - } - - - /* - * Call each currently registered protocol event handler. - */ - for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { - if (MptEvHandlers[ii]) { - dprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n", - ioc->name, ii)); - r += (*(MptEvHandlers[ii]))(ioc, pEventReply); - handlers++; - } - } - /* FIXME? Examine results here? */ - - /* - * If needed, send (a single) EventAck. - */ - if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) { - if ((ii = SendEventAck(ioc, pEventReply)) != 0) { - printk(MYIOC_s_WARN_FMT "SendEventAck returned %d\n", - ioc->name, ii); - } - } - - *evHandlers = handlers; - return r; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_fc_log_info - Log information returned from Fibre Channel IOC. - * @ioc: Pointer to MPT_ADAPTER structure - * @log_info: U32 LogInfo reply word from the IOC - * - * Refer to lsi/fc_log.h. - */ -static void -mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info) -{ - static char *subcl_str[8] = { - "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer", - "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info" - }; - char *desc = "unknown"; - u8 subcl = (log_info >> 24) & 0x7; - u32 SubCl = log_info & 0x27000000; - - switch(log_info) { -/* FCP Initiator */ - case MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME: - desc = "Received an out of order frame - unsupported"; - break; - case MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME: - desc = "Bad start of frame primative"; - break; - case MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME: - desc = "Bad end of frame primative"; - break; - case MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN: - desc = "Receiver hardware detected overrun"; - break; - case MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER: - desc = "Other errors caught by IOC which require retries"; - break; - case MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD: - desc = "Main processor could not initialize sub-processor"; - break; -/* FC Target */ - case MPI_IOCLOGINFO_FC_TARGET_NO_PDISC: - desc = "Not sent because we are waiting for a PDISC from the initiator"; - break; - case MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN: - desc = "Not sent because we are not logged in to the remote node"; - break; - case MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP: - desc = "Data Out, Auto Response, not sent due to a LIP"; - break; - case MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP: - desc = "Data In, Auto Response, not sent due to a LIP"; - break; - case MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA: - desc = "Data In, Auto Response, missing data frames"; - break; - case MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP: - desc = "Data Out, No Response, not sent due to a LIP"; - break; - case MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP: - desc = "Auto-response after a write not sent due to a LIP"; - break; - case MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP: - desc = "Data In, No Response, not completed due to a LIP"; - break; - case MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA: - desc = "Data In, No Response, missing data frames"; - break; - case MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP: - desc = "Manual Response not sent due to a LIP"; - break; - case MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3: - desc = "Not sent because remote node does not support Class 3"; - break; - case MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID: - desc = "Not sent because login to remote node not validated"; - break; - case MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND: - desc = "Cleared from the outbound queue after a logout"; - break; - case MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN: - desc = "Cleared waiting for data after a logout"; - break; -/* LAN */ - case MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING: - desc = "Transaction Context Sgl Missing"; - break; - case MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE: - desc = "Transaction Context found before an EOB"; - break; - case MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET: - desc = "Transaction Context value has reserved bits set"; - break; - case MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG: - desc = "Invalid SGL Flags"; - break; -/* FC Link */ - case MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT: - desc = "Loop initialization timed out"; - break; - case MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED: - desc = "Another system controller already initialized the loop"; - break; - case MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED: - desc = "Not synchronized to signal or still negotiating (possible cable problem)"; - break; - case MPI_IOCLOGINFO_FC_LINK_CRC_ERROR: - desc = "CRC check detected error on received frame"; - break; - } - - printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}", - ioc->name, log_info, subcl_str[subcl]); - if (SubCl == MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET) - printk(", byte_offset=%d\n", log_info & MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET); - else if (SubCl == MPI_IOCLOGINFO_FC_STATE_CHANGE) - printk("\n"); /* StateChg in LogInfo & 0x00FFFFFF, above */ - else - printk("\n" KERN_INFO " %s\n", desc); -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_sp_log_info - Log information returned from SCSI Parallel IOC. - * @ioc: Pointer to MPT_ADAPTER structure - * @mr: Pointer to MPT reply frame - * @log_info: U32 LogInfo word from the IOC - * - * Refer to lsi/sp_log.h. - */ -static void -mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info) -{ - u32 info = log_info & 0x00FF0000; - char *desc = "unknown"; - - switch (info) { - case 0x00010000: - desc = "bug! MID not found"; - if (ioc->reload_fw == 0) - ioc->reload_fw++; - break; - - case 0x00020000: - desc = "Parity Error"; - break; - - case 0x00030000: - desc = "ASYNC Outbound Overrun"; - break; - - case 0x00040000: - desc = "SYNC Offset Error"; - break; - - case 0x00050000: - desc = "BM Change"; - break; - - case 0x00060000: - desc = "Msg In Overflow"; - break; - - case 0x00070000: - desc = "DMA Error"; - break; - - case 0x00080000: - desc = "Outbound DMA Overrun"; - break; - } - - printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc); -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_register_ascqops_strings - Register SCSI ASC/ASCQ and SCSI - * OpCode strings from the (optional) isense module. - * @ascqTable: Pointer to ASCQ_Table_t structure - * @ascqtbl_sz: Number of entries in ASCQ_Table - * @opsTable: Pointer to array of SCSI OpCode strings (char pointers) - * - * Specialized driver registration routine for the isense driver. - */ -int -mpt_register_ascqops_strings(void *ascqTable, int ascqtbl_sz, const char **opsTable) -{ - int r = 0; - - if (ascqTable && ascqtbl_sz && opsTable) { - mpt_v_ASCQ_TablePtr = ascqTable; - mpt_ASCQ_TableSz = ascqtbl_sz; - mpt_ScsiOpcodesPtr = opsTable; - printk(KERN_INFO MYNAM ": English readable SCSI-3 strings enabled:-)\n"); - isense_idx = last_drv_idx; - r = 1; - } - mpt_inc_use_count(); - return r; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_deregister_ascqops_strings - Deregister SCSI ASC/ASCQ and SCSI - * OpCode strings from the isense driver. - * - * Specialized driver deregistration routine for the isense driver. - */ -void -mpt_deregister_ascqops_strings(void) -{ - mpt_v_ASCQ_TablePtr = NULL; - mpt_ASCQ_TableSz = 0; - mpt_ScsiOpcodesPtr = NULL; - printk(KERN_INFO MYNAM ": English readable SCSI-3 strings disabled)-:\n"); - isense_idx = -1; - mpt_dec_use_count(); -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -EXPORT_SYMBOL(mpt_adapters); -EXPORT_SYMBOL(mpt_proc_root_dir); -EXPORT_SYMBOL(DmpService); -EXPORT_SYMBOL(mpt_register); -EXPORT_SYMBOL(mpt_deregister); -EXPORT_SYMBOL(mpt_event_register); -EXPORT_SYMBOL(mpt_event_deregister); -EXPORT_SYMBOL(mpt_reset_register); -EXPORT_SYMBOL(mpt_reset_deregister); -EXPORT_SYMBOL(mpt_get_msg_frame); -EXPORT_SYMBOL(mpt_put_msg_frame); -EXPORT_SYMBOL(mpt_free_msg_frame); -EXPORT_SYMBOL(mpt_add_sge); -EXPORT_SYMBOL(mpt_add_chain); -EXPORT_SYMBOL(mpt_send_handshake_request); -EXPORT_SYMBOL(mpt_handshake_req_reply_wait); -EXPORT_SYMBOL(mpt_adapter_find_first); -EXPORT_SYMBOL(mpt_adapter_find_next); -EXPORT_SYMBOL(mpt_verify_adapter); -EXPORT_SYMBOL(mpt_GetIocState); -EXPORT_SYMBOL(mpt_print_ioc_summary); -EXPORT_SYMBOL(mpt_lan_index); -EXPORT_SYMBOL(mpt_stm_index); -EXPORT_SYMBOL(mpt_HardResetHandler); -EXPORT_SYMBOL(mpt_config); -EXPORT_SYMBOL(mpt_read_ioc_pg_3); -EXPORT_SYMBOL(mpt_alloc_fw_memory); -EXPORT_SYMBOL(mpt_free_fw_memory); - -EXPORT_SYMBOL(mpt_register_ascqops_strings); -EXPORT_SYMBOL(mpt_deregister_ascqops_strings); -EXPORT_SYMBOL(mpt_v_ASCQ_TablePtr); -EXPORT_SYMBOL(mpt_ASCQ_TableSz); -EXPORT_SYMBOL(mpt_ScsiOpcodesPtr); - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * fusion_init - Fusion MPT base driver initialization routine. - * - * Returns 0 for success, non-zero for failure. - */ -int __init -fusion_init(void) -{ - int i; - - if (FusionInitCalled++) { - dprintk((KERN_INFO MYNAM ": INFO - Driver late-init entry point called\n")); - return 0; - } - - Q_INIT(&MptAdapters, MPT_ADAPTER); /* set to empty */ - for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) { - MptCallbacks[i] = NULL; - MptDriverClass[i] = MPTUNKNOWN_DRIVER; - MptEvHandlers[i] = NULL; - MptResetHandlers[i] = NULL; - } - - DmpService = NULL; - - /* NEW! 20010120 -sralston - * Register ourselves (mptbase) in order to facilitate - * EventNotification handling. - */ - mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER); - - /* Register for hard reset handling callbacks. - */ - if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) { - dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n")); - } else { - /* FIXME! */ - } - - if ((i = mpt_pci_scan()) < 0) - return i; - - show_mptmod_ver(my_NAME, my_VERSION); - printk(KERN_INFO COPYRIGHT "\n"); - - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * fusion_exit - Perform driver unload cleanup. - * - * This routine frees all resources associated with each MPT adapter - * and removes all %MPT_PROCFS_MPTBASEDIR entries. - */ -static void -fusion_exit(void) -{ - MPT_ADAPTER *this; - struct pci_dev *pdev = NULL; - - dprintk((KERN_INFO MYNAM ": fusion_exit() called!\n")); - - /* Whups? 20010120 -sralston - * Moved this *above* removal of all MptAdapters! - */ -#ifdef CONFIG_PROC_FS - (void) procmpt_destroy(); -#endif - - while (! Q_IS_EMPTY(&MptAdapters)) { - this = MptAdapters.head; - - /* Disable interrupts! */ - CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF); - - this->active = 0; - - pdev = (struct pci_dev *)this->pcidev; - mptscsih_sync_irq(pdev->irq); - - /* Clear any lingering interrupt */ - CHIPREG_WRITE32(&this->chip->IntStatus, 0); - - CHIPREG_READ32(&this->chip->IntStatus); - - Q_DEL_ITEM(this); - mpt_adapter_dispose(this); - } - - mpt_reset_deregister(mpt_base_index); -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -module_init(fusion_init); -module_exit(fusion_exit); diff --git a/xen/drivers/message/fusion/mptbase.h b/xen/drivers/message/fusion/mptbase.h deleted file mode 100644 index 1ca83d3278..0000000000 --- a/xen/drivers/message/fusion/mptbase.h +++ /dev/null @@ -1,1123 +0,0 @@ -/* - * linux/drivers/message/fusion/mptbase.h - * High performance SCSI + LAN / Fibre Channel device drivers. - * For use with PCI chip/adapter(s): - * LSIFC9xx/LSI409xx Fibre Channel - * running LSI Logic Fusion MPT (Message Passing Technology) firmware. - * - * Credits: - * (see mptbase.c) - * - * Copyright (c) 1999-2002 LSI Logic Corporation - * Originally By: Steven J. Ralston - * (mailto:sjralston1@netscape.net) - * (mailto:lstephens@lsil.com) - * - * $Id: mptbase.h,v 1.149 2003/05/07 14:08:31 pdelaney Exp $ - */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - NO WARRANTY - THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - solely responsible for determining the appropriateness of using and - distributing the Program and assumes all risks associated with its - exercise of rights under this Agreement, including but not limited to - the risks and costs of program errors, damage to or loss of data, - programs or equipment, and unavailability or interruption of operations. - - DISCLAIMER OF LIABILITY - NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef MPTBASE_H_INCLUDED -#define MPTBASE_H_INCLUDED -/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#include - -#include "linux_compat.h" /* linux-2.2.x (vs. -2.4.x) tweaks */ -#include "scsi3.h" /* SCSI defines */ - -#include "lsi/mpi_type.h" -#include "lsi/mpi.h" /* Fusion MPI(nterface) basic defs */ -#include "lsi/mpi_ioc.h" /* Fusion MPT IOC(ontroller) defs */ -#include "lsi/mpi_cnfg.h" /* IOC configuration support */ -#include "lsi/mpi_init.h" /* SCSI Host (initiator) protocol support */ -#include "lsi/mpi_lan.h" /* LAN over FC protocol support */ -#include "lsi/mpi_raid.h" /* Integrated Mirroring support */ - -#include "lsi/mpi_fc.h" /* Fibre Channel (lowlevel) support */ -#include "lsi/mpi_targ.h" /* SCSI/FCP Target protcol support */ -#include "lsi/fc_log.h" - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#ifndef MODULEAUTHOR -#define MODULEAUTHOR "LSI Logic Corporation" -#endif - -#ifndef COPYRIGHT -#define COPYRIGHT "Copyright (c) 1999-2002 " MODULEAUTHOR -#endif - -#define MPT_LINUX_VERSION_COMMON "2.05.05+" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-2.05.05+" -#define WHAT_MAGIC_STRING "@" "(" "#" ")" - -#define show_mptmod_ver(s,ver) \ - printk(KERN_INFO "%s %s\n", s, ver); - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Fusion MPT(linux) driver configurable stuff... - */ -#define MPT_MAX_ADAPTERS 18 -#define MPT_MAX_PROTOCOL_DRIVERS 16 -#define MPT_MAX_BUS 1 /* Do not change */ -#define MPT_MAX_FC_DEVICES 255 -#define MPT_MAX_SCSI_DEVICES 16 -#define MPT_LAST_LUN 31 -#define MPT_SENSE_BUFFER_ALLOC 64 - /* allow for 256 max sense alloc, but only 255 max request */ -#if MPT_SENSE_BUFFER_ALLOC >= 256 -# undef MPT_SENSE_BUFFER_ALLOC -# define MPT_SENSE_BUFFER_ALLOC 256 -# define MPT_SENSE_BUFFER_SIZE 255 -#else -# define MPT_SENSE_BUFFER_SIZE MPT_SENSE_BUFFER_ALLOC -#endif - -#define MPT_NAME_LENGTH 32 - -#define MPT_PROCFS_MPTBASEDIR "mpt" - /* chg it to "driver/fusion" ? */ -#define MPT_PROCFS_SUMMARY_ALL_NODE MPT_PROCFS_MPTBASEDIR "/summary" -#define MPT_PROCFS_SUMMARY_ALL_PATHNAME "/proc/" MPT_PROCFS_SUMMARY_ALL_NODE -#define MPT_FW_REV_MAGIC_ID_STRING "FwRev=" - -#define MPT_MAX_REQ_DEPTH 1023 -#define MPT_DEFAULT_REQ_DEPTH 256 -#define MPT_MIN_REQ_DEPTH 128 - -#define MPT_MAX_REPLY_DEPTH MPT_MAX_REQ_DEPTH -#define MPT_DEFAULT_REPLY_DEPTH 128 -#define MPT_MIN_REPLY_DEPTH 8 -#define MPT_MAX_REPLIES_PER_ISR 32 - -#define MPT_MAX_FRAME_SIZE 128 -#define MPT_DEFAULT_FRAME_SIZE 128 - -#define MPT_SG_REQ_128_SCALE 1 -#define MPT_SG_REQ_96_SCALE 2 -#define MPT_SG_REQ_64_SCALE 4 - -#define CAN_SLEEP 1 -#define NO_SLEEP 0 - -#define MPT_COALESCING_TIMEOUT 0x10 - -/* - * SCSI transfer rate defines. - */ -#define MPT_ULTRA320 0x08 -#define MPT_ULTRA160 0x09 -#define MPT_ULTRA2 0x0A -#define MPT_ULTRA 0x0C -#define MPT_FAST 0x19 -#define MPT_SCSI 0x32 -#define MPT_ASYNC 0xFF - -#define MPT_NARROW 0 -#define MPT_WIDE 1 - -#ifdef __KERNEL__ /* { */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -/* SAE: Xen doesn't have a proc filesystem */ -#if defined(CONFIG_PROC_FS) -#include -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Attempt semi-consistent error & warning msgs across - * MPT drivers. NOTE: Users of these macro defs must - * themselves define their own MYNAM. - */ -#define MYIOC_s_INFO_FMT KERN_INFO MYNAM ": %s: " -#define MYIOC_s_NOTE_FMT KERN_NOTICE MYNAM ": %s: " -#define MYIOC_s_WARN_FMT KERN_WARNING MYNAM ": %s: WARNING - " -#define MYIOC_s_ERR_FMT KERN_ERR MYNAM ": %s: ERROR - " - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * MPT protocol driver defs... - */ -typedef enum { - MPTBASE_DRIVER, /* MPT base class */ - MPTCTL_DRIVER, /* MPT ioctl class */ - MPTSCSIH_DRIVER, /* MPT SCSI host (initiator) class */ - MPTLAN_DRIVER, /* MPT LAN class */ - MPTSTM_DRIVER, /* MPT SCSI target mode class */ - MPTDMP_DRIVER, /* MPT Dynamic Multi-pathing class */ - MPTUNKNOWN_DRIVER -} MPT_DRIVER_CLASS; - -/* - * MPT adapter / port / bus / device info structures... - */ - -typedef union _MPT_FRAME_TRACKER { - struct { - struct _MPT_FRAME_HDR *forw; - struct _MPT_FRAME_HDR *back; - u32 arg1; - u32 pad; - void *argp1; -#ifndef MPT_SCSI_USE_NEW_EH - void *argp2; -#endif - } linkage; - /* - * NOTE: When request frames are free, on the linkage structure - * contets are valid. All other values are invalid. - * In particular, do NOT reply on offset [2] - * (in words) being the * message context. - * The message context must be reset (computed via base address - * + an offset) prior to issuing any command. - * - * NOTE2: On non-32-bit systems, where pointers are LARGE, - * using the linkage pointers destroys our sacred MsgContext - * field contents. But we don't care anymore because these - * are now reset in mpt_put_msg_frame() just prior to sending - * a request off to the IOC. - */ - struct { - u32 __hdr[2]; - /* - * The following _MUST_ match the location of the - * MsgContext field in the MPT message headers. - */ - union { - u32 MsgContext; - struct { - u16 req_idx; /* Request index */ - u8 cb_idx; /* callback function index */ - u8 rsvd; - } fld; - } msgctxu; - } hwhdr; - /* - * Remark: 32 bit identifier: - * 31-24: reserved - * 23-16: call back index - * 15-0 : request index - */ -} MPT_FRAME_TRACKER; - -/* - * We might want to view/access a frame as: - * 1) generic request header - * 2) SCSIIORequest - * 3) SCSIIOReply - * 4) MPIDefaultReply - * 5) frame tracker - */ -typedef struct _MPT_FRAME_HDR { - union { - MPIHeader_t hdr; - SCSIIORequest_t scsireq; - SCSIIOReply_t sreply; - MPIDefaultReply_t reply; - MPT_FRAME_TRACKER frame; - } u; -} MPT_FRAME_HDR; - -#define MPT_REQ_MSGFLAGS_DROPME 0x80 - -/* Used for tracking the free request frames - * and free reply frames. - */ -typedef struct _MPT_Q_TRACKER { - MPT_FRAME_HDR *head; - MPT_FRAME_HDR *tail; -} MPT_Q_TRACKER; - - -typedef struct _MPT_SGL_HDR { - SGESimple32_t sge[1]; -} MPT_SGL_HDR; - -typedef struct _MPT_SGL64_HDR { - SGESimple64_t sge[1]; -} MPT_SGL64_HDR; - - -typedef struct _Q_ITEM { - struct _Q_ITEM *forw; - struct _Q_ITEM *back; -} Q_ITEM; - -typedef struct _Q_TRACKER { - struct _Q_ITEM *head; - struct _Q_ITEM *tail; -} Q_TRACKER; - -typedef struct _MPT_DONE_Q { - struct _MPT_DONE_Q *forw; - struct _MPT_DONE_Q *back; - void *argp; -} MPT_DONE_Q; - -typedef struct _DONE_Q_TRACKER { - MPT_DONE_Q *head; - MPT_DONE_Q *tail; -} DONE_Q_TRACKER; - -/* - * Chip-specific stuff... FC929 delineates break between - * FC and Parallel SCSI parts. Do NOT re-order. - */ - -typedef enum { - FC919X = 0x0819, - FC929X = 0x0829, - FC909 = 0x0909, - FC919 = 0x0919, - FC929 = 0x0929, - C1030 = 0x1030, - C1035 = 0x1035, - FCUNK = 0xFBAD -} CHIP_TYPE; - -/* - * System interface register set - */ - -typedef struct _SYSIF_REGS -{ - u32 Doorbell; /* 00 System<->IOC Doorbell reg */ - u32 WriteSequence; /* 04 Write Sequence register */ - u32 Diagnostic; /* 08 Diagnostic register */ - u32 TestBase; /* 0C Test Base Address */ - u32 DiagRwData; /* 10 Read Write Data (fw download) */ - u32 DiagRwAddress; /* 14 Read Write Address (fw download)*/ - u32 Reserved1[6]; /* 18-2F reserved for future use */ - u32 IntStatus; /* 30 Interrupt Status */ - u32 IntMask; /* 34 Interrupt Mask */ - u32 Reserved2[2]; /* 38-3F reserved for future use */ - u32 RequestFifo; /* 40 Request Post/Free FIFO */ - u32 ReplyFifo; /* 44 Reply Post/Free FIFO */ - u32 Reserved3[2]; /* 48-4F reserved for future use */ - u32 HostIndex; /* 50 Host Index register */ - u32 Reserved4[15]; /* 54-8F */ - u32 Fubar; /* 90 For Fubar usage */ - u32 Reserved5[27]; /* 94-FF */ -} SYSIF_REGS; - -/* - * NOTE: Use MPI_{DOORBELL,WRITESEQ,DIAG}_xxx defs in lsi/mpi.h - * in conjunction with SYSIF_REGS accesses! - */ - - -/* - * Dynamic Multi-Pathing specific stuff... - */ -#define DMP_MAX_PATHS 8 - -typedef struct _PathInfo { - u8 ioc; - u8 target; - u8 pad; - u8 pflags; -} PathInfo; - -#define PATHINFO_FLAGS_OWNED 0x01 -#define PATHINFO_FLAGS_EXISTS 0x02 -#define PATHINFO_FLAGS_AVAILABLE 0x04 -#define PATHINFO_FLAGS_SECONDARY 0x08 - -#define PFLAGS_EXISTS_AND_AVAIL (PATHINFO_FLAGS_EXISTS|PATHINFO_FLAGS_AVAILABLE) -#define PFLAGS_AVAIL_AND_OWNED (PATHINFO_FLAGS_AVAILABLE|PATHINFO_FLAGS_OWNED) - -typedef struct _ScsiCmndTracker { - void *head; - void *tail; -} ScsiCmndTracker; - - -/* - * VirtDevice - FC LUN device or SCSI target device - * (used to be FCSCSI_TARGET) - */ -typedef struct _VirtDevice { - struct _VirtDevice *forw; - struct _VirtDevice *back; - struct scsi_device *device; - rwlock_t VdevLock; - int ref_cnt; - u8 tflags; - u8 ioc_id; - u8 target_id; - u8 bus_id; - u8 minSyncFactor; /* 0xFF is async */ - u8 maxOffset; /* 0 if async */ - u8 maxWidth; /* 0 if narrow, 1 if wide*/ - u8 negoFlags; /* bit field, 0 if WDTR/SDTR/QAS allowed */ - u8 raidVolume; /* set, if RAID Volume */ - u8 type; /* byte 0 of Inquiry data */ - u8 cflags; /* controller flags */ - u8 rsvd1raid; - int npaths; - u16 fc_phys_lun; - u16 fc_xlat_lun; - int stall_detected; - PathInfo path[DMP_MAX_PATHS]; - struct timer_list stall_timer; - struct timer_list retry_timer; - struct timer_list gone_timer; - ScsiCmndTracker WaitQ; - ScsiCmndTracker SentQ; - ScsiCmndTracker DoneQ; - u32 num_luns; -//--- LUN split here? - u32 luns; /* Max LUNs is 32 */ - u8 inq_data[SCSI_STD_INQUIRY_BYTES]; /* 36 */ - u8 pad0[4]; - u8 inq00_data[20]; - u8 pad1[4]; - /* IEEE Registered Extended Identifier - obtained via INQUIRY VPD page 0x83 */ - /* NOTE: Do not separate uniq_prepad and uniq_data - as they are treateed as a single entity in the code */ - u8 uniq_prepad[8]; - u8 uniq_data[20]; - u8 pad2[4]; - u8 inqC3_data[12]; - u8 pad3[4]; - u8 inqC9_data[12]; - u8 pad4[4]; - u8 dev_vol_name[64]; -} VirtDevice; - -/* - * Fibre Channel (SCSI) target device and associated defines... - */ -#define MPT_TARGET_DEFAULT_DV_STATUS 0 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,55) -#define MPT_TARGET_FLAGS_CONFIGURED 0x02 -#define MPT_TARGET_FLAGS_Q_YES 0x08 -#else -#define MPT_TARGET_FLAGS_VALID_NEGO 0x01 -#define MPT_TARGET_FLAGS_VALID_INQUIRY 0x02 -#define MPT_TARGET_FLAGS_Q_YES 0x08 -#define MPT_TARGET_FLAGS_VALID_56 0x10 -#endif - -#define MPT_TARGET_NO_NEGO_WIDE 0x01 -#define MPT_TARGET_NO_NEGO_SYNC 0x02 -#define MPT_TARGET_NO_NEGO_QAS 0x04 - -typedef struct _VirtDevTracker { - struct _VirtDevice *head; - struct _VirtDevice *tail; - rwlock_t VlistLock; - int pad; -} VirtDevTracker; - -/* SAE: Xen doesn't have proc */ -#if defined(CONFIG_PROC_FS) - -/* - * /proc/mpt interface - */ -typedef struct { - const char *name; - mode_t mode; - int pad; - read_proc_t *read_proc; - write_proc_t *write_proc; -} mpt_proc_entry_t; - -#define MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len) \ -do { \ - len -= offset; \ - if (len < request) { \ - *eof = 1; \ - if (len <= 0) \ - return 0; \ - } else \ - len = request; \ - *start = buf + offset; \ - return len; \ -} while (0) - -#endif - -/* - * IOCTL structure and associated defines - */ - -#define MPT_IOCTL_STATUS_DID_IOCRESET 0x01 /* IOC Reset occurred on the current*/ -#define MPT_IOCTL_STATUS_RF_VALID 0x02 /* The Reply Frame is VALID */ -#define MPT_IOCTL_STATUS_TIMER_ACTIVE 0x04 /* The timer is running */ -#define MPT_IOCTL_STATUS_SENSE_VALID 0x08 /* Sense data is valid */ -#define MPT_IOCTL_STATUS_COMMAND_GOOD 0x10 /* Command Status GOOD */ -#define MPT_IOCTL_STATUS_TMTIMER_ACTIVE 0x20 /* The TM timer is running */ -#define MPT_IOCTL_STATUS_TM_FAILED 0x40 /* User TM request failed */ - -#define MPTCTL_RESET_OK 0x01 /* Issue Bus Reset */ - -typedef struct _MPT_IOCTL { - struct _MPT_ADAPTER *ioc; - struct timer_list timer; /* timer function for this adapter */ - u8 ReplyFrame[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */ - u8 sense[MPT_SENSE_BUFFER_ALLOC]; - int wait_done; /* wake-up value for this ioc */ - u8 rsvd; - u8 status; /* current command status */ - u8 reset; /* 1 if bus reset allowed */ - u8 target; /* target for reset */ - void *tmPtr; - struct timer_list TMtimer; /* timer function for this adapter */ -} MPT_IOCTL; - -/* - * Event Structure and define - */ -#define MPTCTL_EVENT_LOG_SIZE (0x0000000A) -typedef struct _mpt_ioctl_events { - u32 event; /* Specified by define above */ - u32 eventContext; /* Index or counter */ - int data[2]; /* First 8 bytes of Event Data */ -} MPT_IOCTL_EVENTS; - -/* - * CONFIGPARM status defines - */ -#define MPT_CONFIG_GOOD MPI_IOCSTATUS_SUCCESS -#define MPT_CONFIG_ERROR 0x002F - -/* - * Substructure to store SCSI specific configuration page data - */ - /* dvStatus defines: */ -#define MPT_SCSICFG_NEGOTIATE 0x01 /* Negotiate on next IO */ -#define MPT_SCSICFG_NEED_DV 0x02 /* Schedule DV */ -#define MPT_SCSICFG_DV_PENDING 0x04 /* DV on this physical id pending */ -#define MPT_SCSICFG_DV_NOT_DONE 0x08 /* DV has not been performed */ -#define MPT_SCSICFG_BLK_NEGO 0x10 /* WriteSDP1 with WDTR and SDTR disabled */ -#define MPT_SCSICFG_RELOAD_IOC_PG3 0x20 /* IOC Pg 3 data is obsolete */ - /* Args passed to writeSDP1: */ -#define MPT_SCSICFG_USE_NVRAM 0x01 /* WriteSDP1 using NVRAM */ -#define MPT_SCSICFG_ALL_IDS 0x02 /* WriteSDP1 to all IDS */ -/* #define MPT_SCSICFG_BLK_NEGO 0x10 WriteSDP1 with WDTR and SDTR disabled */ - -typedef struct _ScsiCfgData { - int *nvram; /* table of device NVRAM values */ - IOCPage3_t *pIocPg3; /* table of physical disks */ - u8 dvStatus[MPT_MAX_SCSI_DEVICES]; - int isRaid; /* bit field, 1 if RAID */ - u8 minSyncFactor; /* 0xFF if async */ - u8 maxSyncOffset; /* 0 if async */ - u8 maxBusWidth; /* 0 if narrow, 1 if wide */ - u8 busType; /* SE, LVD, HD */ - u8 sdp1version; /* SDP1 version */ - u8 sdp1length; /* SDP1 length */ - u8 sdp0version; /* SDP0 version */ - u8 sdp0length; /* SDP0 length */ - u8 dvScheduled; /* 1 if scheduled */ - u8 forceDv; /* 1 to force DV scheduling */ - u8 noQas; /* Disable QAS for this adapter */ - u8 rsvd[2]; -} ScsiCfgData; - -typedef struct _fw_image { - char *fw; - dma_addr_t fw_dma; - u32 size; - u32 rsvd; -} fw_image_t; - -/* - * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS - */ -typedef struct _MPT_ADAPTER -{ - struct _MPT_ADAPTER *forw; - struct _MPT_ADAPTER *back; - int id; /* Unique adapter id N {0,1,2,...} */ - int pci_irq; /* This irq */ - char name[MPT_NAME_LENGTH]; /* "iocN" */ - char *prod_name; /* "LSIFC9x9" */ - volatile SYSIF_REGS *chip; /* == c8817000 (mmap) */ - volatile SYSIF_REGS *pio_chip; /* Programmed IO (downloadboot) */ - u32 mem_phys; /* == f4020000 (mmap) */ - u32 pio_mem_phys; /* Programmed IO (downloadboot) */ - int mem_size; /* mmap memory size */ - int alloc_total; - u32 last_state; - int active; - u8 *reply_alloc; /* Reply frames alloc ptr */ - dma_addr_t reply_alloc_dma; - MPT_FRAME_HDR *reply_frames; /* Reply msg frames - rounded up! */ - dma_addr_t reply_frames_dma; - u32 reply_frames_low_dma; - int reply_depth; /* Num Allocated reply frames */ - int reply_sz; /* Reply frame size */ - CHIP_TYPE chip_type; - /* We (host driver) get to manage our own RequestQueue! */ - u8 *req_alloc; /* Request frames alloc ptr */ - dma_addr_t req_alloc_dma; - MPT_FRAME_HDR *req_frames; /* Request msg frames - rounded up! */ - dma_addr_t req_frames_dma; - u32 req_frames_low_dma; - int req_depth; /* Number of request frames */ - int req_sz; /* Request frame size (bytes) */ - spinlock_t FreeQlock; - MPT_Q_TRACKER FreeQ; - /* Pool of SCSI sense buffers for commands coming from - * the SCSI mid-layer. We have one 256 byte sense buffer - * for each REQ entry. - */ - u8 *sense_buf_pool; - dma_addr_t sense_buf_pool_dma; - u32 sense_buf_low_dma; - int mtrr_reg; - struct pci_dev *pcidev; /* struct pci_dev pointer */ - u8 *memmap; /* mmap address */ - struct Scsi_Host *sh; /* Scsi Host pointer */ - ScsiCfgData spi_data; /* Scsi config. data */ - MPT_IOCTL *ioctl; /* ioctl data pointer */ - struct proc_dir_entry *ioc_dentry; - struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */ - spinlock_t diagLock; /* diagnostic reset lock */ - int diagPending; - u32 biosVersion; /* BIOS version from IO Unit Page 2 */ - int eventTypes; /* Event logging parameters */ - int eventContext; /* Next event context */ - int eventLogSize; /* Max number of cached events */ -#ifdef MPTSCSIH_DBG_TIMEOUT - int timeout_hard; - int timeout_delta; - int timeout_cnt; - int timeout_maxcnt; -#endif - struct _mpt_ioctl_events *events; /* pointer to event log */ - fw_image_t **cached_fw; /* Pointer to FW SG List */ - Q_TRACKER configQ; /* linked list of config. requests */ - int num_fw_frags; /* Number of SGE in FW SG List */ - int hs_reply_idx; -#ifndef MFCNT - u32 pad0; -#else - u32 mfcnt; -#endif - u32 hs_req[MPT_MAX_FRAME_SIZE/sizeof(u32)]; - u16 hs_reply[MPT_MAX_FRAME_SIZE/sizeof(u16)]; - IOCFactsReply_t facts; - PortFactsReply_t pfacts[2]; - FCPortPage0_t fc_port_page0[2]; - LANPage0_t lan_cnfg_page0; - LANPage1_t lan_cnfg_page1; - u8 FirstWhoInit; - u8 upload_fw; /* If set, do a fw upload */ - u8 reload_fw; /* Force a FW Reload on next reset */ - u8 pad1[5]; -} MPT_ADAPTER; - - -typedef struct _MPT_ADAPTER_TRACKER { - MPT_ADAPTER *head; - MPT_ADAPTER *tail; -} MPT_ADAPTER_TRACKER; - -/* - * New return value convention: - * 1 = Ok to free associated request frame - * 0 = not Ok ... - */ -typedef int (*MPT_CALLBACK)(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply); -typedef int (*MPT_EVHANDLER)(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply); -typedef int (*MPT_RESETHANDLER)(MPT_ADAPTER *ioc, int reset_phase); -/* reset_phase defs */ -#define MPT_IOC_PRE_RESET 0 -#define MPT_IOC_POST_RESET 1 -#define MPT_IOC_SETUP_RESET 2 - -/* - * Invent MPT host event (super-set of MPI Events) - * Fitted to 1030's 64-byte [max] request frame size - */ -typedef struct _MPT_HOST_EVENT { - EventNotificationReply_t MpiEvent; /* 8 32-bit words! */ - u32 pad[6]; - void *next; -} MPT_HOST_EVENT; - -#define MPT_HOSTEVENT_IOC_BRINGUP 0x91 -#define MPT_HOSTEVENT_IOC_RECOVER 0x92 - -/* Define the generic types based on the size - * of the dma_addr_t type. - */ -typedef struct _mpt_sge { - u32 FlagsLength; - dma_addr_t Address; -} MptSge_t; - -#define mpt_addr_size() \ - ((sizeof(dma_addr_t) == sizeof(u64)) ? MPI_SGE_FLAGS_64_BIT_ADDRESSING : \ - MPI_SGE_FLAGS_32_BIT_ADDRESSING) - -#define mpt_msg_flags() \ - ((sizeof(dma_addr_t) == sizeof(u64)) ? MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 : \ - MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32) - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Funky (private) macros... - */ -#ifdef MPT_DEBUG -#define dprintk(x) printk x -#else -#define dprintk(x) -#endif - -#ifdef MPT_DEBUG_HANDSHAKE -#define dhsprintk(x) printk x -#else -#define dhsprintk(x) -#endif - -//#if defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME) -#ifdef MPT_DEBUG_MSG_FRAME -#define dmfprintk(x) printk x -#else -#define dmfprintk(x) -#endif - -#ifdef MPT_DEBUG_IRQ -#define dirqprintk(x) printk x -#else -#define dirqprintk(x) -#endif - -#ifdef MPT_DEBUG_SG -#define dsgprintk(x) printk x -#else -#define dsgprintk(x) -#endif - -#if defined(MPT_DEBUG_DL) -//#if defined(MPT_DEBUG_DL) || defined(MPT_DEBUG) -#define ddlprintk(x) printk x -#else -#define ddlprintk(x) -#endif - - -#ifdef MPT_DEBUG_DV -#define ddvprintk(x) printk x -#else -#define ddvprintk(x) -#endif - -#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) -#define ddvtprintk(x) printk x -#else -#define ddvtprintk(x) -#endif - -#ifdef MPT_DEBUG_IOCTL -#define dctlprintk(x) printk x -#else -#define dctlprintk(x) -#endif - -#ifdef MPT_DEBUG_RESET -#define dtmprintk(x) printk x -#else -#define dtmprintk(x) -#endif - -#ifdef MPT_DEBUG_NEH -#define nehprintk(x) printk x -#else -#define nehprintk(x) -#endif - -#if defined(MPT_DEBUG_CONFIG) -//#if defined(MPT_DEBUG_CONFIG) || defined(MPT_DEBUG) -#define dcprintk(x) printk x -#else -#define dcprintk(x) -#endif - -#if defined(MPT_DEBUG_SCSI) || defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME) -#define dsprintk(x) printk x -#else -#define dsprintk(x) -#endif - - -#define MPT_INDEX_2_MFPTR(ioc,idx) \ - (MPT_FRAME_HDR*)( (u8*)(ioc)->req_frames + (ioc)->req_sz * (idx) ) - -#define MFPTR_2_MPT_INDEX(ioc,mf) \ - (int)( ((u8*)mf - (u8*)(ioc)->req_frames) / (ioc)->req_sz ) - -#define MPT_INDEX_2_RFPTR(ioc,idx) \ - (MPT_FRAME_HDR*)( (u8*)(ioc)->reply_frames + (ioc)->req_sz * (idx) ) - -#define Q_INIT(q,type) (q)->head = (q)->tail = (type*)(q) -#define Q_IS_EMPTY(q) ((Q_ITEM*)(q)->head == (Q_ITEM*)(q)) - -#define Q_ADD_TAIL(qt,i,type) { \ - Q_TRACKER *_qt = (Q_TRACKER*)(qt); \ - Q_ITEM *oldTail = _qt->tail; \ - (i)->forw = (type*)_qt; \ - (i)->back = (type*)oldTail; \ - oldTail->forw = (Q_ITEM*)(i); \ - _qt->tail = (Q_ITEM*)(i); \ -} - -#define Q_ADD_HEAD(qt,i,type) { \ - Q_TRACKER *_qt = (Q_TRACKER*)(qt); \ - Q_ITEM *oldHead = _qt->head; \ - (i)->forw = (type*)oldHead; \ - (i)->back = (type*)_qt; \ - oldHead->back = (Q_ITEM*)(i); \ - _qt->head = (Q_ITEM*)(i); \ -} - -#define Q_DEL_ITEM(i) { \ - Q_ITEM *_forw = (Q_ITEM*)(i)->forw; \ - Q_ITEM *_back = (Q_ITEM*)(i)->back; \ - _back->forw = _forw; \ - _forw->back = _back; \ -} - -#define SWAB4(value) \ - (u32)( (((value) & 0x000000ff) << 24) \ - | (((value) & 0x0000ff00) << 8) \ - | (((value) & 0x00ff0000) >> 8) \ - | (((value) & 0xff000000) >> 24) ) - - -#if defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME) -#define DBG_DUMP_REPLY_FRAME(mfp) \ - { u32 *m = (u32 *)(mfp); \ - int i, n = (le32_to_cpu(m[0]) & 0x00FF0000) >> 16; \ - printk(KERN_INFO " "); \ - for (i=0; iSCp area - * NOTE: SCp area is 36 bytes min, 44 bytes max? - */ -typedef struct _scPrivate { - struct scsi_cmnd *forw; - struct scsi_cmnd *back; - void *p1; - void *p2; - u8 io_path_id; /* DMP */ - u8 pad[7]; -} scPrivate; - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * More Dynamic Multi-Pathing stuff... - */ - -/* Forward decl, a strange C thing, to prevent gcc compiler warnings */ -struct scsi_cmnd; - -/* - * DMP service layer structure / API interface - */ -typedef struct _DmpServices { - VirtDevTracker VdevList; - struct semaphore *Daemon; - int (*ScsiPathSelect) - (struct scsi_cmnd *, MPT_SCSI_HOST **hd, int *target, int *lun); - int (*DmpIoDoneChk) - (MPT_SCSI_HOST *, struct scsi_cmnd *, - SCSIIORequest_t *, - SCSIIOReply_t *); - void (*mptscsih_scanVlist) - (MPT_SCSI_HOST *, int portnum); - int (*ScsiAbort) - (struct scsi_cmnd *); - int (*ScsiBusReset) - (struct scsi_cmnd *); -} DmpServices_t; - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Generic structure passed to the base mpt_config function. - */ -typedef struct _x_config_parms { - Q_ITEM linkage; /* linked list */ - struct timer_list timer; /* timer function for this request */ - ConfigPageHeader_t *hdr; - dma_addr_t physAddr; - int wait_done; /* wait for this request */ - u32 pageAddr; /* properly formatted */ - u8 action; - u8 dir; - u8 timeout; /* seconds */ - u8 pad1; - u16 status; - u16 pad2; -} CONFIGPARMS; - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Public entry points... - */ -extern int mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass); -extern void mpt_deregister(int cb_idx); -extern int mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc); -extern void mpt_event_deregister(int cb_idx); -extern int mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func); -extern void mpt_reset_deregister(int cb_idx); -extern int mpt_register_ascqops_strings(void *ascqTable, int ascqtbl_sz, const char **opsTable); -extern void mpt_deregister_ascqops_strings(void); -extern MPT_FRAME_HDR *mpt_get_msg_frame(int handle, int iocid); -extern void mpt_free_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf); -extern void mpt_put_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf); -extern void mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr); -extern void mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr); - -extern int mpt_send_handshake_request(int handle, int iocid, int reqBytes, u32 *req, int sleepFlag); -extern int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait, int sleepFlag); -extern int mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp); -extern MPT_ADAPTER *mpt_adapter_find_first(void); -extern MPT_ADAPTER *mpt_adapter_find_next(MPT_ADAPTER *prev); -extern u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked); -extern void mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan); -extern int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag); -extern int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg); -extern void *mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size, int *frags, int *alloc_sz); -extern void mpt_free_fw_memory(MPT_ADAPTER *ioc, fw_image_t **alt_img); -extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); - -/* - * Public data decl's... - */ -extern MPT_ADAPTER *mpt_adapters[MPT_MAX_ADAPTERS]; -extern struct proc_dir_entry *mpt_proc_root_dir; -extern DmpServices_t *DmpService; - -extern int mpt_lan_index; /* needed by mptlan.c */ -extern int mpt_stm_index; /* needed by mptstm.c */ - -extern void *mpt_v_ASCQ_TablePtr; -extern const char **mpt_ScsiOpcodesPtr; -extern int mpt_ASCQ_TableSz; - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#endif /* } __KERNEL__ */ - -/* - * More (public) macros... - */ -#ifndef MIN -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif -#ifndef MAX -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#endif - -#ifndef offsetof -#define offsetof(t, m) ((size_t) (&((t *)0)->m)) -#endif - -#if defined(__alpha__) || defined(__sparc_v9__) || defined(__ia64__) || defined(__x86_64__) -#define CAST_U32_TO_PTR(x) ((void *)(u64)x) -#define CAST_PTR_TO_U32(x) ((u32)(u64)x) -#else -#define CAST_U32_TO_PTR(x) ((void *)x) -#define CAST_PTR_TO_U32(x) ((u32)x) -#endif - -#define MPT_PROTOCOL_FLAGS_c_c_c_c(pflags) \ - ((pflags) & MPI_PORTFACTS_PROTOCOL_INITIATOR) ? 'I' : 'i', \ - ((pflags) & MPI_PORTFACTS_PROTOCOL_TARGET) ? 'T' : 't', \ - ((pflags) & MPI_PORTFACTS_PROTOCOL_LAN) ? 'L' : 'l', \ - ((pflags) & MPI_PORTFACTS_PROTOCOL_LOGBUSADDR) ? 'B' : 'b' - -/* - * Shifted SGE Defines - Use in SGE with FlagsLength member. - * Otherwise, use MPI_xxx defines (refer to "lsi/mpi.h" header). - * Defaults: 32 bit SGE, SYSTEM_ADDRESS if direction bit is 0, read - */ -#define MPT_TRANSFER_IOC_TO_HOST (0x00000000) -#define MPT_TRANSFER_HOST_TO_IOC (0x04000000) -#define MPT_SGE_FLAGS_LAST_ELEMENT (0x80000000) -#define MPT_SGE_FLAGS_END_OF_BUFFER (0x40000000) -#define MPT_SGE_FLAGS_LOCAL_ADDRESS (0x08000000) -#define MPT_SGE_FLAGS_DIRECTION (0x04000000) -#define MPT_SGE_FLAGS_ADDRESSING (mpt_addr_size() << MPI_SGE_FLAGS_SHIFT) -#define MPT_SGE_FLAGS_END_OF_LIST (0x01000000) - -#define MPT_SGE_FLAGS_TRANSACTION_ELEMENT (0x00000000) -#define MPT_SGE_FLAGS_SIMPLE_ELEMENT (0x10000000) -#define MPT_SGE_FLAGS_CHAIN_ELEMENT (0x30000000) -#define MPT_SGE_FLAGS_ELEMENT_MASK (0x30000000) - -#define MPT_SGE_FLAGS_SSIMPLE_READ \ - (MPT_SGE_FLAGS_LAST_ELEMENT | \ - MPT_SGE_FLAGS_END_OF_BUFFER | \ - MPT_SGE_FLAGS_END_OF_LIST | \ - MPT_SGE_FLAGS_SIMPLE_ELEMENT | \ - MPT_SGE_FLAGS_ADDRESSING | \ - MPT_TRANSFER_IOC_TO_HOST) -#define MPT_SGE_FLAGS_SSIMPLE_WRITE \ - (MPT_SGE_FLAGS_LAST_ELEMENT | \ - MPT_SGE_FLAGS_END_OF_BUFFER | \ - MPT_SGE_FLAGS_END_OF_LIST | \ - MPT_SGE_FLAGS_SIMPLE_ELEMENT | \ - MPT_SGE_FLAGS_ADDRESSING | \ - MPT_TRANSFER_HOST_TO_IOC) - -/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#endif - diff --git a/xen/drivers/message/fusion/mptscsih.c b/xen/drivers/message/fusion/mptscsih.c deleted file mode 100644 index 49b0271efe..0000000000 --- a/xen/drivers/message/fusion/mptscsih.c +++ /dev/null @@ -1,7957 +0,0 @@ -/* - * linux/drivers/message/fusion/mptscsih.c - * High performance SCSI / Fibre Channel SCSI Host device driver. - * For use with PCI chip/adapter(s): - * LSIFC9xx/LSI409xx Fibre Channel - * running LSI Logic Fusion MPT (Message Passing Technology) firmware. - * - * Credits: - * This driver would not exist if not for Alan Cox's development - * of the linux i2o driver. - * - * A special thanks to Pamela Delaney (LSI Logic) for tons of work - * and countless enhancements while adding support for the 1030 - * chip family. Pam has been instrumental in the development of - * of the 2.xx.xx series fusion drivers, and her contributions are - * far too numerous to hope to list in one place. - * - * A huge debt of gratitude is owed to David S. Miller (DaveM) - * for fixing much of the stupid and broken stuff in the early - * driver while porting to sparc64 platform. THANK YOU! - * - * (see mptbase.c) - * - * Copyright (c) 1999-2002 LSI Logic Corporation - * Original author: Steven J. Ralston - * (mailto:sjralston1@netscape.net) - * (mailto:lstephens@lsil.com) - * - * $Id: mptscsih.c,v 1.1.2.4 2003/05/07 14:08:34 pdelaney Exp $ - */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - NO WARRANTY - THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - solely responsible for determining the appropriateness of using and - distributing the Program and assumes all risks associated with its - exercise of rights under this Agreement, including but not limited to - the risks and costs of program errors, damage to or loss of data, - programs or equipment, and unavailability or interruption of operations. - - DISCLAIMER OF LIABILITY - NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#include /* SAE: Necessary... */ -#include -#include -#include -#include -#include -#include -#include -#include /* for io_request_lock (spinlock) decl */ -#include /* for mdelay */ -#include /* needed for in_interrupt() proto */ -#include /* notifier code */ -#include -#include /* SAE: Necessary... */ -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,45) -#include "../../scsi/sd.h" -#endif - -#include "mptbase.h" -#include "mptscsih.h" -#include "isense.h" - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#define my_NAME "Fusion MPT SCSI Host driver" -#define my_VERSION MPT_LINUX_VERSION_COMMON -#define MYNAM "mptscsih" - -MODULE_AUTHOR(MODULEAUTHOR); -MODULE_DESCRIPTION(my_NAME); -MODULE_LICENSE("GPL"); - -/* Set string for command line args from insmod */ -#ifdef MODULE -char *mptscsih = 0; -MODULE_PARM(mptscsih, "s"); -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -typedef struct _BIG_SENSE_BUF { - u8 data[MPT_SENSE_BUFFER_ALLOC]; -} BIG_SENSE_BUF; - -#define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */ -#define MPT_SCANDV_DID_RESET (0x00000001) -#define MPT_SCANDV_SENSE (0x00000002) -#define MPT_SCANDV_SOME_ERROR (0x00000004) -#define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008) -#define MPT_SCANDV_ISSUE_SENSE (0x00000010) - -#define MPT_SCANDV_MAX_RETRIES (10) - -#define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */ -#define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */ -#define MPT_ICFLAG_PHYS_DISK 0x04 /* Any SCSI IO but do Phys Disk Format */ -#define MPT_ICFLAG_TAGGED_CMD 0x08 /* Do tagged IO */ -#define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occured with this command */ -#define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */ - -typedef struct _internal_cmd { - char *data; /* data pointer */ - dma_addr_t data_dma; /* data dma address */ - int size; /* transfer size */ - u8 cmd; /* SCSI Op Code */ - u8 bus; /* bus number */ - u8 id; /* SCSI ID (virtual) */ - u8 lun; - u8 flags; /* Bit Field - See above */ - u8 physDiskNum; /* Phys disk number, -1 else */ - u8 rsvd2; - u8 rsvd; -} INTERNAL_CMD; - -typedef struct _negoparms { - u8 width; - u8 offset; - u8 factor; - u8 flags; -} NEGOPARMS; - -typedef struct _dv_parameters { - NEGOPARMS max; - NEGOPARMS now; - u8 cmd; - u8 id; - u16 pad1; -} DVPARAMETERS; - - -/* - * Other private/forward protos... - */ -static int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); -static void mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq); -static int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); - -static int mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt, - SCSIIORequest_t *pReq, int req_idx); -static void mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx); -static int mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init); -static void copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); -#ifndef MPT_SCSI_USE_NEW_EH -static void search_taskQ_for_cmd(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd); -#else -static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); -#endif -static u32 SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc); -static MPT_FRAME_HDR *mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx); -static void post_pendingQ_commands(MPT_SCSI_HOST *hd); - -static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, int sleepFlag); -static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, int sleepFlag); - -static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); -static int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); - -static VirtDevice *mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen); -void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56); -static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq); -static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags); -static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id); -static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags); -static int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); -static void mptscsih_timer_expired(unsigned long data); -static void mptscsih_taskmgmt_timeout(unsigned long data); -static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); -static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum); - -#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION -static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); -static void mptscsih_domainValidation(void *hd); -static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); -static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id); -static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target); -static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage); -static void mptscsih_fillbuf(char *buffer, int size, int index, int width); -#endif -#if XEN_KILLED -static int mptscsih_setup(char *str); -static int mptscsih_halt(struct notifier_block *nb, ulong event, void *buf); - -/* - * Reboot Notification - */ -static struct notifier_block mptscsih_notifier = { - mptscsih_halt, NULL, 0 -}; -#endif - -/* - * Private data... - */ - -static int mpt_scsi_hosts = 0; -static atomic_t queue_depth; - -static int ScsiDoneCtx = -1; -static int ScsiTaskCtx = -1; -static int ScsiScanDvCtx = -1; /* Used only for bus scan and dv */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,28) -static struct proc_dir_entry proc_mpt_scsihost = -{ - .low_ino = PROC_SCSI_MPT, - .namelen = 8, - .name = "mptscsih", - .mode = S_IFDIR | S_IRUGO | S_IXUGO, - .nlink = 2, -}; -#endif - -#define SNS_LEN(scp) sizeof((scp)->sense_buffer) - -#ifndef MPT_SCSI_USE_NEW_EH -/* - * Stuff to handle single-threading SCSI TaskMgmt - * (abort/reset) requests... - */ -static spinlock_t mytaskQ_lock = SPIN_LOCK_UNLOCKED; -static int mytaskQ_bh_active = 0; -static struct mpt_work_struct mptscsih_ptaskfoo; -static atomic_t mpt_taskQdepth; -#endif - -#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION -/* - * Domain Validation task structure - */ -static spinlock_t dvtaskQ_lock = SPIN_LOCK_UNLOCKED; -static int dvtaskQ_active = 0; -static int dvtaskQ_release = 0; -static struct mpt_work_struct mptscsih_dvTask; -#endif - -/* SAE: No wait queues in Xen */ -#ifdef XEN_KILLED -/* - * Wait Queue setup - */ -static DECLARE_WAIT_QUEUE_HEAD (scandv_waitq); - -#endif - -static int scandv_wait_done = 1; - -/* Driver default setup - */ -static struct mptscsih_driver_setup - driver_setup = MPTSCSIH_DRIVER_SETUP; - -#ifdef MPTSCSIH_DBG_TIMEOUT -static Scsi_Cmnd *foo_to[8]; -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Private inline routines... - */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* 19991030 -sralston - * Return absolute SCSI data direction: - * 1 = _DATA_OUT - * 0 = _DIR_NONE - * -1 = _DATA_IN - * - * Changed: 3-20-2002 pdelaney to use the default data - * direction and the defines set up in the - * 2.4 kernel series - * 1 = _DATA_OUT changed to SCSI_DATA_WRITE (1) - * 0 = _DIR_NONE changed to SCSI_DATA_NONE (3) - * -1 = _DATA_IN changed to SCSI_DATA_READ (2) - * If the direction is unknown, fall through to original code. - * - * Mid-layer bug fix(): sg interface generates the wrong data - * direction in some cases. Set the direction the hard way for - * the most common commands. - */ -static inline int -mptscsih_io_direction(Scsi_Cmnd *cmd) -{ - switch (cmd->cmnd[0]) { - case WRITE_6: - case WRITE_10: - return SCSI_DATA_WRITE; - break; - case READ_6: - case READ_10: - return SCSI_DATA_READ; - break; - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - if (cmd->sc_data_direction != SCSI_DATA_UNKNOWN) - return cmd->sc_data_direction; -#endif - switch (cmd->cmnd[0]) { - /* _DATA_OUT commands */ - case WRITE_6: case WRITE_10: case WRITE_12: - case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER: - case WRITE_VERIFY: case WRITE_VERIFY_12: - case COMPARE: case COPY: case COPY_VERIFY: - case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: - case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12: - case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT: - case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK: - case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG: - case REASSIGN_BLOCKS: - case PERSISTENT_RESERVE_OUT: - case 0xea: - case 0xa3: - return SCSI_DATA_WRITE; - - /* No data transfer commands */ - case SEEK_6: case SEEK_10: - case RESERVE: case RELEASE: - case TEST_UNIT_READY: - case START_STOP: - case ALLOW_MEDIUM_REMOVAL: - return SCSI_DATA_NONE; - - /* Conditional data transfer commands */ - case FORMAT_UNIT: - if (cmd->cmnd[1] & 0x10) /* FmtData (data out phase)? */ - return SCSI_DATA_WRITE; - else - return SCSI_DATA_NONE; - - case VERIFY: - if (cmd->cmnd[1] & 0x02) /* VERIFY:BYTCHK (data out phase)? */ - return SCSI_DATA_WRITE; - else - return SCSI_DATA_NONE; - - case RESERVE_10: - if (cmd->cmnd[1] & 0x03) /* RESERVE:{LongID|Extent} (data out phase)? */ - return SCSI_DATA_WRITE; - else - return SCSI_DATA_NONE; - - /* Must be data _IN! */ - default: - return SCSI_DATA_READ; - } -} /* mptscsih_io_direction() */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_add_sge - Place a simple SGE at address pAddr. - * @pAddr: virtual address for SGE - * @flagslength: SGE flags and data transfer length - * @dma_addr: Physical address - * - * This routine places a MPT request frame back on the MPT adapter's - * FreeQ. - */ -static inline void -mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr) -{ - if (sizeof(dma_addr_t) == sizeof(u64)) { - SGESimple64_t *pSge = (SGESimple64_t *) pAddr; - u32 tmp = dma_addr & 0xFFFFFFFF; - - pSge->FlagsLength = cpu_to_le32(flagslength); - pSge->Address.Low = cpu_to_le32(tmp); - tmp = (u32) ((u64)dma_addr >> 32); - pSge->Address.High = cpu_to_le32(tmp); - - } else { - SGESimple32_t *pSge = (SGESimple32_t *) pAddr; - pSge->FlagsLength = cpu_to_le32(flagslength); - pSge->Address = cpu_to_le32(dma_addr); - } -} /* mptscsih_add_sge() */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_add_chain - Place a chain SGE at address pAddr. - * @pAddr: virtual address for SGE - * @next: nextChainOffset value (u32's) - * @length: length of next SGL segment - * @dma_addr: Physical address - * - * This routine places a MPT request frame back on the MPT adapter's - * FreeQ. - */ -static inline void -mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr) -{ - if (sizeof(dma_addr_t) == sizeof(u64)) { - SGEChain64_t *pChain = (SGEChain64_t *) pAddr; - u32 tmp = dma_addr & 0xFFFFFFFF; - - pChain->Length = cpu_to_le16(length); - pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size(); - - pChain->NextChainOffset = next; - - pChain->Address.Low = cpu_to_le32(tmp); - tmp = (u32) ((u64)dma_addr >> 32); - pChain->Address.High = cpu_to_le32(tmp); - } else { - SGEChain32_t *pChain = (SGEChain32_t *) pAddr; - pChain->Length = cpu_to_le16(length); - pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size(); - pChain->NextChainOffset = next; - pChain->Address = cpu_to_le32(dma_addr); - } -} /* mptscsih_add_chain() */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_getFreeChainBuffes - Function to get a free chain - * from the MPT_SCSI_HOST FreeChainQ. - * @hd: Pointer to the MPT_SCSI_HOST instance - * @req_idx: Index of the SCSI IO request frame. (output) - * - * return SUCCESS or FAILED - */ -static inline int -mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex) -{ - MPT_FRAME_HDR *chainBuf = NULL; - unsigned long flags; - int rc = FAILED; - int chain_idx = MPT_HOST_NO_CHAIN; - - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - if (!Q_IS_EMPTY(&hd->FreeChainQ)) { - - int offset; - - chainBuf = hd->FreeChainQ.head; - Q_DEL_ITEM(&chainBuf->u.frame.linkage); - offset = (u8 *)chainBuf - (u8 *)hd->ChainBuffer; - chain_idx = offset / hd->ioc->req_sz; - rc = SUCCESS; - } - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - - - *retIndex = chain_idx; - - dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n", - hd->ioc->name, *retIndex, chainBuf)); - - return rc; -} /* mptscsih_getFreeChainBuffer() */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the - * SCSIIORequest_t Message Frame. - * @hd: Pointer to MPT_SCSI_HOST structure - * @SCpnt: Pointer to Scsi_Cmnd structure - * @pReq: Pointer to SCSIIORequest_t structure - * - * Returns ... - */ -static int -mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt, - SCSIIORequest_t *pReq, int req_idx) -{ - char *psge; - char *chainSge; - struct scatterlist *sg; - int frm_sz; - int sges_left, sg_done; - int chain_idx = MPT_HOST_NO_CHAIN; - int sgeOffset; - int numSgeSlots, numSgeThisFrame; - u32 sgflags, sgdir, thisxfer = 0; - int chain_dma_off = 0; - int newIndex; - int ii; - dma_addr_t v2; - - sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK; - if (sgdir == MPI_SCSIIO_CONTROL_WRITE) { - sgdir = MPT_TRANSFER_HOST_TO_IOC; - } else { - sgdir = MPT_TRANSFER_IOC_TO_HOST; - } - - psge = (char *) &pReq->SGL; - frm_sz = hd->ioc->req_sz; - - /* Map the data portion, if any. - * sges_left = 0 if no data transfer. - */ - sges_left = SCpnt->use_sg; - if (SCpnt->use_sg) { - sges_left = pci_map_sg(hd->ioc->pcidev, - (struct scatterlist *) SCpnt->request_buffer, - SCpnt->use_sg, - scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); - } else if (SCpnt->request_bufflen) { - dma_addr_t buf_dma_addr; - scPrivate *my_priv; - - buf_dma_addr = pci_map_single(hd->ioc->pcidev, - SCpnt->request_buffer, - SCpnt->request_bufflen, - scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); - - /* We hide it here for later unmap. */ - my_priv = (scPrivate *) &SCpnt->SCp; - my_priv->p1 = (void *)(ulong) buf_dma_addr; - - dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n", - hd->ioc->name, SCpnt, SCpnt->request_bufflen)); - - mptscsih_add_sge((char *) &pReq->SGL, - 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen, - buf_dma_addr); - - return SUCCESS; - } - - /* Handle the SG case. - */ - sg = (struct scatterlist *) SCpnt->request_buffer; - sg_done = 0; - sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION); - chainSge = NULL; - - /* Prior to entering this loop - the following must be set - * current MF: sgeOffset (bytes) - * chainSge (Null if original MF is not a chain buffer) - * sg_done (num SGE done for this MF) - */ - -nextSGEset: - numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) ); - numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots; - - sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir; - - /* Get first (num - 1) SG elements - * Skip any SG entries with a length of 0 - * NOTE: at finish, sg and psge pointed to NEXT data/location positions - */ - for (ii=0; ii < (numSgeThisFrame-1); ii++) { - thisxfer = sg_dma_len(sg); - if (thisxfer == 0) { - sg ++; /* Get next SG element from the OS */ - sg_done++; - continue; - } - - v2 = sg_dma_address(sg); - mptscsih_add_sge(psge, sgflags | thisxfer, v2); - - sg++; /* Get next SG element from the OS */ - psge += (sizeof(u32) + sizeof(dma_addr_t)); - sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); - sg_done++; - } - - if (numSgeThisFrame == sges_left) { - /* Add last element, end of buffer and end of list flags. - */ - sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT | - MPT_SGE_FLAGS_END_OF_BUFFER | - MPT_SGE_FLAGS_END_OF_LIST; - - /* Add last SGE and set termination flags. - * Note: Last SGE may have a length of 0 - which should be ok. - */ - thisxfer = sg_dma_len(sg); - - v2 = sg_dma_address(sg); - mptscsih_add_sge(psge, sgflags | thisxfer, v2); - /* - sg++; - psge += (sizeof(u32) + sizeof(dma_addr_t)); - */ - sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); - sg_done++; - - if (chainSge) { - /* The current buffer is a chain buffer, - * but there is not another one. - * Update the chain element - * Offset and Length fields. - */ - mptscsih_add_chain((char *)chainSge, 0, sgeOffset, hd->ChainBufferDMA + chain_dma_off); - } else { - /* The current buffer is the original MF - * and there is no Chain buffer. - */ - pReq->ChainOffset = 0; - } - } else { - /* At least one chain buffer is needed. - * Complete the first MF - * - last SGE element, set the LastElement bit - * - set ChainOffset (words) for orig MF - * (OR finish previous MF chain buffer) - * - update MFStructPtr ChainIndex - * - Populate chain element - * Also - * Loop until done. - */ - - dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n", - hd->ioc->name, sg_done)); - - /* Set LAST_ELEMENT flag for last non-chain element - * in the buffer. Since psge points at the NEXT - * SGE element, go back one SGE element, update the flags - * and reset the pointer. (Note: sgflags & thisxfer are already - * set properly). - */ - if (sg_done) { - u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t))); - sgflags = le32_to_cpu(*ptmp); - sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT; - *ptmp = cpu_to_le32(sgflags); - } - - if (chainSge) { - /* The current buffer is a chain buffer. - * chainSge points to the previous Chain Element. - * Update its chain element Offset and Length (must - * include chain element size) fields. - * Old chain element is now complete. - */ - u8 nextChain = (u8) (sgeOffset >> 2); - sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); - mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, hd->ChainBufferDMA + chain_dma_off); - } else { - /* The original MF buffer requires a chain buffer - - * set the offset. - * Last element in this MF is a chain element. - */ - pReq->ChainOffset = (u8) (sgeOffset >> 2); - } - - sges_left -= sg_done; - - - /* NOTE: psge points to the beginning of the chain element - * in current buffer. Get a chain buffer. - */ - if ((mptscsih_getFreeChainBuffer(hd, &newIndex)) == FAILED) - return FAILED; - - /* Update the tracking arrays. - * If chainSge == NULL, update ReqToChain, else ChainToChain - */ - if (chainSge) { - hd->ChainToChain[chain_idx] = newIndex; - } else { - hd->ReqToChain[req_idx] = newIndex; - } - chain_idx = newIndex; - chain_dma_off = hd->ioc->req_sz * chain_idx; - - /* Populate the chainSGE for the current buffer. - * - Set chain buffer pointer to psge and fill - * out the Address and Flags fields. - */ - chainSge = (char *) psge; - dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)", - psge, req_idx)); - - /* Start the SGE for the next buffer - */ - psge = (char *) (hd->ChainBuffer + chain_dma_off); - sgeOffset = 0; - sg_done = 0; - - dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n", - psge, chain_idx)); - - /* Start the SGE for the next buffer - */ - - goto nextSGEset; - } - - return SUCCESS; -} /* mptscsih_AddSGE() */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_io_done - Main SCSI IO callback routine registered to - * Fusion MPT (base) driver - * @ioc: Pointer to MPT_ADAPTER structure - * @mf: Pointer to original MPT request frame - * @r: Pointer to MPT reply frame (NULL if TurboReply) - * - * This routine is called from mpt.c::mpt_interrupt() at the completion - * of any SCSI IO request. - * This routine is registered with the Fusion MPT (base) driver at driver - * load/init time via the mpt_register() API call. - * - * Returns 1 indicating alloc'd request frame ptr should be freed. - */ -static int -mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) -{ - Scsi_Cmnd *sc; - MPT_SCSI_HOST *hd; - SCSIIORequest_t *pScsiReq; - SCSIIOReply_t *pScsiReply; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) - unsigned long flags; -#endif - u16 req_idx; - - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - - if ((mf == NULL) || - (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) { - printk(MYIOC_s_ERR_FMT "%s req frame ptr! (=%p)!\n", - ioc->name, mf?"BAD":"NULL", (void *) mf); - return 0; - } - - req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); - sc = hd->ScsiLookup[req_idx]; - if (sc == NULL) { - MPIHeader_t *hdr = (MPIHeader_t *)mf; - - atomic_dec(&queue_depth); - - /* Remark: writeSDP1 will use the ScsiDoneCtx - * If a SCSI I/O cmd, device disabled by OS and - * completion done. Cannot touch sc struct. Just free mem. - */ - if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST) - printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n", ioc->name); - - mptscsih_freeChainBuffers(hd, req_idx); - return 1; - } - - dmfprintk((MYIOC_s_INFO_FMT "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n", - ioc->name, mf, mr, sc, req_idx)); - - atomic_dec(&queue_depth); - - sc->result = DID_OK << 16; /* Set default reply as OK */ - pScsiReq = (SCSIIORequest_t *) mf; - pScsiReply = (SCSIIOReply_t *) mr; - -#ifdef MPTSCSIH_DBG_TIMEOUT - if (ioc->timeout_cnt > 0) { - int ii, left = 0; - - for (ii=0; ii < 8; ii++) { - if (sc == foo_to[ii]) { - printk(MYIOC_s_INFO_FMT "complete (%p, %ld)\n", - ioc->name, sc, jiffies); - foo_to[ii] = NULL; - } - if (foo_to[ii] != NULL) - left++; - } - - if (left == 0) { - ioc->timeout_maxcnt = 0; - ioc->timeout_cnt = 0; - } - } -#endif - if (pScsiReply == NULL) { - /* special context reply handling */ - - /* If regular Inquiry cmd - save inquiry data - */ - if (pScsiReq->CDB[0] == INQUIRY && !(pScsiReq->CDB[1] & 0x3)) { - int dlen; - - dlen = le32_to_cpu(pScsiReq->DataLength); - if (dlen >= SCSI_STD_INQUIRY_BYTES) { - mptscsih_initTarget(hd, - sc->channel, - sc->target, - pScsiReq->LUN[1], - sc->buffer, - dlen); - } - } - } else { - u32 xfer_cnt; - u16 status; - u8 scsi_state; - - status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK; - scsi_state = pScsiReply->SCSIState; - - dprintk((KERN_NOTICE " Uh-Oh! (%d:%d:%d) mf=%p, mr=%p, sc=%p\n", - ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1], - mf, mr, sc)); - dprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh" - ", SCSIStatus=%02xh, IOCLogInfo=%08xh\n", - status, scsi_state, pScsiReply->SCSIStatus, - le32_to_cpu(pScsiReply->IOCLogInfo))); - - if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) - copy_sense_data(sc, hd, mf, pScsiReply); - - /* - * Look for + dump FCP ResponseInfo[]! - */ - if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) { - dprintk((KERN_NOTICE " FCP_ResponseInfo=%08xh\n", - le32_to_cpu(pScsiReply->ResponseInfo))); - } - - switch(status) { - case MPI_IOCSTATUS_BUSY: /* 0x0002 */ - /* CHECKME! - * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry) - * But not: DID_BUS_BUSY lest one risk - * killing interrupt handler:-( - */ - sc->result = STS_BUSY; - break; - - case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */ - case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */ - sc->result = DID_BAD_TARGET << 16; - break; - - case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ - /* Spoof to SCSI Selection Timeout! */ - sc->result = DID_NO_CONNECT << 16; - - if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF) - hd->sel_timeout[pScsiReq->TargetID]++; - break; - - case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ -#ifndef MPT_SCSI_USE_NEW_EH - search_taskQ_for_cmd(sc, hd); -#endif - /* Linux handles an unsolicited DID_RESET better - * than an unsolicited DID_ABORT. - */ - sc->result = DID_RESET << 16; - - /* GEM Workaround. */ - if (hd->is_spi) - mptscsih_no_negotiate(hd, sc->target); - break; - - case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ - case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ -#ifndef MPT_SCSI_USE_NEW_EH - search_taskQ_for_cmd(sc, hd); -#endif - sc->result = DID_RESET << 16; - - /* GEM Workaround. */ - if (hd->is_spi) - mptscsih_no_negotiate(hd, sc->target); - break; - - case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ - case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ - /* - * YIKES! I just discovered that SCSI IO which - * returns check condition, SenseKey=05 (ILLEGAL REQUEST) - * and ASC/ASCQ=94/01 (LSI Logic RAID vendor specific), - * comes down this path! - * Do upfront check for valid SenseData and give it - * precedence! - */ - sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus; - if (scsi_state == 0) { - ; - } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) { - /* Have already saved the status and sense data - */ - ; - } else if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) { - /* What to do? - */ - sc->result = DID_SOFT_ERROR << 16; - } - else if (scsi_state & MPI_SCSI_STATE_TERMINATED) { - /* Not real sure here either... */ - sc->result = DID_RESET << 16; - } - - /* Give report and update residual count. - */ - xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); - dprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n", - sc->underflow)); - dprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt)); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - sc->resid = sc->request_bufflen - xfer_cnt; - dprintk((KERN_NOTICE " SET sc->resid=%02xh\n", sc->resid)); -#endif - - /* Report Queue Full - */ - if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL) - mptscsih_report_queue_full(sc, pScsiReply, pScsiReq); - - /* If regular Inquiry cmd and some data was transferred, - * save inquiry data - */ - if ( pScsiReq->CDB[0] == INQUIRY - && !(pScsiReq->CDB[1] & 0x3) - && xfer_cnt >= SCSI_STD_INQUIRY_BYTES - ) { - mptscsih_initTarget(hd, - sc->channel, - sc->target, - pScsiReq->LUN[1], - sc->buffer, - xfer_cnt); - } - break; - - case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ - case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ - sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus; - if (scsi_state == 0) { - ; - } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) { - /* - * If running against circa 200003dd 909 MPT f/w, - * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL - * (QUEUE_FULL) returned from device! --> get 0x0000?128 - * and with SenseBytes set to 0. - */ - if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL) - mptscsih_report_queue_full(sc, pScsiReply, pScsiReq); - -#ifndef MPT_SCSI_USE_NEW_EH - /* ADDED 20011120 -sralston - * Scsi mid-layer (old_eh) doesn't seem to like it - * when RAID returns SCSIStatus=02 (CHECK CONDITION), - * SenseKey=01 (RECOVERED ERROR), ASC/ASCQ=95/01. - * Seems to be * treating this as a IO error:-( - * - * So just lie about it altogether here. - * - * NOTE: It still gets reported to syslog via - * mpt_ScsiHost_ErrorReport from copy_sense_data - * call far above. - */ - if ( pScsiReply->SCSIStatus == STS_CHECK_CONDITION - && SD_Sense_Key(sc->sense_buffer) == SK_RECOVERED_ERROR - ) { - sc->result = 0; - } -#endif - - } - else if (scsi_state & - (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS) - ) { - /* - * What to do? - */ - sc->result = DID_SOFT_ERROR << 16; - } - else if (scsi_state & MPI_SCSI_STATE_TERMINATED) { - /* Not real sure here either... */ - sc->result = DID_RESET << 16; - } - else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) { - /* Device Inq. data indicates that it supports - * QTags, but rejects QTag messages. - * This command completed OK. - * - * Not real sure here either so do nothing... */ - } - - if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL) - mptscsih_report_queue_full(sc, pScsiReply, pScsiReq); - - /* Add handling of: - * Reservation Conflict, Busy, - * Command Terminated, CHECK - */ - - /* If regular Inquiry cmd - save inquiry data - */ - xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); - if ( sc->result == (DID_OK << 16) - && pScsiReq->CDB[0] == INQUIRY - && !(pScsiReq->CDB[1] & 0x3) - && xfer_cnt >= SCSI_STD_INQUIRY_BYTES - ) { - mptscsih_initTarget(hd, - sc->channel, - sc->target, - pScsiReq->LUN[1], - sc->buffer, - xfer_cnt); - } - break; - - case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ - if (pScsiReply->SCSIState & MPI_SCSI_STATE_TERMINATED) { - /* Not real sure here either... */ - sc->result = DID_RESET << 16; - } else - sc->result = DID_SOFT_ERROR << 16; - break; - - case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */ - case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */ - case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */ - case MPI_IOCSTATUS_RESERVED: /* 0x0005 */ - case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */ - case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */ - case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */ - case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ - case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ - case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ - default: - /* - * What to do? - */ - sc->result = DID_SOFT_ERROR << 16; - break; - - } /* switch(status) */ - - dprintk((KERN_NOTICE " sc->result set to %08xh\n", sc->result)); - } /* end of address reply case */ - - /* Unmap the DMA buffers, if any. */ - if (sc->use_sg) { - pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer, - sc->use_sg, scsi_to_pci_dma_dir(sc->sc_data_direction)); - } else if (sc->request_bufflen) { - scPrivate *my_priv; - - my_priv = (scPrivate *) &sc->SCp; - pci_unmap_single(ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1, - sc->request_bufflen, - scsi_to_pci_dma_dir(sc->sc_data_direction)); - } - - hd->ScsiLookup[req_idx] = NULL; - -#ifndef MPT_SCSI_USE_NEW_EH - sc->host_scribble = NULL; -#endif - - MPT_HOST_LOCK(flags); - sc->scsi_done(sc); /* Issue the command callback */ - MPT_HOST_UNLOCK(flags); - - /* Free Chain buffers */ - mptscsih_freeChainBuffers(hd, req_idx); - - return 1; -} - -#ifndef MPT_SCSI_USE_NEW_EH /* { */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * search_taskQ - Search SCSI task mgmt request queue for specific - * request type. - * @remove: (Boolean) Should request be removed if found? - * @sc: Pointer to Scsi_Cmnd structure - * @task_type: Task type to search for - * - * Returns pointer to MPT request frame if found, or %NULL if request - * was not found. - */ -static MPT_FRAME_HDR * -search_taskQ(int remove, Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, u8 task_type) -{ - MPT_FRAME_HDR *mf = NULL; - unsigned long flags; - int count = 0; - int list_sz; - - dprintk((KERN_INFO MYNAM ": search_taskQ(%d,sc=%p,%d) called\n", - remove, sc, task_type)); - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - list_sz = hd->taskQcnt; - if (! Q_IS_EMPTY(&hd->taskQ)) { - mf = hd->taskQ.head; - do { - count++; - if (mf->u.frame.linkage.argp1 == sc && - mf->u.frame.linkage.arg1 == task_type) { - if (remove) { - Q_DEL_ITEM(&mf->u.frame.linkage); - hd->taskQcnt--; - atomic_dec(&mpt_taskQdepth); - - /* Don't save mf into nextmf because - * exit after command has been deleted. - */ - - /* Place the MF back on the FreeQ */ - Q_ADD_TAIL(&hd->ioc->FreeQ, - &mf->u.frame.linkage, - MPT_FRAME_HDR); -#ifdef MFCNT - hd->ioc->mfcnt--; -#endif - } - break; - } - } while ((mf = mf->u.frame.linkage.forw) != (MPT_FRAME_HDR*)&hd->taskQ); - if (mf == (MPT_FRAME_HDR*)&hd->taskQ) { - mf = NULL; - } - } - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - - if (list_sz) { - dprintk((KERN_INFO " Results=%p (%sFOUND%s)!\n", - mf, - mf ? "" : "NOT_", - (mf && remove) ? "+REMOVED" : "" )); - dprintk((KERN_INFO " (searched thru %d of %d items on taskQ)\n", - count, - list_sz )); - } - - return mf; -} - -/* - * clean_taskQ - Clean the SCSI task mgmt request for - * this SCSI host instance. - * @hd: MPT_SCSI_HOST pointer - * - * Returns: None. - */ -static void -clean_taskQ(MPT_SCSI_HOST *hd) -{ - MPT_FRAME_HDR *mf = NULL; - MPT_FRAME_HDR *nextmf = NULL; - MPT_ADAPTER *ioc = hd->ioc; - unsigned long flags; - - dprintk((KERN_INFO MYNAM ": clean_taskQ called\n")); - - spin_lock_irqsave(&ioc->FreeQlock, flags); - if (! Q_IS_EMPTY(&hd->taskQ)) { - mf = hd->taskQ.head; - do { - Q_DEL_ITEM(&mf->u.frame.linkage); - hd->taskQcnt--; - atomic_dec(&mpt_taskQdepth); - - nextmf = mf->u.frame.linkage.forw; - - /* Place the MF back on the FreeQ */ - Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, - MPT_FRAME_HDR); -#ifdef MFCNT - hd->ioc->mfcnt--; -#endif - } while ((mf = nextmf) != (MPT_FRAME_HDR*)&hd->taskQ); - } - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - - return; -} - -/* - * search_taskQ_for_cmd - Search the SCSI task mgmt request queue for - * the specified command. If found, delete - * @hd: MPT_SCSI_HOST pointer - * - * Returns: None. - */ -static void -search_taskQ_for_cmd(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd) -{ - MPT_FRAME_HDR *mf = NULL; - unsigned long flags; - int count = 0; - - dprintk((KERN_INFO MYNAM ": search_taskQ_for_cmd(sc=%p) called\n", sc)); - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - if (! Q_IS_EMPTY(&hd->taskQ)) { - mf = hd->taskQ.head; - do { - count++; - if (mf->u.frame.linkage.argp1 == sc) { - Q_DEL_ITEM(&mf->u.frame.linkage); - hd->taskQcnt--; - atomic_dec(&mpt_taskQdepth); - dprintk((KERN_INFO MYNAM - ": Cmd %p found! Deleting.\n", sc)); - - /* Don't save mf into nextmf because - * exit after command has been deleted. - */ - - /* Place the MF back on the FreeQ */ - Q_ADD_TAIL(&hd->ioc->FreeQ, - &mf->u.frame.linkage, - MPT_FRAME_HDR); -#ifdef MFCNT - hd->ioc->mfcnt--; -#endif - break; - } - } while ((mf = mf->u.frame.linkage.forw) != (MPT_FRAME_HDR*)&hd->taskQ); - } - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - - return; -} - -#endif /* } MPT_SCSI_USE_NEW_EH */ - - -/* - * Flush all commands on the doneQ. - * Lock Q when deleting/adding members - * Lock io_request_lock for OS callback. - */ -static void -flush_doneQ(MPT_SCSI_HOST *hd) -{ - MPT_DONE_Q *buffer; - Scsi_Cmnd *SCpnt; - unsigned long flags; - - /* Flush the doneQ. - */ - dtmprintk((KERN_INFO MYNAM ": flush_doneQ called\n")); - while (1) { - spin_lock_irqsave(&hd->freedoneQlock, flags); - if (Q_IS_EMPTY(&hd->doneQ)) { - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - break; - } - - buffer = hd->doneQ.head; - /* Delete from Q - */ - Q_DEL_ITEM(buffer); - - /* Set the Scsi_Cmnd pointer - */ - SCpnt = (Scsi_Cmnd *) buffer->argp; - buffer->argp = NULL; - - /* Add to the freeQ - */ - Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q); - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - - /* Do the OS callback. - */ - MPT_HOST_LOCK(flags); - SCpnt->scsi_done(SCpnt); - MPT_HOST_UNLOCK(flags); - } - - return; -} - -/* - * Search the doneQ for a specific command. If found, delete from Q. - * Calling function will finish processing. - */ -static void -search_doneQ_for_cmd(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt) -{ - unsigned long flags; - MPT_DONE_Q *buffer; - - spin_lock_irqsave(&hd->freedoneQlock, flags); - if (!Q_IS_EMPTY(&hd->doneQ)) { - buffer = hd->doneQ.head; - do { - Scsi_Cmnd *sc = (Scsi_Cmnd *) buffer->argp; - if (SCpnt == sc) { - Q_DEL_ITEM(buffer); - SCpnt->result = sc->result; - - /* Set the Scsi_Cmnd pointer - */ - buffer->argp = NULL; - - /* Add to the freeQ - */ - Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q); - break; - } - } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->doneQ); - } - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - return; -} - -static void -mptscsih_reset_timeouts (MPT_SCSI_HOST *hd) -{ - Scsi_Cmnd *SCpnt = NULL; - int ii; - int max = hd->ioc->req_depth; - - for (ii= 0; ii < max; ii++) { - if ((SCpnt = hd->ScsiLookup[ii]) != NULL) { - mod_timer(&SCpnt->eh_timeout, jiffies + (HZ * 60)); - dtmprintk((MYIOC_s_WARN_FMT "resetting SCpnt=%p timeout + 60HZ", - (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt)); - } - } -} - -/* - * mptscsih_flush_running_cmds - For each command found, search - * Scsi_Host instance taskQ and reply to OS. - * Called only if recovering from a FW reload. - * @hd: Pointer to a SCSI HOST structure - * - * Returns: None. - * - * Must be called while new I/Os are being queued. - */ -static void -mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) -{ - Scsi_Cmnd *SCpnt = NULL; - MPT_FRAME_HDR *mf = NULL; - MPT_DONE_Q *buffer = NULL; - int ii; - int max = hd->ioc->req_depth; - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) - unsigned long flags; -#endif - - dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n")); - for (ii= 0; ii < max; ii++) { - if ((SCpnt = hd->ScsiLookup[ii]) != NULL) { - - /* Command found. - */ -#ifndef MPT_SCSI_USE_NEW_EH - /* Search taskQ, if found, delete. - */ - search_taskQ_for_cmd(SCpnt, hd); -#endif - - /* Search pendingQ, if found, - * delete from Q. If found, do not decrement - * queue_depth, command never posted. - */ - if (mptscsih_search_pendingQ(hd, ii) == NULL) - atomic_dec(&queue_depth); - - /* Null ScsiLookup index - */ - hd->ScsiLookup[ii] = NULL; - - mf = MPT_INDEX_2_MFPTR(hd->ioc, ii); - dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n", mf, SCpnt)); - - /* Set status, free OS resources (SG DMA buffers) - * Free driver resources (chain, msg buffers) - */ - if (SCpnt->use_sg) { - pci_unmap_sg(hd->ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer, - SCpnt->use_sg, scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); - } else if (SCpnt->request_bufflen) { - scPrivate *my_priv; - - my_priv = (scPrivate *) &SCpnt->SCp; - pci_unmap_single(hd->ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1, - SCpnt->request_bufflen, - scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); - } - SCpnt->result = DID_RESET << 16; - SCpnt->host_scribble = NULL; - - /* Free Chain buffers */ - mptscsih_freeChainBuffers(hd, ii); - - /* Free Message frames */ - mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf); - -#if 1 - /* Post to doneQ, do not reply until POST phase - * of reset handler....prevents new commands from - * being queued. - */ - spin_lock_irqsave(&hd->freedoneQlock, flags); - if (!Q_IS_EMPTY(&hd->freeQ)) { - buffer = hd->freeQ.head; - Q_DEL_ITEM(buffer); - - /* Set the Scsi_Cmnd pointer - */ - buffer->argp = (void *)SCpnt; - - /* Add to the doneQ - */ - Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q); - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - } else { - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - SCpnt->scsi_done(SCpnt); - } -#else - MPT_HOST_LOCK(flags); - SCpnt->scsi_done(SCpnt); /* Issue the command callback */ - MPT_HOST_UNLOCK(flags); -#endif - } - } - - return; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_initChainBuffers - Allocate memory for and initialize - * chain buffers, chain buffer control arrays and spinlock. - * @hd: Pointer to MPT_SCSI_HOST structure - * @init: If set, initialize the spin lock. - */ -static int -mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init) -{ - MPT_FRAME_HDR *chain; - u8 *mem; - unsigned long flags; - int sz, ii, num_chain; - int scale, num_sge; - - /* ReqToChain size must equal the req_depth - * index = req_idx - */ - sz = hd->ioc->req_depth * sizeof(int); - if (hd->ReqToChain == NULL) { - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) - return -1; - - hd->ReqToChain = (int *) mem; - } else { - mem = (u8 *) hd->ReqToChain; - } - memset(mem, 0xFF, sz); - - - /* ChainToChain size must equal the total number - * of chain buffers to be allocated. - * index = chain_idx - * - * Calculate the number of chain buffers needed(plus 1) per I/O - * then multiply the the maximum number of simultaneous cmds - * - * num_sge = num sge in request frame + last chain buffer - * scale = num sge per chain buffer if no chain element - */ - scale = hd->ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); - if (sizeof(dma_addr_t) == sizeof(u64)) - num_sge = scale + (hd->ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32)); - else - num_sge = 1+ scale + (hd->ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32)); - - num_chain = 1; - while (hd->max_sge - num_sge > 0) { - num_chain++; - num_sge += (scale - 1); - } - num_chain++; - - if ((int) hd->ioc->chip_type > (int) FC929) - num_chain *= MPT_SCSI_CAN_QUEUE; - else - num_chain *= MPT_FC_CAN_QUEUE; - - hd->num_chain = num_chain; - - sz = num_chain * sizeof(int); - if (hd->ChainToChain == NULL) { - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) - return -1; - - hd->ChainToChain = (int *) mem; - } else { - mem = (u8 *) hd->ChainToChain; - } - memset(mem, 0xFF, sz); - - sz = num_chain * hd->ioc->req_sz; - if (hd->ChainBuffer == NULL) { - /* Allocate free chain buffer pool - */ - mem = pci_alloc_consistent(hd->ioc->pcidev, sz, &hd->ChainBufferDMA); - if (mem == NULL) - return -1; - - hd->ChainBuffer = (u8*)mem; - } else { - mem = (u8 *) hd->ChainBuffer; - } - memset(mem, 0, sz); - - dprintk((KERN_INFO " ChainBuffer @ %p(%p), sz=%d\n", - hd->ChainBuffer, (void *)(ulong)hd->ChainBufferDMA, sz)); - - /* Initialize the free chain Q. - */ - if (init) { - spin_lock_init(&hd->FreeChainQlock); - } - - spin_lock_irqsave (&hd->FreeChainQlock, flags); - Q_INIT(&hd->FreeChainQ, MPT_FRAME_HDR); - - /* Post the chain buffers to the FreeChainQ. - */ - mem = (u8 *)hd->ChainBuffer; - for (ii=0; ii < num_chain; ii++) { - chain = (MPT_FRAME_HDR *) mem; - Q_ADD_TAIL(&hd->FreeChainQ.head, &chain->u.frame.linkage, MPT_FRAME_HDR); - mem += hd->ioc->req_sz; - } - spin_unlock_irqrestore(&hd->FreeChainQlock, flags); - - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Hack! It might be nice to report if a device is returning QUEUE_FULL - * but maybe not each and every time... - */ -static long last_queue_full = 0; - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_report_queue_full - Report QUEUE_FULL status returned - * from a SCSI target device. - * @sc: Pointer to Scsi_Cmnd structure - * @pScsiReply: Pointer to SCSIIOReply_t - * @pScsiReq: Pointer to original SCSI request - * - * This routine periodically reports QUEUE_FULL status returned from a - * SCSI target device. It reports this to the console via kernel - * printk() API call, not more than once every 10 seconds. - */ -static void -mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq) -{ - long time = jiffies; - - if (time - last_queue_full > 10 * HZ) { - char *ioc_str = "ioc?"; - - if (sc->host != NULL && sc->host->hostdata != NULL) - ioc_str = ((MPT_SCSI_HOST *)sc->host->hostdata)->ioc->name; - printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n", - ioc_str, 0, sc->target, sc->lun); - last_queue_full = time; - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int BeenHereDoneThat = 0; -static char *info_kbuf = NULL; - -/* SCSI host fops start here... */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_detect - Register MPT adapter(s) as SCSI host(s) with - * linux scsi mid-layer. - * @tpnt: Pointer to Scsi_Host_Template structure - * - * (linux Scsi_Host_Template.detect routine) - * - * Returns number of SCSI host adapters that were successfully - * registered with the linux scsi mid-layer via the scsi_register() - * API call. - */ -int -mptscsih_detect(Scsi_Host_Template *tpnt) -{ - struct Scsi_Host *sh = NULL; - MPT_SCSI_HOST *hd = NULL; - MPT_ADAPTER *this; - MPT_DONE_Q *freedoneQ; - unsigned long flags; - int sz, ii; - int numSGE = 0; - int scale; - int ioc_cap; - u8 *mem; - - if (! BeenHereDoneThat++) { - /*show_mptmod_ver(my_NAME, my_VERSION);*/ - - ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER); - ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER); - ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER); - -#ifndef MPT_SCSI_USE_NEW_EH - spin_lock_init(&mytaskQ_lock); -#endif - - if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) { - dprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); - } else { - /* FIXME! */ - } - - if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) { - dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n")); - } else { - /* FIXME! */ - } - } - dprintk((KERN_INFO MYNAM ": mptscsih_detect()\n")); - -#ifdef MODULE - /* Evaluate the command line arguments, if any */ - if (mptscsih) - mptscsih_setup(mptscsih); -#endif -#ifndef MPT_SCSI_USE_NEW_EH - atomic_set(&mpt_taskQdepth, 0); -#endif - - this = mpt_adapter_find_first(); - while (this != NULL) { - /* 20010202 -sralston - * Added sanity check on readiness of the MPT adapter. - */ - if (this->last_state != MPI_IOC_STATE_OPERATIONAL) { - printk(MYIOC_s_WARN_FMT "Skipping because it's not operational!\n", - this->name); - continue; - } - - if (!this->active) { - printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n", - this->name); - continue; - } - - - /* Sanity check - ensure at least 1 port is INITIATOR capable - */ - ioc_cap = 0; - for (ii=0; ii < this->facts.NumberOfPorts; ii++) { - if (this->pfacts[ii].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) - ioc_cap ++; - } - - if (!ioc_cap) { - printk(MYIOC_s_WARN_FMT "Skipping because SCSI Initiator mode is NOT enabled!\n", - this->name); - continue; - } - -/* SAE: No proc! */ -#if defined(CONFIG_PROC_FS) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - tpnt->proc_dir = &proc_mpt_scsihost; -#endif - tpnt->proc_info = mptscsih_proc_info; -#endif /* SAE: CONFIG_PROC_FS */ - sh = scsi_register(tpnt, sizeof(MPT_SCSI_HOST)); - if (sh != NULL) { - spin_lock_irqsave(&this->FreeQlock, flags); - sh->io_port = 0; - sh->n_io_port = 0; - sh->irq = 0; - - /* Yikes! This is important! - * Otherwise, by default, linux - * only scans target IDs 0-7! - * pfactsN->MaxDevices unreliable - * (not supported in early - * versions of the FW). - * max_id = 1 + actual max id, - * max_lun = 1 + actual last lun, - * see hosts.h :o( - */ - if ((int)this->chip_type > (int)FC929) - sh->max_id = MPT_MAX_SCSI_DEVICES; - else { - /* For FC, increase the queue depth - * from MPT_SCSI_CAN_QUEUE (31) - * to MPT_FC_CAN_QUEUE (63). - */ - sh->can_queue = MPT_FC_CAN_QUEUE; - sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255; - } - sh->max_lun = MPT_LAST_LUN + 1; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) - sh->max_sectors = MPT_SCSI_MAX_SECTORS; -#endif -/* SAE: The logic of this one just baffles me, should be && defined (I think)... */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && defined CONFIG_HIGHIO - sh->highmem_io = 1; -#endif - /* MPI uses {port, bus, id, lun}, but logically maps - * devices on different ports to different buses, i.e., - * bus 1 may be the 2nd bus on port 0 or the 1st bus on port 1. - * Map bus to channel, ignore port number in SCSI.... - * hd->port = 0; - * If max_channel > 0, need to adjust mem alloc, free, DV - * and all access to VirtDev - */ - sh->max_channel = 0; - sh->this_id = this->pfacts[0].PortSCSIID; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44) - /* OS entry to allow host drivers to force - * a queue depth on a per device basis. - */ - sh->select_queue_depths = mptscsih_select_queue_depths; -#endif - /* Required entry. - */ - sh->unique_id = this->id; - - /* Verify that we won't exceed the maximum - * number of chain buffers - * We can optimize: ZZ = req_sz/sizeof(SGE) - * For 32bit SGE's: - * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ - * + (req_sz - 64)/sizeof(SGE) - * A slightly different algorithm is required for - * 64bit SGEs. - */ - scale = this->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); - if (sizeof(dma_addr_t) == sizeof(u64)) { - numSGE = (scale - 1) * (this->facts.MaxChainDepth-1) + scale + - (this->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32)); - } else { - numSGE = 1 + (scale - 1) * (this->facts.MaxChainDepth-1) + scale + - (this->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32)); - } - - if (numSGE < sh->sg_tablesize) { - /* Reset this value */ - dprintk((MYIOC_s_INFO_FMT - "Resetting sg_tablesize to %d from %d\n", - this->name, numSGE, sh->sg_tablesize)); - sh->sg_tablesize = numSGE; - } - - /* Set the pci device pointer in Scsi_Host structure. - */ - scsi_set_pci_device(sh, this->pcidev); - - spin_unlock_irqrestore(&this->FreeQlock, flags); - - hd = (MPT_SCSI_HOST *) sh->hostdata; - hd->ioc = this; - hd->max_sge = sh->sg_tablesize; - - if ((int)this->chip_type > (int)FC929) - hd->is_spi = 1; - - if (DmpService && - (this->chip_type == FC919 || this->chip_type == FC929)) - hd->is_multipath = 1; - - /* SCSI needs Scsi_Cmnd lookup table! - * (with size equal to req_depth*PtrSz!) - */ - sz = hd->ioc->req_depth * sizeof(void *); - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) - goto done; - - memset(mem, 0, sz); - hd->ScsiLookup = (struct scsi_cmnd **) mem; - - dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", - this->name, hd->ScsiLookup, sz)); - - if (mptscsih_initChainBuffers(hd, 1) < 0) - goto done; - - /* Allocate memory for free and doneQ's - */ - sz = sh->can_queue * sizeof(MPT_DONE_Q); - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) - goto done; - - memset(mem, 0xFF, sz); - hd->memQ = mem; - - /* Initialize the free, done and pending Qs. - */ - Q_INIT(&hd->freeQ, MPT_DONE_Q); - Q_INIT(&hd->doneQ, MPT_DONE_Q); - Q_INIT(&hd->pendingQ, MPT_DONE_Q); - spin_lock_init(&hd->freedoneQlock); - - mem = hd->memQ; - for (ii=0; ii < sh->can_queue; ii++) { - freedoneQ = (MPT_DONE_Q *) mem; - Q_ADD_TAIL(&hd->freeQ.head, freedoneQ, MPT_DONE_Q); - mem += sizeof(MPT_DONE_Q); - } - - /* Initialize this Scsi_Host - * internal task Q. - */ - Q_INIT(&hd->taskQ, MPT_FRAME_HDR); - hd->taskQcnt = 0; - - /* Allocate memory for the device structures. - * A non-Null pointer at an offset - * indicates a device exists. - * max_id = 1 + maximum id (hosts.h) - */ - sz = sh->max_id * sizeof(void *); - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) - goto done; - - memset(mem, 0, sz); - hd->Targets = (VirtDevice **) mem; - - dprintk((KERN_INFO " Targets @ %p, sz=%d\n", hd->Targets, sz)); - - - /* Clear the TM flags - */ - hd->tmPending = 0; -#ifdef MPT_SCSI_USE_NEW_EH - hd->tmState = TM_STATE_NONE; -#endif - hd->resetPending = 0; - hd->abortSCpnt = NULL; - hd->tmPtr = NULL; - hd->numTMrequests = 0; - - /* Clear the pointer used to store - * single-threaded commands, i.e., those - * issued during a bus scan, dv and - * configuration pages. - */ - hd->cmdPtr = NULL; - - /* Attach the SCSI Host to the IOC structure - */ - this->sh = sh; - - /* Initialize this SCSI Hosts' timers - * To use, set the timer expires field - * and add_timer - */ - init_timer(&hd->timer); - hd->timer.data = (unsigned long) hd; - hd->timer.function = mptscsih_timer_expired; - - init_timer(&hd->TMtimer); - hd->TMtimer.data = (unsigned long) hd; - hd->TMtimer.function = mptscsih_taskmgmt_timeout; - hd->qtag_tick = jiffies; - - /* Moved Earlier Pam D */ - /* this->sh = sh; */ - -#ifdef MPTSCSIH_DBG_TIMEOUT - hd->ioc->timeout_hard = 0; - hd->ioc->timeout_delta = 30 * HZ; - hd->ioc->timeout_maxcnt = 0; - hd->ioc->timeout_cnt = 0; - for (ii=0; ii < 8; ii++) - foo_to[ii] = NULL; -#endif - - if (hd->is_spi) { - /* Update with the driver setup - * values. - */ - if (hd->ioc->spi_data.maxBusWidth > driver_setup.max_width) - hd->ioc->spi_data.maxBusWidth = driver_setup.max_width; - if (hd->ioc->spi_data.minSyncFactor < driver_setup.min_sync_fac) - hd->ioc->spi_data.minSyncFactor = driver_setup.min_sync_fac; - - if (hd->ioc->spi_data.minSyncFactor == MPT_ASYNC) - hd->ioc->spi_data.maxSyncOffset = 0; - - hd->negoNvram = 0; -#ifdef MPTSCSIH_DISABLE_DOMAIN_VALIDATION - hd->negoNvram = MPT_SCSICFG_USE_NVRAM; -#endif - if (driver_setup.dv == 0) - hd->negoNvram = MPT_SCSICFG_USE_NVRAM; - - hd->ioc->spi_data.forceDv = 0; - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) - hd->ioc->spi_data.dvStatus[ii] = MPT_SCSICFG_NEGOTIATE; - - if (hd->negoNvram == 0) { - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) - hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_NOT_DONE; - } - - ddvprintk((MYIOC_s_INFO_FMT - "dv %x width %x factor %x \n", - hd->ioc->name, driver_setup.dv, - driver_setup.max_width, - driver_setup.min_sync_fac)); - } - - mpt_scsi_hosts++; - - } - else { - /* SAE: Nice to know if this is failing */ - printk(KERN_WARNING MYNAM ": failed scsi_register\n"); - } - - this = mpt_adapter_find_next(this); - } - -done: - if (mpt_scsi_hosts > 0) { -/* SAE: */ -#if XEN_KILLED - register_reboot_notifier(&mptscsih_notifier); -#endif - } - else { - mpt_reset_deregister(ScsiDoneCtx); - dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notifications\n")); - - mpt_event_deregister(ScsiDoneCtx); - dprintk((KERN_INFO MYNAM ": Deregistered for IOC event notifications\n")); - - mpt_deregister(ScsiScanDvCtx); - mpt_deregister(ScsiTaskCtx); - mpt_deregister(ScsiDoneCtx); - - if (info_kbuf != NULL) - kfree(info_kbuf); - } - - return mpt_scsi_hosts; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_release - Unregister SCSI host from linux scsi mid-layer - * @host: Pointer to Scsi_Host structure - * - * (linux Scsi_Host_Template.release routine) - * This routine releases all resources associated with the SCSI host - * adapter. - * - * Returns 0 for success. - */ -int -mptscsih_release(struct Scsi_Host *host) -{ - MPT_SCSI_HOST *hd; - int count; - unsigned long flags; - - hd = (MPT_SCSI_HOST *) host->hostdata; - -#ifndef MPT_SCSI_USE_NEW_EH -#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION - spin_lock_irqsave(&dvtaskQ_lock, flags); - dvtaskQ_release = 1; - spin_unlock_irqrestore(&dvtaskQ_lock, flags); -#endif - - count = 10 * HZ; - spin_lock_irqsave(&mytaskQ_lock, flags); - if (mytaskQ_bh_active) { - spin_unlock_irqrestore(&mytaskQ_lock, flags); - dprintk((KERN_INFO MYNAM ": Info: Zapping TaskMgmt thread!\n")); - clean_taskQ(hd); - - while(mytaskQ_bh_active && --count) { -/* SAE: */ -#ifdef XEN_KILLED - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); -#else - mdelay(1); -#endif - } - } else { - spin_unlock_irqrestore(&mytaskQ_lock, flags); - } - if (!count) - printk(KERN_ERR MYNAM ": ERROR - TaskMgmt thread still active!\n"); - -#endif - -#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION - /* Check DV thread active */ - count = 10 * HZ; - spin_lock_irqsave(&dvtaskQ_lock, flags); - if (dvtaskQ_active) { - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - while(dvtaskQ_active && --count) { -/* SAE: */ -#ifdef XEN_KILLED - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); -#else - mdelay(1); -#endif - } - } else { - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - } - if (!count) - printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n"); -#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) - else - printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count); -#endif -#endif - -/* SAE: */ -#if XEN_KILLED - unregister_reboot_notifier(&mptscsih_notifier); -#endif - - if (hd != NULL) { - int sz1, sz2, sz3, sztarget=0; - int szr2chain = 0; - int szc2chain = 0; - int szchain = 0; - int szQ = 0; - - /* Synchronize disk caches - */ - (void) mptscsih_synchronize_cache(hd, 0); - - sz1 = sz2 = sz3 = 0; - - if (hd->ScsiLookup != NULL) { - sz1 = hd->ioc->req_depth * sizeof(void *); - kfree(hd->ScsiLookup); - hd->ScsiLookup = NULL; - } - - if (hd->ReqToChain != NULL) { - szr2chain = hd->ioc->req_depth * sizeof(int); - kfree(hd->ReqToChain); - hd->ReqToChain = NULL; - } - - if (hd->ChainToChain != NULL) { - szc2chain = hd->num_chain * sizeof(int); - kfree(hd->ChainToChain); - hd->ChainToChain = NULL; - } - - if (hd->ChainBuffer != NULL) { - sz2 = hd->num_chain * hd->ioc->req_sz; - szchain = szr2chain + szc2chain + sz2; - - pci_free_consistent(hd->ioc->pcidev, sz2, - hd->ChainBuffer, hd->ChainBufferDMA); - hd->ChainBuffer = NULL; - } - - if (hd->memQ != NULL) { - szQ = host->can_queue * sizeof(MPT_DONE_Q); - kfree(hd->memQ); - hd->memQ = NULL; - } - - if (hd->Targets != NULL) { - int max, ii; - - /* - * Free any target structures that were allocated. - */ - if (hd->is_spi) { - max = MPT_MAX_SCSI_DEVICES; - } else { - max = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255; - } - for (ii=0; ii < max; ii++) { - if (hd->Targets[ii]) { - kfree(hd->Targets[ii]); - hd->Targets[ii] = NULL; - sztarget += sizeof(VirtDevice); - } - } - - /* - * Free pointer array. - */ - sz3 = max * sizeof(void *); - kfree(hd->Targets); - hd->Targets = NULL; - } - - dprintk((MYIOC_s_INFO_FMT "Free'd ScsiLookup (%d), chain (%d) and Target (%d+%d) memory\n", - hd->ioc->name, sz1, szchain, sz3, sztarget)); - dprintk(("Free'd done and free Q (%d) memory\n", szQ)); - } - /* NULL the Scsi_Host pointer - */ - hd->ioc->sh = NULL; - scsi_unregister(host); - - if (mpt_scsi_hosts) { - if (--mpt_scsi_hosts == 0) { - mpt_reset_deregister(ScsiDoneCtx); - dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notifications\n")); - - mpt_event_deregister(ScsiDoneCtx); - dprintk((KERN_INFO MYNAM ": Deregistered for IOC event notifications\n")); - - mpt_deregister(ScsiScanDvCtx); - mpt_deregister(ScsiTaskCtx); - mpt_deregister(ScsiDoneCtx); - - if (info_kbuf != NULL) - kfree(info_kbuf); - } - } - - return 0; -} - -#if 0 /* XEN */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_halt - Process the reboot notification - * @nb: Pointer to a struct notifier_block (ignored) - * @event: event (SYS_HALT, SYS_RESTART, SYS_POWER_OFF) - * @buf: Pointer to a data buffer (ignored) - * - * This routine called if a system shutdown or reboot is to occur. - * - * Return NOTIFY_DONE if this is something other than a reboot message. - * NOTIFY_OK if this is a reboot message. - */ -static int -mptscsih_halt(struct notifier_block *nb, ulong event, void *buf) -{ - MPT_ADAPTER *ioc = NULL; - MPT_SCSI_HOST *hd = NULL; - - /* Ignore all messages other than reboot message - */ - if ((event != SYS_RESTART) && (event != SYS_HALT) - && (event != SYS_POWER_OFF)) - return (NOTIFY_DONE); - - for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) { - /* Flush the cache of this adapter - */ - if (ioc->sh) { - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - if (hd) { - mptscsih_synchronize_cache(hd, 0); - } - } - } - -/* SAE: Gone */ -#if XEN_KILLED - unregister_reboot_notifier(&mptscsih_notifier); -#endif - return NOTIFY_OK; -} -#endif /* 0 (XEN) */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_info - Return information about MPT adapter - * @SChost: Pointer to Scsi_Host structure - * - * (linux Scsi_Host_Template.info routine) - * - * Returns pointer to buffer where information was written. - */ -const char * -mptscsih_info(struct Scsi_Host *SChost) -{ - MPT_SCSI_HOST *h = NULL; - int size = 0; - - if (info_kbuf == NULL) - if ((info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL) - return info_kbuf; - - h = (MPT_SCSI_HOST *)SChost->hostdata; - info_kbuf[0] = '\0'; - if (h) { - mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0); - info_kbuf[size-1] = '\0'; - } - - return info_kbuf; -} - -struct info_str { - char *buffer; - int length; - int offset; - int pos; -}; - -#if 0 /* XEN */ -static void copy_mem_info(struct info_str *info, char *data, int len) -{ - if (info->pos + len > info->length) - len = info->length - info->pos; - - if (info->pos + len < info->offset) { - info->pos += len; - return; - } - - if (info->pos < info->offset) { - data += (info->offset - info->pos); - len -= (info->offset - info->pos); - } - - if (len > 0) { - memcpy(info->buffer + info->pos, data, len); - info->pos += len; - } -} - -static int copy_info(struct info_str *info, char *fmt, ...) -{ - va_list args; - char buf[81]; - int len; - - va_start(args, fmt); - len = vsprintf(buf, fmt, args); - va_end(args); - - copy_mem_info(info, buf, len); - return len; -} -#endif /* 0 (XEN) */ - -/* SAE: For some reason off_t is not in any of the types.. */ -#ifndef off_t -#define off_t int -#endif - -#if 0 /* XEN */ -static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len) -{ - struct info_str info; - - info.buffer = pbuf; - info.length = len; - info.offset = offset; - info.pos = 0; - - copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name); - copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word); - copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts); - copy_info(&info, "MaxQ=%d\n", ioc->req_depth); - - return ((info.pos > info.offset) ? info.pos - info.offset : 0); -} -#endif /* 0 (XEN) */ - -#ifndef MPTSCSIH_DBG_TIMEOUT -#if 0 /* XEN */ -static int mptscsih_user_command(MPT_ADAPTER *ioc, char *pbuf, int len) -{ - /* Not yet implemented */ - return len; -} -#endif /* 0 (XEN) */ -#else -#define is_digit(c) ((c) >= '0' && (c) <= '9') -#define digit_to_bin(c) ((c) - '0') -#define is_space(c) ((c) == ' ' || (c) == '\t') - -#define UC_DBG_TIMEOUT 0x01 -#define UC_DBG_HARDRESET 0x02 - -static int skip_spaces(char *ptr, int len) -{ - int cnt, c; - - for (cnt = len; cnt > 0 && (c = *ptr++) && is_space(c); cnt --); - - return (len - cnt); -} - -static int get_int_arg(char *ptr, int len, ulong *pv) -{ - int cnt, c; - ulong v; - for (v = 0, cnt = len; cnt > 0 && (c=*ptr++) && is_digit(c); cnt --) { - v = (v * 10) + digit_to_bin(c); - } - - if (pv) - *pv = v; - - return (len - cnt); -} - - -static int is_keyword(char *ptr, int len, char *verb) -{ - int verb_len = strlen(verb); - - if (len >= strlen(verb) && !memcmp(verb, ptr, verb_len)) - return verb_len; - else - return 0; -} - -#define SKIP_SPACES(min_spaces) \ - if ((arg_len = skip_spaces(ptr,len)) < (min_spaces)) \ - return -EINVAL; \ - ptr += arg_len; \ - len -= arg_len; - -#define GET_INT_ARG(v) \ - if (!(arg_len = get_int_arg(ptr,len, &(v)))) \ - return -EINVAL; \ - ptr += arg_len; \ - len -= arg_len; - -static int mptscsih_user_command(MPT_ADAPTER *ioc, char *buffer, int length) -{ - char *ptr = buffer; - char btmp[24]; /* REMOVE */ - int arg_len; - int len = length; - int cmd; - ulong number = 1; - ulong delta = 10; - - if ((len > 0) && (ptr[len -1] == '\n')) - --len; - - if (len < 22) { - strncpy(btmp, buffer, len); - btmp[len+1]='\0'; - } else { - strncpy(btmp, buffer, 22); - btmp[23]='\0'; - } - printk("user_command: ioc %d, buffer %s, length %d\n", - ioc->id, btmp, length); - - if ((arg_len = is_keyword(ptr, len, "timeout")) != 0) - cmd = UC_DBG_TIMEOUT; - else if ((arg_len = is_keyword(ptr, len, "hardreset")) != 0) - cmd = UC_DBG_HARDRESET; - else - return -EINVAL; - - ptr += arg_len; - len -= arg_len; - - switch(cmd) { - case UC_DBG_TIMEOUT: - SKIP_SPACES(1); - GET_INT_ARG(number); - SKIP_SPACES(1); - GET_INT_ARG(delta); - break; - } - - printk("user_command: cnt=%ld delta=%ld\n", number, delta); - - if (len) - return -EINVAL; - else { - if (cmd == UC_DBG_HARDRESET) { - ioc->timeout_hard = 1; - } else if (cmd == UC_DBG_TIMEOUT) { - /* process this command ... - */ - ioc->timeout_maxcnt = 0; - ioc->timeout_delta = delta < 2 ? 2 : delta; - ioc->timeout_cnt = 0; - ioc->timeout_maxcnt = number < 8 ? number: 8; - } - } - /* Not yet implemented */ - return length; -} -#endif - -/* SAE: No proc */ -#if defined(CONFIG_PROC_FS) - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_proc_info - Return information about MPT adapter - * - * (linux Scsi_Host_Template.info routine) - * - * buffer: if write, user data; if read, buffer for user - * length: if write, return length; - * offset: if write, 0; if read, the current offset into the buffer from - * the previous read. - * hostno: scsi host number - * func: if write = 1; if read = 0 - */ -int mptscsih_proc_info(char *buffer, char **start, off_t offset, - int length, int hostno, int func) -{ - MPT_ADAPTER *ioc = NULL; - MPT_SCSI_HOST *hd = NULL; - int size = 0; - - dprintk(("Called mptscsih_proc_info: hostno=%d, func=%d\n", hostno, func)); - dprintk(("buffer %p, start=%p (%p) offset=%ld length = %d\n", - buffer, start, *start, offset, length)); - - for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) { - if ((ioc->sh) && (ioc->sh->host_no == hostno)) { - hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; - break; - } - } - if ((ioc == NULL) || (ioc->sh == NULL) || (hd == NULL)) - return 0; - - if (func) { - size = mptscsih_user_command(ioc, buffer, length); - } else { - if (start) - *start = buffer; - - size = mptscsih_host_info(ioc, buffer, offset, length); - } - - return size; -} - -#endif /* SAE: CONFIG_PROC_FS */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - static int max_qd = 1; -#if 0 -static int index_log[128]; -static int index_ent = 0; -static __inline__ void ADD_INDEX_LOG(int req_ent) -{ - int i = index_ent++; - - index_log[i & (128 - 1)] = req_ent; -} -#else -#define ADD_INDEX_LOG(req_ent) do { } while(0) -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_put_msgframe - Wrapper routine to post message frame to F/W. - * @context: Call back context (ScsiDoneCtx, ScsiScanDvCtx) - * @id: IOC id number - * @mf: Pointer to message frame - * - * Handles the call to mptbase for posting request and queue depth - * tracking. - * - * Returns none. - */ -static inline void -mptscsih_put_msgframe(int context, int id, MPT_FRAME_HDR *mf) -{ - /* Main banana... */ - atomic_inc(&queue_depth); - if (atomic_read(&queue_depth) > max_qd) { - max_qd = atomic_read(&queue_depth); - dprintk((KERN_INFO MYNAM ": Queue depth now %d.\n", max_qd)); - } - - mpt_put_msg_frame(context, id, mf); - - return; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine. - * @SCpnt: Pointer to Scsi_Cmnd structure - * @done: Pointer SCSI mid-layer IO completion function - * - * (linux Scsi_Host_Template.queuecommand routine) - * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest - * from a linux Scsi_Cmnd request and send it to the IOC. - * - * Returns 0. (rtn value discarded by linux scsi mid-layer) - */ -int -mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) -{ - MPT_SCSI_HOST *hd; - MPT_FRAME_HDR *mf; - SCSIIORequest_t *pScsiReq; - VirtDevice *pTarget; - MPT_DONE_Q *buffer = NULL; - unsigned long flags; - int target; - int lun; - int datadir; - u32 datalen; - u32 scsictl; - u32 scsidir; - u32 cmd_len; - int my_idx; - int ii; - int rc; - int did_errcode; - int issueCmd; - - did_errcode = 0; - hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata; - target = SCpnt->target; - lun = SCpnt->lun; - SCpnt->scsi_done = done; - - pTarget = hd->Targets[target]; - - dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n", - (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done)); - - if (hd->resetPending) { - /* Prevent new commands from being issued - * while reloading the FW. Reset timer to 60 seconds, - * as the FW can take some time to come ready. - * For New EH, cmds on doneQ posted to FW. - */ - did_errcode = 1; - mod_timer(&SCpnt->eh_timeout, jiffies + (HZ * 60)); - dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n", - (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt)); - goto did_error; - } - - /* - * Put together a MPT SCSI request... - */ - if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc->id)) == NULL) { - dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n", - hd->ioc->name)); - did_errcode = 2; - goto did_error; - } - - pScsiReq = (SCSIIORequest_t *) mf; - - my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); - - ADD_INDEX_LOG(my_idx); - - /* - * The scsi layer should be handling this stuff - * (In 2.3.x it does -DaveM) - */ - - /* BUG FIX! 19991030 -sralston - * TUR's being issued with scsictl=0x02000000 (DATA_IN)! - * Seems we may receive a buffer (datalen>0) even when there - * will be no data transfer! GRRRRR... - */ - datadir = mptscsih_io_direction(SCpnt); - if (datadir == SCSI_DATA_READ) { - datalen = SCpnt->request_bufflen; - scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */ - } else if (datadir == SCSI_DATA_WRITE) { - datalen = SCpnt->request_bufflen; - scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */ - } else { - datalen = 0; - scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER; - } - - /* Default to untagged. Once a target structure has been allocated, - * use the Inquiry data to determine if device supports tagged. - */ - if ( pTarget - && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES) - && (SCpnt->device->tagged_supported)) { - scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ; - } else { - scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED; - } - - /* Use the above information to set up the message frame - */ - pScsiReq->TargetID = (u8) target; - pScsiReq->Bus = (u8) SCpnt->channel; - pScsiReq->ChainOffset = 0; - pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; - pScsiReq->CDBLength = SCpnt->cmd_len; - pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; - pScsiReq->Reserved = 0; - pScsiReq->MsgFlags = mpt_msg_flags(); - pScsiReq->LUN[0] = 0; - pScsiReq->LUN[1] = lun; - pScsiReq->LUN[2] = 0; - pScsiReq->LUN[3] = 0; - pScsiReq->LUN[4] = 0; - pScsiReq->LUN[5] = 0; - pScsiReq->LUN[6] = 0; - pScsiReq->LUN[7] = 0; - pScsiReq->Control = cpu_to_le32(scsictl); - - /* - * Write SCSI CDB into the message - * Should write from cmd_len up to 16, but skip for performance reasons. - */ - cmd_len = SCpnt->cmd_len; - for (ii=0; ii < cmd_len; ii++) - pScsiReq->CDB[ii] = SCpnt->cmnd[ii]; - - for (ii=cmd_len; ii < 16; ii++) - pScsiReq->CDB[ii] = 0; - - /* DataLength */ - pScsiReq->DataLength = cpu_to_le32(datalen); - - /* SenseBuffer low address */ - pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma - + (my_idx * MPT_SENSE_BUFFER_ALLOC)); - - /* Now add the SG list - * Always have a SGE even if null length. - */ - rc = SUCCESS; - if (datalen == 0) { - /* Add a NULL SGE */ - mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0, - (dma_addr_t) -1); - } else { - /* Add a 32 or 64 bit SGE */ - rc = mptscsih_AddSGE(hd, SCpnt, pScsiReq, my_idx); - } - - - if (rc == SUCCESS) { - hd->ScsiLookup[my_idx] = SCpnt; - SCpnt->host_scribble = NULL; - - /* SCSI specific processing */ - issueCmd = 1; - if (hd->is_spi) { - int dvStatus = hd->ioc->spi_data.dvStatus[target]; - - if (dvStatus || hd->ioc->spi_data.forceDv) { - - /* Write SDP1 on this I/O to this target */ - if (dvStatus & MPT_SCSICFG_NEGOTIATE) { - mptscsih_writeSDP1(hd, 0, target, hd->negoNvram); - dvStatus &= ~MPT_SCSICFG_NEGOTIATE; - hd->ioc->spi_data.dvStatus[target] = dvStatus; - } else if (dvStatus & MPT_SCSICFG_BLK_NEGO) { - mptscsih_writeSDP1(hd, 0, target, MPT_SCSICFG_BLK_NEGO); - dvStatus &= ~MPT_SCSICFG_BLK_NEGO; - hd->ioc->spi_data.dvStatus[target] = dvStatus; - } - -#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION - if ((dvStatus & MPT_SCSICFG_NEED_DV) || - (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) { - unsigned long lflags; - /* Schedule DV if necessary */ - spin_lock_irqsave(&dvtaskQ_lock, lflags); - if (!dvtaskQ_active) { - dvtaskQ_active = 1; - spin_unlock_irqrestore(&dvtaskQ_lock, lflags); - MPT_INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd); - - SCHEDULE_TASK(&mptscsih_dvTask); - } else { - spin_unlock_irqrestore(&dvtaskQ_lock, lflags); - } - hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV; - } - - /* Trying to do DV to this target, extend timeout. - * Wait to issue intil flag is clear - */ - if (dvStatus & MPT_SCSICFG_DV_PENDING) { - mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ); - issueCmd = 0; - } - - /* Set the DV flags. - */ - if (dvStatus & MPT_SCSICFG_DV_NOT_DONE) - mptscsih_set_dvflags(hd, pScsiReq); -#endif - } - } - -#ifdef MPTSCSIH_DBG_TIMEOUT - if (hd->ioc->timeout_cnt < hd->ioc->timeout_maxcnt) { - foo_to[hd->ioc->timeout_cnt] = SCpnt; - hd->ioc->timeout_cnt++; - //mod_timer(&SCpnt->eh_timeout, jiffies + hd->ioc->timeout_delta); - issueCmd = 0; - printk(MYIOC_s_WARN_FMT - "to pendingQ: (sc=%p, mf=%p, time=%ld)\n", - hd->ioc->name, SCpnt, mf, jiffies); - } -#endif - - if (issueCmd) { - mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf); - dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", - hd->ioc->name, SCpnt, mf, my_idx)); - } else { - ddvtprintk((MYIOC_s_INFO_FMT "Pending cmd=%p idx %d\n", - hd->ioc->name, SCpnt, my_idx)); - /* Place this command on the pendingQ if possible */ - spin_lock_irqsave(&hd->freedoneQlock, flags); - if (!Q_IS_EMPTY(&hd->freeQ)) { - buffer = hd->freeQ.head; - Q_DEL_ITEM(buffer); - - /* Save the mf pointer - */ - buffer->argp = (void *)mf; - - /* Add to the pendingQ - */ - Q_ADD_TAIL(&hd->pendingQ.head, buffer, MPT_DONE_Q); - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - } else { - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - SCpnt->result = (DID_BUS_BUSY << 16); - SCpnt->scsi_done(SCpnt); - } - } - } else { - mptscsih_freeChainBuffers(hd, my_idx); - mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf); - did_errcode = 3; - goto did_error; - } - - return 0; - -did_error: - dprintk((MYIOC_s_WARN_FMT "_qcmd did_errcode=%d (sc=%p)\n", - hd->ioc->name, did_errcode, SCpnt)); - /* Just wish OS to issue a retry */ - SCpnt->result = (DID_BUS_BUSY << 16); - spin_lock_irqsave(&hd->freedoneQlock, flags); - if (!Q_IS_EMPTY(&hd->freeQ)) { - dtmprintk((MYIOC_s_WARN_FMT "SCpnt=%p to doneQ\n", - (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt)); - buffer = hd->freeQ.head; - Q_DEL_ITEM(buffer); - - /* Set the Scsi_Cmnd pointer - */ - buffer->argp = (void *)SCpnt; - - /* Add to the doneQ - */ - Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q); - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - } else { - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - SCpnt->scsi_done(SCpnt); - } - - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_freeChainBuffers - Function to free chain buffers associated - * with a SCSI IO request - * @hd: Pointer to the MPT_SCSI_HOST instance - * @req_idx: Index of the SCSI IO request frame. - * - * Called if SG chain buffer allocation fails and mptscsih callbacks. - * No return. - */ -static void -mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx) -{ - MPT_FRAME_HDR *chain = NULL; - unsigned long flags; - int chain_idx; - int next; - - /* Get the first chain index and reset - * tracker state. - */ - chain_idx = hd->ReqToChain[req_idx]; - hd->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN; - - while (chain_idx != MPT_HOST_NO_CHAIN) { - - /* Save the next chain buffer index */ - next = hd->ChainToChain[chain_idx]; - - /* Free this chain buffer and reset - * tracker - */ - hd->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN; - - chain = (MPT_FRAME_HDR *) (hd->ChainBuffer - + (chain_idx * hd->ioc->req_sz)); - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - Q_ADD_TAIL(&hd->FreeChainQ.head, - &chain->u.frame.linkage, MPT_FRAME_HDR); - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - - dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n", - hd->ioc->name, chain_idx)); - - /* handle next */ - chain_idx = next; - } - return; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Reset Handling - */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_TMHandler - Generic handler for SCSI Task Management. - * Fall through to mpt_HardResetHandler if: not operational, too many - * failed TM requests or handshake failure. - * - * @ioc: Pointer to MPT_ADAPTER structure - * @type: Task Management type - * @target: Logical Target ID for reset (if appropriate) - * @lun: Logical Unit for reset (if appropriate) - * @ctx2abort: Context for the task to be aborted (if appropriate) - * @sleepFlag: If set, use udelay instead of schedule in handshake code. - * - * Remark: Currently invoked from a non-interrupt thread (_bh). - * - * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC - * will be active. - * - * Returns 0 for SUCCESS or -1 if FAILED. - */ -static int -mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, int sleepFlag) -{ - MPT_ADAPTER *ioc = NULL; - int rc = -1; - int doTask = 1; - u32 ioc_raw_state; - unsigned long flags; - - /* If FW is being reloaded currently, return success to - * the calling function. - */ - if (hd == NULL) - return 0; - - ioc = hd->ioc; - if (ioc == NULL) { - printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n"); - return FAILED; - } - dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name)); - - // SJR - CHECKME - Can we avoid this here? - // (mpt_HardResetHandler has this check...) - spin_lock_irqsave(&ioc->diagLock, flags); - if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) { - spin_unlock_irqrestore(&ioc->diagLock, flags); - return FAILED; - } - spin_unlock_irqrestore(&ioc->diagLock, flags); - - /* Do not do a Task Management if there are - * too many failed TMs on this adapter. - */ - if (hd->numTMrequests > MPT_HOST_TOO_MANY_TM) - doTask = 0; - -#ifdef MPT_SCSI_USE_NEW_EH - /* Wait a fixed amount of time for the TM pending flag to be cleared. - * If we time out and not bus reset, then we return a FAILED status to the caller. - * The call to mptscsih_tm_pending_wait() will set the pending flag if we are - * successful. Otherwise, reload the FW. - */ - if (mptscsih_tm_pending_wait(hd) == FAILED) { - if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { - nehprintk((KERN_WARNING MYNAM ": %s: TMHandler abort: " - "Timed out waiting for last TM (%d) to complete! \n", - hd->ioc->name, hd->tmPending)); - return FAILED; - } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { - nehprintk((KERN_WARNING MYNAM ": %s: TMHandler target reset: " - "Timed out waiting for last TM (%d) to complete! \n", - hd->ioc->name, hd->tmPending)); - return FAILED; - } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { - nehprintk((KERN_WARNING MYNAM ": %s: TMHandler bus reset: " - "Timed out waiting for last TM (%d) to complete! \n", - hd->ioc->name, hd->tmPending)); - if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)) - return FAILED; - - doTask = 0; - } - } else { - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - hd->tmPending |= (1 << type); - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - } -#endif - - /* Is operational? - */ - ioc_raw_state = mpt_GetIocState(hd->ioc, 0); - -#ifdef MPT_DEBUG_RESET - if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { - printk(MYIOC_s_WARN_FMT - "TM Handler: IOC Not operational(0x%x)!\n", - hd->ioc->name, ioc_raw_state); - } -#endif - - if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) - && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) { - - /* Isse the Task Mgmt request. - */ - if (hd->hard_resets < -1) - hd->hard_resets++; - rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, sleepFlag); - if (rc) { - printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name); - } else { - dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name)); - } - } -#ifdef MPTSCSIH_DBG_TIMEOUT - if (hd->ioc->timeout_hard) - rc = 1; -#endif - - /* Only fall through to the HRH if this is a bus reset - */ - if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc || - ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) { - dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", - hd->ioc->name)); - rc = mpt_HardResetHandler(hd->ioc, sleepFlag); - } - - dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc)); -#ifndef MPT_SCSI_USE_NEW_EH - dtmprintk((MYIOC_s_INFO_FMT "TMHandler: _bh_handler state (%d) taskQ count (%d)\n", - ioc->name, mytaskQ_bh_active, hd->taskQcnt)); -#endif - - return rc; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_IssueTaskMgmt - Generic send Task Management function. - * @hd: Pointer to MPT_SCSI_HOST structure - * @type: Task Management type - * @target: Logical Target ID for reset (if appropriate) - * @lun: Logical Unit for reset (if appropriate) - * @ctx2abort: Context for the task to be aborted (if appropriate) - * @sleepFlag: If set, use udelay instead of schedule in handshake code. - * - * Remark: _HardResetHandler can be invoked from an interrupt thread (timer) - * or a non-interrupt thread. In the former, must not call schedule(). - * - * Not all fields are meaningfull for all task types. - * - * Returns 0 for SUCCESS, -999 for "no msg frames", - * else other non-zero value returned. - */ -static int -mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, int sleepFlag) -{ - MPT_FRAME_HDR *mf; - SCSITaskMgmt_t *pScsiTm; - int ii; - int retval; - - /* Return Fail to calling function if no message frames available. - */ - if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) { - dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n", - hd->ioc->name)); - //return FAILED; - return -999; - } - dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n", - hd->ioc->name, mf)); - - /* Format the Request - */ - pScsiTm = (SCSITaskMgmt_t *) mf; - pScsiTm->TargetID = target; - pScsiTm->Bus = channel; - pScsiTm->ChainOffset = 0; - pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; - - pScsiTm->Reserved = 0; - pScsiTm->TaskType = type; - pScsiTm->Reserved1 = 0; - pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) - ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0; - - for (ii= 0; ii < 8; ii++) { - pScsiTm->LUN[ii] = 0; - } - pScsiTm->LUN[1] = lun; - - for (ii=0; ii < 7; ii++) - pScsiTm->Reserved2[ii] = 0; - - pScsiTm->TaskMsgContext = ctx2abort; - dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt, ctx2abort (0x%08x), type (%d)\n", - hd->ioc->name, ctx2abort, type)); - - /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake - mpt_put_msg_frame(hd->ioc->id, mf); - * Save the MF pointer in case the request times out. - */ - hd->tmPtr = mf; - hd->numTMrequests++; - hd->TMtimer.expires = jiffies + HZ*20; /* 20 seconds */ - add_timer(&hd->TMtimer); - - if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, - sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, sleepFlag)) - != 0) { - dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!" - " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf)); - hd->numTMrequests--; - hd->tmPtr = NULL; - del_timer(&hd->TMtimer); - mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf); - } - - return retval; -} - -#ifdef MPT_SCSI_USE_NEW_EH /* { */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_abort - Abort linux Scsi_Cmnd routine, new_eh variant - * @SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted - * - * (linux Scsi_Host_Template.eh_abort_handler routine) - * - * Returns SUCCESS or FAILED. - */ -int -mptscsih_abort(Scsi_Cmnd * SCpnt) -{ - MPT_SCSI_HOST *hd; - MPT_FRAME_HDR *mf; - u32 ctx2abort; - int scpnt_idx; - - /* If we can't locate our host adapter structure, return FAILED status. - */ - if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) { - SCpnt->result = DID_RESET << 16; - SCpnt->scsi_done(SCpnt); - nehprintk((KERN_WARNING MYNAM ": mptscsih_abort: " - "Can't locate host! (sc=%p)\n", - SCpnt)); - return FAILED; - } - - if (hd->resetPending) - return FAILED; - - printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p, numIOs=%d)\n", - hd->ioc->name, SCpnt, atomic_read(&queue_depth)); - - if (hd->timeouts < -1) - hd->timeouts++; - - /* Find this command - */ - if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { - /* Cmd not found in ScsiLookup. If found in - * doneQ, delete from Q. Do OS callback. - */ - search_doneQ_for_cmd(hd, SCpnt); - - SCpnt->result = DID_RESET << 16; - SCpnt->scsi_done(SCpnt); - nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " - "Command not in the active list! (sc=%p)\n", - hd->ioc->name, SCpnt)); - return SUCCESS; - } - - /* If this command is pended, then timeout/hang occurred - * during DV. Post command and flush pending Q - * and then following up with the reset request. - */ - if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) { - mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf); - post_pendingQ_commands(hd); - nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " - "Posting pended cmd! (sc=%p)\n", - hd->ioc->name, SCpnt)); - } - - /* Most important! Set TaskMsgContext to SCpnt's MsgContext! - * (the IO to be ABORT'd) - * - * NOTE: Since we do not byteswap MsgContext, we do not - * swap it here either. It is an opaque cookie to - * the controller, so it does not matter. -DaveM - */ - mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx); - ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext; - - hd->abortSCpnt = SCpnt; - if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, - SCpnt->channel, SCpnt->target, SCpnt->lun, ctx2abort, NO_SLEEP) - < 0) { - - /* The TM request failed and the subsequent FW-reload failed! - * Fatal error case. - */ - printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n", - hd->ioc->name, SCpnt); - - /* We must clear our pending flag before clearing our state. - */ - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - - return FAILED; - } - return FAILED; - -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant - * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to - * - * (linux Scsi_Host_Template.eh_dev_reset_handler routine) - * - * Returns SUCCESS or FAILED. - */ -int -mptscsih_dev_reset(Scsi_Cmnd * SCpnt) -{ - MPT_SCSI_HOST *hd; - - /* If we can't locate our host adapter structure, return FAILED status. - */ - if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL){ - nehprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: " - "Can't locate host! (sc=%p)\n", - SCpnt)); - return FAILED; - } - - if (hd->resetPending) - return FAILED; - - printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p, numIOs=%d)\n", - hd->ioc->name, SCpnt, atomic_read(&queue_depth)); - - /* Unsupported for SCSI. Supported for FCP - */ - if (hd->is_spi) - return FAILED; - - if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, - SCpnt->channel, SCpnt->target, 0, 0, NO_SLEEP) - < 0){ - /* The TM request failed and the subsequent FW-reload failed! - * Fatal error case. - */ - printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n", - hd->ioc->name, SCpnt); - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - return FAILED; - } - return SUCCESS; - -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant - * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to - * - * (linux Scsi_Host_Template.eh_bus_reset_handler routine) - * - * Returns SUCCESS or FAILED. - */ -int -mptscsih_bus_reset(Scsi_Cmnd * SCpnt) -{ - MPT_SCSI_HOST *hd; - - /* If we can't locate our host adapter structure, return FAILED status. - */ - if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL){ - nehprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: " - "Can't locate host! (sc=%p)\n", - SCpnt ) ); - return FAILED; - } - - printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p, numIOs=%d)\n", - hd->ioc->name, SCpnt, atomic_read(&queue_depth)); - - if (hd->timeouts < -1) - hd->timeouts++; - - /* We are now ready to execute the task management request. */ - if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - SCpnt->channel, 0, 0, 0, NO_SLEEP) - < 0){ - - /* The TM request failed and the subsequent FW-reload failed! - * Fatal error case. - */ - printk(MYIOC_s_WARN_FMT - "Error processing TaskMgmt request (sc=%p)\n", - hd->ioc->name, SCpnt); - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - return FAILED; - } - - return SUCCESS; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_host_reset - Perform a SCSI host adapter RESET! - * new_eh variant - * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to - * - * (linux Scsi_Host_Template.eh_host_reset_handler routine) - * - * Returns SUCCESS or FAILED. - */ -int -mptscsih_host_reset(Scsi_Cmnd *SCpnt) -{ - MPT_SCSI_HOST * hd; - int status = SUCCESS; - - /* If we can't locate the host to reset, then we failed. */ - if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL){ - nehprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: " - "Can't locate host! (sc=%p)\n", - SCpnt ) ); - return FAILED; - } - - printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n", - hd->ioc->name, SCpnt); - printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n", - hd->ioc->name, atomic_read(&queue_depth)); - - /* If our attempts to reset the host failed, then return a failed - * status. The host will be taken off line by the SCSI mid-layer. - */ - if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0){ - status = FAILED; - } else { - /* Make sure TM pending is cleared and TM state is set to - * NONE. - */ - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - } - - - nehprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: " - "Status = %s\n", - (status == SUCCESS) ? "SUCCESS" : "FAILED" ) ); - - return status; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_tm_pending_wait - wait for pending task management request to - * complete. - * @hd: Pointer to MPT host structure. - * - * Returns {SUCCESS,FAILED}. - */ -static int -mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd) -{ - unsigned long flags; - int loop_count = 2 * 10 * 4; /* Wait 2 seconds */ - int status = FAILED; - - do { - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - if (hd->tmState == TM_STATE_NONE) { - hd->tmState = TM_STATE_IN_PROGRESS; - hd->tmPending = 1; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - status = SUCCESS; - break; - } - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - //set_current_state(TASK_INTERRUPTIBLE); - //schedule_timeout(HZ/4); - mdelay(250); - } while (--loop_count); - - return status; -} - -#else /* MPT_SCSI old EH stuff... */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_old_abort - Abort linux Scsi_Cmnd routine - * @SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted - * - * (linux Scsi_Host_Template.abort routine) - * - * Returns SCSI_ABORT_{SUCCESS,BUSY,PENDING}. - */ -int -mptscsih_old_abort(Scsi_Cmnd *SCpnt) -{ - MPT_SCSI_HOST *hd; - MPT_FRAME_HDR *mf; - struct mpt_work_struct *ptaskfoo; - unsigned long flags; - int scpnt_idx; - - printk(KERN_WARNING MYNAM ": OldAbort scheduling ABORT SCSI IO (sc=%p)\n", (void *) SCpnt); - printk(KERN_WARNING " IOs outstanding = %d\n", atomic_read(&queue_depth)); - - if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) { - printk(KERN_WARNING " WARNING - OldAbort, NULL hostdata ptr!!\n"); - SCpnt->result = DID_ERROR << 16; - SCpnt->scsi_done(SCpnt); - return SCSI_ABORT_NOT_RUNNING; - } - - if (hd->timeouts < -1) - hd->timeouts++; - - if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { - /* Cmd not found in ScsiLookup. - * If found in doneQ, delete from Q. - * Do OS callback. - */ - search_doneQ_for_cmd(hd, SCpnt); - - SCpnt->result = DID_RESET << 16; - SCpnt->scsi_done(SCpnt); - return SCSI_ABORT_SUCCESS; - } else { - /* If this command is pended, then timeout/hang occurred - * during DV. Force bus reset by posting command to F/W - * and then following up with the reset request. - */ - if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) { - mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf); - post_pendingQ_commands(hd); - } - } - - /* - * Check to see if there's already an ABORT queued for this guy. - */ - mf = search_taskQ(0, SCpnt, hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK); - if (mf != NULL) { - dtmprintk((MYIOC_s_INFO_FMT "OldAbort:Abort Task PENDING cmd (%p) taskQ depth (%d)\n", - hd->ioc->name, SCpnt, hd->taskQcnt)); - return SCSI_ABORT_PENDING; - } - - // SJR - CHECKME - Can we avoid this here? - // (mpt_HardResetHandler has this check...) - /* If IOC is reloading FW, return PENDING. - */ - spin_lock_irqsave(&hd->ioc->diagLock, flags); - if (hd->ioc->diagPending) { - spin_unlock_irqrestore(&hd->ioc->diagLock, flags); - return SCSI_ABORT_PENDING; - } - spin_unlock_irqrestore(&hd->ioc->diagLock, flags); - - /* If there are no message frames what should we do? - */ - if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) { - printk((KERN_WARNING " WARNING - OldAbort, no msg frames!!\n")); - /* We are out of message frames! - * Call the reset handler to do a FW reload. - */ - printk((KERN_WARNING " Reloading Firmware!!\n")); - if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) { - printk((KERN_WARNING " Firmware Reload FAILED!!\n")); - } - return SCSI_ABORT_PENDING; - } - - /* - * Add ourselves to (end of) taskQ . - * Check to see if our _bh is running. If NOT, schedule it. - */ - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - Q_ADD_TAIL(&hd->taskQ, &mf->u.frame.linkage, MPT_FRAME_HDR); - hd->taskQcnt++; - atomic_inc(&mpt_taskQdepth); - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - - spin_lock_irqsave(&mytaskQ_lock, flags); - - /* Save the original SCpnt mf pointer - */ - SCpnt->host_scribble = (u8 *) MPT_INDEX_2_MFPTR (hd->ioc, scpnt_idx); - - /* For the time being, force bus reset on any abort - * requests for the 1030/1035 FW. - */ - if (hd->is_spi) - mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; - else - mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK; - - mf->u.frame.linkage.argp1 = SCpnt; - mf->u.frame.linkage.argp2 = (void *) hd; - - dtmprintk((MYIOC_s_INFO_FMT "OldAbort:_bh_handler state (%d) taskQ count (%d)\n", - hd->ioc->name, mytaskQ_bh_active, hd->taskQcnt)); - - if (! mytaskQ_bh_active) { - mytaskQ_bh_active = 1; - spin_unlock_irqrestore(&mytaskQ_lock, flags); - - ptaskfoo = (struct mpt_work_struct *) &mptscsih_ptaskfoo; - MPT_INIT_WORK(&mptscsih_ptaskfoo, mptscsih_taskmgmt_bh, (void *) SCpnt); - - SCHEDULE_TASK(ptaskfoo); - } else { - spin_unlock_irqrestore(&mytaskQ_lock, flags); - } - - return SCSI_ABORT_PENDING; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_old_reset - Perform a SCSI BUS_RESET! - * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to - * @reset_flags: (not used?) - * - * (linux Scsi_Host_Template.reset routine) - * - * Returns SCSI_RESET_{SUCCESS,PUNT,PENDING}. - */ -int -mptscsih_old_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) -{ - MPT_SCSI_HOST *hd; - MPT_FRAME_HDR *mf; - struct mpt_work_struct *ptaskfoo; - unsigned long flags; - int scpnt_idx; - - printk(KERN_WARNING MYNAM ": OldReset scheduling BUS_RESET (sc=%p)\n", (void *) SCpnt); - printk(KERN_WARNING " IOs outstanding = %d\n", atomic_read(&queue_depth)); - - if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) { - SCpnt->result = DID_RESET << 16; - SCpnt->scsi_done(SCpnt); - return SCSI_RESET_SUCCESS; - } - - if (hd->timeouts < -1) - hd->timeouts++; - - if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { - /* Cmd not found in ScsiLookup. - * If found in doneQ, delete from Q. - * Do OS callback. - */ - search_doneQ_for_cmd(hd, SCpnt); - - SCpnt->result = DID_RESET << 16; - SCpnt->scsi_done(SCpnt); - return SCSI_RESET_SUCCESS; - } else { - /* If this command is pended, then timeout/hang occurred - * during DV. Force bus reset by posting command to F/W - * and then following up with the reset request. - */ - if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) { - mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf); - post_pendingQ_commands(hd); - } - } - - /* - * Check to see if there's an ABORT_TASK queued for this guy. - * If so, delete. - */ - search_taskQ(1, SCpnt, hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK); - - /* - * Check to see if there's already a BUS_RESET queued for this guy. - */ - mf = search_taskQ(0, SCpnt, hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS); - if (mf != NULL) { - dtmprintk((MYIOC_s_INFO_FMT "OldReset:Reset Task PENDING cmd (%p) taskQ depth (%d)\n", - hd->ioc->name, SCpnt, hd->taskQcnt)); - return SCSI_RESET_PENDING; - } - - // SJR - CHECKME - Can we avoid this here? - // (mpt_HardResetHandler has this check...) - /* If IOC is reloading FW, return PENDING. - */ - spin_lock_irqsave(&hd->ioc->diagLock, flags); - if (hd->ioc->diagPending) { - spin_unlock_irqrestore(&hd->ioc->diagLock, flags); - return SCSI_RESET_PENDING; - } - spin_unlock_irqrestore(&hd->ioc->diagLock, flags); - - if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) { - /* We are out of message frames! - * Call the reset handler to do a FW reload. - */ - printk((KERN_WARNING " Reloading Firmware!!\n")); - if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) { - printk((KERN_WARNING " Firmware Reload FAILED!!\n")); - } - return SCSI_RESET_PENDING; - } - - /* - * Add ourselves to (end of) taskQ. - * Check to see if our _bh is running. If NOT, schedule it. - */ - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - Q_ADD_TAIL(&hd->taskQ, &mf->u.frame.linkage, MPT_FRAME_HDR); - hd->taskQcnt++; - atomic_inc(&mpt_taskQdepth); - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - - - dtmprintk((MYIOC_s_INFO_FMT "OldReset: _bh_handler state (%d) taskQ count (%d)\n", - hd->ioc->name, mytaskQ_bh_active, hd->taskQcnt)); - - spin_lock_irqsave(&mytaskQ_lock, flags); - /* Save the original SCpnt mf pointer - */ - SCpnt->host_scribble = (u8 *) MPT_INDEX_2_MFPTR (hd->ioc, scpnt_idx); - - mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; - mf->u.frame.linkage.argp1 = SCpnt; - mf->u.frame.linkage.argp2 = (void *) hd; - - if (! mytaskQ_bh_active) { - mytaskQ_bh_active = 1; - spin_unlock_irqrestore(&mytaskQ_lock, flags); - /* - * Oh how cute, no alloc/free/mgmt needed if we use - * (bottom/unused portion of) MPT request frame. - */ - ptaskfoo = (struct mpt_work_struct *) &mptscsih_ptaskfoo; - MPT_INIT_WORK(&mptscsih_ptaskfoo, mptscsih_taskmgmt_bh, (void *) SCpnt); - - SCHEDULE_TASK(ptaskfoo); - } else { - spin_unlock_irqrestore(&mytaskQ_lock, flags); - } - return SCSI_RESET_PENDING; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_taskmgmt_bh - SCSI task mgmt bottom half handler - * @sc: (unused) - * - * This routine (thread) is active whenever there are any outstanding - * SCSI task management requests for a SCSI host adapter. - * IMPORTANT! This routine is scheduled therefore should never be - * running in ISR context. i.e., it's safe to sleep here. - */ -void -mptscsih_taskmgmt_bh(void *sc) -{ - MPT_ADAPTER *ioc; - Scsi_Cmnd *SCpnt; - MPT_FRAME_HDR *mf = NULL; - MPT_SCSI_HOST *hd; - u32 ctx2abort = 0; - unsigned long flags; - int scpnt_idx; - int did; - u8 task_type; - - spin_lock_irqsave(&mytaskQ_lock, flags); - mytaskQ_bh_active = 1; - spin_unlock_irqrestore(&mytaskQ_lock, flags); - - do { -/* SAE: Not in kernel thread */ -#ifdef XEN_KILLED - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); -#else - /* SAE: Trying a lower value... 250 -> 100 */ - mdelay(100); -#endif - did = 0; - - for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) { - if (ioc->sh) { - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - if (hd == NULL) { - printk(KERN_ERR MYNAM - ": ERROR - TaskMgmt NULL SCSI Host!" - "(ioc=%p, sh=%p hd=%p)\n", - (void *) ioc, (void *) ioc->sh, (void *) hd); - continue; - } - -#ifdef MPTSCSIH_DBG_TIMEOUT - if (ioc->timeout_hard == 1) { - mptscsih_TMHandler(hd, - MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - 0, 0, 0, 0, CAN_SLEEP); - - } -#endif - - spin_lock_irqsave(&ioc->FreeQlock, flags); - if (Q_IS_EMPTY(&hd->taskQ)) { - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - continue; - } - - /* If we ever find a non-empty queue, - * keep the handler alive - */ - did++; - - /* tmPending is SMP lock-protected */ - if (hd->tmPending || hd->tmPtr) { - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - continue; - } - hd->tmPending = 1; - - /* Process this request - */ - mf = hd->taskQ.head; - Q_DEL_ITEM(&mf->u.frame.linkage); - hd->taskQcnt--; - atomic_dec(&mpt_taskQdepth); - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - - SCpnt = (Scsi_Cmnd*)mf->u.frame.linkage.argp1; - if (SCpnt == NULL) { - printk(KERN_ERR MYNAM ": ERROR - TaskMgmt has NULL SCpnt! (mf=%p:sc=%p)\n", - (void *) mf, (void *) SCpnt); - mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf); - spin_lock_irqsave(&ioc->FreeQlock, flags); - hd->tmPending = 0; - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - continue; - } - - /* Get the ScsiLookup index pointer - * from the SC pointer. - */ - if (!SCpnt->host_scribble || ((MPT_SCSI_HOST *)SCpnt->host->hostdata != hd)) { - /* The command associated with the - * abort/reset request must have - * completed and this is a stale - * request. We are done. - * Free the current MF and continue. - */ - mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf); - spin_lock_irqsave(&ioc->FreeQlock, flags); - hd->tmPending = 0; - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - continue; - } - - scpnt_idx = MFPTR_2_MPT_INDEX(hd->ioc, SCpnt->host_scribble); - if (scpnt_idx != SCPNT_TO_LOOKUP_IDX(SCpnt)) { - /* Error! this should never happen!! - */ - mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf); - spin_lock_irqsave(&ioc->FreeQlock, flags); - hd->tmPending = 0; - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - continue; - } - - task_type = mf->u.frame.linkage.arg1; - ctx2abort = 0; - if (task_type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { - MPT_FRAME_HDR *SCpntMf; - - /* - * Most important! Set TaskMsgContext to SCpnt's MsgContext! - * (the IO to be ABORT'd) - * - * NOTE: Since we do not byteswap MsgContext, we do not - * swap it here either. It is an opaque cookie to - * the controller, so it does not matter. -DaveM - */ - SCpntMf = (MPT_FRAME_HDR *) SCpnt->host_scribble; - ctx2abort = SCpntMf->u.frame.hwhdr.msgctxu.MsgContext; - - hd->abortSCpnt = SCpnt; - printk(KERN_WARNING MYNAM ": Attempting ABORT SCSI IO! (mf=%p:sc=%p)\n", - (void *) mf, (void *) SCpnt); - } - - /* The TM handler will allocate a new mf, - * so free the current mf. - */ - mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf); - mf = NULL; - - if (mptscsih_TMHandler(hd, task_type, SCpnt->channel, - SCpnt->target, SCpnt->lun, - ctx2abort, CAN_SLEEP) < 0) { - - /* The TM request failed and the subsequent FW-reload failed! - * Fatal error case. - */ - printk(KERN_WARNING MYNAM - ": WARNING[1] - IOC error processing TaskMgmt request (sc=%p)\n", (void *) SCpnt); - - if (hd->ScsiLookup[scpnt_idx] != NULL) { - atomic_dec(&queue_depth); - SCpnt->result = DID_SOFT_ERROR << 16; - MPT_HOST_LOCK(flags); - SCpnt->scsi_done(SCpnt); - MPT_HOST_UNLOCK(flags); - mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf); - } - spin_lock_irqsave(&ioc->FreeQlock, flags); - hd->tmPending = 0; - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - hd->abortSCpnt = NULL; - } - } - } - if (atomic_read(&mpt_taskQdepth) > 0) - did++; - - } while ( did ); - - spin_lock_irqsave(&mytaskQ_lock, flags); - mytaskQ_bh_active = 0; - spin_unlock_irqrestore(&mytaskQ_lock, flags); - - return; -} -#endif /* } */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver - * @ioc: Pointer to MPT_ADAPTER structure - * @mf: Pointer to SCSI task mgmt request frame - * @mr: Pointer to SCSI task mgmt reply frame - * - * This routine is called from mptbase.c::mpt_interrupt() at the completion - * of any SCSI task management request. - * This routine is registered with the MPT (base) driver at driver - * load/init time via the mpt_register() API call. - * - * Returns 1 indicating alloc'd request frame ptr should be freed. - */ -static int -mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) -{ - SCSITaskMgmtReply_t *pScsiTmReply; - SCSITaskMgmt_t *pScsiTmReq; - MPT_SCSI_HOST *hd = NULL; - unsigned long flags; - u8 tmType = 0; - - dtmprintk((MYIOC_s_INFO_FMT "SCSI TaskMgmt completed (mf=%p,r=%p)\n", - ioc->name, mf, mr)); - - if (ioc->sh) { - /* Depending on the thread, a timer is activated for - * the TM request. Delete this timer on completion of TM. - * Decrement count of outstanding TM requests. - */ - hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; - if (hd->tmPtr) { - del_timer(&hd->TMtimer); - } - dtmprintk((MYIOC_s_INFO_FMT "taskQcnt (%d)\n", - ioc->name, hd->taskQcnt)); - } else { - dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n", - ioc->name)); - return 1; - } - - if (mr == NULL) { - dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n", - ioc->name, mf)); - return 1; - } else { - pScsiTmReply = (SCSITaskMgmtReply_t*)mr; - pScsiTmReq = (SCSITaskMgmt_t*)mf; - - /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */ - tmType = pScsiTmReq->TaskType; - - dtmprintk((KERN_INFO " TaskType = %d, TerminationCount=%d\n", - tmType, le32_to_cpu(pScsiTmReply->TerminationCount))); - - /* Error? (anything non-zero?) */ - if (*(u32 *)&pScsiTmReply->Reserved2[0]) { - u16 iocstatus; - - iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; - dtmprintk((KERN_INFO " SCSI TaskMgmt (%d) - Oops!\n", tmType)); - dtmprintk((KERN_INFO " IOCStatus = %04xh\n", iocstatus)); - dtmprintk((KERN_INFO " IOCLogInfo = %08xh\n", - le32_to_cpu(pScsiTmReply->IOCLogInfo))); - - /* clear flags and continue. - */ - if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) - hd->abortSCpnt = NULL; - - /* If an internal command is present - * or the TM failed - reload the FW. - * FC FW may respond FAILED to an ABORT - */ - if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { - if ((hd->cmdPtr) || - (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) { - if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) { - printk((KERN_WARNING - " Firmware Reload FAILED!!\n")); - } - } - } - } else { - dtmprintk((KERN_INFO " SCSI TaskMgmt SUCCESS!\n")); - -#ifndef MPT_SCSI_USE_NEW_EH - if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { - /* clean taskQ - remove tasks associated with - * completed commands. - */ - clean_taskQ(hd); - } else if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { - /* If taskQ contains another request - * for this SCpnt, delete this request. - */ - search_taskQ_for_cmd(hd->abortSCpnt, hd); - } -#endif - hd->numTMrequests--; - hd->abortSCpnt = NULL; - flush_doneQ(hd); - - } - } - -#ifndef MPT_SCSI_USE_NEW_EH - /* - * Signal to _bh thread that we finished. - * This IOC can now process another TM command. - */ - dtmprintk((MYIOC_s_INFO_FMT "taskmgmt_complete: (=%p) done! Num Failed(%d) Task Count (%d)\n", - ioc->name, mf, hd->numTMrequests, hd->taskQcnt)); -#endif - hd->tmPtr = NULL; - spin_lock_irqsave(&ioc->FreeQlock, flags); - hd->tmPending = 0; - spin_unlock_irqrestore(&ioc->FreeQlock, flags); -#ifdef MPT_SCSI_USE_NEW_EH - hd->tmState = TM_STATE_NONE; -#endif - - return 1; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * This is anyones guess quite frankly. - */ -int -mptscsih_bios_param(Disk * disk, kdev_t dev, int *ip) -{ - unsigned capacity = disk->capacity; - int size; - - size = capacity; - ip[0] = 64; /* heads */ - ip[1] = 32; /* sectors */ - if ((ip[2] = size >> 11) > 1024) { /* cylinders, test for big disk */ - ip[0] = 255; /* heads */ - ip[1] = 63; /* sectors */ - ip[2] = size / (255 * 63); /* cylinders */ - } - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * OS entry point to adjust the queue_depths on a per-device basis. - * Called once per device the bus scan. Use it to force the queue_depth - * member to 1 if a device does not support Q tags. - */ -void -mptscsih_select_queue_depths(struct Scsi_Host *sh, Scsi_Device *sdList) -{ - struct scsi_device *device; - VirtDevice *pTarget; - MPT_SCSI_HOST *hd; - - for (device = sdList; device != NULL; device = device->next) { - - if (device->host != sh) - continue; - - hd = (MPT_SCSI_HOST *) sh->hostdata; - if (hd == NULL) - continue; - - if (hd->Targets != NULL) { - pTarget = NULL; - if (device->id > sh->max_id) { - /* error case, should never happen */ - device->queue_depth = 1; - continue; - } else { - pTarget = hd->Targets[device->id]; - } - - if (pTarget == NULL) { - /* error case - don't know about this device */ - device->queue_depth = 1; - } else if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { - if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) - device->queue_depth = 1; - else if (((pTarget->inq_data[0] & 0x1f) == 0x00) - && (pTarget->minSyncFactor <= MPT_ULTRA160 || !hd->is_spi)){ - device->queue_depth = MPT_SCSI_CMD_PER_DEV_HIGH; - } else - device->queue_depth = MPT_SCSI_CMD_PER_DEV_LOW; - - } else { - /* error case - No Inq. Data */ - device->queue_depth = 1; - } - - if (pTarget != NULL) { - printk(MYIOC_s_INFO_FMT - "scsi%d: Id=%d Lun=%d: Queue depth=%d\n", - hd->ioc->name, sh->host_no, - device->id, device->lun, device->queue_depth); - - dprintk((MYIOC_s_INFO_FMT - "Id = %d, sync factor = %x\n", - hd->ioc->name, pTarget->target_id, - pTarget->minSyncFactor)); - } - } - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Private routines... - */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* Utility function to copy sense data from the scsi_cmnd buffer - * to the FC and SCSI target structures. - * - */ -static void -copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply) -{ - VirtDevice *target; - SCSIIORequest_t *pReq; - u32 sense_count = le32_to_cpu(pScsiReply->SenseCount); - int index; - char devFoo[96]; - IO_Info_t thisIo; - - /* Get target structure - */ - pReq = (SCSIIORequest_t *) mf; - index = (int) pReq->TargetID; - target = hd->Targets[index]; - if (hd->is_multipath && sc->device->hostdata) - target = (VirtDevice *) sc->device->hostdata; - - if (sense_count) { - u8 *sense_data; - int req_index; - - /* Copy the sense received into the scsi command block. */ - req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); - sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC)); - memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc)); - - /* Log SMART data (asc = 0x5D, non-IM case only) if required. - */ - if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) { - if ((sense_data[12] == 0x5D) && (target->raidVolume == 0)) { - int idx; - MPT_ADAPTER *ioc = hd->ioc; - - idx = ioc->eventContext % ioc->eventLogSize; - ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE; - ioc->events[idx].eventContext = ioc->eventContext; - - ioc->events[idx].data[0] = (pReq->LUN[1] << 24) || - (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) || - (pReq->Bus << 8) || pReq->TargetID; - - ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12]; - - ioc->eventContext++; - } - } - - /* Print an error report for the user. - */ - thisIo.cdbPtr = sc->cmnd; - thisIo.sensePtr = sc->sense_buffer; - thisIo.SCSIStatus = pScsiReply->SCSIStatus; - thisIo.DoDisplay = 1; - if (hd->is_multipath) - sprintf(devFoo, "%d:%d:%d \"%s\"", - hd->ioc->id, - pReq->TargetID, - pReq->LUN[1], - target->dev_vol_name); - else - sprintf(devFoo, "%d:%d:%d", hd->ioc->id, sc->target, sc->lun); - thisIo.DevIDStr = devFoo; -/* fubar */ - thisIo.dataPtr = NULL; - thisIo.inqPtr = NULL; - if (sc->device) { - thisIo.inqPtr = sc->device->vendor-8; /* FIXME!!! */ - } - (void) mpt_ScsiHost_ErrorReport(&thisIo); - - } else { - dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n", - hd->ioc->name)); - } - - return; -} - -static u32 -SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc) -{ - MPT_SCSI_HOST *hd; - int i; - - hd = (MPT_SCSI_HOST *) sc->host->hostdata; - - for (i = 0; i < hd->ioc->req_depth; i++) { - if (hd->ScsiLookup[i] == sc) { - return i; - } - } - - return -1; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -/* see mptscsih.h */ - -#ifdef MPT_SCSIHOST_NEED_ENTRY_EXIT_HOOKUPS - static Scsi_Host_Template driver_template = MPT_SCSIHOST; -# include "../../scsi/scsi_module.c.inc" -#endif - - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* Search the pendingQ for a command with specific index. - * If found, delete and return mf pointer - * If not found, return NULL - */ -static MPT_FRAME_HDR * -mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx) -{ - unsigned long flags; - MPT_DONE_Q *buffer; - MPT_FRAME_HDR *mf = NULL; - MPT_FRAME_HDR *cmdMfPtr = NULL; - - ddvtprintk((MYIOC_s_INFO_FMT ": search_pendingQ ...", hd->ioc->name)); - cmdMfPtr = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx); - spin_lock_irqsave(&hd->freedoneQlock, flags); - if (!Q_IS_EMPTY(&hd->pendingQ)) { - buffer = hd->pendingQ.head; - do { - mf = (MPT_FRAME_HDR *) buffer->argp; - if (mf == cmdMfPtr) { - Q_DEL_ITEM(buffer); - - /* clear the arg pointer - */ - buffer->argp = NULL; - - /* Add to the freeQ - */ - Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q); - break; - } - mf = NULL; - } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->pendingQ); - } - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - ddvtprintk((" ...return %p\n", mf)); - return mf; -} - -/* Post all commands on the pendingQ to the FW. - * Lock Q when deleting/adding members - * Lock io_request_lock for OS callback. - */ -static void -post_pendingQ_commands(MPT_SCSI_HOST *hd) -{ - MPT_FRAME_HDR *mf; - MPT_DONE_Q *buffer; - unsigned long flags; - - /* Flush the pendingQ. - */ - ddvtprintk((MYIOC_s_INFO_FMT ": post_pendingQ_commands\n", hd->ioc->name)); - while (1) { - spin_lock_irqsave(&hd->freedoneQlock, flags); - if (Q_IS_EMPTY(&hd->pendingQ)) { - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - break; - } - - buffer = hd->pendingQ.head; - /* Delete from Q - */ - Q_DEL_ITEM(buffer); - - mf = (MPT_FRAME_HDR *) buffer->argp; - buffer->argp = NULL; - - /* Add to the freeQ - */ - Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q); - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - - if (!mf) { - /* This should never happen */ - printk(MYIOC_s_WARN_FMT "post_pendingQ_commands: mf %p\n", hd->ioc->name, (void *) mf); - continue; - } - - mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf); - -#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) - { - u16 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); - Scsi_Cmnd *sc = hd->ScsiLookup[req_idx]; - printk(MYIOC_s_INFO_FMT "Issued SCSI cmd (sc=%p) idx=%d (mf=%p)\n", - hd->ioc->name, sc, req_idx, mf); - } -#endif - } - - return; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int -mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) -{ - MPT_SCSI_HOST *hd = NULL; - unsigned long flags; - - dtmprintk((KERN_WARNING MYNAM - ": IOC %s_reset routed to SCSI host driver!\n", - reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( - reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); - - /* If a FW reload request arrives after base installed but - * before all scsi hosts have been attached, then an alt_ioc - * may have a NULL sh pointer. - */ - if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL)) - return 0; - else - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - - if (reset_phase == MPT_IOC_SETUP_RESET) { - dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name)); - /* Clean Up: - * 1. Set Hard Reset Pending Flag - * All new commands go to doneQ - */ - hd->resetPending = 1; - - /* 2. Reset timeouts on all running commands - */ - mptscsih_reset_timeouts (hd); - - } else if (reset_phase == MPT_IOC_PRE_RESET) { - dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name)); - - /* 2. Flush running commands - * Clean ScsiLookup (and associated memory) - * AND clean mytaskQ - */ - - /* 2b. Reply to OS all known outstanding I/O commands. - */ - mptscsih_flush_running_cmds(hd); - - /* 2c. If there was an internal command that - * has not completed, configuration or io request, - * free these resources. - */ - if (hd->cmdPtr) { - del_timer(&hd->timer); - mpt_free_msg_frame(ScsiScanDvCtx, ioc->id, hd->cmdPtr); - atomic_dec(&queue_depth); - } - - /* 2d. If a task management has not completed, - * free resources associated with this request. - */ - if (hd->tmPtr) { - del_timer(&hd->TMtimer); - mpt_free_msg_frame(ScsiTaskCtx, ioc->id, hd->tmPtr); - } - -#ifndef MPT_SCSI_USE_NEW_EH - /* 2e. Delete all commands on taskQ - * Should be superfluous - as this taskQ should - * be empty. - */ - clean_taskQ(hd); -#endif - -#ifdef MPTSCSIH_DBG_TIMEOUT - ioc->timeout_hard = 0; -#endif - - dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name)); - } else { - ScsiCfgData *pSpi = NULL; - - dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name)); - - /* Once a FW reload begins, all new OS commands are - * redirected to the doneQ w/ a reset status. - * Init all control structures. - */ - - /* ScsiLookup initialization - */ - { - int ii; - for (ii=0; ii < hd->ioc->req_depth; ii++) - hd->ScsiLookup[ii] = NULL; - } - - /* 2. Chain Buffer initialization - */ - mptscsih_initChainBuffers(hd, 0); - - /* 3. tmPtr clear - */ - if (hd->tmPtr) { - hd->tmPtr = NULL; - } - - /* 4. Renegotiate to all devices, if SCSI - */ - if (hd->is_spi) - mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM); - - /* 5. Enable new commands to be posted - */ - spin_lock_irqsave(&ioc->FreeQlock, flags); - hd->tmPending = 0; - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - hd->resetPending = 0; - hd->numTMrequests = 0; -#ifdef MPT_SCSI_USE_NEW_EH - hd->tmState = TM_STATE_NONE; -#endif - - /* 6. If there was an internal command, - * wake this process up. - */ - if (hd->cmdPtr) { - /* - * Wake up the original calling thread - */ - hd->pLocal = &hd->localReply; - hd->pLocal->completion = MPT_SCANDV_DID_RESET; - scandv_wait_done = 1; -/* SAE: No wait queues */ -#ifdef XEN_KILLED - wake_up(&scandv_waitq); -#else - mdelay(100); -#endif - hd->cmdPtr = NULL; - } - - /* 7. Flush doneQ - */ - flush_doneQ(hd); - - /* 8. Set flag to force DV and re-read IOC Page 3 - */ - if (hd->is_spi) { - pSpi = &ioc->spi_data; - pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; - ddvtprintk(("Set reload IOC Pg3 Flag\n")); - } - - dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name)); - } - - return 1; /* currently means nothing really */ -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int -mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) -{ - MPT_SCSI_HOST *hd; - u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; - - dprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", ioc->name, event)); - - switch (event) { - case MPI_EVENT_UNIT_ATTENTION: /* 03 */ - /* FIXME! */ - break; - case MPI_EVENT_IOC_BUS_RESET: /* 04 */ - case MPI_EVENT_EXT_BUS_RESET: /* 05 */ - hd = NULL; - if (ioc->sh) { - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - if (hd && (hd->is_spi) && (hd->soft_resets < -1)) - hd->soft_resets++; - } - break; - case MPI_EVENT_LOGOUT: /* 09 */ - /* FIXME! */ - break; - - /* - * CHECKME! Don't think we need to do - * anything for these, but... - */ - case MPI_EVENT_RESCAN: /* 06 */ - case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */ - case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */ - /* - * CHECKME! Falling thru... - */ - break; - - case MPI_EVENT_INTEGRATED_RAID: /* 0B */ -#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION - /* negoNvram set to 0 if DV enabled and to USE_NVRAM if - * if DV disabled. Need to check for target mode. - */ - hd = NULL; - if (ioc->sh) - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - - if (hd && (hd->is_spi) && (hd->negoNvram == 0)) { - ScsiCfgData *pSpi; - Ioc3PhysDisk_t *pPDisk; - int numPDisk; - u8 reason; - u8 physDiskNum; - - reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16; - if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) { - /* New or replaced disk. - * Set DV flag and schedule DV. - */ - pSpi = &ioc->spi_data; - physDiskNum = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24; - ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum)); - if (pSpi->pIocPg3) { - pPDisk = pSpi->pIocPg3->PhysDisk; - numPDisk =pSpi->pIocPg3->NumPhysDisks; - - while (numPDisk) { - if (physDiskNum == pPDisk->PhysDiskNum) { - pSpi->dvStatus[pPDisk->PhysDiskID] = (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE); - pSpi->forceDv = MPT_SCSICFG_NEED_DV; - ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID)); - break; - } - pPDisk++; - numPDisk--; - } - - if (numPDisk == 0) { - /* The physical disk that needs DV was not found - * in the stored IOC Page 3. The driver must reload - * this page. DV routine will set the NEED_DV flag for - * all phys disks that have DV_NOT_DONE set. - */ - pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; - ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum)); - } - } - } - } -#endif - -#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) - printk("Raid Event RF: "); - { - u32 *m = (u32 *)pEvReply; - int ii; - int n = (int)pEvReply->MsgLength; - for (ii=6; ii < n; ii++) - printk(" %08x", le32_to_cpu(m[ii])); - printk("\n"); - } -#endif - break; - - case MPI_EVENT_NONE: /* 00 */ - case MPI_EVENT_LOG_DATA: /* 01 */ - case MPI_EVENT_STATE_CHANGE: /* 02 */ - case MPI_EVENT_EVENT_CHANGE: /* 0A */ - default: - dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event)); - break; - } - - return 1; /* currently means nothing really */ -} - -#if 0 /* { */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * scsiherr.c - Fusion MPT SCSI Host driver error handling/reporting. - * - * drivers/message/fusion/scsiherr.c - */ - -//extern const char **mpt_ScsiOpcodesPtr; /* needed by mptscsih.c */ -//extern ASCQ_Table_t *mpt_ASCQ_TablePtr; -//extern int mpt_ASCQ_TableSz; - -#define MYNAM "mptscsih" - -#endif /* } */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Private data... - */ -static ASCQ_Table_t *mptscsih_ASCQ_TablePtr; - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* old symsense.c stuff... */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Private data... - * To protect ourselves against those that would pass us bogus pointers - */ -static u8 dummyInqData[SCSI_STD_INQUIRY_BYTES] - = { 0x1F, 0x00, 0x00, 0x00, - 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static u8 dummySenseData[SCSI_STD_SENSE_BYTES] - = { 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 }; -static u8 dummyCDB[16] - = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static u8 dummyScsiData[16] - = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - -#if 0 -static const char *PeripheralDeviceTypeString[32] = { - "Direct-access", /* 00h */ - "Sequential-access", /* 01h */ - "Printer", /* 02h */ - "Processor", /* 03h */ - /*"Write-Once-Read-Multiple",*/ /* 04h */ - "WORM", /* 04h */ - "CD-ROM", /* 05h */ - "Scanner", /* 06h */ - "Optical memory", /* 07h */ - "Media Changer", /* 08h */ - "Communications", /* 09h */ - "(Graphics arts pre-press)", /* 0Ah */ - "(Graphics arts pre-press)", /* 0Bh */ - "Array controller", /* 0Ch */ - "Enclosure services", /* 0Dh */ - "Simplified direct-access", /* 0Eh */ - "Reserved-0Fh", /* 0Fh */ - "Reserved-10h", /* 10h */ - "Reserved-11h", /* 11h */ - "Reserved-12h", /* 12h */ - "Reserved-13h", /* 13h */ - "Reserved-14h", /* 14h */ - "Reserved-15h", /* 15h */ - "Reserved-16h", /* 16h */ - "Reserved-17h", /* 17h */ - "Reserved-18h", /* 18h */ - "Reserved-19h", /* 19h */ - "Reserved-1Ah", /* 1Ah */ - "Reserved-1Bh", /* 1Bh */ - "Reserved-1Ch", /* 1Ch */ - "Reserved-1Dh", /* 1Dh */ - "Reserved-1Eh", /* 1Eh */ - "Unknown" /* 1Fh */ -}; -#endif - -static char *ScsiStatusString[] = { - "GOOD", /* 00h */ - NULL, /* 01h */ - "CHECK CONDITION", /* 02h */ - NULL, /* 03h */ - "CONDITION MET", /* 04h */ - NULL, /* 05h */ - NULL, /* 06h */ - NULL, /* 07h */ - "BUSY", /* 08h */ - NULL, /* 09h */ - NULL, /* 0Ah */ - NULL, /* 0Bh */ - NULL, /* 0Ch */ - NULL, /* 0Dh */ - NULL, /* 0Eh */ - NULL, /* 0Fh */ - "INTERMEDIATE", /* 10h */ - NULL, /* 11h */ - NULL, /* 12h */ - NULL, /* 13h */ - "INTERMEDIATE-CONDITION MET", /* 14h */ - NULL, /* 15h */ - NULL, /* 16h */ - NULL, /* 17h */ - "RESERVATION CONFLICT", /* 18h */ - NULL, /* 19h */ - NULL, /* 1Ah */ - NULL, /* 1Bh */ - NULL, /* 1Ch */ - NULL, /* 1Dh */ - NULL, /* 1Eh */ - NULL, /* 1Fh */ - NULL, /* 20h */ - NULL, /* 21h */ - "COMMAND TERMINATED", /* 22h */ - NULL, /* 23h */ - NULL, /* 24h */ - NULL, /* 25h */ - NULL, /* 26h */ - NULL, /* 27h */ - "TASK SET FULL", /* 28h */ - NULL, /* 29h */ - NULL, /* 2Ah */ - NULL, /* 2Bh */ - NULL, /* 2Ch */ - NULL, /* 2Dh */ - NULL, /* 2Eh */ - NULL, /* 2Fh */ - "ACA ACTIVE", /* 30h */ - NULL -}; - -static const char *ScsiCommonOpString[] = { - "TEST UNIT READY", /* 00h */ - "REZERO UNIT (REWIND)", /* 01h */ - NULL, /* 02h */ - "REQUEST_SENSE", /* 03h */ - "FORMAT UNIT (MEDIUM)", /* 04h */ - "READ BLOCK LIMITS", /* 05h */ - NULL, /* 06h */ - "REASSIGN BLOCKS", /* 07h */ - "READ(6)", /* 08h */ - NULL, /* 09h */ - "WRITE(6)", /* 0Ah */ - "SEEK(6)", /* 0Bh */ - NULL, /* 0Ch */ - NULL, /* 0Dh */ - NULL, /* 0Eh */ - "READ REVERSE", /* 0Fh */ - "WRITE_FILEMARKS", /* 10h */ - "SPACE(6)", /* 11h */ - "INQUIRY", /* 12h */ - NULL -}; - -static const char *SenseKeyString[] = { - "NO SENSE", /* 0h */ - "RECOVERED ERROR", /* 1h */ - "NOT READY", /* 2h */ - "MEDIUM ERROR", /* 3h */ - "HARDWARE ERROR", /* 4h */ - "ILLEGAL REQUEST", /* 5h */ - "UNIT ATTENTION", /* 6h */ - "DATA PROTECT", /* 7h */ - "BLANK CHECK", /* 8h */ - "VENDOR-SPECIFIC", /* 9h */ - "ABORTED COPY", /* Ah */ - "ABORTED COMMAND", /* Bh */ - "EQUAL (obsolete)", /* Ch */ - "VOLUME OVERFLOW", /* Dh */ - "MISCOMPARE", /* Eh */ - "RESERVED", /* Fh */ - NULL -}; - -#define SPECIAL_ASCQ(c,q) \ - (((c) == 0x40 && (q) != 0x00) || ((c) == 0x4D) || ((c) == 0x70)) - -#if 0 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Sense_Key_Specific() - If Sense_Key_Specific_Valid bit is set, - * then print additional information via - * a call to SDMS_SystemAlert(). - */ -static void Sense_Key_Specific(IO_Info_t *ioop, char *msg1) -{ - u8 *sd; - u8 BadValue; - u8 SenseKey; - int Offset; - int len = strlen(msg1); - - sd = ioop->sensePtr; - if (SD_Additional_Sense_Length(sd) < 8) - return; - - SenseKey = SD_Sense_Key(sd); - - if (SD_Sense_Key_Specific_Valid(sd)) { - if (SenseKey == SK_ILLEGAL_REQUEST) { - Offset = SD_Bad_Byte(sd); - if (SD_Was_Illegal_Request(sd)) { - BadValue = ioop->cdbPtr[Offset]; - len += sprintf(msg1+len, "\n Illegal CDB value=%02Xh found at CDB ", - BadValue); - } else { - BadValue = ioop->dataPtr[Offset]; - len += sprintf(msg1+len, "\n Illegal DATA value=%02Xh found at DATA ", - BadValue); - } - len += sprintf(msg1+len, "byte=%02Xh", Offset); - if (SD_SKS_Bit_Pointer_Valid(sd)) - len += sprintf(msg1+len, "/bit=%1Xh", SD_SKS_Bit_Pointer(sd)); - } else if ((SenseKey == SK_RECOVERED_ERROR) || - (SenseKey == SK_HARDWARE_ERROR) || - (SenseKey == SK_MEDIUM_ERROR)) { - len += sprintf(msg1+len, "\n Recovery algorithm Actual_Retry_Count=%02Xh", - SD_Actual_Retry_Count(sd)); - } - } -} -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int dump_cdb(char *foo, unsigned char *cdb) -{ - int i, grpCode, cdbLen; - int l = 0; - - grpCode = cdb[0] >> 5; - if (grpCode < 1) - cdbLen = 6; - else if (grpCode < 3) - cdbLen = 10; - else if (grpCode == 5) - cdbLen = 12; - else - cdbLen = 16; - - for (i=0; i < cdbLen; i++) - l += sprintf(foo+l, " %02X", cdb[i]); - - return l; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#if 0 -static int dump_sd(char *foo, unsigned char *sd) -{ - int snsLen = 8 + SD_Additional_Sense_Length(sd); - int l = 0; - int i; - - for (i=0; i < MIN(snsLen,18); i++) - l += sprintf(foo+l, " %02X", sd[i]); - l += sprintf(foo+l, "%s", snsLen>18 ? " ..." : ""); - - return l; -} -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* Do ASC/ASCQ lookup/grindage to English readable string(s) */ -static const char * ascq_set_strings_4max( - u8 ASC, u8 ASCQ, - const char **s1, const char **s2, const char **s3, const char **s4) -{ - static const char *asc_04_part1_string = "LOGICAL UNIT "; - static const char *asc_04_part2a_string = "NOT READY, "; - static const char *asc_04_part2b_string = "IS "; - static const char *asc_04_ascq_NN_part3_strings[] = { /* ASC ASCQ (hex) */ - "CAUSE NOT REPORTABLE", /* 04 00 */ - "IN PROCESS OF BECOMING READY", /* 04 01 */ - "INITIALIZING CMD. REQUIRED", /* 04 02 */ - "MANUAL INTERVENTION REQUIRED", /* 04 03 */ - /* Add " IN PROGRESS" to all the following... */ - "FORMAT", /* 04 04 */ - "REBUILD", /* 04 05 */ - "RECALCULATION", /* 04 06 */ - "OPERATION", /* 04 07 */ - "LONG WRITE", /* 04 08 */ - "SELF-TEST", /* 04 09 */ - NULL - }; - static char *asc_04_part4_string = " IN PROGRESS"; - - static char *asc_29_ascq_NN_strings[] = { /* ASC ASCQ (hex) */ - "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED", /* 29 00 */ - "POWER ON OCCURRED", /* 29 01 */ - "SCSI BUS RESET OCCURRED", /* 29 02 */ - "BUS DEVICE RESET FUNCTION OCCURRED", /* 29 03 */ - "DEVICE INTERNAL RESET", /* 29 04 */ - "TRANSCEIVER MODE CHANGED TO SINGLE-ENDED", /* 29 05 */ - "TRANSCEIVER MODE CHANGED TO LVD", /* 29 06 */ - NULL - }; - static char *ascq_vendor_uniq = "(Vendor Unique)"; - static char *ascq_noone = "(no matching ASC/ASCQ description found)"; - int idx; - - *s1 = *s2 = *s3 = *s4 = ""; /* set'em all to the empty "" string */ - - /* CHECKME! Need lock/sem? - * Update and examine for isense module presense. - */ - mptscsih_ASCQ_TablePtr = (ASCQ_Table_t *)mpt_v_ASCQ_TablePtr; - - if (mptscsih_ASCQ_TablePtr == NULL) { - /* 2nd chances... */ - if (ASC == 0x04 && (ASCQ < sizeof(asc_04_ascq_NN_part3_strings)/sizeof(char*)-1)) { - *s1 = asc_04_part1_string; - *s2 = (ASCQ == 0x01) ? asc_04_part2b_string : asc_04_part2a_string; - *s3 = asc_04_ascq_NN_part3_strings[ASCQ]; - /* check for " IN PROGRESS" ones */ - if (ASCQ >= 0x04) - *s4 = asc_04_part4_string; - } else if (ASC == 0x29 && (ASCQ < sizeof(asc_29_ascq_NN_strings)/sizeof(char*)-1)) - *s1 = asc_29_ascq_NN_strings[ASCQ]; - /* - * Else { leave all *s[1-4] values pointing to the empty "" string } - */ - return *s1; - } - - /* - * Need to check ASC here; if it is "special," then - * the ASCQ is variable, and indicates failed component number. - * We must treat the ASCQ as a "don't care" while searching the - * mptscsih_ASCQ_Table[] by masking it off, and then restoring it later - * on when we actually need to identify the failed component. - */ - if (SPECIAL_ASCQ(ASC,ASCQ)) - ASCQ = 0xFF; - - /* OK, now search mptscsih_ASCQ_Table[] for a matching entry */ - for (idx = 0; mptscsih_ASCQ_TablePtr && idx < mpt_ASCQ_TableSz; idx++) - if ((ASC == mptscsih_ASCQ_TablePtr[idx].ASC) && (ASCQ == mptscsih_ASCQ_TablePtr[idx].ASCQ)) { - *s1 = mptscsih_ASCQ_TablePtr[idx].Description; - return *s1; - } - - if ((ASC >= 0x80) || (ASCQ >= 0x80)) - *s1 = ascq_vendor_uniq; - else - *s1 = ascq_noone; - - return *s1; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * SCSI Information Report; desired output format... - *--- -SCSI Error: (iocnum:target_id:LUN) Status=02h (CHECK CONDITION) - Key=6h (UNIT ATTENTION); FRU=03h - ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED" - CDB: 00 00 00 00 00 00 - TestUnitReady - *--- - */ -/* - * SCSI Error Report; desired output format... - *--- -SCSI Error Report =-=-=-=-=-=-=-=-=-=-=-=-=-= (ioc0,scsi0:0) - SCSI_Status=02h (CHECK CONDITION) - Original_CDB[]: 00 00 00 00 00 00 - TestUnitReady - SenseData[12h]: 70 00 06 00 00 00 00 0A 00 00 00 00 29 00 03 00 00 00 - SenseKey=6h (UNIT ATTENTION); FRU=03h - ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED" - *--- - */ - -int mpt_ScsiHost_ErrorReport(IO_Info_t *ioop) -{ - char foo[512]; - char buf2[32]; - char *statstr; - const char *opstr; - int sk = SD_Sense_Key(ioop->sensePtr); - const char *skstr = SenseKeyString[sk]; - unsigned char asc = SD_ASC(ioop->sensePtr); - unsigned char ascq = SD_ASCQ(ioop->sensePtr); - int l; - - /* Change the error logging to only report errors on - * read and write commands. Ignore errors on other commands. - * Should this be configurable via proc? - */ - switch (ioop->cdbPtr[0]) { - case READ_6: - case WRITE_6: - case READ_10: - case WRITE_10: - case READ_12: - case WRITE_12: - break; - default: - return 0; - } - - /* - * More quiet mode. - * Filter out common, repetitive, warning-type errors... like: - * POWER ON (06,29/00 or 06,29/01), - * SPINNING UP (02,04/01), - * LOGICAL UNIT NOT SUPPORTED (05,25/00), etc. - */ - if (sk == SK_NO_SENSE) { - return 0; - } - - if ( (sk==SK_UNIT_ATTENTION && asc==0x29 && (ascq==0x00 || ascq==0x01)) - || (sk==SK_NOT_READY && asc==0x04 && (ascq==0x01 || ascq==0x02)) - || (sk==SK_ILLEGAL_REQUEST && asc==0x25 && ascq==0x00) - ) - { - /* Do nothing! */ - return 0; - } - - /* Prevent the system from continually writing to the log - * if a medium is not found: 02 3A 00 - * Changer issues: TUR, Read Capacity, Table of Contents continually - */ - if (sk==SK_NOT_READY && asc==0x3A) { - if (ioop->cdbPtr == NULL) { - return 0; - } else if ((ioop->cdbPtr[0] == CMD_TestUnitReady) || - (ioop->cdbPtr[0] == CMD_ReadCapacity) || - (ioop->cdbPtr[0] == 0x43)) { - return 0; - } - } - if (sk==SK_UNIT_ATTENTION) { - if (ioop->cdbPtr == NULL) - return 0; - else if (ioop->cdbPtr[0] == CMD_TestUnitReady) - return 0; - } - - /* - * Protect ourselves... - */ - if (ioop->cdbPtr == NULL) - ioop->cdbPtr = dummyCDB; - if (ioop->sensePtr == NULL) - ioop->sensePtr = dummySenseData; - if (ioop->inqPtr == NULL) - ioop->inqPtr = dummyInqData; - if (ioop->dataPtr == NULL) - ioop->dataPtr = dummyScsiData; - - statstr = NULL; - if ((ioop->SCSIStatus >= sizeof(ScsiStatusString)/sizeof(char*)-1) || - ((statstr = (char*)ScsiStatusString[ioop->SCSIStatus]) == NULL)) { - (void) sprintf(buf2, "Bad-Reserved-%02Xh", ioop->SCSIStatus); - statstr = buf2; - } - - opstr = NULL; - if (1+ioop->cdbPtr[0] <= sizeof(ScsiCommonOpString)/sizeof(char*)) - opstr = ScsiCommonOpString[ioop->cdbPtr[0]]; - else if (mpt_ScsiOpcodesPtr) - opstr = mpt_ScsiOpcodesPtr[ioop->cdbPtr[0]]; - - l = sprintf(foo, "SCSI Error: (%s) Status=%02Xh (%s)\n", - ioop->DevIDStr, - ioop->SCSIStatus, - statstr); - l += sprintf(foo+l, " Key=%Xh (%s); FRU=%02Xh\n ASC/ASCQ=%02Xh/%02Xh", - sk, skstr, SD_FRU(ioop->sensePtr), asc, ascq ); - { - const char *x1, *x2, *x3, *x4; - x1 = x2 = x3 = x4 = ""; - x1 = ascq_set_strings_4max(asc, ascq, &x1, &x2, &x3, &x4); - if (x1 != NULL) { - if (x1[0] != '(') - l += sprintf(foo+l, " \"%s%s%s%s\"", x1,x2,x3,x4); - else - l += sprintf(foo+l, " %s%s%s%s", x1,x2,x3,x4); - } - } - l += sprintf(foo+l, "\n CDB:"); - l += dump_cdb(foo+l, ioop->cdbPtr); - if (opstr) - l += sprintf(foo+l, " - \"%s\"", opstr); - l += sprintf(foo+l, "\n"); - - PrintF(("%s\n", foo)); - - return l; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_initTarget - Target, LUN alloc/free functionality. - * @hd: Pointer to MPT_SCSI_HOST structure - * @bus_id: Bus number (?) - * @target_id: SCSI target id - * @lun: SCSI LUN id - * @data: Pointer to data - * @dlen: Number of INQUIRY bytes - * - * NOTE: It's only SAFE to call this routine if data points to - * sane & valid STANDARD INQUIRY data! - * - * Allocate and initialize memory for this target. - * Save inquiry data. - * - * Returns pointer to VirtDevice structure. - */ -static VirtDevice * -mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen) -{ - VirtDevice *vdev; - int sz; - - dprintk((MYIOC_s_INFO_FMT "initTarget (%d,%d,%d) called, hd=%p\n", - hd->ioc->name, bus_id, target_id, lun, hd)); - - if ((vdev = hd->Targets[target_id]) == NULL) { - if ((vdev = kmalloc(sizeof(VirtDevice), GFP_ATOMIC)) == NULL) { - printk(MYIOC_s_ERR_FMT "initTarget kmalloc(%d) FAILED!\n", - hd->ioc->name, (int)sizeof(VirtDevice)); - } else { - memset(vdev, 0, sizeof(VirtDevice)); - rwlock_init(&vdev->VdevLock); - Q_INIT(&vdev->WaitQ, void); - Q_INIT(&vdev->SentQ, void); - Q_INIT(&vdev->DoneQ, void); - vdev->tflags = 0; - vdev->ioc_id = hd->ioc->id; - vdev->target_id = target_id; - vdev->bus_id = bus_id; - - hd->Targets[target_id] = vdev; - dprintk((KERN_INFO " *NEW* Target structure (id %d) @ %p\n", - target_id, vdev)); - } - } - - vdev->raidVolume = 0; - if (vdev && hd->is_spi) { - if (hd->ioc->spi_data.isRaid & (1 << target_id)) { - vdev->raidVolume = 1; - ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", target_id)); - } - } - - if (vdev && data) { - if ((!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) || - ((dlen > 56) && (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56)))) { - - /* Copy the inquiry data - if we haven't yet. - */ - sz = MIN(dlen, SCSI_STD_INQUIRY_BYTES); - - memcpy (vdev->inq_data, data, sz); - vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; - - /* Update the target capabilities - */ - if (dlen > 56) { - mptscsih_setTargetNegoParms(hd, vdev, data[56]); - vdev->tflags |= MPT_TARGET_FLAGS_VALID_56; - } else - mptscsih_setTargetNegoParms(hd, vdev, 0); - - /* If LUN 0, tape and have not done DV, set the DV flag. - */ - if (hd->is_spi && (lun == 0) && ((data[0] & 0x1F) == 0x01)) { - ScsiCfgData *pSpi = &hd->ioc->spi_data; - if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE) - pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV; - } - } - - /* Is LUN supported? If so, upper 3 bits will be 0 - * in first byte of inquiry data. - */ - if ((*data & 0xe0) == 0) - vdev->luns |= (1 << lun); - } - - - dprintk((KERN_INFO " target = %p\n", vdev)); - return vdev; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Update the target negotiation parameters based on the - * the Inquiry data, adapter capabilities, and NVRAM settings. - * - */ -void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56) -{ - ScsiCfgData *pspi_data = &hd->ioc->spi_data; - int id = (int) target->target_id; - int nvram; - char canQ = 0; - u8 width = MPT_NARROW; - u8 factor = MPT_ASYNC; - u8 offset = 0; - u8 version, nfactor; - u8 noQas = 0; - - ddvtprintk((KERN_INFO "set Target: (id %d) byte56 0x%x\n", id, byte56)); - - if (!hd->is_spi) { - if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { - if (target->inq_data[7] & 0x02) - target->tflags |= MPT_TARGET_FLAGS_Q_YES; - } - return; - } - - /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine - * support. If available, default QAS to off and allow enabling. - * If not available, default QAS to on, turn off for non-disks. - */ - if (target->tflags & MPT_TARGET_FLAGS_VALID_56) - noQas = 1; - - /* Set flags based on Inquiry data - */ - if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { - if ((target->inq_data[0] & 0x1F) != 0x00) - noQas = 1; - - version = target->inq_data[2] & 0x07; - if (version < 2) { - width = 0; - factor = MPT_ULTRA2; - offset = pspi_data->maxSyncOffset; - } else { - if (target->inq_data[7] & 0x20) { - width = 1; - } - - if (target->inq_data[7] & 0x10) { - /* bits 2 & 3 show DT support - */ - if ((byte56 & 0x04) == 0) - factor = MPT_ULTRA2; - else if ((byte56 & 0x03) == 0) - factor = MPT_ULTRA160; - else - factor = MPT_ULTRA320; - - /* If RAID, never disable QAS - * else if non RAID, do not disable - * QAS if bit 1 is set - * bit 1 QAS support, non-raid only - * bit 0 IU support - */ - if ((target->raidVolume == 1) || ((byte56 & 0x02) != 0)) - noQas = 0; - - offset = pspi_data->maxSyncOffset; - } else { - factor = MPT_ASYNC; - offset = 0; - } - } - - if (target->inq_data[7] & 0x02) { - canQ = 1; - } - - /* Update tflags based on NVRAM settings. (SCSI only) - */ - if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { - nvram = pspi_data->nvram[id]; - nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8; - - if (width) - width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; - - if (offset > 0) { - /* Ensure factor is set to the - * maximum of: adapter, nvram, inquiry - */ - if (nfactor) { - if (nfactor < pspi_data->minSyncFactor ) - nfactor = pspi_data->minSyncFactor; - - factor = MAX (factor, nfactor); - if (factor == MPT_ASYNC) - offset = 0; - } else { - offset = 0; - factor = MPT_ASYNC; - } - } else { - factor = MPT_ASYNC; - } - } - - /* Make sure data is consistent - */ - if ((!width) && (factor < MPT_ULTRA2)) { - factor = MPT_ULTRA2; - } - - /* Save the data to the target structure. - */ - target->minSyncFactor = factor; - target->maxOffset = offset; - target->maxWidth = width; - if (canQ) { - target->tflags |= MPT_TARGET_FLAGS_Q_YES; - } - - target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO; - - /* Disable unused features. - */ - target->negoFlags = pspi_data->noQas; - if (!width) - target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE; - - if (!offset) - target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC; - - if (noQas) - target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; - - /* GEM, processor WORKAROUND - */ - if (((target->inq_data[0] & 0x1F) == 0x03) || ((target->inq_data[0] & 0x1F) > 0x08)){ - target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC); - pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO; - } - - /* Disable QAS if mixed configuration case - */ - if ((noQas) && (!pspi_data->noQas) && ((target->inq_data[0] & 0x1F) != 0x03)){ - VirtDevice *vdev; - int ii; - - ddvtprintk((KERN_INFO "Disabling QAS!\n")); - pspi_data->noQas = MPT_TARGET_NO_NEGO_QAS; - for (ii = 0; ii < id; ii++) { - vdev = hd->Targets[id]; - if (vdev != NULL) - vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS; - } - } - } - - return; -} - -/* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return. - * Else set the NEED_DV flag after Read Capacity Issued (disks) - * or Mode Sense (cdroms). - * - * Tapes, initTarget will set this flag on completion of Inquiry command. - * Called only if DV_NOT_DONE flag is set - */ -static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq) -{ - u8 cmd; - - if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0)) - return; - - cmd = pReq->CDB[0]; - - if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) { - ScsiCfgData *pSpi = &hd->ioc->spi_data; - if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) { - /* Set NEED_DV for all hidden disks - */ - Ioc3PhysDisk_t *pPDisk = pSpi->pIocPg3->PhysDisk; - int numPDisk = pSpi->pIocPg3->NumPhysDisks; - - while (numPDisk) { - pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV; - ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID)); - pPDisk++; - numPDisk--; - } - } - pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV; - ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID)); - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * If no Target, bus reset on 1st I/O. Set the flag to - * prevent any future negotiations to this device. - */ -static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id) -{ - - if ((hd->Targets) && (hd->Targets[target_id] == NULL)) - hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO; - - return; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * SCSI Config Page functionality ... - */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptscsih_setDevicePage1Flags - add Requested and Configuration fields flags - * based on width, factor and offset parameters. - * @width: bus width - * @factor: sync factor - * @offset: sync offset - * @requestedPtr: pointer to requested values (updated) - * @configurationPtr: pointer to configuration values (updated) - * @flags: flags to block WDTR or SDTR negotiation - * - * Return: None. - * - * Remark: Called by writeSDP1 and _dv_params - */ -static void -mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags) -{ - u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE; - u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC; - - *configurationPtr = 0; - *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0; - *requestedPtr |= (offset << 16) | (factor << 8); - - if (width && offset && !nowide && !nosync) { - if (factor < MPT_ULTRA160) { - *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT); - if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0) - *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS; - } else if (factor < MPT_ULTRA2) { - *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT; - } - } - - if (nowide) - *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED; - - if (nosync) - *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED; - - return; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptscsih_writeSDP1 - write SCSI Device Page 1 - * @hd: Pointer to a SCSI Host Strucutre - * @portnum: IOC port number - * @target_id: writeSDP1 for single ID - * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO - * - * Return: -EFAULT if read of config page header fails - * or 0 if success. - * - * Remark: If a target has been found, the settings from the - * target structure are used, else the device is set - * to async/narrow. - * - * Remark: Called during init and after a FW reload. - * Remark: We do not wait for a return, write pages sequentially. - */ -static int -mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) -{ - MPT_ADAPTER *ioc = hd->ioc; - Config_t *pReq = NULL; - SCSIDevicePage1_t *pData = NULL; - VirtDevice *pTarget = NULL; - MPT_FRAME_HDR *mf; - dma_addr_t dataDma; - u16 req_idx; - u32 frameOffset; - u32 requested, configuration, flagsLength; - int ii, nvram; - int id = 0, maxid = 0; - u8 width; - u8 factor; - u8 offset; - u8 bus = 0; - u8 negoFlags; - u8 maxwidth, maxoffset, maxfactor; - - - if (ioc->spi_data.sdp1length == 0) - return 0; - - if (flags & MPT_SCSICFG_ALL_IDS) { - id = 0; - maxid = ioc->sh->max_id - 1; - } else if (ioc->sh) { - id = target_id; - maxid = MIN(id, ioc->sh->max_id - 1); - } - - for (; id <= maxid; id++) { - - if (id == ioc->pfacts[portnum].PortSCSIID) - continue; - - /* Use NVRAM to get adapter and target maximums - * Data over-riden by target structure information, if present - */ - maxwidth = ioc->spi_data.maxBusWidth; - maxoffset = ioc->spi_data.maxSyncOffset; - maxfactor = ioc->spi_data.minSyncFactor; - if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { - nvram = ioc->spi_data.nvram[id]; - - if (maxwidth) - maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; - - if (maxoffset > 0) { - maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8; - if (maxfactor == 0) { - /* Key for async */ - maxfactor = MPT_ASYNC; - maxoffset = 0; - } else if (maxfactor < ioc->spi_data.minSyncFactor) { - maxfactor = ioc->spi_data.minSyncFactor; - } - } else - maxfactor = MPT_ASYNC; - } - - /* Set the negotiation flags. - */ - negoFlags = ioc->spi_data.noQas; - if (!maxwidth) - negoFlags |= MPT_TARGET_NO_NEGO_WIDE; - - if (!maxoffset) - negoFlags |= MPT_TARGET_NO_NEGO_SYNC; - - if (flags & MPT_SCSICFG_USE_NVRAM) { - width = maxwidth; - factor = maxfactor; - offset = maxoffset; - } else { - width = 0; - factor = MPT_ASYNC; - offset = 0; - //negoFlags = 0; - //negoFlags = MPT_TARGET_NO_NEGO_SYNC; - } - -#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION - /* Force to async and narrow if DV has not been executed - * for this ID - */ - if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) { - width = 0; - factor = MPT_ASYNC; - offset = 0; - } -#endif - - /* If id is not a raid volume, get the updated - * transmission settings from the target structure. - */ - if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) { - width = pTarget->maxWidth; - factor = pTarget->minSyncFactor; - offset = pTarget->maxOffset; - negoFlags = pTarget->negoFlags; - pTarget = NULL; - } - - if (flags & MPT_SCSICFG_BLK_NEGO) - negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC; - - mptscsih_setDevicePage1Flags(width, factor, offset, - &requested, &configuration, negoFlags); - - /* Get a MF for this command. - */ - if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc->id)) == NULL) { - dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n", - ioc->name)); - return -EAGAIN; - } - - ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n", - hd->ioc->name, mf, id, requested, configuration)); - - - /* Set the request and the data pointers. - * Request takes: 36 bytes (32 bit SGE) - * SCSI Device Page 1 requires 16 bytes - * 40 + 16 <= size of SCSI IO Request = 56 bytes - * and MF size >= 64 bytes. - * Place data at end of MF. - */ - pReq = (Config_t *)mf; - - req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); - frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t); - - pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset); - dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset; - - /* Complete the request frame (same for all requests). - */ - pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; - pReq->Reserved = 0; - pReq->ChainOffset = 0; - pReq->Function = MPI_FUNCTION_CONFIG; - pReq->Reserved1[0] = 0; - pReq->Reserved1[1] = 0; - pReq->Reserved1[2] = 0; - pReq->MsgFlags = 0; - for (ii=0; ii < 8; ii++) { - pReq->Reserved2[ii] = 0; - } - pReq->Header.PageVersion = ioc->spi_data.sdp1version; - pReq->Header.PageLength = ioc->spi_data.sdp1length; - pReq->Header.PageNumber = 1; - pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; - pReq->PageAddress = cpu_to_le32(id | (bus << 8 )); - - /* Add a SGE to the config request. - */ - flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4; - - mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); - - /* Set up the common data portion - */ - pData->Header.PageVersion = pReq->Header.PageVersion; - pData->Header.PageLength = pReq->Header.PageLength; - pData->Header.PageNumber = pReq->Header.PageNumber; - pData->Header.PageType = pReq->Header.PageType; - pData->RequestedParameters = cpu_to_le32(requested); - pData->Reserved = 0; - pData->Configuration = cpu_to_le32(configuration); - - dprintk((MYIOC_s_INFO_FMT - "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n", - ioc->name, id, (id | (bus<<8)), - requested, configuration)); - - mptscsih_put_msgframe(ScsiDoneCtx, ioc->id, mf); - } - - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptscsih_taskmgmt_timeout - Call back for timeout on a - * task management request. - * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long - * - */ -static void mptscsih_taskmgmt_timeout(unsigned long data) -{ - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data; - - dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_taskmgmt_timeout: " - "TM request timed out!\n", hd->ioc->name)); - - /* Delete the timer that triggered this callback. - * Remark: del_timer checks to make sure timer is active - * before deleting. - */ - del_timer(&hd->TMtimer); - - /* Call the reset handler. Already had a TM request - * timeout - so issue a diagnostic reset - */ - if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) { - printk((KERN_WARNING " Firmware Reload FAILED!!\n")); - } -#ifdef MPT_SCSI_USE_NEW_EH - else { - /* Because we have reset the IOC, no TM requests can be - * pending. So let's make sure the tmPending flag is reset. - */ - nehprintk((KERN_WARNING MYNAM - ": %s: mptscsih_taskmgmt_timeout\n", - hd->ioc->name)); - hd->tmPending = 0; - } -#endif - - return; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Bus Scan and Domain Validation functionality ... - */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_scandv_complete - Scan and DV callback routine registered - * to Fustion MPT (base) driver. - * - * @ioc: Pointer to MPT_ADAPTER structure - * @mf: Pointer to original MPT request frame - * @mr: Pointer to MPT reply frame (NULL if TurboReply) - * - * This routine is called from mpt.c::mpt_interrupt() at the completion - * of any SCSI IO request. - * This routine is registered with the Fusion MPT (base) driver at driver - * load/init time via the mpt_register() API call. - * - * Returns 1 indicating alloc'd request frame ptr should be freed. - * - * Remark: Sets a completion code and (possibly) saves sense data - * in the IOC member localReply structure. - * Used ONLY for DV and other internal commands. - */ -static int -mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) -{ - MPT_SCSI_HOST *hd; - SCSIIORequest_t *pReq; - int completionCode; - u16 req_idx; - - if ((mf == NULL) || - (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) { - printk(MYIOC_s_ERR_FMT - "ScanDvComplete, %s req frame ptr! (=%p)\n", - ioc->name, mf?"BAD":"NULL", (void *) mf); - goto wakeup; - } - - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - del_timer(&hd->timer); - req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); - hd->ScsiLookup[req_idx] = NULL; - pReq = (SCSIIORequest_t *) mf; - - if (mf != hd->cmdPtr) { - printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n", - hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx); - } - hd->cmdPtr = NULL; - - ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n", - hd->ioc->name, mf, mr, req_idx)); - - atomic_dec(&queue_depth); - - hd->pLocal = &hd->localReply; - hd->pLocal->scsiStatus = 0; - - /* If target struct exists, clear sense valid flag. - */ - if (mr == NULL) { - completionCode = MPT_SCANDV_GOOD; - } else { - SCSIIOReply_t *pReply; - u16 status; - - pReply = (SCSIIOReply_t *) mr; - - status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; - - ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n", - status, pReply->SCSIState, pReply->SCSIStatus, - le32_to_cpu(pReply->IOCLogInfo))); - - switch(status) { - - case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ - completionCode = MPT_SCANDV_SELECTION_TIMEOUT; - break; - - case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ - case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ - case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ - case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ - completionCode = MPT_SCANDV_DID_RESET; - break; - - case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ - case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ - case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ - if (pReply->Function == MPI_FUNCTION_CONFIG) { - ConfigReply_t *pr = (ConfigReply_t *)mr; - completionCode = MPT_SCANDV_GOOD; - hd->pLocal->header.PageVersion = pr->Header.PageVersion; - hd->pLocal->header.PageLength = pr->Header.PageLength; - hd->pLocal->header.PageNumber = pr->Header.PageNumber; - hd->pLocal->header.PageType = pr->Header.PageType; - - } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) { - /* If the RAID Volume request is successful, - * return GOOD, else indicate that - * some type of error occurred. - */ - MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr; - if (pr->ActionStatus == MPI_RAID_ACTION_ASTATUS_SUCCESS) - completionCode = MPT_SCANDV_GOOD; - else - completionCode = MPT_SCANDV_SOME_ERROR; - - } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) { - u8 *sense_data; - int sz; - - /* save sense data in global structure - */ - completionCode = MPT_SCANDV_SENSE; - hd->pLocal->scsiStatus = pReply->SCSIStatus; - sense_data = ((u8 *)hd->ioc->sense_buf_pool + - (req_idx * MPT_SENSE_BUFFER_ALLOC)); - - sz = MIN (pReq->SenseBufferLength, - SCSI_STD_SENSE_BYTES); - memcpy(hd->pLocal->sense, sense_data, sz); - - ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n", - sense_data)); - } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) { - if (pReq->CDB[0] == CMD_Inquiry) - completionCode = MPT_SCANDV_ISSUE_SENSE; - else - completionCode = MPT_SCANDV_DID_RESET; - } - else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS) - completionCode = MPT_SCANDV_DID_RESET; - else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) - completionCode = MPT_SCANDV_DID_RESET; - else { - /* If no error, this will be equivalent - * to MPT_SCANDV_GOOD - */ - completionCode = MPT_SCANDV_GOOD; - hd->pLocal->scsiStatus = pReply->SCSIStatus; - } - break; - - case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ - if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) - completionCode = MPT_SCANDV_DID_RESET; - else - completionCode = MPT_SCANDV_SOME_ERROR; - break; - - default: - completionCode = MPT_SCANDV_SOME_ERROR; - break; - - } /* switch(status) */ - - ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n", - completionCode)); - } /* end of address reply case */ - - hd->pLocal->completion = completionCode; - - /* MF and RF are freed in mpt_interrupt - */ -wakeup: - /* Free Chain buffers (will never chain) in scan or dv */ - //mptscsih_freeChainBuffers(hd, req_idx); - - /* - * Wake up the original calling thread - */ - scandv_wait_done = 1; -/* SAE: No wait queues */ -#ifdef XEN_KILLED - wake_up(&scandv_waitq); -#else - mdelay(100); -#endif - - return 1; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptscsih_timer_expired - Call back for timer process. - * Used only for dv functionality. - * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long - * - */ -static void mptscsih_timer_expired(unsigned long data) -{ - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data; -#ifndef MPT_SCSI_USE_NEW_EH - unsigned long flags; -#endif - - - ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr)); - - if (hd->cmdPtr) { - MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr; - - if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) { - /* Desire to issue a task management request here. - * TM requests MUST be single threaded. - * If old eh code and no TM current, issue request. - * If new eh code, do nothing. Wait for OS cmd timeout - * for bus reset. - */ -#ifndef MPT_SCSI_USE_NEW_EH - SCSIIORequest_t *pReq = (SCSIIORequest_t *) hd->cmdPtr; - - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - if (hd->tmPending) { - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - return; - } else - hd->tmPending = 1; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - pReq->Bus, 0, 0, 0, NO_SLEEP) < 0) { - printk(MYIOC_s_WARN_FMT "TM FAILED!\n", hd->ioc->name); - } -#else - ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name)); -#endif - } else { - /* Perform a FW reload */ - if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) { - printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name); - } - } - } else { - /* This should NEVER happen */ - printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name); - } - - /* No more processing. - * TM call will generate an interrupt for SCSI TM Management. - * The FW will reply to all outstanding commands, callback will finish cleanup. - * Hard reset clean-up will free all resources. - */ - ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name)); - - return; -} - -#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptscsih_do_raid - Format and Issue a RAID volume request message. - * @hd: Pointer to scsi host structure - * @action: What do be done. - * @id: Logical target id. - * @bus: Target locations bus. - * - * Returns: < 0 on a fatal error - * 0 on success - * - * Remark: Wait to return until reply processed by the ISR. - */ -static int -mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io) -{ - MpiRaidActionRequest_t *pReq; - MPT_FRAME_HDR *mf; - int in_isr; - - in_isr = in_interrupt(); - if (in_isr) { - dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n", - hd->ioc->name)); - return -EPERM; - } - - /* Get and Populate a free Frame - */ - if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc->id)) == NULL) { - ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n", - hd->ioc->name)); - return -EAGAIN; - } - pReq = (MpiRaidActionRequest_t *)mf; - pReq->Action = action; - pReq->Reserved1 = 0; - pReq->ChainOffset = 0; - pReq->Function = MPI_FUNCTION_RAID_ACTION; - pReq->VolumeID = io->id; - pReq->VolumeBus = io->bus; - pReq->PhysDiskNum = io->physDiskNum; - pReq->MsgFlags = 0; - pReq->Reserved2 = 0; - pReq->ActionDataWord = 0; /* Reserved for this action */ - //pReq->ActionDataSGE = 0; - - mpt_add_sge((char *)&pReq->ActionDataSGE, - MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); - - ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n", - hd->ioc->name, action, io->id)); - - hd->pLocal = NULL; - hd->timer.expires = jiffies + HZ*2; /* 2 second timeout */ - scandv_wait_done = 0; - - /* Save cmd pointer, for resource free if timeout or - * FW reload occurs - */ - hd->cmdPtr = mf; - - add_timer(&hd->timer); - mptscsih_put_msgframe(ScsiScanDvCtx, hd->ioc->id, mf); -/* SAE: No wait queues */ -#ifdef XEN_KILLED - wait_event(scandv_waitq, scandv_wait_done); -#else - /* SAE: Decrease the wait time: 100 -> 1 */ - while(!scandv_wait_done) { - mdelay(1); - } -#endif - - if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD)) - return -1; - - return 0; -} -#endif /* ~MPTSCSIH_DISABLE_DOMAIN_VALIDATION */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_do_cmd - Do internal command. - * @hd: MPT_SCSI_HOST pointer - * @io: INTERNAL_CMD pointer. - * - * Issue the specified internally generated command and do command - * specific cleanup. For bus scan / DV only. - * NOTES: If command is Inquiry and status is good, - * initialize a target structure, save the data - * - * Remark: Single threaded access only. - * - * Return: - * < 0 if an illegal command or no resources - * - * 0 if good - * - * > 0 if command complete but some type of completion error. - */ -static int -mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) -{ - MPT_FRAME_HDR *mf; - SCSIIORequest_t *pScsiReq; - SCSIIORequest_t ReqCopy; - int my_idx, ii, dir; - int rc, cmdTimeout; - int in_isr; - char cmdLen; - char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - char cmd = io->cmd; - - in_isr = in_interrupt(); - - if (in_isr) { - dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n", - hd->ioc->name)); - return -EPERM; - } - - - /* Set command specific information - */ - switch (cmd) { - case CMD_Inquiry: - cmdLen = 6; - dir = MPI_SCSIIO_CONTROL_READ; - CDB[0] = cmd; - CDB[4] = io->size; - cmdTimeout = 10; - break; - - case CMD_TestUnitReady: - cmdLen = 6; - dir = MPI_SCSIIO_CONTROL_READ; - cmdTimeout = 10; - break; - - case CMD_StartStopUnit: - cmdLen = 6; - dir = MPI_SCSIIO_CONTROL_READ; - CDB[0] = cmd; - CDB[4] = 1; /*Spin up the disk */ - cmdTimeout = 15; - break; - - case CMD_RequestSense: - cmdLen = 6; - CDB[0] = cmd; - CDB[4] = io->size; - dir = MPI_SCSIIO_CONTROL_READ; - cmdTimeout = 10; - break; - - case CMD_ReadBuffer: - cmdLen = 10; - dir = MPI_SCSIIO_CONTROL_READ; - CDB[0] = cmd; - if (io->flags & MPT_ICFLAG_ECHO) { - CDB[1] = 0x0A; - } else { - CDB[1] = 0x02; - } - - if (io->flags & MPT_ICFLAG_BUF_CAP) { - CDB[1] |= 0x01; - } - CDB[6] = (io->size >> 16) & 0xFF; - CDB[7] = (io->size >> 8) & 0xFF; - CDB[8] = io->size & 0xFF; - cmdTimeout = 10; - break; - - case CMD_WriteBuffer: - cmdLen = 10; - dir = MPI_SCSIIO_CONTROL_WRITE; - CDB[0] = cmd; - if (io->flags & MPT_ICFLAG_ECHO) { - CDB[1] = 0x0A; - } else { - CDB[1] = 0x02; - } - CDB[6] = (io->size >> 16) & 0xFF; - CDB[7] = (io->size >> 8) & 0xFF; - CDB[8] = io->size & 0xFF; - cmdTimeout = 10; - break; - - case CMD_Reserve6: - cmdLen = 6; - dir = MPI_SCSIIO_CONTROL_READ; - CDB[0] = cmd; - cmdTimeout = 10; - break; - - case CMD_Release6: - cmdLen = 6; - dir = MPI_SCSIIO_CONTROL_READ; - CDB[0] = cmd; - cmdTimeout = 10; - break; - - case CMD_SynchronizeCache: - cmdLen = 10; - dir = MPI_SCSIIO_CONTROL_READ; - CDB[0] = cmd; -// CDB[1] = 0x02; /* set immediate bit */ - cmdTimeout = 10; - break; - - default: - /* Error Case */ - return -EFAULT; - } - - /* Get and Populate a free Frame - */ - if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc->id)) == NULL) { - ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n", - hd->ioc->name)); - return -EBUSY; - } - - pScsiReq = (SCSIIORequest_t *) mf; - - /* Get the request index */ - my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); - ADD_INDEX_LOG(my_idx); /* for debug */ - - if (io->flags & MPT_ICFLAG_PHYS_DISK) { - pScsiReq->TargetID = io->physDiskNum; - pScsiReq->Bus = 0; - pScsiReq->ChainOffset = 0; - pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; - } else { - pScsiReq->TargetID = io->id; - pScsiReq->Bus = io->bus; - pScsiReq->ChainOffset = 0; - pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; - } - - pScsiReq->CDBLength = cmdLen; - pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; - - pScsiReq->Reserved = 0; - - pScsiReq->MsgFlags = mpt_msg_flags(); - /* MsgContext set in mpt_get_msg_fram call */ - - for (ii=0; ii < 8; ii++) - pScsiReq->LUN[ii] = 0; - pScsiReq->LUN[1] = io->lun; - - if (io->flags & MPT_ICFLAG_TAGGED_CMD) - pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ); - else - pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); - - if (cmd == CMD_RequestSense) { - pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); - ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n", - hd->ioc->name, cmd)); - } - - for (ii=0; ii < 16; ii++) - pScsiReq->CDB[ii] = CDB[ii]; - - pScsiReq->DataLength = cpu_to_le32(io->size); - pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma - + (my_idx * MPT_SENSE_BUFFER_ALLOC)); - - ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n", - hd->ioc->name, cmd, io->bus, io->id, io->lun)); - - if (dir == MPI_SCSIIO_CONTROL_READ) { - mpt_add_sge((char *) &pScsiReq->SGL, - MPT_SGE_FLAGS_SSIMPLE_READ | io->size, - io->data_dma); - } else { - mpt_add_sge((char *) &pScsiReq->SGL, - MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, - io->data_dma); - } - - /* The ISR will free the request frame, but we need - * the information to initialize the target. Duplicate. - */ - memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t)); - - /* Issue this command after: - * finish init - * add timer - * Wait until the reply has been received - * ScsiScanDvCtx callback function will - * set hd->pLocal; - * set scandv_wait_done and call wake_up - */ - hd->pLocal = NULL; - hd->timer.expires = jiffies + HZ*cmdTimeout; - scandv_wait_done = 0; - - /* Save cmd pointer, for resource free if timeout or - * FW reload occurs - */ - hd->cmdPtr = mf; - - add_timer(&hd->timer); - mptscsih_put_msgframe(ScsiScanDvCtx, hd->ioc->id, mf); -/* SAE: No wait queues */ -#ifdef XEN_KILLED - wait_event(scandv_waitq, scandv_wait_done); -#else - /* SAE: Decrease the wait time: 100 -> 1 */ - while(!scandv_wait_done) { - mdelay(1); - } -#endif - - if (hd->pLocal) { - rc = hd->pLocal->completion; - hd->pLocal->skip = 0; - - /* Always set fatal error codes in some cases. - */ - if (rc == MPT_SCANDV_SELECTION_TIMEOUT) - rc = -ENXIO; - else if (rc == MPT_SCANDV_SOME_ERROR) - rc = -rc; - } else { - rc = -EFAULT; - /* This should never happen. */ - ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n", - hd->ioc->name)); - } - - return rc; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks. - * @hd: Pointer to MPT_SCSI_HOST structure - * @portnum: IOC port number - * - * Uses the ISR, but with special processing. - * MUST be single-threaded. - * - * Return: 0 on completion - */ -static int -mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum) -{ - MPT_ADAPTER *ioc= hd->ioc; - VirtDevice *pTarget = NULL; - SCSIDevicePage1_t *pcfg1Data = NULL; - INTERNAL_CMD iocmd; - CONFIGPARMS cfg; - dma_addr_t cfg1_dma_addr = -1; - ConfigPageHeader_t header1; - int bus = 0; - int id = 0; - int lun = 0; - int hostId = ioc->pfacts[portnum].PortSCSIID; - int max_id; - int requested, configuration, data; - int doConfig = 0; - u8 flags, factor; - - max_id = ioc->sh->max_id - 1; - - /* Following parameters will not change - * in this routine. - */ - iocmd.cmd = CMD_SynchronizeCache; - iocmd.flags = 0; - iocmd.physDiskNum = -1; - iocmd.data = NULL; - iocmd.data_dma = -1; - iocmd.size = 0; - iocmd.rsvd = iocmd.rsvd2 = 0; - - /* No SCSI hosts - */ - if (hd->Targets == NULL) - return 0; - - /* Skip the host - */ - if (id == hostId) - id++; - - /* Write SDP1 for all SCSI devices - * Alloc memory and set up config buffer - */ - if (hd->is_spi) { - if (ioc->spi_data.sdp1length > 0) { - pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev, - ioc->spi_data.sdp1length * 4, &cfg1_dma_addr); - - if (pcfg1Data != NULL) { - doConfig = 1; - header1.PageVersion = ioc->spi_data.sdp1version; - header1.PageLength = ioc->spi_data.sdp1length; - header1.PageNumber = 1; - header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; - cfg.hdr = &header1; - cfg.physAddr = cfg1_dma_addr; - cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; - cfg.dir = 1; - cfg.timeout = 0; - } - } - } - - /* loop through all devices on this port - */ - while (bus < MPT_MAX_BUS) { - iocmd.bus = bus; - iocmd.id = id; - pTarget = hd->Targets[(int)id]; - - if (doConfig) { - - /* Set the negotiation flags */ - if (pTarget && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) { - flags = pTarget->negoFlags; - } else { - flags = hd->ioc->spi_data.noQas; - if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { - data = hd->ioc->spi_data.nvram[id]; - - if (data & MPT_NVRAM_WIDE_DISABLE) - flags |= MPT_TARGET_NO_NEGO_WIDE; - - factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT; - if ((factor == 0) || (factor == MPT_ASYNC)) - flags |= MPT_TARGET_NO_NEGO_SYNC; - } - } - - /* Force to async, narrow */ - mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested, - &configuration, flags); - pcfg1Data->RequestedParameters = le32_to_cpu(requested); - pcfg1Data->Reserved = 0; - pcfg1Data->Configuration = le32_to_cpu(configuration); - cfg.pageAddr = (bus<<8) | id; - mpt_config(hd->ioc, &cfg); - } - - /* If target Ptr NULL or if this target is NOT a disk, skip. - */ - // if (pTarget && ((pTarget->inq_data[0] & 0x1F) == 0)) { - if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){ - for (lun=0; lun <= MPT_LAST_LUN; lun++) { - /* If LUN present, issue the command - */ - if (pTarget->luns & (1< max_id) { - id = 0; - bus++; - } - } - - if (pcfg1Data) { - pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr); - } - - return 0; -} - -#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_domainValidation - Top level handler for domain validation. - * @hd: Pointer to MPT_SCSI_HOST structure. - * - * Uses the ISR, but with special processing. - * Called from schedule, should not be in interrupt mode. - * While thread alive, do dv for all devices needing dv - * - * Return: None. - */ -static void -mptscsih_domainValidation(void *arg) -{ - MPT_SCSI_HOST *hd = NULL; - MPT_ADAPTER *ioc = NULL; - unsigned long flags; - int id, maxid, dvStatus, did; - int ii, isPhysDisk; - - spin_lock_irqsave(&dvtaskQ_lock, flags); - dvtaskQ_active = 1; - if (dvtaskQ_release) { - dvtaskQ_active = 0; - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - return; - } - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - - /* For this ioc, loop through all devices and do dv to each device. - * When complete with this ioc, search through the ioc list, and - * for each scsi ioc found, do dv for all devices. Exit when no - * device needs dv. - */ - did = 1; - while (did) { - did = 0; - for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) { - spin_lock_irqsave(&dvtaskQ_lock, flags); - if (dvtaskQ_release) { - dvtaskQ_active = 0; - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - return; - } - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - -/* SAE: */ -#ifdef XEN_KILLED - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); -#else - /* SAE: Decrease the wait time: 250 -> 100 */ - mdelay(100); -#endif - - /* DV only to SCSI adapters */ - if ((int)ioc->chip_type <= (int)FC929) - continue; - - /* Make sure everything looks ok */ - if (ioc->sh == NULL) - continue; - - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - if (hd == NULL) - continue; - - if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) { - mpt_read_ioc_pg_3(ioc); - if (ioc->spi_data.pIocPg3) { - Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk; - int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks; - - while (numPDisk) { - if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE) - ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV; - - pPDisk++; - numPDisk--; - } - } - ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3; - } - - maxid = MIN (ioc->sh->max_id, MPT_MAX_SCSI_DEVICES); - - for (id = 0; id < maxid; id++) { - spin_lock_irqsave(&dvtaskQ_lock, flags); - if (dvtaskQ_release) { - dvtaskQ_active = 0; - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - return; - } - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - dvStatus = hd->ioc->spi_data.dvStatus[id]; - - if (dvStatus & MPT_SCSICFG_NEED_DV) { - did++; - hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING; - hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV; - -/* SAE: */ -#ifdef XEN_KILLED - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); -#else - /* SAE: Decrease the wait time: 250 -> 100 */ - mdelay(100); -#endif - - /* If hidden phys disk, block IO's to all - * raid volumes - * else, process normally - */ - isPhysDisk = mptscsih_is_phys_disk(ioc, id); - if (isPhysDisk) { - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { - if (hd->ioc->spi_data.isRaid & (1 << ii)) { - hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING; - } - } - } - - if (mptscsih_doDv(hd, 0, id) == 1) { - /* Untagged device was busy, try again - */ - hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV; - hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING; - } else { - /* DV is complete. Clear flags. - */ - hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING); - } - - if (isPhysDisk) { - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { - if (hd->ioc->spi_data.isRaid & (1 << ii)) { - hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING; - } - } - } - - /* Post OS IOs that were pended while - * DV running. - */ - post_pendingQ_commands(hd); - - if (hd->ioc->spi_data.noQas) - mptscsih_qas_check(hd, id); - } - } - } - } - - spin_lock_irqsave(&dvtaskQ_lock, flags); - dvtaskQ_active = 0; - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - - return; -} - -/* Search IOC page 3 to determine if this is hidden physical disk - */ -static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) -{ - if (ioc->spi_data.pIocPg3) { - Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk; - int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks; - - while (numPDisk) { - if (pPDisk->PhysDiskID == id) { - return 1; - } - pPDisk++; - numPDisk--; - } - } - return 0; -} - -/* Write SDP1 if no QAS has been enabled - */ -static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id) -{ - VirtDevice *pTarget = NULL; - int ii; - - if (hd->Targets == NULL) - return; - - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { - if (ii == id) - continue; - - if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0) - continue; - - pTarget = hd->Targets[ii]; - - if ((pTarget != NULL) && (!pTarget->raidVolume)) { - if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) { - pTarget->negoFlags |= hd->ioc->spi_data.noQas; - mptscsih_writeSDP1(hd, 0, ii, 0); - } - } else { - if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) - mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM); - } - } - return; -} - - - -#define MPT_GET_NVRAM_VALS 0x01 -#define MPT_UPDATE_MAX 0x02 -#define MPT_SET_MAX 0x04 -#define MPT_SET_MIN 0x08 -#define MPT_FALLBACK 0x10 -#define MPT_SAVE 0x20 - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_doDv - Perform domain validation to a target. - * @hd: Pointer to MPT_SCSI_HOST structure. - * @portnum: IOC port number. - * @target: Physical ID of this target - * - * Uses the ISR, but with special processing. - * MUST be single-threaded. - * Test will exit if target is at async & narrow. - * - * Return: None. - */ -static int -mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) -{ - MPT_ADAPTER *ioc = hd->ioc; - VirtDevice *pTarget = NULL; - SCSIDevicePage1_t *pcfg1Data = NULL; - SCSIDevicePage0_t *pcfg0Data = NULL; - u8 *pbuf1 = NULL; - u8 *pbuf2 = NULL; - u8 *pDvBuf = NULL; - dma_addr_t dvbuf_dma = -1; - dma_addr_t buf1_dma = -1; - dma_addr_t buf2_dma = -1; - dma_addr_t cfg1_dma_addr = -1; - dma_addr_t cfg0_dma_addr = -1; - ConfigPageHeader_t header1; - ConfigPageHeader_t header0; - DVPARAMETERS dv; - INTERNAL_CMD iocmd; - CONFIGPARMS cfg; - int dv_alloc = 0; - int rc, sz = 0; - int bufsize = 0; - int dataBufSize = 0; - int echoBufSize = 0; - int notDone; - int patt; - int repeat; - int retcode = 0; - int nfactor = MPT_ULTRA320; - char firstPass = 1; - char doFallback = 0; - char readPage0; - char bus, lun; - char inq0 = 0; - - if (ioc->spi_data.sdp1length == 0) - return 0; - - if (ioc->spi_data.sdp0length == 0) - return 0; - - /* If multiple buses are used, require that the initiator - * id be the same on all buses. - */ - if (id == ioc->pfacts[0].PortSCSIID) - return 0; - - lun = 0; - bus = (u8) bus_number; - ddvtprintk((MYIOC_s_NOTE_FMT - "DV started: numIOs %d bus=%d, id %d dv @ %p\n", - ioc->name, atomic_read(&queue_depth), bus, id, &dv)); - - /* Prep DV structure - */ - memset (&dv, 0, sizeof(DVPARAMETERS)); - dv.id = id; - - /* Populate tmax with the current maximum - * transfer parameters for this target. - * Exit if narrow and async. - */ - dv.cmd = MPT_GET_NVRAM_VALS; - mptscsih_dv_parms(hd, &dv, NULL); - if ((!dv.max.width) && (!dv.max.offset)) - return 0; - - /* Prep SCSI IO structure - */ - iocmd.id = id; - iocmd.bus = bus; - iocmd.lun = lun; - iocmd.flags = 0; - iocmd.physDiskNum = -1; - iocmd.rsvd = iocmd.rsvd2 = 0; - - pTarget = hd->Targets[id]; - if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) { - /* Another GEM workaround. Check peripheral device type, - * if PROCESSOR, quit DV. - */ - if (((pTarget->inq_data[0] & 0x1F) == 0x03) || ((pTarget->inq_data[0] & 0x1F) > 0x08)) { - pTarget->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC); - return 0; - } - } - - /* Use tagged commands if possible. - */ - if (pTarget) { - if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES) - iocmd.flags |= MPT_ICFLAG_TAGGED_CMD; - else { - if (hd->ioc->facts.FWVersion.Word < 0x01000600) - return 0; - - if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) && - (hd->ioc->facts.FWVersion.Word < 0x01010B00)) - return 0; - } - } - - /* Prep cfg structure - */ - cfg.pageAddr = (bus<<8) | id; - cfg.hdr = NULL; - - /* Prep SDP0 header - */ - header0.PageVersion = ioc->spi_data.sdp0version; - header0.PageLength = ioc->spi_data.sdp0length; - header0.PageNumber = 0; - header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; - - /* Prep SDP1 header - */ - header1.PageVersion = ioc->spi_data.sdp1version; - header1.PageLength = ioc->spi_data.sdp1length; - header1.PageNumber = 1; - header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; - - if (header0.PageLength & 1) - dv_alloc = (header0.PageLength * 4) + 4; - - dv_alloc += (2048 + (header1.PageLength * 4)); - - pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma); - if (pDvBuf == NULL) - return 0; - - sz = 0; - pbuf1 = (u8 *)pDvBuf; - buf1_dma = dvbuf_dma; - sz +=1024; - - pbuf2 = (u8 *) (pDvBuf + sz); - buf2_dma = dvbuf_dma + sz; - sz +=1024; - - pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz); - cfg0_dma_addr = dvbuf_dma + sz; - sz += header0.PageLength * 4; - - /* 8-byte alignment - */ - if (header0.PageLength & 1) - sz += 4; - - pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz); - cfg1_dma_addr = dvbuf_dma + sz; - - /* Skip this ID? Set cfg.hdr to force config page write - */ - { - ScsiCfgData *pspi_data = &hd->ioc->spi_data; - if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { - /* Set the factor from nvram */ - nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8; - if (nfactor < pspi_data->minSyncFactor ) - nfactor = pspi_data->minSyncFactor; - - if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE)) { - - ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n", - ioc->name, bus, id, lun)); - - dv.cmd = MPT_SET_MAX; - mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); - cfg.hdr = &header1; - - /* Save the final negotiated settings to - * SCSI device page 1. - */ - cfg.physAddr = cfg1_dma_addr; - cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; - cfg.dir = 1; - mpt_config(hd->ioc, &cfg); - goto target_done; - } - } - } - - /* Finish iocmd inititialization - hidden or visible disk? */ - if (ioc->spi_data.pIocPg3) { - /* Searc IOC page 3 for matching id - */ - Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk; - int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks; - - while (numPDisk) { - if (pPDisk->PhysDiskID == id) { - /* match */ - iocmd.flags |= MPT_ICFLAG_PHYS_DISK; - iocmd.physDiskNum = pPDisk->PhysDiskNum; - - /* Quiesce the IM - */ - if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) { - ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name)); - goto target_done; - } - break; - } - pPDisk++; - numPDisk--; - } - } - - /* RAID Volume ID's may double for a physical device. If RAID but - * not a physical ID as well, skip DV. - */ - if ((hd->ioc->spi_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK)) - goto target_done; - - - /* Basic Test. - * Async & Narrow - Inquiry - * Async & Narrow - Inquiry - * Maximum transfer rate - Inquiry - * Compare buffers: - * If compare, test complete. - * If miscompare and first pass, repeat - * If miscompare and not first pass, fall back and repeat - */ - hd->pLocal = NULL; - readPage0 = 0; - sz = SCSI_STD_INQUIRY_BYTES; - rc = MPT_SCANDV_GOOD; - while (1) { - ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test.\n", ioc->name)); - retcode = 0; - dv.cmd = MPT_SET_MIN; - mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); - - cfg.hdr = &header1; - cfg.physAddr = cfg1_dma_addr; - cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; - cfg.dir = 1; - if (mpt_config(hd->ioc, &cfg) != 0) - goto target_done; - - /* Wide - narrow - wide workaround case - */ - if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) { - /* Send an untagged command to reset disk Qs corrupted - * when a parity error occurs on a Request Sense. - */ - if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) || - ((hd->ioc->facts.FWVersion.Word >= 0x01010000) && - (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) { - - iocmd.cmd = CMD_RequestSense; - iocmd.data_dma = buf1_dma; - iocmd.data = pbuf1; - iocmd.size = 0x12; - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - else { - if (hd->pLocal == NULL) - goto target_done; - rc = hd->pLocal->completion; - if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) { - dv.max.width = 0; - doFallback = 0; - } else - goto target_done; - } - } else - goto target_done; - } - - iocmd.cmd = CMD_Inquiry; - iocmd.data_dma = buf1_dma; - iocmd.data = pbuf1; - iocmd.size = sz; - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - else { - if (hd->pLocal == NULL) - goto target_done; - rc = hd->pLocal->completion; - if (rc == MPT_SCANDV_GOOD) { - if (hd->pLocal->scsiStatus == STS_BUSY) { - if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0) - retcode = 1; - else - retcode = 0; - - goto target_done; - } - } else if (rc == MPT_SCANDV_SENSE) { - ; - } else { - /* If first command doesn't complete - * with a good status or with a check condition, - * exit. - */ - goto target_done; - } - } - - /* Reset the size for disks - */ - inq0 = (*pbuf1) & 0x1F; - if ((inq0 == 0) && pTarget && !pTarget->raidVolume) { - sz = 0x40; - iocmd.size = sz; - } - - /* Another GEM workaround. Check peripheral device type, - * if PROCESSOR, quit DV. - */ - if (((pbuf1[0] & 0x1F) == 0x03) || ((pbuf1[0] & 0x1F) > 0x08)) - goto target_done; - - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - - if (sz == 0x40) { - if ((pTarget->maxWidth == 1) && (pTarget->maxOffset) && (nfactor < 0x0A) - && (pTarget->minSyncFactor > 0x09)) { - if ((pbuf1[56] & 0x04) == 0) - ; - else if ((pbuf1[56] & 0x01) == 1) { - pTarget->minSyncFactor = nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320; - } else { - pTarget->minSyncFactor = nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160; - } - - dv.max.factor = pTarget->minSyncFactor; - - if ((pbuf1[56] & 0x02) == 0) { - pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS; - hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; - } - } - } - - if (doFallback) - dv.cmd = MPT_FALLBACK; - else - dv.cmd = MPT_SET_MAX; - - mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); - if (mpt_config(hd->ioc, &cfg) != 0) - goto target_done; - - if ((!dv.now.width) && (!dv.now.offset)) - goto target_done; - - iocmd.cmd = CMD_Inquiry; - iocmd.data_dma = buf2_dma; - iocmd.data = pbuf2; - iocmd.size = sz; - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - else if (hd->pLocal == NULL) - goto target_done; - else { - /* Save the return code. - * If this is the first pass, - * read SCSI Device Page 0 - * and update the target max parameters. - */ - rc = hd->pLocal->completion; - doFallback = 0; - if (rc == MPT_SCANDV_GOOD) { - if (!readPage0) { - u32 sdp0_info; - u32 sdp0_nego; - - cfg.hdr = &header0; - cfg.physAddr = cfg0_dma_addr; - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - cfg.dir = 0; - - if (mpt_config(hd->ioc, &cfg) != 0) - goto target_done; - - sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E; - sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8; - - /* Quantum and Fujitsu workarounds. - * Quantum: PPR U320 -> PPR reply with Ultra2 and wide - * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide - * Resetart with a request for U160. - */ - if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) { - doFallback = 1; - } else { - dv.cmd = MPT_UPDATE_MAX; - mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data); - /* Update the SCSI device page 1 area - */ - pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters; - readPage0 = 1; - } - } - - /* Quantum workaround. Restart this test will the fallback - * flag set. - */ - if (doFallback == 0) { - if (memcmp(pbuf1, pbuf2, sz) != 0) { - if (!firstPass) - doFallback = 1; - } else - break; /* test complete */ - } - - - } else if (rc == MPT_SCANDV_ISSUE_SENSE) - doFallback = 1; /* set fallback flag */ - else if ((rc == MPT_SCANDV_DID_RESET) || (rc == MPT_SCANDV_SENSE)) - doFallback = 1; /* set fallback flag */ - else - goto target_done; - - firstPass = 0; - } - } - ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test completed OK.\n", ioc->name)); - inq0 = (*pbuf1) & 0x1F; - - /* Continue only for disks - */ - if (inq0 != 0) - goto target_done; - - /* Start the Enhanced Test. - * 0) issue TUR to clear out check conditions - * 1) read capacity of echo (regular) buffer - * 2) reserve device - * 3) do write-read-compare data pattern test - * 4) release - * 5) update nego parms to target struct - */ - cfg.hdr = &header1; - cfg.physAddr = cfg1_dma_addr; - cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; - cfg.dir = 1; - - iocmd.cmd = CMD_TestUnitReady; - iocmd.data_dma = -1; - iocmd.data = NULL; - iocmd.size = 0; - notDone = 1; - while (notDone) { - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - - if (hd->pLocal == NULL) - goto target_done; - - rc = hd->pLocal->completion; - if (rc == MPT_SCANDV_GOOD) - notDone = 0; - else if (rc == MPT_SCANDV_SENSE) { - u8 skey = hd->pLocal->sense[2] & 0x0F; - u8 asc = hd->pLocal->sense[12]; - u8 ascq = hd->pLocal->sense[13]; - ddvprintk((MYIOC_s_INFO_FMT - "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", - ioc->name, skey, asc, ascq)); - - if (skey == SK_UNIT_ATTENTION) - notDone++; /* repeat */ - else if ((skey == SK_NOT_READY) && - (asc == 0x04)&&(ascq == 0x01)) { - /* wait then repeat */ - mdelay (2000); - notDone++; - } else if ((skey == SK_NOT_READY) && (asc == 0x3A)) { - /* no medium, try read test anyway */ - notDone = 0; - } else { - /* All other errors are fatal. - */ - ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.", - ioc->name)); - goto target_done; - } - } else - goto target_done; - } - - iocmd.cmd = CMD_ReadBuffer; - iocmd.data_dma = buf1_dma; - iocmd.data = pbuf1; - iocmd.size = 4; - iocmd.flags |= MPT_ICFLAG_BUF_CAP; - - dataBufSize = 0; - echoBufSize = 0; - for (patt = 0; patt < 2; patt++) { - if (patt == 0) - iocmd.flags |= MPT_ICFLAG_ECHO; - else - iocmd.flags &= ~MPT_ICFLAG_ECHO; - - notDone = 1; - while (notDone) { - bufsize = 0; - - /* If not ready after 8 trials, - * give up on this device. - */ - if (notDone > 8) - goto target_done; - - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - else if (hd->pLocal == NULL) - goto target_done; - else { - rc = hd->pLocal->completion; - ddvprintk(("ReadBuffer Comp Code %d", rc)); - ddvprintk((" buff: %0x %0x %0x %0x\n", - pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3])); - - if (rc == MPT_SCANDV_GOOD) { - notDone = 0; - if (iocmd.flags & MPT_ICFLAG_ECHO) { - bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3]; - } else { - bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3]; - } - } else if (rc == MPT_SCANDV_SENSE) { - u8 skey = hd->pLocal->sense[2] & 0x0F; - u8 asc = hd->pLocal->sense[12]; - u8 ascq = hd->pLocal->sense[13]; - ddvprintk((MYIOC_s_INFO_FMT - "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", - ioc->name, skey, asc, ascq)); - if (skey == SK_ILLEGAL_REQUEST) { - notDone = 0; - } else if (skey == SK_UNIT_ATTENTION) { - notDone++; /* repeat */ - } else if ((skey == SK_NOT_READY) && - (asc == 0x04)&&(ascq == 0x01)) { - /* wait then repeat */ - mdelay (2000); - notDone++; - } else { - /* All other errors are fatal. - */ - ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.", - ioc->name)); - goto target_done; - } - } else { - /* All other errors are fatal - */ - goto target_done; - } - } - } - - if (iocmd.flags & MPT_ICFLAG_ECHO) - echoBufSize = bufsize; - else - dataBufSize = bufsize; - } - sz = 0; - iocmd.flags &= ~MPT_ICFLAG_BUF_CAP; - - /* Use echo buffers if possible, - * Exit if both buffers are 0. - */ - if (echoBufSize > 0) { - iocmd.flags |= MPT_ICFLAG_ECHO; - if (dataBufSize > 0) - bufsize = MIN(echoBufSize, dataBufSize); - else - bufsize = echoBufSize; - } else if (dataBufSize == 0) - goto target_done; - - ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name, - (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize)); - - /* Data buffers for write-read-compare test max 1K. - */ - sz = MIN(bufsize, 1024); - - /* --- loop ---- - * On first pass, always issue a reserve. - * On additional loops, only if a reset has occurred. - * iocmd.flags indicates if echo or regular buffer - */ - for (patt = 0; patt < 4; patt++) { - ddvprintk(("Pattern %d\n", patt)); - if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) { - iocmd.cmd = CMD_TestUnitReady; - iocmd.data_dma = -1; - iocmd.data = NULL; - iocmd.size = 0; - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - - iocmd.cmd = CMD_Release6; - iocmd.data_dma = -1; - iocmd.data = NULL; - iocmd.size = 0; - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - else if (hd->pLocal == NULL) - goto target_done; - else { - rc = hd->pLocal->completion; - ddvprintk(("Release rc %d\n", rc)); - if (rc == MPT_SCANDV_GOOD) - iocmd.flags &= ~MPT_ICFLAG_RESERVED; - else - goto target_done; - } - iocmd.flags &= ~MPT_ICFLAG_RESERVED; - } - iocmd.flags &= ~MPT_ICFLAG_DID_RESET; - - repeat = 5; - while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) { - iocmd.cmd = CMD_Reserve6; - iocmd.data_dma = -1; - iocmd.data = NULL; - iocmd.size = 0; - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - else if (hd->pLocal == NULL) - goto target_done; - else { - rc = hd->pLocal->completion; - if (rc == MPT_SCANDV_GOOD) { - iocmd.flags |= MPT_ICFLAG_RESERVED; - } else if (rc == MPT_SCANDV_SENSE) { - /* Wait if coming ready - */ - u8 skey = hd->pLocal->sense[2] & 0x0F; - u8 asc = hd->pLocal->sense[12]; - u8 ascq = hd->pLocal->sense[13]; - ddvprintk((MYIOC_s_INFO_FMT - "DV: Reserve Failed: ", ioc->name)); - ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", - skey, asc, ascq)); - - if ((skey == SK_NOT_READY) && (asc == 0x04)&& - (ascq == 0x01)) { - /* wait then repeat */ - mdelay (2000); - notDone++; - } else { - ddvprintk((MYIOC_s_INFO_FMT - "DV: Reserved Failed.", ioc->name)); - goto target_done; - } - } else { - ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.", - ioc->name)); - goto target_done; - } - } - } - - mptscsih_fillbuf(pbuf1, sz, patt, 1); - iocmd.cmd = CMD_WriteBuffer; - iocmd.data_dma = buf1_dma; - iocmd.data = pbuf1; - iocmd.size = sz; - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - else if (hd->pLocal == NULL) - goto target_done; - else { - rc = hd->pLocal->completion; - if (rc == MPT_SCANDV_GOOD) - ; /* Issue read buffer */ - else if (rc == MPT_SCANDV_DID_RESET) { - /* If using echo buffers, reset to data buffers. - * Else do Fallback and restart - * this test (re-issue reserve - * because of bus reset). - */ - if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) { - iocmd.flags &= ~MPT_ICFLAG_ECHO; - } else { - dv.cmd = MPT_FALLBACK; - mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); - - if (mpt_config(hd->ioc, &cfg) != 0) - goto target_done; - - if ((!dv.now.width) && (!dv.now.offset)) - goto target_done; - } - - iocmd.flags |= MPT_ICFLAG_DID_RESET; - patt = -1; - continue; - } else if (rc == MPT_SCANDV_SENSE) { - /* Restart data test if UA, else quit. - */ - u8 skey = hd->pLocal->sense[2] & 0x0F; - ddvprintk((MYIOC_s_INFO_FMT - "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey, - hd->pLocal->sense[12], hd->pLocal->sense[13])); - if (skey == SK_UNIT_ATTENTION) { - patt = -1; - continue; - } else if (skey == SK_ILLEGAL_REQUEST) { - if (iocmd.flags & MPT_ICFLAG_ECHO) { - if (dataBufSize >= bufsize) { - iocmd.flags &= ~MPT_ICFLAG_ECHO; - patt = -1; - continue; - } - } - goto target_done; - } - else - goto target_done; - } else { - /* fatal error */ - goto target_done; - } - } - - iocmd.cmd = CMD_ReadBuffer; - iocmd.data_dma = buf2_dma; - iocmd.data = pbuf2; - iocmd.size = sz; - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - else if (hd->pLocal == NULL) - goto target_done; - else { - rc = hd->pLocal->completion; - if (rc == MPT_SCANDV_GOOD) { - /* If buffers compare, - * go to next pattern, - * else, do a fallback and restart - * data transfer test. - */ - if (memcmp (pbuf1, pbuf2, sz) == 0) { - ; /* goto next pattern */ - } else { - /* Miscompare with Echo buffer, go to data buffer, - * if that buffer exists. - * Miscompare with Data buffer, check first 4 bytes, - * some devices return capacity. Exit in this case. - */ - if (iocmd.flags & MPT_ICFLAG_ECHO) { - if (dataBufSize >= bufsize) - iocmd.flags &= ~MPT_ICFLAG_ECHO; - else - goto target_done; - } else { - if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) { - /* Argh. Device returning wrong data. - * Quit DV for this device. - */ - goto target_done; - } - - /* Had an actual miscompare. Slow down.*/ - dv.cmd = MPT_FALLBACK; - mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); - - if (mpt_config(hd->ioc, &cfg) != 0) - goto target_done; - - if ((!dv.now.width) && (!dv.now.offset)) - goto target_done; - } - - patt = -1; - continue; - } - } else if (rc == MPT_SCANDV_DID_RESET) { - /* Do Fallback and restart - * this test (re-issue reserve - * because of bus reset). - */ - dv.cmd = MPT_FALLBACK; - mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); - - if (mpt_config(hd->ioc, &cfg) != 0) - goto target_done; - - if ((!dv.now.width) && (!dv.now.offset)) - goto target_done; - - iocmd.flags |= MPT_ICFLAG_DID_RESET; - patt = -1; - continue; - } else if (rc == MPT_SCANDV_SENSE) { - /* Restart data test if UA, else quit. - */ - u8 skey = hd->pLocal->sense[2] & 0x0F; - ddvprintk((MYIOC_s_INFO_FMT - "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey, - hd->pLocal->sense[12], hd->pLocal->sense[13])); - if (skey == SK_UNIT_ATTENTION) { - patt = -1; - continue; - } - else - goto target_done; - } else { - /* fatal error */ - goto target_done; - } - } - - } /* --- end of patt loop ---- */ - -target_done: - if (iocmd.flags & MPT_ICFLAG_RESERVED) { - iocmd.cmd = CMD_Release6; - iocmd.data_dma = -1; - iocmd.data = NULL; - iocmd.size = 0; - if (mptscsih_do_cmd(hd, &iocmd) < 0) - printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d", - ioc->name, id); - else if (hd->pLocal) { - if (hd->pLocal->completion == MPT_SCANDV_GOOD) - iocmd.flags &= ~MPT_ICFLAG_RESERVED; - } else { - printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d", - ioc->name, id); - } - } - - - /* Set if cfg1_dma_addr contents is valid - */ - if ((cfg.hdr != NULL) && (retcode == 0)){ - /* If disk, not U320, disable QAS - */ - if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) - hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; - - dv.cmd = MPT_SAVE; - mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); - - /* Double writes to SDP1 can cause problems, - * skip save of the final negotiated settings to - * SCSI device page 1. - * - cfg.hdr = &header1; - cfg.physAddr = cfg1_dma_addr; - cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; - cfg.dir = 1; - mpt_config(hd->ioc, &cfg); - */ - } - - /* If this is a RAID Passthrough, enable internal IOs - */ - if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) { - if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0) - ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name)); - } - - /* Done with the DV scan of the current target - */ - if (pDvBuf) - pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma); - - ddvtprintk((MYIOC_s_INFO_FMT "DV Done. IOs outstanding = %d\n", - ioc->name, atomic_read(&queue_depth))); - - return retcode; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptscsih_dv_parms - perform a variety of operations on the - * parameters used for negotiation. - * @hd: Pointer to a SCSI host. - * @dv: Pointer to a structure that contains the maximum and current - * negotiated parameters. - */ -static void -mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) -{ - VirtDevice *pTarget = NULL; - SCSIDevicePage0_t *pPage0 = NULL; - SCSIDevicePage1_t *pPage1 = NULL; - int val = 0, data, configuration; - u8 width = 0; - u8 offset = 0; - u8 factor = 0; - u8 negoFlags = 0; - u8 cmd = dv->cmd; - u8 id = dv->id; - - switch (cmd) { - case MPT_GET_NVRAM_VALS: - ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ", - hd->ioc->name)); - /* Get the NVRAM values and save in tmax - * If not an LVD bus, the adapter minSyncFactor has been - * already throttled back. - */ - if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) { - width = pTarget->maxWidth; - offset = pTarget->maxOffset; - factor = pTarget->minSyncFactor; - negoFlags = pTarget->negoFlags; - } else { - if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { - data = hd->ioc->spi_data.nvram[id]; - width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; - if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0) - factor = MPT_ASYNC; - else { - factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT; - if ((factor == 0) || (factor == MPT_ASYNC)){ - factor = MPT_ASYNC; - offset = 0; - } - } - } else { - width = MPT_NARROW; - offset = 0; - factor = MPT_ASYNC; - } - - /* Set the negotiation flags */ - negoFlags = hd->ioc->spi_data.noQas; - if (!width) - negoFlags |= MPT_TARGET_NO_NEGO_WIDE; - - if (!offset) - negoFlags |= MPT_TARGET_NO_NEGO_SYNC; - } - - /* limit by adapter capabilities */ - width = MIN(width, hd->ioc->spi_data.maxBusWidth); - offset = MIN(offset, hd->ioc->spi_data.maxSyncOffset); - factor = MAX(factor, hd->ioc->spi_data.minSyncFactor); - - /* Check Consistency */ - if (offset && (factor < MPT_ULTRA2) && !width) - factor = MPT_ULTRA2; - - dv->max.width = width; - dv->max.offset = offset; - dv->max.factor = factor; - dv->max.flags = negoFlags; - ddvprintk((" width %d, factor %x, offset %x flags %x\n", - width, factor, offset, negoFlags)); - break; - - case MPT_UPDATE_MAX: - ddvprintk((MYIOC_s_NOTE_FMT - "Updating with SDP0 Data: ", hd->ioc->name)); - /* Update tmax values with those from Device Page 0.*/ - pPage0 = (SCSIDevicePage0_t *) pPage; - if (pPage0) { - val = cpu_to_le32(pPage0->NegotiatedParameters); - dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0; - dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16; - dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8; - } - - dv->now.width = dv->max.width; - dv->now.offset = dv->max.offset; - dv->now.factor = dv->max.factor; - ddvprintk(("width %d, factor %x, offset %x, flags %x\n", - dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags)); - break; - - case MPT_SET_MAX: - ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ", - hd->ioc->name)); - /* Set current to the max values. Update the config page.*/ - dv->now.width = dv->max.width; - dv->now.offset = dv->max.offset; - dv->now.factor = dv->max.factor; - dv->now.flags = dv->max.flags; - - pPage1 = (SCSIDevicePage1_t *)pPage; - if (pPage1) { - mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor, - dv->now.offset, &val, &configuration, dv->now.flags); - pPage1->RequestedParameters = le32_to_cpu(val); - pPage1->Reserved = 0; - pPage1->Configuration = le32_to_cpu(configuration); - - } - - ddvprintk(("width %d, factor %x, offset %x request %x, config %x\n", - dv->now.width, dv->now.factor, dv->now.offset, val, configuration)); - break; - - case MPT_SET_MIN: - ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ", - hd->ioc->name)); - /* Set page to asynchronous and narrow - * Do not update now, breaks fallback routine. */ - width = MPT_NARROW; - offset = 0; - factor = MPT_ASYNC; - negoFlags = dv->max.flags; - - pPage1 = (SCSIDevicePage1_t *)pPage; - if (pPage1) { - mptscsih_setDevicePage1Flags (width, factor, - offset, &val, &configuration, negoFlags); - pPage1->RequestedParameters = le32_to_cpu(val); - pPage1->Reserved = 0; - pPage1->Configuration = le32_to_cpu(configuration); - } - ddvprintk(("width %d, factor %x, offset %x request %x config %x\n", - width, factor, offset, val, configuration)); - break; - - case MPT_FALLBACK: - ddvprintk((MYIOC_s_NOTE_FMT - "Fallback: Start: offset %d, factor %x, width %d \n", - hd->ioc->name, dv->now.offset, - dv->now.factor, dv->now.width)); - width = dv->now.width; - offset = dv->now.offset; - factor = dv->now.factor; - if ((offset) && (dv->max.width)) { - if (factor < MPT_ULTRA160) - factor = MPT_ULTRA160; - else if (factor < MPT_ULTRA2) { - factor = MPT_ULTRA2; - width = MPT_WIDE; - } else if ((factor == MPT_ULTRA2) && width) { - factor = MPT_ULTRA2; - width = MPT_NARROW; - } else if (factor < MPT_ULTRA) { - factor = MPT_ULTRA; - width = MPT_WIDE; - } else if ((factor == MPT_ULTRA) && width) { - factor = MPT_ULTRA; - width = MPT_NARROW; - } else if (factor < MPT_FAST) { - factor = MPT_FAST; - width = MPT_WIDE; - } else if ((factor == MPT_FAST) && width) { - factor = MPT_FAST; - width = MPT_NARROW; - } else if (factor < MPT_SCSI) { - factor = MPT_SCSI; - width = MPT_WIDE; - } else if ((factor == MPT_SCSI) && width) { - factor = MPT_SCSI; - width = MPT_NARROW; - } else { - factor = MPT_ASYNC; - offset = 0; - } - - } else if (offset) { - width = MPT_NARROW; - if (factor < MPT_ULTRA) - factor = MPT_ULTRA; - else if (factor < MPT_FAST) - factor = MPT_FAST; - else if (factor < MPT_SCSI) - factor = MPT_SCSI; - else { - factor = MPT_ASYNC; - offset = 0; - } - - } else { - width = MPT_NARROW; - factor = MPT_ASYNC; - } - dv->max.flags |= MPT_TARGET_NO_NEGO_QAS; - - dv->now.width = width; - dv->now.offset = offset; - dv->now.factor = factor; - dv->now.flags = dv->max.flags; - - pPage1 = (SCSIDevicePage1_t *)pPage; - if (pPage1) { - mptscsih_setDevicePage1Flags (width, factor, offset, &val, - &configuration, dv->now.flags); - - pPage1->RequestedParameters = le32_to_cpu(val); - pPage1->Reserved = 0; - pPage1->Configuration = le32_to_cpu(configuration); - } - - ddvprintk(("Finish: offset %d, factor %x, width %d, request %x config %x\n", - dv->now.offset, dv->now.factor, dv->now.width, val, configuration)); - break; - - case MPT_SAVE: - ddvprintk((MYIOC_s_NOTE_FMT - "Saving to Target structure: ", hd->ioc->name)); - ddvprintk(("offset %d, factor %x, width %d \n", - dv->now.offset, dv->now.factor, dv->now.width)); - - /* Save these values to target structures - * or overwrite nvram (phys disks only). - */ - - if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume ) { - pTarget->maxWidth = dv->now.width; - pTarget->maxOffset = dv->now.offset; - pTarget->minSyncFactor = dv->now.factor; - pTarget->negoFlags = dv->now.flags; - } else { - /* Preserv all flags, use - * read-modify-write algorithm - */ - if (hd->ioc->spi_data.nvram) { - data = hd->ioc->spi_data.nvram[id]; - - if (dv->now.width) - data &= ~MPT_NVRAM_WIDE_DISABLE; - else - data |= MPT_NVRAM_WIDE_DISABLE; - - if (!dv->now.offset) - factor = MPT_ASYNC; - - data &= ~MPT_NVRAM_SYNC_MASK; - data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK; - - hd->ioc->spi_data.nvram[id] = data; - } - } - break; - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptscsih_fillbuf - fill a buffer with a special data pattern - * cleanup. For bus scan only. - * - * @buffer: Pointer to data buffer to be filled. - * @size: Number of bytes to fill - * @index: Pattern index - * @width: bus width, 0 (8 bits) or 1 (16 bits) - */ -static void -mptscsih_fillbuf(char *buffer, int size, int index, int width) -{ - char *ptr = buffer; - int ii; - char byte; - short val; - - switch (index) { - case 0: - - if (width) { - /* Pattern: 0000 FFFF 0000 FFFF - */ - for (ii=0; ii < size; ii++, ptr++) { - if (ii & 0x02) - *ptr = 0xFF; - else - *ptr = 0x00; - } - } else { - /* Pattern: 00 FF 00 FF - */ - for (ii=0; ii < size; ii++, ptr++) { - if (ii & 0x01) - *ptr = 0xFF; - else - *ptr = 0x00; - } - } - break; - - case 1: - if (width) { - /* Pattern: 5555 AAAA 5555 AAAA 5555 - */ - for (ii=0; ii < size; ii++, ptr++) { - if (ii & 0x02) - *ptr = 0xAA; - else - *ptr = 0x55; - } - } else { - /* Pattern: 55 AA 55 AA 55 - */ - for (ii=0; ii < size; ii++, ptr++) { - if (ii & 0x01) - *ptr = 0xAA; - else - *ptr = 0x55; - } - } - break; - - case 2: - /* Pattern: 00 01 02 03 04 05 - * ... FE FF 00 01.. - */ - for (ii=0; ii < size; ii++, ptr++) - *ptr = (char) ii; - break; - - case 3: - if (width) { - /* Wide Pattern: FFFE 0001 FFFD 0002 - * ... 4000 DFFF 8000 EFFF - */ - byte = 0; - for (ii=0; ii < size/2; ii++) { - /* Create the base pattern - */ - val = (1 << byte); - /* every 64 (0x40) bytes flip the pattern - * since we fill 2 bytes / iteration, - * test for ii = 0x20 - */ - if (ii & 0x20) - val = ~(val); - - if (ii & 0x01) { - *ptr = (char)( (val & 0xFF00) >> 8); - ptr++; - *ptr = (char)(val & 0xFF); - byte++; - byte &= 0x0F; - } else { - val = ~val; - *ptr = (char)( (val & 0xFF00) >> 8); - ptr++; - *ptr = (char)(val & 0xFF); - } - - ptr++; - } - } else { - /* Narrow Pattern: FE 01 FD 02 FB 04 - * .. 7F 80 01 FE 02 FD ... 80 7F - */ - byte = 0; - for (ii=0; ii < size; ii++, ptr++) { - /* Base pattern - first 32 bytes - */ - if (ii & 0x01) { - *ptr = (1 << byte); - byte++; - byte &= 0x07; - } else { - *ptr = (char) (~(1 << byte)); - } - - /* Flip the pattern every 32 bytes - */ - if (ii & 0x20) - *ptr = ~(*ptr); - } - } - break; - } -} -#endif /* ~MPTSCSIH_DISABLE_DOMAIN_VALIDATION */ - -#if 0 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* Commandline Parsing routines and defines. - * - * insmod format: - * insmod mptscsih mptscsih="width:1 dv:n factor:0x09" - * boot format: - * mptscsih=width:1,dv:n,factor:0x8 - * - */ -#ifdef MODULE -#define ARG_SEP ' ' -#else -#define ARG_SEP ',' -#endif - -static char setup_token[] __initdata = - "dv:" - "width:" - "factor:" - ; /* DONNOT REMOVE THIS ';' */ - -#define OPT_DV 1 -#define OPT_MAX_WIDTH 2 -#define OPT_MIN_SYNC_FACTOR 3 - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int -__init get_setup_token(char *p) -{ - char *cur = setup_token; - char *pc; - int i = 0; - - while (cur != NULL && (pc = strchr(cur, ':')) != NULL) { - ++pc; - ++i; - if (!strncmp(p, cur, pc - cur)) - return i; - cur = pc; - } - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int -__init mptscsih_setup(char *str) -{ - char *cur = str; - char *pc, *pv; - unsigned long val; - int c; - - while (cur != NULL && (pc = strchr(cur, ':')) != NULL) { - char *pe; - - val = 0; - pv = pc; - c = *++pv; - - if (c == 'n') - val = 0; - else if (c == 'y') - val = 1; - else - val = (int) simple_strtoul(pv, &pe, 0); - - printk("Found Token: %s, value %x\n", cur, (int)val); - switch (get_setup_token(cur)) { - case OPT_DV: - driver_setup.dv = val; - break; - - case OPT_MAX_WIDTH: - driver_setup.max_width = val; - break; - - case OPT_MIN_SYNC_FACTOR: - driver_setup.min_sync_fac = val; - break; - - default: - printk("mptscsih_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur); - break; - } - - if ((cur = strchr(cur, ARG_SEP)) != NULL) - ++cur; - } - return 1; -} -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#endif - diff --git a/xen/drivers/message/fusion/mptscsih.h b/xen/drivers/message/fusion/mptscsih.h deleted file mode 100644 index 4efc5f1451..0000000000 --- a/xen/drivers/message/fusion/mptscsih.h +++ /dev/null @@ -1,343 +0,0 @@ -/* - * linux/drivers/message/fusion/mptscsih.h - * High performance SCSI / Fibre Channel SCSI Host device driver. - * For use with PCI chip/adapter(s): - * LSIFC9xx/LSI409xx Fibre Channel - * running LSI Logic Fusion MPT (Message Passing Technology) firmware. - * - * Credits: - * This driver would not exist if not for Alan Cox's development - * of the linux i2o driver. - * - * A huge debt of gratitude is owed to David S. Miller (DaveM) - * for fixing much of the stupid and broken stuff in the early - * driver while porting to sparc64 platform. THANK YOU! - * - * (see also mptbase.c) - * - * Copyright (c) 1999-2002 LSI Logic Corporation - * Originally By: Steven J. Ralston - * (mailto:sjralston1@netscape.net) - * (mailto:lstephens@lsil.com) - * - * $Id: mptscsih.h,v 1.1.2.2 2003/05/07 14:08:35 pdelaney Exp $ - */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - NO WARRANTY - THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - solely responsible for determining the appropriateness of using and - distributing the Program and assumes all risks associated with its - exercise of rights under this Agreement, including but not limited to - the risks and costs of program errors, damage to or loss of data, - programs or equipment, and unavailability or interruption of operations. - - DISCLAIMER OF LIABILITY - NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef SCSIHOST_H_INCLUDED -#define SCSIHOST_H_INCLUDED -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#include -#include - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * SCSI Public stuff... - */ - -/* - * Try to keep these at 2^N-1 - */ -#define MPT_FC_CAN_QUEUE 127 -#if defined MPT_SCSI_USE_NEW_EH - #define MPT_SCSI_CAN_QUEUE 127 -#else - #define MPT_SCSI_CAN_QUEUE 63 -#endif - -#define MPT_SCSI_CMD_PER_DEV_HIGH 31 -#define MPT_SCSI_CMD_PER_DEV_LOW 7 - -#define MPT_SCSI_CMD_PER_LUN 7 - -#define MPT_SCSI_MAX_SECTORS 8192 - -/* - * Set the MAX_SGE value based on user input. - */ -#ifdef CONFIG_FUSION_MAX_SGE -#if CONFIG_FUSION_MAX_SGE < 16 -#define MPT_SCSI_SG_DEPTH 16 -#elif CONFIG_FUSION_MAX_SGE > 128 -#define MPT_SCSI_SG_DEPTH 128 -#else -#define MPT_SCSI_SG_DEPTH CONFIG_FUSION_MAX_SGE -#endif -#else -#define MPT_SCSI_SG_DEPTH 40 -#endif - -/* To disable domain validation, uncomment the - * following line. No effect for FC devices. - * For SCSI devices, driver will negotiate to - * NVRAM settings (if available) or to maximum adapter - * capabilities. - */ -/* #define MPTSCSIH_DISABLE_DOMAIN_VALIDATION */ - - -/* SCSI driver setup structure. Settings can be overridden - * by command line options. - */ -#define MPTSCSIH_DOMAIN_VALIDATION 1 -#define MPTSCSIH_MAX_WIDTH 1 -#define MPTSCSIH_MIN_SYNC 0x08 - -struct mptscsih_driver_setup -{ - u8 dv; - u8 max_width; - u8 min_sync_fac; -}; - - -#define MPTSCSIH_DRIVER_SETUP \ -{ \ - MPTSCSIH_DOMAIN_VALIDATION, \ - MPTSCSIH_MAX_WIDTH, \ - MPTSCSIH_MIN_SYNC, \ -} - - - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Various bits and pieces broke within the lk-2.4.0-testN series:-( - * So here are various HACKS to work around them. - */ - -/* - * Conditionalizing with "#ifdef MODULE/#endif" around: - * static Scsi_Host_Template driver_template = XX; - * #include <../../scsi/scsi_module.c> - * lines was REMOVED @ lk-2.4.0-test9 - * Issue discovered 20001213 by: sshirron - */ -#define MPT_SCSIHOST_NEED_ENTRY_EXIT_HOOKUPS 1 -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,0) -# if LINUX_VERSION_CODE == KERNEL_VERSION(2,4,0) - /* - * Super HACK! -by sralston:-( - * (good grief; heaven help me!) - */ -# include -# if !defined(CAP_LEASE) && !defined(MODULE) -# undef MPT_SCSIHOST_NEED_ENTRY_EXIT_HOOKUPS -# endif -# else -# ifndef MODULE -# undef MPT_SCSIHOST_NEED_ENTRY_EXIT_HOOKUPS -# endif -# endif -#endif - -/* - * tq_scheduler disappeared @ lk-2.4.0-test12 - * (right when newly defined TQ_ACTIVE) - * tq_struct reworked in 2.5.41. Include workqueue.h. - */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,41) -# include -# include -#define SCHEDULE_TASK(x) \ - if (schedule_work(x) == 0) { \ - /*MOD_DEC_USE_COUNT*/; \ - } -#else -#define HAVE_TQ_SCHED 1 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -# include -# ifdef TQ_ACTIVE -# undef HAVE_TQ_SCHED -# endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,40) -# undef HAVE_TQ_SCHED -#endif -#endif -#ifdef HAVE_TQ_SCHED -#define SCHEDULE_TASK(x) \ - /*MOD_INC_USE_COUNT*/; \ - (x)->next = NULL; \ - queue_task(x, &tq_scheduler) -#else - -/* SAE: mdelay */ -#define SCHEDULE_TASK(x) mdelay(100) - -#if XEN_KILLED - -#define SCHEDULE_TASK(x) \ - *MOD_INC_USE_COUNT*; \ - if (schedule_task(x) == 0) { \ - *MOD_DEC_USE_COUNT*; - -#endif - -#endif -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#define x_scsi_detect mptscsih_detect -#define x_scsi_release mptscsih_release -#define x_scsi_info mptscsih_info -#define x_scsi_queuecommand mptscsih_qcmd -#define x_scsi_abort mptscsih_abort -#define x_scsi_bus_reset mptscsih_bus_reset -#define x_scsi_dev_reset mptscsih_dev_reset -#define x_scsi_host_reset mptscsih_host_reset -#define x_scsi_bios_param mptscsih_bios_param - -#define x_scsi_taskmgmt_bh mptscsih_taskmgmt_bh -#define x_scsi_old_abort mptscsih_old_abort -#define x_scsi_old_reset mptscsih_old_reset -#define x_scsi_select_queue_depths mptscsih_select_queue_depths - -/* SAE: No proc */ - -#if defined(CONFIG_PROC_FS) -#define x_scsi_proc_info mptscsih_proc_info -#else -#define x_scsi_proc_info NULL -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * MPT SCSI Host / Initiator decls... - */ -extern int x_scsi_detect(Scsi_Host_Template *); -extern int x_scsi_release(struct Scsi_Host *host); -extern const char *x_scsi_info(struct Scsi_Host *); -extern int x_scsi_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -#ifdef MPT_SCSI_USE_NEW_EH -extern int x_scsi_abort(Scsi_Cmnd *); -extern int x_scsi_bus_reset(Scsi_Cmnd *); -extern int x_scsi_dev_reset(Scsi_Cmnd *); -extern int x_scsi_host_reset(Scsi_Cmnd *); -#else -extern int x_scsi_old_abort(Scsi_Cmnd *); -extern int x_scsi_old_reset(Scsi_Cmnd *, unsigned int); -#endif -extern int x_scsi_bios_param(Disk *, kdev_t, int *); -extern void x_scsi_taskmgmt_bh(void *); -extern void x_scsi_select_queue_depths(struct Scsi_Host *, Scsi_Device *); - -/* SAE: No proc */ - -#if defined(CONFIG_PROC_FS) - -extern int x_scsi_proc_info(char *, char **, off_t, int, int, int); - -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -#define PROC_SCSI_DECL -#else -#define PROC_SCSI_DECL .proc_name = "mptscsih", -#endif - -#ifdef MPT_SCSI_USE_NEW_EH -#define MPT_SCSIHOST { \ - .next = NULL, \ - PROC_SCSI_DECL \ - .proc_info = x_scsi_proc_info, \ - .name = "MPT SCSI Host", \ - .detect = x_scsi_detect, \ - .release = x_scsi_release, \ - .info = x_scsi_info, \ - .command = NULL, \ - .queuecommand = x_scsi_queuecommand, \ - .eh_strategy_handler = NULL, \ - .eh_abort_handler = x_scsi_abort, \ - .eh_device_reset_handler = x_scsi_dev_reset, \ - .eh_bus_reset_handler = x_scsi_bus_reset, \ - .eh_host_reset_handler = NULL, \ - .bios_param = x_scsi_bios_param, \ - .can_queue = MPT_SCSI_CAN_QUEUE, \ - .this_id = -1, \ - .sg_tablesize = MPT_SCSI_SG_DEPTH, \ - .cmd_per_lun = MPT_SCSI_CMD_PER_LUN, \ - .unchecked_isa_dma = 0, \ - .use_clustering = ENABLE_CLUSTERING, \ - .use_new_eh_code = 1 \ -} - -#else /* MPT_SCSI_USE_NEW_EH */ - -#define MPT_SCSIHOST { \ - .next = NULL, \ - PROC_SCSI_DECL \ - .name = "MPT SCSI Host", \ - .detect = x_scsi_detect, \ - .release = x_scsi_release, \ - .info = x_scsi_info, \ - .command = NULL, \ - .queuecommand = x_scsi_queuecommand, \ - .abort = x_scsi_old_abort, \ - .reset = x_scsi_old_reset, \ - .bios_param = x_scsi_bios_param, \ - .can_queue = MPT_SCSI_CAN_QUEUE, \ - .this_id = -1, \ - .sg_tablesize = MPT_SCSI_SG_DEPTH, \ - .cmd_per_lun = MPT_SCSI_CMD_PER_LUN, \ - .unchecked_isa_dma = 0, \ - .use_clustering = ENABLE_CLUSTERING \ -} -#endif /* MPT_SCSI_USE_NEW_EH */ - - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -/* include/scsi/scsi.h may not be quite complete... */ -#ifndef RESERVE_10 -#define RESERVE_10 0x56 -#endif -#ifndef RELEASE_10 -#define RELEASE_10 0x57 -#endif -#ifndef PERSISTENT_RESERVE_IN -#define PERSISTENT_RESERVE_IN 0x5e -#endif -#ifndef PERSISTENT_RESERVE_OUT -#define PERSISTENT_RESERVE_OUT 0x5f -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#endif - diff --git a/xen/drivers/message/fusion/scsi3.h b/xen/drivers/message/fusion/scsi3.h deleted file mode 100644 index e7eaf30ef2..0000000000 --- a/xen/drivers/message/fusion/scsi3.h +++ /dev/null @@ -1,707 +0,0 @@ -/* - * linux/drivers/message/fusion/scsi3.h - * SCSI-3 definitions and macros. - * (Ultimately) SCSI-3 definitions; for now, inheriting - * SCSI-2 definitions. - * - * Copyright (c) 1996-2002 Steven J. Ralston - * Written By: Steven J. Ralston (19960517) - * (mailto:sjralston1@netscape.net) - * (mailto:lstephens@lsil.com) - * - * $Id: scsi3.h,v 1.9 2002/02/27 18:45:02 sralston Exp $ - */ - -#ifndef SCSI3_H_INCLUDED -#define SCSI3_H_INCLUDED -/***************************************************************************/ - -/**************************************************************************** - * - * Includes - */ -#ifdef __KERNEL__ -#include -#else - #ifndef U_STUFF_DEFINED - #define U_STUFF_DEFINED - typedef unsigned char u8; - typedef unsigned short u16; - typedef unsigned int u32; - #endif -#endif - -/**************************************************************************** - * - * Defines - */ - -/* - * SCSI Commands - */ -#define CMD_TestUnitReady 0x00 -#define CMD_RezeroUnit 0x01 /* direct-access devices */ -#define CMD_Rewind 0x01 /* sequential-access devices */ -#define CMD_RequestSense 0x03 -#define CMD_FormatUnit 0x04 -#define CMD_ReassignBlock 0x07 -#define CMD_Read6 0x08 -#define CMD_Write6 0x0A -#define CMD_WriteFilemark 0x10 -#define CMD_Space 0x11 -#define CMD_Inquiry 0x12 -#define CMD_ModeSelect6 0x15 -#define CMD_ModeSense6 0x1A -#define CMD_Reserve6 0x16 -#define CMD_Release6 0x17 -#define CMD_Erase 0x19 -#define CMD_StartStopUnit 0x1b /* direct-access devices */ -#define CMD_LoadUnload 0x1b /* sequential-access devices */ -#define CMD_ReceiveDiagnostic 0x1C -#define CMD_SendDiagnostic 0x1D -#define CMD_ReadCapacity 0x25 -#define CMD_Read10 0x28 -#define CMD_Write10 0x2A -#define CMD_WriteVerify 0x2E -#define CMD_Verify 0x2F -#define CMD_SynchronizeCache 0x35 -#define CMD_ReadDefectData 0x37 -#define CMD_WriteBuffer 0x3B -#define CMD_ReadBuffer 0x3C -#define CMD_ReadLong 0x3E -#define CMD_LogSelect 0x4C -#define CMD_LogSense 0x4D -#define CMD_ModeSelect10 0x55 -#define CMD_Reserve10 0x56 -#define CMD_Release10 0x57 -#define CMD_ModeSense10 0x5A -#define CMD_PersistReserveIn 0x5E -#define CMD_PersistReserveOut 0x5F -#define CMD_ReportLuns 0xA0 - -/* - * Control byte field - */ -#define CONTROL_BYTE_NACA_BIT 0x04 -#define CONTROL_BYTE_Flag_BIT 0x02 -#define CONTROL_BYTE_Link_BIT 0x01 - -/* - * SCSI Messages - */ -#define MSG_COMPLETE 0x00 -#define MSG_EXTENDED 0x01 -#define MSG_SAVE_POINTERS 0x02 -#define MSG_RESTORE_POINTERS 0x03 -#define MSG_DISCONNECT 0x04 -#define MSG_IDERROR 0x05 -#define MSG_ABORT 0x06 -#define MSG_REJECT 0x07 -#define MSG_NOP 0x08 -#define MSG_PARITY_ERROR 0x09 -#define MSG_LINKED_CMD_COMPLETE 0x0a -#define MSG_LCMD_COMPLETE_W_FLG 0x0b -#define MSG_BUS_DEVICE_RESET 0x0c -#define MSG_ABORT_TAG 0x0d -#define MSG_CLEAR_QUEUE 0x0e -#define MSG_INITIATE_RECOVERY 0x0f - -#define MSG_RELEASE_RECOVRY 0x10 -#define MSG_TERMINATE_IO 0x11 - -#define MSG_SIMPLE_QUEUE 0x20 -#define MSG_HEAD_OF_QUEUE 0x21 -#define MSG_ORDERED_QUEUE 0x22 -#define MSG_IGNORE_WIDE_RESIDUE 0x23 - -#define MSG_IDENTIFY 0x80 -#define MSG_IDENTIFY_W_DISC 0xc0 - -/* - * SCSI Phases - */ -#define PHS_DATA_OUT 0x00 -#define PHS_DATA_IN 0x01 -#define PHS_COMMAND 0x02 -#define PHS_STATUS 0x03 -#define PHS_MSG_OUT 0x06 -#define PHS_MSG_IN 0x07 - -/* - * Statuses - */ -#define STS_GOOD 0x00 -#define STS_CHECK_CONDITION 0x02 -#define STS_CONDITION_MET 0x04 -#define STS_BUSY 0x08 -#define STS_INTERMEDIATE 0x10 -#define STS_INTERMEDIATE_CONDITION_MET 0x14 -#define STS_RESERVATION_CONFLICT 0x18 -#define STS_COMMAND_TERMINATED 0x22 -#define STS_TASK_SET_FULL 0x28 -#define STS_QUEUE_FULL 0x28 -#define STS_ACA_ACTIVE 0x30 - -#define STS_VALID_MASK 0x3e - -#define SCSI_STATUS(x) ((x) & STS_VALID_MASK) - -/* - * SCSI QTag Types - */ -#define QTAG_SIMPLE 0x20 -#define QTAG_HEAD_OF_Q 0x21 -#define QTAG_ORDERED 0x22 - -/* - * SCSI Sense Key Definitons - */ -#define SK_NO_SENSE 0x00 -#define SK_RECOVERED_ERROR 0x01 -#define SK_NOT_READY 0x02 -#define SK_MEDIUM_ERROR 0x03 -#define SK_HARDWARE_ERROR 0x04 -#define SK_ILLEGAL_REQUEST 0x05 -#define SK_UNIT_ATTENTION 0x06 -#define SK_DATA_PROTECT 0x07 -#define SK_BLANK_CHECK 0x08 -#define SK_VENDOR_SPECIFIC 0x09 -#define SK_COPY_ABORTED 0x0a -#define SK_ABORTED_COMMAND 0x0b -#define SK_EQUAL 0x0c -#define SK_VOLUME_OVERFLOW 0x0d -#define SK_MISCOMPARE 0x0e -#define SK_RESERVED 0x0f - - - -#define SCSI_MAX_INQUIRY_BYTES 96 -#define SCSI_STD_INQUIRY_BYTES 36 - -#undef USE_SCSI_COMPLETE_INQDATA -/* - * Structure definition for SCSI Inquiry Data - * - * NOTE: The following structure is 96 bytes in size - * iff USE_SCSI_COMPLETE_INQDATA IS defined above (i.e. w/ "#define"). - * If USE_SCSI_COMPLETE_INQDATA is NOT defined above (i.e. w/ "#undef") - * then the following structure is only 36 bytes in size. - * THE CHOICE IS YOURS! - */ -typedef struct SCSI_Inquiry_Data -{ -#ifdef USE_SCSI_COMPLETE_INQDATA - u8 InqByte[SCSI_MAX_INQUIRY_BYTES]; -#else - u8 InqByte[SCSI_STD_INQUIRY_BYTES]; -#endif - -/* - * the following structure works only for little-endian (Intel, - * LSB first (1234) byte order) systems with 4-byte ints. - * - u32 Periph_Device_Type : 5, - Periph_Qualifier : 3, - Device_Type_Modifier : 7, - Removable_Media : 1, - ANSI_Version : 3, - ECMA_Version : 3, - ISO_Version : 2, - Response_Data_Format : 4, - reserved_0 : 3, - AERC : 1 ; - u32 Additional_Length : 8, - reserved_1 :16, - SftReset : 1, - CmdQue : 1, - reserved_2 : 1, - Linked : 1, - Sync : 1, - WBus16 : 1, - WBus32 : 1, - RelAdr : 1 ; - u8 Vendor_ID[8]; - u8 Product_ID[16]; - u8 Revision_Level [4]; -#ifdef USE_SCSI_COMPLETE_INQDATA - u8 Vendor_Specific[20]; - u8 reserved_3[40]; -#endif - * - */ - -} SCSI_Inquiry_Data_t; - -#define INQ_PERIPHINFO_BYTE 0 -#define INQ_Periph_Qualifier_MASK 0xe0 -#define INQ_Periph_Device_Type_MASK 0x1f - -#define INQ_Peripheral_Qualifier(inqp) \ - (int)((*((u8*)(inqp)+INQ_PERIPHINFO_BYTE) & INQ_Periph_Qualifier_MASK) >> 5) -#define INQ_Peripheral_Device_Type(inqp) \ - (int)(*((u8*)(inqp)+INQ_PERIPHINFO_BYTE) & INQ_Periph_Device_Type_MASK) - - -#define INQ_DEVTYPEMOD_BYTE 1 -#define INQ_RMB_BIT 0x80 -#define INQ_Device_Type_Modifier_MASK 0x7f - -#define INQ_Removable_Medium(inqp) \ - (int)(*((u8*)(inqp)+INQ_DEVTYPEMOD_BYTE) & INQ_RMB_BIT) -#define INQ_Device_Type_Modifier(inqp) \ - (int)(*((u8*)(inqp)+INQ_DEVTYPEMOD_BYTE) & INQ_Device_Type_Modifier_MASK) - - -#define INQ_VERSIONINFO_BYTE 2 -#define INQ_ISO_Version_MASK 0xc0 -#define INQ_ECMA_Version_MASK 0x38 -#define INQ_ANSI_Version_MASK 0x07 - -#define INQ_ISO_Version(inqp) \ - (int)(*((u8*)(inqp)+INQ_VERSIONINFO_BYTE) & INQ_ISO_Version_MASK) -#define INQ_ECMA_Version(inqp) \ - (int)(*((u8*)(inqp)+INQ_VERSIONINFO_BYTE) & INQ_ECMA_Version_MASK) -#define INQ_ANSI_Version(inqp) \ - (int)(*((u8*)(inqp)+INQ_VERSIONINFO_BYTE) & INQ_ANSI_Version_MASK) - - -#define INQ_BYTE3 3 -#define INQ_AERC_BIT 0x80 -#define INQ_TrmTsk_BIT 0x40 -#define INQ_NormACA_BIT 0x20 -#define INQ_RDF_MASK 0x0F - -#define INQ_AER_Capable(inqp) \ - (int)(*((u8*)(inqp)+INQ_BYTE3) & INQ_AERC_BIT) -#define INQ_TrmTsk(inqp) \ - (int)(*((u8*)(inqp)+INQ_BYTE3) & INQ_TrmTsk_BIT) -#define INQ_NormACA(inqp) \ - (int)(*((u8*)(inqp)+INQ_BYTE3) & INQ_NormACA_BIT) -#define INQ_Response_Data_Format(inqp) \ - (int)(*((u8*)(inqp)+INQ_BYTE3) & INQ_RDF_MASK) - - -#define INQ_CAPABILITY_BYTE 7 -#define INQ_RelAdr_BIT 0x80 -#define INQ_WBus32_BIT 0x40 -#define INQ_WBus16_BIT 0x20 -#define INQ_Sync_BIT 0x10 -#define INQ_Linked_BIT 0x08 - /* INQ_Reserved BIT 0x40 */ -#define INQ_CmdQue_BIT 0x02 -#define INQ_SftRe_BIT 0x01 - -#define IS_RelAdr_DEV(inqp) \ - (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_RelAdr_BIT) -#define IS_WBus32_DEV(inqp) \ - (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_WBus32_BIT) -#define IS_WBus16_DEV(inqp) \ - (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_WBus16_BIT) -#define IS_Sync_DEV(inqp) \ - (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_Sync_BIT) -#define IS_Linked_DEV(inqp) \ - (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_Linked_BIT) -#define IS_CmdQue_DEV(inqp) \ - (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_CmdQue_BIT) -#define IS_SftRe_DEV(inqp) \ - (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_SftRe_BIT) - -#define INQ_Width_BITS \ - (INQ_WBus32_BIT | INQ_WBus16_BIT) -#define IS_Wide_DEV(inqp) \ - (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_Width_BITS) - - -/* - * SCSI peripheral device types - */ -#define SCSI_TYPE_DAD 0x00 /* Direct Access Device */ -#define SCSI_TYPE_SAD 0x01 /* Sequential Access Device */ -#define SCSI_TYPE_TAPE SCSI_TYPE_SAD -#define SCSI_TYPE_PRT 0x02 /* Printer */ -#define SCSI_TYPE_PROC 0x03 /* Processor */ -#define SCSI_TYPE_WORM 0x04 -#define SCSI_TYPE_CDROM 0x05 -#define SCSI_TYPE_SCAN 0x06 /* Scanner */ -#define SCSI_TYPE_OPTICAL 0x07 /* Magneto/Optical */ -#define SCSI_TYPE_CHANGER 0x08 -#define SCSI_TYPE_COMM 0x09 /* Communications device */ -#define SCSI_TYPE_UNKNOWN 0x1f -#define SCSI_TYPE_UNCONFIGURED_LUN 0x7f - -#define SCSI_TYPE_MAX_KNOWN SCSI_TYPE_COMM - -/* - * Peripheral Qualifiers - */ -#define DEVICE_PRESENT 0x00 -#define LUN_NOT_PRESENT 0x01 -#define LUN_NOT_SUPPORTED 0x03 - -/* - * ANSI Versions - */ -#ifndef SCSI_1 -#define SCSI_1 0x01 -#endif -#ifndef SCSI_2 -#define SCSI_2 0x02 -#endif -#ifndef SCSI_3 -#define SCSI_3 0x03 -#endif - - -#define SCSI_MAX_SENSE_BYTES 255 -#define SCSI_STD_SENSE_BYTES 18 -#define SCSI_PAD_SENSE_BYTES (SCSI_MAX_SENSE_BYTES - SCSI_STD_SENSE_BYTES) - -#undef USE_SCSI_COMPLETE_SENSE -/* - * Structure definition for SCSI Sense Data - * - * NOTE: The following structure is 255 bytes in size - * iiff USE_SCSI_COMPLETE_SENSE IS defined above (i.e. w/ "#define"). - * If USE_SCSI_COMPLETE_SENSE is NOT defined above (i.e. w/ "#undef") - * then the following structure is only 19 bytes in size. - * THE CHOICE IS YOURS! - * - */ -typedef struct SCSI_Sense_Data -{ -#ifdef USE_SCSI_COMPLETE_SENSE - u8 SenseByte[SCSI_MAX_SENSE_BYTES]; -#else - u8 SenseByte[SCSI_STD_SENSE_BYTES]; -#endif - -/* - * the following structure works only for little-endian (Intel, - * LSB first (1234) byte order) systems with 4-byte ints. - * - u8 Error_Code :4, // 0x00 - Error_Class :3, - Valid :1 - ; - u8 Segment_Number // 0x01 - ; - u8 Sense_Key :4, // 0x02 - Reserved :1, - Incorrect_Length_Indicator:1, - End_Of_Media :1, - Filemark :1 - ; - u8 Information_MSB; // 0x03 - u8 Information_Byte2; // 0x04 - u8 Information_Byte1; // 0x05 - u8 Information_LSB; // 0x06 - u8 Additional_Length; // 0x07 - - u32 Command_Specific_Information; // 0x08 - 0x0b - - u8 Additional_Sense_Code; // 0x0c - u8 Additional_Sense_Code_Qualifier; // 0x0d - u8 Field_Replaceable_Unit_Code; // 0x0e - u8 Illegal_Req_Bit_Pointer :3, // 0x0f - Illegal_Req_Bit_Valid :1, - Illegal_Req_Reserved :2, - Illegal_Req_Cmd_Data :1, - Sense_Key_Specific_Valid :1 - ; - u16 Sense_Key_Specific_Data; // 0x10 - 0x11 - -#ifdef USE_SCSI_COMPLETE_SENSE - u8 Additional_Sense_Data[SCSI_PAD_SENSE_BYTES]; -#else - u8 Additional_Sense_Data[1]; -#endif - * - */ - -} SCSI_Sense_Data_t; - - -#define SD_ERRCODE_BYTE 0 -#define SD_Valid_BIT 0x80 -#define SD_Error_Code_MASK 0x7f -#define SD_Valid(sdp) \ - (int)(*((u8*)(sdp)+SD_ERRCODE_BYTE) & SD_Valid_BIT) -#define SD_Error_Code(sdp) \ - (int)(*((u8*)(sdp)+SD_ERRCODE_BYTE) & SD_Error_Code_MASK) - - -#define SD_SEGNUM_BYTE 1 -#define SD_Segment_Number(sdp) (int)(*((u8*)(sdp)+SD_SEGNUM_BYTE)) - - -#define SD_SENSEKEY_BYTE 2 -#define SD_Filemark_BIT 0x80 -#define SD_EOM_BIT 0x40 -#define SD_ILI_BIT 0x20 -#define SD_Sense_Key_MASK 0x0f -#define SD_Filemark(sdp) \ - (int)(*((u8*)(sdp)+SD_SENSEKEY_BYTE) & SD_Filemark_BIT) -#define SD_EOM(sdp) \ - (int)(*((u8*)(sdp)+SD_SENSEKEY_BYTE) & SD_EOM_BIT) -#define SD_ILI(sdp) \ - (int)(*((u8*)(sdp)+SD_SENSEKEY_BYTE) & SD_ILI_BIT) -#define SD_Sense_Key(sdp) \ - (int)(*((u8*)(sdp)+SD_SENSEKEY_BYTE) & SD_Sense_Key_MASK) - - -#define SD_INFO3_BYTE 3 -#define SD_INFO2_BYTE 4 -#define SD_INFO1_BYTE 5 -#define SD_INFO0_BYTE 6 -#define SD_Information3(sdp) (int)(*((u8*)(sdp)+SD_INFO3_BYTE)) -#define SD_Information2(sdp) (int)(*((u8*)(sdp)+SD_INFO2_BYTE)) -#define SD_Information1(sdp) (int)(*((u8*)(sdp)+SD_INFO1_BYTE)) -#define SD_Information0(sdp) (int)(*((u8*)(sdp)+SD_INFO0_BYTE)) - - -#define SD_ADDL_LEN_BYTE 7 -#define SD_Additional_Sense_Length(sdp) \ - (int)(*((u8*)(sdp)+SD_ADDL_LEN_BYTE)) -#define SD_Addl_Sense_Len SD_Additional_Sense_Length - - -#define SD_CMD_SPECIFIC3_BYTE 8 -#define SD_CMD_SPECIFIC2_BYTE 9 -#define SD_CMD_SPECIFIC1_BYTE 10 -#define SD_CMD_SPECIFIC0_BYTE 11 -#define SD_Cmd_Specific_Info3(sdp) (int)(*((u8*)(sdp)+SD_CMD_SPECIFIC3_BYTE)) -#define SD_Cmd_Specific_Info2(sdp) (int)(*((u8*)(sdp)+SD_CMD_SPECIFIC2_BYTE)) -#define SD_Cmd_Specific_Info1(sdp) (int)(*((u8*)(sdp)+SD_CMD_SPECIFIC1_BYTE)) -#define SD_Cmd_Specific_Info0(sdp) (int)(*((u8*)(sdp)+SD_CMD_SPECIFIC0_BYTE)) - - -#define SD_ADDL_SENSE_CODE_BYTE 12 -#define SD_Additional_Sense_Code(sdp) \ - (int)(*((u8*)(sdp)+SD_ADDL_SENSE_CODE_BYTE)) -#define SD_Addl_Sense_Code SD_Additional_Sense_Code -#define SD_ASC SD_Additional_Sense_Code - - -#define SD_ADDL_SENSE_CODE_QUAL_BYTE 13 -#define SD_Additional_Sense_Code_Qualifier(sdp) \ - (int)(*((u8*)(sdp)+SD_ADDL_SENSE_CODE_QUAL_BYTE)) -#define SD_Addl_Sense_Code_Qual SD_Additional_Sense_Code_Qualifier -#define SD_ASCQ SD_Additional_Sense_Code_Qualifier - - -#define SD_FIELD_REPL_UNIT_CODE_BYTE 14 -#define SD_Field_Replaceable_Unit_Code(sdp) \ - (int)(*((u8*)(sdp)+SD_FIELD_REPL_UNIT_CODE_BYTE)) -#define SD_Field_Repl_Unit_Code SD_Field_Replaceable_Unit_Code -#define SD_FRUC SD_Field_Replaceable_Unit_Code -#define SD_FRU SD_Field_Replaceable_Unit_Code - - -/* - * Sense-Key Specific offsets and macros. - */ -#define SD_SKS2_BYTE 15 -#define SD_SKS_Valid_BIT 0x80 -#define SD_SKS_Cmd_Data_BIT 0x40 -#define SD_SKS_Bit_Ptr_Valid_BIT 0x08 -#define SD_SKS_Bit_Ptr_MASK 0x07 -#define SD_SKS1_BYTE 16 -#define SD_SKS0_BYTE 17 -#define SD_Sense_Key_Specific_Valid(sdp) \ - (int)(*((u8*)(sdp)+SD_SKS2_BYTE) & SD_SKS_Valid_BIT) -#define SD_SKS_Valid SD_Sense_Key_Specific_Valid -#define SD_SKS_CDB_Error(sdp) \ - (int)(*((u8*)(sdp)+SD_SKS2_BYTE) & SD_SKS_Cmd_Data_BIT) -#define SD_Was_Illegal_Request SD_SKS_CDB_Error -#define SD_SKS_Bit_Pointer_Valid(sdp) \ - (int)(*((u8*)(sdp)+SD_SKS2_BYTE) & SD_SKS_Bit_Ptr_Valid_BIT) -#define SD_SKS_Bit_Pointer(sdp) \ - (int)(*((u8*)(sdp)+SD_SKS2_BYTE) & SD_SKS_Bit_Ptr_MASK) -#define SD_Field_Pointer(sdp) \ - (int)( ((u16)(*((u8*)(sdp)+SD_SKS1_BYTE)) << 8) \ - + *((u8*)(sdp)+SD_SKS0_BYTE) ) -#define SD_Bad_Byte SD_Field_Pointer -#define SD_Actual_Retry_Count SD_Field_Pointer -#define SD_Progress_Indication SD_Field_Pointer - -/* - * Mode Sense Write Protect Mask - */ -#define WRITE_PROTECT_MASK 0X80 - -/* - * Medium Type Codes - */ -#define OPTICAL_DEFAULT 0x00 -#define OPTICAL_READ_ONLY_MEDIUM 0x01 -#define OPTICAL_WRITE_ONCE_MEDIUM 0x02 -#define OPTICAL_READ_WRITABLE_MEDIUM 0x03 -#define OPTICAL_RO_OR_WO_MEDIUM 0x04 -#define OPTICAL_RO_OR_RW_MEDIUM 0x05 -#define OPTICAL_WO_OR_RW_MEDIUM 0x06 - - - -/* - * Structure definition for READ6, WRITE6 (6-byte CDB) - */ -typedef struct SCSI_RW6_CDB -{ - u32 OpCode :8, - LBA_HI :5, /* 5 MSBit's of the LBA */ - Lun :3, - LBA_MID :8, /* NOTE: total of 21 bits in LBA */ - LBA_LO :8 ; /* Max LBA = 0x001fffff */ - u8 BlockCount; - u8 Control; -} SCSI_RW6_t; - -#define MAX_RW6_LBA ((u32)0x001fffff) - -/* - * Structure definition for READ10, WRITE10 (10-byte CDB) - * - * NOTE: ParityCheck bit is applicable only for VERIFY and WRITE VERIFY for - * the ADP-92 DAC only. In the SCSI2 spec. this same bit is defined as a - * FUA (forced unit access) bit for READs and WRITEs. Since this driver - * does not use the FUA, this bit is defined as it is used by the ADP-92. - * Also, for READ CAPACITY, only the OpCode field is used. - */ -typedef struct SCSI_RW10_CDB -{ - u8 OpCode; - u8 Reserved1; - u32 LBA; - u8 Reserved2; - u16 BlockCount; - u8 Control; -} SCSI_RW10_t; - -#define PARITY_CHECK 0x08 /* parity check bit - byte[1], bit 3 */ - - /* - * Structure definition for data returned by READ CAPACITY cmd; - * READ CAPACITY data - */ - typedef struct READ_CAP_DATA - { - u32 MaxLBA; - u32 BlockBytes; - } SCSI_READ_CAP_DATA_t, *pSCSI_READ_CAP_DATA_t; - - -/* - * Structure definition for FORMAT UNIT CDB (6-byte CDB) - */ -typedef struct _SCSI_FORMAT_UNIT -{ - u8 OpCode; - u8 Reserved1; - u8 VendorSpecific; - u16 Interleave; - u8 Control; -} SCSI_FORMAT_UNIT_t; - -/* - * Structure definition for REQUEST SENSE (6-byte CDB) - */ -typedef struct _SCSI_REQUEST_SENSE -{ - u8 OpCode; - u8 Reserved1; - u8 Reserved2; - u8 Reserved3; - u8 AllocLength; - u8 Control; -} SCSI_REQ_SENSE_t; - -/* - * Structure definition for REPORT LUNS (12-byte CDB) - */ -typedef struct _SCSI_REPORT_LUNS -{ - u8 OpCode; - u8 Reserved1[5]; - u32 AllocationLength; - u8 Reserved2; - u8 Control; -} SCSI_REPORT_LUNS_t, *pSCSI_REPORT_LUNS_t; - - /* - * (per-level) LUN information bytes - */ -/* - * Following doesn't work on ARMCC compiler - * [apparently] because it pads every struct - * to be multiple of 4 bytes! - * So SCSI_LUN_LEVELS_t winds up being 16 - * bytes instead of 8! - * - typedef struct LUN_INFO - { - u8 AddrMethod_plus_LunOrBusNumber; - u8 LunOrTarget; - } SCSI_LUN_INFO_t, *pSCSI_LUN_INFO_t; - - typedef struct LUN_LEVELS - { - SCSI_LUN_INFO_t LUN_0; - SCSI_LUN_INFO_t LUN_1; - SCSI_LUN_INFO_t LUN_2; - SCSI_LUN_INFO_t LUN_3; - } SCSI_LUN_LEVELS_t, *pSCSI_LUN_LEVELS_t; -*/ - /* - * All 4 levels (8 bytes) of LUN information - */ - typedef struct LUN_LEVELS - { - u8 LVL1_AddrMethod_plus_LunOrBusNumber; - u8 LVL1_LunOrTarget; - u8 LVL2_AddrMethod_plus_LunOrBusNumber; - u8 LVL2_LunOrTarget; - u8 LVL3_AddrMethod_plus_LunOrBusNumber; - u8 LVL3_LunOrTarget; - u8 LVL4_AddrMethod_plus_LunOrBusNumber; - u8 LVL4_LunOrTarget; - } SCSI_LUN_LEVELS_t, *pSCSI_LUN_LEVELS_t; - - /* - * Structure definition for data returned by REPORT LUNS cmd; - * LUN reporting parameter list format - */ - typedef struct LUN_REPORT - { - u32 LunListLength; - u32 Reserved; - SCSI_LUN_LEVELS_t LunInfo[1]; - } SCSI_LUN_REPORT_t, *pSCSI_LUN_REPORT_t; - -/**************************************************************************** - * - * Externals - */ - -/**************************************************************************** - * - * Public Typedefs & Related Defines - */ - -/**************************************************************************** - * - * Macros (embedded, above) - */ - -/**************************************************************************** - * - * Public Variables - */ - -/**************************************************************************** - * - * Public Prototypes (module entry points) - */ - - -/***************************************************************************/ -#endif diff --git a/xen/drivers/net/3c59x.c b/xen/drivers/net/3c59x.c deleted file mode 100644 index c695986c32..0000000000 --- a/xen/drivers/net/3c59x.c +++ /dev/null @@ -1,2988 +0,0 @@ -/* EtherLinkXL.c: A 3Com EtherLink PCI III/XL ethernet driver for linux. */ -/* - Written 1996-1999 by Donald Becker. - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - This driver is for the 3Com "Vortex" and "Boomerang" series ethercards. - Members of the series include Fast EtherLink 3c590/3c592/3c595/3c597 - and the EtherLink XL 3c900 and 3c905 cards. - - Problem reports and questions should be directed to - vortex@scyld.com - - The author may be reached as becker@scyld.com, or C/O - Scyld Computing Corporation - 410 Severn Ave., Suite 210 - Annapolis MD 21403 - - Linux Kernel Additions: - - 0.99H+lk0.9 - David S. Miller - softnet, PCI DMA updates - 0.99H+lk1.0 - Jeff Garzik - Remove compatibility defines for kernel versions < 2.2.x. - Update for new 2.3.x module interface - LK1.1.2 (March 19, 2000) - * New PCI interface (jgarzik) - - LK1.1.3 25 April 2000, Andrew Morton - - Merged with 3c575_cb.c - - Don't set RxComplete in boomerang interrupt enable reg - - spinlock in vortex_timer to protect mdio functions - - disable local interrupts around call to vortex_interrupt in - vortex_tx_timeout() (So vortex_interrupt can use spin_lock()) - - Select window 3 in vortex_timer()'s write to Wn3_MAC_Ctrl - - In vortex_start_xmit(), move the lock to _after_ we've altered - vp->cur_tx and vp->tx_full. This defeats the race between - vortex_start_xmit() and vortex_interrupt which was identified - by Bogdan Costescu. - - Merged back support for six new cards from various sources - - Set vortex_have_pci if pci_module_init returns zero (fixes cardbus - insertion oops) - - Tell it that 3c905C has NWAY for 100bT autoneg - - Fix handling of SetStatusEnd in 'Too much work..' code, as - per 2.3.99's 3c575_cb (Dave Hinds). - - Split ISR into two for vortex & boomerang - - Fix MOD_INC/DEC races - - Handle resource allocation failures. - - Fix 3CCFE575CT LED polarity - - Make tx_interrupt_mitigation the default - - LK1.1.4 25 April 2000, Andrew Morton - - Add extra TxReset to vortex_up() to fix 575_cb hotplug initialisation probs. - - Put vortex_info_tbl into __devinitdata - - In the vortex_error StatsFull HACK, disable stats in vp->intr_enable as well - as in the hardware. - - Increased the loop counter in issue_and_wait from 2,000 to 4,000. - - LK1.1.5 28 April 2000, andrewm - - Added powerpc defines (John Daniel said these work...) - - Some extra diagnostics - - In vortex_error(), reset the Tx on maxCollisions. Otherwise most - chips usually get a Tx timeout. - - Added extra_reset module parm - - Replaced some inline timer manip with mod_timer - (Franois romieu ) - - In vortex_up(), don't make Wn3_config initialisation dependent upon has_nway - (this came across from 3c575_cb). - - LK1.1.6 06 Jun 2000, andrewm - - Backed out the PPC defines. - - Use del_timer_sync(), mod_timer(). - - Fix wrapped ulong comparison in boomerang_rx() - - Add IS_TORNADO, use it to suppress 3c905C checksum error msg - (Donald Becker, I Lee Hetherington ) - - Replace union wn3_config with BFINS/BFEXT manipulation for - sparc64 (Pete Zaitcev, Peter Jones) - - In vortex_error, do_tx_reset and vortex_tx_timeout(Vortex): - do a netif_wake_queue() to better recover from errors. (Anders Pedersen, - Donald Becker) - - Print a warning on out-of-memory (rate limited to 1 per 10 secs) - - Added two more Cardbus 575 NICs: 5b57 and 6564 (Paul Wagland) - - LK1.1.7 2 Jul 2000 andrewm - - Better handling of shared IRQs - - Reset the transmitter on a Tx reclaim error - - Fixed crash under OOM during vortex_open() (Mark Hemment) - - Fix Rx cessation problem during OOM (help from Mark Hemment) - - The spinlocks around the mdio access were blocking interrupts for 300uS. - Fix all this to use spin_lock_bh() within mdio_read/write - - Only write to TxFreeThreshold if it's a boomerang - other NICs don't - have one. - - Added 802.3x MAC-layer flow control support - - LK1.1.8 13 Aug 2000 andrewm - - Ignore request_region() return value - already reserved if Cardbus. - - Merged some additional Cardbus flags from Don's 0.99Qk - - Some fixes for 3c556 (Fred Maciel) - - Fix for EISA initialisation (Jan Rekorajski) - - Renamed MII_XCVR_PWR and EEPROM_230 to align with 3c575_cb and D. Becker's drivers - - Fixed MII_XCVR_PWR for 3CCFE575CT - - Added INVERT_LED_PWR, used it. - - Backed out the extra_reset stuff - - LK1.1.9 12 Sep 2000 andrewm - - Backed out the tx_reset_resume flags. It was a no-op. - - In vortex_error, don't reset the Tx on txReclaim errors - - In vortex_error, don't reset the Tx on maxCollisions errors. - Hence backed out all the DownListPtr logic here. - - In vortex_error, give Tornado cards a partial TxReset on - maxCollisions (David Hinds). Defined MAX_COLLISION_RESET for this. - - Redid some driver flags and device names based on pcmcia_cs-3.1.20. - - Fixed a bug where, if vp->tx_full is set when the interface - is downed, it remains set when the interface is upped. Bad - things happen. - - LK1.1.10 17 Sep 2000 andrewm - - Added EEPROM_8BIT for 3c555 (Fred Maciel) - - Added experimental support for the 3c556B Laptop Hurricane (Louis Gerbarg) - - Add HAS_NWAY to "3c900 Cyclone 10Mbps TPO" - - LK1.1.11 13 Nov 2000 andrewm - - Dump MOD_INC/DEC_USE_COUNT, use SET_MODULE_OWNER - - LK1.1.12 1 Jan 2001 andrewm (2.4.0-pre1) - - Call pci_enable_device before we request our IRQ (Tobias Ringstrom) - - Add 3c590 PCI latency timer hack to vortex_probe1 (from 0.99Ra) - - Added extended issue_and_wait for the 3c905CX. - - Look for an MII on PHY index 24 first (3c905CX oddity). - - Add HAS_NWAY to 3cSOHO100-TX (Brett Frankenberger) - - Don't free skbs we don't own on oom path in vortex_open(). - - LK1.1.13 27 Jan 2001 - - Added explicit `medialock' flag so we can truly - lock the media type down with `options'. - - "check ioremap return and some tidbits" (Arnaldo Carvalho de Melo ) - - Added and used EEPROM_NORESET for 3c556B PM resumes. - - Fixed leakage of vp->rx_ring. - - Break out separate HAS_HWCKSM device capability flag. - - Kill vp->tx_full (ANK) - - Merge zerocopy fragment handling (ANK?) - - LK1.1.14 15 Feb 2001 - - Enable WOL. Can be turned on with `enable_wol' module option. - - EISA and PCI initialisation fixes (jgarzik, Manfred Spraul) - - If a device's internalconfig register reports it has NWAY, - use it, even if autoselect is enabled. - - LK1.1.15 6 June 2001 akpm - - Prevent double counting of received bytes (Lars Christensen) - - Add ethtool support (jgarzik) - - Add module parm descriptions (Andrzej M. Krzysztofowicz) - - Implemented alloc_etherdev() API - - Special-case the 'Tx error 82' message. - - LK1.1.16 18 July 2001 akpm - - Make NETIF_F_SG dependent upon nr_free_highpages(), not on CONFIG_HIGHMEM - - Lessen verbosity of bootup messages - - Fix WOL - use new PM API functions. - - Use netif_running() instead of vp->open in suspend/resume. - - Don't reset the interface logic on open/close/rmmod. It upsets - autonegotiation, and hence DHCP (from 0.99T). - - Back out EEPROM_NORESET flag because of the above (we do it for all - NICs). - - Correct 3c982 identification string - - Rename wait_for_completion() to issue_and_wait() to avoid completion.h - clash. - - - See http://www.uow.edu.au/~andrewm/linux/#3c59x-2.3 for more details. - - Also see Documentation/networking/vortex.txt -*/ - -/* - * FIXME: This driver _could_ support MTU changing, but doesn't. See Don's hamachi.c implementation - * as well as other drivers - * - * NOTE: If you make 'vortex_debug' a constant (#define vortex_debug 0) the driver shrinks by 2k - * due to dead code elimination. There will be some performance benefits from this due to - * elimination of all the tests and reduced cache footprint. - */ - - -#define DRV_NAME "3c59x" -#define DRV_VERSION "LK1.1.16" -#define DRV_RELDATE "19 July 2001" - - -/* "Knobs" that adjust features and parameters. */ -/* Set the copy breakpoint for the copy-only-tiny-frames scheme. - Setting to > 1512 effectively disables this feature. */ -/*#ifndef __arm__ -static const int rx_copybreak = 200; -#else*/ -/* ARM systems perform better by disregarding the bus-master - transfer capability of these cards. -- rmk */ -/*static const int rx_copybreak = 1513; -#endif*/ -static const int rx_copybreak = 0; /* Xen doesn't copybreak in drivers. */ - -/* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */ -static const int mtu = 1500; -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static int max_interrupt_work = 32; -/* Tx timeout interval (millisecs) */ -static int watchdog = 5000; - -/* Allow aggregation of Tx interrupts. Saves CPU load at the cost - * of possible Tx stalls if the system is blocking interrupts - * somewhere else. Undefine this to disable. - */ -#define tx_interrupt_mitigation 1 - -/* Put out somewhat more debugging messages. (0: no msg, 1 minimal .. 6). */ -#define vortex_debug debug -#ifdef VORTEX_DEBUG -static int vortex_debug = VORTEX_DEBUG; -#else -static int vortex_debug = 1; -#endif - -#ifndef __OPTIMIZE__ -#error You must compile this file with the correct options! -#error See the last lines of the source file. -#error You must compile this driver with "-O". -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* For NR_IRQS only. */ -#include -#include -#include - -/* A few values that may be tweaked. */ -/* Keep the ring sizes a power of two for efficiency. */ -#undef TX_RING_SIZE -#undef RX_RING_SIZE -#define TX_RING_SIZE 16 -#define RX_RING_SIZE 32 -#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ - -/* Kernel compatibility defines, some common to David Hinds' PCMCIA package. - This is only in the support-all-kernels source code. */ - -#define RUN_AT(x) (jiffies + (x)) - -#include - - -static char version[] __devinitdata = -DRV_NAME ": Donald Becker and others. www.scyld.com/network/vortex.html\n"; - -MODULE_AUTHOR("Donald Becker "); -MODULE_DESCRIPTION("3Com 3c59x/3c9xx ethernet driver " - DRV_VERSION " " DRV_RELDATE); -MODULE_LICENSE("GPL"); - -MODULE_PARM(debug, "i"); -MODULE_PARM(options, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(hw_checksums, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(flow_ctrl, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(enable_wol, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(rx_copybreak, "i"); -MODULE_PARM(max_interrupt_work, "i"); -MODULE_PARM(compaq_ioaddr, "i"); -MODULE_PARM(compaq_irq, "i"); -MODULE_PARM(compaq_device_id, "i"); -MODULE_PARM(watchdog, "i"); -MODULE_PARM_DESC(debug, "3c59x debug level (0-6)"); -MODULE_PARM_DESC(options, "3c59x: Bits 0-3: media type, bit 4: bus mastering, bit 9: full duplex"); -MODULE_PARM_DESC(full_duplex, "3c59x full duplex setting(s) (1)"); -MODULE_PARM_DESC(hw_checksums, "3c59x Hardware checksum checking by adapter(s) (0-1)"); -MODULE_PARM_DESC(flow_ctrl, "3c59x 802.3x flow control usage (PAUSE only) (0-1)"); -MODULE_PARM_DESC(enable_wol, "3c59x: Turn on Wake-on-LAN for adapter(s) (0-1)"); -MODULE_PARM_DESC(rx_copybreak, "3c59x copy breakpoint for copy-only-tiny-frames"); -MODULE_PARM_DESC(max_interrupt_work, "3c59x maximum events handled per interrupt"); -MODULE_PARM_DESC(compaq_ioaddr, "3c59x PCI I/O base address (Compaq BIOS problem workaround)"); -MODULE_PARM_DESC(compaq_irq, "3c59x PCI IRQ number (Compaq BIOS problem workaround)"); -MODULE_PARM_DESC(compaq_device_id, "3c59x PCI device ID (Compaq BIOS problem workaround)"); -MODULE_PARM_DESC(watchdog, "3c59x transmit timeout in milliseconds"); - -/* Operational parameter that usually are not changed. */ - -/* The Vortex size is twice that of the original EtherLinkIII series: the - runtime register window, window 1, is now always mapped in. - The Boomerang size is twice as large as the Vortex -- it has additional - bus master control registers. */ -#define VORTEX_TOTAL_SIZE 0x20 -#define BOOMERANG_TOTAL_SIZE 0x40 - -/* Set iff a MII transceiver on any interface requires mdio preamble. - This only set with the original DP83840 on older 3c905 boards, so the extra - code size of a per-interface flag is not worthwhile. */ -static char mii_preamble_required; - -#define PFX DRV_NAME ": " - - - -/* - Theory of Operation - -I. Board Compatibility - -This device driver is designed for the 3Com FastEtherLink and FastEtherLink -XL, 3Com's PCI to 10/100baseT adapters. It also works with the 10Mbs -versions of the FastEtherLink cards. The supported product IDs are - 3c590, 3c592, 3c595, 3c597, 3c900, 3c905 - -The related ISA 3c515 is supported with a separate driver, 3c515.c, included -with the kernel source or available from - cesdis.gsfc.nasa.gov:/pub/linux/drivers/3c515.html - -II. Board-specific settings - -PCI bus devices are configured by the system at boot time, so no jumpers -need to be set on the board. The system BIOS should be set to assign the -PCI INTA signal to an otherwise unused system IRQ line. - -The EEPROM settings for media type and forced-full-duplex are observed. -The EEPROM media type should be left at the default "autoselect" unless using -10base2 or AUI connections which cannot be reliably detected. - -III. Driver operation - -The 3c59x series use an interface that's very similar to the previous 3c5x9 -series. The primary interface is two programmed-I/O FIFOs, with an -alternate single-contiguous-region bus-master transfer (see next). - -The 3c900 "Boomerang" series uses a full-bus-master interface with separate -lists of transmit and receive descriptors, similar to the AMD LANCE/PCnet, -DEC Tulip and Intel Speedo3. The first chip version retains a compatible -programmed-I/O interface that has been removed in 'B' and subsequent board -revisions. - -One extension that is advertised in a very large font is that the adapters -are capable of being bus masters. On the Vortex chip this capability was -only for a single contiguous region making it far less useful than the full -bus master capability. There is a significant performance impact of taking -an extra interrupt or polling for the completion of each transfer, as well -as difficulty sharing the single transfer engine between the transmit and -receive threads. Using DMA transfers is a win only with large blocks or -with the flawed versions of the Intel Orion motherboard PCI controller. - -The Boomerang chip's full-bus-master interface is useful, and has the -currently-unused advantages over other similar chips that queued transmit -packets may be reordered and receive buffer groups are associated with a -single frame. - -With full-bus-master support, this driver uses a "RX_COPYBREAK" scheme. -Rather than a fixed intermediate receive buffer, this scheme allocates -full-sized skbuffs as receive buffers. The value RX_COPYBREAK is used as -the copying breakpoint: it is chosen to trade-off the memory wasted by -passing the full-sized skbuff to the queue layer for all frames vs. the -copying cost of copying a frame to a correctly-sized skbuff. - -IIIC. Synchronization -The driver runs as two independent, single-threaded flows of control. One -is the send-packet routine, which enforces single-threaded use by the -dev->tbusy flag. The other thread is the interrupt handler, which is single -threaded by the hardware and other software. - -IV. Notes - -Thanks to Cameron Spitzer and Terry Murphy of 3Com for providing development -3c590, 3c595, and 3c900 boards. -The name "Vortex" is the internal 3Com project name for the PCI ASIC, and -the EISA version is called "Demon". According to Terry these names come -from rides at the local amusement park. - -The new chips support both ethernet (1.5K) and FDDI (4.5K) packet sizes! -This driver only supports ethernet packets because of the skbuff allocation -limit of 4K. -*/ - -/* This table drives the PCI probe routines. It's mostly boilerplate in all - of the drivers, and will likely be provided by some future kernel. -*/ -enum pci_flags_bit { - PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, - PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, -}; - -enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4, IS_TORNADO=8, - EEPROM_8BIT=0x10, /* AKPM: Uses 0x230 as the base bitmaps for EEPROM reads */ - HAS_PWR_CTRL=0x20, HAS_MII=0x40, HAS_NWAY=0x80, HAS_CB_FNS=0x100, - INVERT_MII_PWR=0x200, INVERT_LED_PWR=0x400, MAX_COLLISION_RESET=0x800, - EEPROM_OFFSET=0x1000, HAS_HWCKSM=0x2000 }; - -enum vortex_chips { - CH_3C590 = 0, - CH_3C592, - CH_3C597, - CH_3C595_1, - CH_3C595_2, - - CH_3C595_3, - CH_3C900_1, - CH_3C900_2, - CH_3C900_3, - CH_3C900_4, - - CH_3C900_5, - CH_3C900B_FL, - CH_3C905_1, - CH_3C905_2, - CH_3C905B_1, - - CH_3C905B_2, - CH_3C905B_FX, - CH_3C905C, - CH_3C980, - CH_3C9805, - - CH_3CSOHO100_TX, - CH_3C555, - CH_3C556, - CH_3C556B, - CH_3C575, - - CH_3C575_1, - CH_3CCFE575, - CH_3CCFE575CT, - CH_3CCFE656, - CH_3CCFEM656, - - CH_3CCFEM656_1, - CH_3C450, -}; - - -/* note: this array directly indexed by above enums, and MUST - * be kept in sync with both the enums above, and the PCI device - * table below - */ -static struct vortex_chip_info { - const char *name; - int flags; - int drv_flags; - int io_size; -} vortex_info_tbl[] __devinitdata = { -#define EISA_TBL_OFFSET 0 /* Offset of this entry for vortex_eisa_init */ - {"3c590 Vortex 10Mbps", - PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, }, - {"3c592 EISA 10Mbps Demon/Vortex", /* AKPM: from Don's 3c59x_cb.c 0.49H */ - PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, }, - {"3c597 EISA Fast Demon/Vortex", /* AKPM: from Don's 3c59x_cb.c 0.49H */ - PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, }, - {"3c595 Vortex 100baseTx", - PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, }, - {"3c595 Vortex 100baseT4", - PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, }, - - {"3c595 Vortex 100base-MII", - PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, }, - {"3c900 Boomerang 10baseT", - PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, }, - {"3c900 Boomerang 10Mbps Combo", - PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, }, - {"3c900 Cyclone 10Mbps TPO", /* AKPM: from Don's 0.99M */ - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, }, - {"3c900 Cyclone 10Mbps Combo", - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, }, - - {"3c900 Cyclone 10Mbps TPC", /* AKPM: from Don's 0.99M */ - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, }, - {"3c900B-FL Cyclone 10base-FL", - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, }, - {"3c905 Boomerang 100baseTx", - PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, }, - {"3c905 Boomerang 100baseT4", - PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, }, - {"3c905B Cyclone 100baseTx", - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, }, - - {"3c905B Cyclone 10/100/BNC", - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, }, - {"3c905B-FX Cyclone 100baseFx", - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, }, - {"3c905C Tornado", - PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, }, - {"3c980 Cyclone", - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, }, - {"3c982 Dual Port Server Cyclone", - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, }, - - {"3cSOHO100-TX Hurricane", - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, }, - {"3c555 Laptop Hurricane", - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|EEPROM_8BIT|HAS_HWCKSM, 128, }, - {"3c556 Laptop Tornado", - PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_8BIT|HAS_CB_FNS|INVERT_MII_PWR| - HAS_HWCKSM, 128, }, - {"3c556B Laptop Hurricane", - PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_OFFSET|HAS_CB_FNS|INVERT_MII_PWR| - HAS_HWCKSM, 128, }, - {"3c575 [Megahertz] 10/100 LAN CardBus", - PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, }, - - {"3c575 Boomerang CardBus", - PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, }, - {"3CCFE575BT Cyclone CardBus", - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT| - INVERT_LED_PWR|HAS_HWCKSM, 128, }, - {"3CCFE575CT Tornado CardBus", - PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR| - MAX_COLLISION_RESET|HAS_HWCKSM, 128, }, - {"3CCFE656 Cyclone CardBus", - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR| - INVERT_LED_PWR|HAS_HWCKSM, 128, }, - {"3CCFEM656B Cyclone+Winmodem CardBus", - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR| - INVERT_LED_PWR|HAS_HWCKSM, 128, }, - - {"3CXFEM656C Tornado+Winmodem CardBus", /* From pcmcia-cs-3.1.5 */ - PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR| - MAX_COLLISION_RESET|HAS_HWCKSM, 128, }, - {"3c450 HomePNA Tornado", /* AKPM: from Don's 0.99Q */ - PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, }, - {0,}, /* 0 terminated list. */ -}; - - -static struct pci_device_id vortex_pci_tbl[] __devinitdata = { - { 0x10B7, 0x5900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C590 }, - { 0x10B7, 0x5920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C592 }, - { 0x10B7, 0x5970, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C597 }, - { 0x10B7, 0x5950, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C595_1 }, - { 0x10B7, 0x5951, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C595_2 }, - - { 0x10B7, 0x5952, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C595_3 }, - { 0x10B7, 0x9000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_1 }, - { 0x10B7, 0x9001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_2 }, - { 0x10B7, 0x9004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_3 }, - { 0x10B7, 0x9005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_4 }, - - { 0x10B7, 0x9006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_5 }, - { 0x10B7, 0x900A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900B_FL }, - { 0x10B7, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_1 }, - { 0x10B7, 0x9051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_2 }, - { 0x10B7, 0x9055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_1 }, - - { 0x10B7, 0x9058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_2 }, - { 0x10B7, 0x905A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_FX }, - { 0x10B7, 0x9200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905C }, - { 0x10B7, 0x9800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C980 }, - { 0x10B7, 0x9805, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C9805 }, - - { 0x10B7, 0x7646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CSOHO100_TX }, - { 0x10B7, 0x5055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C555 }, - { 0x10B7, 0x6055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C556 }, - { 0x10B7, 0x6056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C556B }, - { 0x10B7, 0x5b57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575 }, - - { 0x10B7, 0x5057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575_1 }, - { 0x10B7, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575 }, - { 0x10B7, 0x5257, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575CT }, - { 0x10B7, 0x6560, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE656 }, - { 0x10B7, 0x6562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656 }, - - { 0x10B7, 0x6564, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656_1 }, - { 0x10B7, 0x4500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C450 }, - {0,} /* 0 terminated list. */ -}; -MODULE_DEVICE_TABLE(pci, vortex_pci_tbl); - - -/* Operational definitions. - These are not used by other compilation units and thus are not - exported in a ".h" file. - - First the windows. There are eight register windows, with the command - and status registers available in each. - */ -#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD) -#define EL3_CMD 0x0e -#define EL3_STATUS 0x0e - -/* The top five bits written to EL3_CMD are a command, the lower - 11 bits are the parameter, if applicable. - Note that 11 parameters bits was fine for ethernet, but the new chip - can handle FDDI length frames (~4500 octets) and now parameters count - 32-bit 'Dwords' rather than octets. */ - -enum vortex_cmd { - TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11, - RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, - UpStall = 6<<11, UpUnstall = (6<<11)+1, - DownStall = (6<<11)+2, DownUnstall = (6<<11)+3, - RxDiscard = 8<<11, TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11, - FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11, - SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11, - SetTxThreshold = 18<<11, SetTxStart = 19<<11, - StartDMAUp = 20<<11, StartDMADown = (20<<11)+1, StatsEnable = 21<<11, - StatsDisable = 22<<11, StopCoax = 23<<11, SetFilterBit = 25<<11,}; - -/* The SetRxFilter command accepts the following classes: */ -enum RxFilter { - RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 }; - -/* Bits in the general status register. */ -enum vortex_status { - IntLatch = 0x0001, HostError = 0x0002, TxComplete = 0x0004, - TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020, - IntReq = 0x0040, StatsFull = 0x0080, - DMADone = 1<<8, DownComplete = 1<<9, UpComplete = 1<<10, - DMAInProgress = 1<<11, /* DMA controller is still busy.*/ - CmdInProgress = 1<<12, /* EL3_CMD is still busy.*/ -}; - -/* Register window 1 offsets, the window used in normal operation. - On the Vortex this window is always mapped at offsets 0x10-0x1f. */ -enum Window1 { - TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14, - RxStatus = 0x18, Timer=0x1A, TxStatus = 0x1B, - TxFree = 0x1C, /* Remaining free bytes in Tx buffer. */ -}; -enum Window0 { - Wn0EepromCmd = 10, /* Window 0: EEPROM command register. */ - Wn0EepromData = 12, /* Window 0: EEPROM results register. */ - IntrStatus=0x0E, /* Valid in all windows. */ -}; -enum Win0_EEPROM_bits { - EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0, - EEPROM_EWENB = 0x30, /* Enable erasing/writing for 10 msec. */ - EEPROM_EWDIS = 0x00, /* Disable EWENB before 10 msec timeout. */ -}; -/* EEPROM locations. */ -enum eeprom_offset { - PhysAddr01=0, PhysAddr23=1, PhysAddr45=2, ModelID=3, - EtherLink3ID=7, IFXcvrIO=8, IRQLine=9, - NodeAddr01=10, NodeAddr23=11, NodeAddr45=12, - DriverTune=13, Checksum=15}; - -enum Window2 { /* Window 2. */ - Wn2_ResetOptions=12, -}; -enum Window3 { /* Window 3: MAC/config bits. */ - Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8, -}; - -#define BFEXT(value, offset, bitcount) \ - ((((unsigned long)(value)) >> (offset)) & ((1 << (bitcount)) - 1)) - -#define BFINS(lhs, rhs, offset, bitcount) \ - (((lhs) & ~((((1 << (bitcount)) - 1)) << (offset))) | \ - (((rhs) & ((1 << (bitcount)) - 1)) << (offset))) - -#define RAM_SIZE(v) BFEXT(v, 0, 3) -#define RAM_WIDTH(v) BFEXT(v, 3, 1) -#define RAM_SPEED(v) BFEXT(v, 4, 2) -#define ROM_SIZE(v) BFEXT(v, 6, 2) -#define RAM_SPLIT(v) BFEXT(v, 16, 2) -#define XCVR(v) BFEXT(v, 20, 4) -#define AUTOSELECT(v) BFEXT(v, 24, 1) - -enum Window4 { /* Window 4: Xcvr/media bits. */ - Wn4_FIFODiag = 4, Wn4_NetDiag = 6, Wn4_PhysicalMgmt=8, Wn4_Media = 10, -}; -enum Win4_Media_bits { - Media_SQE = 0x0008, /* Enable SQE error counting for AUI. */ - Media_10TP = 0x00C0, /* Enable link beat and jabber for 10baseT. */ - Media_Lnk = 0x0080, /* Enable just link beat for 100TX/100FX. */ - Media_LnkBeat = 0x0800, -}; -enum Window7 { /* Window 7: Bus Master control. */ - Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12, -}; -/* Boomerang bus master control registers. */ -enum MasterCtrl { - PktStatus = 0x20, DownListPtr = 0x24, FragAddr = 0x28, FragLen = 0x2c, - TxFreeThreshold = 0x2f, UpPktStatus = 0x30, UpListPtr = 0x38, -}; - -/* The Rx and Tx descriptor lists. - Caution Alpha hackers: these types are 32 bits! Note also the 8 byte - alignment contraint on tx_ring[] and rx_ring[]. */ -#define LAST_FRAG 0x80000000 /* Last Addr/Len pair in descriptor. */ -#define DN_COMPLETE 0x00010000 /* This packet has been downloaded */ -struct boom_rx_desc { - u32 next; /* Last entry points to 0. */ - s32 status; - u32 addr; /* Up to 63 addr/len pairs possible. */ - s32 length; /* Set LAST_FRAG to indicate last pair. */ -}; -/* Values for the Rx status entry. */ -enum rx_desc_status { - RxDComplete=0x00008000, RxDError=0x4000, - /* See boomerang_rx() for actual error bits */ - IPChksumErr=1<<25, TCPChksumErr=1<<26, UDPChksumErr=1<<27, - IPChksumValid=1<<29, TCPChksumValid=1<<30, UDPChksumValid=1<<31, -}; - -#ifdef MAX_SKB_FRAGS -#define DO_ZEROCOPY 1 -#else -#define DO_ZEROCOPY 0 -#endif - -struct boom_tx_desc { - u32 next; /* Last entry points to 0. */ - s32 status; /* bits 0:12 length, others see below. */ -#if DO_ZEROCOPY - struct { - u32 addr; - s32 length; - } frag[1+MAX_SKB_FRAGS]; -#else - u32 addr; - s32 length; -#endif -}; - -/* Values for the Tx status entry. */ -enum tx_desc_status { - CRCDisable=0x2000, TxDComplete=0x8000, - AddIPChksum=0x02000000, AddTCPChksum=0x04000000, AddUDPChksum=0x08000000, - TxIntrUploaded=0x80000000, /* IRQ when in FIFO, but maybe not sent. */ -}; - -/* Chip features we care about in vp->capabilities, read from the EEPROM. */ -enum ChipCaps { CapBusMaster=0x20, CapPwrMgmt=0x2000 }; - -struct vortex_private { - /* The Rx and Tx rings should be quad-word-aligned. */ - struct boom_rx_desc* rx_ring; - struct boom_tx_desc* tx_ring; - dma_addr_t rx_ring_dma; - dma_addr_t tx_ring_dma; - /* The addresses of transmit- and receive-in-place skbuffs. */ - struct sk_buff* rx_skbuff[RX_RING_SIZE]; - struct sk_buff* tx_skbuff[TX_RING_SIZE]; - struct net_device *next_module; /* NULL if PCI device */ - unsigned int cur_rx, cur_tx; /* The next free ring entry */ - unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ - struct net_device_stats stats; - struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */ - dma_addr_t tx_skb_dma; /* Allocated DMA address for bus master ctrl DMA. */ - - /* PCI configuration space information. */ - struct pci_dev *pdev; - char *cb_fn_base; /* CardBus function status addr space. */ - - /* Some values here only for performance evaluation and path-coverage */ - int rx_nocopy, rx_copy, queued_packet, rx_csumhits; - int card_idx; - - /* The remainder are related to chip state, mostly media selection. */ - struct timer_list timer; /* Media selection timer. */ - struct timer_list rx_oom_timer; /* Rx skb allocation retry timer */ - int options; /* User-settable misc. driver options. */ - unsigned int media_override:4, /* Passed-in media type. */ - default_media:4, /* Read from the EEPROM/Wn3_Config. */ - full_duplex:1, force_fd:1, autoselect:1, - bus_master:1, /* Vortex can only do a fragment bus-m. */ - full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang */ - flow_ctrl:1, /* Use 802.3x flow control (PAUSE only) */ - partner_flow_ctrl:1, /* Partner supports flow control */ - has_nway:1, - enable_wol:1, /* Wake-on-LAN is enabled */ - pm_state_valid:1, /* power_state[] has sane contents */ - open:1, - medialock:1, - must_free_region:1; /* Flag: if zero, Cardbus owns the I/O region */ - int drv_flags; - u16 status_enable; - u16 intr_enable; - u16 available_media; /* From Wn3_Options. */ - u16 capabilities, info1, info2; /* Various, from EEPROM. */ - u16 advertising; /* NWay media advertisement */ - unsigned char phys[2]; /* MII device addresses. */ - u16 deferred; /* Resend these interrupts when we - * bale from the ISR */ - u16 io_size; /* Size of PCI region (for release_region) */ - spinlock_t lock; /* Serialise access to device & its vortex_private */ - spinlock_t mdio_lock; /* Serialise access to mdio hardware */ - u32 power_state[16]; -}; - -/* The action to take with a media selection timer tick. - Note that we deviate from the 3Com order by checking 10base2 before AUI. - */ -enum xcvr_types { - XCVR_10baseT=0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx, - XCVR_100baseFx, XCVR_MII=6, XCVR_NWAY=8, XCVR_ExtMII=9, XCVR_Default=10, -}; - -static struct media_table { - char *name; - unsigned int media_bits:16, /* Bits to set in Wn4_Media register. */ - mask:8, /* The transceiver-present bit in Wn3_Config.*/ - next:8; /* The media type to try next. */ - int wait; /* Time before we check media status. */ -} media_tbl[] = { - { "10baseT", Media_10TP,0x08, XCVR_10base2, (14*HZ)/10}, - { "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1*HZ)/10}, - { "undefined", 0, 0x80, XCVR_10baseT, 10000}, - { "10base2", 0, 0x10, XCVR_AUI, (1*HZ)/10}, - { "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14*HZ)/10}, - { "100baseFX", Media_Lnk, 0x04, XCVR_MII, (14*HZ)/10}, - { "MII", 0, 0x41, XCVR_10baseT, 3*HZ }, - { "undefined", 0, 0x01, XCVR_10baseT, 10000}, - { "Autonegotiate", 0, 0x41, XCVR_10baseT, 3*HZ}, - { "MII-External", 0, 0x41, XCVR_10baseT, 3*HZ }, - { "Default", 0, 0xFF, XCVR_10baseT, 10000}, -}; - -static int vortex_probe1(struct pci_dev *pdev, long ioaddr, int irq, - int chip_idx, int card_idx); -static void vortex_up(struct net_device *dev); -static void vortex_down(struct net_device *dev); -static int vortex_open(struct net_device *dev); -static void mdio_sync(long ioaddr, int bits); -static int mdio_read(struct net_device *dev, int phy_id, int location); -static void mdio_write(struct net_device *vp, int phy_id, int location, int value); -static void vortex_timer(unsigned long arg); -static void rx_oom_timer(unsigned long arg); -static int vortex_start_xmit(struct sk_buff *skb, struct net_device *dev); -static int boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev); -static int vortex_rx(struct net_device *dev); -static int boomerang_rx(struct net_device *dev); -static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static int vortex_close(struct net_device *dev); -static void dump_tx_ring(struct net_device *dev); -static void update_stats(long ioaddr, struct net_device *dev); -static struct net_device_stats *vortex_get_stats(struct net_device *dev); -static void set_rx_mode(struct net_device *dev); -static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static void vortex_tx_timeout(struct net_device *dev); -static void acpi_set_WOL(struct net_device *dev); - -/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */ -/* Option count limit only -- unlimited interfaces are supported. */ -#define MAX_UNITS 8 -static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1,}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int hw_checksums[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int flow_ctrl[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int enable_wol[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* #define dev_alloc_skb dev_alloc_skb_debug */ - -/* A list of all installed Vortex EISA devices, for removing the driver module. */ -static struct net_device *root_vortex_eisa_dev; - -/* Variables to work-around the Compaq PCI BIOS32 problem. */ -static int compaq_ioaddr, compaq_irq, compaq_device_id = 0x5900; - -static int vortex_cards_found; - -#ifdef CONFIG_PM - -static int vortex_suspend (struct pci_dev *pdev, u32 state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - - if (dev && dev->priv) { - if (netif_running(dev)) { - netif_device_detach(dev); - vortex_down(dev); - } - } - return 0; -} - -static int vortex_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - - if (dev && dev->priv) { - if (netif_running(dev)) { - vortex_up(dev); - netif_device_attach(dev); - } - } - return 0; -} - -#endif /* CONFIG_PM */ - -/* returns count found (>= 0), or negative on error */ -static int __init vortex_eisa_init (void) -{ - long ioaddr; - int rc; - int orig_cards_found = vortex_cards_found; - - /* Now check all slots of the EISA bus. */ - if (!EISA_bus) - return 0; - - for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) { - int device_id; - - if (request_region(ioaddr, VORTEX_TOTAL_SIZE, DRV_NAME) == NULL) - continue; - - /* Check the standard EISA ID register for an encoded '3Com'. */ - if (inw(ioaddr + 0xC80) != 0x6d50) { - release_region (ioaddr, VORTEX_TOTAL_SIZE); - continue; - } - - /* Check for a product that we support, 3c59{2,7} any rev. */ - device_id = (inb(ioaddr + 0xC82)<<8) + inb(ioaddr + 0xC83); - if ((device_id & 0xFF00) != 0x5900) { - release_region (ioaddr, VORTEX_TOTAL_SIZE); - continue; - } - - rc = vortex_probe1(NULL, ioaddr, inw(ioaddr + 0xC88) >> 12, - EISA_TBL_OFFSET, vortex_cards_found); - if (rc == 0) - vortex_cards_found++; - else - release_region (ioaddr, VORTEX_TOTAL_SIZE); - } - - /* Special code to work-around the Compaq PCI BIOS32 problem. */ - if (compaq_ioaddr) { - vortex_probe1(NULL, compaq_ioaddr, compaq_irq, - compaq_device_id, vortex_cards_found++); - } - - return vortex_cards_found - orig_cards_found; -} - -/* returns count (>= 0), or negative on error */ -static int __devinit vortex_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - int rc; - - /* wake up and enable device */ - if (pci_enable_device (pdev)) { - rc = -EIO; - } else { - rc = vortex_probe1 (pdev, pci_resource_start (pdev, 0), pdev->irq, - ent->driver_data, vortex_cards_found); - if (rc == 0) - vortex_cards_found++; - } - return rc; -} - -/* - * Start up the PCI device which is described by *pdev. - * Return 0 on success. - * - * NOTE: pdev can be NULL, for the case of an EISA driver - */ -static int __devinit vortex_probe1(struct pci_dev *pdev, - long ioaddr, int irq, - int chip_idx, int card_idx) -{ - struct vortex_private *vp; - int option; - unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */ - int i, step; - struct net_device *dev; - static int printed_version; - int retval, print_info; - struct vortex_chip_info * const vci = &vortex_info_tbl[chip_idx]; - char *print_name; - - if (!printed_version) { - printk (version); - printed_version = 1; - } - - print_name = pdev ? pdev->slot_name : "3c59x"; - - dev = alloc_etherdev(sizeof(*vp)); - retval = -ENOMEM; - if (!dev) { - printk (KERN_ERR PFX "unable to allocate etherdev, aborting\n"); - goto out; - } - SET_MODULE_OWNER(dev); - vp = dev->priv; - - /* The lower four bits are the media type. */ - if (dev->mem_start) { - /* - * The 'options' param is passed in as the third arg to the - * LILO 'ether=' argument for non-modular use - */ - option = dev->mem_start; - } - else if (card_idx < MAX_UNITS) - option = options[card_idx]; - else - option = -1; - - if (option > 0) { - if (option & 0x8000) - vortex_debug = 7; - if (option & 0x4000) - vortex_debug = 2; - if (option & 0x0400) - vp->enable_wol = 1; - } - - print_info = (vortex_debug > 1); - if (print_info) - printk (KERN_INFO "See Documentation/networking/vortex.txt\n"); - - printk(KERN_INFO "%s: 3Com %s %s at 0x%lx. Vers " DRV_VERSION "\n", - print_name, - pdev ? "PCI" : "EISA", - vci->name, - ioaddr); - - dev->base_addr = ioaddr; - dev->irq = irq; - dev->mtu = mtu; - vp->drv_flags = vci->drv_flags; - vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0; - vp->io_size = vci->io_size; - vp->card_idx = card_idx; - - /* module list only for EISA devices */ - if (pdev == NULL) { - vp->next_module = root_vortex_eisa_dev; - root_vortex_eisa_dev = dev; - } - - /* PCI-only startup logic */ - if (pdev) { - /* EISA resources already marked, so only PCI needs to do this here */ - /* Ignore return value, because Cardbus drivers already allocate for us */ - if (request_region(ioaddr, vci->io_size, print_name) != NULL) - vp->must_free_region = 1; - - /* enable bus-mastering if necessary */ - if (vci->flags & PCI_USES_MASTER) - pci_set_master (pdev); - - if (vci->drv_flags & IS_VORTEX) { - u8 pci_latency; - u8 new_latency = 248; - - /* Check the PCI latency value. On the 3c590 series the latency timer - must be set to the maximum value to avoid data corruption that occurs - when the timer expires during a transfer. This bug exists the Vortex - chip only. */ - pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); - if (pci_latency < new_latency) { - printk(KERN_INFO "%s: Overriding PCI latency" - " timer (CFLT) setting of %d, new value is %d.\n", - print_name, pci_latency, new_latency); - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency); - } - } - } - - spin_lock_init(&vp->lock); - spin_lock_init(&vp->mdio_lock); - vp->pdev = pdev; - - /* Makes sure rings are at least 16 byte aligned. */ - vp->rx_ring = pci_alloc_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE - + sizeof(struct boom_tx_desc) * TX_RING_SIZE, - &vp->rx_ring_dma); - retval = -ENOMEM; - if (vp->rx_ring == 0) - goto free_region; - - vp->tx_ring = (struct boom_tx_desc *)(vp->rx_ring + RX_RING_SIZE); - vp->tx_ring_dma = vp->rx_ring_dma + sizeof(struct boom_rx_desc) * RX_RING_SIZE; - - /* if we are a PCI driver, we store info in pdev->driver_data - * instead of a module list */ - if (pdev) - pci_set_drvdata(pdev, dev); - - vp->media_override = 7; - if (option >= 0) { - vp->media_override = ((option & 7) == 2) ? 0 : option & 15; - if (vp->media_override != 7) - vp->medialock = 1; - vp->full_duplex = (option & 0x200) ? 1 : 0; - vp->bus_master = (option & 16) ? 1 : 0; - } - - if (card_idx < MAX_UNITS) { - if (full_duplex[card_idx] > 0) - vp->full_duplex = 1; - if (flow_ctrl[card_idx] > 0) - vp->flow_ctrl = 1; - if (enable_wol[card_idx] > 0) - vp->enable_wol = 1; - } - - vp->force_fd = vp->full_duplex; - vp->options = option; - /* Read the station address from the EEPROM. */ - EL3WINDOW(0); - { - int base; - - if (vci->drv_flags & EEPROM_8BIT) - base = 0x230; - else if (vci->drv_flags & EEPROM_OFFSET) - base = EEPROM_Read + 0x30; - else - base = EEPROM_Read; - - for (i = 0; i < 0x40; i++) { - int timer; - outw(base + i, ioaddr + Wn0EepromCmd); - /* Pause for at least 162 us. for the read to take place. */ - for (timer = 10; timer >= 0; timer--) { - udelay(162); - if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0) - break; - } - eeprom[i] = inw(ioaddr + Wn0EepromData); - } - } - for (i = 0; i < 0x18; i++) - checksum ^= eeprom[i]; - checksum = (checksum ^ (checksum >> 8)) & 0xff; - if (checksum != 0x00) { /* Grrr, needless incompatible change 3Com. */ - while (i < 0x21) - checksum ^= eeprom[i++]; - checksum = (checksum ^ (checksum >> 8)) & 0xff; - } - if ((checksum != 0x00) && !(vci->drv_flags & IS_TORNADO)) - printk(" ***INVALID CHECKSUM %4.4x*** ", checksum); - for (i = 0; i < 3; i++) - ((u16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]); - if (print_info) { - for (i = 0; i < 6; i++) - printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]); - } - EL3WINDOW(2); - for (i = 0; i < 6; i++) - outb(dev->dev_addr[i], ioaddr + i); - -#ifdef __sparc__ - if (print_info) - printk(", IRQ %s\n", __irq_itoa(dev->irq)); -#else - if (print_info) - printk(", IRQ %d\n", dev->irq); - /* Tell them about an invalid IRQ. */ - if (dev->irq <= 0 || dev->irq >= NR_IRQS) - printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n", - dev->irq); -#endif - - EL3WINDOW(4); - step = (inb(ioaddr + Wn4_NetDiag) & 0x1e) >> 1; - if (print_info) { - printk(KERN_INFO " product code %02x%02x rev %02x.%d date %02d-" - "%02d-%02d\n", eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14], - step, (eeprom[4]>>5) & 15, eeprom[4] & 31, eeprom[4]>>9); - } - - - if (pdev && vci->drv_flags & HAS_CB_FNS) { - unsigned long fn_st_addr; /* Cardbus function status space */ - unsigned short n; - - fn_st_addr = pci_resource_start (pdev, 2); - if (fn_st_addr) { - vp->cb_fn_base = ioremap(fn_st_addr, 128); - retval = -ENOMEM; - if (!vp->cb_fn_base) - goto free_ring; - } - if (print_info) { - printk(KERN_INFO "%s: CardBus functions mapped %8.8lx->%p\n", - print_name, fn_st_addr, vp->cb_fn_base); - } - EL3WINDOW(2); - - n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010; - if (vp->drv_flags & INVERT_LED_PWR) - n |= 0x10; - if (vp->drv_flags & INVERT_MII_PWR) - n |= 0x4000; - outw(n, ioaddr + Wn2_ResetOptions); - } - - /* Extract our information from the EEPROM data. */ - vp->info1 = eeprom[13]; - vp->info2 = eeprom[15]; - vp->capabilities = eeprom[16]; - - if (vp->info1 & 0x8000) { - vp->full_duplex = 1; - if (print_info) - printk(KERN_INFO "Full duplex capable\n"); - } - - { - static const char * ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; - unsigned int config; - EL3WINDOW(3); - vp->available_media = inw(ioaddr + Wn3_Options); - if ((vp->available_media & 0xff) == 0) /* Broken 3c916 */ - vp->available_media = 0x40; - config = inl(ioaddr + Wn3_Config); - if (print_info) { - printk(KERN_DEBUG " Internal config register is %4.4x, " - "transceivers %#x.\n", config, inw(ioaddr + Wn3_Options)); - printk(KERN_INFO " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", - 8 << RAM_SIZE(config), - RAM_WIDTH(config) ? "word" : "byte", - ram_split[RAM_SPLIT(config)], - AUTOSELECT(config) ? "autoselect/" : "", - XCVR(config) > XCVR_ExtMII ? "" : - media_tbl[XCVR(config)].name); - } - vp->default_media = XCVR(config); - if (vp->default_media == XCVR_NWAY) - vp->has_nway = 1; - vp->autoselect = AUTOSELECT(config); - } - - if (vp->media_override != 7) { - printk(KERN_INFO "%s: Media override to transceiver type %d (%s).\n", - print_name, vp->media_override, - media_tbl[vp->media_override].name); - dev->if_port = vp->media_override; - } else - dev->if_port = vp->default_media; - - if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) { - int phy, phy_idx = 0; - EL3WINDOW(4); - mii_preamble_required++; - mii_preamble_required++; - mdio_read(dev, 24, 1); - for (phy = 0; phy < 32 && phy_idx < 1; phy++) { - int mii_status, phyx; - - /* - * For the 3c905CX we look at index 24 first, because it bogusly - * reports an external PHY at all indices - */ - if (phy == 0) - phyx = 24; - else if (phy <= 24) - phyx = phy - 1; - else - phyx = phy; - mii_status = mdio_read(dev, phyx, 1); - if (mii_status && mii_status != 0xffff) { - vp->phys[phy_idx++] = phyx; - if (print_info) { - printk(KERN_INFO " MII transceiver found at address %d," - " status %4x.\n", phyx, mii_status); - } - if ((mii_status & 0x0040) == 0) - mii_preamble_required++; - } - } - mii_preamble_required--; - if (phy_idx == 0) { - printk(KERN_WARNING" ***WARNING*** No MII transceivers found!\n"); - vp->phys[0] = 24; - } else { - vp->advertising = mdio_read(dev, vp->phys[0], 4); - if (vp->full_duplex) { - /* Only advertise the FD media types. */ - vp->advertising &= ~0x02A0; - mdio_write(dev, vp->phys[0], 4, vp->advertising); - } - } - } - - if (vp->capabilities & CapBusMaster) { - vp->full_bus_master_tx = 1; - if (print_info) { - printk(KERN_INFO " Enabling bus-master transmits and %s receives.\n", - (vp->info2 & 1) ? "early" : "whole-frame" ); - } - vp->full_bus_master_rx = (vp->info2 & 1) ? 1 : 2; - vp->bus_master = 0; /* AKPM: vortex only */ - } - - /* The 3c59x-specific entries in the device structure. */ - dev->open = vortex_open; - if (vp->full_bus_master_tx) { - dev->hard_start_xmit = boomerang_start_xmit; - /* Actually, it still should work with iommu. */ - dev->features |= NETIF_F_SG; - if (((hw_checksums[card_idx] == -1) && (vp->drv_flags & HAS_HWCKSM)) || - (hw_checksums[card_idx] == 1)) { - dev->features |= NETIF_F_IP_CSUM; - } - } else { - dev->hard_start_xmit = vortex_start_xmit; - } - - if (print_info) { - printk(KERN_INFO "%s: scatter/gather %sabled. h/w checksums %sabled\n", - print_name, - (dev->features & NETIF_F_SG) ? "en":"dis", - (dev->features & NETIF_F_IP_CSUM) ? "en":"dis"); - } - - dev->stop = vortex_close; - dev->get_stats = vortex_get_stats; - dev->do_ioctl = vortex_ioctl; - dev->set_multicast_list = set_rx_mode; - dev->tx_timeout = vortex_tx_timeout; - dev->watchdog_timeo = (watchdog * HZ) / 1000; - if (pdev && vp->enable_wol) { - vp->pm_state_valid = 1; - pci_save_state(vp->pdev, vp->power_state); - acpi_set_WOL(dev); - } - retval = register_netdev(dev); - if (retval == 0) - return 0; - -free_ring: - pci_free_consistent(pdev, - sizeof(struct boom_rx_desc) * RX_RING_SIZE - + sizeof(struct boom_tx_desc) * TX_RING_SIZE, - vp->rx_ring, - vp->rx_ring_dma); -free_region: - if (vp->must_free_region) - release_region(ioaddr, vci->io_size); - kfree (dev); - printk(KERN_ERR PFX "vortex_probe1 fails. Returns %d\n", retval); -out: - return retval; -} - -static void -issue_and_wait(struct net_device *dev, int cmd) -{ - int i; - - outw(cmd, dev->base_addr + EL3_CMD); - for (i = 0; i < 2000; i++) { - if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress)) - return; - } - - /* OK, that didn't work. Do it the slow way. One second */ - for (i = 0; i < 100000; i++) { - if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress)) { - if (vortex_debug > 1) - printk(KERN_INFO "%s: command 0x%04x took %d usecs\n", - dev->name, cmd, i * 10); - return; - } - udelay(10); - } - printk(KERN_ERR "%s: command 0x%04x did not complete! Status=0x%x\n", - dev->name, cmd, inw(dev->base_addr + EL3_STATUS)); -} - -static void -vortex_up(struct net_device *dev) -{ - long ioaddr = dev->base_addr; - struct vortex_private *vp = (struct vortex_private *)dev->priv; - unsigned int config; - int i; - - if (vp->pdev && vp->enable_wol) { - pci_set_power_state(vp->pdev, 0); /* Go active */ - pci_restore_state(vp->pdev, vp->power_state); - } - - /* Before initializing select the active media port. */ - EL3WINDOW(3); - config = inl(ioaddr + Wn3_Config); - - if (vp->media_override != 7) { - printk(KERN_INFO "%s: Media override to transceiver %d (%s).\n", - dev->name, vp->media_override, - media_tbl[vp->media_override].name); - dev->if_port = vp->media_override; - } else if (vp->autoselect) { - if (vp->has_nway) { - if (vortex_debug > 1) - printk(KERN_INFO "%s: using NWAY device table, not %d\n", - dev->name, dev->if_port); - dev->if_port = XCVR_NWAY; - } else { - /* Find first available media type, starting with 100baseTx. */ - dev->if_port = XCVR_100baseTx; - while (! (vp->available_media & media_tbl[dev->if_port].mask)) - dev->if_port = media_tbl[dev->if_port].next; - if (vortex_debug > 1) - printk(KERN_INFO "%s: first available media type: %s\n", - dev->name, media_tbl[dev->if_port].name); - } - } else { - dev->if_port = vp->default_media; - if (vortex_debug > 1) - printk(KERN_INFO "%s: using default media %s\n", - dev->name, media_tbl[dev->if_port].name); - } - - init_timer(&vp->timer); - vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait); - vp->timer.data = (unsigned long)dev; - vp->timer.function = vortex_timer; /* timer handler */ - add_timer(&vp->timer); - - init_timer(&vp->rx_oom_timer); - vp->rx_oom_timer.data = (unsigned long)dev; - vp->rx_oom_timer.function = rx_oom_timer; - - if (vortex_debug > 1) - printk(KERN_DEBUG "%s: Initial media type %s.\n", - dev->name, media_tbl[dev->if_port].name); - - vp->full_duplex = vp->force_fd; - config = BFINS(config, dev->if_port, 20, 4); - if (vortex_debug > 6) - printk(KERN_DEBUG "vortex_up(): writing 0x%x to InternalConfig\n", config); - outl(config, ioaddr + Wn3_Config); - - if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) { - int mii_reg1, mii_reg5; - EL3WINDOW(4); - /* Read BMSR (reg1) only to clear old status. */ - mii_reg1 = mdio_read(dev, vp->phys[0], 1); - mii_reg5 = mdio_read(dev, vp->phys[0], 5); - if (mii_reg5 == 0xffff || mii_reg5 == 0x0000) - ; /* No MII device or no link partner report */ - else if ((mii_reg5 & 0x0100) != 0 /* 100baseTx-FD */ - || (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, but not 100-HD */ - vp->full_duplex = 1; - vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0); - if (vortex_debug > 1) - printk(KERN_INFO "%s: MII #%d status %4.4x, link partner capability %4.4x," - " info1 %04x, setting %s-duplex.\n", - dev->name, vp->phys[0], - mii_reg1, mii_reg5, - vp->info1, ((vp->info1 & 0x8000) || vp->full_duplex) ? "full" : "half"); - EL3WINDOW(3); - } - - /* Set the full-duplex bit. */ - outw( ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) | - (dev->mtu > 1500 ? 0x40 : 0) | - ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0), - ioaddr + Wn3_MAC_Ctrl); - - if (vortex_debug > 1) { - printk(KERN_DEBUG "%s: vortex_up() InternalConfig %8.8x.\n", - dev->name, config); - } - - issue_and_wait(dev, TxReset); - /* - * Don't reset the PHY - that upsets autonegotiation during DHCP operations. - */ - issue_and_wait(dev, RxReset|0x04); - - outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD); - - if (vortex_debug > 1) { - EL3WINDOW(4); - printk(KERN_DEBUG "%s: vortex_up() irq %d media status %4.4x.\n", - dev->name, dev->irq, inw(ioaddr + Wn4_Media)); - } - - /* Set the station address and mask in window 2 each time opened. */ - EL3WINDOW(2); - for (i = 0; i < 6; i++) - outb(dev->dev_addr[i], ioaddr + i); - for (; i < 12; i+=2) - outw(0, ioaddr + i); - - if (vp->cb_fn_base) { - unsigned short n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010; - if (vp->drv_flags & INVERT_LED_PWR) - n |= 0x10; - if (vp->drv_flags & INVERT_MII_PWR) - n |= 0x4000; - outw(n, ioaddr + Wn2_ResetOptions); - } - - if (dev->if_port == XCVR_10base2) - /* Start the thinnet transceiver. We should really wait 50ms...*/ - outw(StartCoax, ioaddr + EL3_CMD); - if (dev->if_port != XCVR_NWAY) { - EL3WINDOW(4); - outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) | - media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media); - } - - /* Switch to the stats window, and clear all stats by reading. */ - outw(StatsDisable, ioaddr + EL3_CMD); - EL3WINDOW(6); - for (i = 0; i < 10; i++) - inb(ioaddr + i); - inw(ioaddr + 10); - inw(ioaddr + 12); - /* New: On the Vortex we must also clear the BadSSD counter. */ - EL3WINDOW(4); - inb(ioaddr + 12); - /* ..and on the Boomerang we enable the extra statistics bits. */ - outw(0x0040, ioaddr + Wn4_NetDiag); - - /* Switch to register set 7 for normal use. */ - EL3WINDOW(7); - - if (vp->full_bus_master_rx) { /* Boomerang bus master. */ - vp->cur_rx = vp->dirty_rx = 0; - /* Initialize the RxEarly register as recommended. */ - outw(SetRxThreshold + (1536>>2), ioaddr + EL3_CMD); - outl(0x0020, ioaddr + PktStatus); - outl(vp->rx_ring_dma, ioaddr + UpListPtr); - } - if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */ - vp->cur_tx = vp->dirty_tx = 0; - if (vp->drv_flags & IS_BOOMERANG) - outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */ - /* Clear the Rx, Tx rings. */ - for (i = 0; i < RX_RING_SIZE; i++) /* AKPM: this is done in vortex_open, too */ - vp->rx_ring[i].status = 0; - for (i = 0; i < TX_RING_SIZE; i++) - vp->tx_skbuff[i] = 0; - outl(0, ioaddr + DownListPtr); - } - /* Set receiver mode: presumably accept b-case and phys addr only. */ - set_rx_mode(dev); - outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ - -// issue_and_wait(dev, SetTxStart|0x07ff); - outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ - outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ - /* Allow status bits to be seen. */ - vp->status_enable = SetStatusEnb | HostError|IntReq|StatsFull|TxComplete| - (vp->full_bus_master_tx ? DownComplete : TxAvailable) | - (vp->full_bus_master_rx ? UpComplete : RxComplete) | - (vp->bus_master ? DMADone : 0); - vp->intr_enable = SetIntrEnb | IntLatch | TxAvailable | - (vp->full_bus_master_rx ? 0 : RxComplete) | - StatsFull | HostError | TxComplete | IntReq - | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete; - outw(vp->status_enable, ioaddr + EL3_CMD); - /* Ack all pending events, and set active indicator mask. */ - outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, - ioaddr + EL3_CMD); - outw(vp->intr_enable, ioaddr + EL3_CMD); - if (vp->cb_fn_base) /* The PCMCIA people are idiots. */ - writel(0x8000, vp->cb_fn_base + 4); - netif_start_queue (dev); -} - -static int -vortex_open(struct net_device *dev) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - int i; - int retval; - - /* Use the now-standard shared IRQ implementation. */ - if ((retval = request_irq(dev->irq, vp->full_bus_master_rx ? - &boomerang_interrupt : &vortex_interrupt, SA_SHIRQ, dev->name, dev))) { - printk(KERN_ERR "%s: Could not reserve IRQ %d\n", dev->name, dev->irq); - goto out; - } - - if (vp->full_bus_master_rx) { /* Boomerang bus master. */ - if (vortex_debug > 2) - printk(KERN_DEBUG "%s: Filling in the Rx ring.\n", dev->name); - for (i = 0; i < RX_RING_SIZE; i++) { - struct sk_buff *skb; - vp->rx_ring[i].next = cpu_to_le32(vp->rx_ring_dma + sizeof(struct boom_rx_desc) * (i+1)); - vp->rx_ring[i].status = 0; /* Clear complete bit. */ - vp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LAST_FRAG); - skb = dev_alloc_skb(PKT_BUF_SZ); - vp->rx_skbuff[i] = skb; - if (skb == NULL) - break; /* Bad news! */ - skb->dev = dev; /* Mark as being used by this device. */ - skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - vp->rx_ring[i].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE)); - } - if (i != RX_RING_SIZE) { - int j; - printk(KERN_EMERG "%s: no memory for rx ring\n", dev->name); - for (j = 0; j < i; j++) { - if (vp->rx_skbuff[j]) { - dev_kfree_skb(vp->rx_skbuff[j]); - vp->rx_skbuff[j] = 0; - } - } - retval = -ENOMEM; - goto out_free_irq; - } - /* Wrap the ring. */ - vp->rx_ring[i-1].next = cpu_to_le32(vp->rx_ring_dma); - } - - vortex_up(dev); - return 0; - -out_free_irq: - free_irq(dev->irq, dev); -out: - if (vortex_debug > 1) - printk(KERN_ERR "%s: vortex_open() fails: returning %d\n", dev->name, retval); - return retval; -} - -static void -vortex_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct vortex_private *vp = (struct vortex_private *)dev->priv; - long ioaddr = dev->base_addr; - int next_tick = 60*HZ; - int ok = 0; - int media_status, mii_status, old_window; - - if (vortex_debug > 2) { - printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n", - dev->name, media_tbl[dev->if_port].name); - printk(KERN_DEBUG "dev->watchdog_timeo=%d\n", dev->watchdog_timeo); - } - - if (vp->medialock) - goto leave_media_alone; - disable_irq(dev->irq); - old_window = inw(ioaddr + EL3_CMD) >> 13; - EL3WINDOW(4); - media_status = inw(ioaddr + Wn4_Media); - switch (dev->if_port) { - case XCVR_10baseT: case XCVR_100baseTx: case XCVR_100baseFx: - if (media_status & Media_LnkBeat) { - ok = 1; - if (vortex_debug > 1) - printk(KERN_DEBUG "%s: Media %s has link beat, %x.\n", - dev->name, media_tbl[dev->if_port].name, media_status); - } else if (vortex_debug > 1) - printk(KERN_DEBUG "%s: Media %s has no link beat, %x.\n", - dev->name, media_tbl[dev->if_port].name, media_status); - break; - case XCVR_MII: case XCVR_NWAY: - { - mii_status = mdio_read(dev, vp->phys[0], 1); - ok = 1; - if (vortex_debug > 2) - printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n", - dev->name, mii_status); - if (mii_status & 0x0004) { - int mii_reg5 = mdio_read(dev, vp->phys[0], 5); - if (! vp->force_fd && mii_reg5 != 0xffff) { - int duplex = (mii_reg5&0x0100) || - (mii_reg5 & 0x01C0) == 0x0040; - if (vp->full_duplex != duplex) { - vp->full_duplex = duplex; - printk(KERN_INFO "%s: Setting %s-duplex based on MII " - "#%d link partner capability of %4.4x.\n", - dev->name, vp->full_duplex ? "full" : "half", - vp->phys[0], mii_reg5); - /* Set the full-duplex bit. */ - EL3WINDOW(3); - outw( (vp->full_duplex ? 0x20 : 0) | - (dev->mtu > 1500 ? 0x40 : 0) | - ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0), - ioaddr + Wn3_MAC_Ctrl); - if (vortex_debug > 1) - printk(KERN_DEBUG "Setting duplex in Wn3_MAC_Ctrl\n"); - /* AKPM: bug: should reset Tx and Rx after setting Duplex. Page 180 */ - } - } - } - } - break; - default: /* Other media types handled by Tx timeouts. */ - if (vortex_debug > 1) - printk(KERN_DEBUG "%s: Media %s has no indication, %x.\n", - dev->name, media_tbl[dev->if_port].name, media_status); - ok = 1; - } - if ( ! ok) { - unsigned int config; - - do { - dev->if_port = media_tbl[dev->if_port].next; - } while ( ! (vp->available_media & media_tbl[dev->if_port].mask)); - if (dev->if_port == XCVR_Default) { /* Go back to default. */ - dev->if_port = vp->default_media; - if (vortex_debug > 1) - printk(KERN_DEBUG "%s: Media selection failing, using default " - "%s port.\n", - dev->name, media_tbl[dev->if_port].name); - } else { - if (vortex_debug > 1) - printk(KERN_DEBUG "%s: Media selection failed, now trying " - "%s port.\n", - dev->name, media_tbl[dev->if_port].name); - next_tick = media_tbl[dev->if_port].wait; - } - outw((media_status & ~(Media_10TP|Media_SQE)) | - media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media); - - EL3WINDOW(3); - config = inl(ioaddr + Wn3_Config); - config = BFINS(config, dev->if_port, 20, 4); - outl(config, ioaddr + Wn3_Config); - - outw(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax, - ioaddr + EL3_CMD); - if (vortex_debug > 1) - printk(KERN_DEBUG "wrote 0x%08x to Wn3_Config\n", config); - /* AKPM: FIXME: Should reset Rx & Tx here. P60 of 3c90xc.pdf */ - } - EL3WINDOW(old_window); - enable_irq(dev->irq); - -leave_media_alone: - if (vortex_debug > 2) - printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n", - dev->name, media_tbl[dev->if_port].name); - - mod_timer(&vp->timer, RUN_AT(next_tick)); - if (vp->deferred) - outw(FakeIntr, ioaddr + EL3_CMD); - return; -} - -static void vortex_tx_timeout(struct net_device *dev) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - long ioaddr = dev->base_addr; - - printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n", - dev->name, inb(ioaddr + TxStatus), - inw(ioaddr + EL3_STATUS)); - EL3WINDOW(4); - printk(KERN_ERR " diagnostics: net %04x media %04x dma %8.8x.\n", - inw(ioaddr + Wn4_NetDiag), inw(ioaddr + Wn4_Media), - inl(ioaddr + PktStatus)); - /* Slight code bloat to be user friendly. */ - if ((inb(ioaddr + TxStatus) & 0x88) == 0x88) - printk(KERN_ERR "%s: Transmitter encountered 16 collisions --" - " network cable problem?\n", dev->name); - if (inw(ioaddr + EL3_STATUS) & IntLatch) { - printk(KERN_ERR "%s: Interrupt posted but not delivered --" - " IRQ blocked by another device?\n", dev->name); - /* Bad idea here.. but we might as well handle a few events. */ - { - /* - * Block interrupts because vortex_interrupt does a bare spin_lock() - */ - unsigned long flags; - local_irq_save(flags); - if (vp->full_bus_master_tx) - boomerang_interrupt(dev->irq, dev, 0); - else - vortex_interrupt(dev->irq, dev, 0); - local_irq_restore(flags); - } - } - - if (vortex_debug > 0) - dump_tx_ring(dev); - - issue_and_wait(dev, TxReset); - - vp->stats.tx_errors++; - if (vp->full_bus_master_tx) { - printk(KERN_DEBUG "%s: Resetting the Tx ring pointer.\n", dev->name); - if (vp->cur_tx - vp->dirty_tx > 0 && inl(ioaddr + DownListPtr) == 0) - outl(vp->tx_ring_dma + (vp->dirty_tx % TX_RING_SIZE) * sizeof(struct boom_tx_desc), - ioaddr + DownListPtr); - if (vp->cur_tx - vp->dirty_tx < TX_RING_SIZE) - netif_wake_queue (dev); - if (vp->drv_flags & IS_BOOMERANG) - outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); - outw(DownUnstall, ioaddr + EL3_CMD); - } else { - vp->stats.tx_dropped++; - netif_wake_queue(dev); - } - - /* Issue Tx Enable */ - outw(TxEnable, ioaddr + EL3_CMD); - dev->trans_start = jiffies; - - /* Switch to register set 7 for normal use. */ - EL3WINDOW(7); -} - -/* - * Handle uncommon interrupt sources. This is a separate routine to minimize - * the cache impact. - */ -static void -vortex_error(struct net_device *dev, int status) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - long ioaddr = dev->base_addr; - int do_tx_reset = 0, reset_mask = 0; - unsigned char tx_status = 0; - - if (vortex_debug > 2) { - printk(KERN_ERR "%s: vortex_error(), status=0x%x\n", dev->name, status); - } - - if (status & TxComplete) { /* Really "TxError" for us. */ - tx_status = inb(ioaddr + TxStatus); - /* Presumably a tx-timeout. We must merely re-enable. */ - if (vortex_debug > 2 - || (tx_status != 0x88 && vortex_debug > 0)) { - printk(KERN_ERR "%s: Transmit error, Tx status register %2.2x.\n", - dev->name, tx_status); - if (tx_status == 0x82) { - printk(KERN_ERR "Probably a duplex mismatch. See " - "Documentation/networking/vortex.txt\n"); - } - dump_tx_ring(dev); - } - if (tx_status & 0x14) vp->stats.tx_fifo_errors++; - if (tx_status & 0x38) vp->stats.tx_aborted_errors++; - outb(0, ioaddr + TxStatus); - if (tx_status & 0x30) { /* txJabber or txUnderrun */ - do_tx_reset = 1; - } else if ((tx_status & 0x08) && (vp->drv_flags & MAX_COLLISION_RESET)) { /* maxCollisions */ - do_tx_reset = 1; - reset_mask = 0x0108; /* Reset interface logic, but not download logic */ - } else { /* Merely re-enable the transmitter. */ - outw(TxEnable, ioaddr + EL3_CMD); - } - } - - if (status & RxEarly) { /* Rx early is unused. */ - vortex_rx(dev); - outw(AckIntr | RxEarly, ioaddr + EL3_CMD); - } - if (status & StatsFull) { /* Empty statistics. */ - static int DoneDidThat; - if (vortex_debug > 4) - printk(KERN_DEBUG "%s: Updating stats.\n", dev->name); - update_stats(ioaddr, dev); - /* HACK: Disable statistics as an interrupt source. */ - /* This occurs when we have the wrong media type! */ - if (DoneDidThat == 0 && - inw(ioaddr + EL3_STATUS) & StatsFull) { - printk(KERN_WARNING "%s: Updating statistics failed, disabling " - "stats as an interrupt source.\n", dev->name); - EL3WINDOW(5); - outw(SetIntrEnb | (inw(ioaddr + 10) & ~StatsFull), ioaddr + EL3_CMD); - vp->intr_enable &= ~StatsFull; - EL3WINDOW(7); - DoneDidThat++; - } - } - if (status & IntReq) { /* Restore all interrupt sources. */ - outw(vp->status_enable, ioaddr + EL3_CMD); - outw(vp->intr_enable, ioaddr + EL3_CMD); - } - if (status & HostError) { - u16 fifo_diag; - EL3WINDOW(4); - fifo_diag = inw(ioaddr + Wn4_FIFODiag); - printk(KERN_ERR "%s: Host error, FIFO diagnostic register %4.4x.\n", - dev->name, fifo_diag); - /* Adapter failure requires Tx/Rx reset and reinit. */ - if (vp->full_bus_master_tx) { - int bus_status = inl(ioaddr + PktStatus); - /* 0x80000000 PCI master abort. */ - /* 0x40000000 PCI target abort. */ - if (vortex_debug) - printk(KERN_ERR "%s: PCI bus error, bus status %8.8x\n", dev->name, bus_status); - - /* In this case, blow the card away */ - vortex_down(dev); - issue_and_wait(dev, TotalReset | 0xff); - vortex_up(dev); /* AKPM: bug. vortex_up() assumes that the rx ring is full. It may not be. */ - } else if (fifo_diag & 0x0400) - do_tx_reset = 1; - if (fifo_diag & 0x3000) { - /* Reset Rx fifo and upload logic */ - issue_and_wait(dev, RxReset|0x07); - /* Set the Rx filter to the current state. */ - set_rx_mode(dev); - outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */ - outw(AckIntr | HostError, ioaddr + EL3_CMD); - } - } - - if (do_tx_reset) { - issue_and_wait(dev, TxReset|reset_mask); - outw(TxEnable, ioaddr + EL3_CMD); - if (!vp->full_bus_master_tx) - netif_wake_queue(dev); - } -} - -static int -vortex_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - long ioaddr = dev->base_addr; - - /* Put out the doubleword header... */ - outl(skb->len, ioaddr + TX_FIFO); - if (vp->bus_master) { - /* Set the bus-master controller to transfer the packet. */ - int len = (skb->len + 3) & ~3; - outl( vp->tx_skb_dma = pci_map_single(vp->pdev, skb->data, len, PCI_DMA_TODEVICE), - ioaddr + Wn7_MasterAddr); - outw(len, ioaddr + Wn7_MasterLen); - vp->tx_skb = skb; - outw(StartDMADown, ioaddr + EL3_CMD); - /* netif_wake_queue() will be called at the DMADone interrupt. */ - } else { - /* ... and the packet rounded to a doubleword. */ - outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); - dev_kfree_skb (skb); - if (inw(ioaddr + TxFree) > 1536) { - netif_start_queue (dev); /* AKPM: redundant? */ - } else { - /* Interrupt us when the FIFO has room for max-sized packet. */ - netif_stop_queue(dev); - outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD); - } - } - - dev->trans_start = jiffies; - - /* Clear the Tx status stack. */ - { - int tx_status; - int i = 32; - - while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) { - if (tx_status & 0x3C) { /* A Tx-disabling error occurred. */ - if (vortex_debug > 2) - printk(KERN_DEBUG "%s: Tx error, status %2.2x.\n", - dev->name, tx_status); - if (tx_status & 0x04) vp->stats.tx_fifo_errors++; - if (tx_status & 0x38) vp->stats.tx_aborted_errors++; - if (tx_status & 0x30) { - issue_and_wait(dev, TxReset); - } - outw(TxEnable, ioaddr + EL3_CMD); - } - outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */ - } - } - return 0; -} - -static int -boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - long ioaddr = dev->base_addr; - /* Calculate the next Tx descriptor entry. */ - int entry = vp->cur_tx % TX_RING_SIZE; - struct boom_tx_desc *prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE]; - unsigned long flags; - - if (vortex_debug > 6) { - printk(KERN_DEBUG "boomerang_start_xmit()\n"); - if (vortex_debug > 3) - printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n", - dev->name, vp->cur_tx); - } - - if (vp->cur_tx - vp->dirty_tx >= TX_RING_SIZE) { - if (vortex_debug > 0) - printk(KERN_WARNING "%s: BUG! Tx Ring full, refusing to send buffer.\n", - dev->name); - netif_stop_queue(dev); - return 1; - } - - vp->tx_skbuff[entry] = skb; - - vp->tx_ring[entry].next = 0; -#if DO_ZEROCOPY - if (skb->ip_summed != CHECKSUM_HW) - vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded); - else - vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded | AddTCPChksum); - - if (!skb_shinfo(skb)->nr_frags) { - vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->data, - skb->len, PCI_DMA_TODEVICE)); - vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb->len | LAST_FRAG); - } else { - int i; - - vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->data, - skb->len-skb->data_len, PCI_DMA_TODEVICE)); - vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb->len-skb->data_len); - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - - vp->tx_ring[entry].frag[i+1].addr = - cpu_to_le32(pci_map_single(vp->pdev, - (void*)page_address(frag->page) + frag->page_offset, - frag->size, PCI_DMA_TODEVICE)); - - if (i == skb_shinfo(skb)->nr_frags-1) - vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(frag->size|LAST_FRAG); - else - vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(frag->size); - } - } -#else - vp->tx_ring[entry].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->data, skb->len, PCI_DMA_TODEVICE)); - vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG); - vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded); -#endif - - spin_lock_irqsave(&vp->lock, flags); - /* Wait for the stall to complete. */ - issue_and_wait(dev, DownStall); - prev_entry->next = cpu_to_le32(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc)); - if (inl(ioaddr + DownListPtr) == 0) { - outl(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc), ioaddr + DownListPtr); - vp->queued_packet++; - } - - vp->cur_tx++; - if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1) { - netif_stop_queue (dev); - } else { /* Clear previous interrupt enable. */ -#if defined(tx_interrupt_mitigation) - /* Dubious. If in boomeang_interrupt "faster" cyclone ifdef - * were selected, this would corrupt DN_COMPLETE. No? - */ - prev_entry->status &= cpu_to_le32(~TxIntrUploaded); -#endif - } - outw(DownUnstall, ioaddr + EL3_CMD); - spin_unlock_irqrestore(&vp->lock, flags); - dev->trans_start = jiffies; - return 0; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ - -/* - * This is the ISR for the vortex series chips. - * full_bus_master_tx == 0 && full_bus_master_rx == 0 - */ - -static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = dev_id; - struct vortex_private *vp = (struct vortex_private *)dev->priv; - long ioaddr; - int status; - int work_done = max_interrupt_work; - - ioaddr = dev->base_addr; - spin_lock(&vp->lock); - - status = inw(ioaddr + EL3_STATUS); - - if (vortex_debug > 6) - printk("vortex_interrupt(). status=0x%4x\n", status); - - if ((status & IntLatch) == 0) - goto handler_exit; /* No interrupt: shared IRQs cause this */ - - if (status & IntReq) { - status |= vp->deferred; - vp->deferred = 0; - } - - if (status == 0xffff) /* h/w no longer present (hotplug)? */ - goto handler_exit; - - if (vortex_debug > 4) - printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n", - dev->name, status, inb(ioaddr + Timer)); - - do { - if (vortex_debug > 5) - printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n", - dev->name, status); - if (status & RxComplete) - vortex_rx(dev); - - if (status & TxAvailable) { - if (vortex_debug > 5) - printk(KERN_DEBUG " TX room bit was handled.\n"); - /* There's room in the FIFO for a full-sized packet. */ - outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); - netif_wake_queue (dev); - } - - if (status & DMADone) { - if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) { - outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */ - pci_unmap_single(vp->pdev, vp->tx_skb_dma, (vp->tx_skb->len + 3) & ~3, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(vp->tx_skb); /* Release the transferred buffer */ - if (inw(ioaddr + TxFree) > 1536) { - /* - * AKPM: FIXME: I don't think we need this. If the queue was stopped due to - * insufficient FIFO room, the TxAvailable test will succeed and call - * netif_wake_queue() - */ - netif_wake_queue(dev); - } else { /* Interrupt when FIFO has room for max-sized packet. */ - outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD); - netif_stop_queue(dev); - } - } - } - /* Check for all uncommon interrupts at once. */ - if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) { - if (status == 0xffff) - break; - vortex_error(dev, status); - } - - if (--work_done < 0) { - printk(KERN_WARNING "%s: Too much work in interrupt, status " - "%4.4x.\n", dev->name, status); - /* Disable all pending interrupts. */ - do { - vp->deferred |= status; - outw(SetStatusEnb | (~vp->deferred & vp->status_enable), - ioaddr + EL3_CMD); - outw(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD); - } while ((status = inw(ioaddr + EL3_CMD)) & IntLatch); - /* The timer will reenable interrupts. */ - mod_timer(&vp->timer, jiffies + 1*HZ); - break; - } - /* Acknowledge the IRQ. */ - outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); - } while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete)); - - if (vortex_debug > 4) - printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n", - dev->name, status); -handler_exit: - spin_unlock(&vp->lock); -} - -/* - * This is the ISR for the boomerang series chips. - * full_bus_master_tx == 1 && full_bus_master_rx == 1 - */ - -static void boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = dev_id; - struct vortex_private *vp = (struct vortex_private *)dev->priv; - long ioaddr; - int status; - int work_done = max_interrupt_work; - - ioaddr = dev->base_addr; - - /* - * It seems dopey to put the spinlock this early, but we could race against vortex_tx_timeout - * and boomerang_start_xmit - */ - spin_lock(&vp->lock); - - status = inw(ioaddr + EL3_STATUS); - - if (vortex_debug > 6) - printk(KERN_DEBUG "boomerang_interrupt. status=0x%4x\n", status); - - if ((status & IntLatch) == 0) - goto handler_exit; /* No interrupt: shared IRQs can cause this */ - - if (status == 0xffff) { /* h/w no longer present (hotplug)? */ - if (vortex_debug > 1) - printk(KERN_DEBUG "boomerang_interrupt(1): status = 0xffff\n"); - goto handler_exit; - } - - if (status & IntReq) { - status |= vp->deferred; - vp->deferred = 0; - } - - if (vortex_debug > 4) - printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n", - dev->name, status, inb(ioaddr + Timer)); - do { - if (vortex_debug > 5) - printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n", - dev->name, status); - if (status & UpComplete) { - outw(AckIntr | UpComplete, ioaddr + EL3_CMD); - if (vortex_debug > 5) - printk(KERN_DEBUG "boomerang_interrupt->boomerang_rx\n"); - boomerang_rx(dev); - } - - if (status & DownComplete) { - unsigned int dirty_tx = vp->dirty_tx; - - outw(AckIntr | DownComplete, ioaddr + EL3_CMD); - while (vp->cur_tx - dirty_tx > 0) { - int entry = dirty_tx % TX_RING_SIZE; -#if 1 /* AKPM: the latter is faster, but cyclone-only */ - if (inl(ioaddr + DownListPtr) == - vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc)) - break; /* It still hasn't been processed. */ -#else - if ((vp->tx_ring[entry].status & DN_COMPLETE) == 0) - break; /* It still hasn't been processed. */ -#endif - - if (vp->tx_skbuff[entry]) { - struct sk_buff *skb = vp->tx_skbuff[entry]; -#if DO_ZEROCOPY - int i; - for (i=0; i<=skb_shinfo(skb)->nr_frags; i++) - pci_unmap_single(vp->pdev, - le32_to_cpu(vp->tx_ring[entry].frag[i].addr), - le32_to_cpu(vp->tx_ring[entry].frag[i].length)&0xFFF, - PCI_DMA_TODEVICE); -#else - pci_unmap_single(vp->pdev, - le32_to_cpu(vp->tx_ring[entry].addr), skb->len, PCI_DMA_TODEVICE); -#endif - dev_kfree_skb_irq(skb); - vp->tx_skbuff[entry] = 0; - } else { - printk(KERN_DEBUG "boomerang_interrupt: no skb!\n"); - } - /* vp->stats.tx_packets++; Counted below. */ - dirty_tx++; - } - vp->dirty_tx = dirty_tx; - if (vp->cur_tx - dirty_tx <= TX_RING_SIZE - 1) { - if (vortex_debug > 6) - printk(KERN_DEBUG "boomerang_interrupt: wake queue\n"); - netif_wake_queue (dev); - } - } - - /* Check for all uncommon interrupts at once. */ - if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) - vortex_error(dev, status); - - if (--work_done < 0) { - printk(KERN_WARNING "%s: Too much work in interrupt, status " - "%4.4x.\n", dev->name, status); - /* Disable all pending interrupts. */ - do { - vp->deferred |= status; - outw(SetStatusEnb | (~vp->deferred & vp->status_enable), - ioaddr + EL3_CMD); - outw(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD); - } while ((status = inw(ioaddr + EL3_CMD)) & IntLatch); - /* The timer will reenable interrupts. */ - mod_timer(&vp->timer, jiffies + 1*HZ); - break; - } - /* Acknowledge the IRQ. */ - outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); - if (vp->cb_fn_base) /* The PCMCIA people are idiots. */ - writel(0x8000, vp->cb_fn_base + 4); - - } while ((status = inw(ioaddr + EL3_STATUS)) & IntLatch); - - if (vortex_debug > 4) - printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n", - dev->name, status); -handler_exit: - spin_unlock(&vp->lock); -} - -static int vortex_rx(struct net_device *dev) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - long ioaddr = dev->base_addr; - int i; - short rx_status; - - if (vortex_debug > 5) - printk(KERN_DEBUG "vortex_rx(): status %4.4x, rx_status %4.4x.\n", - inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus)); - while ((rx_status = inw(ioaddr + RxStatus)) > 0) { - if (rx_status & 0x4000) { /* Error, update stats. */ - unsigned char rx_error = inb(ioaddr + RxErrors); - if (vortex_debug > 2) - printk(KERN_DEBUG " Rx error: status %2.2x.\n", rx_error); - vp->stats.rx_errors++; - if (rx_error & 0x01) vp->stats.rx_over_errors++; - if (rx_error & 0x02) vp->stats.rx_length_errors++; - if (rx_error & 0x04) vp->stats.rx_frame_errors++; - if (rx_error & 0x08) vp->stats.rx_crc_errors++; - if (rx_error & 0x10) vp->stats.rx_length_errors++; - } else { - /* The packet length: up to 4.5K!. */ - int pkt_len = rx_status & 0x1fff; - struct sk_buff *skb; - - skb = dev_alloc_skb(pkt_len + 5); - if (vortex_debug > 4) - printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n", - pkt_len, rx_status); - if (skb != NULL) { - skb->dev = dev; - skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - /* 'skb_put()' points to the start of sk_buff data area. */ - if (vp->bus_master && - ! (inw(ioaddr + Wn7_MasterStatus) & 0x8000)) { - dma_addr_t dma = pci_map_single(vp->pdev, skb_put(skb, pkt_len), - pkt_len, PCI_DMA_FROMDEVICE); - outl(dma, ioaddr + Wn7_MasterAddr); - outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen); - outw(StartDMAUp, ioaddr + EL3_CMD); - while (inw(ioaddr + Wn7_MasterStatus) & 0x8000) - ; - pci_unmap_single(vp->pdev, dma, pkt_len, PCI_DMA_FROMDEVICE); - } else { - char *vdata = map_domain_mem(__pa(skb_put(skb, pkt_len))); - insl(ioaddr + RX_FIFO, vdata, - (pkt_len + 3) >> 2); - unmap_domain_mem(vdata); - } - outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */ - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); - dev->last_rx = jiffies; - vp->stats.rx_packets++; - /* Wait a limited time to go to next packet. */ - for (i = 200; i >= 0; i--) - if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) - break; - continue; - } else if (vortex_debug > 0) - printk(KERN_NOTICE "%s: No memory to allocate a sk_buff of " - "size %d.\n", dev->name, pkt_len); - } - vp->stats.rx_dropped++; - issue_and_wait(dev, RxDiscard); - } - - return 0; -} - -static int -boomerang_rx(struct net_device *dev) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - int entry = vp->cur_rx % RX_RING_SIZE; - long ioaddr = dev->base_addr; - int rx_status; - int rx_work_limit = vp->dirty_rx + RX_RING_SIZE - vp->cur_rx; - - if (vortex_debug > 5) - printk(KERN_DEBUG "boomerang_rx(): status %4.4x\n", inw(ioaddr+EL3_STATUS)); - - while ((rx_status = le32_to_cpu(vp->rx_ring[entry].status)) & RxDComplete){ - if (--rx_work_limit < 0) - break; - if (rx_status & RxDError) { /* Error, update stats. */ - unsigned char rx_error = rx_status >> 16; - if (vortex_debug > 2) - printk(KERN_DEBUG " Rx error: status %2.2x.\n", rx_error); - vp->stats.rx_errors++; - if (rx_error & 0x01) vp->stats.rx_over_errors++; - if (rx_error & 0x02) vp->stats.rx_length_errors++; - if (rx_error & 0x04) vp->stats.rx_frame_errors++; - if (rx_error & 0x08) vp->stats.rx_crc_errors++; - if (rx_error & 0x10) vp->stats.rx_length_errors++; - } else { - /* The packet length: up to 4.5K!. */ - int pkt_len = rx_status & 0x1fff; - struct sk_buff *skb; - dma_addr_t dma = le32_to_cpu(vp->rx_ring[entry].addr); - - if (vortex_debug > 4) - printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n", - pkt_len, rx_status); - - /* Check if the packet is long enough to just accept without - copying to a properly sized skbuff. */ - if (pkt_len < rx_copybreak && (skb = dev_alloc_skb(pkt_len + 2)) != 0) { - skb->dev = dev; - skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - pci_dma_sync_single(vp->pdev, dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); - /* 'skb_put()' points to the start of sk_buff data area. */ - memcpy(skb_put(skb, pkt_len), - vp->rx_skbuff[entry]->tail, - pkt_len); - vp->rx_copy++; - } else { - /* Pass up the skbuff already on the Rx ring. */ - skb = vp->rx_skbuff[entry]; - vp->rx_skbuff[entry] = NULL; - skb_put(skb, pkt_len); - pci_unmap_single(vp->pdev, dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); - vp->rx_nocopy++; - } - skb->protocol = eth_type_trans(skb, dev); - { /* Use hardware checksum info. */ - int csum_bits = rx_status & 0xee000000; - if (csum_bits && - (csum_bits == (IPChksumValid | TCPChksumValid) || - csum_bits == (IPChksumValid | UDPChksumValid))) { - skb->ip_summed = CHECKSUM_UNNECESSARY; - vp->rx_csumhits++; - } - } - netif_rx(skb); - dev->last_rx = jiffies; - vp->stats.rx_packets++; - } - entry = (++vp->cur_rx) % RX_RING_SIZE; - } - /* Refill the Rx ring buffers. */ - for (; vp->cur_rx - vp->dirty_rx > 0; vp->dirty_rx++) { - struct sk_buff *skb; - entry = vp->dirty_rx % RX_RING_SIZE; - if (vp->rx_skbuff[entry] == NULL) { - skb = dev_alloc_skb(PKT_BUF_SZ); - if (skb == NULL) { - static unsigned long last_jif; - if ((jiffies - last_jif) > 10 * HZ) { - printk(KERN_WARNING "%s: memory shortage\n", dev->name); - last_jif = jiffies; - } - if ((vp->cur_rx - vp->dirty_rx) == RX_RING_SIZE) - mod_timer(&vp->rx_oom_timer, RUN_AT(HZ * 1)); - break; /* Bad news! */ - } - skb->dev = dev; /* Mark as being used by this device. */ - skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - vp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE)); - vp->rx_skbuff[entry] = skb; - } - vp->rx_ring[entry].status = 0; /* Clear complete bit. */ - outw(UpUnstall, ioaddr + EL3_CMD); - } - return 0; -} - -/* - * If we've hit a total OOM refilling the Rx ring we poll once a second - * for some memory. Otherwise there is no way to restart the rx process. - */ -static void -rx_oom_timer(unsigned long arg) -{ - struct net_device *dev = (struct net_device *)arg; - struct vortex_private *vp = (struct vortex_private *)dev->priv; - - spin_lock_irq(&vp->lock); - if ((vp->cur_rx - vp->dirty_rx) == RX_RING_SIZE) /* This test is redundant, but makes me feel good */ - boomerang_rx(dev); - if (vortex_debug > 1) { - printk(KERN_DEBUG "%s: rx_oom_timer %s\n", dev->name, - ((vp->cur_rx - vp->dirty_rx) != RX_RING_SIZE) ? "succeeded" : "retrying"); - } - spin_unlock_irq(&vp->lock); -} - -static void -vortex_down(struct net_device *dev) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - long ioaddr = dev->base_addr; - - netif_stop_queue (dev); - - del_timer_sync(&vp->rx_oom_timer); - del_timer_sync(&vp->timer); - - /* Turn off statistics ASAP. We update vp->stats below. */ - outw(StatsDisable, ioaddr + EL3_CMD); - - /* Disable the receiver and transmitter. */ - outw(RxDisable, ioaddr + EL3_CMD); - outw(TxDisable, ioaddr + EL3_CMD); - - if (dev->if_port == XCVR_10base2) - /* Turn off thinnet power. Green! */ - outw(StopCoax, ioaddr + EL3_CMD); - - outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD); - - update_stats(ioaddr, dev); - if (vp->full_bus_master_rx) - outl(0, ioaddr + UpListPtr); - if (vp->full_bus_master_tx) - outl(0, ioaddr + DownListPtr); - - if (vp->pdev && vp->enable_wol) { - pci_save_state(vp->pdev, vp->power_state); - acpi_set_WOL(dev); - } -} - -static int -vortex_close(struct net_device *dev) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - long ioaddr = dev->base_addr; - int i; - - if (netif_device_present(dev)) - vortex_down(dev); - - if (vortex_debug > 1) { - printk(KERN_DEBUG"%s: vortex_close() status %4.4x, Tx status %2.2x.\n", - dev->name, inw(ioaddr + EL3_STATUS), inb(ioaddr + TxStatus)); - printk(KERN_DEBUG "%s: vortex close stats: rx_nocopy %d rx_copy %d" - " tx_queued %d Rx pre-checksummed %d.\n", - dev->name, vp->rx_nocopy, vp->rx_copy, vp->queued_packet, vp->rx_csumhits); - } - -#if DO_ZEROCOPY - if ( vp->rx_csumhits && - ((vp->drv_flags & HAS_HWCKSM) == 0) && - (hw_checksums[vp->card_idx] == -1)) { - printk(KERN_WARNING "%s supports hardware checksums, and we're not using them!\n", dev->name); - printk(KERN_WARNING "Please see http://www.uow.edu.au/~andrewm/zerocopy.html\n"); - } -#endif - - free_irq(dev->irq, dev); - - if (vp->full_bus_master_rx) { /* Free Boomerang bus master Rx buffers. */ - for (i = 0; i < RX_RING_SIZE; i++) - if (vp->rx_skbuff[i]) { - pci_unmap_single( vp->pdev, le32_to_cpu(vp->rx_ring[i].addr), - PKT_BUF_SZ, PCI_DMA_FROMDEVICE); - dev_kfree_skb(vp->rx_skbuff[i]); - vp->rx_skbuff[i] = 0; - } - } - if (vp->full_bus_master_tx) { /* Free Boomerang bus master Tx buffers. */ - for (i = 0; i < TX_RING_SIZE; i++) { - if (vp->tx_skbuff[i]) { - struct sk_buff *skb = vp->tx_skbuff[i]; -#if DO_ZEROCOPY - int k; - - for (k=0; k<=skb_shinfo(skb)->nr_frags; k++) - pci_unmap_single(vp->pdev, - le32_to_cpu(vp->tx_ring[i].frag[k].addr), - le32_to_cpu(vp->tx_ring[i].frag[k].length)&0xFFF, - PCI_DMA_TODEVICE); -#else - pci_unmap_single(vp->pdev, le32_to_cpu(vp->tx_ring[i].addr), skb->len, PCI_DMA_TODEVICE); -#endif - dev_kfree_skb(skb); - vp->tx_skbuff[i] = 0; - } - } - } - - return 0; -} - -static void -dump_tx_ring(struct net_device *dev) -{ - if (vortex_debug > 0) { - struct vortex_private *vp = (struct vortex_private *)dev->priv; - long ioaddr = dev->base_addr; - - if (vp->full_bus_master_tx) { - int i; - int stalled = inl(ioaddr + PktStatus) & 0x04; /* Possible racy. But it's only debug stuff */ - - printk(KERN_ERR " Flags; bus-master %d, dirty %d(%d) current %d(%d)\n", - vp->full_bus_master_tx, - vp->dirty_tx, vp->dirty_tx % TX_RING_SIZE, - vp->cur_tx, vp->cur_tx % TX_RING_SIZE); - printk(KERN_ERR " Transmit list %8.8x vs. %p.\n", - inl(ioaddr + DownListPtr), - &vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]); - issue_and_wait(dev, DownStall); - for (i = 0; i < TX_RING_SIZE; i++) { - printk(KERN_ERR " %d: @%p length %8.8x status %8.8x\n", i, - &vp->tx_ring[i], -#if DO_ZEROCOPY - le32_to_cpu(vp->tx_ring[i].frag[0].length), -#else - le32_to_cpu(vp->tx_ring[i].length), -#endif - le32_to_cpu(vp->tx_ring[i].status)); - } - if (!stalled) - outw(DownUnstall, ioaddr + EL3_CMD); - } - } -} - -static struct net_device_stats *vortex_get_stats(struct net_device *dev) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - unsigned long flags; - - if (netif_device_present(dev)) { /* AKPM: Used to be netif_running */ - spin_lock_irqsave (&vp->lock, flags); - update_stats(dev->base_addr, dev); - spin_unlock_irqrestore (&vp->lock, flags); - } - return &vp->stats; -} - -/* Update statistics. - Unlike with the EL3 we need not worry about interrupts changing - the window setting from underneath us, but we must still guard - against a race condition with a StatsUpdate interrupt updating the - table. This is done by checking that the ASM (!) code generated uses - atomic updates with '+='. - */ -static void update_stats(long ioaddr, struct net_device *dev) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - int old_window = inw(ioaddr + EL3_CMD); - - if (old_window == 0xffff) /* Chip suspended or ejected. */ - return; - /* Unlike the 3c5x9 we need not turn off stats updates while reading. */ - /* Switch to the stats window, and read everything. */ - EL3WINDOW(6); - vp->stats.tx_carrier_errors += inb(ioaddr + 0); - vp->stats.tx_heartbeat_errors += inb(ioaddr + 1); - /* Multiple collisions. */ inb(ioaddr + 2); - vp->stats.collisions += inb(ioaddr + 3); - vp->stats.tx_window_errors += inb(ioaddr + 4); - vp->stats.rx_fifo_errors += inb(ioaddr + 5); - vp->stats.tx_packets += inb(ioaddr + 6); - vp->stats.tx_packets += (inb(ioaddr + 9)&0x30) << 4; - /* Rx packets */ inb(ioaddr + 7); /* Must read to clear */ - /* Tx deferrals */ inb(ioaddr + 8); - /* Don't bother with register 9, an extension of registers 6&7. - If we do use the 6&7 values the atomic update assumption above - is invalid. */ - vp->stats.rx_bytes += inw(ioaddr + 10); - vp->stats.tx_bytes += inw(ioaddr + 12); - /* New: On the Vortex we must also clear the BadSSD counter. */ - EL3WINDOW(4); - inb(ioaddr + 12); - - { - u8 up = inb(ioaddr + 13); - vp->stats.rx_bytes += (up & 0x0f) << 16; - vp->stats.tx_bytes += (up & 0xf0) << 12; - } - - EL3WINDOW(old_window >> 13); - return; -} - - -static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr) -{ - struct vortex_private *vp = dev->priv; - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - if (vp->pdev) - strcpy(info.bus_info, vp->pdev->slot_name); - else - sprintf(info.bus_info, "EISA 0x%lx %d", - dev->base_addr, dev->irq); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - - } - - return -EOPNOTSUPP; -} - -static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - long ioaddr = dev->base_addr; - struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data; - int phy = vp->phys[0] & 0x1f; - int retval; - - switch(cmd) { - case SIOCETHTOOL: - return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); - - case SIOCGMIIPHY: /* Get address of MII PHY in use. */ - case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ - data->phy_id = phy; - - case SIOCGMIIREG: /* Read MII PHY register. */ - case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ - EL3WINDOW(4); - data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f); - retval = 0; - break; - - case SIOCSMIIREG: /* Write MII PHY register. */ - case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ - if (!capable(CAP_NET_ADMIN)) { - retval = -EPERM; - } else { - EL3WINDOW(4); - mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in); - retval = 0; - } - break; - default: - retval = -EOPNOTSUPP; - break; - } - - return retval; -} - -/* Pre-Cyclone chips have no documented multicast filter, so the only - multicast setting is to receive all multicast frames. At least - the chip has a very clean way to set the mode, unlike many others. */ -static void set_rx_mode(struct net_device *dev) -{ - long ioaddr = dev->base_addr; - int new_mode; - - if (dev->flags & IFF_PROMISC) { - if (vortex_debug > 0) - printk(KERN_NOTICE "%s: Setting promiscuous mode.\n", dev->name); - new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast|RxProm; - } else if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) { - new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast; - } else - new_mode = SetRxFilter | RxStation | RxBroadcast; - - outw(new_mode, ioaddr + EL3_CMD); -} - -/* MII transceiver control section. - Read and write the MII registers using software-generated serial - MDIO protocol. See the MII specifications or DP83840A data sheet - for details. */ - -/* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define mdio_delay() inl(mdio_addr) - -#define MDIO_SHIFT_CLK 0x01 -#define MDIO_DIR_WRITE 0x04 -#define MDIO_DATA_WRITE0 (0x00 | MDIO_DIR_WRITE) -#define MDIO_DATA_WRITE1 (0x02 | MDIO_DIR_WRITE) -#define MDIO_DATA_READ 0x02 -#define MDIO_ENB_IN 0x00 - -/* Generate the preamble required for initial synchronization and - a few older transceivers. */ -static void mdio_sync(long ioaddr, int bits) -{ - long mdio_addr = ioaddr + Wn4_PhysicalMgmt; - - /* Establish sync by sending at least 32 logic ones. */ - while (-- bits >= 0) { - outw(MDIO_DATA_WRITE1, mdio_addr); - mdio_delay(); - outw(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); - mdio_delay(); - } -} - -static int mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - int i; - long ioaddr = dev->base_addr; - int read_cmd = (0xf6 << 10) | (phy_id << 5) | location; - unsigned int retval = 0; - long mdio_addr = ioaddr + Wn4_PhysicalMgmt; - - spin_lock_bh(&vp->mdio_lock); - - if (mii_preamble_required) - mdio_sync(ioaddr, 32); - - /* Shift the read command bits out. */ - for (i = 14; i >= 0; i--) { - int dataval = (read_cmd&(1< 0; i--) { - outw(MDIO_ENB_IN, mdio_addr); - mdio_delay(); - retval = (retval << 1) | ((inw(mdio_addr) & MDIO_DATA_READ) ? 1 : 0); - outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); - mdio_delay(); - } - spin_unlock_bh(&vp->mdio_lock); - return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff; -} - -static void mdio_write(struct net_device *dev, int phy_id, int location, int value) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - long ioaddr = dev->base_addr; - int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value; - long mdio_addr = ioaddr + Wn4_PhysicalMgmt; - int i; - - spin_lock_bh(&vp->mdio_lock); - - if (mii_preamble_required) - mdio_sync(ioaddr, 32); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = (write_cmd&(1<= 0; i--) { - outw(MDIO_ENB_IN, mdio_addr); - mdio_delay(); - outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); - mdio_delay(); - } - spin_unlock_bh(&vp->mdio_lock); - return; -} - -/* ACPI: Advanced Configuration and Power Interface. */ -/* Set Wake-On-LAN mode and put the board into D3 (power-down) state. */ -static void acpi_set_WOL(struct net_device *dev) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - long ioaddr = dev->base_addr; - - /* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */ - EL3WINDOW(7); - outw(2, ioaddr + 0x0c); - /* The RxFilter must accept the WOL frames. */ - outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD); - outw(RxEnable, ioaddr + EL3_CMD); - - /* Change the power state to D3; RxEnable doesn't take effect. */ - pci_enable_wake(vp->pdev, 0, 1); - pci_set_power_state(vp->pdev, 3); -} - - -static void __devexit vortex_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct vortex_private *vp; - - if (!dev) { - printk("vortex_remove_one called for EISA device!\n"); - BUG(); - } - - vp = dev->priv; - - /* AKPM: FIXME: we should have - * if (vp->cb_fn_base) iounmap(vp->cb_fn_base); - * here - */ - unregister_netdev(dev); - /* Should really use issue_and_wait() here */ - outw(TotalReset|0x14, dev->base_addr + EL3_CMD); - - if (vp->pdev && vp->enable_wol) { - pci_set_power_state(vp->pdev, 0); /* Go active */ - if (vp->pm_state_valid) - pci_restore_state(vp->pdev, vp->power_state); - } - - pci_free_consistent(pdev, - sizeof(struct boom_rx_desc) * RX_RING_SIZE - + sizeof(struct boom_tx_desc) * TX_RING_SIZE, - vp->rx_ring, - vp->rx_ring_dma); - if (vp->must_free_region) - release_region(dev->base_addr, vp->io_size); - kfree(dev); -} - - -static struct pci_driver vortex_driver = { - name: "3c59x", - probe: vortex_init_one, - remove: __devexit_p(vortex_remove_one), - id_table: vortex_pci_tbl, -#ifdef CONFIG_PM - suspend: vortex_suspend, - resume: vortex_resume, -#endif -}; - - -static int vortex_have_pci; -static int vortex_have_eisa; - - -static int __init vortex_init (void) -{ - int pci_rc, eisa_rc; - - pci_rc = pci_module_init(&vortex_driver); - eisa_rc = vortex_eisa_init(); - - if (pci_rc == 0) - vortex_have_pci = 1; - if (eisa_rc > 0) - vortex_have_eisa = 1; - - return (vortex_have_pci + vortex_have_eisa) ? 0 : -ENODEV; -} - - -static void __exit vortex_eisa_cleanup (void) -{ - struct net_device *dev, *tmp; - struct vortex_private *vp; - long ioaddr; - - dev = root_vortex_eisa_dev; - - while (dev) { - vp = dev->priv; - ioaddr = dev->base_addr; - - unregister_netdev (dev); - outw (TotalReset, ioaddr + EL3_CMD); - release_region (ioaddr, VORTEX_TOTAL_SIZE); - - tmp = dev; - dev = vp->next_module; - - kfree (tmp); - } -} - - -static void __exit vortex_cleanup (void) -{ - if (vortex_have_pci) - pci_unregister_driver (&vortex_driver); - if (vortex_have_eisa) - vortex_eisa_cleanup (); -} - - -module_init(vortex_init); -module_exit(vortex_cleanup); diff --git a/xen/drivers/net/8139too.c b/xen/drivers/net/8139too.c deleted file mode 100644 index f3a5f421ca..0000000000 --- a/xen/drivers/net/8139too.c +++ /dev/null @@ -1,2715 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - - See 8139too.txt for more details. - -*/ -#define XEN - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.26" - - -#include -#include - -#ifdef XEN -typedef int pid_t; -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#ifndef XEN -#include -#endif -#include -#include -#include -#ifndef XEN -#include -#endif -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#if defined(CONFIG_8139TOO_PIO) || defined(XEN) /* XXX MMIO fails on Xen :-( */ -#define USE_IO_OPS 1 -#endif - -/* define to 1 to enable copious debugging info */ -#undef RTL8139_DEBUG - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - -#undef DPRINTK - -#ifdef RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static int max_interrupt_work = 20; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -#ifndef XEN -/* bitmapped message enable number */ -static int debug = -1; -#endif - -/* Size of the in-memory receive ring. */ -#define RX_BUF_LEN_IDX 2 /* 0==8K, 1==16K, 2==32K, 3==64K */ -#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8139_CB, - SMC1211TX, - /*MPX5030,*/ - DELTA8139, - ADDTRON8139, - DFE538TX, - DFE690TXD, - FE2000VX, - ALLIED8139, - RTL8129, - FNW3603TX, - FNW3800TX, -} board_t; - - -/* indexed by board_t, above */ -static struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139 Fast Ethernet", RTL8139_CAPS }, - { "RealTek RTL8139B PCI/CardBus", RTL8139_CAPS }, - { "SMC1211TX EZCard 10/100 (RealTek RTL8139)", RTL8139_CAPS }, -/* { MPX5030, "Accton MPX5030 (RealTek RTL8139)", RTL8139_CAPS },*/ - { "Delta Electronics 8139 10/100BaseTX", RTL8139_CAPS }, - { "Addtron Technolgy 8139 10/100BaseTX", RTL8139_CAPS }, - { "D-Link DFE-538TX (RealTek RTL8139)", RTL8139_CAPS }, - { "D-Link DFE-690TXD (RealTek RTL8139)", RTL8139_CAPS }, - { "AboCom FE2000VX (RealTek RTL8139)", RTL8139_CAPS }, - { "Allied Telesyn 8139 CardBus", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, - { "Planex FNW-3603-TX 10/100 CardBus", RTL8139_CAPS }, - { "Planex FNW-3800-TX 10/100 CardBus", RTL8139_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] __devinitdata = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139_CB }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMC1211TX }, -/* {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MPX5030 },*/ - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DELTA8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ADDTRON8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DFE538TX }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DFE690TXD }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FE2000VX }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ALLIED8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FNW3603TX }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FNW3800TX }, - -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, DFE538TX }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, FE2000VX }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -#ifndef XEN -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; -#endif - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - ChipVersion = 0x43, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - TxIFG1 = (1 << 25), /* Interframe Gap Time */ - TxIFG0 = (1 << 24), /* Enabling these bits violates IEEE 802.3 */ - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer */ - RxNoWrap = (1 << 7), -}; - - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -#ifdef CONFIG_8139TOO_TUNE_TWISTER - -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139B, - CH_8130, - CH_8139C, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - - -/* directly indexed by chip_t, above */ -const static struct { - const char *name; - u8 version; /* from RTL8139C docs */ - u32 RxConfigMask; /* should clear the bits supported by this chip */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - 0x40, - 0xf0fe0040, /* XXX copied from RTL8139A, verify */ - HasHltClk, - }, - - { "RTL-8139 rev K", - 0x60, - 0xf0fe0040, - HasHltClk, - }, - - { "RTL-8139A", - 0x70, - 0xf0fe0040, - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - 0x78, - 0xf0fc0040, - HasLWake, - }, - - { "RTL-8130", - 0x7C, - 0xf0fe0040, /* XXX copied from RTL8139A, verify */ - HasLWake, - }, - - { "RTL-8139C", - 0x74, - 0xf0fc0040, /* XXX copied from RTL8139B, verify */ - HasLWake, - }, - -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - struct net_device_stats stats; - unsigned char *rx_ring; - unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t rx_ring_dma; - dma_addr_t tx_bufs_dma; - signed char phys[4]; /* MII device addresses. */ - char twistie, twist_row, twist_col; /* Twister tune state. */ - unsigned int default_port:4; /* Last dev->if_port value. */ - spinlock_t lock; - chip_t chipset; - pid_t thr_pid; -#ifndef XEN - wait_queue_head_t thr_wait; - struct completion thr_exited; -#endif - u32 rx_config; - struct rtl_extra_stats xstats; - int time_to_die; - struct mii_if_info mii; - unsigned int regs_len; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); - -MODULE_PARM (multicast_filter_limit, "i"); -MODULE_PARM (max_interrupt_work, "i"); -MODULE_PARM (media, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM (full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM (debug, "i"); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (max_interrupt_work, "8139too maximum events handled per interrupt"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -#ifndef XEN -static int rtl8139_thread (void *data); -#endif -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -static void rtl8139_interrupt (int irq, void *dev_instance, - struct pt_regs *regs); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); - -#ifdef USE_IO_OPS - -#define RTL_R8(reg) inb (((unsigned long)ioaddr) + (reg)) -#define RTL_R16(reg) inw (((unsigned long)ioaddr) + (reg)) -#define RTL_R32(reg) ((unsigned long) inl (((unsigned long)ioaddr) + (reg))) -#define RTL_W8(reg, val8) outb ((val8), ((unsigned long)ioaddr) + (reg)) -#define RTL_W16(reg, val16) outw ((val16), ((unsigned long)ioaddr) + (reg)) -#define RTL_W32(reg, val32) outl ((val32), ((unsigned long)ioaddr) + (reg)) -#define RTL_W8_F RTL_W8 -#define RTL_W16_F RTL_W16 -#define RTL_W32_F RTL_W32 -#undef readb -#undef readw -#undef readl -#undef writeb -#undef writew -#undef writel -#define readb(addr) inb((unsigned long)(addr)) -#define readw(addr) inw((unsigned long)(addr)) -#define readl(addr) inl((unsigned long)(addr)) -#define writeb(val,addr) outb((val),(unsigned long)(addr)) -#define writew(val,addr) outw((val),(unsigned long)(addr)) -#define writel(val,addr) outl((val),(unsigned long)(addr)) - -#else - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { writeb ((val8), ioaddr + (reg)); readb (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { writew ((val16), ioaddr + (reg)); readw (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { writel ((val32), ioaddr + (reg)); readl (ioaddr + (reg)); } while (0) - - -#define MMIO_FLUSH_AUDIT_COMPLETE 1 -#if MMIO_FLUSH_AUDIT_COMPLETE - -/* write MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) - -#else - -/* write MMIO register, then flush */ -#define RTL_W8 RTL_W8_F -#define RTL_W16 RTL_W16_F -#define RTL_W32 RTL_W32_F - -#endif /* MMIO_FLUSH_AUDIT_COMPLETE */ - -/* read MMIO register */ -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -#endif /* USE_IO_OPS */ - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); - -static const unsigned int rtl8139_tx_config = - (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp; - struct pci_dev *pdev; - - assert (dev != NULL); - assert (dev->priv != NULL); - - tp = dev->priv; - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifndef USE_IO_OPS - if (tp->mmio_addr) - iounmap (tp->mmio_addr); -#endif /* !USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - -#ifndef RTL8139_NDEBUG - /* poison memory before freeing */ - memset (dev, 0xBC, - sizeof (struct net_device) + - sizeof (struct rtl8139_private)); -#endif /* RTL8139_NDEBUG */ - - kfree (dev); - - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc; - unsigned int i; - u32 pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 tmp; - -#ifdef XEN - DPRINTK(">\n"); -#endif - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and dev->priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - printk (KERN_ERR PFX "%s: Unable to alloc new net device\n", pdev->slot_name); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); - tp = dev->priv; - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - printk (KERN_ERR PFX "%s: region #0 not a PIO resource, aborting\n", pdev->slot_name); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - printk (KERN_ERR PFX "%s: Invalid PCI I/O region size(s), aborting\n", pdev->slot_name); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - printk (KERN_ERR PFX "%s: region #1 not an MMIO resource, aborting\n", pdev->slot_name); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - printk (KERN_ERR PFX "%s: Invalid PCI mem region size(s), aborting\n", pdev->slot_name); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, "8139too"); - if (rc) - goto err_out; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = (void *) pio_start; - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = ioremap (mmio_start, mmio_len); - if (ioaddr == NULL) { - printk (KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", pdev->slot_name); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - printk (KERN_ERR PFX "%s: Chip not responding, ignoring board\n", - pdev->slot_name); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - tmp = RTL_R8 (ChipVersion); - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (tmp == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - printk (KERN_DEBUG PFX "%s: unknown chip version, assuming RTL-8139\n", - pdev->slot_name); - printk (KERN_DEBUG PFX "%s: TxConfig = 0x%lx\n", pdev->slot_name, RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - tmp, - tp->chipset, - rtl_chip_info[tp->chipset].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) - RTL_W8 (Config4, tmp8 & ~LWPTN); - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void *ioaddr; - static int board_idx = -1; - u8 pci_rev; - -#ifdef XEN - DPRINTK("\n"); -#endif - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) { - printk(KERN_INFO PFX "pci dev %s (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->slot_name, pdev->vendor, pdev->device, pci_rev); - printk(KERN_INFO PFX "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - tp = dev->priv; - ioaddr = tp->mmio_addr; - - assert (ioaddr != NULL); - assert (dev != NULL); - assert (tp != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ -#ifdef XEN -#else - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; -#endif - - dev->irq = pdev->irq; - - /* dev->priv/tp zeroed and aligned in alloc_etherdev */ - tp = dev->priv; - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - spin_lock_init (&tp->lock); -#ifndef XEN - init_waitqueue_head (&tp->thr_wait); - init_completion (&tp->thr_exited); -#endif - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *np; - - assert (dev != NULL); - np = dev->priv; - assert (np != NULL); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() readl(ee_addr) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - void *ee_addr = ioaddr + Cfg9346; - int read_cmd = location | (EE_READ_CMD << addr_len); - - writeb (EE_ENB & ~EE_CS, ee_addr); - writeb (EE_ENB, ee_addr); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - writeb (EE_ENB | dataval, ee_addr); - eeprom_delay (); - writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); - eeprom_delay (); - } - writeb (EE_ENB, ee_addr); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - writeb (EE_ENB | EE_SHIFT_CLK, ee_addr); - eeprom_delay (); - retval = - (retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 : - 0); - writeb (EE_ENB, ee_addr); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - writeb (~EE_CS, ee_addr); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay(mdio_addr) readb(mdio_addr) - - -static char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void *mdio_addr) -{ - int i; - - for (i = 32; i >= 0; i--) { - writeb (MDIO_WRITE1, mdio_addr); - mdio_delay (mdio_addr); - writeb (MDIO_WRITE1 | MDIO_CLK, mdio_addr); - mdio_delay (mdio_addr); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = dev->priv; - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void *mdio_addr = tp->mmio_addr + Config4; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - return location < 8 && mii_2_8139_map[location] ? - readw (tp->mmio_addr + mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (mdio_addr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - writeb (MDIO_DIR | dataval, mdio_addr); - mdio_delay (mdio_addr); - writeb (MDIO_DIR | dataval | MDIO_CLK, mdio_addr); - mdio_delay (mdio_addr); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - writeb (0, mdio_addr); - mdio_delay (mdio_addr); - retval = (retval << 1) | ((readb (mdio_addr) & MDIO_DATA_IN) ? 1 : 0); - writeb (MDIO_CLK, mdio_addr); - mdio_delay (mdio_addr); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = dev->priv; -#ifdef CONFIG_8139TOO_8129 - void *mdio_addr = tp->mmio_addr + Config4; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (mdio_addr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - writeb (dataval, mdio_addr); - mdio_delay (mdio_addr); - writeb (dataval | MDIO_CLK, mdio_addr); - mdio_delay (mdio_addr); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - writeb (0, mdio_addr); - mdio_delay (mdio_addr); - writeb (MDIO_CLK, mdio_addr); - mdio_delay (mdio_addr); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = dev->priv; - int retval; -#ifdef RTL8139_DEBUG - void *ioaddr = tp->mmio_addr; -#endif - -#ifdef XEN - DPRINTK(" open device\n"); -#endif - retval = request_irq (dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma); - tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - tp->twistie = (tp->chipset == CH_8139_K) ? 1 : 0; - tp->time_to_die = 0; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - - DPRINTK ("%s: rtl8139_open() ioaddr %#lx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", - dev->name, pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - -#ifndef XEN - tp->thr_pid = kernel_thread (rtl8139_thread, dev, CLONE_FS | CLONE_FILES); - if (tp->thr_pid < 0) - printk (KERN_WARNING "%s: unable to start kernel thread\n", - dev->name); -#endif - - return 0; -} - - -static void rtl_check_media (struct net_device *dev) -{ - struct rtl8139_private *tp = dev->priv; - -#ifdef XEN - DPRINTK(">\n"); -#endif - if (tp->phys[0] >= 0) { - u16 mii_lpa = mdio_read(dev, tp->phys[0], MII_LPA); - if (mii_lpa == 0xffff) - ; /* Not there */ - else if ((mii_lpa & LPA_100FULL) == LPA_100FULL - || (mii_lpa & 0x00C0) == LPA_10FULL) - tp->mii.full_duplex = 1; - - printk (KERN_INFO"%s: Setting %s%s-duplex based on" - " auto-negotiated partner ability %4.4x.\n", - dev->name, mii_lpa == 0 ? "" : - (mii_lpa & 0x0180) ? "100mbps " : "10mbps ", - tp->mii.full_duplex ? "full" : "half", mii_lpa); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - -#ifdef XEN - DPRINTK(">\n"); -#endif - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - - /* Check this value: the documentation for IFG contradicts ifself. */ - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); - - netif_start_queue (dev); -#ifdef XEN - DPRINTK("<\n"); -#endif -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = dev->priv; - int i; - -#ifdef XEN - DPRINTK(">\n"); -#endif - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - - -#ifndef XEN -static int rtl8139_thread (void *data) -{ - struct net_device *dev = data; - struct rtl8139_private *tp = dev->priv; - unsigned long timeout; - - daemonize (); - reparent_to_init(); - spin_lock_irq(¤t->sigmask_lock); - sigemptyset(¤t->blocked); - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); - - strncpy (current->comm, dev->name, sizeof(current->comm) - 1); - current->comm[sizeof(current->comm) - 1] = '\0'; - - while (1) { - timeout = next_tick; - do { - timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout); - } while (!signal_pending (current) && (timeout > 0)); - - if (signal_pending (current)) { - spin_lock_irq(¤t->sigmask_lock); - flush_signals(current); - spin_unlock_irq(¤t->sigmask_lock); - } - - if (tp->time_to_die) - break; - - rtnl_lock (); - rtl8139_thread_iter (dev, tp, tp->mmio_addr); - rtnl_unlock (); - } - - complete_and_exit (&tp->thr_exited, 0); -} -#endif - - -static void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - unsigned long flags; - - DPRINTK ("%s: Transmit timeout, status %2.2x %4.4x " - "media %2.2x.\n", dev->name, - RTL_R8 (ChipCmd), - RTL_R16 (IntrStatus), - RTL_R8 (MediaStatus)); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irqsave (&tp->lock, flags); - rtl8139_tx_clear (tp); - spin_unlock_irqrestore (&tp->lock, flags); - - /* ...and finally, reset everything */ - rtl8139_hw_start (dev); - - netif_wake_queue (dev); -} - - -#ifdef XEN -void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) -{ - //unsigned short csum; - //long csstart; - //long csstuff; - - DPRINTK(">\n"); - DPRINTK("len=%d csum=%u ip_summed=%d\n", skb->len, skb->csum, skb->ip_summed); - DPRINTK("head=%p data=%p tail=%p end-%p\n", skb->head, skb->data, skb->tail, skb->end); - - memcpy(to, skb->data, skb->len); - - //csstart = skb->h.raw - skb->data; - //csum = compute_cksum(skb->data + csstart, skb->len - csstart); - //csstuff = csstart + skb->csum; - //*((unsigned short *)(to + csstuff)) = csum; - DPRINTK("<\n"); -} -#endif - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - /* Note: the chip doesn't have auto-pad! */ - spin_lock_irq(&tp->lock); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irq(&tp->lock); - - DPRINTK ("%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void *ioaddr) -{ - unsigned long dirty_tx, tx_left; - -#ifdef XEN - DPRINTK(">\n"); -#endif - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - DPRINTK ("%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (netif_queue_stopped (dev)) - netif_wake_queue (dev); - } -#ifdef XEN - DPRINTK("<\n"); -#endif -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - DPRINTK ("%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -static void rtl8139_rx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, void *ioaddr) -{ - unsigned char *rx_ring; - u16 cur_rx; - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - rx_ring = tp->rx_ring; - cur_rx = tp->cur_rx; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - int ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int rx_size; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - DPRINTK ("%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (rx_size == 0xfff0) { - tp->xstats.early_rx++; - break; - } - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if ((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - return; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - /* TODO: consider allocating skb's outside of - * interrupt context, both to speed interrupt processing, - * and also to reduce the chances of having to - * drop packets here under memory pressure. - */ - - skb = dev_alloc_skb (pkt_size + 2); - if (skb) { - skb->dev = dev; - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ - - eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0); - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - netif_rx (skb); - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - } else { - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, cur_rx - 16); - - if (RTL_R16 (IntrStatus) & RxAckBits) - RTL_W16_F (IntrStatus, RxAckBits); - } - - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - tp->cur_rx = cur_rx; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - /* Really link-change on new chips. */ - int lpar = RTL_R16 (NWayLPAR); - int duplex = (lpar & LPA_100FULL) || (lpar & 0x01C0) == 0x0040 - || tp->mii.force_media; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - status &= ~RxUnderrun; - } - - /* XXX along with rtl8139_rx_err, are we double-counting errors? */ - if (status & - (RxUnderrun | RxOverflow | RxErr | RxFIFOOver)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & (RxUnderrun | RxFIFOOver)) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static void rtl8139_interrupt (int irq, void *dev_instance, - struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = dev->priv; - int boguscnt = max_interrupt_work; - void *ioaddr = tp->mmio_addr; - int ackstat, status; - int link_changed = 0; /* avoid bogus "uninit" warning */ - -#ifdef XEN - DPRINTK(" irq=%d\n", irq); -#endif - spin_lock (&tp->lock); - - do { - status = RTL_R16 (IntrStatus); - - /* h/w no longer present (hotplug?) or major error, bail */ - if (status == 0xFFFF) - break; - - if ((status & - (PCIErr | PCSTimeout | RxUnderrun | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxErr | RxOK)) == 0) - break; - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (status & RxUnderrun) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - /* The chip takes special action when we clear RxAckBits, - * so we clear them later in rtl8139_rx_interrupt - */ - ackstat = status & ~(RxAckBits | TxErr); - RTL_W16 (IntrStatus, ackstat); - - DPRINTK ("%s: interrupt status=%#4.4x ackstat=%#4.4x new intstat=%#4.4x.\n", - dev->name, status, ackstat, RTL_R16 (IntrStatus)); - - if (netif_running (dev) && (status & RxAckBits)) - rtl8139_rx_interrupt (dev, tp, ioaddr); - - /* Check uncommon events with one test. */ - if (status & (PCIErr | PCSTimeout | RxUnderrun | RxOverflow | - RxFIFOOver | RxErr)) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (netif_running (dev) && (status & (TxOK | TxErr))) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - - boguscnt--; - } while (boguscnt > 0); - - if (boguscnt <= 0) { - printk (KERN_WARNING "%s: Too much work at interrupt, " - "IntrStatus=0x%4.4x.\n", dev->name, status); - - /* Clear all interrupt sources. */ - RTL_W16 (IntrStatus, 0xffff); - } - - spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); -} - - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; -#ifndef XEN - int ret = 0; -#endif - unsigned long flags; - - netif_stop_queue (dev); - -#ifndef XEN - if (tp->thr_pid >= 0) { - tp->time_to_die = 1; - wmb(); - ret = kill_proc (tp->thr_pid, SIGTERM, 1); - if (ret) { - printk (KERN_ERR "%s: unable to signal thread\n", dev->name); - return ret; - } - wait_for_completion (&tp->thr_exited); - } -#endif - - DPRINTK ("%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - -#ifndef XEN - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void netdev_get_wol (struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = dev->priv; - void *ioaddr = np->mmio_addr; - - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int netdev_set_wol (struct net_device *dev, - const struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = dev->priv; - void *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - - return 0; -} - -static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) -{ - struct rtl8139_private *np = dev->priv; - u32 ethcmd; - - /* dev_ioctl() in ../../net/core/dev.c has already checked - capable(CAP_NET_ADMIN), so don't bother with that here. */ - - if (get_user(ethcmd, (u32 *)useraddr)) - return -EFAULT; - - switch (ethcmd) { - - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy (info.driver, DRV_NAME); - strcpy (info.version, DRV_VERSION); - strcpy (info.bus_info, np->pci_dev->slot_name); - info.regdump_len = np->regs_len; - if (copy_to_user (useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } - - /* get settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, &ecmd); - spin_unlock_irq(&np->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - /* set settings */ - case ETHTOOL_SSET: { - int r; - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - spin_lock_irq(&np->lock); - r = mii_ethtool_sset(&np->mii, &ecmd); - spin_unlock_irq(&np->lock); - return r; - } - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - return mii_nway_restart(&np->mii); - } - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - edata.data = mii_link_ok(&np->mii); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - - /* get message-level */ - case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = {ETHTOOL_GMSGLVL}; - edata.data = debug; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - /* set message-level */ - case ETHTOOL_SMSGLVL: { - struct ethtool_value edata; - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - debug = edata.data; - return 0; - } - - case ETHTOOL_GWOL: - { - struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; - spin_lock_irq (&np->lock); - netdev_get_wol (dev, &wol); - spin_unlock_irq (&np->lock); - if (copy_to_user (useraddr, &wol, sizeof (wol))) - return -EFAULT; - return 0; - } - - case ETHTOOL_SWOL: - { - struct ethtool_wolinfo wol; - int rc; - if (copy_from_user (&wol, useraddr, sizeof (wol))) - return -EFAULT; - spin_lock_irq (&np->lock); - rc = netdev_set_wol (dev, &wol); - spin_unlock_irq (&np->lock); - return rc; - } - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifndef CONFIG_8139TOO_PIO - /* NIC register dump */ - case ETHTOOL_GREGS: { - struct ethtool_regs regs; - unsigned int regs_len = np->regs_len; - u8 *regbuf = kmalloc(regs_len, GFP_KERNEL); - int rc; - - if (!regbuf) - return -ENOMEM; - memset(regbuf, 0, regs_len); - - rc = copy_from_user(®s, useraddr, sizeof(regs)); - if (rc) { - rc = -EFAULT; - goto err_out_gregs; - } - - if (regs.len > regs_len) - regs.len = regs_len; - if (regs.len < regs_len) { - rc = -EINVAL; - goto err_out_gregs; - } - - regs.version = RTL_REGS_VER; - rc = copy_to_user(useraddr, ®s, sizeof(regs)); - if (rc) { - rc = -EFAULT; - goto err_out_gregs; - } - - useraddr += offsetof(struct ethtool_regs, data); - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs_len); - spin_unlock_irq(&np->lock); - - if (copy_to_user(useraddr, regbuf, regs_len)) - rc = -EFAULT; - -err_out_gregs: - kfree(regbuf); - return rc; - } -#endif /* CONFIG_8139TOO_PIO */ - - /* get string list(s) */ - case ETHTOOL_GSTRINGS: { - struct ethtool_gstrings estr = { ETHTOOL_GSTRINGS }; - - if (copy_from_user(&estr, useraddr, sizeof(estr))) - return -EFAULT; - if (estr.string_set != ETH_SS_STATS) - return -EINVAL; - - estr.len = RTL_NUM_STATS; - if (copy_to_user(useraddr, &estr, sizeof(estr))) - return -EFAULT; - if (copy_to_user(useraddr + sizeof(estr), - ðtool_stats_keys, - sizeof(ethtool_stats_keys))) - return -EFAULT; - return 0; - } - - /* get NIC-specific statistics */ - case ETHTOOL_GSTATS: { - struct ethtool_stats estats = { ETHTOOL_GSTATS }; - u64 *tmp_stats; - const unsigned int sz = sizeof(u64) * RTL_NUM_STATS; - int i; - - estats.n_stats = RTL_NUM_STATS; - if (copy_to_user(useraddr, &estats, sizeof(estats))) - return -EFAULT; - - tmp_stats = kmalloc(sz, GFP_KERNEL); - if (!tmp_stats) - return -ENOMEM; - memset(tmp_stats, 0, sz); - - i = 0; - tmp_stats[i++] = np->xstats.early_rx; - tmp_stats[i++] = np->xstats.tx_buf_mapped; - tmp_stats[i++] = np->xstats.tx_timeouts; - tmp_stats[i++] = np->xstats.rx_lost_in_ring; - if (i != RTL_NUM_STATS) - BUG(); - - i = copy_to_user(useraddr + sizeof(estats), tmp_stats, sz); - kfree(tmp_stats); - - if (i) - return -EFAULT; - return 0; - } - default: - break; - } - - return -EOPNOTSUPP; -} -#endif - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ -#ifdef XEN - DPRINTK("> cmd=%d\n", cmd); - return 0; //-ENOSYS; -#else - struct rtl8139_private *np = dev->priv; - struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data; - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - if (cmd == SIOCETHTOOL) - rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); - - else { - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, data, cmd, NULL); - spin_unlock_irq(&np->lock); - } - - return rc; -#endif -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; - unsigned long flags; - -#ifdef XEN - DPRINTK("\n"); -#endif - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = dev->priv; - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, u32 state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - if (!netif_running (dev)) - return 0; - netif_device_attach (dev); - rtl8139_hw_start (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#if defined(MODULE) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_module_init (&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/xen/drivers/net/Makefile b/xen/drivers/net/Makefile deleted file mode 100644 index 73581d9b79..0000000000 --- a/xen/drivers/net/Makefile +++ /dev/null @@ -1,16 +0,0 @@ - -include $(BASEDIR)/Rules.mk - -default: $(OBJS) - $(MAKE) -C tulip - $(MAKE) -C e100 - $(MAKE) -C e1000 - $(LD) -r -o driver.o e1000/e1000.o $(OBJS) e100/e100.o tulip/tulip.o - -clean: - $(MAKE) -C tulip clean - $(MAKE) -C e100 clean - $(MAKE) -C e1000 clean - rm -f *.o *~ core - -.PHONY: default clean diff --git a/xen/drivers/net/SUPPORTED_CARDS b/xen/drivers/net/SUPPORTED_CARDS deleted file mode 100644 index 94ff7bc8f2..0000000000 --- a/xen/drivers/net/SUPPORTED_CARDS +++ /dev/null @@ -1,14 +0,0 @@ - -Recommended (cards tested and working at full efficiency): - 3com 3c905 (3c59x.c Linux driver) - Broadcom tg3 (tg3.c Linux driver) - Intel e1000 (e1000 Linux driver) - Intel e100 (e100 Linux driver) [*] - -Driver ported, but may not be tested, and won't work at full -efficiency (extra copies are incurred within Xen): - ne2k, pcnet32/lance, rtl8139, tulip, via-rhine, - -*: Note that certain revisions of e100 do not support - scatter/gather DMA. These cards will incur an extra - copy within Xen for every transmitted packet. \ No newline at end of file diff --git a/xen/drivers/net/Space.c b/xen/drivers/net/Space.c deleted file mode 100644 index 91fa78dcf0..0000000000 --- a/xen/drivers/net/Space.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Holds initial configuration information for devices. - * - * Version: @(#)Space.c 1.0.7 08/12/93 - * - * Authors: Ross Biro, - * Fred N. van Kempen, - * Donald J. Becker, - */ -#include -#include - -/* - * KAF (23/7/02): All the probe shit is gone from here -- each network - * driver should probe as part of its setup, and dynamically append - * to dev_base when it finds a NIC. - */ - -/* - * The @dev_base list is protected by @dev_base_lock and the rtln - * semaphore. - * - * Pure readers hold dev_base_lock for reading. - * - * Writers must hold the rtnl semaphore while they loop through the - * dev_base list, and hold dev_base_lock for writing when they do the - * actual updates. This allows pure readers to access the list even - * while a writer is preparing to update it. - * - * To put it another way, dev_base_lock is held for writing only to - * protect against pure readers; the rtnl semaphore provides the - * protection against other writers. - * - * See, for example usages, register_netdevice() and - * unregister_netdevice(), which must be called with the rtnl - * semaphore held. - */ -struct net_device *dev_base = NULL; -rwlock_t dev_base_lock = RW_LOCK_UNLOCKED; - diff --git a/xen/drivers/net/dummy.c b/xen/drivers/net/dummy.c deleted file mode 100644 index dbc3682ad7..0000000000 --- a/xen/drivers/net/dummy.c +++ /dev/null @@ -1,79 +0,0 @@ -/****************************************************************************** - * dummy.c - * - * A cut down version of Linux's dummy network driver. GPLed and all that. - */ - -#include -#include -#include -#include -#include - -static int dummy_xmit(struct sk_buff *skb, struct net_device *dev); -static struct net_device_stats *dummy_get_stats(struct net_device *dev); - -static int __init dummy_init(struct net_device *dev) -{ - dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL); - if ( dev->priv == NULL ) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct net_device_stats)); - - dev->get_stats = dummy_get_stats; - dev->hard_start_xmit = dummy_xmit; - - ether_setup(dev); - dev->flags |= IFF_NOARP; - dev->features = NETIF_F_SG | NETIF_F_HIGHDMA; - - return 0; -} - -static int dummy_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct net_device_stats *stats = dev->priv; - - stats->tx_packets++; - stats->tx_bytes += skb->len; - - dev_kfree_skb(skb); - - return 0; -} - -static struct net_device_stats *dummy_get_stats(struct net_device *dev) -{ - return dev->priv; -} - -static struct net_device dev_dummy; - -static int __init dummy_init_module(void) -{ - int err; - - dev_dummy.init = dummy_init; - SET_MODULE_OWNER(&dev_dummy); - - if ( (err = dev_alloc_name(&dev_dummy,"dummy")) < 0 ) - return err; - - if ( (err = register_netdev(&dev_dummy)) < 0 ) - return err; - - return 0; -} - -static void __exit dummy_cleanup_module(void) -{ - unregister_netdev(&dev_dummy); - kfree(dev_dummy.priv); - - memset(&dev_dummy, 0, sizeof(dev_dummy)); - dev_dummy.init = dummy_init; -} - -module_init(dummy_init_module); -module_exit(dummy_cleanup_module); -MODULE_LICENSE("GPL"); diff --git a/xen/drivers/net/e100/LICENSE b/xen/drivers/net/e100/LICENSE deleted file mode 100644 index 5f297e5bb4..0000000000 --- a/xen/drivers/net/e100/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - -"This software program is licensed subject to the GNU General Public License -(GPL). Version 2, June 1991, available at -" - -GNU General Public License - -Version 2, June 1991 - -Copyright (C) 1989, 1991 Free Software Foundation, Inc. -59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - -Everyone is permitted to copy and distribute verbatim copies of this license -document, but changing it is not allowed. - -Preamble - -The licenses for most software are designed to take away your freedom to -share and change it. By contrast, the GNU General Public License is intended -to guarantee your freedom to share and change free software--to make sure -the software is free for all its users. This General Public License applies -to most of the Free Software Foundation's software and to any other program -whose authors commit to using it. (Some other Free Software Foundation -software is covered by the GNU Library General Public License instead.) You -can apply it to your programs, too. - -When we speak of free software, we are referring to freedom, not price. Our -General Public Licenses are designed to make sure that you have the freedom -to distribute copies of free software (and charge for this service if you -wish), that you receive source code or can get it if you want it, that you -can change the software or use pieces of it in new free programs; and that -you know you can do these things. - -To protect your rights, we need to make restrictions that forbid anyone to -deny you these rights or to ask you to surrender the rights. These -restrictions translate to certain responsibilities for you if you distribute -copies of the software, or if you modify it. - -For example, if you distribute copies of such a program, whether gratis or -for a fee, you must give the recipients all the rights that you have. You -must make sure that they, too, receive or can get the source code. And you -must show them these terms so they know their rights. - -We protect your rights with two steps: (1) copyright the software, and (2) -offer you this license which gives you legal permission to copy, distribute -and/or modify the software. - -Also, for each author's protection and ours, we want to make certain that -everyone understands that there is no warranty for this free software. If -the software is modified by someone else and passed on, we want its -recipients to know that what they have is not the original, so that any -problems introduced by others will not reflect on the original authors' -reputations. - -Finally, any free program is threatened constantly by software patents. We -wish to avoid the danger that redistributors of a free program will -individually obtain patent licenses, in effect making the program -proprietary. To prevent this, we have made it clear that any patent must be -licensed for everyone's free use or not licensed at all. - -The precise terms and conditions for copying, distribution and modification -follow. - -TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - -0. This License applies to any program or other work which contains a notice - placed by the copyright holder saying it may be distributed under the - terms of this General Public License. The "Program", below, refers to any - such program or work, and a "work based on the Program" means either the - Program or any derivative work under copyright law: that is to say, a - work containing the Program or a portion of it, either verbatim or with - modifications and/or translated into another language. (Hereinafter, - translation is included without limitation in the term "modification".) - Each licensee is addressed as "you". - - Activities other than copying, distribution and modification are not - covered by this License; they are outside its scope. The act of running - the Program is not restricted, and the output from the Program is covered - only if its contents constitute a work based on the Program (independent - of having been made by running the Program). Whether that is true depends - on what the Program does. - -1. You may copy and distribute verbatim copies of the Program's source code - as you receive it, in any medium, provided that you conspicuously and - appropriately publish on each copy an appropriate copyright notice and - disclaimer of warranty; keep intact all the notices that refer to this - License and to the absence of any warranty; and give any other recipients - of the Program a copy of this License along with the Program. - - You may charge a fee for the physical act of transferring a copy, and you - may at your option offer warranty protection in exchange for a fee. - -2. You may modify your copy or copies of the Program or any portion of it, - thus forming a work based on the Program, and copy and distribute such - modifications or work under the terms of Section 1 above, provided that - you also meet all of these conditions: - - * a) You must cause the modified files to carry prominent notices stating - that you changed the files and the date of any change. - - * b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any part - thereof, to be licensed as a whole at no charge to all third parties - under the terms of this License. - - * c) If the modified program normally reads commands interactively when - run, you must cause it, when started running for such interactive - use in the most ordinary way, to print or display an announcement - including an appropriate copyright notice and a notice that there is - no warranty (or else, saying that you provide a warranty) and that - users may redistribute the program under these conditions, and - telling the user how to view a copy of this License. (Exception: if - the Program itself is interactive but does not normally print such - an announcement, your work based on the Program is not required to - print an announcement.) - - These requirements apply to the modified work as a whole. If identifiable - sections of that work are not derived from the Program, and can be - reasonably considered independent and separate works in themselves, then - this License, and its terms, do not apply to those sections when you - distribute them as separate works. But when you distribute the same - sections as part of a whole which is a work based on the Program, the - distribution of the whole must be on the terms of this License, whose - permissions for other licensees extend to the entire whole, and thus to - each and every part regardless of who wrote it. - - Thus, it is not the intent of this section to claim rights or contest - your rights to work written entirely by you; rather, the intent is to - exercise the right to control the distribution of derivative or - collective works based on the Program. - - In addition, mere aggregation of another work not based on the Program - with the Program (or with a work based on the Program) on a volume of a - storage or distribution medium does not bring the other work under the - scope of this License. - -3. You may copy and distribute the Program (or a work based on it, under - Section 2) in object code or executable form under the terms of Sections - 1 and 2 above provided that you also do one of the following: - - * a) Accompany it with the complete corresponding machine-readable source - code, which must be distributed under the terms of Sections 1 and 2 - above on a medium customarily used for software interchange; or, - - * b) Accompany it with a written offer, valid for at least three years, - to give any third party, for a charge no more than your cost of - physically performing source distribution, a complete machine- - readable copy of the corresponding source code, to be distributed - under the terms of Sections 1 and 2 above on a medium customarily - used for software interchange; or, - - * c) Accompany it with the information you received as to the offer to - distribute corresponding source code. (This alternative is allowed - only for noncommercial distribution and only if you received the - program in object code or executable form with such an offer, in - accord with Subsection b above.) - - The source code for a work means the preferred form of the work for - making modifications to it. For an executable work, complete source code - means all the source code for all modules it contains, plus any - associated interface definition files, plus the scripts used to control - compilation and installation of the executable. However, as a special - exception, the source code distributed need not include anything that is - normally distributed (in either source or binary form) with the major - components (compiler, kernel, and so on) of the operating system on which - the executable runs, unless that component itself accompanies the - executable. - - If distribution of executable or object code is made by offering access - to copy from a designated place, then offering equivalent access to copy - the source code from the same place counts as distribution of the source - code, even though third parties are not compelled to copy the source - along with the object code. - -4. You may not copy, modify, sublicense, or distribute the Program except as - expressly provided under this License. Any attempt otherwise to copy, - modify, sublicense or distribute the Program is void, and will - automatically terminate your rights under this License. However, parties - who have received copies, or rights, from you under this License will not - have their licenses terminated so long as such parties remain in full - compliance. - -5. You are not required to accept this License, since you have not signed - it. However, nothing else grants you permission to modify or distribute - the Program or its derivative works. These actions are prohibited by law - if you do not accept this License. Therefore, by modifying or - distributing the Program (or any work based on the Program), you - indicate your acceptance of this License to do so, and all its terms and - conditions for copying, distributing or modifying the Program or works - based on it. - -6. Each time you redistribute the Program (or any work based on the - Program), the recipient automatically receives a license from the - original licensor to copy, distribute or modify the Program subject to - these terms and conditions. You may not impose any further restrictions - on the recipients' exercise of the rights granted herein. You are not - responsible for enforcing compliance by third parties to this License. - -7. If, as a consequence of a court judgment or allegation of patent - infringement or for any other reason (not limited to patent issues), - conditions are imposed on you (whether by court order, agreement or - otherwise) that contradict the conditions of this License, they do not - excuse you from the conditions of this License. If you cannot distribute - so as to satisfy simultaneously your obligations under this License and - any other pertinent obligations, then as a consequence you may not - distribute the Program at all. For example, if a patent license would - not permit royalty-free redistribution of the Program by all those who - receive copies directly or indirectly through you, then the only way you - could satisfy both it and this License would be to refrain entirely from - distribution of the Program. - - If any portion of this section is held invalid or unenforceable under any - particular circumstance, the balance of the section is intended to apply - and the section as a whole is intended to apply in other circumstances. - - It is not the purpose of this section to induce you to infringe any - patents or other property right claims or to contest validity of any - such claims; this section has the sole purpose of protecting the - integrity of the free software distribution system, which is implemented - by public license practices. Many people have made generous contributions - to the wide range of software distributed through that system in - reliance on consistent application of that system; it is up to the - author/donor to decide if he or she is willing to distribute software - through any other system and a licensee cannot impose that choice. - - This section is intended to make thoroughly clear what is believed to be - a consequence of the rest of this License. - -8. If the distribution and/or use of the Program is restricted in certain - countries either by patents or by copyrighted interfaces, the original - copyright holder who places the Program under this License may add an - explicit geographical distribution limitation excluding those countries, - so that distribution is permitted only in or among countries not thus - excluded. In such case, this License incorporates the limitation as if - written in the body of this License. - -9. The Free Software Foundation may publish revised and/or new versions of - the General Public License from time to time. Such new versions will be - similar in spirit to the present version, but may differ in detail to - address new problems or concerns. - - Each version is given a distinguishing version number. If the Program - specifies a version number of this License which applies to it and "any - later version", you have the option of following the terms and - conditions either of that version or of any later version published by - the Free Software Foundation. If the Program does not specify a version - number of this License, you may choose any version ever published by the - Free Software Foundation. - -10. If you wish to incorporate parts of the Program into other free programs - whose distribution conditions are different, write to the author to ask - for permission. For software which is copyrighted by the Free Software - Foundation, write to the Free Software Foundation; we sometimes make - exceptions for this. Our decision will be guided by the two goals of - preserving the free status of all derivatives of our free software and - of promoting the sharing and reuse of software generally. - - NO WARRANTY - -11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY - FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN - OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES - PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER - EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE - ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH - YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL - NECESSARY SERVICING, REPAIR OR CORRECTION. - -12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING - WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR - REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR - DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL - DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM - (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED - INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF - THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR - OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -END OF TERMS AND CONDITIONS - -How to Apply These Terms to Your New Programs - -If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it free -software which everyone can redistribute and change under these terms. - -To do so, attach the following notices to the program. It is safest to -attach them to the start of each source file to most effectively convey the -exclusion of warranty; and each file should have at least the "copyright" -line and a pointer to where the full notice is found. - -one line to give the program's name and an idea of what it does. -Copyright (C) yyyy name of author - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your option) -any later version. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 -Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this when -it starts in an interactive mode: - -Gnomovision version 69, Copyright (C) year name of author Gnomovision comes -with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free -software, and you are welcome to redistribute it under certain conditions; -type 'show c' for details. - -The hypothetical commands 'show w' and 'show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may be -called something other than 'show w' and 'show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - -Yoyodyne, Inc., hereby disclaims all copyright interest in the program -'Gnomovision' (which makes passes at compilers) written by James Hacker. - -signature of Ty Coon, 1 April 1989 -Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General Public -License instead of this License. diff --git a/xen/drivers/net/e100/Makefile b/xen/drivers/net/e100/Makefile deleted file mode 100644 index b16f6f07fc..0000000000 --- a/xen/drivers/net/e100/Makefile +++ /dev/null @@ -1,8 +0,0 @@ - -include $(BASEDIR)/Rules.mk - -default: $(OBJS) - $(LD) -r -o e100.o $(OBJS) - -clean: - rm -f *.o *~ core diff --git a/xen/drivers/net/e100/e100.h b/xen/drivers/net/e100/e100.h deleted file mode 100644 index 8503550d9c..0000000000 --- a/xen/drivers/net/e100/e100.h +++ /dev/null @@ -1,1005 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -#ifndef _E100_INC_ -#define _E100_INC_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/*#include */ -#include -#include -#include -#include -#include -/*#include */ -#include - -#include -#include -/*#include */ -#include -#include - -#define yield() ((void)0) - -#define E100_REGS_LEN 1 -/* - * Configure parameters for buffers per controller. - * If the machine this is being used on is a faster machine (i.e. > 150MHz) - * and running on a 10MBS network then more queueing of data occurs. This - * may indicate the some of the numbers below should be adjusted. Here are - * some typical numbers: - * MAX_TCB 64 - * MAX_RFD 64 - * The default numbers give work well on most systems tests so no real - * adjustments really need to take place. Also, if the machine is connected - * to a 100MBS network the numbers described above can be lowered from the - * defaults as considerably less data will be queued. - */ - -#define TX_FRAME_CNT 8 /* consecutive transmit frames per interrupt */ -/* TX_FRAME_CNT must be less than MAX_TCB */ - -#define E100_DEFAULT_TCB 64 -#define E100_MIN_TCB 2*TX_FRAME_CNT + 3 /* make room for at least 2 interrupts */ -#define E100_MAX_TCB 1024 - -#define E100_DEFAULT_RFD 64 -#define E100_MIN_RFD 8 -#define E100_MAX_RFD 1024 - -#define E100_DEFAULT_XSUM true -#define E100_DEFAULT_BER ZLOCK_MAX_ERRORS -#define E100_DEFAULT_SPEED_DUPLEX 0 -#define E100_DEFAULT_FC 0 -#define E100_DEFAULT_IFS true -#define E100_DEFAULT_UCODE true - -#define TX_THRSHLD 8 - -/* IFS parameters */ -#define MIN_NUMBER_OF_TRANSMITS_100 1000 -#define MIN_NUMBER_OF_TRANSMITS_10 100 - -#define E100_MAX_NIC 16 - -#define E100_MAX_SCB_WAIT 100 /* Max udelays in wait_scb */ -#define E100_MAX_CU_IDLE_WAIT 50 /* Max udelays in wait_cus_idle */ - -/* HWI feature related constant */ -#define HWI_MAX_LOOP 100 -#define MAX_SAME_RESULTS 3 -#define HWI_REGISTER_GRANULARITY 80 /* register granularity = 80 Cm */ -#define HWI_NEAR_END_BOUNDARY 1000 /* Near end is defined as < 10 meters */ - -/* CPUSAVER_BUNDLE_MAX: Sets the maximum number of frames that will be bundled. - * In some situations, such as the TCP windowing algorithm, it may be - * better to limit the growth of the bundle size than let it go as - * high as it can, because that could cause too much added latency. - * The default is six, because this is the number of packets in the - * default TCP window size. A value of 1 would make CPUSaver indicate - * an interrupt for every frame received. If you do not want to put - * a limit on the bundle size, set this value to xFFFF. - */ -#define E100_DEFAULT_CPUSAVER_BUNDLE_MAX 6 -#define E100_DEFAULT_CPUSAVER_INTERRUPT_DELAY 0x600 -#define E100_DEFAULT_BUNDLE_SMALL_FR false - -/* end of configurables */ - -/* ====================================================================== */ -/* hw */ -/* ====================================================================== */ - -/* timeout for command completion */ -#define E100_CMD_WAIT 100 /* iterations */ - -struct driver_stats { - struct net_device_stats net_stats; - - unsigned long tx_late_col; - unsigned long tx_ok_defrd; - unsigned long tx_one_retry; - unsigned long tx_mt_one_retry; - unsigned long rcv_cdt_frames; - unsigned long xmt_fc_pkts; - unsigned long rcv_fc_pkts; - unsigned long rcv_fc_unsupported; - unsigned long xmt_tco_pkts; - unsigned long rcv_tco_pkts; - unsigned long rx_intr_pkts; -}; - -/* TODO: kill me when we can do C99 */ -#define false (0) -#define true (1) - -/* Changed for 82558 and 82559 enhancements */ -/* defines for 82558/9 flow control CSR values */ -#define DFLT_FC_THLD 0x00 /* Rx FIFO threshold of 0.5KB free */ -#define DFLT_FC_CMD 0x00 /* FC Command in CSR */ - -/* ====================================================================== */ -/* equates */ -/* ====================================================================== */ - -/* - * These are general purpose defines - */ - -/* Bit Mask definitions */ -#define BIT_0 0x0001 -#define BIT_1 0x0002 -#define BIT_2 0x0004 -#define BIT_3 0x0008 -#define BIT_4 0x0010 -#define BIT_5 0x0020 -#define BIT_6 0x0040 -#define BIT_7 0x0080 -#define BIT_8 0x0100 -#define BIT_9 0x0200 -#define BIT_10 0x0400 -#define BIT_11 0x0800 -#define BIT_12 0x1000 -#define BIT_13 0x2000 -#define BIT_14 0x4000 -#define BIT_15 0x8000 -#define BIT_28 0x10000000 - -#define BIT_0_2 0x0007 -#define BIT_0_3 0x000F -#define BIT_0_4 0x001F -#define BIT_0_5 0x003F -#define BIT_0_6 0x007F -#define BIT_0_7 0x00FF -#define BIT_0_8 0x01FF -#define BIT_0_13 0x3FFF -#define BIT_0_15 0xFFFF -#define BIT_1_2 0x0006 -#define BIT_1_3 0x000E -#define BIT_2_5 0x003C -#define BIT_3_4 0x0018 -#define BIT_4_5 0x0030 -#define BIT_4_6 0x0070 -#define BIT_4_7 0x00F0 -#define BIT_5_7 0x00E0 -#define BIT_5_12 0x1FE0 -#define BIT_5_15 0xFFE0 -#define BIT_6_7 0x00c0 -#define BIT_7_11 0x0F80 -#define BIT_8_10 0x0700 -#define BIT_9_13 0x3E00 -#define BIT_12_15 0xF000 -#define BIT_8_15 0xFF00 - -#define BIT_16_20 0x001F0000 -#define BIT_21_25 0x03E00000 -#define BIT_26_27 0x0C000000 - -/* Transmit Threshold related constants */ -#define DEFAULT_TX_PER_UNDERRUN 20000 - -#define MAX_MULTICAST_ADDRS 64 -#define MAX_FILTER 16 - -#define FULL_DUPLEX 2 -#define HALF_DUPLEX 1 - -/* - * These defines are specific to the 82557 - */ - -/* E100 PORT functions -- lower 4 bits */ -#define PORT_SOFTWARE_RESET 0 -#define PORT_SELFTEST 1 -#define PORT_SELECTIVE_RESET 2 -#define PORT_DUMP 3 - -/* SCB Status Word bit definitions */ -/* Interrupt status/ack fields */ -/* ER and FCP interrupts for 82558 masks */ -#define SCB_STATUS_ACK_MASK BIT_8_15 /* Status Mask */ -#define SCB_STATUS_ACK_CX BIT_15 /* CU Completed Action Cmd */ -#define SCB_STATUS_ACK_FR BIT_14 /* RU Received A Frame */ -#define SCB_STATUS_ACK_CNA BIT_13 /* CU Became Inactive (IDLE) */ -#define SCB_STATUS_ACK_RNR BIT_12 /* RU Became Not Ready */ -#define SCB_STATUS_ACK_MDI BIT_11 /* MDI read or write done */ -#define SCB_STATUS_ACK_SWI BIT_10 /* S/W generated interrupt */ -#define SCB_STATUS_ACK_ER BIT_9 /* Early Receive */ -#define SCB_STATUS_ACK_FCP BIT_8 /* Flow Control Pause */ - -/*- CUS Fields */ -#define SCB_CUS_MASK (BIT_6 | BIT_7) /* CUS 2-bit Mask */ -#define SCB_CUS_IDLE 0 /* CU Idle */ -#define SCB_CUS_SUSPEND BIT_6 /* CU Suspended */ -#define SCB_CUS_ACTIVE BIT_7 /* CU Active */ - -/*- RUS Fields */ -#define SCB_RUS_IDLE 0 /* RU Idle */ -#define SCB_RUS_MASK BIT_2_5 /* RUS 3-bit Mask */ -#define SCB_RUS_SUSPEND BIT_2 /* RU Suspended */ -#define SCB_RUS_NO_RESOURCES BIT_3 /* RU Out Of Resources */ -#define SCB_RUS_READY BIT_4 /* RU Ready */ -#define SCB_RUS_SUSP_NO_RBDS (BIT_2 | BIT_5) /* RU No More RBDs */ -#define SCB_RUS_NO_RBDS (BIT_3 | BIT_5) /* RU No More RBDs */ -#define SCB_RUS_READY_NO_RBDS (BIT_4 | BIT_5) /* RU Ready, No RBDs */ - -/* SCB Command Word bit definitions */ -/*- CUC fields */ -/* Changing mask to 4 bits */ -#define SCB_CUC_MASK BIT_4_7 /* CUC 4-bit Mask */ -#define SCB_CUC_NOOP 0 -#define SCB_CUC_START BIT_4 /* CU Start */ -#define SCB_CUC_RESUME BIT_5 /* CU Resume */ -#define SCB_CUC_UNKNOWN BIT_7 /* CU unknown command */ -/* Changed for 82558 enhancements */ -#define SCB_CUC_STATIC_RESUME (BIT_5 | BIT_7) /* 82558/9 Static Resume */ -#define SCB_CUC_DUMP_ADDR BIT_6 /* CU Dump Counters Address */ -#define SCB_CUC_DUMP_STAT (BIT_4 | BIT_6) /* CU Dump stat. counters */ -#define SCB_CUC_LOAD_BASE (BIT_5 | BIT_6) /* Load the CU base */ -/* Below was defined as BIT_4_7 */ -#define SCB_CUC_DUMP_RST_STAT BIT_4_6 /* CU Dump & reset statistics cntrs */ - -/*- RUC fields */ -#define SCB_RUC_MASK BIT_0_2 /* RUC 3-bit Mask */ -#define SCB_RUC_START BIT_0 /* RU Start */ -#define SCB_RUC_RESUME BIT_1 /* RU Resume */ -#define SCB_RUC_ABORT BIT_2 /* RU Abort */ -#define SCB_RUC_LOAD_HDS (BIT_0 | BIT_2) /* Load RFD Header Data Size */ -#define SCB_RUC_LOAD_BASE (BIT_1 | BIT_2) /* Load the RU base */ -#define SCB_RUC_RBD_RESUME BIT_0_2 /* RBD resume */ - -/* Interrupt fields (assuming byte addressing) */ -#define SCB_INT_MASK BIT_0 /* Mask interrupts */ -#define SCB_SOFT_INT BIT_1 /* Generate a S/W interrupt */ -/* Specific Interrupt Mask Bits (upper byte of SCB Command word) */ -#define SCB_FCP_INT_MASK BIT_2 /* Flow Control Pause */ -#define SCB_ER_INT_MASK BIT_3 /* Early Receive */ -#define SCB_RNR_INT_MASK BIT_4 /* RU Not Ready */ -#define SCB_CNA_INT_MASK BIT_5 /* CU Not Active */ -#define SCB_FR_INT_MASK BIT_6 /* Frame Received */ -#define SCB_CX_INT_MASK BIT_7 /* CU eXecution w/ I-bit done */ -#define SCB_BACHELOR_INT_MASK BIT_2_7 /* 82558 interrupt mask bits */ - -#define SCB_GCR2_EEPROM_ACCESS_SEMAPHORE BIT_7 - -/* EEPROM bit definitions */ -/*- EEPROM control register bits */ -#define EEPROM_FLAG_ASF 0x8000 -#define EEPROM_FLAG_GCL 0x4000 - -#define EN_TRNF 0x10 /* Enable turnoff */ -#define EEDO 0x08 /* EEPROM data out */ -#define EEDI 0x04 /* EEPROM data in (set for writing data) */ -#define EECS 0x02 /* EEPROM chip select (1=hi, 0=lo) */ -#define EESK 0x01 /* EEPROM shift clock (1=hi, 0=lo) */ - -/*- EEPROM opcodes */ -#define EEPROM_READ_OPCODE 06 -#define EEPROM_WRITE_OPCODE 05 -#define EEPROM_ERASE_OPCODE 07 -#define EEPROM_EWEN_OPCODE 19 /* Erase/write enable */ -#define EEPROM_EWDS_OPCODE 16 /* Erase/write disable */ - -/*- EEPROM data locations */ -#define EEPROM_NODE_ADDRESS_BYTE_0 0 -#define EEPROM_COMPATIBILITY_WORD 3 -#define EEPROM_PWA_NO 8 -#define EEPROM_ID_WORD 0x0A -#define EEPROM_CONFIG_ASF 0x0D -#define EEPROM_SMBUS_ADDR 0x90 - -#define EEPROM_SUM 0xbaba - -// Zero Locking Algorithm definitions: -#define ZLOCK_ZERO_MASK 0x00F0 -#define ZLOCK_MAX_READS 50 -#define ZLOCK_SET_ZERO 0x2010 -#define ZLOCK_MAX_SLEEP 300 * HZ -#define ZLOCK_MAX_ERRORS 300 - -/* E100 Action Commands */ -#define CB_IA_ADDRESS 1 -#define CB_CONFIGURE 2 -#define CB_MULTICAST 3 -#define CB_TRANSMIT 4 -#define CB_LOAD_MICROCODE 5 -#define CB_LOAD_FILTER 8 -#define CB_MAX_NONTX_CMD 9 -#define CB_IPCB_TRANSMIT 9 - -/* Pre-defined Filter Bits */ -#define CB_FILTER_EL 0x80000000 -#define CB_FILTER_FIX 0x40000000 -#define CB_FILTER_ARP 0x08000000 -#define CB_FILTER_IA_MATCH 0x02000000 - -/* Command Block (CB) Field Definitions */ -/*- CB Command Word */ -#define CB_EL_BIT BIT_15 /* CB EL Bit */ -#define CB_S_BIT BIT_14 /* CB Suspend Bit */ -#define CB_I_BIT BIT_13 /* CB Interrupt Bit */ -#define CB_TX_SF_BIT BIT_3 /* TX CB Flexible Mode */ -#define CB_CMD_MASK BIT_0_3 /* CB 4-bit CMD Mask */ -#define CB_CID_DEFAULT (0x1f << 8) /* CB 5-bit CID (max value) */ - -/*- CB Status Word */ -#define CB_STATUS_MASK BIT_12_15 /* CB Status Mask (4-bits) */ -#define CB_STATUS_COMPLETE BIT_15 /* CB Complete Bit */ -#define CB_STATUS_OK BIT_13 /* CB OK Bit */ -#define CB_STATUS_VLAN BIT_12 /* CB Valn detected Bit */ -#define CB_STATUS_FAIL BIT_11 /* CB Fail (F) Bit */ - -/*misc command bits */ -#define CB_TX_EOF_BIT BIT_15 /* TX CB/TBD EOF Bit */ - -/* Config params */ -#define CB_CFIG_BYTE_COUNT 22 /* 22 config bytes */ -#define CB_CFIG_D102_BYTE_COUNT 10 - -/* Receive Frame Descriptor Fields */ - -/*- RFD Status Bits */ -#define RFD_RECEIVE_COLLISION BIT_0 /* Collision detected on Receive */ -#define RFD_IA_MATCH BIT_1 /* Indv Address Match Bit */ -#define RFD_RX_ERR BIT_4 /* RX_ERR pin on Phy was set */ -#define RFD_FRAME_TOO_SHORT BIT_7 /* Receive Frame Short */ -#define RFD_DMA_OVERRUN BIT_8 /* Receive DMA Overrun */ -#define RFD_NO_RESOURCES BIT_9 /* No Buffer Space */ -#define RFD_ALIGNMENT_ERROR BIT_10 /* Alignment Error */ -#define RFD_CRC_ERROR BIT_11 /* CRC Error */ -#define RFD_STATUS_OK BIT_13 /* RFD OK Bit */ -#define RFD_STATUS_COMPLETE BIT_15 /* RFD Complete Bit */ - -/*- RFD Command Bits*/ -#define RFD_EL_BIT BIT_15 /* RFD EL Bit */ -#define RFD_S_BIT BIT_14 /* RFD Suspend Bit */ -#define RFD_H_BIT BIT_4 /* Header RFD Bit */ -#define RFD_SF_BIT BIT_3 /* RFD Flexible Mode */ - -/*- RFD misc bits*/ -#define RFD_EOF_BIT BIT_15 /* RFD End-Of-Frame Bit */ -#define RFD_F_BIT BIT_14 /* RFD Buffer Fetch Bit */ -#define RFD_ACT_COUNT_MASK BIT_0_13 /* RFD Actual Count Mask */ - -/* Receive Buffer Descriptor Fields*/ -#define RBD_EOF_BIT BIT_15 /* RBD End-Of-Frame Bit */ -#define RBD_F_BIT BIT_14 /* RBD Buffer Fetch Bit */ -#define RBD_ACT_COUNT_MASK BIT_0_13 /* RBD Actual Count Mask */ - -#define SIZE_FIELD_MASK BIT_0_13 /* Size of the associated buffer */ -#define RBD_EL_BIT BIT_15 /* RBD EL Bit */ - -/* Self Test Results*/ -#define CB_SELFTEST_FAIL_BIT BIT_12 -#define CB_SELFTEST_DIAG_BIT BIT_5 -#define CB_SELFTEST_REGISTER_BIT BIT_3 -#define CB_SELFTEST_ROM_BIT BIT_2 - -#define CB_SELFTEST_ERROR_MASK ( \ - CB_SELFTEST_FAIL_BIT | CB_SELFTEST_DIAG_BIT | \ - CB_SELFTEST_REGISTER_BIT | CB_SELFTEST_ROM_BIT) - -/* adapter vendor & device ids */ -#define PCI_OHIO_BOARD 0x10f0 /* subdevice ID, Ohio dual port nic */ - -/* Values for PCI_REV_ID_REGISTER values */ -#define D101A4_REV_ID 4 /* 82558 A4 stepping */ -#define D101B0_REV_ID 5 /* 82558 B0 stepping */ -#define D101MA_REV_ID 8 /* 82559 A0 stepping */ -#define D101S_REV_ID 9 /* 82559S A-step */ -#define D102_REV_ID 12 -#define D102C_REV_ID 13 /* 82550 step C */ -#define D102E_REV_ID 15 - -/* ############Start of 82555 specific defines################## */ - -#define PHY_82555_LED_SWITCH_CONTROL 0x1b /* 82555 led switch control register */ - -/* 82555 led switch control reg. opcodes */ -#define PHY_82555_LED_NORMAL_CONTROL 0 // control back to the 8255X -#define PHY_82555_LED_DRIVER_CONTROL BIT_2 // the driver is in control -#define PHY_82555_LED_OFF BIT_2 // activity LED is off -#define PHY_82555_LED_ON_559 (BIT_0 | BIT_2) // activity LED is on for 559 and later -#define PHY_82555_LED_ON_PRE_559 (BIT_0 | BIT_1 | BIT_2) // activity LED is on for 558 and before - -// Describe the state of the phy led. -// needed for the function : 'e100_blink_timer' -enum led_state_e { - LED_OFF = 0, - LED_ON, -}; - -/* ############End of 82555 specific defines##################### */ - -#define RFD_PARSE_BIT BIT_3 -#define RFD_TCP_PACKET 0x00 -#define RFD_UDP_PACKET 0x01 -#define TCPUDP_CHECKSUM_BIT_VALID BIT_4 -#define TCPUDP_CHECKSUM_VALID BIT_5 -#define CHECKSUM_PROTOCOL_MASK 0x03 - -#define VLAN_SIZE 4 -#define CHKSUM_SIZE 2 -#define RFD_DATA_SIZE (ETH_FRAME_LEN + CHKSUM_SIZE + VLAN_SIZE) - -/* Bits for bdp->flags */ -#define DF_LINK_FC_CAP 0x00000001 /* Link is flow control capable */ -#define DF_CSUM_OFFLOAD 0x00000002 -#define DF_UCODE_LOADED 0x00000004 -#define USE_IPCB 0x00000008 /* set if using ipcb for transmits */ -#define IS_BACHELOR 0x00000010 /* set if 82558 or newer board */ -#define IS_ICH 0x00000020 -#define DF_SPEED_FORCED 0x00000040 /* set if speed is forced */ -#define LED_IS_ON 0x00000080 /* LED is turned ON by the driver */ -#define DF_LINK_FC_TX_ONLY 0x00000100 /* Received PAUSE frames are honored*/ - -typedef struct net_device_stats net_dev_stats_t; - -/* needed macros */ -/* These macros use the bdp pointer. If you use them it better be defined */ -#define PREV_TCB_USED(X) ((X).tail ? (X).tail - 1 : bdp->params.TxDescriptors - 1) -#define NEXT_TCB_TOUSE(X) ((((X) + 1) >= bdp->params.TxDescriptors) ? 0 : (X) + 1) -#define TCB_TO_USE(X) ((X).tail) -#define TCBS_AVAIL(X) (NEXT_TCB_TOUSE( NEXT_TCB_TOUSE((X).tail)) != (X).head) - -#define RFD_POINTER(skb,bdp) ((rfd_t *) (((unsigned char *)((skb)->data))-((bdp)->rfd_size))) - -/* ====================================================================== */ -/* 82557 */ -/* ====================================================================== */ - -/* Changed for 82558 enhancement */ -typedef struct _d101_scb_ext_t { - u32 scb_rx_dma_cnt; /* Rx DMA byte count */ - u8 scb_early_rx_int; /* Early Rx DMA byte count */ - u8 scb_fc_thld; /* Flow Control threshold */ - u8 scb_fc_xon_xoff; /* Flow Control XON/XOFF values */ - u8 scb_pmdr; /* Power Mgmt. Driver Reg */ -} d101_scb_ext __attribute__ ((__packed__)); - -/* Changed for 82559 enhancement */ -typedef struct _d101m_scb_ext_t { - u32 scb_rx_dma_cnt; /* Rx DMA byte count */ - u8 scb_early_rx_int; /* Early Rx DMA byte count */ - u8 scb_fc_thld; /* Flow Control threshold */ - u8 scb_fc_xon_xoff; /* Flow Control XON/XOFF values */ - u8 scb_pmdr; /* Power Mgmt. Driver Reg */ - u8 scb_gen_ctrl; /* General Control */ - u8 scb_gen_stat; /* General Status */ - u16 scb_reserved; /* Reserved */ - u32 scb_function_event; /* Cardbus Function Event */ - u32 scb_function_event_mask; /* Cardbus Function Mask */ - u32 scb_function_present_state; /* Cardbus Function state */ - u32 scb_force_event; /* Cardbus Force Event */ -} d101m_scb_ext __attribute__ ((__packed__)); - -/* Changed for 82550 enhancement */ -typedef struct _d102_scb_ext_t { - u32 scb_rx_dma_cnt; /* Rx DMA byte count */ - u8 scb_early_rx_int; /* Early Rx DMA byte count */ - u8 scb_fc_thld; /* Flow Control threshold */ - u8 scb_fc_xon_xoff; /* Flow Control XON/XOFF values */ - u8 scb_pmdr; /* Power Mgmt. Driver Reg */ - u8 scb_gen_ctrl; /* General Control */ - u8 scb_gen_stat; /* General Status */ - u8 scb_gen_ctrl2; - u8 scb_reserved; /* Reserved */ - u32 scb_scheduling_reg; - u32 scb_reserved2; - u32 scb_function_event; /* Cardbus Function Event */ - u32 scb_function_event_mask; /* Cardbus Function Mask */ - u32 scb_function_present_state; /* Cardbus Function state */ - u32 scb_force_event; /* Cardbus Force Event */ -} d102_scb_ext __attribute__ ((__packed__)); - -/* - * 82557 status control block. this will be memory mapped & will hang of the - * the bdp, which hangs of the bdp. This is the brain of it. - */ -typedef struct _scb_t { - u16 scb_status; /* SCB Status register */ - u8 scb_cmd_low; /* SCB Command register (low byte) */ - u8 scb_cmd_hi; /* SCB Command register (high byte) */ - u32 scb_gen_ptr; /* SCB General pointer */ - u32 scb_port; /* PORT register */ - u16 scb_flsh_cntrl; /* Flash Control register */ - u16 scb_eprm_cntrl; /* EEPROM control register */ - u32 scb_mdi_cntrl; /* MDI Control Register */ - /* Changed for 82558 enhancement */ - union { - u32 scb_rx_dma_cnt; /* Rx DMA byte count */ - d101_scb_ext d101_scb; /* 82558/9 specific fields */ - d101m_scb_ext d101m_scb; /* 82559 specific fields */ - d102_scb_ext d102_scb; - } scb_ext; -} scb_t __attribute__ ((__packed__)); - -/* Self test - * This is used to dump results of the self test - */ -typedef struct _self_test_t { - u32 st_sign; /* Self Test Signature */ - u32 st_result; /* Self Test Results */ -} self_test_t __attribute__ ((__packed__)); - -/* - * Statistical Counters - */ -/* 82557 counters */ -typedef struct _basic_cntr_t { - u32 xmt_gd_frames; /* Good frames transmitted */ - u32 xmt_max_coll; /* Fatal frames -- had max collisions */ - u32 xmt_late_coll; /* Fatal frames -- had a late coll. */ - u32 xmt_uruns; /* Xmit underruns (fatal or re-transmit) */ - u32 xmt_lost_crs; /* Frames transmitted without CRS */ - u32 xmt_deferred; /* Deferred transmits */ - u32 xmt_sngl_coll; /* Transmits that had 1 and only 1 coll. */ - u32 xmt_mlt_coll; /* Transmits that had multiple coll. */ - u32 xmt_ttl_coll; /* Transmits that had 1+ collisions. */ - u32 rcv_gd_frames; /* Good frames received */ - u32 rcv_crc_errs; /* Aligned frames that had a CRC error */ - u32 rcv_algn_errs; /* Receives that had alignment errors */ - u32 rcv_rsrc_err; /* Good frame dropped cuz no resources */ - u32 rcv_oruns; /* Overrun errors - bus was busy */ - u32 rcv_err_coll; /* Received frms. that encountered coll. */ - u32 rcv_shrt_frames; /* Received frames that were to short */ -} basic_cntr_t; - -/* 82558 extended statistic counters */ -typedef struct _ext_cntr_t { - u32 xmt_fc_frames; - u32 rcv_fc_frames; - u32 rcv_fc_unsupported; -} ext_cntr_t; - -/* 82559 TCO statistic counters */ -typedef struct _tco_cntr_t { - u16 xmt_tco_frames; - u16 rcv_tco_frames; -} tco_cntr_t; - -/* Structures to access thet physical dump area */ -/* Use one of these types, according to the statisitcal counters mode, - to cast the pointer to the physical dump area and access the cmd_complete - DWORD. */ - -/* 557-mode : only basic counters + cmd_complete */ -typedef struct _err_cntr_557_t { - basic_cntr_t basic_stats; - u32 cmd_complete; -} err_cntr_557_t; - -/* 558-mode : basic + extended counters + cmd_complete */ -typedef struct _err_cntr_558_t { - basic_cntr_t basic_stats; - ext_cntr_t extended_stats; - u32 cmd_complete; -} err_cntr_558_t; - -/* 559-mode : basic + extended + TCO counters + cmd_complete */ -typedef struct _err_cntr_559_t { - basic_cntr_t basic_stats; - ext_cntr_t extended_stats; - tco_cntr_t tco_stats; - u32 cmd_complete; -} err_cntr_559_t; - -/* This typedef defines the struct needed to hold the largest number of counters */ -typedef err_cntr_559_t max_counters_t; - -/* Different statistical-counters mode the controller may be in */ -typedef enum _stat_mode_t { - E100_BASIC_STATS = 0, /* 82557 stats : 16 counters / 16 dw */ - E100_EXTENDED_STATS, /* 82558 stats : 19 counters / 19 dw */ - E100_TCO_STATS /* 82559 stats : 21 counters / 20 dw */ -} stat_mode_t; - -/* dump statistical counters complete codes */ -#define DUMP_STAT_COMPLETED 0xA005 -#define DUMP_RST_STAT_COMPLETED 0xA007 - -/* Command Block (CB) Generic Header Structure*/ -typedef struct _cb_header_t { - u16 cb_status; /* Command Block Status */ - u16 cb_cmd; /* Command Block Command */ - u32 cb_lnk_ptr; /* Link To Next CB */ -} cb_header_t __attribute__ ((__packed__)); - -//* Individual Address Command Block (IA_CB)*/ -typedef struct _ia_cb_t { - cb_header_t ia_cb_hdr; - u8 ia_addr[ETH_ALEN]; -} ia_cb_t __attribute__ ((__packed__)); - -/* Configure Command Block (CONFIG_CB)*/ -typedef struct _config_cb_t { - cb_header_t cfg_cbhdr; - u8 cfg_byte[CB_CFIG_BYTE_COUNT + CB_CFIG_D102_BYTE_COUNT]; -} config_cb_t __attribute__ ((__packed__)); - -/* MultiCast Command Block (MULTICAST_CB)*/ -typedef struct _multicast_cb_t { - cb_header_t mc_cbhdr; - u16 mc_count; /* Number of multicast addresses */ - u8 mc_addr[(ETH_ALEN * MAX_MULTICAST_ADDRS)]; -} mltcst_cb_t __attribute__ ((__packed__)); - -#define UCODE_MAX_DWORDS 134 -/* Load Microcode Command Block (LOAD_UCODE_CB)*/ -typedef struct _load_ucode_cb_t { - cb_header_t load_ucode_cbhdr; - u32 ucode_dword[UCODE_MAX_DWORDS]; -} load_ucode_cb_t __attribute__ ((__packed__)); - -/* Load Programmable Filter Data*/ -typedef struct _filter_cb_t { - cb_header_t filter_cb_hdr; - u32 filter_data[MAX_FILTER]; -} filter_cb_t __attribute__ ((__packed__)); - -/* NON_TRANSMIT_CB -- Generic Non-Transmit Command Block - */ -typedef struct _nxmit_cb_t { - union { - config_cb_t config; - ia_cb_t setup; - load_ucode_cb_t load_ucode; - mltcst_cb_t multicast; - filter_cb_t filter; - } ntcb; -} nxmit_cb_t __attribute__ ((__packed__)); - -/*Block for queuing for postponed execution of the non-transmit commands*/ -typedef struct _nxmit_cb_entry_t { - struct list_head list_elem; - nxmit_cb_t *non_tx_cmd; - dma_addr_t dma_addr; - unsigned long expiration_time; -} nxmit_cb_entry_t; - -/* States for postponed non tx commands execution */ -typedef enum _non_tx_cmd_state_t { - E100_NON_TX_IDLE = 0, /* No queued NON-TX commands */ - E100_WAIT_TX_FINISH, /* Wait for completion of the TX activities */ - E100_WAIT_NON_TX_FINISH /* Wait for completion of the non TX command */ -} non_tx_cmd_state_t; - -/* some defines for the ipcb */ -#define IPCB_IP_CHECKSUM_ENABLE BIT_4 -#define IPCB_TCPUDP_CHECKSUM_ENABLE BIT_5 -#define IPCB_TCP_PACKET BIT_6 -#define IPCB_LARGESEND_ENABLE BIT_7 -#define IPCB_HARDWAREPARSING_ENABLE BIT_0 -#define IPCB_INSERTVLAN_ENABLE BIT_1 -#define IPCB_IP_ACTIVATION_DEFAULT IPCB_HARDWAREPARSING_ENABLE - -/* Transmit Buffer Descriptor (TBD)*/ -typedef struct _tbd_t { - u32 tbd_buf_addr; /* Physical Transmit Buffer Address */ - u16 tbd_buf_cnt; /* Actual Count Of Bytes */ - u16 padd; -} tbd_t __attribute__ ((__packed__)); - -/* d102 specific fields */ -typedef struct _tcb_ipcb_t { - u16 schedule_low; - u8 ip_schedule; - u8 ip_activation_high; - u16 vlan; - u8 ip_header_offset; - u8 tcp_header_offset; - union { - u32 sec_rec_phys_addr; - u32 tbd_zero_address; - } tbd_sec_addr; - union { - u16 sec_rec_size; - u16 tbd_zero_size; - } tbd_sec_size; - u16 total_tcp_payload; -} tcb_ipcb_t __attribute__ ((__packed__)); - -#define E100_TBD_ARRAY_SIZE (2+MAX_SKB_FRAGS) - -/* Transmit Command Block (TCB)*/ -struct _tcb_t { - cb_header_t tcb_hdr; - u32 tcb_tbd_ptr; /* TBD address */ - u16 tcb_cnt; /* Data Bytes In TCB past header */ - u8 tcb_thrshld; /* TX Threshold for FIFO Extender */ - u8 tcb_tbd_num; - - union { - tcb_ipcb_t ipcb; /* d102 ipcb fields */ - tbd_t tbd_array[E100_TBD_ARRAY_SIZE]; - } tcbu; - - /* From here onward we can dump anything we want as long as the - * size of the total structure is a multiple of a paragraph - * boundary ( i.e. -16 bit aligned ). - */ - tbd_t *tbd_ptr; - - u32 tcb_tbd_dflt_ptr; /* TBD address for non-segmented packet */ - u32 tcb_tbd_expand_ptr; /* TBD address for segmented packet */ - - struct sk_buff *tcb_skb; /* the associated socket buffer */ - dma_addr_t tcb_phys; /* phys addr of the TCB */ -} __attribute__ ((__packed__)); - -#define _TCB_T_ -typedef struct _tcb_t tcb_t; - -/* Receive Frame Descriptor (RFD) - will be using the simple model*/ -struct _rfd_t { - /* 8255x */ - cb_header_t rfd_header; - u32 rfd_rbd_ptr; /* Receive Buffer Descriptor Addr */ - u16 rfd_act_cnt; /* Number Of Bytes Received */ - u16 rfd_sz; /* Number Of Bytes In RFD */ - /* D102 aka Gamla */ - u16 vlanid; - u8 rcvparserstatus; - u8 reserved; - u16 securitystatus; - u8 checksumstatus; - u8 zerocopystatus; - u8 pad[8]; /* data should be 16 byte aligned */ - u8 data[RFD_DATA_SIZE]; - -} __attribute__ ((__packed__)); - -#define _RFD_T_ -typedef struct _rfd_t rfd_t; - -/* Receive Buffer Descriptor (RBD)*/ -typedef struct _rbd_t { - u16 rbd_act_cnt; /* Number Of Bytes Received */ - u16 rbd_filler; - u32 rbd_lnk_addr; /* Link To Next RBD */ - u32 rbd_rcb_addr; /* Receive Buffer Address */ - u16 rbd_sz; /* Receive Buffer Size */ - u16 rbd_filler1; -} rbd_t __attribute__ ((__packed__)); - -/* - * This structure is used to maintain a FIFO access to a resource that is - * maintained as a circular queue. The resource to be maintained is pointed - * to by the "data" field in the structure below. In this driver the TCBs', - * TBDs' & RFDs' are maintained as a circular queue & are managed thru this - * structure. - */ -typedef struct _buf_pool_t { - unsigned int head; /* index to first used resource */ - unsigned int tail; /* index to last used resource */ - void *data; /* points to resource pool */ -} buf_pool_t; - -/*Rx skb holding structure*/ -struct rx_list_elem { - struct list_head list_elem; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum next_cu_cmd_e { RESUME_NO_WAIT = 0, RESUME_WAIT, START_WAIT }; -enum zlock_state_e { ZLOCK_INITIAL, ZLOCK_READING, ZLOCK_SLEEPING }; -enum tx_queue_stop_type { LONG_STOP = 0, SHORT_STOP }; - -/* 64 bit aligned size */ -#define E100_SIZE_64A(X) ((sizeof(X) + 7) & ~0x7) - -typedef struct _bd_dma_able_t { - char selftest[E100_SIZE_64A(self_test_t)]; - char stats_counters[E100_SIZE_64A(max_counters_t)]; -} bd_dma_able_t; - -/* bit masks for bool parameters */ -#define PRM_XSUMRX 0x00000001 -#define PRM_UCODE 0x00000002 -#define PRM_FC 0x00000004 -#define PRM_IFS 0x00000008 -#define PRM_BUNDLE_SMALL 0x00000010 - -struct cfg_params { - int e100_speed_duplex; - int RxDescriptors; - int TxDescriptors; - int IntDelay; - int BundleMax; - int ber; - u32 b_params; -}; -struct ethtool_lpbk_data{ - dma_addr_t dma_handle; - tcb_t *tcb; - rfd_t *rfd; - -}; - -struct e100_private { - struct vlan_group *vlgrp; - u32 flags; /* board management flags */ - u32 tx_per_underrun; /* number of good tx frames per underrun */ - unsigned int tx_count; /* count of tx frames, so we can request an interrupt */ - u8 tx_thld; /* stores transmit threshold */ - u16 eeprom_size; - u32 pwa_no; /* PWA: xxxxxx-0xx */ - u8 perm_node_address[ETH_ALEN]; - struct list_head active_rx_list; /* list of rx buffers */ - struct list_head rx_struct_pool; /* pool of rx buffer struct headers */ - u16 rfd_size; /* size of the adapter's RFD struct */ - int skb_req; /* number of skbs neede by the adapter */ - u8 intr_mask; /* mask for interrupt status */ - - void *dma_able; /* dma allocated structs */ - dma_addr_t dma_able_phys; - self_test_t *selftest; /* pointer to self test area */ - dma_addr_t selftest_phys; /* phys addr of selftest */ - max_counters_t *stats_counters; /* pointer to stats table */ - dma_addr_t stat_cnt_phys; /* phys addr of stat counter area */ - - stat_mode_t stat_mode; /* statistics mode: extended, TCO, basic */ - scb_t *scb; /* memory mapped ptr to 82557 scb */ - - tcb_t *last_tcb; /* pointer to last tcb sent */ - buf_pool_t tcb_pool; /* adapter's TCB array */ - dma_addr_t tcb_phys; /* phys addr of start of TCBs */ - - u16 cur_line_speed; - u16 cur_dplx_mode; - - struct net_device *device; - struct pci_dev *pdev; - struct driver_stats drv_stats; - - u8 rev_id; /* adapter PCI revision ID */ - - unsigned int phy_addr; /* address of PHY component */ - unsigned int PhyId; /* ID of PHY component */ - unsigned int PhyState; /* state for the fix squelch algorithm */ - unsigned int PhyDelay; /* delay for the fix squelch algorithm */ - - /* Lock defintions for the driver */ - spinlock_t bd_lock; /* board lock */ - spinlock_t bd_non_tx_lock; /* Non transmit command lock */ - spinlock_t config_lock; /* config block lock */ - spinlock_t mdi_access_lock; /* mdi lock */ - - struct timer_list watchdog_timer; /* watchdog timer id */ - - /* non-tx commands parameters */ - struct timer_list nontx_timer_id; /* non-tx timer id */ - struct list_head non_tx_cmd_list; - non_tx_cmd_state_t non_tx_command_state; - nxmit_cb_entry_t *same_cmd_entry[CB_MAX_NONTX_CMD]; - - enum next_cu_cmd_e next_cu_cmd; - - /* Zero Locking Algorithm data members */ - enum zlock_state_e zlock_state; - u8 zlock_read_data[16]; /* number of times each value 0-15 was read */ - u16 zlock_read_cnt; /* counts number of reads */ - ulong zlock_sleep_cnt; /* keeps track of "sleep" time */ - - u8 config[CB_CFIG_BYTE_COUNT + CB_CFIG_D102_BYTE_COUNT]; - - /* IFS params */ - u8 ifs_state; - u8 ifs_value; - - struct cfg_params params; /* adapter's command line parameters */ - - u32 speed_duplex_caps; /* adapter's speed/duplex capabilities */ - - /* WOL params for ethtool */ - u32 wolsupported; - u32 wolopts; - u16 ip_lbytes; - struct ethtool_lpbk_data loopback; - struct timer_list blink_timer; /* led blink timer id */ - -#ifdef CONFIG_PM - u32 pci_state[16]; -#endif - char ifname[IFNAMSIZ]; -#ifdef E100_CU_DEBUG - u8 last_cmd; - u8 last_sub_cmd; -#endif -}; - -#define E100_AUTONEG 0 -#define E100_SPEED_10_HALF 1 -#define E100_SPEED_10_FULL 2 -#define E100_SPEED_100_HALF 3 -#define E100_SPEED_100_FULL 4 - -/********* function prototypes *************/ -extern void e100_isolate_driver(struct e100_private *bdp); -extern void e100_sw_reset(struct e100_private *bdp, u32 reset_cmd); -extern u8 e100_start_cu(struct e100_private *bdp, tcb_t *tcb); -extern void e100_free_non_tx_cmd(struct e100_private *bdp, - nxmit_cb_entry_t *non_tx_cmd); -extern nxmit_cb_entry_t *e100_alloc_non_tx_cmd(struct e100_private *bdp); -extern unsigned char e100_exec_non_cu_cmd(struct e100_private *bdp, - nxmit_cb_entry_t *cmd); -extern unsigned char e100_selftest(struct e100_private *bdp, u32 *st_timeout, - u32 *st_result); -extern unsigned char e100_get_link_state(struct e100_private *bdp); -extern unsigned char e100_wait_scb(struct e100_private *bdp); - -extern void e100_deisolate_driver(struct e100_private *bdp, u8 full_reset); -extern unsigned char e100_configure_device(struct e100_private *bdp); -#ifdef E100_CU_DEBUG -extern unsigned char e100_cu_unknown_state(struct e100_private *bdp); -#endif - -static inline u16 SKB_RFD_STATUS(struct sk_buff *skb, struct e100_private *bdp) -{ - u16 status; - rfd_t *rfd = RFD_POINTER(skb, bdp); - rfd = map_domain_mem(__pa(rfd)); - status = rfd->rfd_header.cb_status; - unmap_domain_mem(rfd); - return status; -} - -#define ROM_TEST_FAIL 0x01 -#define REGISTER_TEST_FAIL 0x02 -#define SELF_TEST_FAIL 0x04 -#define TEST_TIMEOUT 0x08 - -enum test_offsets { - E100_EEPROM_TEST_FAIL = 0, - E100_CHIP_TIMEOUT, - E100_ROM_TEST_FAIL, - E100_REG_TEST_FAIL, - E100_MAC_TEST_FAIL, - E100_LPBK_MAC_FAIL, - E100_LPBK_PHY_FAIL, - E100_MAX_TEST_RES -}; - -#endif diff --git a/xen/drivers/net/e100/e100_config.c b/xen/drivers/net/e100/e100_config.c deleted file mode 100644 index d9df35677a..0000000000 --- a/xen/drivers/net/e100/e100_config.c +++ /dev/null @@ -1,639 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -/********************************************************************** -* * -* INTEL CORPORATION * -* * -* This software is supplied under the terms of the license included * -* above. All use of this driver must be in accordance with the terms * -* of that license. * -* * -* Module Name: e100_config.c * -* * -* Abstract: Functions for configuring the network adapter. * -* * -* Environment: This file is intended to be specific to the Linux * -* operating system. * -* * -**********************************************************************/ -#include "e100_config.h" - -static void e100_config_long_rx(struct e100_private *bdp, unsigned char enable); - -static const u8 def_config[] = { - CB_CFIG_BYTE_COUNT, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x32, 0x07, 0x01, - 0x00, 0x2e, 0x00, 0x60, 0x00, 0xf2, 0xc8, 0x00, - 0x40, 0xf2, 0x80, 0x3f, 0x05 -}; - -/** - * e100_config_init_82557 - config the 82557 adapter - * @bdp: atapter's private data struct - * - * This routine will initialize the 82557 configure block. - * All other init functions will only set values that are - * different from the 82557 default. - */ -static void __devinit -e100_config_init_82557(struct e100_private *bdp) -{ - /* initialize config block */ - memcpy(bdp->config, def_config, sizeof (def_config)); - bdp->config[0] = CB_CFIG_BYTE_COUNT; /* just in case */ - - e100_config_ifs(bdp); - - /* - * Enable extended statistical counters (82558 and up) and TCO counters - * (82559 and up) and set the statistical counters' mode in bdp - * - * stat. mode | TCO stat. bit (2) | Extended stat. bit (5) - * ------------------------------------------------------------------ - * Basic (557) | 0 | 1 - * ------------------------------------------------------------------ - * Extended (558) | 0 | 0 - * ------------------------------------------------------------------ - * TCO (559) | 1 | 1 - * ------------------------------------------------------------------ - * Reserved | 1 | 0 - * ------------------------------------------------------------------ - */ - bdp->config[6] &= ~CB_CFIG_TCO_STAT; - bdp->config[6] |= CB_CFIG_EXT_STAT_DIS; - bdp->stat_mode = E100_BASIC_STATS; - - /* Setup for MII or 503 operation. The CRS+CDT bit should only be set */ - /* when operating in 503 mode. */ - if (bdp->phy_addr == 32) { - bdp->config[8] &= ~CB_CFIG_503_MII; - bdp->config[15] |= CB_CFIG_CRS_OR_CDT; - } else { - bdp->config[8] |= CB_CFIG_503_MII; - bdp->config[15] &= ~CB_CFIG_CRS_OR_CDT; - } - - e100_config_fc(bdp); - e100_config_force_dplx(bdp); - e100_config_promisc(bdp, false); - e100_config_mulcast_enbl(bdp, false); -} - -static void __devinit -e100_config_init_82558(struct e100_private *bdp) -{ - /* MWI enable. This should be turned on only if the adapter is a 82558/9 - * and if the PCI command reg. has enabled the MWI bit. */ - bdp->config[3] |= CB_CFIG_MWI_EN; - - bdp->config[6] &= ~CB_CFIG_EXT_TCB_DIS; - - if (bdp->rev_id >= D101MA_REV_ID) { - /* this is 82559 and up - enable TCO counters */ - bdp->config[6] |= CB_CFIG_TCO_STAT; - bdp->config[6] |= CB_CFIG_EXT_STAT_DIS; - bdp->stat_mode = E100_TCO_STATS; - - if ((bdp->rev_id < D102_REV_ID) && - (bdp->params.b_params & PRM_XSUMRX) && - (bdp->pdev->device != 0x1209)) { - - bdp->flags |= DF_CSUM_OFFLOAD; - bdp->config[9] |= 1; - } - } else { - /* this is 82558 */ - bdp->config[6] &= ~CB_CFIG_TCO_STAT; - bdp->config[6] &= ~CB_CFIG_EXT_STAT_DIS; - bdp->stat_mode = E100_EXTENDED_STATS; - } - - e100_config_long_rx(bdp, true); -} - -static void __devinit -e100_config_init_82550(struct e100_private *bdp) -{ - /* The D102 chip allows for 32 config bytes. This value is - * supposed to be in Byte 0. Just add the extra bytes to - * what was already setup in the block. */ - bdp->config[0] += CB_CFIG_D102_BYTE_COUNT; - - /* now we need to enable the extended RFD. When this is - * enabled, the immediated receive data buffer starts at offset - * 32 from the RFD base address, instead of at offset 16. */ - bdp->config[7] |= CB_CFIG_EXTENDED_RFD; - - /* put the chip into D102 receive mode. This is necessary - * for any parsing and offloading features. */ - bdp->config[22] = CB_CFIG_RECEIVE_GAMLA_MODE; - - /* set the flag if checksum offloading was enabled */ - if (bdp->params.b_params & PRM_XSUMRX) { - bdp->flags |= DF_CSUM_OFFLOAD; - } -} - -/* Initialize the adapter's configure block */ -void __devinit -e100_config_init(struct e100_private *bdp) -{ - e100_config_init_82557(bdp); - - if (bdp->flags & IS_BACHELOR) - e100_config_init_82558(bdp); - - if (bdp->rev_id >= D102_REV_ID) - e100_config_init_82550(bdp); -} - -/** - * e100_force_config - force a configure command - * @bdp: atapter's private data struct - * - * This routine will force a configure command to the adapter. - * The command will be executed in polled mode as interrupts - * are _disabled_ at this time. - * - * Returns: - * true: if the configure command was successfully issued and completed - * false: otherwise - */ -unsigned char -e100_force_config(struct e100_private *bdp) -{ - spin_lock_bh(&(bdp->config_lock)); - - bdp->config[0] = CB_CFIG_BYTE_COUNT; - if (bdp->rev_id >= D102_REV_ID) { - /* The D102 chip allows for 32 config bytes. This value is - supposed to be in Byte 0. Just add the extra bytes to - what was already setup in the block. */ - bdp->config[0] += CB_CFIG_D102_BYTE_COUNT; - } - - spin_unlock_bh(&(bdp->config_lock)); - - // although we call config outside the lock, there is no - // race condition because config byte count has maximum value - return e100_config(bdp); -} - -/** - * e100_config - issue a configure command - * @bdp: atapter's private data struct - * - * This routine will issue a configure command to the 82557. - * This command will be executed in polled mode as interrupts - * are _disabled_ at this time. - * - * Returns: - * true: if the configure command was successfully issued and completed - * false: otherwise - */ -unsigned char -e100_config(struct e100_private *bdp) -{ - cb_header_t *pntcb_hdr; - unsigned char res = true; - nxmit_cb_entry_t *cmd; - - if (bdp->config[0] == 0) { - goto exit; - } - - if ((cmd = e100_alloc_non_tx_cmd(bdp)) == NULL) { - res = false; - goto exit; - } - - pntcb_hdr = (cb_header_t *) cmd->non_tx_cmd; - pntcb_hdr->cb_cmd = __constant_cpu_to_le16(CB_CONFIGURE); - - spin_lock_bh(&bdp->config_lock); - - if (bdp->config[0] < CB_CFIG_MIN_PARAMS) { - bdp->config[0] = CB_CFIG_MIN_PARAMS; - } - - /* Copy the device's config block to the device's memory */ - memcpy(cmd->non_tx_cmd->ntcb.config.cfg_byte, bdp->config, - bdp->config[0]); - /* reset number of bytes to config next time */ - bdp->config[0] = 0; - - spin_unlock_bh(&bdp->config_lock); - - res = e100_exec_non_cu_cmd(bdp, cmd); - -exit: - if (netif_running(bdp->device)) - netif_wake_queue(bdp->device); - return res; -} - -/** - * e100_config_fc - config flow-control state - * @bdp: adapter's private data struct - * - * This routine will enable or disable flow control support in the adapter's - * config block. Flow control will be enable only if requested using the command - * line option, and if the link is flow-contorl capable (both us and the link - * partner). But, if link partner is capable of autoneg, but not capable of - * flow control, received PAUSE frames are still honored. - */ -void -e100_config_fc(struct e100_private *bdp) -{ - unsigned char enable = false; - /* 82557 doesn't support fc. Don't touch this option */ - if (!(bdp->flags & IS_BACHELOR)) - return; - - /* Enable fc if requested and if the link supports it */ - if ((bdp->params.b_params & PRM_FC) && (bdp->flags & - (DF_LINK_FC_CAP | DF_LINK_FC_TX_ONLY))) { - enable = true; - } - - spin_lock_bh(&(bdp->config_lock)); - - if (enable) { - if (bdp->flags & DF_LINK_FC_TX_ONLY) { - /* If link partner is capable of autoneg, but */ - /* not capable of flow control, Received PAUSE */ - /* frames are still honored, i.e., */ - /* transmitted frames would be paused by */ - /* incoming PAUSE frames */ - bdp->config[16] = DFLT_NO_FC_DELAY_LSB; - bdp->config[17] = DFLT_NO_FC_DELAY_MSB; - bdp->config[19] &= ~(CB_CFIG_FC_RESTOP | CB_CFIG_FC_RESTART); - bdp->config[19] |= CB_CFIG_FC_REJECT; - bdp->config[19] &= ~CB_CFIG_TX_FC_DIS; - } else { - bdp->config[16] = DFLT_FC_DELAY_LSB; - bdp->config[17] = DFLT_FC_DELAY_MSB; - bdp->config[19] |= CB_CFIG_FC_OPTS; - bdp->config[19] &= ~CB_CFIG_TX_FC_DIS; - } - } else { - bdp->config[16] = DFLT_NO_FC_DELAY_LSB; - bdp->config[17] = DFLT_NO_FC_DELAY_MSB; - bdp->config[19] &= ~CB_CFIG_FC_OPTS; - bdp->config[19] |= CB_CFIG_TX_FC_DIS; - } - E100_CONFIG(bdp, 19); - spin_unlock_bh(&(bdp->config_lock)); - - return; -} - -/** - * e100_config_promisc - configure promiscuous mode - * @bdp: atapter's private data struct - * @enable: should we enable this option or not - * - * This routine will enable or disable promiscuous mode - * in the adapter's config block. - */ -void -e100_config_promisc(struct e100_private *bdp, unsigned char enable) -{ - spin_lock_bh(&(bdp->config_lock)); - - /* if in promiscuous mode, save bad frames */ - if (enable) { - - if (!(bdp->config[6] & CB_CFIG_SAVE_BAD_FRAMES)) { - bdp->config[6] |= CB_CFIG_SAVE_BAD_FRAMES; - E100_CONFIG(bdp, 6); - } - - if (bdp->config[7] & (u8) BIT_0) { - bdp->config[7] &= (u8) (~BIT_0); - E100_CONFIG(bdp, 7); - } - - if (!(bdp->config[15] & CB_CFIG_PROMISCUOUS)) { - bdp->config[15] |= CB_CFIG_PROMISCUOUS; - E100_CONFIG(bdp, 15); - } - - } else { /* not in promiscuous mode */ - - if (bdp->config[6] & CB_CFIG_SAVE_BAD_FRAMES) { - bdp->config[6] &= ~CB_CFIG_SAVE_BAD_FRAMES; - E100_CONFIG(bdp, 6); - } - - if (!(bdp->config[7] & (u8) BIT_0)) { - bdp->config[7] |= (u8) (BIT_0); - E100_CONFIG(bdp, 7); - } - - if (bdp->config[15] & CB_CFIG_PROMISCUOUS) { - bdp->config[15] &= ~CB_CFIG_PROMISCUOUS; - E100_CONFIG(bdp, 15); - } - } - - spin_unlock_bh(&(bdp->config_lock)); -} - -/** - * e100_config_mulcast_enbl - configure allmulti mode - * @bdp: atapter's private data struct - * @enable: should we enable this option or not - * - * This routine will enable or disable reception of all multicast packets - * in the adapter's config block. - */ -void -e100_config_mulcast_enbl(struct e100_private *bdp, unsigned char enable) -{ - spin_lock_bh(&(bdp->config_lock)); - - /* this flag is used to enable receiving all multicast packet */ - if (enable) { - if (!(bdp->config[21] & CB_CFIG_MULTICAST_ALL)) { - bdp->config[21] |= CB_CFIG_MULTICAST_ALL; - E100_CONFIG(bdp, 21); - } - - } else { - if (bdp->config[21] & CB_CFIG_MULTICAST_ALL) { - bdp->config[21] &= ~CB_CFIG_MULTICAST_ALL; - E100_CONFIG(bdp, 21); - } - } - - spin_unlock_bh(&(bdp->config_lock)); -} - -/** - * e100_config_ifs - configure the IFS parameter - * @bdp: atapter's private data struct - * - * This routine will configure the adaptive IFS value - * in the adapter's config block. IFS values are only - * relevant in half duplex, so set to 0 in full duplex. - */ -void -e100_config_ifs(struct e100_private *bdp) -{ - u8 value = 0; - - spin_lock_bh(&(bdp->config_lock)); - - /* IFS value is only needed to be specified at half-duplex mode */ - if (bdp->cur_dplx_mode == HALF_DUPLEX) { - value = (u8) bdp->ifs_value; - } - - if (bdp->config[2] != value) { - bdp->config[2] = value; - E100_CONFIG(bdp, 2); - } - - spin_unlock_bh(&(bdp->config_lock)); -} - -/** - * e100_config_force_dplx - configure the forced full duplex mode - * @bdp: atapter's private data struct - * - * This routine will enable or disable force full duplex - * in the adapter's config block. If the PHY is 503, and - * the duplex is full, consider the adapter forced. - */ -void -e100_config_force_dplx(struct e100_private *bdp) -{ - spin_lock_bh(&(bdp->config_lock)); - - /* We must force full duplex on if we are using PHY 0, and we are */ - /* supposed to run in FDX mode. We do this because the e100 has only */ - /* one FDX# input pin, and that pin will be connected to PHY 1. */ - /* Changed the 'if' condition below to fix performance problem * at 10 - * full. The Phy was getting forced to full duplex while the MAC * was - * not, because the cur_dplx_mode was not being set to 2 by SetupPhy. * - * This is how the condition was, initially. * This has been changed so - * that the MAC gets forced to full duplex * simply if the user has - * forced full duplex. * * if (( bdp->phy_addr == 0 ) && ( - * bdp->cur_dplx_mode == 2 )) */ - /* The rest of the fix is in the PhyDetect code. */ - if ((bdp->params.e100_speed_duplex == E100_SPEED_10_FULL) || - (bdp->params.e100_speed_duplex == E100_SPEED_100_FULL) || - ((bdp->phy_addr == 32) && (bdp->cur_dplx_mode == FULL_DUPLEX))) { - if (!(bdp->config[19] & (u8) CB_CFIG_FORCE_FDX)) { - bdp->config[19] |= (u8) CB_CFIG_FORCE_FDX; - E100_CONFIG(bdp, 19); - } - - } else { - if (bdp->config[19] & (u8) CB_CFIG_FORCE_FDX) { - bdp->config[19] &= (u8) (~CB_CFIG_FORCE_FDX); - E100_CONFIG(bdp, 19); - } - } - - spin_unlock_bh(&(bdp->config_lock)); -} - -/** - * e100_config_long_rx - * @bdp: atapter's private data struct - * @enable: should we enable this option or not - * - * This routine will enable or disable reception of larger packets. - * This is needed by VLAN implementations. - */ -static void -e100_config_long_rx(struct e100_private *bdp, unsigned char enable) -{ - if (enable) { - if (!(bdp->config[18] & CB_CFIG_LONG_RX_OK)) { - bdp->config[18] |= CB_CFIG_LONG_RX_OK; - E100_CONFIG(bdp, 18); - } - - } else { - if ((bdp->config[18] & CB_CFIG_LONG_RX_OK)) { - bdp->config[18] &= ~CB_CFIG_LONG_RX_OK; - E100_CONFIG(bdp, 18); - } - } -} - -/** - * e100_config_wol - * @bdp: atapter's private data struct - * - * This sets configuration options for PHY and Magic Packet WoL - */ -void -e100_config_wol(struct e100_private *bdp) -{ - spin_lock_bh(&(bdp->config_lock)); - - if (bdp->wolopts & WAKE_PHY) { - bdp->config[9] |= CB_LINK_STATUS_WOL; - } - else { - /* Disable PHY WoL */ - bdp->config[9] &= ~CB_LINK_STATUS_WOL; - } - - if (bdp->wolopts & WAKE_MAGIC) { - bdp->config[19] &= ~CB_DISABLE_MAGPAK_WAKE; - } - else { - /* Disable Magic Packet WoL */ - bdp->config[19] |= CB_DISABLE_MAGPAK_WAKE; - } - - E100_CONFIG(bdp, 19); - spin_unlock_bh(&(bdp->config_lock)); -} - -void -e100_config_vlan_drop(struct e100_private *bdp, unsigned char enable) -{ - spin_lock_bh(&(bdp->config_lock)); - if (enable) { - if (!(bdp->config[22] & CB_CFIG_VLAN_DROP_ENABLE)) { - bdp->config[22] |= CB_CFIG_VLAN_DROP_ENABLE; - E100_CONFIG(bdp, 22); - } - - } else { - if ((bdp->config[22] & CB_CFIG_VLAN_DROP_ENABLE)) { - bdp->config[22] &= ~CB_CFIG_VLAN_DROP_ENABLE; - E100_CONFIG(bdp, 22); - } - } - spin_unlock_bh(&(bdp->config_lock)); -} - -/** - * e100_config_loopback_mode - * @bdp: atapter's private data struct - * @mode: loopback mode(phy/mac/none) - * - */ -unsigned char -e100_config_loopback_mode(struct e100_private *bdp, u8 mode) -{ - unsigned char bc_changed = false; - u8 config_byte; - - spin_lock_bh(&(bdp->config_lock)); - - switch (mode) { - case NO_LOOPBACK: - config_byte = CB_CFIG_LOOPBACK_NORMAL; - break; - case MAC_LOOPBACK: - config_byte = CB_CFIG_LOOPBACK_INTERNAL; - break; - case PHY_LOOPBACK: - config_byte = CB_CFIG_LOOPBACK_EXTERNAL; - break; - default: - printk(KERN_NOTICE "e100: e100_config_loopback_mode: " - "Invalid argument 'mode': %d\n", mode); - goto exit; - } - - if ((bdp->config[10] & CB_CFIG_LOOPBACK_MODE) != config_byte) { - - bdp->config[10] &= (~CB_CFIG_LOOPBACK_MODE); - bdp->config[10] |= config_byte; - E100_CONFIG(bdp, 10); - bc_changed = true; - } - -exit: - spin_unlock_bh(&(bdp->config_lock)); - return bc_changed; -} -unsigned char -e100_config_tcb_ext_enable(struct e100_private *bdp, unsigned char enable) -{ - unsigned char bc_changed = false; - - spin_lock_bh(&(bdp->config_lock)); - - if (enable) { - if (bdp->config[6] & CB_CFIG_EXT_TCB_DIS) { - - bdp->config[6] &= (~CB_CFIG_EXT_TCB_DIS); - E100_CONFIG(bdp, 6); - bc_changed = true; - } - - } else { - if (!(bdp->config[6] & CB_CFIG_EXT_TCB_DIS)) { - - bdp->config[6] |= CB_CFIG_EXT_TCB_DIS; - E100_CONFIG(bdp, 6); - bc_changed = true; - } - } - spin_unlock_bh(&(bdp->config_lock)); - - return bc_changed; -} -unsigned char -e100_config_dynamic_tbd(struct e100_private *bdp, unsigned char enable) -{ - unsigned char bc_changed = false; - - spin_lock_bh(&(bdp->config_lock)); - - if (enable) { - if (!(bdp->config[7] & CB_CFIG_DYNTBD_EN)) { - - bdp->config[7] |= CB_CFIG_DYNTBD_EN; - E100_CONFIG(bdp, 7); - bc_changed = true; - } - - } else { - if (bdp->config[7] & CB_CFIG_DYNTBD_EN) { - - bdp->config[7] &= (~CB_CFIG_DYNTBD_EN); - E100_CONFIG(bdp, 7); - bc_changed = true; - } - } - spin_unlock_bh(&(bdp->config_lock)); - - return bc_changed; -} - diff --git a/xen/drivers/net/e100/e100_config.h b/xen/drivers/net/e100/e100_config.h deleted file mode 100644 index 5d1e194ff2..0000000000 --- a/xen/drivers/net/e100/e100_config.h +++ /dev/null @@ -1,167 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -#ifndef _E100_CONFIG_INC_ -#define _E100_CONFIG_INC_ - -#include "e100.h" - -#define E100_CONFIG(bdp, X) ((bdp)->config[0] = max_t(u8, (bdp)->config[0], (X)+1)) - -#define CB_CFIG_MIN_PARAMS 8 - -/* byte 0 bit definitions*/ -#define CB_CFIG_BYTE_COUNT_MASK BIT_0_5 /* Byte count occupies bit 5-0 */ - -/* byte 1 bit definitions*/ -#define CB_CFIG_RXFIFO_LIMIT_MASK BIT_0_4 /* RxFifo limit mask */ -#define CB_CFIG_TXFIFO_LIMIT_MASK BIT_4_7 /* TxFifo limit mask */ - -/* byte 2 bit definitions -- ADAPTIVE_IFS*/ - -/* word 3 bit definitions -- RESERVED*/ -/* Changed for 82558 enhancements */ -/* byte 3 bit definitions */ -#define CB_CFIG_MWI_EN BIT_0 /* Enable MWI on PCI bus */ -#define CB_CFIG_TYPE_EN BIT_1 /* Type Enable */ -#define CB_CFIG_READAL_EN BIT_2 /* Enable Read Align */ -#define CB_CFIG_TERMCL_EN BIT_3 /* Cache line write */ - -/* byte 4 bit definitions*/ -#define CB_CFIG_RX_MIN_DMA_MASK BIT_0_6 /* Rx minimum DMA count mask */ - -/* byte 5 bit definitions*/ -#define CB_CFIG_TX_MIN_DMA_MASK BIT_0_6 /* Tx minimum DMA count mask */ -#define CB_CFIG_DMBC_EN BIT_7 /* Enable Tx/Rx min. DMA counts */ - -/* Changed for 82558 enhancements */ -/* byte 6 bit definitions*/ -#define CB_CFIG_LATE_SCB BIT_0 /* Update SCB After New Tx Start */ -#define CB_CFIG_DIRECT_DMA_DIS BIT_1 /* Direct DMA mode */ -#define CB_CFIG_TNO_INT BIT_2 /* Tx Not OK Interrupt */ -#define CB_CFIG_TCO_STAT BIT_2 /* TCO statistics in 559 and above */ -#define CB_CFIG_CI_INT BIT_3 /* Command Complete Interrupt */ -#define CB_CFIG_EXT_TCB_DIS BIT_4 /* Extended TCB */ -#define CB_CFIG_EXT_STAT_DIS BIT_5 /* Extended Stats */ -#define CB_CFIG_SAVE_BAD_FRAMES BIT_7 /* Save Bad Frames Enabled */ - -/* byte 7 bit definitions*/ -#define CB_CFIG_DISC_SHORT_FRAMES BIT_0 /* Discard Short Frames */ -#define CB_CFIG_DYNTBD_EN BIT_7 /* Enable dynamic TBD */ -/* Enable extended RFD's on D102 */ -#define CB_CFIG_EXTENDED_RFD BIT_5 - -/* byte 8 bit definitions*/ -#define CB_CFIG_503_MII BIT_0 /* 503 vs. MII mode */ - -/* byte 9 bit definitions -- pre-defined all zeros*/ -#define CB_LINK_STATUS_WOL BIT_5 - -/* byte 10 bit definitions*/ -#define CB_CFIG_NO_SRCADR BIT_3 /* No Source Address Insertion */ -#define CB_CFIG_PREAMBLE_LEN BIT_4_5 /* Preamble Length */ -#define CB_CFIG_LOOPBACK_MODE BIT_6_7 /* Loopback Mode */ -#define CB_CFIG_LOOPBACK_NORMAL 0 -#define CB_CFIG_LOOPBACK_INTERNAL BIT_6 -#define CB_CFIG_LOOPBACK_EXTERNAL BIT_6_7 - -/* byte 11 bit definitions*/ -#define CB_CFIG_LINEAR_PRIORITY BIT_0_2 /* Linear Priority */ - -/* byte 12 bit definitions*/ -#define CB_CFIG_LINEAR_PRI_MODE BIT_0 /* Linear Priority mode */ -#define CB_CFIG_IFS_MASK BIT_4_7 /* Interframe Spacing mask */ - -/* byte 13 bit definitions -- pre-defined all zeros*/ - -/* byte 14 bit definitions -- pre-defined 0xf2*/ - -/* byte 15 bit definitions*/ -#define CB_CFIG_PROMISCUOUS BIT_0 /* Promiscuous Mode Enable */ -#define CB_CFIG_BROADCAST_DIS BIT_1 /* Broadcast Mode Disable */ -#define CB_CFIG_CRS_OR_CDT BIT_7 /* CRS Or CDT */ - -/* byte 16 bit definitions -- pre-defined all zeros*/ -#define DFLT_FC_DELAY_LSB 0x1f /* Delay for outgoing Pause frames */ -#define DFLT_NO_FC_DELAY_LSB 0x00 /* no flow control default value */ - -/* byte 17 bit definitions -- pre-defined 0x40*/ -#define DFLT_FC_DELAY_MSB 0x01 /* Delay for outgoing Pause frames */ -#define DFLT_NO_FC_DELAY_MSB 0x40 /* no flow control default value */ - -/* byte 18 bit definitions*/ -#define CB_CFIG_STRIPPING BIT_0 /* Padding Disabled */ -#define CB_CFIG_PADDING BIT_1 /* Padding Disabled */ -#define CB_CFIG_CRC_IN_MEM BIT_2 /* Transfer CRC To Memory */ - -/* byte 19 bit definitions*/ -#define CB_CFIG_TX_ADDR_WAKE BIT_0 /* Address Wakeup */ -#define CB_DISABLE_MAGPAK_WAKE BIT_1 /* Magic Packet Wakeup disable */ -/* Changed TX_FC_EN to TX_FC_DIS because 0 enables, 1 disables. Jul 8, 1999 */ -#define CB_CFIG_TX_FC_DIS BIT_2 /* Tx Flow Control Disable */ -#define CB_CFIG_FC_RESTOP BIT_3 /* Rx Flow Control Restop */ -#define CB_CFIG_FC_RESTART BIT_4 /* Rx Flow Control Restart */ -#define CB_CFIG_FC_REJECT BIT_5 /* Rx Flow Control Restart */ -#define CB_CFIG_FC_OPTS (CB_CFIG_FC_RESTOP | CB_CFIG_FC_RESTART | CB_CFIG_FC_REJECT) - -/* end 82558/9 specifics */ - -#define CB_CFIG_FORCE_FDX BIT_6 /* Force Full Duplex */ -#define CB_CFIG_FDX_ENABLE BIT_7 /* Full Duplex Enabled */ - -/* byte 20 bit definitions*/ -#define CB_CFIG_MULTI_IA BIT_6 /* Multiple IA Addr */ - -/* byte 21 bit definitions*/ -#define CB_CFIG_MULTICAST_ALL BIT_3 /* Multicast All */ - -/* byte 22 bit defines */ -#define CB_CFIG_RECEIVE_GAMLA_MODE BIT_0 /* D102 receive mode */ -#define CB_CFIG_VLAN_DROP_ENABLE BIT_1 /* vlan stripping */ - -#define CB_CFIG_LONG_RX_OK BIT_3 - -#define NO_LOOPBACK 0 -#define MAC_LOOPBACK 0x01 -#define PHY_LOOPBACK 0x02 - -/* function prototypes */ -extern void e100_config_init(struct e100_private *bdp); -extern unsigned char e100_force_config(struct e100_private *bdp); -extern unsigned char e100_config(struct e100_private *bdp); -extern void e100_config_fc(struct e100_private *bdp); -extern void e100_config_promisc(struct e100_private *bdp, unsigned char enable); -extern void e100_config_brdcast_dsbl(struct e100_private *bdp); -extern void e100_config_mulcast_enbl(struct e100_private *bdp, - unsigned char enable); -extern void e100_config_ifs(struct e100_private *bdp); -extern void e100_config_force_dplx(struct e100_private *bdp); -extern u8 e100_config_loopback_mode(struct e100_private *bdp, u8 mode); -extern u8 e100_config_dynamic_tbd(struct e100_private *bdp, u8 enable); -extern u8 e100_config_tcb_ext_enable(struct e100_private *bdp, u8 enable); -extern void e100_config_vlan_drop(struct e100_private *bdp, unsigned char enable); -#endif /* _E100_CONFIG_INC_ */ diff --git a/xen/drivers/net/e100/e100_eeprom.c b/xen/drivers/net/e100/e100_eeprom.c deleted file mode 100644 index ff843e161b..0000000000 --- a/xen/drivers/net/e100/e100_eeprom.c +++ /dev/null @@ -1,565 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -/********************************************************************** -* * -* INTEL CORPORATION * -* * -* This software is supplied under the terms of the license included * -* above. All use of this driver must be in accordance with the terms * -* of that license. * -* * -* Module Name: e100_eeprom.c * -* * -* Abstract: This module contains routines to read and write to a * -* serial EEPROM * -* * -* Environment: This file is intended to be specific to the Linux * -* operating system. * -* * -**********************************************************************/ -#include "e100.h" - -#define CSR_EEPROM_CONTROL_FIELD(bdp) ((bdp)->scb->scb_eprm_cntrl) - -#define CSR_GENERAL_CONTROL2_FIELD(bdp) \ - ((bdp)->scb->scb_ext.d102_scb.scb_gen_ctrl2) - -#define EEPROM_STALL_TIME 4 -#define EEPROM_CHECKSUM ((u16) 0xBABA) -#define EEPROM_MAX_WORD_SIZE 256 - -void e100_eeprom_cleanup(struct e100_private *adapter); -u16 e100_eeprom_calculate_chksum(struct e100_private *adapter); -static void e100_eeprom_write_word(struct e100_private *adapter, u16 reg, - u16 data); -void e100_eeprom_write_block(struct e100_private *adapter, u16 start, u16 *data, - u16 size); -u16 e100_eeprom_size(struct e100_private *adapter); -u16 e100_eeprom_read(struct e100_private *adapter, u16 reg); - -static void shift_out_bits(struct e100_private *adapter, u16 data, u16 count); -static u16 shift_in_bits(struct e100_private *adapter); -static void raise_clock(struct e100_private *adapter, u16 *x); -static void lower_clock(struct e100_private *adapter, u16 *x); -static u16 eeprom_wait_cmd_done(struct e100_private *adapter); -static void eeprom_stand_by(struct e100_private *adapter); - -//---------------------------------------------------------------------------------------- -// Procedure: eeprom_set_semaphore -// -// Description: This function set (write 1) Gamla EEPROM semaphore bit (bit 23 word 0x1C in the CSR). -// -// Arguments: -// Adapter - Adapter context -// -// Returns: true if success -// else return false -// -//---------------------------------------------------------------------------------------- - -inline u8 -eeprom_set_semaphore(struct e100_private *adapter) -{ - u16 data = 0; - unsigned long expiration_time = jiffies + HZ / 100 + 1; - - do { - // Get current value of General Control 2 - data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter)); - - // Set bit 23 word 0x1C in the CSR. - data |= SCB_GCR2_EEPROM_ACCESS_SEMAPHORE; - writeb(data, &CSR_GENERAL_CONTROL2_FIELD(adapter)); - - // Check to see if this bit set or not. - data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter)); - - if (data & SCB_GCR2_EEPROM_ACCESS_SEMAPHORE) { - return true; - } - - if (time_before(jiffies, expiration_time)) - yield(); - else - return false; - - } while (true); -} - -//---------------------------------------------------------------------------------------- -// Procedure: eeprom_reset_semaphore -// -// Description: This function reset (write 0) Gamla EEPROM semaphore bit -// (bit 23 word 0x1C in the CSR). -// -// Arguments: struct e100_private * adapter - Adapter context -//---------------------------------------------------------------------------------------- - -inline void -eeprom_reset_semaphore(struct e100_private *adapter) -{ - u16 data = 0; - - data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter)); - data &= ~(SCB_GCR2_EEPROM_ACCESS_SEMAPHORE); - writeb(data, &CSR_GENERAL_CONTROL2_FIELD(adapter)); -} - -//---------------------------------------------------------------------------------------- -// Procedure: e100_eeprom_size -// -// Description: This routine determines the size of the EEPROM. This value should be -// checked for validity - ie. is it too big or too small. The size returned -// is then passed to the read/write functions. -// -// Returns: -// Size of the eeprom, or zero if an error occurred -//---------------------------------------------------------------------------------------- -u16 -e100_eeprom_size(struct e100_private *adapter) -{ - u16 x, size = 1; // must be one to accumulate a product - - // if we've already stored this data, read from memory - if (adapter->eeprom_size) { - return adapter->eeprom_size; - } - // otherwise, read from the eeprom - // Set EEPROM semaphore. - if (adapter->rev_id >= D102_REV_ID) { - if (!eeprom_set_semaphore(adapter)) - return 0; - } - // enable the eeprom by setting EECS. - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - x &= ~(EEDI | EEDO | EESK); - x |= EECS; - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - - // write the read opcode - shift_out_bits(adapter, EEPROM_READ_OPCODE, 3); - - // experiment to discover the size of the eeprom. request register zero - // and wait for the eeprom to tell us it has accepted the entire address. - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - do { - size *= 2; // each bit of address doubles eeprom size - x |= EEDO; // set bit to detect "dummy zero" - x &= ~EEDI; // address consists of all zeros - - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - readw(&(adapter->scb->scb_status)); - udelay(EEPROM_STALL_TIME); - raise_clock(adapter, &x); - lower_clock(adapter, &x); - - // check for "dummy zero" - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - if (size > EEPROM_MAX_WORD_SIZE) { - size = 0; - break; - } - } while (x & EEDO); - - // read in the value requested - (void) shift_in_bits(adapter); - e100_eeprom_cleanup(adapter); - - // Clear EEPROM Semaphore. - if (adapter->rev_id >= D102_REV_ID) { - eeprom_reset_semaphore(adapter); - } - - return size; -} - -//---------------------------------------------------------------------------------------- -// Procedure: eeprom_address_size -// -// Description: determines the number of bits in an address for the eeprom acceptable -// values are 64, 128, and 256 -// Arguments: size of the eeprom -// Returns: bits in an address for that size eeprom -//---------------------------------------------------------------------------------------- - -static inline int -eeprom_address_size(u16 size) -{ - int isize = size; - - return (ffs(isize) - 1); -} - -//---------------------------------------------------------------------------------------- -// Procedure: e100_eeprom_read -// -// Description: This routine serially reads one word out of the EEPROM. -// -// Arguments: -// adapter - our adapter context -// reg - EEPROM word to read. -// -// Returns: -// Contents of EEPROM word (reg). -//---------------------------------------------------------------------------------------- - -u16 -e100_eeprom_read(struct e100_private *adapter, u16 reg) -{ - u16 x, data, bits; - - // Set EEPROM semaphore. - if (adapter->rev_id >= D102_REV_ID) { - if (!eeprom_set_semaphore(adapter)) - return 0; - } - // eeprom size is initialized to zero - if (!adapter->eeprom_size) - adapter->eeprom_size = e100_eeprom_size(adapter); - - bits = eeprom_address_size(adapter->eeprom_size); - - // select EEPROM, reset bits, set EECS - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - - x &= ~(EEDI | EEDO | EESK); - x |= EECS; - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - - // write the read opcode and register number in that order - // The opcode is 3bits in length, reg is 'bits' bits long - shift_out_bits(adapter, EEPROM_READ_OPCODE, 3); - shift_out_bits(adapter, reg, bits); - - // Now read the data (16 bits) in from the selected EEPROM word - data = shift_in_bits(adapter); - - e100_eeprom_cleanup(adapter); - - // Clear EEPROM Semaphore. - if (adapter->rev_id >= D102_REV_ID) { - eeprom_reset_semaphore(adapter); - } - - return data; -} - -//---------------------------------------------------------------------------------------- -// Procedure: shift_out_bits -// -// Description: This routine shifts data bits out to the EEPROM. -// -// Arguments: -// data - data to send to the EEPROM. -// count - number of data bits to shift out. -// -// Returns: (none) -//---------------------------------------------------------------------------------------- - -static void -shift_out_bits(struct e100_private *adapter, u16 data, u16 count) -{ - u16 x, mask; - - mask = 1 << (count - 1); - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - x &= ~(EEDO | EEDI); - - do { - x &= ~EEDI; - if (data & mask) - x |= EEDI; - - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - readw(&(adapter->scb->scb_status)); /* flush command to card */ - udelay(EEPROM_STALL_TIME); - raise_clock(adapter, &x); - lower_clock(adapter, &x); - mask = mask >> 1; - } while (mask); - - x &= ~EEDI; - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); -} - -//---------------------------------------------------------------------------------------- -// Procedure: raise_clock -// -// Description: This routine raises the EEPROM's clock input (EESK) -// -// Arguments: -// x - Ptr to the EEPROM control register's current value -// -// Returns: (none) -//---------------------------------------------------------------------------------------- - -void -raise_clock(struct e100_private *adapter, u16 *x) -{ - *x = *x | EESK; - writew(*x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - readw(&(adapter->scb->scb_status)); /* flush command to card */ - udelay(EEPROM_STALL_TIME); -} - -//---------------------------------------------------------------------------------------- -// Procedure: lower_clock -// -// Description: This routine lower's the EEPROM's clock input (EESK) -// -// Arguments: -// x - Ptr to the EEPROM control register's current value -// -// Returns: (none) -//---------------------------------------------------------------------------------------- - -void -lower_clock(struct e100_private *adapter, u16 *x) -{ - *x = *x & ~EESK; - writew(*x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - readw(&(adapter->scb->scb_status)); /* flush command to card */ - udelay(EEPROM_STALL_TIME); -} - -//---------------------------------------------------------------------------------------- -// Procedure: shift_in_bits -// -// Description: This routine shifts data bits in from the EEPROM. -// -// Arguments: -// -// Returns: -// The contents of that particular EEPROM word -//---------------------------------------------------------------------------------------- - -static u16 -shift_in_bits(struct e100_private *adapter) -{ - u16 x, d, i; - - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - x &= ~(EEDO | EEDI); - d = 0; - - for (i = 0; i < 16; i++) { - d <<= 1; - raise_clock(adapter, &x); - - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - - x &= ~EEDI; - if (x & EEDO) - d |= 1; - - lower_clock(adapter, &x); - } - - return d; -} - -//---------------------------------------------------------------------------------------- -// Procedure: e100_eeprom_cleanup -// -// Description: This routine returns the EEPROM to an idle state -//---------------------------------------------------------------------------------------- - -void -e100_eeprom_cleanup(struct e100_private *adapter) -{ - u16 x; - - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - - x &= ~(EECS | EEDI); - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - - raise_clock(adapter, &x); - lower_clock(adapter, &x); -} - -//********************************************************************************** -// Procedure: e100_eeprom_update_chksum -// -// Description: Calculates the checksum and writes it to the EEProm. -// It calculates the checksum accroding to the formula: -// Checksum = 0xBABA - (sum of first 63 words). -// -//----------------------------------------------------------------------------------- -u16 -e100_eeprom_calculate_chksum(struct e100_private *adapter) -{ - u16 idx, xsum_index, checksum = 0; - - // eeprom size is initialized to zero - if (!adapter->eeprom_size) - adapter->eeprom_size = e100_eeprom_size(adapter); - - xsum_index = adapter->eeprom_size - 1; - for (idx = 0; idx < xsum_index; idx++) - checksum += e100_eeprom_read(adapter, idx); - - checksum = EEPROM_CHECKSUM - checksum; - return checksum; -} - -//---------------------------------------------------------------------------------------- -// Procedure: e100_eeprom_write_word -// -// Description: This routine writes a word to a specific EEPROM location without. -// taking EEPROM semaphore and updating checksum. -// Use e100_eeprom_write_block for the EEPROM update -// Arguments: reg - The EEPROM word that we are going to write to. -// data - The data (word) that we are going to write to the EEPROM. -//---------------------------------------------------------------------------------------- -static void -e100_eeprom_write_word(struct e100_private *adapter, u16 reg, u16 data) -{ - u16 x; - u16 bits; - - bits = eeprom_address_size(adapter->eeprom_size); - - /* select EEPROM, mask off ASIC and reset bits, set EECS */ - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - x &= ~(EEDI | EEDO | EESK); - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - readw(&(adapter->scb->scb_status)); /* flush command to card */ - udelay(EEPROM_STALL_TIME); - x |= EECS; - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - - shift_out_bits(adapter, EEPROM_EWEN_OPCODE, 5); - shift_out_bits(adapter, reg, (u16) (bits - 2)); - if (!eeprom_wait_cmd_done(adapter)) - return; - - /* write the new word to the EEPROM & send the write opcode the EEPORM */ - shift_out_bits(adapter, EEPROM_WRITE_OPCODE, 3); - - /* select which word in the EEPROM that we are writing to */ - shift_out_bits(adapter, reg, bits); - - /* write the data to the selected EEPROM word */ - shift_out_bits(adapter, data, 16); - if (!eeprom_wait_cmd_done(adapter)) - return; - - shift_out_bits(adapter, EEPROM_EWDS_OPCODE, 5); - shift_out_bits(adapter, reg, (u16) (bits - 2)); - if (!eeprom_wait_cmd_done(adapter)) - return; - - e100_eeprom_cleanup(adapter); -} - -//---------------------------------------------------------------------------------------- -// Procedure: e100_eeprom_write_block -// -// Description: This routine writes a block of words starting from specified EEPROM -// location and updates checksum -// Arguments: reg - The EEPROM word that we are going to write to. -// data - The data (word) that we are going to write to the EEPROM. -//---------------------------------------------------------------------------------------- -void -e100_eeprom_write_block(struct e100_private *adapter, u16 start, u16 *data, - u16 size) -{ - u16 checksum; - u16 i; - - if (!adapter->eeprom_size) - adapter->eeprom_size = e100_eeprom_size(adapter); - - // Set EEPROM semaphore. - if (adapter->rev_id >= D102_REV_ID) { - if (!eeprom_set_semaphore(adapter)) - return; - } - - for (i = 0; i < size; i++) { - e100_eeprom_write_word(adapter, start + i, data[i]); - } - //Update checksum - checksum = e100_eeprom_calculate_chksum(adapter); - e100_eeprom_write_word(adapter, (adapter->eeprom_size - 1), checksum); - - // Clear EEPROM Semaphore. - if (adapter->rev_id >= D102_REV_ID) { - eeprom_reset_semaphore(adapter); - } -} - -//---------------------------------------------------------------------------------------- -// Procedure: eeprom_wait_cmd_done -// -// Description: This routine waits for the the EEPROM to finish its command. -// Specifically, it waits for EEDO (data out) to go high. -// Returns: true - If the command finished -// false - If the command never finished (EEDO stayed low) -//---------------------------------------------------------------------------------------- -static u16 -eeprom_wait_cmd_done(struct e100_private *adapter) -{ - u16 x; - unsigned long expiration_time = jiffies + HZ / 100 + 1; - - eeprom_stand_by(adapter); - - do { - rmb(); - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - if (x & EEDO) - return true; - if (time_before(jiffies, expiration_time)) - yield(); - else - return false; - } while (true); -} - -//---------------------------------------------------------------------------------------- -// Procedure: eeprom_stand_by -// -// Description: This routine lowers the EEPROM chip select (EECS) for a few microseconds. -//---------------------------------------------------------------------------------------- -static void -eeprom_stand_by(struct e100_private *adapter) -{ - u16 x; - - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - x &= ~(EECS | EESK); - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - readw(&(adapter->scb->scb_status)); /* flush command to card */ - udelay(EEPROM_STALL_TIME); - x |= EECS; - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - readw(&(adapter->scb->scb_status)); /* flush command to card */ - udelay(EEPROM_STALL_TIME); -} diff --git a/xen/drivers/net/e100/e100_main.c b/xen/drivers/net/e100/e100_main.c deleted file mode 100644 index 6ce4d87b8c..0000000000 --- a/xen/drivers/net/e100/e100_main.c +++ /dev/null @@ -1,4265 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -/********************************************************************** -* * -* INTEL CORPORATION * -* * -* This software is supplied under the terms of the license included * -* above. All use of this driver must be in accordance with the terms * -* of that license. * -* * -* Module Name: e100_main.c * -* * -* Abstract: Functions for the driver entry points like load, * -* unload, open and close. All board specific calls made * -* by the network interface section of the driver. * -* * -* Environment: This file is intended to be specific to the Linux * -* operating system. * -* * -**********************************************************************/ - -/* Change Log - * - * 2.2.21 02/11/03 - * o Removed marketing brand strings. Instead, Using generic string - * "Intel(R) PRO/100 Network Connection" for all adapters. - * o Implemented ethtool -S option - * o Strip /proc/net/PRO_LAN_Adapters files for kernel driver - * o Bug fix: Read wrong byte in EEPROM when offset is odd number - * o Bug fix: PHY loopback test fails on ICH devices - * o Bug fix: System panic on e100_close when repeating Hot Remove and - * Add in a team - * o Bug fix: Linux Bonding driver claims adapter's link loss because of - * not updating last_rx field - * o Bug fix: e100 does not check validity of MAC address - * o New feature: added ICH5 support - * - * 2.1.27 11/20/02 - * o Bug fix: Device command timeout due to SMBus processing during init - * o Bug fix: Not setting/clearing I (Interrupt) bit in tcb correctly - * o Bug fix: Not using EEPROM WoL setting as default in ethtool - * o Bug fix: Not able to set autoneg on using ethtool when interface down - * o Bug fix: Not able to change speed/duplex using ethtool/mii - * when interface up - * o Bug fix: Ethtool shows autoneg on when forced to 100/Full - * o Bug fix: Compiler error when CONFIG_PROC_FS not defined - * o Bug fix: 2.5.44 e100 doesn't load with preemptive kernel enabled - * (sleep while holding spinlock) - * o Bug fix: 2.1.24-k1 doesn't display complete statistics - * o Bug fix: System panic due to NULL watchdog timer dereference during - * ifconfig down, rmmod and insmod - * - * 2.1.24 10/7/02 - */ - -#include -/*#include */ -/*#include */ -/*#include */ -#include "e100.h" -#include "e100_ucode.h" -#include "e100_config.h" -#include "e100_phy.h" - -extern void e100_force_speed_duplex_to_phy(struct e100_private *bdp); - -#if 0 -static char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", -}; -#define E100_STATS_LEN sizeof(e100_gstrings_stats) / ETH_GSTRING_LEN -#endif - -#if 0 -static int e100_do_ethtool_ioctl(struct net_device *, struct ifreq *); -#endif -static void e100_get_speed_duplex_caps(struct e100_private *); -#if 0 -static int e100_ethtool_get_settings(struct net_device *, struct ifreq *); -static int e100_ethtool_set_settings(struct net_device *, struct ifreq *); - -static int e100_ethtool_get_drvinfo(struct net_device *, struct ifreq *); -static int e100_ethtool_eeprom(struct net_device *, struct ifreq *); -#endif - -#define E100_EEPROM_MAGIC 0x1234 -#if 0 -static int e100_ethtool_glink(struct net_device *, struct ifreq *); -static int e100_ethtool_gregs(struct net_device *, struct ifreq *); -static int e100_ethtool_nway_rst(struct net_device *, struct ifreq *); -static int e100_ethtool_wol(struct net_device *, struct ifreq *); -#endif -#ifdef CONFIG_PM -static unsigned char e100_setup_filter(struct e100_private *bdp); -static void e100_do_wol(struct pci_dev *pcid, struct e100_private *bdp); -#endif -#if 0 -static u16 e100_get_ip_lbytes(struct net_device *dev); -#endif -extern void e100_config_wol(struct e100_private *bdp); -extern u32 e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags); -#if 0 -static int e100_ethtool_test(struct net_device *, struct ifreq *); -static int e100_ethtool_gstrings(struct net_device *, struct ifreq *); -static char *test_strings[] = { - "E100_EEPROM_TEST_FAIL", - "E100_CHIP_TIMEOUT", - "E100_ROM_TEST_FAIL", - "E100_REG_TEST_FAIL", - "E100_MAC_TEST_FAIL", - "E100_LPBK_MAC_FAIL", - "E100_LPBK_PHY_FAIL" -}; -#endif - -#if 0 -static int e100_ethtool_led_blink(struct net_device *, struct ifreq *); -static int e100_mii_ioctl(struct net_device *, struct ifreq *, int); -#endif - -static unsigned char e100_delayed_exec_non_cu_cmd(struct e100_private *, - nxmit_cb_entry_t *); -static void e100_free_nontx_list(struct e100_private *); -static void e100_non_tx_background(unsigned long); - -/* Global Data structures and variables */ -char e100_copyright[] __devinitdata = "Copyright (c) 2003 Intel Corporation"; -char e100_driver_version[]="2.2.21-k1"; -const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver"; -char e100_short_driver_name[] = "e100"; -static int e100nics = 0; -static void e100_vlan_rx_register(struct net_device *netdev, struct vlan_group - *grp); -static void e100_vlan_rx_add_vid(struct net_device *netdev, u16 vid); -static void e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid); - -#ifdef CONFIG_PM -static int e100_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); -static int e100_suspend(struct pci_dev *pcid, u32 state); -static int e100_resume(struct pci_dev *pcid); -struct notifier_block e100_notifier_reboot = { - .notifier_call = e100_notify_reboot, - .next = NULL, - .priority = 0 -}; -#endif - -/*********************************************************************/ -/*! This is a GCC extension to ANSI C. - * See the item "Labeled Elements in Initializers" in the section - * "Extensions to the C Language Family" of the GCC documentation. - *********************************************************************/ -#define E100_PARAM_INIT { [0 ... E100_MAX_NIC] = -1 } - -/* All parameters are treated the same, as an integer array of values. - * This macro just reduces the need to repeat the same declaration code - * over and over (plus this helps to avoid typo bugs). - */ -#define E100_PARAM(X, S) \ - static const int X[E100_MAX_NIC + 1] = E100_PARAM_INIT; \ - MODULE_PARM(X, "1-" __MODULE_STRING(E100_MAX_NIC) "i"); \ - MODULE_PARM_DESC(X, S); - -/* ====================================================================== */ -#if 0 -static u8 e100_D101M_checksum(struct e100_private *, struct sk_buff *); -static u8 e100_D102_check_checksum(rfd_t *); -static int e100_ioctl(struct net_device *, struct ifreq *, int); -#endif -static int e100_open(struct net_device *); -static int e100_close(struct net_device *); -static int e100_change_mtu(struct net_device *, int); -static int e100_xmit_frame(struct sk_buff *, struct net_device *); -static unsigned char e100_init(struct e100_private *); -static int e100_set_mac(struct net_device *, void *); -struct net_device_stats *e100_get_stats(struct net_device *); - -static void e100intr(int, void *, struct pt_regs *); -static void e100_print_brd_conf(struct e100_private *); -static void e100_set_multi(struct net_device *); -void e100_set_speed_duplex(struct e100_private *); - -static u8 e100_pci_setup(struct pci_dev *, struct e100_private *); -static u8 e100_sw_init(struct e100_private *); -static void e100_tco_workaround(struct e100_private *); -static unsigned char e100_alloc_space(struct e100_private *); -static void e100_dealloc_space(struct e100_private *); -static int e100_alloc_tcb_pool(struct e100_private *); -static void e100_setup_tcb_pool(tcb_t *, unsigned int, struct e100_private *); -static void e100_free_tcb_pool(struct e100_private *); -static int e100_alloc_rfd_pool(struct e100_private *); -static void e100_free_rfd_pool(struct e100_private *); - -static void e100_rd_eaddr(struct e100_private *); -static void e100_rd_pwa_no(struct e100_private *); -extern u16 e100_eeprom_read(struct e100_private *, u16); -extern void e100_eeprom_write_block(struct e100_private *, u16, u16 *, u16); -extern u16 e100_eeprom_size(struct e100_private *); -u16 e100_eeprom_calculate_chksum(struct e100_private *adapter); - -static unsigned char e100_clr_cntrs(struct e100_private *); -static unsigned char e100_load_microcode(struct e100_private *); -static unsigned char e100_hw_init(struct e100_private *); -static unsigned char e100_setup_iaaddr(struct e100_private *, u8 *); -static unsigned char e100_update_stats(struct e100_private *bdp); - -static void e100_start_ru(struct e100_private *); -static void e100_dump_stats_cntrs(struct e100_private *); - -static void e100_check_options(int board, struct e100_private *bdp); -static void e100_set_int_option(int *, int, int, int, int, char *); -static void e100_set_bool_option(struct e100_private *bdp, int, u32, int, - char *); -unsigned char e100_wait_exec_cmplx(struct e100_private *, u32, u8, u8); -void e100_exec_cmplx(struct e100_private *, u32, u8); -/*static unsigned char e100_asf_enabled(struct e100_private *bdp);*/ - -/** - * e100_get_rx_struct - retrieve cell to hold skb buff from the pool - * @bdp: atapter's private data struct - * - * Returns the new cell to hold sk_buff or %NULL. - */ -static inline struct rx_list_elem * -e100_get_rx_struct(struct e100_private *bdp) -{ - struct rx_list_elem *rx_struct = NULL; - - if (!list_empty(&(bdp->rx_struct_pool))) { - rx_struct = list_entry(bdp->rx_struct_pool.next, - struct rx_list_elem, list_elem); - list_del(&(rx_struct->list_elem)); - } - - return rx_struct; -} - -/** - * e100_alloc_skb - allocate an skb for the adapter - * @bdp: atapter's private data struct - * - * Allocates skb with enough room for rfd, and data, and reserve non-data space. - * Returns the new cell with sk_buff or %NULL. - */ -static inline struct rx_list_elem * -e100_alloc_skb(struct e100_private *bdp) -{ - struct sk_buff *new_skb; - u32 skb_size = sizeof (rfd_t); - struct rx_list_elem *rx_struct; - - new_skb = (struct sk_buff *) dev_alloc_skb(skb_size); - if (new_skb) { - /* The IP data should be - DWORD aligned. since the ethernet header is 14 bytes long, - we need to reserve 2 extra bytes so that the TCP/IP headers - will be DWORD aligned. */ - skb_reserve(new_skb, 2); - if ((rx_struct = e100_get_rx_struct(bdp)) == NULL) - goto err; - rx_struct->skb = new_skb; - rx_struct->dma_addr = pci_map_single(bdp->pdev, new_skb->data, - sizeof (rfd_t), - PCI_DMA_FROMDEVICE); - if (!rx_struct->dma_addr) - goto err; - skb_reserve(new_skb, bdp->rfd_size); - return rx_struct; - } else { - return NULL; - } - -err: - dev_kfree_skb_irq(new_skb); - return NULL; -} - -/** - * e100_add_skb_to_end - add an skb to the end of our rfd list - * @bdp: atapter's private data struct - * @rx_struct: rx_list_elem with the new skb - * - * Adds a newly allocated skb to the end of our rfd list. - */ -inline void -e100_add_skb_to_end(struct e100_private *bdp, struct rx_list_elem *rx_struct) -{ - rfd_t *rfdn; /* The new rfd */ - rfd_t *rfd; /* The old rfd */ - struct rx_list_elem *rx_struct_last; - - (rx_struct->skb)->dev = bdp->device; - rfdn = RFD_POINTER(rx_struct->skb, bdp); - rfdn = map_domain_mem(__pa(rfdn)); - rfdn->rfd_header.cb_status = 0; - rfdn->rfd_header.cb_cmd = __constant_cpu_to_le16(RFD_EL_BIT); - rfdn->rfd_act_cnt = 0; - rfdn->rfd_sz = __constant_cpu_to_le16(RFD_DATA_SIZE); - unmap_domain_mem(rfdn); - - pci_dma_sync_single(bdp->pdev, rx_struct->dma_addr, bdp->rfd_size, - PCI_DMA_TODEVICE); - - if (!list_empty(&(bdp->active_rx_list))) { - rx_struct_last = list_entry(bdp->active_rx_list.prev, - struct rx_list_elem, list_elem); - rfd = RFD_POINTER(rx_struct_last->skb, bdp); - rfd = map_domain_mem(__pa(rfd)); - pci_dma_sync_single(bdp->pdev, rx_struct_last->dma_addr, - 4, PCI_DMA_FROMDEVICE); - put_unaligned(cpu_to_le32(rx_struct->dma_addr), - ((u32 *) (&(rfd->rfd_header.cb_lnk_ptr)))); - - pci_dma_sync_single(bdp->pdev, rx_struct_last->dma_addr, - 8, PCI_DMA_TODEVICE); - rfd->rfd_header.cb_cmd &= - __constant_cpu_to_le16((u16) ~RFD_EL_BIT); - unmap_domain_mem(rfd); - - pci_dma_sync_single(bdp->pdev, rx_struct_last->dma_addr, - 4, PCI_DMA_TODEVICE); - } - - list_add_tail(&(rx_struct->list_elem), &(bdp->active_rx_list)); -} - -static inline void -e100_alloc_skbs(struct e100_private *bdp) -{ - for (; bdp->skb_req > 0; bdp->skb_req--) { - struct rx_list_elem *rx_struct; - - if ((rx_struct = e100_alloc_skb(bdp)) == NULL) - return; - - e100_add_skb_to_end(bdp, rx_struct); - } -} - -void e100_tx_srv(struct e100_private *); -u32 e100_rx_srv(struct e100_private *); - -void e100_watchdog(struct net_device *); -void e100_refresh_txthld(struct e100_private *); -void e100_manage_adaptive_ifs(struct e100_private *); -void e100_clear_pools(struct e100_private *); -static void e100_clear_structs(struct net_device *); -static inline tcb_t *e100_prepare_xmit_buff(struct e100_private *, - struct sk_buff *); -static void e100_set_multi_exec(struct net_device *dev); - -MODULE_AUTHOR("Intel Corporation, "); -MODULE_DESCRIPTION("Intel(R) PRO/100 Network Driver"); -MODULE_LICENSE("GPL"); - -E100_PARAM(TxDescriptors, "Number of transmit descriptors"); -E100_PARAM(RxDescriptors, "Number of receive descriptors"); -E100_PARAM(XsumRX, "Disable or enable Receive Checksum offload"); -E100_PARAM(e100_speed_duplex, "Speed and Duplex settings"); -E100_PARAM(ucode, "Disable or enable microcode loading"); -E100_PARAM(ber, "Value for the BER correction algorithm"); -E100_PARAM(flow_control, "Disable or enable Ethernet PAUSE frames processing"); -E100_PARAM(IntDelay, "Value for CPU saver's interrupt delay"); -E100_PARAM(BundleSmallFr, "Disable or enable interrupt bundling of small frames"); -E100_PARAM(BundleMax, "Maximum number for CPU saver's packet bundling"); -E100_PARAM(IFS, "Disable or enable the adaptive IFS algorithm"); - -/** - * e100_exec_cmd - issue a comand - * @bdp: atapter's private data struct - * @scb_cmd_low: the command that is to be issued - * - * This general routine will issue a command to the e100. - */ -static inline void -e100_exec_cmd(struct e100_private *bdp, u8 cmd_low) -{ - writeb(cmd_low, &(bdp->scb->scb_cmd_low)); - readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */ -} - -/** - * e100_wait_scb - wait for SCB to clear - * @bdp: atapter's private data struct - * - * This routine checks to see if the e100 has accepted a command. - * It does so by checking the command field in the SCB, which will - * be zeroed by the e100 upon accepting a command. The loop waits - * for up to 1 millisecond for command acceptance. - * - * Returns: - * true if the SCB cleared within 1 millisecond. - * false if it didn't clear within 1 millisecond - */ -unsigned char -e100_wait_scb(struct e100_private *bdp) -{ - int i; - - /* loop on the scb for a few times */ - for (i = 0; i < 100; i++) { - if (!readb(&bdp->scb->scb_cmd_low)) - return true; - cpu_relax(); - } - - /* it didn't work. do it the slow way using udelay()s */ - for (i = 0; i < E100_MAX_SCB_WAIT; i++) { - if (!readb(&bdp->scb->scb_cmd_low)) - return true; - cpu_relax(); - udelay(1); - } - - return false; -} - -/** - * e100_wait_exec_simple - issue a command - * @bdp: atapter's private data struct - * @scb_cmd_low: the command that is to be issued - * - * This general routine will issue a command to the e100 after waiting for - * the previous command to finish. - * - * Returns: - * true if the command was issued to the chip successfully - * false if the command was not issued to the chip - */ -inline unsigned char -e100_wait_exec_simple(struct e100_private *bdp, u8 scb_cmd_low) -{ - if (!e100_wait_scb(bdp)) { - printk(KERN_DEBUG "e100: %s: e100_wait_exec_simple: failed\n", - bdp->device->name); -#ifdef E100_CU_DEBUG - printk(KERN_ERR "e100: %s: Last command (%x/%x) " - "timeout\n", bdp->device->name, - bdp->last_cmd, bdp->last_sub_cmd); - printk(KERN_ERR "e100: %s: Current simple command (%x) " - "can't be executed\n", - bdp->device->name, scb_cmd_low); -#endif - return false; - } - e100_exec_cmd(bdp, scb_cmd_low); -#ifdef E100_CU_DEBUG - bdp->last_cmd = scb_cmd_low; - bdp->last_sub_cmd = 0; -#endif - return true; -} - -void -e100_exec_cmplx(struct e100_private *bdp, u32 phys_addr, u8 cmd) -{ - writel(phys_addr, &(bdp->scb->scb_gen_ptr)); - readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */ - e100_exec_cmd(bdp, cmd); -} - -unsigned char -e100_wait_exec_cmplx(struct e100_private *bdp, u32 phys_addr, u8 cmd, u8 sub_cmd) -{ - if (!e100_wait_scb(bdp)) { -#ifdef E100_CU_DEBUG - printk(KERN_ERR "e100: %s: Last command (%x/%x) " - "timeout\n", bdp->device->name, - bdp->last_cmd, bdp->last_sub_cmd); - printk(KERN_ERR "e100: %s: Current complex command " - "(%x/%x) can't be executed\n", - bdp->device->name, cmd, sub_cmd); -#endif - return false; - } - e100_exec_cmplx(bdp, phys_addr, cmd); -#ifdef E100_CU_DEBUG - bdp->last_cmd = cmd; - bdp->last_sub_cmd = sub_cmd; -#endif - return true; -} - -inline u8 -e100_wait_cus_idle(struct e100_private *bdp) -{ - int i; - - /* loop on the scb for a few times */ - for (i = 0; i < 100; i++) { - if (((readw(&(bdp->scb->scb_status)) & SCB_CUS_MASK) != - SCB_CUS_ACTIVE)) { - return true; - } - cpu_relax(); - } - - for (i = 0; i < E100_MAX_CU_IDLE_WAIT; i++) { - if (((readw(&(bdp->scb->scb_status)) & SCB_CUS_MASK) != - SCB_CUS_ACTIVE)) { - return true; - } - cpu_relax(); - udelay(1); - } - - return false; -} - -/** - * e100_disable_clear_intr - disable and clear/ack interrupts - * @bdp: atapter's private data struct - * - * This routine disables interrupts at the hardware, by setting - * the M (mask) bit in the adapter's CSR SCB command word. - * It also clear/ack interrupts. - */ -static inline void -e100_disable_clear_intr(struct e100_private *bdp) -{ - u16 intr_status; - /* Disable interrupts on our PCI board by setting the mask bit */ - writeb(SCB_INT_MASK, &bdp->scb->scb_cmd_hi); - intr_status = readw(&bdp->scb->scb_status); - /* ack and clear intrs */ - writew(intr_status, &bdp->scb->scb_status); - readw(&bdp->scb->scb_status); -} - -/** - * e100_set_intr_mask - set interrupts - * @bdp: atapter's private data struct - * - * This routine sets interrupts at the hardware, by resetting - * the M (mask) bit in the adapter's CSR SCB command word - */ -static inline void -e100_set_intr_mask(struct e100_private *bdp) -{ - writeb(bdp->intr_mask, &bdp->scb->scb_cmd_hi); - readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */ -} - -static inline void -e100_trigger_SWI(struct e100_private *bdp) -{ - /* Trigger interrupt on our PCI board by asserting SWI bit */ - writeb(SCB_SOFT_INT, &bdp->scb->scb_cmd_hi); - readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */ -} - -static int __devinit -e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) -{ - static int first_time = true; - struct net_device *dev = NULL; - struct e100_private *bdp = NULL; - int rc = 0; - u16 cal_checksum, read_checksum; - - dev = alloc_etherdev(sizeof (struct e100_private)); - if (dev == NULL) { - printk(KERN_ERR "e100: Not able to alloc etherdev struct\n"); - rc = -ENODEV; - goto out; - } - - SET_MODULE_OWNER(dev); - - if (first_time) { - first_time = false; - printk(KERN_NOTICE "%s - version %s\n", - e100_full_driver_name, e100_driver_version); - printk(KERN_NOTICE "%s\n", e100_copyright); - printk(KERN_NOTICE "\n"); - } - - bdp = dev->priv; - bdp->pdev = pcid; - bdp->device = dev; - - pci_set_drvdata(pcid, dev); - - if ((rc = e100_alloc_space(bdp)) != 0) { - goto err_dev; - } - - bdp->flags = 0; - bdp->ifs_state = 0; - bdp->ifs_value = 0; - bdp->scb = 0; - - init_timer(&bdp->nontx_timer_id); - bdp->nontx_timer_id.data = (unsigned long) bdp; - bdp->nontx_timer_id.function = (void *) &e100_non_tx_background; - INIT_LIST_HEAD(&(bdp->non_tx_cmd_list)); - bdp->non_tx_command_state = E100_NON_TX_IDLE; - - init_timer(&bdp->watchdog_timer); - bdp->watchdog_timer.data = (unsigned long) dev; - bdp->watchdog_timer.function = (void *) &e100_watchdog; - - if ((rc = e100_pci_setup(pcid, bdp)) != 0) { - goto err_dealloc; - } - - if (((bdp->pdev->device > 0x1030) - && (bdp->pdev->device < 0x103F)) - || ((bdp->pdev->device >= 0x1050) - && (bdp->pdev->device <= 0x1057)) - || (bdp->pdev->device == 0x2449) - || (bdp->pdev->device == 0x2459) - || (bdp->pdev->device == 0x245D)) { - bdp->rev_id = D101MA_REV_ID; /* workaround for ICH3 */ - bdp->flags |= IS_ICH; - } - - if (bdp->rev_id == 0xff) - bdp->rev_id = 1; - - if ((u8) bdp->rev_id >= D101A4_REV_ID) - bdp->flags |= IS_BACHELOR; - - if ((u8) bdp->rev_id >= D102_REV_ID) { - bdp->flags |= USE_IPCB; - bdp->rfd_size = 32; - } else { - bdp->rfd_size = 16; - } - e100_check_options(e100nics, bdp); - - if (!e100_init(bdp)) { - printk(KERN_ERR "e100: Failed to initialize, instance #%d\n", - e100nics); - rc = -ENODEV; - goto err_pci; - } - - /* Check if checksum is valid */ - cal_checksum = e100_eeprom_calculate_chksum(bdp); - read_checksum = e100_eeprom_read(bdp, (bdp->eeprom_size - 1)); - if (cal_checksum != read_checksum) { - printk(KERN_ERR "e100: Corrupted EEPROM on instance #%d\n", - e100nics); - rc = -ENODEV; - goto err_pci; - } - - dev->vlan_rx_register = e100_vlan_rx_register; - dev->vlan_rx_add_vid = e100_vlan_rx_add_vid; - dev->vlan_rx_kill_vid = e100_vlan_rx_kill_vid; - dev->irq = pcid->irq; - dev->open = &e100_open; - dev->hard_start_xmit = &e100_xmit_frame; - dev->stop = &e100_close; - dev->change_mtu = &e100_change_mtu; - dev->get_stats = &e100_get_stats; - dev->set_multicast_list = &e100_set_multi; - dev->set_mac_address = &e100_set_mac; -#if 0 - dev->do_ioctl = &e100_ioctl; -#endif - - if (bdp->flags & USE_IPCB) - dev->features = NETIF_F_SG | NETIF_F_HW_CSUM | - NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - - e100nics++; - - e100_get_speed_duplex_caps(bdp); - - if ((rc = register_netdev(dev)) != 0) { - goto err_pci; - } - memcpy(bdp->ifname, dev->name, IFNAMSIZ); - bdp->ifname[IFNAMSIZ-1] = 0; - - printk(KERN_NOTICE - "e100: %s: %s\n", - bdp->device->name, "Intel(R) PRO/100 Network Connection"); - e100_print_brd_conf(bdp); - - bdp->wolsupported = 0; - bdp->wolopts = 0; - - /* Check if WoL is enabled on EEPROM */ - if (e100_eeprom_read(bdp, EEPROM_ID_WORD) & BIT_5) { - /* Magic Packet WoL is enabled on device by default */ - /* if EEPROM WoL bit is TRUE */ - bdp->wolsupported = WAKE_MAGIC; - bdp->wolopts = WAKE_MAGIC; - if (bdp->rev_id >= D101A4_REV_ID) - bdp->wolsupported = WAKE_PHY | WAKE_MAGIC; - if (bdp->rev_id >= D101MA_REV_ID) - bdp->wolsupported |= WAKE_UCAST | WAKE_ARP; - } - - printk(KERN_NOTICE "\n"); - - if ( !(dev->features & NETIF_F_SG) ) - alert_slow_netdevice(dev, (char *)e100_full_driver_name); - - goto out; - -err_pci: - iounmap(bdp->scb); - pci_release_regions(pcid); - pci_disable_device(pcid); -err_dealloc: - e100_dealloc_space(bdp); -err_dev: - pci_set_drvdata(pcid, NULL); - kfree(dev); -out: - return rc; -} - -/** - * e100_clear_structs - free resources - * @dev: adapter's net_device struct - * - * Free all device specific structs, unmap i/o address, etc. - */ -static void __devexit -e100_clear_structs(struct net_device *dev) -{ - struct e100_private *bdp = dev->priv; - - iounmap(bdp->scb); - pci_release_regions(bdp->pdev); - pci_disable_device(bdp->pdev); - - e100_dealloc_space(bdp); - pci_set_drvdata(bdp->pdev, NULL); - kfree(dev); -} - -static void __devexit -e100_remove1(struct pci_dev *pcid) -{ - struct net_device *dev; - struct e100_private *bdp; - - if (!(dev = (struct net_device *) pci_get_drvdata(pcid))) - return; - - bdp = dev->priv; - - unregister_netdev(dev); - - e100_sw_reset(bdp, PORT_SELECTIVE_RESET); - - if (bdp->non_tx_command_state != E100_NON_TX_IDLE) { - del_timer_sync(&bdp->nontx_timer_id); - e100_free_nontx_list(bdp); - bdp->non_tx_command_state = E100_NON_TX_IDLE; - } - - e100_clear_structs(dev); - - --e100nics; -} - -static struct pci_device_id e100_id_table[] __devinitdata = { - {0x8086, 0x1229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1209, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1031, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1033, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1034, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1038, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x103A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x103B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x103C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x103D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x103E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x2459, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x245D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0,} /* This has to be the last entry*/ -}; -MODULE_DEVICE_TABLE(pci, e100_id_table); - -static struct pci_driver e100_driver = { - .name = "e100", - .id_table = e100_id_table, - .probe = e100_found1, - .remove = __devexit_p(e100_remove1), -#ifdef CONFIG_PM - .suspend = e100_suspend, - .resume = e100_resume, -#endif -}; - -static int __init -e100_init_module(void) -{ - int ret; - ret = pci_module_init(&e100_driver); - - if(ret >= 0) { -#ifdef CONFIG_PM - register_reboot_notifier(&e100_notifier_reboot); -#endif - } - - return ret; -} - -static void __exit -e100_cleanup_module(void) -{ -#ifdef CONFIG_PM - unregister_reboot_notifier(&e100_notifier_reboot); -#endif - - pci_unregister_driver(&e100_driver); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); - -/** - * e100_check_options - check command line options - * @board: board number - * @bdp: atapter's private data struct - * - * This routine does range checking on command-line options - */ -void __devinit -e100_check_options(int board, struct e100_private *bdp) -{ - if (board >= E100_MAX_NIC) { - printk(KERN_NOTICE - "e100: No configuration available for board #%d\n", - board); - printk(KERN_NOTICE "e100: Using defaults for all values\n"); - board = E100_MAX_NIC; - } - - e100_set_int_option(&(bdp->params.TxDescriptors), TxDescriptors[board], - E100_MIN_TCB, E100_MAX_TCB, E100_DEFAULT_TCB, - "TxDescriptor count"); - - e100_set_int_option(&(bdp->params.RxDescriptors), RxDescriptors[board], - E100_MIN_RFD, E100_MAX_RFD, E100_DEFAULT_RFD, - "RxDescriptor count"); - - e100_set_int_option(&(bdp->params.e100_speed_duplex), - e100_speed_duplex[board], 0, 4, - E100_DEFAULT_SPEED_DUPLEX, "speed/duplex mode"); - - e100_set_int_option(&(bdp->params.ber), ber[board], 0, ZLOCK_MAX_ERRORS, - E100_DEFAULT_BER, "Bit Error Rate count"); - - e100_set_bool_option(bdp, XsumRX[board], PRM_XSUMRX, E100_DEFAULT_XSUM, - "XsumRX value"); - - /* Default ucode value depended on controller revision */ - if (bdp->rev_id >= D101MA_REV_ID) { - e100_set_bool_option(bdp, ucode[board], PRM_UCODE, - E100_DEFAULT_UCODE, "ucode value"); - } else { - e100_set_bool_option(bdp, ucode[board], PRM_UCODE, false, - "ucode value"); - } - - e100_set_bool_option(bdp, flow_control[board], PRM_FC, E100_DEFAULT_FC, - "flow control value"); - - e100_set_bool_option(bdp, IFS[board], PRM_IFS, E100_DEFAULT_IFS, - "IFS value"); - - e100_set_bool_option(bdp, BundleSmallFr[board], PRM_BUNDLE_SMALL, - E100_DEFAULT_BUNDLE_SMALL_FR, - "CPU saver bundle small frames value"); - - e100_set_int_option(&(bdp->params.IntDelay), IntDelay[board], 0x0, - 0xFFFF, E100_DEFAULT_CPUSAVER_INTERRUPT_DELAY, - "CPU saver interrupt delay value"); - - e100_set_int_option(&(bdp->params.BundleMax), BundleMax[board], 0x1, - 0xFFFF, E100_DEFAULT_CPUSAVER_BUNDLE_MAX, - "CPU saver bundle max value"); - -} - -/** - * e100_set_int_option - check and set an integer option - * @option: a pointer to the relevant option field - * @val: the value specified - * @min: the minimum valid value - * @max: the maximum valid value - * @default_val: the default value - * @name: the name of the option - * - * This routine does range checking on a command-line option. - * If the option's value is '-1' use the specified default. - * Otherwise, if the value is invalid, change it to the default. - */ -void __devinit -e100_set_int_option(int *option, int val, int min, int max, int default_val, - char *name) -{ - if (val == -1) { /* no value specified. use default */ - *option = default_val; - - } else if ((val < min) || (val > max)) { - printk(KERN_NOTICE - "e100: Invalid %s specified (%i). " - "Valid range is %i-%i\n", - name, val, min, max); - printk(KERN_NOTICE "e100: Using default %s of %i\n", name, - default_val); - *option = default_val; - } else { - printk(KERN_INFO "e100: Using specified %s of %i\n", name, val); - *option = val; - } -} - -/** - * e100_set_bool_option - check and set a boolean option - * @bdp: atapter's private data struct - * @val: the value specified - * @mask: the mask for the relevant option - * @default_val: the default value - * @name: the name of the option - * - * This routine checks a boolean command-line option. - * If the option's value is '-1' use the specified default. - * Otherwise, if the value is invalid (not 0 or 1), - * change it to the default. - */ -void __devinit -e100_set_bool_option(struct e100_private *bdp, int val, u32 mask, - int default_val, char *name) -{ - if (val == -1) { - if (default_val) - bdp->params.b_params |= mask; - - } else if ((val != true) && (val != false)) { - printk(KERN_NOTICE - "e100: Invalid %s specified (%i). " - "Valid values are %i/%i\n", - name, val, false, true); - printk(KERN_NOTICE "e100: Using default %s of %i\n", name, - default_val); - - if (default_val) - bdp->params.b_params |= mask; - } else { - printk(KERN_INFO "e100: Using specified %s of %i\n", name, val); - if (val) - bdp->params.b_params |= mask; - } -} - -static int -e100_open(struct net_device *dev) -{ - struct e100_private *bdp; - int rc = 0; - - bdp = dev->priv; - - /* setup the tcb pool */ - if (!e100_alloc_tcb_pool(bdp)) { - rc = -ENOMEM; - goto err_exit; - } - bdp->last_tcb = NULL; - - bdp->tcb_pool.head = 0; - bdp->tcb_pool.tail = 1; - - e100_setup_tcb_pool((tcb_t *) bdp->tcb_pool.data, - bdp->params.TxDescriptors, bdp); - - if (!e100_alloc_rfd_pool(bdp)) { - rc = -ENOMEM; - goto err_exit; - } - - if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0)) { - rc = -EAGAIN; - goto err_exit; - } - - if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0)) { - rc = -EAGAIN; - goto err_exit; - } - - mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ)); - - netif_start_queue(dev); - - e100_start_ru(bdp); - if ((rc = request_irq(dev->irq, &e100intr, SA_SHIRQ, - dev->name, dev)) != 0) { - del_timer_sync(&bdp->watchdog_timer); - goto err_exit; - } - bdp->intr_mask = 0; - e100_set_intr_mask(bdp); - - e100_force_config(bdp); - - goto exit; - -err_exit: - e100_clear_pools(bdp); -exit: - return rc; -} - -static int -e100_close(struct net_device *dev) -{ - struct e100_private *bdp = dev->priv; - - e100_disable_clear_intr(bdp); - free_irq(dev->irq, dev); - bdp->intr_mask = SCB_INT_MASK; - e100_isolate_driver(bdp); - - netif_carrier_off(bdp->device); - bdp->cur_line_speed = 0; - bdp->cur_dplx_mode = 0; - e100_clear_pools(bdp); - - return 0; -} - -static int -e100_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > (ETH_DATA_LEN + VLAN_SIZE))) - return -EINVAL; - - dev->mtu = new_mtu; - return 0; -} - -static int -e100_xmit_frame(struct sk_buff *skb, struct net_device *dev) -{ - int rc = 0; - int notify_stop = false; - struct e100_private *bdp = dev->priv; - - if (!spin_trylock(&bdp->bd_non_tx_lock)) { - printk("Couldn't acqure lock in e100_xmit_frame\n"); - notify_stop = true; - rc = 1; - goto exit2; - } - - if (!TCBS_AVAIL(bdp->tcb_pool) || - (bdp->non_tx_command_state != E100_NON_TX_IDLE)) { - printk("Bailing from e100_tx_frame %d, %d, %d\n", - TCBS_AVAIL(bdp->tcb_pool), - bdp->non_tx_command_state, - E100_NON_TX_IDLE); - notify_stop = true; - rc = 1; - goto exit1; - } - - e100_prepare_xmit_buff(bdp, skb); - - bdp->drv_stats.net_stats.tx_bytes += skb->len; - - dev->trans_start = jiffies; - -exit1: - spin_unlock(&bdp->bd_non_tx_lock); -exit2: - if (notify_stop) { - netif_stop_queue(dev); - } - - return rc; -} - -/** - * e100_get_stats - get driver statistics - * @dev: adapter's net_device struct - * - * This routine is called when the OS wants the adapter's stats returned. - * It returns the address of the net_device_stats stucture for the device. - * If the statistics are currently being updated, then they might be incorrect - * for a short while. However, since this cannot actually cause damage, no - * locking is used. - */ -struct net_device_stats * -e100_get_stats(struct net_device *dev) -{ - struct e100_private *bdp = dev->priv; - - bdp->drv_stats.net_stats.tx_errors = - bdp->drv_stats.net_stats.tx_carrier_errors + - bdp->drv_stats.net_stats.tx_aborted_errors; - - bdp->drv_stats.net_stats.rx_errors = - bdp->drv_stats.net_stats.rx_crc_errors + - bdp->drv_stats.net_stats.rx_frame_errors + - bdp->drv_stats.net_stats.rx_length_errors + - bdp->drv_stats.rcv_cdt_frames; - - return &(bdp->drv_stats.net_stats); -} - -/** - * e100_set_mac - set the MAC address - * @dev: adapter's net_device struct - * @addr: the new address - * - * This routine sets the ethernet address of the board - * Returns: - * 0 - if successful - * -1 - otherwise - */ -static int -e100_set_mac(struct net_device *dev, void *addr) -{ - struct e100_private *bdp; - int rc = -1; - struct sockaddr *p_sockaddr = (struct sockaddr *) addr; - - if (!is_valid_ether_addr(p_sockaddr->sa_data)) - return -EADDRNOTAVAIL; - bdp = dev->priv; - - if (e100_setup_iaaddr(bdp, (u8 *) (p_sockaddr->sa_data))) { - memcpy(&(dev->dev_addr[0]), p_sockaddr->sa_data, ETH_ALEN); - rc = 0; - } - - return rc; -} - -static void -e100_set_multi_exec(struct net_device *dev) -{ - struct e100_private *bdp = dev->priv; - mltcst_cb_t *mcast_buff; - cb_header_t *cb_hdr; - struct dev_mc_list *mc_list; - unsigned int i; - nxmit_cb_entry_t *cmd = e100_alloc_non_tx_cmd(bdp); - - if (cmd != NULL) { - mcast_buff = &((cmd->non_tx_cmd)->ntcb.multicast); - cb_hdr = &((cmd->non_tx_cmd)->ntcb.multicast.mc_cbhdr); - } else { - return; - } - - /* initialize the multi cast command */ - cb_hdr->cb_cmd = __constant_cpu_to_le16(CB_MULTICAST); - - /* now fill in the rest of the multicast command */ - *(u16 *) (&(mcast_buff->mc_count)) = cpu_to_le16(dev->mc_count * 6); - for (i = 0, mc_list = dev->mc_list; - (i < dev->mc_count) && (i < MAX_MULTICAST_ADDRS); - i++, mc_list = mc_list->next) { - /* copy into the command */ - memcpy(&(mcast_buff->mc_addr[i * ETH_ALEN]), - (u8 *) &(mc_list->dmi_addr), ETH_ALEN); - } - - if (!e100_exec_non_cu_cmd(bdp, cmd)) { - printk(KERN_WARNING "e100: %s: Multicast setup failed\n", - dev->name); - } -} - -/** - * e100_set_multi - set multicast status - * @dev: adapter's net_device struct - * - * This routine is called to add or remove multicast addresses, and/or to - * change the adapter's promiscuous state. - */ -static void -e100_set_multi(struct net_device *dev) -{ - struct e100_private *bdp = dev->priv; - unsigned char promisc_enbl; - unsigned char mulcast_enbl; - - promisc_enbl = ((dev->flags & IFF_PROMISC) == IFF_PROMISC); - mulcast_enbl = ((dev->flags & IFF_ALLMULTI) || - (dev->mc_count > MAX_MULTICAST_ADDRS)); - - e100_config_promisc(bdp, promisc_enbl); - e100_config_mulcast_enbl(bdp, mulcast_enbl); - - /* reconfigure the chip if something has changed in its config space */ - e100_config(bdp); - - if (promisc_enbl || mulcast_enbl) { - return; /* no need for Multicast Cmd */ - } - - /* get the multicast CB */ - e100_set_multi_exec(dev); -} - -#if 0 -static int -e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - - switch (cmd) { - - case SIOCETHTOOL: - return e100_do_ethtool_ioctl(dev, ifr); - break; - - case SIOCGMIIPHY: /* Get address of MII PHY in use. */ - case SIOCGMIIREG: /* Read MII PHY register. */ - case SIOCSMIIREG: /* Write to MII PHY register. */ - return e100_mii_ioctl(dev, ifr, cmd); - break; - - default: - return -EOPNOTSUPP; - } - return 0; - -} -#endif - -/** - * e100init - initialize the adapter - * @bdp: atapter's private data struct - * - * This routine is called when this driver is loaded. This is the initialization - * routine which allocates memory, configures the adapter and determines the - * system resources. - * - * Returns: - * true: if successful - * false: otherwise - */ -static unsigned char __devinit -e100_init(struct e100_private *bdp) -{ - u32 st_timeout = 0; - u32 st_result = 0; - e100_sw_init(bdp); - - if (!e100_selftest(bdp, &st_timeout, &st_result)) { - if (st_timeout) { - printk(KERN_ERR "e100: selftest timeout\n"); - } else { - printk(KERN_ERR "e100: selftest failed. Results: %x\n", - st_result); - } - return false; - } - else - printk(KERN_DEBUG "e100: selftest OK.\n"); - - /* read the MAC address from the eprom */ - e100_rd_eaddr(bdp); - if (!is_valid_ether_addr(bdp->device->dev_addr)) { - printk(KERN_ERR "e100: Invalid Ethernet address\n"); - return false; - } - /* read NIC's part number */ - e100_rd_pwa_no(bdp); - - if (!e100_hw_init(bdp)) { - printk(KERN_ERR "e100: hw init failed\n"); - return false; - } - /* Interrupts are enabled after device reset */ - e100_disable_clear_intr(bdp); - - return true; -} - -/** - * e100_sw_init - initialize software structs - * @bdp: atapter's private data struct - * - * This routine initializes all software structures. Sets up the - * circular structures for the RFD's & TCB's. Allocates the per board - * structure for storing adapter information. The CSR is also memory - * mapped in this routine. - * - * Returns : - * true: if S/W was successfully initialized - * false: otherwise - */ -static unsigned char __devinit -e100_sw_init(struct e100_private *bdp) -{ - bdp->next_cu_cmd = START_WAIT; // init the next cu state - - /* - * Set the value for # of good xmits per underrun. the value assigned - * here is an intelligent suggested default. Nothing magical about it. - */ - bdp->tx_per_underrun = DEFAULT_TX_PER_UNDERRUN; - - /* get the default transmit threshold value */ - bdp->tx_thld = TX_THRSHLD; - - /* get the EPROM size */ - bdp->eeprom_size = e100_eeprom_size(bdp); - - /* Initialize our spinlocks */ - spin_lock_init(&(bdp->bd_lock)); - spin_lock_init(&(bdp->bd_non_tx_lock)); - spin_lock_init(&(bdp->config_lock)); - spin_lock_init(&(bdp->mdi_access_lock)); - - return 1; -} - -static void __devinit -e100_tco_workaround(struct e100_private *bdp) -{ - int i; - - /* Do software reset */ - e100_sw_reset(bdp, PORT_SOFTWARE_RESET); - - /* Do a dummy LOAD CU BASE command. */ - /* This gets us out of pre-driver to post-driver. */ - e100_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE); - - /* Wait 20 msec for reset to take effect */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 50 + 1); - - /* disable interrupts since they are enabled */ - /* after device reset */ - e100_disable_clear_intr(bdp); - - /* Wait for command to be cleared up to 1 sec */ - for (i=0; i<100; i++) { - if (!readb(&bdp->scb->scb_cmd_low)) - break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 100 + 1); - } - - /* Wait for TCO request bit in PMDR register to be clear */ - for (i=0; i<50; i++) { - if (!(readb(&bdp->scb->scb_ext.d101m_scb.scb_pmdr) & BIT_1)) - break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 100 + 1); - } -} - -/** - * e100_hw_init - initialized tthe hardware - * @bdp: atapter's private data struct - * - * This routine performs a reset on the adapter, and configures the adapter. - * This includes configuring the 82557 LAN controller, validating and setting - * the node address, detecting and configuring the Phy chip on the adapter, - * and initializing all of the on chip counters. - * - * Returns: - * true - If the adapter was initialized - * false - If the adapter failed initialization - */ -unsigned char __devinit -e100_hw_init(struct e100_private *bdp) -{ - if (!e100_phy_init(bdp)) - return false; - - e100_sw_reset(bdp, PORT_SELECTIVE_RESET); - - /* Only 82559 or above needs TCO workaround */ - if (bdp->rev_id >= D101MA_REV_ID) - e100_tco_workaround(bdp); - - /* Load the CU BASE (set to 0, because we use linear mode) */ - if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0)) - return false; - - if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0)) - return false; - - /* Load interrupt microcode */ - if (e100_load_microcode(bdp)) { - bdp->flags |= DF_UCODE_LOADED; - } - - e100_config_init(bdp); - if (!e100_config(bdp)) { - return false; - } - - if (!e100_setup_iaaddr(bdp, bdp->device->dev_addr)) - return false; - - /* Clear the internal counters */ - if (!e100_clr_cntrs(bdp)) - return false; - - /* Change for 82558 enhancement */ - /* If 82558/9 and if the user has enabled flow control, set up the - * Flow Control Reg. in the CSR */ - if ((bdp->flags & IS_BACHELOR) - && (bdp->params.b_params & PRM_FC)) { - writeb(DFLT_FC_THLD, &bdp->scb->scb_ext.d101_scb.scb_fc_thld); - writeb(DFLT_FC_CMD, - &bdp->scb->scb_ext.d101_scb.scb_fc_xon_xoff); - } - - return true; -} - -/** - * e100_setup_tcb_pool - setup TCB circular list - * @head: Pointer to head of the allocated TCBs - * @qlen: Number of elements in the queue - * @bdp: atapter's private data struct - * - * This routine arranges the contigiously allocated TCB's in a circular list. - * Also does the one time initialization of the TCBs. - */ -static void -e100_setup_tcb_pool(tcb_t *head, unsigned int qlen, struct e100_private *bdp) -{ - int ele_no; - tcb_t *pcurr_tcb; /* point to current tcb */ - u32 next_phys; /* the next phys addr */ - u16 txcommand = CB_S_BIT | CB_TX_SF_BIT; - - bdp->tx_count = 0; - if (bdp->flags & USE_IPCB) { - txcommand |= CB_IPCB_TRANSMIT | CB_CID_DEFAULT; - } else if (bdp->flags & IS_BACHELOR) { - txcommand |= CB_TRANSMIT | CB_CID_DEFAULT; - } else { - txcommand |= CB_TRANSMIT; - } - - for (ele_no = 0, next_phys = bdp->tcb_phys, pcurr_tcb = head; - ele_no < qlen; ele_no++, pcurr_tcb++) { - - /* set the phys addr for this TCB, next_phys has not incr. yet */ - pcurr_tcb->tcb_phys = next_phys; - next_phys += sizeof (tcb_t); - - /* set the link to next tcb */ - if (ele_no == (qlen - 1)) - pcurr_tcb->tcb_hdr.cb_lnk_ptr = - cpu_to_le32(bdp->tcb_phys); - else - pcurr_tcb->tcb_hdr.cb_lnk_ptr = cpu_to_le32(next_phys); - - pcurr_tcb->tcb_hdr.cb_status = 0; - pcurr_tcb->tcb_hdr.cb_cmd = cpu_to_le16(txcommand); - pcurr_tcb->tcb_cnt = 0; - pcurr_tcb->tcb_thrshld = bdp->tx_thld; - if (ele_no < 2) { - pcurr_tcb->tcb_hdr.cb_status = - cpu_to_le16(CB_STATUS_COMPLETE); - } - pcurr_tcb->tcb_tbd_num = 1; - - if (bdp->flags & IS_BACHELOR) { - pcurr_tcb->tcb_tbd_ptr = - __constant_cpu_to_le32(0xFFFFFFFF); - } else { - pcurr_tcb->tcb_tbd_ptr = - cpu_to_le32(pcurr_tcb->tcb_phys + 0x10); - } - - if (bdp->flags & IS_BACHELOR) { - pcurr_tcb->tcb_tbd_expand_ptr = - cpu_to_le32(pcurr_tcb->tcb_phys + 0x20); - } else { - pcurr_tcb->tcb_tbd_expand_ptr = - cpu_to_le32(pcurr_tcb->tcb_phys + 0x10); - } - pcurr_tcb->tcb_tbd_dflt_ptr = pcurr_tcb->tcb_tbd_ptr; - - if (bdp->flags & USE_IPCB) { - pcurr_tcb->tbd_ptr = &(pcurr_tcb->tcbu.tbd_array[1]); - pcurr_tcb->tcbu.ipcb.ip_activation_high = - IPCB_IP_ACTIVATION_DEFAULT; - pcurr_tcb->tcbu.ipcb.vlan = 0; - } else { - pcurr_tcb->tbd_ptr = &(pcurr_tcb->tcbu.tbd_array[0]); - } - - pcurr_tcb->tcb_skb = NULL; - } - - wmb(); -} - -/***************************************************************************/ -/***************************************************************************/ -/* Memory Management Routines */ -/***************************************************************************/ - -/** - * e100_alloc_space - allocate private driver data - * @bdp: atapter's private data struct - * - * This routine allocates memory for the driver. Memory allocated is for the - * selftest and statistics structures. - * - * Returns: - * 0: if the operation was successful - * %-ENOMEM: if memory allocation failed - */ -unsigned char __devinit -e100_alloc_space(struct e100_private *bdp) -{ - unsigned long off; - - /* allocate all the dma-able structures in one call: - * selftest results, adapter stats, and non-tx cb commands */ - if (!(bdp->dma_able = - pci_alloc_consistent(bdp->pdev, sizeof (bd_dma_able_t), - &(bdp->dma_able_phys)))) { - goto err; - } - - /* now assign the various pointers into the struct we've just allocated */ - off = offsetof(bd_dma_able_t, selftest); - - bdp->selftest = (self_test_t *) (bdp->dma_able + off); - bdp->selftest_phys = bdp->dma_able_phys + off; - - off = offsetof(bd_dma_able_t, stats_counters); - - bdp->stats_counters = (max_counters_t *) (bdp->dma_able + off); - bdp->stat_cnt_phys = bdp->dma_able_phys + off; - - return 0; - -err: - printk(KERN_ERR - "e100: Failed to allocate memory\n"); - return -ENOMEM; -} - -/** - * e100_alloc_tcb_pool - allocate TCB circular list - * @bdp: atapter's private data struct - * - * This routine allocates memory for the circular list of transmit descriptors. - * - * Returns: - * 0: if allocation has failed. - * 1: Otherwise. - */ -int -e100_alloc_tcb_pool(struct e100_private *bdp) -{ - int stcb = sizeof (tcb_t) * bdp->params.TxDescriptors; - - /* allocate space for the TCBs */ - if (!(bdp->tcb_pool.data = - pci_alloc_consistent(bdp->pdev, stcb, &bdp->tcb_phys))) - return 0; - - memset(bdp->tcb_pool.data, 0x00, stcb); - - return 1; -} - -void -e100_free_tcb_pool(struct e100_private *bdp) -{ - pci_free_consistent(bdp->pdev, - sizeof (tcb_t) * bdp->params.TxDescriptors, - bdp->tcb_pool.data, bdp->tcb_phys); - bdp->tcb_phys = 0; -} - -static void -e100_dealloc_space(struct e100_private *bdp) -{ - if (bdp->dma_able) { - pci_free_consistent(bdp->pdev, sizeof (bd_dma_able_t), - bdp->dma_able, bdp->dma_able_phys); - } - - bdp->selftest_phys = 0; - bdp->stat_cnt_phys = 0; - bdp->dma_able_phys = 0; - bdp->dma_able = 0; -} - -static void -e100_free_rfd_pool(struct e100_private *bdp) -{ - struct rx_list_elem *rx_struct; - - while (!list_empty(&(bdp->active_rx_list))) { - - rx_struct = list_entry(bdp->active_rx_list.next, - struct rx_list_elem, list_elem); - list_del(&(rx_struct->list_elem)); - pci_unmap_single(bdp->pdev, rx_struct->dma_addr, - sizeof (rfd_t), PCI_DMA_TODEVICE); - dev_kfree_skb(rx_struct->skb); - kfree(rx_struct); - } - - while (!list_empty(&(bdp->rx_struct_pool))) { - rx_struct = list_entry(bdp->rx_struct_pool.next, - struct rx_list_elem, list_elem); - list_del(&(rx_struct->list_elem)); - kfree(rx_struct); - } -} - -/** - * e100_alloc_rfd_pool - allocate RFDs - * @bdp: atapter's private data struct - * - * Allocates initial pool of skb which holds both rfd and data, - * and return a pointer to the head of the list - */ -static int -e100_alloc_rfd_pool(struct e100_private *bdp) -{ - struct rx_list_elem *rx_struct; - int i; - - INIT_LIST_HEAD(&(bdp->active_rx_list)); - INIT_LIST_HEAD(&(bdp->rx_struct_pool)); - bdp->skb_req = bdp->params.RxDescriptors; - for (i = 0; i < bdp->skb_req; i++) { - rx_struct = kmalloc(sizeof (struct rx_list_elem), GFP_ATOMIC); - list_add(&(rx_struct->list_elem), &(bdp->rx_struct_pool)); - } - e100_alloc_skbs(bdp); - return !list_empty(&(bdp->active_rx_list)); - -} - -void -e100_clear_pools(struct e100_private *bdp) -{ - bdp->last_tcb = NULL; - e100_free_rfd_pool(bdp); - e100_free_tcb_pool(bdp); -} - -/*****************************************************************************/ -/*****************************************************************************/ -/* Run Time Functions */ -/*****************************************************************************/ - -/** - * e100_watchdog - * @dev: adapter's net_device struct - * - * This routine runs every 2 seconds and updates our statitics and link state, - * and refreshs txthld value. - */ -void -e100_watchdog(struct net_device *dev) -{ - struct e100_private *bdp = dev->priv; - -#ifdef E100_CU_DEBUG - if (e100_cu_unknown_state(bdp)) { - printk(KERN_ERR "e100: %s: CU unknown state in e100_watchdog\n", - dev->name); - } -#endif - if (!netif_running(dev)) { - return; - } - - /* check if link state has changed */ - if (e100_phy_check(bdp)) { - if (netif_carrier_ok(dev)) { - printk(KERN_ERR - "e100: %s NIC Link is Up %d Mbps %s duplex\n", - bdp->device->name, bdp->cur_line_speed, - (bdp->cur_dplx_mode == HALF_DUPLEX) ? - "Half" : "Full"); - - e100_config_fc(bdp); - e100_config(bdp); - - } else { - printk(KERN_ERR "e100: %s NIC Link is Down\n", - bdp->device->name); - } - } - - // toggle the tx queue according to link status - // this also resolves a race condition between tx & non-cu cmd flows - if (netif_carrier_ok(dev)) { - if (netif_running(dev)) - netif_wake_queue(dev); - } else { - if (netif_running(dev)) - netif_stop_queue(dev); - /* When changing to non-autoneg, device may lose */ - /* link with some switches. e100 will try to */ - /* revover link by sending command to PHY layer */ - if (bdp->params.e100_speed_duplex != E100_AUTONEG) - e100_force_speed_duplex_to_phy(bdp); - } - - rmb(); - - if (e100_update_stats(bdp)) { - - /* Check if a change in the IFS parameter is needed, - and configure the device accordingly */ - if (bdp->params.b_params & PRM_IFS) - e100_manage_adaptive_ifs(bdp); - - /* Now adjust our dynamic tx threshold value */ - e100_refresh_txthld(bdp); - - /* Now if we are on a 557 and we havn't received any frames then we - * should issue a multicast command to reset the RU */ - if (bdp->rev_id < D101A4_REV_ID) { - if (!(bdp->stats_counters->basic_stats.rcv_gd_frames)) { - e100_set_multi(dev); - } - } - - /* Update the statistics needed by the upper interface */ - /* This should be the last statistic related command - * as it's async. now */ - e100_dump_stats_cntrs(bdp); - } - - wmb(); - - /* relaunch watchdog timer in 2 sec */ - mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ)); - - if (list_empty(&bdp->active_rx_list)) - e100_trigger_SWI(bdp); -} - -/** - * e100_manage_adaptive_ifs - * @bdp: atapter's private data struct - * - * This routine manages the adaptive Inter-Frame Spacing algorithm - * using a state machine. - */ -void -e100_manage_adaptive_ifs(struct e100_private *bdp) -{ - static u16 state_table[9][4] = { // rows are states - {2, 0, 0, 0}, // state0 // column0: next state if increasing - {2, 0, 5, 30}, // state1 // column1: next state if decreasing - {5, 1, 5, 30}, // state2 // column2: IFS value for 100 mbit - {5, 3, 0, 0}, // state3 // column3: IFS value for 10 mbit - {5, 3, 10, 60}, // state4 - {8, 4, 10, 60}, // state5 - {8, 6, 0, 0}, // state6 - {8, 6, 20, 60}, // state7 - {8, 7, 20, 60} // state8 - }; - - u32 transmits = - le32_to_cpu(bdp->stats_counters->basic_stats.xmt_gd_frames); - u32 collisions = - le32_to_cpu(bdp->stats_counters->basic_stats.xmt_ttl_coll); - u32 state = bdp->ifs_state; - u32 old_value = bdp->ifs_value; - int next_col; - u32 min_transmits; - - if (bdp->cur_dplx_mode == FULL_DUPLEX) { - bdp->ifs_state = 0; - bdp->ifs_value = 0; - - } else { /* Half Duplex */ - /* Set speed specific parameters */ - if (bdp->cur_line_speed == 100) { - next_col = 2; - min_transmits = MIN_NUMBER_OF_TRANSMITS_100; - - } else { /* 10 Mbps */ - next_col = 3; - min_transmits = MIN_NUMBER_OF_TRANSMITS_10; - } - - if ((transmits / 32 < collisions) - && (transmits > min_transmits)) { - state = state_table[state][0]; /* increment */ - - } else if (transmits < min_transmits) { - state = state_table[state][1]; /* decrement */ - } - - bdp->ifs_value = state_table[state][next_col]; - bdp->ifs_state = state; - } - - /* If the IFS value has changed, configure the device */ - if (bdp->ifs_value != old_value) { - e100_config_ifs(bdp); - e100_config(bdp); - } -} - -/** - * e100intr - interrupt handler - * @irq: the IRQ number - * @dev_inst: the net_device struct - * @regs: registers (unused) - * - * This routine is the ISR for the e100 board. It services - * the RX & TX queues & starts the RU if it has stopped due - * to no resources. - */ -void -e100intr(int irq, void *dev_inst, struct pt_regs *regs) -{ - struct net_device *dev; - struct e100_private *bdp; - u16 intr_status; - - dev = dev_inst; - bdp = dev->priv; - - intr_status = readw(&bdp->scb->scb_status); - /* If not my interrupt, just return */ - if (!(intr_status & SCB_STATUS_ACK_MASK) || (intr_status == 0xffff)) { - return; - } - - /* disable and ack intr */ - e100_disable_clear_intr(bdp); - - /* the device is closed, don't continue or else bad things may happen. */ - if (!netif_running(dev)) { - e100_set_intr_mask(bdp); - return; - } - - /* SWI intr (triggered by watchdog) is signal to allocate new skb buffers */ - if (intr_status & SCB_STATUS_ACK_SWI) { - e100_alloc_skbs(bdp); - } - - /* do recv work if any */ - if (intr_status & - (SCB_STATUS_ACK_FR | SCB_STATUS_ACK_RNR | SCB_STATUS_ACK_SWI)) - bdp->drv_stats.rx_intr_pkts += e100_rx_srv(bdp); - - /* clean up after tx'ed packets */ - if (intr_status & (SCB_STATUS_ACK_CNA | SCB_STATUS_ACK_CX)) - e100_tx_srv(bdp); - - e100_set_intr_mask(bdp); -} - -/** - * e100_tx_skb_free - free TX skbs resources - * @bdp: atapter's private data struct - * @tcb: associated tcb of the freed skb - * - * This routine frees resources of TX skbs. - */ -static inline void -e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb) -{ - if (tcb->tcb_skb) { - int i; - tbd_t *tbd_arr = tcb->tbd_ptr; - int frags = skb_shinfo(tcb->tcb_skb)->nr_frags; - - for (i = 0; i <= frags; i++, tbd_arr++) { - pci_unmap_single(bdp->pdev, - le32_to_cpu(tbd_arr->tbd_buf_addr), - le16_to_cpu(tbd_arr->tbd_buf_cnt), - PCI_DMA_TODEVICE); - } - dev_kfree_skb_irq(tcb->tcb_skb); - tcb->tcb_skb = NULL; - } -} - -/** - * e100_tx_srv - service TX queues - * @bdp: atapter's private data struct - * - * This routine services the TX queues. It reclaims the TCB's & TBD's & other - * resources used during the transmit of this buffer. It is called from the ISR. - * We don't need a tx_lock since we always access buffers which were already - * prepared. - */ -void -e100_tx_srv(struct e100_private *bdp) -{ - tcb_t *tcb; - int i; - - /* go over at most TxDescriptors buffers */ - for (i = 0; i < bdp->params.TxDescriptors; i++) { - tcb = bdp->tcb_pool.data; - tcb += bdp->tcb_pool.head; - - rmb(); - - /* if the buffer at 'head' is not complete, break */ - if (!(tcb->tcb_hdr.cb_status & - __constant_cpu_to_le16(CB_STATUS_COMPLETE))) - break; - - /* service next buffer, clear the out of resource condition */ - e100_tx_skb_free(bdp, tcb); - - if (netif_running(bdp->device)) - netif_wake_queue(bdp->device); - - /* if we've caught up with 'tail', break */ - if (NEXT_TCB_TOUSE(bdp->tcb_pool.head) == bdp->tcb_pool.tail) { - break; - } - - bdp->tcb_pool.head = NEXT_TCB_TOUSE(bdp->tcb_pool.head); - } -} - -/** - * e100_rx_srv - service RX queue - * @bdp: atapter's private data struct - * @max_number_of_rfds: max number of RFDs to process - * @rx_congestion: flag pointer, to inform the calling function of congestion. - * - * This routine processes the RX interrupt & services the RX queues. - * For each successful RFD, it allocates a new msg block, links that - * into the RFD list, and sends the old msg upstream. - * The new RFD is then put at the end of the free list of RFD's. - * It returns the number of serviced RFDs. - */ -u32 -e100_rx_srv(struct e100_private *bdp) -{ - rfd_t *rfd; /* new rfd, received rfd */ - int i; - u16 rfd_status; - struct sk_buff *skb; - struct net_device *dev; - unsigned int data_sz; - struct rx_list_elem *rx_struct; - u32 rfd_cnt = 0; - - dev = bdp->device; - - /* current design of rx is as following: - * 1. socket buffer (skb) used to pass network packet to upper layer - * 2. all HW host memory structures (like RFDs, RBDs and data buffers) - * are placed in a skb's data room - * 3. when rx process is complete, we change skb internal pointers to exclude - * from data area all unrelated things (RFD, RDB) and to leave - * just rx'ed packet netto - * 4. for each skb passed to upper layer, new one is allocated instead. - * 5. if no skb left, in 2 sec another atempt to allocate skbs will be made - * (watchdog trigger SWI intr and isr should allocate new skbs) - */ - for (i = 0; i < bdp->params.RxDescriptors; i++) { - if (list_empty(&(bdp->active_rx_list))) { - break; - } - - rx_struct = list_entry(bdp->active_rx_list.next, - struct rx_list_elem, list_elem); - skb = rx_struct->skb; - - rfd = RFD_POINTER(skb, bdp); /* locate RFD within skb */ - rfd = map_domain_mem(__pa(rfd)); - - // sync only the RFD header - pci_dma_sync_single(bdp->pdev, rx_struct->dma_addr, - bdp->rfd_size, PCI_DMA_FROMDEVICE); - rfd_status = le16_to_cpu(rfd->rfd_header.cb_status); /* get RFD's status */ - if (!(rfd_status & RFD_STATUS_COMPLETE)) /* does not contains data yet - exit */ - { - unmap_domain_mem(rfd); - break; - } - - /* to allow manipulation with current skb we need to unlink it */ - list_del(&(rx_struct->list_elem)); - - /* do not free & unmap badly received packet. - * move it to the end of skb list for reuse */ - if (!(rfd_status & RFD_STATUS_OK)) { - e100_add_skb_to_end(bdp, rx_struct); - unmap_domain_mem(rfd); - continue; - } - - data_sz = min_t(u16, (le16_to_cpu(rfd->rfd_act_cnt) & 0x3fff), - (sizeof (rfd_t) - bdp->rfd_size)); - - unmap_domain_mem(rfd); - - /* now sync all the data */ - pci_dma_sync_single(bdp->pdev, rx_struct->dma_addr, - (data_sz + bdp->rfd_size), - PCI_DMA_FROMDEVICE); - - pci_unmap_single(bdp->pdev, rx_struct->dma_addr, - sizeof (rfd_t), PCI_DMA_FROMDEVICE); - - list_add(&(rx_struct->list_elem), &(bdp->rx_struct_pool)); - - /* end of dma access to rfd */ - bdp->skb_req++; /* incr number of requested skbs */ - e100_alloc_skbs(bdp); /* and get them */ - - /* set packet size, excluding checksum (2 last bytes) if it is present */ - if ((bdp->flags & DF_CSUM_OFFLOAD) - && (bdp->rev_id < D102_REV_ID)) - skb_put(skb, (int) data_sz - 2); - else - skb_put(skb, (int) data_sz); - - /* set the protocol */ - skb->protocol = eth_type_trans(skb, dev); - - /* set the checksum info */ -#if 0 - if (bdp->flags & DF_CSUM_OFFLOAD) { - if (bdp->rev_id >= D102_REV_ID) { - skb->ip_summed = e100_D102_check_checksum(rfd); - } else { - skb->ip_summed = e100_D101M_checksum(bdp, skb); - } - } else { -#endif - skb->ip_summed = CHECKSUM_NONE; -#if 0 - } -#endif - -#if 0 - if(bdp->vlgrp && (rfd_status & CB_STATUS_VLAN)) { - vlan_hwaccel_rx(skb, bdp->vlgrp, be16_to_cpu(rfd->vlanid)); - } else { -#endif - netif_rx(skb); -#if 0 - } -#endif - dev->last_rx = jiffies; - bdp->drv_stats.net_stats.rx_bytes += skb->len; - - rfd_cnt++; - } /* end of rfd loop */ - - /* restart the RU if it has stopped */ - if ((readw(&bdp->scb->scb_status) & SCB_RUS_MASK) != SCB_RUS_READY) { - e100_start_ru(bdp); - } - - return rfd_cnt; -} - -void -e100_refresh_txthld(struct e100_private *bdp) -{ - basic_cntr_t *pstat = &(bdp->stats_counters->basic_stats); - - /* as long as tx_per_underrun is not 0, we can go about dynamically * - * adjusting the xmit threshold. we stop doing that & resort to defaults - * * once the adjustments become meaningless. the value is adjusted by * - * dumping the error counters & checking the # of xmit underrun errors * - * we've had. */ - if (bdp->tx_per_underrun) { - /* We are going to last values dumped from the dump statistics - * command */ - if (le32_to_cpu(pstat->xmt_gd_frames)) { - if (le32_to_cpu(pstat->xmt_uruns)) { - /* - * if we have had more than one underrun per "DEFAULT # - * OF XMITS ALLOWED PER UNDERRUN" good xmits, raise the - * THRESHOLD. - */ - if ((le32_to_cpu(pstat->xmt_gd_frames) / - le32_to_cpu(pstat->xmt_uruns)) < - bdp->tx_per_underrun) { - bdp->tx_thld += 3; - } - } - - /* - * if we've had less than one underrun per the DEFAULT number of - * of good xmits allowed, lower the THOLD but not less than 0 - */ - if (le32_to_cpu(pstat->xmt_gd_frames) > - bdp->tx_per_underrun) { - bdp->tx_thld--; - - if (bdp->tx_thld < 6) - bdp->tx_thld = 6; - - } - } - - /* end good xmits */ - /* - * * if our adjustments are becoming unresonable, stop adjusting & - * resort * to defaults & pray. A THOLD value > 190 means that the - * adapter will * wait for 190*8=1520 bytes in TX FIFO before it - * starts xmit. Since * MTU is 1514, it doesn't make any sense for - * further increase. */ - if (bdp->tx_thld >= 190) { - bdp->tx_per_underrun = 0; - bdp->tx_thld = 189; - } - } /* end underrun check */ -} - -/** - * e100_prepare_xmit_buff - prepare a buffer for transmission - * @bdp: atapter's private data struct - * @skb: skb to send - * - * This routine prepare a buffer for transmission. It checks - * the message length for the appropiate size. It picks up a - * free tcb from the TCB pool and sets up the corresponding - * TBD's. If the number of fragments are more than the number - * of TBD/TCB it copies all the fragments in a coalesce buffer. - * It returns a pointer to the prepared TCB. - */ -static inline tcb_t * -e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb) -{ - tcb_t *tcb, *prev_tcb; - - tcb = bdp->tcb_pool.data; - tcb += TCB_TO_USE(bdp->tcb_pool); - - if (bdp->flags & USE_IPCB) { - tcb->tcbu.ipcb.ip_activation_high = IPCB_IP_ACTIVATION_DEFAULT; - tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCP_PACKET; - tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCPUDP_CHECKSUM_ENABLE; - } - - if(bdp->vlgrp && vlan_tx_tag_present(skb)) { - (tcb->tcbu).ipcb.ip_activation_high |= IPCB_INSERTVLAN_ENABLE; - (tcb->tcbu).ipcb.vlan = cpu_to_be16(vlan_tx_tag_get(skb)); - } - - tcb->tcb_hdr.cb_status = 0; - tcb->tcb_thrshld = bdp->tx_thld; - tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_S_BIT); - - /* Set I (Interrupt) bit on every (TX_FRAME_CNT)th packet */ - if (!(++bdp->tx_count % TX_FRAME_CNT)) - tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_I_BIT); - else - /* Clear I bit on other packets */ - tcb->tcb_hdr.cb_cmd &= ~__constant_cpu_to_le16(CB_I_BIT); - - tcb->tcb_skb = skb; - -#if 0 - if (skb->ip_summed == CHECKSUM_HW) { - const struct iphdr *ip = skb->nh.iph; - - if ((ip->protocol == IPPROTO_TCP) || - (ip->protocol == IPPROTO_UDP)) { - - tcb->tcbu.ipcb.ip_activation_high |= - IPCB_HARDWAREPARSING_ENABLE; - tcb->tcbu.ipcb.ip_schedule |= - IPCB_TCPUDP_CHECKSUM_ENABLE; - - if (ip->protocol == IPPROTO_TCP) - tcb->tcbu.ipcb.ip_schedule |= IPCB_TCP_PACKET; - } - } -#endif - - if (!skb_shinfo(skb)->nr_frags) { - (tcb->tbd_ptr)->tbd_buf_addr = - cpu_to_le32(pci_map_single(bdp->pdev, skb->data, - skb->len, PCI_DMA_TODEVICE)); - (tcb->tbd_ptr)->tbd_buf_cnt = cpu_to_le16(skb->len); - tcb->tcb_tbd_num = 1; - tcb->tcb_tbd_ptr = tcb->tcb_tbd_dflt_ptr; - } else { - int i; - void *addr; - tbd_t *tbd_arr_ptr = &(tcb->tbd_ptr[1]); - skb_frag_t *frag = &skb_shinfo(skb)->frags[0]; - - (tcb->tbd_ptr)->tbd_buf_addr = - cpu_to_le32(pci_map_single(bdp->pdev, skb->data, - (skb->len - skb->data_len), - PCI_DMA_TODEVICE)); - (tcb->tbd_ptr)->tbd_buf_cnt = - cpu_to_le16(skb->len - skb->data_len); - - for (i = 0; i < skb_shinfo(skb)->nr_frags; - i++, tbd_arr_ptr++, frag++) { - - addr = ((void *) page_address(frag->page) + - frag->page_offset); - - tbd_arr_ptr->tbd_buf_addr = - cpu_to_le32(pci_map_single(bdp->pdev, - addr, frag->size, - PCI_DMA_TODEVICE)); - tbd_arr_ptr->tbd_buf_cnt = cpu_to_le16(frag->size); - } - tcb->tcb_tbd_num = skb_shinfo(skb)->nr_frags + 1; - tcb->tcb_tbd_ptr = tcb->tcb_tbd_expand_ptr; - } - - /* clear the S-BIT on the previous tcb */ - prev_tcb = bdp->tcb_pool.data; - prev_tcb += PREV_TCB_USED(bdp->tcb_pool); - prev_tcb->tcb_hdr.cb_cmd &= __constant_cpu_to_le16((u16) ~CB_S_BIT); - - bdp->tcb_pool.tail = NEXT_TCB_TOUSE(bdp->tcb_pool.tail); - - wmb(); - - e100_start_cu(bdp, tcb); - - return tcb; -} - -/* Changed for 82558 enhancement */ -/** - * e100_start_cu - start the adapter's CU - * @bdp: atapter's private data struct - * @tcb: TCB to be transmitted - * - * This routine issues a CU Start or CU Resume command to the 82558/9. - * This routine was added because the prepare_ext_xmit_buff takes advantage - * of the 82558/9's Dynamic TBD chaining feature and has to start the CU as - * soon as the first TBD is ready. - * - * e100_start_cu must be called while holding the tx_lock ! - */ -u8 -e100_start_cu(struct e100_private *bdp, tcb_t *tcb) -{ - unsigned long lock_flag; - u8 ret = true; - - spin_lock_irqsave(&(bdp->bd_lock), lock_flag); - switch (bdp->next_cu_cmd) { - case RESUME_NO_WAIT: - /*last cu command was a CU_RESMUE if this is a 558 or newer we don't need to - * wait for command word to clear, we reach here only if we are bachlor - */ - e100_exec_cmd(bdp, SCB_CUC_RESUME); - break; - - case RESUME_WAIT: - if ((bdp->flags & IS_ICH) && - (bdp->cur_line_speed == 10) && - (bdp->cur_dplx_mode == HALF_DUPLEX)) { - e100_wait_exec_simple(bdp, SCB_CUC_NOOP); - udelay(1); - } - if ((e100_wait_exec_simple(bdp, SCB_CUC_RESUME)) && - (bdp->flags & IS_BACHELOR) && (!(bdp->flags & IS_ICH))) { - bdp->next_cu_cmd = RESUME_NO_WAIT; - } - break; - - case START_WAIT: - // The last command was a non_tx CU command - if (!e100_wait_cus_idle(bdp)) - printk(KERN_DEBUG - "e100: %s: cu_start: timeout waiting for cu\n", - bdp->device->name); - if (!e100_wait_exec_cmplx(bdp, (u32) (tcb->tcb_phys), - SCB_CUC_START, CB_TRANSMIT)) { - printk(KERN_DEBUG - "e100: %s: cu_start: timeout waiting for scb\n", - bdp->device->name); - e100_exec_cmplx(bdp, (u32) (tcb->tcb_phys), - SCB_CUC_START); - ret = false; - } - - bdp->next_cu_cmd = RESUME_WAIT; - - break; - } - - /* save the last tcb */ - bdp->last_tcb = tcb; - - spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag); - return ret; -} - -/* ====================================================================== */ -/* hw */ -/* ====================================================================== */ - -/** - * e100_selftest - perform H/W self test - * @bdp: atapter's private data struct - * @st_timeout: address to return timeout value, if fails - * @st_result: address to return selftest result, if fails - * - * This routine will issue PORT Self-test command to test the e100. - * The self-test will fail if the adapter's master-enable bit is not - * set in the PCI Command Register, or if the adapter is not seated - * in a PCI master-enabled slot. we also disable interrupts when the - * command is completed. - * - * Returns: - * true: if adapter passes self_test - * false: otherwise - */ -unsigned char -e100_selftest(struct e100_private *bdp, u32 *st_timeout, u32 *st_result) -{ - u32 selftest_cmd; - - /* initialize the nic state before running test */ - e100_sw_reset(bdp, PORT_SOFTWARE_RESET); - /* Setup the address of the self_test area */ - selftest_cmd = bdp->selftest_phys; - - /* Setup SELF TEST Command Code in D3 - D0 */ - selftest_cmd |= PORT_SELFTEST; - - /* Initialize the self-test signature and results DWORDS */ - bdp->selftest->st_sign = 0; - bdp->selftest->st_result = 0xffffffff; - - /* Do the port command */ - writel(selftest_cmd, &bdp->scb->scb_port); - readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */ - - /* Wait at least 10 milliseconds for the self-test to complete */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 100 + 1); - - /* disable interrupts since they are enabled */ - /* after device reset during selftest */ - e100_disable_clear_intr(bdp); - - /* if The First Self Test DWORD Still Zero, We've timed out. If the - * second DWORD is not zero then we have an error. */ - if ((bdp->selftest->st_sign == 0) || (bdp->selftest->st_result != 0)) { - - if (st_timeout) - *st_timeout = !(le32_to_cpu(bdp->selftest->st_sign)); - - if (st_result) - *st_result = le32_to_cpu(bdp->selftest->st_result); - - return false; - } - - return true; -} - -/** - * e100_setup_iaaddr - issue IA setup sommand - * @bdp: atapter's private data struct - * @eaddr: new ethernet address - * - * This routine will issue the IA setup command. This command - * will notify the 82557 (e100) of what its individual (node) - * address is. This command will be executed in polled mode. - * - * Returns: - * true: if the IA setup command was successfully issued and completed - * false: otherwise - */ -unsigned char -e100_setup_iaaddr(struct e100_private *bdp, u8 *eaddr) -{ - unsigned int i; - cb_header_t *ntcb_hdr; - unsigned char res; - nxmit_cb_entry_t *cmd; - - if ((cmd = e100_alloc_non_tx_cmd(bdp)) == NULL) { - res = false; - goto exit; - } - - ntcb_hdr = (cb_header_t *) cmd->non_tx_cmd; - ntcb_hdr->cb_cmd = __constant_cpu_to_le16(CB_IA_ADDRESS); - - for (i = 0; i < ETH_ALEN; i++) { - (cmd->non_tx_cmd)->ntcb.setup.ia_addr[i] = eaddr[i]; - } - - res = e100_exec_non_cu_cmd(bdp, cmd); - if (!res) - printk(KERN_WARNING "e100: %s: IA setup failed\n", - bdp->device->name); - -exit: - return res; -} - -/** - * e100_start_ru - start the RU if needed - * @bdp: atapter's private data struct - * - * This routine checks the status of the 82557's receive unit(RU), - * and starts the RU if it was not already active. However, - * before restarting the RU, the driver gives the RU the buffers - * it freed up during the servicing of the ISR. If there are - * no free buffers to give to the RU, (i.e. we have reached a - * no resource condition) the RU will not be started till the - * next ISR. - */ -void -e100_start_ru(struct e100_private *bdp) -{ - struct rx_list_elem *rx_struct = NULL; - int buffer_found = 0; - struct list_head *entry_ptr; - - list_for_each(entry_ptr, &(bdp->active_rx_list)) { - rx_struct = - list_entry(entry_ptr, struct rx_list_elem, list_elem); - pci_dma_sync_single(bdp->pdev, rx_struct->dma_addr, - bdp->rfd_size, PCI_DMA_FROMDEVICE); - if (!((SKB_RFD_STATUS(rx_struct->skb, bdp) & - __constant_cpu_to_le16(RFD_STATUS_COMPLETE)))) { - buffer_found = 1; - break; - } - } - - /* No available buffers */ - if (!buffer_found) { - return; - } - - spin_lock(&bdp->bd_lock); - - if (!e100_wait_exec_cmplx(bdp, rx_struct->dma_addr, SCB_RUC_START, 0)) { - printk(KERN_DEBUG - "e100: %s: start_ru: wait_scb failed\n", - bdp->device->name); - e100_exec_cmplx(bdp, rx_struct->dma_addr, SCB_RUC_START); - } - if (bdp->next_cu_cmd == RESUME_NO_WAIT) { - bdp->next_cu_cmd = RESUME_WAIT; - } - spin_unlock(&bdp->bd_lock); -} - -/** - * e100_cmd_complete_location - * @bdp: atapter's private data struct - * - * This routine returns a pointer to the location of the command-complete - * DWord in the dump statistical counters area, according to the statistical - * counters mode (557 - basic, 558 - extended, or 559 - TCO mode). - * See e100_config_init() for the setting of the statistical counters mode. - */ -static u32 * -e100_cmd_complete_location(struct e100_private *bdp) -{ - u32 *cmd_complete; - max_counters_t *stats = bdp->stats_counters; - - switch (bdp->stat_mode) { - case E100_EXTENDED_STATS: - cmd_complete = - (u32 *) &(((err_cntr_558_t *) (stats))->cmd_complete); - break; - - case E100_TCO_STATS: - cmd_complete = - (u32 *) &(((err_cntr_559_t *) (stats))->cmd_complete); - break; - - case E100_BASIC_STATS: - default: - cmd_complete = - (u32 *) &(((err_cntr_557_t *) (stats))->cmd_complete); - break; - } - - return cmd_complete; -} - -/** - * e100_clr_cntrs - clear statistics counters - * @bdp: atapter's private data struct - * - * This routine will clear the adapter error statistic counters. - * - * Returns: - * true: if successfully cleared stat counters - * false: otherwise - */ -static unsigned char __devinit -e100_clr_cntrs(struct e100_private *bdp) -{ - volatile u32 *pcmd_complete; - - /* clear the dump counter complete word */ - pcmd_complete = e100_cmd_complete_location(bdp); - *pcmd_complete = 0; - wmb(); - - if (!e100_wait_exec_cmplx(bdp, bdp->stat_cnt_phys, SCB_CUC_DUMP_ADDR, 0)) - return false; - - /* wait 10 microseconds for the command to complete */ - udelay(10); - - if (!e100_wait_exec_simple(bdp, SCB_CUC_DUMP_RST_STAT)) - return false; - - if (bdp->next_cu_cmd == RESUME_NO_WAIT) { - bdp->next_cu_cmd = RESUME_WAIT; - } - - return true; -} - -static unsigned char -e100_update_stats(struct e100_private *bdp) -{ - u32 *pcmd_complete; - basic_cntr_t *pstat = &(bdp->stats_counters->basic_stats); - - // check if last dump command completed - pcmd_complete = e100_cmd_complete_location(bdp); - if (*pcmd_complete != le32_to_cpu(DUMP_RST_STAT_COMPLETED) && - *pcmd_complete != le32_to_cpu(DUMP_STAT_COMPLETED)) { - return false; - } - - /* increment the statistics */ - bdp->drv_stats.net_stats.rx_packets += - le32_to_cpu(pstat->rcv_gd_frames); - bdp->drv_stats.net_stats.tx_packets += - le32_to_cpu(pstat->xmt_gd_frames); - bdp->drv_stats.net_stats.rx_dropped += le32_to_cpu(pstat->rcv_rsrc_err); - bdp->drv_stats.net_stats.collisions += le32_to_cpu(pstat->xmt_ttl_coll); - bdp->drv_stats.net_stats.rx_length_errors += - le32_to_cpu(pstat->rcv_shrt_frames); - bdp->drv_stats.net_stats.rx_over_errors += - le32_to_cpu(pstat->rcv_rsrc_err); - bdp->drv_stats.net_stats.rx_crc_errors += - le32_to_cpu(pstat->rcv_crc_errs); - bdp->drv_stats.net_stats.rx_frame_errors += - le32_to_cpu(pstat->rcv_algn_errs); - bdp->drv_stats.net_stats.rx_fifo_errors += - le32_to_cpu(pstat->rcv_oruns); - bdp->drv_stats.net_stats.tx_aborted_errors += - le32_to_cpu(pstat->xmt_max_coll); - bdp->drv_stats.net_stats.tx_carrier_errors += - le32_to_cpu(pstat->xmt_lost_crs); - bdp->drv_stats.net_stats.tx_fifo_errors += - le32_to_cpu(pstat->xmt_uruns); - - bdp->drv_stats.tx_late_col += le32_to_cpu(pstat->xmt_late_coll); - bdp->drv_stats.tx_ok_defrd += le32_to_cpu(pstat->xmt_deferred); - bdp->drv_stats.tx_one_retry += le32_to_cpu(pstat->xmt_sngl_coll); - bdp->drv_stats.tx_mt_one_retry += le32_to_cpu(pstat->xmt_mlt_coll); - bdp->drv_stats.rcv_cdt_frames += le32_to_cpu(pstat->rcv_err_coll); - - if (bdp->stat_mode != E100_BASIC_STATS) { - ext_cntr_t *pex_stat = &bdp->stats_counters->extended_stats; - - bdp->drv_stats.xmt_fc_pkts += - le32_to_cpu(pex_stat->xmt_fc_frames); - bdp->drv_stats.rcv_fc_pkts += - le32_to_cpu(pex_stat->rcv_fc_frames); - bdp->drv_stats.rcv_fc_unsupported += - le32_to_cpu(pex_stat->rcv_fc_unsupported); - } - - if (bdp->stat_mode == E100_TCO_STATS) { - tco_cntr_t *ptco_stat = &bdp->stats_counters->tco_stats; - - bdp->drv_stats.xmt_tco_pkts += - le16_to_cpu(ptco_stat->xmt_tco_frames); - bdp->drv_stats.rcv_tco_pkts += - le16_to_cpu(ptco_stat->rcv_tco_frames); - } - - *pcmd_complete = 0; - return true; -} - -/** - * e100_dump_stat_cntrs - * @bdp: atapter's private data struct - * - * This routine will dump the board statistical counters without waiting - * for stat_dump to complete. Any access to this stats should verify the completion - * of the command - */ -void -e100_dump_stats_cntrs(struct e100_private *bdp) -{ - unsigned long lock_flag_bd; - - spin_lock_irqsave(&(bdp->bd_lock), lock_flag_bd); - - /* dump h/w stats counters */ - if (e100_wait_exec_simple(bdp, SCB_CUC_DUMP_RST_STAT)) { - if (bdp->next_cu_cmd == RESUME_NO_WAIT) { - bdp->next_cu_cmd = RESUME_WAIT; - } - } - - spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag_bd); -} - -/** - * e100_exec_non_cu_cmd - * @bdp: atapter's private data struct - * @command: the non-cu command to execute - * - * This routine will submit a command block to be executed, - */ -unsigned char -e100_exec_non_cu_cmd(struct e100_private *bdp, nxmit_cb_entry_t *command) -{ - cb_header_t *ntcb_hdr; - unsigned long lock_flag; - unsigned long expiration_time; - unsigned char rc = true; - u8 sub_cmd; - - ntcb_hdr = (cb_header_t *) command->non_tx_cmd; /* get hdr of non tcb cmd */ - sub_cmd = cpu_to_le16(ntcb_hdr->cb_cmd); - - /* Set the Command Block to be the last command block */ - ntcb_hdr->cb_cmd |= __constant_cpu_to_le16(CB_EL_BIT); - ntcb_hdr->cb_status = 0; - ntcb_hdr->cb_lnk_ptr = 0; - - wmb(); - if (in_interrupt()) - return e100_delayed_exec_non_cu_cmd(bdp, command); - - if (netif_running(bdp->device) && netif_carrier_ok(bdp->device)) - return e100_delayed_exec_non_cu_cmd(bdp, command); - - spin_lock_bh(&(bdp->bd_non_tx_lock)); - - if (bdp->non_tx_command_state != E100_NON_TX_IDLE) { - goto delayed_exec; - } - - if (bdp->last_tcb) { - rmb(); - if ((bdp->last_tcb->tcb_hdr.cb_status & - __constant_cpu_to_le16(CB_STATUS_COMPLETE)) == 0) - goto delayed_exec; - } - - if ((readw(&bdp->scb->scb_status) & SCB_CUS_MASK) == SCB_CUS_ACTIVE) { - goto delayed_exec; - } - - spin_lock_irqsave(&bdp->bd_lock, lock_flag); - - if (!e100_wait_exec_cmplx(bdp, command->dma_addr, SCB_CUC_START, sub_cmd)) { - spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag); - rc = false; - goto exit; - } - - bdp->next_cu_cmd = START_WAIT; - spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag); - - /* now wait for completion of non-cu CB up to 20 msec */ - expiration_time = jiffies + HZ / 50 + 1; - rmb(); - while (!(ntcb_hdr->cb_status & - __constant_cpu_to_le16(CB_STATUS_COMPLETE))) { - - if (time_before(jiffies, expiration_time)) { - spin_unlock_bh(&(bdp->bd_non_tx_lock)); - yield(); - spin_lock_bh(&(bdp->bd_non_tx_lock)); - } else { -#ifdef E100_CU_DEBUG - printk(KERN_ERR "e100: %s: non-TX command (%x) " - "timeout\n", bdp->device->name, sub_cmd); -#endif - rc = false; - goto exit; - } - rmb(); - } - -exit: - e100_free_non_tx_cmd(bdp, command); - - if (netif_running(bdp->device)) - netif_wake_queue(bdp->device); - - spin_unlock_bh(&(bdp->bd_non_tx_lock)); - return rc; - -delayed_exec: - spin_unlock_bh(&(bdp->bd_non_tx_lock)); - return e100_delayed_exec_non_cu_cmd(bdp, command); -} - -/** - * e100_sw_reset - * @bdp: atapter's private data struct - * @reset_cmd: s/w reset or selective reset - * - * This routine will issue a software reset to the adapter. It - * will also disable interrupts, as the are enabled after reset. - */ -void -e100_sw_reset(struct e100_private *bdp, u32 reset_cmd) -{ - /* Do a selective reset first to avoid a potential PCI hang */ - writel(PORT_SELECTIVE_RESET, &bdp->scb->scb_port); - readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */ - - /* wait for the reset to take effect */ - udelay(20); - if (reset_cmd == PORT_SOFTWARE_RESET) { - writel(PORT_SOFTWARE_RESET, &bdp->scb->scb_port); - - /* wait 20 micro seconds for the reset to take effect */ - udelay(20); - } - - /* Mask off our interrupt line -- it is unmasked after reset */ - e100_disable_clear_intr(bdp); -#ifdef E100_CU_DEBUG - bdp->last_cmd = 0; - bdp->last_sub_cmd = 0; -#endif -} - -/** - * e100_load_microcode - Download microsocde to controller. - * @bdp: atapter's private data struct - * - * This routine downloads microcode on to the controller. This - * microcode is available for the 82558/9, 82550. Currently the - * microcode handles interrupt bundling and TCO workaround. - * - * Returns: - * true: if successfull - * false: otherwise - */ -static unsigned char -e100_load_microcode(struct e100_private *bdp) -{ - static struct { - u8 rev_id; - u32 ucode[UCODE_MAX_DWORDS + 1]; - int timer_dword; - int bundle_dword; - int min_size_dword; - } ucode_opts[] = { - { D101A4_REV_ID, - D101_A_RCVBUNDLE_UCODE, - D101_CPUSAVER_TIMER_DWORD, - D101_CPUSAVER_BUNDLE_DWORD, - D101_CPUSAVER_MIN_SIZE_DWORD }, - { D101B0_REV_ID, - D101_B0_RCVBUNDLE_UCODE, - D101_CPUSAVER_TIMER_DWORD, - D101_CPUSAVER_BUNDLE_DWORD, - D101_CPUSAVER_MIN_SIZE_DWORD }, - { D101MA_REV_ID, - D101M_B_RCVBUNDLE_UCODE, - D101M_CPUSAVER_TIMER_DWORD, - D101M_CPUSAVER_BUNDLE_DWORD, - D101M_CPUSAVER_MIN_SIZE_DWORD }, - { D101S_REV_ID, - D101S_RCVBUNDLE_UCODE, - D101S_CPUSAVER_TIMER_DWORD, - D101S_CPUSAVER_BUNDLE_DWORD, - D101S_CPUSAVER_MIN_SIZE_DWORD }, - { D102_REV_ID, - D102_B_RCVBUNDLE_UCODE, - D102_B_CPUSAVER_TIMER_DWORD, - D102_B_CPUSAVER_BUNDLE_DWORD, - D102_B_CPUSAVER_MIN_SIZE_DWORD }, - { D102C_REV_ID, - D102_C_RCVBUNDLE_UCODE, - D102_C_CPUSAVER_TIMER_DWORD, - D102_C_CPUSAVER_BUNDLE_DWORD, - D102_C_CPUSAVER_MIN_SIZE_DWORD }, - { D102E_REV_ID, - D102_E_RCVBUNDLE_UCODE, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { 0, {0}, 0, 0, 0} - }, *opts; - - opts = ucode_opts; - - /* User turned ucode loading off */ - if (!(bdp->params.b_params & PRM_UCODE)) - return false; - - /* These controllers do not need ucode */ - if (bdp->flags & IS_ICH) - return false; - - /* Search for ucode match against h/w rev_id */ - while (opts->rev_id) { - if (bdp->rev_id == opts->rev_id) { - int i; - u32 *ucode_dword; - load_ucode_cb_t *ucode_cmd_ptr; - nxmit_cb_entry_t *cmd = e100_alloc_non_tx_cmd(bdp); - - if (cmd != NULL) { - ucode_cmd_ptr = - (load_ucode_cb_t *) cmd->non_tx_cmd; - ucode_dword = ucode_cmd_ptr->ucode_dword; - } else { - return false; - } - - memcpy(ucode_dword, opts->ucode, sizeof (opts->ucode)); - - /* Insert user-tunable settings */ - ucode_dword[opts->timer_dword] &= 0xFFFF0000; - ucode_dword[opts->timer_dword] |= - (u16) bdp->params.IntDelay; - ucode_dword[opts->bundle_dword] &= 0xFFFF0000; - ucode_dword[opts->bundle_dword] |= - (u16) bdp->params.BundleMax; - ucode_dword[opts->min_size_dword] &= 0xFFFF0000; - ucode_dword[opts->min_size_dword] |= - (bdp->params.b_params & PRM_BUNDLE_SMALL) ? - 0xFFFF : 0xFF80; - - for (i = 0; i < UCODE_MAX_DWORDS; i++) - cpu_to_le32s(&(ucode_dword[i])); - - ucode_cmd_ptr->load_ucode_cbhdr.cb_cmd = - __constant_cpu_to_le16(CB_LOAD_MICROCODE); - - return e100_exec_non_cu_cmd(bdp, cmd); - } - opts++; - } - - return false; -} - -/***************************************************************************/ -/***************************************************************************/ -/* EEPROM Functions */ -/***************************************************************************/ - -/* Read PWA (printed wired assembly) number */ -void __devinit -e100_rd_pwa_no(struct e100_private *bdp) -{ - bdp->pwa_no = e100_eeprom_read(bdp, EEPROM_PWA_NO); - bdp->pwa_no <<= 16; - bdp->pwa_no |= e100_eeprom_read(bdp, EEPROM_PWA_NO + 1); -} - -/* Read the permanent ethernet address from the eprom. */ -void __devinit -e100_rd_eaddr(struct e100_private *bdp) -{ - int i; - u16 eeprom_word; - - for (i = 0; i < 6; i += 2) { - eeprom_word = - e100_eeprom_read(bdp, - EEPROM_NODE_ADDRESS_BYTE_0 + (i / 2)); - - bdp->device->dev_addr[i] = - bdp->perm_node_address[i] = (u8) eeprom_word; - bdp->device->dev_addr[i + 1] = - bdp->perm_node_address[i + 1] = (u8) (eeprom_word >> 8); - } -} - -/* Check the D102 RFD flags to see if the checksum passed */ -#if 0 -static unsigned char -e100_D102_check_checksum(rfd_t *rfd) -{ - if (((le16_to_cpu(rfd->rfd_header.cb_status)) & RFD_PARSE_BIT) - && (((rfd->rcvparserstatus & CHECKSUM_PROTOCOL_MASK) == - RFD_TCP_PACKET) - || ((rfd->rcvparserstatus & CHECKSUM_PROTOCOL_MASK) == - RFD_UDP_PACKET)) - && (rfd->checksumstatus & TCPUDP_CHECKSUM_BIT_VALID) - && (rfd->checksumstatus & TCPUDP_CHECKSUM_VALID)) { - return CHECKSUM_UNNECESSARY; - } - return CHECKSUM_NONE; -} -#endif /* 0 */ - -/** - * e100_D101M_checksum - * @bdp: atapter's private data struct - * @skb: skb received - * - * Sets the skb->csum value from D101 csum found at the end of the Rx frame. The - * D101M sums all words in frame excluding the ethernet II header (14 bytes) so - * in case the packet is ethernet II and the protocol is IP, all is need is to - * assign this value to skb->csum. - */ -#if 0 -static unsigned char -e100_D101M_checksum(struct e100_private *bdp, struct sk_buff *skb) -{ - unsigned short proto = (skb->protocol); - - if (proto == __constant_htons(ETH_P_IP)) { - - skb->csum = get_unaligned((u16 *) (skb->tail)); - return CHECKSUM_HW; - } - return CHECKSUM_NONE; -} -#endif /* 0 */ - -/***************************************************************************/ -/***************************************************************************/ -/***************************************************************************/ -/***************************************************************************/ -/* Auxilary Functions */ -/***************************************************************************/ - -/* Print the board's configuration */ -void __devinit -e100_print_brd_conf(struct e100_private *bdp) -{ - /* Print the string if checksum Offloading was enabled */ - if (bdp->flags & DF_CSUM_OFFLOAD) - printk(KERN_NOTICE " Hardware receive checksums enabled\n"); - else { - if (bdp->rev_id >= D101MA_REV_ID) - printk(KERN_NOTICE " Hardware receive checksums disabled\n"); - } - - if ((bdp->flags & DF_UCODE_LOADED)) - printk(KERN_NOTICE " cpu cycle saver enabled\n"); -} - -/** - * e100_pci_setup - setup the adapter's PCI information - * @pcid: adapter's pci_dev struct - * @bdp: atapter's private data struct - * - * This routine sets up all PCI information for the adapter. It enables the bus - * master bit (some BIOS don't do this), requests memory ans I/O regions, and - * calls ioremap() on the adapter's memory region. - * - * Returns: - * true: if successfull - * false: otherwise - */ -static unsigned char __devinit -e100_pci_setup(struct pci_dev *pcid, struct e100_private *bdp) -{ - struct net_device *dev = bdp->device; - int rc = 0; - - if ((rc = pci_enable_device(pcid)) != 0) { - goto err; - } - - /* dev and ven ID have already been checked so it is our device */ - pci_read_config_byte(pcid, PCI_REVISION_ID, (u8 *) &(bdp->rev_id)); - - /* address #0 is a memory region */ - dev->mem_start = pci_resource_start(pcid, 0); - dev->mem_end = dev->mem_start + sizeof (scb_t); - - /* address #1 is a IO region */ - dev->base_addr = pci_resource_start(pcid, 1); - - if ((rc = pci_request_regions(pcid, e100_short_driver_name)) != 0) { - goto err_disable; - } - - pci_enable_wake(pcid, 0, 0); - - /* if Bus Mastering is off, turn it on! */ - pci_set_master(pcid); - - /* address #0 is a memory mapping */ - bdp->scb = (scb_t *) ioremap_nocache(dev->mem_start, sizeof (scb_t)); - - if (!bdp->scb) { - printk(KERN_ERR "e100: %s: Failed to map PCI address 0x%lX\n", - dev->name, pci_resource_start(pcid, 0)); - rc = -ENOMEM; - goto err_region; - } - - return 0; - -err_region: - pci_release_regions(pcid); -err_disable: - pci_disable_device(pcid); -err: - return rc; -} - -void -e100_isolate_driver(struct e100_private *bdp) -{ - - /* Check if interface is up */ - /* NOTE: Can't use netif_running(bdp->device) because */ - /* dev_close clears __LINK_STATE_START before calling */ - /* e100_close (aka dev->stop) */ - if (bdp->device->flags & IFF_UP) { - e100_disable_clear_intr(bdp); - del_timer_sync(&bdp->watchdog_timer); - netif_carrier_off(bdp->device); - netif_stop_queue(bdp->device); - bdp->last_tcb = NULL; - } - e100_sw_reset(bdp, PORT_SELECTIVE_RESET); -} - -void -e100_set_speed_duplex(struct e100_private *bdp) -{ - int carrier_ok; - /* Device may lose link with some siwtches when */ - /* changing speed/duplex to non-autoneg. e100 */ - /* needs to remember carrier state in order to */ - /* start watchdog timer for recovering link */ - if ((carrier_ok = netif_carrier_ok(bdp->device))) - e100_isolate_driver(bdp); - e100_phy_set_speed_duplex(bdp, true); - e100_config_fc(bdp); /* re-config flow-control if necessary */ - e100_config(bdp); - if (carrier_ok) - e100_deisolate_driver(bdp, false); -} - -static void -e100_tcb_add_C_bit(struct e100_private *bdp) -{ - tcb_t *tcb = (tcb_t *) bdp->tcb_pool.data; - int i; - - for (i = 0; i < bdp->params.TxDescriptors; i++, tcb++) { - tcb->tcb_hdr.cb_status |= cpu_to_le16(CB_STATUS_COMPLETE); - } -} - -/* - * Procedure: e100_configure_device - * - * Description: This routine will configure device - * - * Arguments: - * bdp - Ptr to this card's e100_bdconfig structure - * - * Returns: - * true upon success - * false upon failure - */ -unsigned char -e100_configure_device(struct e100_private *bdp) -{ - /*load CU & RU base */ - if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0)) - return false; - - if (e100_load_microcode(bdp)) - bdp->flags |= DF_UCODE_LOADED; - - if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0)) - return false; - - /* Issue the load dump counters address command */ - if (!e100_wait_exec_cmplx(bdp, bdp->stat_cnt_phys, SCB_CUC_DUMP_ADDR, 0)) - return false; - - if (!e100_setup_iaaddr(bdp, bdp->device->dev_addr)) { - printk(KERN_ERR "e100: e100_configure_device: " - "setup iaaddr failed\n"); - return false; - } - - e100_set_multi_exec(bdp->device); - - /* Change for 82558 enhancement */ - /* If 82558/9 and if the user has enabled flow control, set up */ - /* flow Control Reg. in the CSR */ - if ((bdp->flags & IS_BACHELOR) - && (bdp->params.b_params & PRM_FC)) { - writeb(DFLT_FC_THLD, - &bdp->scb->scb_ext.d101_scb.scb_fc_thld); - writeb(DFLT_FC_CMD, - &bdp->scb->scb_ext.d101_scb.scb_fc_xon_xoff); - } - - e100_force_config(bdp); - - return true; -} - -void -e100_deisolate_driver(struct e100_private *bdp, u8 full_reset) -{ - u32 cmd = full_reset ? PORT_SOFTWARE_RESET : PORT_SELECTIVE_RESET; - e100_sw_reset(bdp, cmd); - if (cmd == PORT_SOFTWARE_RESET) { - if (!e100_configure_device(bdp)) - printk(KERN_ERR "e100: e100_deisolate_driver:" - " device configuration failed\n"); - } - - if (netif_running(bdp->device)) { - - bdp->next_cu_cmd = START_WAIT; - bdp->last_tcb = NULL; - - e100_start_ru(bdp); - - /* relaunch watchdog timer in 2 sec */ - mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ)); - - // we must clear tcbs since we may have lost Tx intrrupt - // or have unsent frames on the tcb chain - e100_tcb_add_C_bit(bdp); - e100_tx_srv(bdp); - netif_wake_queue(bdp->device); - e100_set_intr_mask(bdp); - } -} - -#if 0 -static int -e100_do_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr) -{ - struct ethtool_cmd ecmd; - int rc = -EOPNOTSUPP; - - if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd.cmd))) - return -EFAULT; - - switch (ecmd.cmd) { - case ETHTOOL_GSET: - rc = e100_ethtool_get_settings(dev, ifr); - break; - case ETHTOOL_SSET: - rc = e100_ethtool_set_settings(dev, ifr); - break; - case ETHTOOL_GDRVINFO: - rc = e100_ethtool_get_drvinfo(dev, ifr); - break; - case ETHTOOL_GREGS: - rc = e100_ethtool_gregs(dev, ifr); - break; - case ETHTOOL_NWAY_RST: - rc = e100_ethtool_nway_rst(dev, ifr); - break; - case ETHTOOL_GLINK: - rc = e100_ethtool_glink(dev, ifr); - break; - case ETHTOOL_GEEPROM: - case ETHTOOL_SEEPROM: - rc = e100_ethtool_eeprom(dev, ifr); - break; - case ETHTOOL_GSTATS: { - struct { - struct ethtool_stats cmd; - uint64_t data[E100_STATS_LEN]; - } stats = { {ETHTOOL_GSTATS, E100_STATS_LEN} }; - struct e100_private *bdp = dev->priv; - void *addr = ifr->ifr_data; - int i; - - for(i = 0; i < E100_STATS_LEN; i++) - stats.data[i] = - ((unsigned long *)&bdp->drv_stats.net_stats)[i]; - if(copy_to_user(addr, &stats, sizeof(stats))) - return -EFAULT; - return 0; - } - case ETHTOOL_GWOL: - case ETHTOOL_SWOL: - rc = e100_ethtool_wol(dev, ifr); - break; - case ETHTOOL_TEST: - rc = e100_ethtool_test(dev, ifr); - break; - case ETHTOOL_GSTRINGS: - rc = e100_ethtool_gstrings(dev,ifr); - break; - case ETHTOOL_PHYS_ID: - rc = e100_ethtool_led_blink(dev,ifr); - break; - default: - break; - } //switch - return rc; -} - -static int -e100_ethtool_get_settings(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - struct ethtool_cmd ecmd; - u16 advert = 0; - - memset((void *) &ecmd, 0, sizeof (ecmd)); - - bdp = dev->priv; - - ecmd.supported = bdp->speed_duplex_caps; - - ecmd.port = - (bdp->speed_duplex_caps & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE; - ecmd.transceiver = XCVR_INTERNAL; - ecmd.phy_address = bdp->phy_addr; - - if (netif_carrier_ok(bdp->device)) { - ecmd.speed = bdp->cur_line_speed; - ecmd.duplex = - (bdp->cur_dplx_mode == HALF_DUPLEX) ? DUPLEX_HALF : DUPLEX_FULL; - } - else { - ecmd.speed = -1; - ecmd.duplex = -1; - } - - ecmd.advertising = ADVERTISED_TP; - - if (bdp->params.e100_speed_duplex == E100_AUTONEG) { - ecmd.autoneg = AUTONEG_ENABLE; - ecmd.advertising |= ADVERTISED_Autoneg; - } else { - ecmd.autoneg = AUTONEG_DISABLE; - } - - if (bdp->speed_duplex_caps & SUPPORTED_MII) { - e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &advert); - - if (advert & ADVERTISE_10HALF) - ecmd.advertising |= ADVERTISED_10baseT_Half; - if (advert & ADVERTISE_10FULL) - ecmd.advertising |= ADVERTISED_10baseT_Full; - if (advert & ADVERTISE_100HALF) - ecmd.advertising |= ADVERTISED_100baseT_Half; - if (advert & ADVERTISE_100FULL) - ecmd.advertising |= ADVERTISED_100baseT_Full; - } else { - ecmd.autoneg = AUTONEG_DISABLE; - ecmd.advertising &= ~ADVERTISED_Autoneg; - } - - if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd))) - return -EFAULT; - - return 0; -} - -static int -e100_ethtool_set_settings(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - int e100_new_speed_duplex; - int ethtool_new_speed_duplex; - struct ethtool_cmd ecmd; - - if (!capable(CAP_NET_ADMIN)) { - return -EPERM; - } - - bdp = dev->priv; - if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) { - return -EFAULT; - } - - if ((ecmd.autoneg == AUTONEG_ENABLE) - && (bdp->speed_duplex_caps & SUPPORTED_Autoneg)) { - bdp->params.e100_speed_duplex = E100_AUTONEG; - e100_set_speed_duplex(bdp); - } else { - if (ecmd.speed == SPEED_10) { - if (ecmd.duplex == DUPLEX_HALF) { - e100_new_speed_duplex = - E100_SPEED_10_HALF; - ethtool_new_speed_duplex = - SUPPORTED_10baseT_Half; - } else { - e100_new_speed_duplex = - E100_SPEED_10_FULL; - ethtool_new_speed_duplex = - SUPPORTED_10baseT_Full; - } - } else { - if (ecmd.duplex == DUPLEX_HALF) { - e100_new_speed_duplex = - E100_SPEED_100_HALF; - ethtool_new_speed_duplex = - SUPPORTED_100baseT_Half; - } else { - e100_new_speed_duplex = - E100_SPEED_100_FULL; - ethtool_new_speed_duplex = - SUPPORTED_100baseT_Full; - } - } - - if (bdp->speed_duplex_caps & ethtool_new_speed_duplex) { - bdp->params.e100_speed_duplex = - e100_new_speed_duplex; - e100_set_speed_duplex(bdp); - } else { - return -EOPNOTSUPP; - } - } - - return 0; -} - -static int -e100_ethtool_glink(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - struct ethtool_value info; - - memset((void *) &info, 0, sizeof (info)); - - bdp = dev->priv; - info.cmd = ETHTOOL_GLINK; - - /* Consider both PHY link and netif_running */ - info.data = e100_update_link_state(bdp); - - if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) - return -EFAULT; - - return 0; -} - -static int -e100_ethtool_test(struct net_device *dev, struct ifreq *ifr) -{ - struct ethtool_test *info; - int rc = -EFAULT; - - info = kmalloc(sizeof(*info) + E100_MAX_TEST_RES * sizeof(u64), - GFP_ATOMIC); - - if (!info) - return -ENOMEM; - - memset((void *) info, 0, sizeof(*info) + - E100_MAX_TEST_RES * sizeof(u64)); - - if (copy_from_user(info, ifr->ifr_data, sizeof(*info))) - goto exit; - - info->flags = e100_run_diag(dev, info->data, info->flags); - - if (!copy_to_user(ifr->ifr_data, info, - sizeof(*info) + E100_MAX_TEST_RES * sizeof(u64))) - rc = 0; -exit: - kfree(info); - return rc; -} - -static int -e100_ethtool_gregs(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - u32 regs_buff[E100_REGS_LEN]; - struct ethtool_regs regs = {ETHTOOL_GREGS}; - void *addr = ifr->ifr_data; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - bdp = dev->priv; - - if(copy_from_user(®s, addr, sizeof(regs))) - return -EFAULT; - - regs.version = (1 << 24) | bdp->rev_id; - regs_buff[0] = readb(&(bdp->scb->scb_cmd_hi)) << 24 | - readb(&(bdp->scb->scb_cmd_low)) << 16 | - readw(&(bdp->scb->scb_status)); - - if(copy_to_user(addr, ®s, sizeof(regs))) - return -EFAULT; - - addr += offsetof(struct ethtool_regs, data); - if(copy_to_user(addr, regs_buff, regs.len)) - return -EFAULT; - - return 0; -} - -static int -e100_ethtool_nway_rst(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - bdp = dev->priv; - - if ((bdp->speed_duplex_caps & SUPPORTED_Autoneg) && - (bdp->params.e100_speed_duplex == E100_AUTONEG)) { - e100_set_speed_duplex(bdp); - } else { - return -EFAULT; - } - return 0; -} - -static int -e100_ethtool_get_drvinfo(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - struct ethtool_drvinfo info; - - memset((void *) &info, 0, sizeof (info)); - - bdp = dev->priv; - - strncpy(info.driver, e100_short_driver_name, sizeof (info.driver) - 1); - strncpy(info.version, e100_driver_version, sizeof (info.version) - 1); - strncpy(info.fw_version, "N/A", - sizeof (info.fw_version) - 1); - strncpy(info.bus_info, bdp->pdev->slot_name, - sizeof (info.bus_info) - 1); - info.n_stats = E100_STATS_LEN; - info.regdump_len = E100_REGS_LEN * sizeof(u32); - info.eedump_len = (bdp->eeprom_size << 1); - info.testinfo_len = E100_MAX_TEST_RES; - if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) - return -EFAULT; - - return 0; -} - -static int -e100_ethtool_eeprom(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - struct ethtool_eeprom ecmd; - u16 eeprom_data[256]; - u16 *usr_eeprom_ptr; - u16 first_word, last_word; - int i, max_len; - void *ptr; - u8 *eeprom_data_bytes = (u8 *)eeprom_data; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - bdp = dev->priv; - - if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) - return -EFAULT; - - usr_eeprom_ptr = - (u16 *) (ifr->ifr_data + offsetof(struct ethtool_eeprom, data)); - - max_len = bdp->eeprom_size * 2; - - if (ecmd.offset > ecmd.offset + ecmd.len) - return -EINVAL; - - if ((ecmd.offset + ecmd.len) > max_len) - ecmd.len = (max_len - ecmd.offset); - - first_word = ecmd.offset >> 1; - last_word = (ecmd.offset + ecmd.len - 1) >> 1; - - if (first_word >= bdp->eeprom_size) - return -EFAULT; - - if (ecmd.cmd == ETHTOOL_GEEPROM) { - for(i = 0; i <= (last_word - first_word); i++) - eeprom_data[i] = e100_eeprom_read(bdp, first_word + i); - - ecmd.magic = E100_EEPROM_MAGIC; - - if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd))) - return -EFAULT; - - if(ecmd.offset & 1) - eeprom_data_bytes++; - if (copy_to_user(usr_eeprom_ptr, eeprom_data_bytes, ecmd.len)) - return -EFAULT; - } else { - if (ecmd.magic != E100_EEPROM_MAGIC) - return -EFAULT; - - ptr = (void *)eeprom_data; - if(ecmd.offset & 1) { - /* need modification of first changed EEPROM word */ - /* only the second byte of the word is being modified */ - eeprom_data[0] = e100_eeprom_read(bdp, first_word); - ptr++; - } - if((ecmd.offset + ecmd.len) & 1) { - /* need modification of last changed EEPROM word */ - /* only the first byte of the word is being modified */ - eeprom_data[last_word - first_word] = - e100_eeprom_read(bdp, last_word); - } - if(copy_from_user(ptr, usr_eeprom_ptr, ecmd.len)) - return -EFAULT; - - e100_eeprom_write_block(bdp, first_word, eeprom_data, - last_word - first_word + 1); - - if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd))) - return -EFAULT; - } - return 0; -} -#endif - -#if 0 -#define E100_BLINK_INTERVAL (HZ/4) -/** - * e100_led_control - * @bdp: atapter's private data struct - * @led_mdi_op: led operation - * - * Software control over adapter's led. The possible operations are: - * TURN LED OFF, TURN LED ON and RETURN LED CONTROL TO HARDWARE. - */ -static void -e100_led_control(struct e100_private *bdp, u16 led_mdi_op) -{ - e100_mdi_write(bdp, PHY_82555_LED_SWITCH_CONTROL, - bdp->phy_addr, led_mdi_op); - -} -/** - * e100_led_blink_callback - * @data: pointer to atapter's private data struct - * - * Blink timer callback function. Toggles ON/OFF led status bit and calls - * led hardware access function. - */ -static void -e100_led_blink_callback(unsigned long data) -{ - struct e100_private *bdp = (struct e100_private *) data; - - if(bdp->flags & LED_IS_ON) { - bdp->flags &= ~LED_IS_ON; - e100_led_control(bdp, PHY_82555_LED_OFF); - } else { - bdp->flags |= LED_IS_ON; - if (bdp->rev_id >= D101MA_REV_ID) - e100_led_control(bdp, PHY_82555_LED_ON_559); - else - e100_led_control(bdp, PHY_82555_LED_ON_PRE_559); - } - - mod_timer(&bdp->blink_timer, jiffies + E100_BLINK_INTERVAL); -} -/** - * e100_ethtool_led_blink - * @dev: pointer to atapter's net_device struct - * @ifr: pointer to ioctl request structure - * - * Blink led ioctl handler. Initialtes blink timer and sleeps until - * blink period expires. Than it kills timer and returns. The led control - * is returned back to hardware when blink timer is killed. - */ -static int -e100_ethtool_led_blink(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - struct ethtool_value ecmd; - - bdp = dev->priv; - - if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) - return -EFAULT; - - if(!bdp->blink_timer.function) { - init_timer(&bdp->blink_timer); - bdp->blink_timer.function = e100_led_blink_callback; - bdp->blink_timer.data = (unsigned long) bdp; - } - - mod_timer(&bdp->blink_timer, jiffies); - - set_current_state(TASK_INTERRUPTIBLE); - - if ((!ecmd.data) || (ecmd.data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))) - ecmd.data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - - schedule_timeout(ecmd.data * HZ); - - del_timer_sync(&bdp->blink_timer); - - e100_led_control(bdp, PHY_82555_LED_NORMAL_CONTROL); - - return 0; -} -#endif - -static inline int __devinit -e100_10BaseT_adapter(struct e100_private *bdp) -{ - return ((bdp->pdev->device == 0x1229) && - (bdp->pdev->subsystem_vendor == 0x8086) && - (bdp->pdev->subsystem_device == 0x0003)); -} - -static void __devinit -e100_get_speed_duplex_caps(struct e100_private *bdp) -{ - u16 status; - - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &status); - - bdp->speed_duplex_caps = 0; - - bdp->speed_duplex_caps |= - (status & BMSR_ANEGCAPABLE) ? SUPPORTED_Autoneg : 0; - - bdp->speed_duplex_caps |= - (status & BMSR_10HALF) ? SUPPORTED_10baseT_Half : 0; - - bdp->speed_duplex_caps |= - (status & BMSR_10FULL) ? SUPPORTED_10baseT_Full : 0; - - bdp->speed_duplex_caps |= - (status & BMSR_100HALF) ? SUPPORTED_100baseT_Half : 0; - - bdp->speed_duplex_caps |= - (status & BMSR_100FULL) ? SUPPORTED_100baseT_Full : 0; - - if (IS_NC3133(bdp)) - bdp->speed_duplex_caps = - (SUPPORTED_FIBRE | SUPPORTED_100baseT_Full); - else - bdp->speed_duplex_caps |= SUPPORTED_TP; - - if ((status == 0xFFFF) && e100_10BaseT_adapter(bdp)) { - bdp->speed_duplex_caps = - (SUPPORTED_10baseT_Half | SUPPORTED_TP); - } else { - bdp->speed_duplex_caps |= SUPPORTED_MII; - } - -} - -#ifdef CONFIG_PM -static unsigned char -e100_setup_filter(struct e100_private *bdp) -{ - cb_header_t *ntcb_hdr; - unsigned char res = false; - nxmit_cb_entry_t *cmd; - - if ((cmd = e100_alloc_non_tx_cmd(bdp)) == NULL) { - goto exit; - } - - ntcb_hdr = (cb_header_t *) cmd->non_tx_cmd; - ntcb_hdr->cb_cmd = __constant_cpu_to_le16(CB_LOAD_FILTER); - - /* Set EL and FIX bit */ - (cmd->non_tx_cmd)->ntcb.filter.filter_data[0] = - __constant_cpu_to_le32(CB_FILTER_EL | CB_FILTER_FIX); - - if (bdp->wolopts & WAKE_UCAST) { - (cmd->non_tx_cmd)->ntcb.filter.filter_data[0] |= - __constant_cpu_to_le32(CB_FILTER_IA_MATCH); - } - - if (bdp->wolopts & WAKE_ARP) { - /* Setup ARP bit and lower IP parts */ - /* bdp->ip_lbytes contains 2 lower bytes of IP address in network byte order */ - (cmd->non_tx_cmd)->ntcb.filter.filter_data[0] |= - cpu_to_le32(CB_FILTER_ARP | bdp->ip_lbytes); - } - - res = e100_exec_non_cu_cmd(bdp, cmd); - if (!res) - printk(KERN_WARNING "e100: %s: Filter setup failed\n", - bdp->device->name); - -exit: - return res; - -} - -static void -e100_do_wol(struct pci_dev *pcid, struct e100_private *bdp) -{ - e100_config_wol(bdp); - - if (e100_config(bdp)) { - if (bdp->wolopts & (WAKE_UCAST | WAKE_ARP)) - if (!e100_setup_filter(bdp)) - printk(KERN_ERR - "e100: WOL options failed\n"); - } else { - printk(KERN_ERR "e100: config WOL failed\n"); - } -} -#endif - -#if 0 -static u16 -e100_get_ip_lbytes(struct net_device *dev) -{ - struct in_ifaddr *ifa; - struct in_device *in_dev; - u32 res = 0; - - in_dev = (struct in_device *) dev->ip_ptr; - /* Check if any in_device bound to interface */ - if (in_dev) { - /* Check if any IP address is bound to interface */ - if ((ifa = in_dev->ifa_list) != NULL) { - res = __constant_ntohl(ifa->ifa_address); - res = __constant_htons(res & 0x0000ffff); - } - } - return res; -} - -static int -e100_ethtool_wol(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - struct ethtool_wolinfo wolinfo; - int res = 0; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - bdp = dev->priv; - - if (copy_from_user(&wolinfo, ifr->ifr_data, sizeof (wolinfo))) { - return -EFAULT; - } - - switch (wolinfo.cmd) { - case ETHTOOL_GWOL: - wolinfo.supported = bdp->wolsupported; - wolinfo.wolopts = bdp->wolopts; - if (copy_to_user(ifr->ifr_data, &wolinfo, sizeof (wolinfo))) - res = -EFAULT; - break; - case ETHTOOL_SWOL: - /* If ALL requests are supported or request is DISABLE wol */ - if (((wolinfo.wolopts & bdp->wolsupported) == wolinfo.wolopts) - || (wolinfo.wolopts == 0)) { - bdp->wolopts = wolinfo.wolopts; - } else { - res = -EOPNOTSUPP; - } - if (wolinfo.wolopts & WAKE_ARP) - bdp->ip_lbytes = e100_get_ip_lbytes(dev); - break; - default: - break; - } - return res; -} - -static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr) -{ - struct ethtool_gstrings info; - char *strings = NULL; - char *usr_strings; - int i; - - memset((void *) &info, 0, sizeof(info)); - - usr_strings = (u8 *) (ifr->ifr_data + - offsetof(struct ethtool_gstrings, data)); - - if (copy_from_user(&info, ifr->ifr_data, sizeof (info))) - return -EFAULT; - - switch (info.string_set) { - case ETH_SS_TEST: { - int ret = 0; - if (info.len > E100_MAX_TEST_RES) - info.len = E100_MAX_TEST_RES; - strings = kmalloc(info.len * ETH_GSTRING_LEN, GFP_ATOMIC); - if (!strings) - return -ENOMEM; - memset(strings, 0, info.len * ETH_GSTRING_LEN); - - for (i = 0; i < info.len; i++) { - sprintf(strings + i * ETH_GSTRING_LEN, "%-31s", - test_strings[i]); - } - if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) - ret = -EFAULT; - if (copy_to_user(usr_strings, strings, info.len * ETH_GSTRING_LEN)) - ret = -EFAULT; - kfree(strings); - return ret; - } - case ETH_SS_STATS: { - char *strings = NULL; - void *addr = ifr->ifr_data; - info.len = E100_STATS_LEN; - strings = *e100_gstrings_stats; - if(copy_to_user(ifr->ifr_data, &info, sizeof(info))) - return -EFAULT; - addr += offsetof(struct ethtool_gstrings, data); - if(copy_to_user(addr, strings, - info.len * ETH_GSTRING_LEN)) - return -EFAULT; - return 0; - } - default: - return -EOPNOTSUPP; - } -} - -static int -e100_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct e100_private *bdp; - struct mii_ioctl_data *data_ptr = - (struct mii_ioctl_data *) &(ifr->ifr_data); - - bdp = dev->priv; - - switch (cmd) { - case SIOCGMIIPHY: - data_ptr->phy_id = bdp->phy_addr & 0x1f; - break; - - case SIOCGMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - e100_mdi_read(bdp, data_ptr->reg_num & 0x1f, bdp->phy_addr, - &(data_ptr->val_out)); - break; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - /* If reg = 0 && change speed/duplex */ - if (data_ptr->reg_num == 0 && - (data_ptr->val_in == (BMCR_ANENABLE | BMCR_ANRESTART) /* restart cmd */ - || data_ptr->val_in == (BMCR_RESET) /* reset cmd */ - || data_ptr->val_in & (BMCR_SPEED100 | BMCR_FULLDPLX) - || data_ptr->val_in == 0)) { - if (data_ptr->val_in == (BMCR_ANENABLE | BMCR_ANRESTART) - || data_ptr->val_in == (BMCR_RESET)) - bdp->params.e100_speed_duplex = E100_AUTONEG; - else if (data_ptr->val_in == (BMCR_SPEED100 | BMCR_FULLDPLX)) - bdp->params.e100_speed_duplex = E100_SPEED_100_FULL; - else if (data_ptr->val_in == (BMCR_SPEED100)) - bdp->params.e100_speed_duplex = E100_SPEED_100_HALF; - else if (data_ptr->val_in == (BMCR_FULLDPLX)) - bdp->params.e100_speed_duplex = E100_SPEED_10_FULL; - else - bdp->params.e100_speed_duplex = E100_SPEED_10_HALF; - e100_set_speed_duplex(bdp); - } - else - /* Only allows changing speed/duplex */ - return -EINVAL; - - break; - - default: - return -EOPNOTSUPP; - } - return 0; -} -#endif - -nxmit_cb_entry_t * -e100_alloc_non_tx_cmd(struct e100_private *bdp) -{ - nxmit_cb_entry_t *non_tx_cmd_elem; - - if (!(non_tx_cmd_elem = (nxmit_cb_entry_t *) - kmalloc(sizeof (nxmit_cb_entry_t), GFP_ATOMIC))) { - return NULL; - } - non_tx_cmd_elem->non_tx_cmd = - pci_alloc_consistent(bdp->pdev, sizeof (nxmit_cb_t), - &(non_tx_cmd_elem->dma_addr)); - if (non_tx_cmd_elem->non_tx_cmd == NULL) { - kfree(non_tx_cmd_elem); - return NULL; - } - return non_tx_cmd_elem; -} - -void -e100_free_non_tx_cmd(struct e100_private *bdp, - nxmit_cb_entry_t *non_tx_cmd_elem) -{ - pci_free_consistent(bdp->pdev, sizeof (nxmit_cb_t), - non_tx_cmd_elem->non_tx_cmd, - non_tx_cmd_elem->dma_addr); - kfree(non_tx_cmd_elem); -} - -static void -e100_free_nontx_list(struct e100_private *bdp) -{ - nxmit_cb_entry_t *command; - int i; - - while (!list_empty(&bdp->non_tx_cmd_list)) { - command = list_entry(bdp->non_tx_cmd_list.next, - nxmit_cb_entry_t, list_elem); - list_del(&(command->list_elem)); - e100_free_non_tx_cmd(bdp, command); - } - - for (i = 0; i < CB_MAX_NONTX_CMD; i++) { - bdp->same_cmd_entry[i] = NULL; - } -} - -static unsigned char -e100_delayed_exec_non_cu_cmd(struct e100_private *bdp, - nxmit_cb_entry_t *command) -{ - nxmit_cb_entry_t *same_command; - cb_header_t *ntcb_hdr; - u16 cmd; - - ntcb_hdr = (cb_header_t *) command->non_tx_cmd; - - cmd = CB_CMD_MASK & le16_to_cpu(ntcb_hdr->cb_cmd); - - spin_lock_bh(&(bdp->bd_non_tx_lock)); - - same_command = bdp->same_cmd_entry[cmd]; - - if (same_command != NULL) { - memcpy((void *) (same_command->non_tx_cmd), - (void *) (command->non_tx_cmd), sizeof (nxmit_cb_t)); - e100_free_non_tx_cmd(bdp, command); - } else { - list_add_tail(&(command->list_elem), &(bdp->non_tx_cmd_list)); - bdp->same_cmd_entry[cmd] = command; - } - - if (bdp->non_tx_command_state == E100_NON_TX_IDLE) { - bdp->non_tx_command_state = E100_WAIT_TX_FINISH; - mod_timer(&(bdp->nontx_timer_id), jiffies + 1); - } - - spin_unlock_bh(&(bdp->bd_non_tx_lock)); - return true; -} - -static void -e100_non_tx_background(unsigned long ptr) -{ - struct e100_private *bdp = (struct e100_private *) ptr; - nxmit_cb_entry_t *active_command; - int restart = true; - cb_header_t *non_tx_cmd; - u8 sub_cmd; - - spin_lock_bh(&(bdp->bd_non_tx_lock)); - - switch (bdp->non_tx_command_state) { - case E100_WAIT_TX_FINISH: - if (bdp->last_tcb != NULL) { - rmb(); - if ((bdp->last_tcb->tcb_hdr.cb_status & - __constant_cpu_to_le16(CB_STATUS_COMPLETE)) == 0) - goto exit; - } - if ((readw(&bdp->scb->scb_status) & SCB_CUS_MASK) == - SCB_CUS_ACTIVE) { - goto exit; - } - break; - - case E100_WAIT_NON_TX_FINISH: - active_command = list_entry(bdp->non_tx_cmd_list.next, - nxmit_cb_entry_t, list_elem); - rmb(); - - if (((((cb_header_t *) (active_command->non_tx_cmd))->cb_status - & __constant_cpu_to_le16(CB_STATUS_COMPLETE)) == 0) - && time_before(jiffies, active_command->expiration_time)) { - goto exit; - } else { - non_tx_cmd = (cb_header_t *) active_command->non_tx_cmd; - sub_cmd = CB_CMD_MASK & le16_to_cpu(non_tx_cmd->cb_cmd); -#ifdef E100_CU_DEBUG - if (!(non_tx_cmd->cb_status - & __constant_cpu_to_le16(CB_STATUS_COMPLETE))) - printk(KERN_ERR "e100: %s: Queued " - "command (%x) timeout\n", - bdp->device->name, sub_cmd); -#endif - list_del(&(active_command->list_elem)); - e100_free_non_tx_cmd(bdp, active_command); - } - break; - - default: - break; - } //switch - - if (list_empty(&bdp->non_tx_cmd_list)) { - bdp->non_tx_command_state = E100_NON_TX_IDLE; - spin_lock_irq(&(bdp->bd_lock)); - bdp->next_cu_cmd = START_WAIT; - spin_unlock_irq(&(bdp->bd_lock)); - restart = false; - goto exit; - } else { - u16 cmd_type; - - bdp->non_tx_command_state = E100_WAIT_NON_TX_FINISH; - active_command = list_entry(bdp->non_tx_cmd_list.next, - nxmit_cb_entry_t, list_elem); - sub_cmd = ((cb_header_t *) active_command->non_tx_cmd)->cb_cmd; - spin_lock_irq(&(bdp->bd_lock)); - e100_wait_exec_cmplx(bdp, active_command->dma_addr, - SCB_CUC_START, sub_cmd); - spin_unlock_irq(&(bdp->bd_lock)); - active_command->expiration_time = jiffies + HZ; - cmd_type = CB_CMD_MASK & - le16_to_cpu(((cb_header_t *) - (active_command->non_tx_cmd))->cb_cmd); - bdp->same_cmd_entry[cmd_type] = NULL; - } - -exit: - if (restart) { - mod_timer(&(bdp->nontx_timer_id), jiffies + 1); - } else { - if (netif_running(bdp->device)) - netif_wake_queue(bdp->device); - } - spin_unlock_bh(&(bdp->bd_non_tx_lock)); -} - -static void -e100_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) -{ - struct e100_private *bdp = netdev->priv; - - e100_disable_clear_intr(bdp); - bdp->vlgrp = grp; - - if(grp) { - /* enable VLAN tag insert/strip */ - e100_config_vlan_drop(bdp, true); - - } else { - /* disable VLAN tag insert/strip */ - e100_config_vlan_drop(bdp, false); - } - - e100_config(bdp); - e100_set_intr_mask(bdp); -} - -static void -e100_vlan_rx_add_vid(struct net_device *netdev, u16 vid) -{ - /* We don't do Vlan filtering */ - return; -} - -static void -e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) -{ - struct e100_private *bdp = netdev->priv; - - if(bdp->vlgrp) - bdp->vlgrp->vlan_devices[vid] = NULL; - /* We don't do Vlan filtering */ - return; -} - -#ifdef CONFIG_PM -static int -e100_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) -{ - struct pci_dev *pdev; - - switch(event) { - case SYS_DOWN: - case SYS_HALT: - case SYS_POWER_OFF: - pci_for_each_dev(pdev) { - if(pci_dev_driver(pdev) == &e100_driver) { - /* If net_device struct is allocated? */ - if (pci_get_drvdata(pdev)) - e100_suspend(pdev, 3); - - } - } - } - return NOTIFY_DONE; -} - -static int -e100_suspend(struct pci_dev *pcid, u32 state) -{ - struct net_device *netdev = pci_get_drvdata(pcid); - struct e100_private *bdp = netdev->priv; - - e100_isolate_driver(bdp); - pci_save_state(pcid, bdp->pci_state); - - /* Enable or disable WoL */ - e100_do_wol(pcid, bdp); - - /* If wol is enabled */ - if (bdp->wolopts || e100_asf_enabled(bdp)) { - pci_enable_wake(pcid, 3, 1); /* Enable PME for power state D3 */ - pci_set_power_state(pcid, 3); /* Set power state to D3. */ - } else { - /* Disable bus mastering */ - pci_disable_device(pcid); - pci_set_power_state(pcid, state); - } - return 0; -} - -static int -e100_resume(struct pci_dev *pcid) -{ - struct net_device *netdev = pci_get_drvdata(pcid); - struct e100_private *bdp = netdev->priv; - - pci_set_power_state(pcid, 0); - pci_enable_wake(pcid, 0, 0); /* Clear PME status and disable PME */ - pci_restore_state(pcid, bdp->pci_state); - - /* Also do device full reset because device was in D3 state */ - e100_deisolate_driver(bdp, true); - - return 0; -} - -/** - * e100_asf_enabled - checks if ASF is configured on the current adaper - * by reading registers 0xD and 0x90 in the EEPROM - * @bdp: atapter's private data struct - * - * Returns: true if ASF is enabled - */ -static unsigned char -e100_asf_enabled(struct e100_private *bdp) -{ - u16 asf_reg; - u16 smbus_addr_reg; - if ((bdp->pdev->device >= 0x1050) && (bdp->pdev->device <= 0x1055)) { - asf_reg = e100_eeprom_read(bdp, EEPROM_CONFIG_ASF); - if ((asf_reg & EEPROM_FLAG_ASF) - && !(asf_reg & EEPROM_FLAG_GCL)) { - smbus_addr_reg = - e100_eeprom_read(bdp, EEPROM_SMBUS_ADDR); - if ((smbus_addr_reg & 0xFF) != 0xFE) - return true; - } - } - return false; -} -#endif /* CONFIG_PM */ - -#ifdef E100_CU_DEBUG -unsigned char -e100_cu_unknown_state(struct e100_private *bdp) -{ - u8 scb_cmd_low; - u16 scb_status; - scb_cmd_low = bdp->scb->scb_cmd_low; - scb_status = le16_to_cpu(bdp->scb->scb_status); - /* If CU is active and executing unknown cmd */ - if (scb_status & SCB_CUS_ACTIVE && scb_cmd_low & SCB_CUC_UNKNOWN) - return true; - else - return false; -} -#endif - diff --git a/xen/drivers/net/e100/e100_phy.c b/xen/drivers/net/e100/e100_phy.c deleted file mode 100644 index 08782934bd..0000000000 --- a/xen/drivers/net/e100/e100_phy.c +++ /dev/null @@ -1,1160 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -#include "e100_phy.h" - -void e100_handle_zlock(struct e100_private *bdp); - -/* - * Procedure: e100_mdi_write - * - * Description: This routine will write a value to the specified MII register - * of an external MDI compliant device (e.g. PHY 100). The - * command will execute in polled mode. - * - * Arguments: - * bdp - Ptr to this card's e100_bdconfig structure - * reg_addr - The MII register that we are writing to - * phy_addr - The MDI address of the Phy component. - * data - The value that we are writing to the MII register. - * - * Returns: - * NOTHING - */ -int -e100_mdi_write(struct e100_private *bdp, u32 reg_addr, u32 phy_addr, u16 data) -{ - int e100_retry; - u32 temp_val; - unsigned int mdi_cntrl; - - spin_lock_bh(&bdp->mdi_access_lock); - temp_val = (((u32) data) | (reg_addr << 16) | - (phy_addr << 21) | (MDI_WRITE << 26)); - writel(temp_val, &bdp->scb->scb_mdi_cntrl); - readw(&bdp->scb->scb_status); - - /* wait 20usec before checking status */ - udelay(20); - - /* poll for the mdi write to complete */ - e100_retry = E100_CMD_WAIT; - while ((!((mdi_cntrl = readl(&bdp->scb->scb_mdi_cntrl)) & MDI_PHY_READY)) && (e100_retry)) { - - udelay(20); - e100_retry--; - } - spin_unlock_bh(&bdp->mdi_access_lock); - if (mdi_cntrl & MDI_PHY_READY) - return 0; - else { - printk(KERN_ERR "e100: MDI write timeout\n"); - return 1; - } -} - -/* - * Procedure: e100_mdi_read - * - * Description: This routine will read a value from the specified MII register - * of an external MDI compliant device (e.g. PHY 100), and return - * it to the calling routine. The command will execute in polled - * mode. - * - * Arguments: - * bdp - Ptr to this card's e100_bdconfig structure - * reg_addr - The MII register that we are reading from - * phy_addr - The MDI address of the Phy component. - * - * Results: - * data - The value that we read from the MII register. - * - * Returns: - * NOTHING - */ -int -e100_mdi_read(struct e100_private *bdp, u32 reg_addr, u32 phy_addr, u16 *data) -{ - int e100_retry; - u32 temp_val; - unsigned int mdi_cntrl; - - spin_lock_bh(&bdp->mdi_access_lock); - /* Issue the read command to the MDI control register. */ - temp_val = ((reg_addr << 16) | (phy_addr << 21) | (MDI_READ << 26)); - writel(temp_val, &bdp->scb->scb_mdi_cntrl); - readw(&bdp->scb->scb_status); - - /* wait 20usec before checking status */ - udelay(20); - - /* poll for the mdi read to complete */ - e100_retry = E100_CMD_WAIT; - while ((!((mdi_cntrl = readl(&bdp->scb->scb_mdi_cntrl)) & MDI_PHY_READY)) && (e100_retry)) { - - udelay(20); - e100_retry--; - } - - spin_unlock_bh(&bdp->mdi_access_lock); - if (mdi_cntrl & MDI_PHY_READY) { - /* return the lower word */ - *data = (u16) mdi_cntrl; - return 0; - } - else { - printk(KERN_ERR "e100: MDI read timeout\n"); - return 1; - } -} - -static unsigned char __devinit -e100_phy_valid(struct e100_private *bdp, unsigned int phy_address) -{ - u16 ctrl_reg, stat_reg; - - /* Read the MDI control register */ - e100_mdi_read(bdp, MII_BMCR, phy_address, &ctrl_reg); - - /* Read the status register twice, bacause of sticky bits */ - e100_mdi_read(bdp, MII_BMSR, phy_address, &stat_reg); - e100_mdi_read(bdp, MII_BMSR, phy_address, &stat_reg); - - if ((ctrl_reg == 0xffff) || ((stat_reg == 0) && (ctrl_reg == 0))) - return false; - - return true; -} - -static void __devinit -e100_phy_address_detect(struct e100_private *bdp) -{ - unsigned int addr; - unsigned char valid_phy_found = false; - - if (IS_NC3133(bdp)) { - bdp->phy_addr = 0; - return; - } - - if (e100_phy_valid(bdp, PHY_DEFAULT_ADDRESS)) { - bdp->phy_addr = PHY_DEFAULT_ADDRESS; - valid_phy_found = true; - - } else { - for (addr = MIN_PHY_ADDR; addr <= MAX_PHY_ADDR; addr++) { - if (e100_phy_valid(bdp, addr)) { - bdp->phy_addr = addr; - valid_phy_found = true; - break; - } - } - } - - if (!valid_phy_found) { - bdp->phy_addr = PHY_ADDRESS_503; - } -} - -static void __devinit -e100_phy_id_detect(struct e100_private *bdp) -{ - u16 low_id_reg, high_id_reg; - - if (bdp->phy_addr == PHY_ADDRESS_503) { - bdp->PhyId = PHY_503; - return; - } - if (!(bdp->flags & IS_ICH)) { - if (bdp->rev_id >= D102_REV_ID) { - bdp->PhyId = PHY_82562ET; - return; - } - } - - /* Read phy id from the MII register */ - e100_mdi_read(bdp, MII_PHYSID1, bdp->phy_addr, &low_id_reg); - e100_mdi_read(bdp, MII_PHYSID2, bdp->phy_addr, &high_id_reg); - - bdp->PhyId = ((unsigned int) low_id_reg | - ((unsigned int) high_id_reg << 16)); -} - -static void __devinit -e100_phy_isolate(struct e100_private *bdp) -{ - unsigned int phy_address; - u16 ctrl_reg; - - /* Go over all phy addresses. Deisolate the selected one, and isolate - * all the rest */ - for (phy_address = 0; phy_address <= MAX_PHY_ADDR; phy_address++) { - if (phy_address != bdp->phy_addr) { - e100_mdi_write(bdp, MII_BMCR, phy_address, - BMCR_ISOLATE); - - } else { - e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &ctrl_reg); - ctrl_reg &= ~BMCR_ISOLATE; - e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg); - } - - udelay(100); - } -} - -static unsigned char __devinit -e100_phy_specific_setup(struct e100_private *bdp) -{ - u16 misc_reg; - - if (bdp->phy_addr == PHY_ADDRESS_503) { - switch (bdp->params.e100_speed_duplex) { - case E100_AUTONEG: - /* The adapter can't autoneg. so set to 10/HALF */ - printk(KERN_INFO - "e100: 503 serial component detected which " - "cannot autonegotiate\n"); - printk(KERN_INFO - "e100: speed/duplex forced to " - "10Mbps / Half duplex\n"); - bdp->params.e100_speed_duplex = E100_SPEED_10_HALF; - break; - - case E100_SPEED_100_HALF: - case E100_SPEED_100_FULL: - printk(KERN_ERR - "e100: 503 serial component detected " - "which does not support 100Mbps\n"); - printk(KERN_ERR - "e100: Change the forced speed/duplex " - "to a supported setting\n"); - return false; - } - - return true; - } - - if (IS_NC3133(bdp)) { - u16 int_reg; - - /* enable 100BASE fiber interface */ - e100_mdi_write(bdp, MDI_NC3133_CONFIG_REG, bdp->phy_addr, - MDI_NC3133_100FX_ENABLE); - - if ((bdp->params.e100_speed_duplex != E100_AUTONEG) && - (bdp->params.e100_speed_duplex != E100_SPEED_100_FULL)) { - /* just inform user about 100 full */ - printk(KERN_ERR "e100: NC3133 NIC can only run " - "at 100Mbps full duplex\n"); - } - - bdp->params.e100_speed_duplex = E100_SPEED_100_FULL; - - /* enable interrupts */ - e100_mdi_read(bdp, MDI_NC3133_INT_ENABLE_REG, - bdp->phy_addr, &int_reg); - int_reg |= MDI_NC3133_INT_ENABLE; - e100_mdi_write(bdp, MDI_NC3133_INT_ENABLE_REG, - bdp->phy_addr, int_reg); - } - - /* Handle the National TX */ - if ((bdp->PhyId & PHY_MODEL_REV_ID_MASK) == PHY_NSC_TX) { - e100_mdi_read(bdp, NSC_CONG_CONTROL_REG, - bdp->phy_addr, &misc_reg); - - misc_reg |= NSC_TX_CONG_TXREADY; - - /* disable the congestion control bit in the National Phy */ - misc_reg &= ~NSC_TX_CONG_ENABLE; - - e100_mdi_write(bdp, NSC_CONG_CONTROL_REG, - bdp->phy_addr, misc_reg); - } - - return true; -} - -/* - * Procedure: e100_phy_fix_squelch - * - * Description: - * Help find link on certain rare scenarios. - * NOTE: This routine must be called once per watchdog, - * and *after* setting the current link state. - * - * Arguments: - * bdp - Ptr to this card's e100_bdconfig structure - * - * Returns: - * NOTHING - */ -static void -e100_phy_fix_squelch(struct e100_private *bdp) -{ - if ((bdp->PhyId != PHY_82555_TX) || (bdp->flags & DF_SPEED_FORCED)) - return; - - if (netif_carrier_ok(bdp->device)) { - switch (bdp->PhyState) { - case 0: - break; - case 1: - e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, 0x0000); - break; - case 2: - e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR, - bdp->phy_addr, 0x3000); - break; - } - bdp->PhyState = 0; - bdp->PhyDelay = 0; - - } else if (!bdp->PhyDelay--) { - switch (bdp->PhyState) { - case 0: - e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, EXTENDED_SQUELCH_BIT); - bdp->PhyState = 1; - break; - case 1: - e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, 0x0000); - e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR, - bdp->phy_addr, 0x2010); - bdp->PhyState = 2; - break; - case 2: - e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR, - bdp->phy_addr, 0x3000); - bdp->PhyState = 0; - break; - } - - e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, - BMCR_ANENABLE | BMCR_ANRESTART); - bdp->PhyDelay = 3; - } -} - -/* - * Procedure: e100_fix_polarity - * - * Description: - * Fix for 82555 auto-polarity toggle problem. With a short cable - * connecting an 82555 with an 840A link partner, if the medium is noisy, - * the 82555 sometime thinks that the polarity might be wrong and so - * toggles polarity. This happens repeatedly and results in a high bit - * error rate. - * NOTE: This happens only at 10 Mbps - * - * Arguments: - * bdp - Ptr to this card's e100_bdconfig structure - * - * Returns: - * NOTHING - */ -static void __devinit -e100_fix_polarity(struct e100_private *bdp) -{ - u16 status; - u16 errors; - u16 misc_reg; - int speed; - - if ((bdp->PhyId != PHY_82555_TX) && (bdp->PhyId != PHY_82562ET) && - (bdp->PhyId != PHY_82562EM)) - return; - - /* If the user wants auto-polarity disabled, do only that and nothing * - * else. * e100_autopolarity == 0 means disable --- we do just the - * disabling * e100_autopolarity == 1 means enable --- we do nothing at - * all * e100_autopolarity >= 2 means we do the workaround code. */ - /* Change for 82558 enhancement */ - switch (E100_AUTOPOLARITY) { - case 0: - e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, &misc_reg); - e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr, - (u16) (misc_reg | DISABLE_AUTO_POLARITY)); - break; - - case 1: - e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, &misc_reg); - e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr, - (u16) (misc_reg & ~DISABLE_AUTO_POLARITY)); - break; - - case 2: - /* we do this only if link is up */ - if (!netif_carrier_ok(bdp->device)) { - break; - } - - e100_mdi_read(bdp, PHY_82555_CSR, bdp->phy_addr, &status); - speed = (status & PHY_82555_SPEED_BIT) ? 100 : 10; - - /* we need to do this only if speed is 10 */ - if (speed != 10) { - break; - } - - /* see if we have any end of frame errors */ - e100_mdi_read(bdp, PHY_82555_EOF_COUNTER, - bdp->phy_addr, &errors); - - /* if non-zero, wait for 100 ms before reading again */ - if (errors) { - udelay(200); - e100_mdi_read(bdp, PHY_82555_EOF_COUNTER, - bdp->phy_addr, &errors); - - /* if non-zero again, we disable polarity */ - if (errors) { - e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, &misc_reg); - e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, - (u16) (misc_reg | - DISABLE_AUTO_POLARITY)); - } - } - - if (!errors) { - /* it is safe to read the polarity now */ - e100_mdi_read(bdp, PHY_82555_CSR, - bdp->phy_addr, &status); - - /* if polarity is normal, disable polarity */ - if (!(status & PHY_82555_POLARITY_BIT)) { - e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, &misc_reg); - e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, - (u16) (misc_reg | - DISABLE_AUTO_POLARITY)); - } - } - break; - - default: - break; - } -} - -/* - * Procedure: e100_find_speed_duplex - * - * Description: This routine will figure out what line speed and duplex mode - * the PHY is currently using. - * - * Arguments: - * bdp - Ptr to this card's e100_bdconfig structure - * - * Returns: - * NOTHING - */ -static void -e100_find_speed_duplex(struct e100_private *bdp) -{ - unsigned int PhyId; - u16 stat_reg, misc_reg; - u16 ad_reg, lp_ad_reg; - - PhyId = bdp->PhyId & PHY_MODEL_REV_ID_MASK; - - /* First we should check to see if we have link */ - /* If we don't have a link no reason to print a speed and duplex */ - if (!e100_update_link_state(bdp)) { - bdp->cur_line_speed = 0; - bdp->cur_dplx_mode = 0; - return; - } - - /* On the 82559 and later controllers, speed/duplex is part of the * - * SCB. So, we save an mdi_read and get these from the SCB. * */ - if (bdp->rev_id >= D101MA_REV_ID) { - /* Read speed */ - if (readb(&bdp->scb->scb_ext.d101m_scb.scb_gen_stat) & BIT_1) - bdp->cur_line_speed = 100; - else - bdp->cur_line_speed = 10; - - /* Read duplex */ - if (readb(&bdp->scb->scb_ext.d101m_scb.scb_gen_stat) & BIT_2) - bdp->cur_dplx_mode = FULL_DUPLEX; - else - bdp->cur_dplx_mode = HALF_DUPLEX; - - return; - } - - /* If this is a Phy 100, then read bits 1 and 0 of extended register 0, - * to get the current speed and duplex settings. */ - if ((PhyId == PHY_100_A) || (PhyId == PHY_100_C) || - (PhyId == PHY_82555_TX)) { - - /* Read Phy 100 extended register 0 */ - e100_mdi_read(bdp, EXTENDED_REG_0, bdp->phy_addr, &misc_reg); - - /* Get current speed setting */ - if (misc_reg & PHY_100_ER0_SPEED_INDIC) - bdp->cur_line_speed = 100; - else - bdp->cur_line_speed = 10; - - /* Get current duplex setting -- FDX enabled if bit is set */ - if (misc_reg & PHY_100_ER0_FDX_INDIC) - bdp->cur_dplx_mode = FULL_DUPLEX; - else - bdp->cur_dplx_mode = HALF_DUPLEX; - - return; - } - - /* See if link partner is capable of Auto-Negotiation (bit 0, reg 6) */ - e100_mdi_read(bdp, MII_EXPANSION, bdp->phy_addr, &misc_reg); - - /* See if Auto-Negotiation was complete (bit 5, reg 1) */ - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg); - - /* If a True NWAY connection was made, then we can detect speed/dplx - * by ANDing our adapter's advertised abilities with our link partner's - * advertised ablilities, and then assuming that the highest common - * denominator was chosed by NWAY. */ - if ((misc_reg & EXPANSION_NWAY) && (stat_reg & BMSR_ANEGCOMPLETE)) { - - /* Read our advertisement register */ - e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &ad_reg); - - /* Read our link partner's advertisement register */ - e100_mdi_read(bdp, MII_LPA, bdp->phy_addr, &lp_ad_reg); - - /* AND the two advertisement registers together, and get rid - * of any extraneous bits. */ - ad_reg &= (lp_ad_reg & NWAY_LP_ABILITY); - - /* Get speed setting */ - if (ad_reg & - (ADVERTISE_100HALF | ADVERTISE_100FULL | - ADVERTISE_100BASE4)) - - bdp->cur_line_speed = 100; - else - bdp->cur_line_speed = 10; - - /* Get duplex setting -- use priority resolution algorithm */ - if (ad_reg & ADVERTISE_100BASE4) { - bdp->cur_dplx_mode = HALF_DUPLEX; - } else if (ad_reg & ADVERTISE_100FULL) { - bdp->cur_dplx_mode = FULL_DUPLEX; - } else if (ad_reg & ADVERTISE_100HALF) { - bdp->cur_dplx_mode = HALF_DUPLEX; - } else if (ad_reg & ADVERTISE_10FULL) { - bdp->cur_dplx_mode = FULL_DUPLEX; - } else { - bdp->cur_dplx_mode = HALF_DUPLEX; - } - - return; - } - - /* If we are connected to a dumb (non-NWAY) repeater or hub, and the - * line speed was determined automatically by parallel detection, then - * we have no way of knowing exactly what speed the PHY is set to - * unless that PHY has a propietary register which indicates speed in - * this situation. The NSC TX PHY does have such a register. Also, - * since NWAY didn't establish the connection, the duplex setting - * should HALF duplex. */ - bdp->cur_dplx_mode = HALF_DUPLEX; - - if (PhyId == PHY_NSC_TX) { - /* Read register 25 to get the SPEED_10 bit */ - e100_mdi_read(bdp, NSC_SPEED_IND_REG, bdp->phy_addr, &misc_reg); - - /* If bit 6 was set then we're at 10Mbps */ - if (misc_reg & NSC_TX_SPD_INDC_SPEED) - bdp->cur_line_speed = 10; - else - bdp->cur_line_speed = 100; - - } else { - /* If we don't know the line speed, default to 10Mbps */ - bdp->cur_line_speed = 10; - } -} - -/* - * Procedure: e100_force_speed_duplex - * - * Description: This routine forces line speed and duplex mode of the - * adapter based on the values the user has set in e100.c. - * - * Arguments: bdp - Pointer to the e100_private structure for the board - * - * Returns: void - * - */ -void -e100_force_speed_duplex(struct e100_private *bdp) -{ - u16 control; - unsigned long expires; - - e100_phy_reset(bdp); - - bdp->flags |= DF_SPEED_FORCED; - - e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control); - control &= ~BMCR_ANENABLE; - control &= ~BMCR_LOOPBACK; - - switch (bdp->params.e100_speed_duplex) { - case E100_SPEED_10_HALF: - control &= ~BMCR_SPEED100; - control &= ~BMCR_FULLDPLX; - bdp->cur_line_speed = 10; - bdp->cur_dplx_mode = HALF_DUPLEX; - break; - - case E100_SPEED_10_FULL: - control &= ~BMCR_SPEED100; - control |= BMCR_FULLDPLX; - bdp->cur_line_speed = 10; - bdp->cur_dplx_mode = FULL_DUPLEX; - break; - - case E100_SPEED_100_HALF: - control |= BMCR_SPEED100; - control &= ~BMCR_FULLDPLX; - bdp->cur_line_speed = 100; - bdp->cur_dplx_mode = HALF_DUPLEX; - break; - - case E100_SPEED_100_FULL: - control |= BMCR_SPEED100; - control |= BMCR_FULLDPLX; - bdp->cur_line_speed = 100; - bdp->cur_dplx_mode = FULL_DUPLEX; - break; - } - - e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control); - - /* loop must run at least once */ - expires = jiffies + 2 * HZ; - do { - if (e100_update_link_state(bdp) || - time_after(jiffies, expires)) { - break; - } else { - yield(); - } - - } while (true); -} - -void -e100_force_speed_duplex_to_phy(struct e100_private *bdp) -{ - u16 control; - - e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control); - control &= ~BMCR_ANENABLE; - control &= ~BMCR_LOOPBACK; - - switch (bdp->params.e100_speed_duplex) { - case E100_SPEED_10_HALF: - control &= ~BMCR_SPEED100; - control &= ~BMCR_FULLDPLX; - break; - - case E100_SPEED_10_FULL: - control &= ~BMCR_SPEED100; - control |= BMCR_FULLDPLX; - break; - - case E100_SPEED_100_HALF: - control |= BMCR_SPEED100; - control &= ~BMCR_FULLDPLX; - break; - - case E100_SPEED_100_FULL: - control |= BMCR_SPEED100; - control |= BMCR_FULLDPLX; - break; - } - - /* Send speed/duplex command to PHY layer. */ - e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control); -} - -/* - * Procedure: e100_set_fc - * - * Description: Checks the link's capability for flow control. - * - * Arguments: bdp - Pointer to the e100_private structure for the board - * - * Returns: void - * - */ -static void -e100_set_fc(struct e100_private *bdp) -{ - u16 ad_reg; - u16 lp_ad_reg; - u16 exp_reg; - - /* no flow control for 82557, forced links or half duplex */ - if (!netif_carrier_ok(bdp->device) || (bdp->flags & DF_SPEED_FORCED) || - (bdp->cur_dplx_mode == HALF_DUPLEX) || - !(bdp->flags & IS_BACHELOR)) { - - bdp->flags &= ~DF_LINK_FC_CAP; - return; - } - - /* See if link partner is capable of Auto-Negotiation (bit 0, reg 6) */ - e100_mdi_read(bdp, MII_EXPANSION, bdp->phy_addr, &exp_reg); - - if (exp_reg & EXPANSION_NWAY) { - /* Read our advertisement register */ - e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &ad_reg); - - /* Read our link partner's advertisement register */ - e100_mdi_read(bdp, MII_LPA, bdp->phy_addr, &lp_ad_reg); - - ad_reg &= lp_ad_reg; /* AND the 2 ad registers */ - - if (ad_reg & NWAY_AD_FC_SUPPORTED) - bdp->flags |= DF_LINK_FC_CAP; - else - /* If link partner is capable of autoneg, but */ - /* not capable of flow control, Received PAUSE */ - /* frames are still honored, i.e., */ - /* transmitted frames would be paused */ - /* by incoming PAUSE frames */ - bdp->flags |= DF_LINK_FC_TX_ONLY; - - } else { - bdp->flags &= ~DF_LINK_FC_CAP; - } -} - -/* - * Procedure: e100_phy_check - * - * Arguments: bdp - Pointer to the e100_private structure for the board - * - * Returns: true if link state was changed - * false otherwise - * - */ -unsigned char -e100_phy_check(struct e100_private *bdp) -{ - unsigned char old_link; - unsigned char changed = false; - - old_link = netif_carrier_ok(bdp->device) ? 1 : 0; - e100_find_speed_duplex(bdp); - - if (!old_link && netif_carrier_ok(bdp->device)) { - e100_set_fc(bdp); - changed = true; - } - - if (old_link && !netif_carrier_ok(bdp->device)) { - /* reset the zero lock state */ - bdp->zlock_state = ZLOCK_INITIAL; - - // set auto lock for phy auto-negotiation on link up - if ((bdp->PhyId & PHY_MODEL_REV_ID_MASK) == PHY_82555_TX) - e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR, - bdp->phy_addr, 0); - changed = true; - } - - e100_phy_fix_squelch(bdp); - e100_handle_zlock(bdp); - - return changed; -} - -/* - * Procedure: e100_auto_neg - * - * Description: This routine will start autonegotiation and wait - * for it to complete - * - * Arguments: - * bdp - pointer to this card's e100_bdconfig structure - * force_restart - defines if autoneg should be restarted even if it - * has been completed before - * Returns: - * NOTHING - */ -static void -e100_auto_neg(struct e100_private *bdp, unsigned char force_restart) -{ - u16 stat_reg; - unsigned long expires; - - bdp->flags &= ~DF_SPEED_FORCED; - - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg); - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg); - - /* if we are capable of performing autoneg then we restart if needed */ - if ((stat_reg != 0xFFFF) && (stat_reg & BMSR_ANEGCAPABLE)) { - - if ((!force_restart) && - (stat_reg & BMSR_ANEGCOMPLETE)) { - goto exit; - } - - e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, - BMCR_ANENABLE | BMCR_ANRESTART); - - /* wait for autoneg to complete (up to 3 seconds) */ - expires = jiffies + HZ * 3; - do { - /* now re-read the value. Sticky so read twice */ - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg); - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg); - - if ((stat_reg & BMSR_ANEGCOMPLETE) || - time_after(jiffies, expires) ) { - goto exit; - } else { - yield(); - } - } while (true); - } - -exit: - e100_find_speed_duplex(bdp); -} - -void -e100_phy_set_speed_duplex(struct e100_private *bdp, unsigned char force_restart) -{ - if (bdp->params.e100_speed_duplex == E100_AUTONEG) { - if (bdp->rev_id >= D102_REV_ID) - /* Enable MDI/MDI-X auto switching */ - e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr, - MDI_MDIX_AUTO_SWITCH_ENABLE); - e100_auto_neg(bdp, force_restart); - - } else { - if (bdp->rev_id >= D102_REV_ID) - /* Disable MDI/MDI-X auto switching */ - e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr, - MDI_MDIX_RESET_ALL_MASK); - e100_force_speed_duplex(bdp); - } - - e100_set_fc(bdp); -} - -void -e100_phy_autoneg(struct e100_private *bdp) -{ - u16 ctrl_reg; - - ctrl_reg = BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET; - - e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg); - - udelay(100); -} - -void -e100_phy_set_loopback(struct e100_private *bdp) -{ - u16 ctrl_reg; - ctrl_reg = BMCR_LOOPBACK; - e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg); - udelay(100); -} - -void -e100_phy_reset(struct e100_private *bdp) -{ - u16 ctrl_reg; - ctrl_reg = BMCR_RESET; - e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg); -} - -unsigned char __devinit -e100_phy_init(struct e100_private *bdp) -{ - e100_phy_address_detect(bdp); - e100_phy_isolate(bdp); - e100_phy_id_detect(bdp); - - if (!e100_phy_specific_setup(bdp)) - return false; - - bdp->PhyState = 0; - bdp->PhyDelay = 0; - bdp->zlock_state = ZLOCK_INITIAL; - - e100_phy_set_speed_duplex(bdp, false); - e100_fix_polarity(bdp); - - return true; -} - -/* - * Procedure: e100_get_link_state - * - * Description: This routine checks the link status of the adapter - * - * Arguments: bdp - Pointer to the e100_private structure for the board - * - * - * Returns: true - If a link is found - * false - If there is no link - * - */ -unsigned char -e100_get_link_state(struct e100_private *bdp) -{ - unsigned char link = false; - u16 status; - - /* Check link status */ - /* If the controller is a 82559 or later one, link status is available - * from the CSR. This avoids the mdi_read. */ - if (bdp->rev_id >= D101MA_REV_ID) { - if (readb(&bdp->scb->scb_ext.d101m_scb.scb_gen_stat) & BIT_0) { - link = true; - } else { - link = false; - } - - } else { - /* Read the status register twice because of sticky bits */ - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &status); - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &status); - - if (status & BMSR_LSTATUS) { - link = true; - } else { - link = false; - } - } - - return link; -} - -/* - * Procedure: e100_update_link_state - * - * Description: This routine updates the link status of the adapter, - * also considering netif_running - * - * Arguments: bdp - Pointer to the e100_private structure for the board - * - * - * Returns: true - If a link is found - * false - If there is no link - * - */ -unsigned char -e100_update_link_state(struct e100_private *bdp) -{ - unsigned char link; - - /* Logical AND PHY link & netif_running */ - link = e100_get_link_state(bdp) && netif_running(bdp->device); - - if (link) { - if (!netif_carrier_ok(bdp->device)) - netif_carrier_on(bdp->device); - } else { - if (netif_carrier_ok(bdp->device)) - netif_carrier_off(bdp->device); - } - - return link; -} - -/**************************************************************************\ - ** - ** PROC NAME: e100_handle_zlock - ** This function manages a state machine that controls - ** the driver's zero locking algorithm. - ** This function is called by e100_watchdog() every ~2 second. - ** States: - ** The current link handling state is stored in - ** bdp->zlock_state, and is one of: - ** ZLOCK_INITIAL, ZLOCK_READING, ZLOCK_SLEEPING - ** Detailed description of the states and the transitions - ** between states is found below. - ** Note that any time the link is down / there is a reset - ** state will be changed outside this function to ZLOCK_INITIAL - ** Algorithm: - ** 1. If link is up & 100 Mbps continue else stay in #1: - ** 2. Set 'auto lock' - ** 3. Read & Store 100 times 'Zero' locked in 1 sec interval - ** 4. If max zero read >= 0xB continue else goto 1 - ** 5. Set most popular 'Zero' read in #3 - ** 6. Sleep 5 minutes - ** 7. Read number of errors, if it is > 300 goto 2 else goto 6 - ** Data Structures (in DRIVER_DATA): - ** zlock_state - current state of the algorithm - ** zlock_read_cnt - counts number of reads (up to 100) - ** zlock_read_data[i] - counts number of times 'Zero' read was i, 0 <= i <= 15 - ** zlock_sleep_cnt - keeps track of "sleep" time (up to 300 secs = 5 minutes) - ** - ** Parameters: DRIVER_DATA *bdp - ** - ** bdp - Pointer to HSM's adapter data space - ** - ** Return Value: NONE - ** - ** See Also: e100_watchdog() - ** - \**************************************************************************/ -void -e100_handle_zlock(struct e100_private *bdp) -{ - u16 pos; - u16 eq_reg; - u16 err_cnt; - u8 mpz; /* Most Popular Zero */ - - switch (bdp->zlock_state) { - case ZLOCK_INITIAL: - - if (((u8) bdp->rev_id <= D102_REV_ID) || - !(bdp->cur_line_speed == 100) || - !netif_carrier_ok(bdp->device)) { - break; - } - - /* initialize hw and sw and start reading */ - e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR, - bdp->phy_addr, 0); - /* reset read counters: */ - bdp->zlock_read_cnt = 0; - for (pos = 0; pos < 16; pos++) - bdp->zlock_read_data[pos] = 0; - /* start reading in the next call back: */ - bdp->zlock_state = ZLOCK_READING; - - /* FALL THROUGH !! */ - - case ZLOCK_READING: - /* state: reading (100 times) zero locked in 1 sec interval - * prev states: ZLOCK_INITIAL - * next states: ZLOCK_INITIAL, ZLOCK_SLEEPING */ - - e100_mdi_read(bdp, PHY_82555_MDI_EQUALIZER_CSR, - bdp->phy_addr, &eq_reg); - pos = (eq_reg & ZLOCK_ZERO_MASK) >> 4; - bdp->zlock_read_data[pos]++; - bdp->zlock_read_cnt++; - - if (bdp->zlock_read_cnt == ZLOCK_MAX_READS) { - /* check if we read a 'Zero' value of 0xB or greater */ - if ((bdp->zlock_read_data[0xB]) || - (bdp->zlock_read_data[0xC]) || - (bdp->zlock_read_data[0xD]) || - (bdp->zlock_read_data[0xE]) || - (bdp->zlock_read_data[0xF])) { - - /* we've read 'Zero' value of 0xB or greater, - * find most popular 'Zero' value and lock it */ - mpz = 0; - /* this loop finds the most popular 'Zero': */ - for (pos = 1; pos < 16; pos++) { - if (bdp->zlock_read_data[pos] > - bdp->zlock_read_data[mpz]) - - mpz = pos; - } - /* now lock the most popular 'Zero': */ - eq_reg = (ZLOCK_SET_ZERO | mpz); - e100_mdi_write(bdp, - PHY_82555_MDI_EQUALIZER_CSR, - bdp->phy_addr, eq_reg); - - /* sleep for 5 minutes: */ - bdp->zlock_sleep_cnt = jiffies; - bdp->zlock_state = ZLOCK_SLEEPING; - /* we will be reading the # of errors after 5 - * minutes, so we need to reset the error - * counters - these registers are self clearing - * on read, so read them */ - e100_mdi_read(bdp, PHY_82555_SYMBOL_ERR, - bdp->phy_addr, &err_cnt); - - } else { - /* we did not read a 'Zero' value of 0xB or - * above. go back to the start */ - bdp->zlock_state = ZLOCK_INITIAL; - } - - } - break; - - case ZLOCK_SLEEPING: - /* state: sleeping for 5 minutes - * prev states: ZLOCK_READING - * next states: ZLOCK_READING, ZLOCK_SLEEPING */ - - /* if 5 minutes have passed: */ - if ((jiffies - bdp->zlock_sleep_cnt) >= ZLOCK_MAX_SLEEP) { - /* read and sum up the number of errors: */ - e100_mdi_read(bdp, PHY_82555_SYMBOL_ERR, - bdp->phy_addr, &err_cnt); - /* if we've more than 300 errors (this number was - * calculated according to the spec max allowed errors - * (80 errors per 1 million frames) for 5 minutes in - * 100 Mbps (or the user specified max BER number) */ - if (err_cnt > bdp->params.ber) { - /* start again in the next callback: */ - bdp->zlock_state = ZLOCK_INITIAL; - } else { - /* we don't have more errors than allowed, - * sleep for 5 minutes */ - bdp->zlock_sleep_cnt = jiffies; - } - } - break; - - default: - break; - } -} diff --git a/xen/drivers/net/e100/e100_phy.h b/xen/drivers/net/e100/e100_phy.h deleted file mode 100644 index df2d483e67..0000000000 --- a/xen/drivers/net/e100/e100_phy.h +++ /dev/null @@ -1,158 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -#ifndef _E100_PHY_INC_ -#define _E100_PHY_INC_ - -#include "e100.h" - -/* - * Auto-polarity enable/disable - * e100_autopolarity = 0 => disable auto-polarity - * e100_autopolarity = 1 => enable auto-polarity - * e100_autopolarity = 2 => let software determine - */ -#define E100_AUTOPOLARITY 2 - -#define IS_NC3133(bdp) (((bdp)->pdev->subsystem_vendor == 0x0E11) && \ - ((bdp)->pdev->subsystem_device == 0xB0E1)) - -#define PHY_503 0 -#define PHY_100_A 0x000003E0 -#define PHY_100_C 0x035002A8 -#define PHY_NSC_TX 0x5c002000 -#define PHY_82562ET 0x033002A8 -#define PHY_82562EM 0x032002A8 -#define PHY_82562EH 0x017002A8 -#define PHY_82555_TX 0x015002a8 /* added this for 82555 */ -#define PHY_OTHER 0xFFFF -#define MAX_PHY_ADDR 31 -#define MIN_PHY_ADDR 0 - -#define PHY_MODEL_REV_ID_MASK 0xFFF0FFFF - -#define PHY_DEFAULT_ADDRESS 1 -#define PHY_ADDRESS_503 32 - -/* MDI Control register bit definitions */ -#define MDI_PHY_READY BIT_28 /* PHY is ready for next MDI cycle */ - -#define MDI_NC3133_CONFIG_REG 0x19 -#define MDI_NC3133_100FX_ENABLE BIT_2 -#define MDI_NC3133_INT_ENABLE_REG 0x17 -#define MDI_NC3133_INT_ENABLE BIT_1 - -/* MDI Control register opcode definitions */ -#define MDI_WRITE 1 /* Phy Write */ -#define MDI_READ 2 /* Phy read */ - -/* MDI register set*/ -#define AUTO_NEG_NEXT_PAGE_REG 0x07 /* Auto-negotiation next page xmit */ -#define EXTENDED_REG_0 0x10 /* Extended reg 0 (Phy 100 modes) */ -#define EXTENDED_REG_1 0x14 /* Extended reg 1 (Phy 100 error indications) */ -#define NSC_CONG_CONTROL_REG 0x17 /* National (TX) congestion control */ -#define NSC_SPEED_IND_REG 0x19 /* National (TX) speed indication */ - -#define HWI_CONTROL_REG 0x1D /* HWI Control register */ -/* MDI/MDI-X Control Register bit definitions */ -#define MDI_MDIX_RES_TIMER BIT_0_3 /* minimum slot time for resolution timer */ -#define MDI_MDIX_CONFIG_IS_OK BIT_4 /* 1 = resolution algorithm completes OK */ -#define MDI_MDIX_STATUS BIT_5 /* 1 = MDIX (croos over), 0 = MDI (straight through) */ -#define MDI_MDIX_SWITCH BIT_6 /* 1 = Forces to MDIX, 0 = Forces to MDI */ -#define MDI_MDIX_AUTO_SWITCH_ENABLE BIT_7 /* 1 = MDI/MDI-X feature enabled */ -#define MDI_MDIX_CONCT_CONFIG BIT_8 /* Sets the MDI/MDI-X connectivity configuration (test prupose only) */ -#define MDI_MDIX_CONCT_TEST_ENABLE BIT_9 /* 1 = Enables connectivity testing */ -#define MDI_MDIX_RESET_ALL_MASK 0x0000 - -/* HWI Control Register bit definitions */ -#define HWI_TEST_DISTANCE BIT_0_8 /* distance to cable problem */ -#define HWI_TEST_HIGHZ_PROBLEM BIT_9 /* 1 = Open Circuit */ -#define HWI_TEST_LOWZ_PROBLEM BIT_10 /* 1 = Short Circuit */ -#define HWI_TEST_RESERVED (BIT_11 | BIT_12) /* reserved */ -#define HWI_TEST_EXECUTE BIT_13 /* 1 = Execute the HWI test on the PHY */ -#define HWI_TEST_ABILITY BIT_14 /* 1 = test passed */ -#define HWI_TEST_ENABLE BIT_15 /* 1 = Enables the HWI feature */ -#define HWI_RESET_ALL_MASK 0x0000 - -/* ############Start of 82555 specific defines################## */ - -/* Intel 82555 specific registers */ -#define PHY_82555_CSR 0x10 /* 82555 CSR */ -#define PHY_82555_SPECIAL_CONTROL 0x11 /* 82555 special control register */ - -#define PHY_82555_RCV_ERR 0x15 /* 82555 100BaseTx Receive Error - * Frame Counter */ -#define PHY_82555_SYMBOL_ERR 0x16 /* 82555 RCV Symbol Error Counter */ -#define PHY_82555_PREM_EOF_ERR 0x17 /* 82555 100BaseTx RCV Premature End - * of Frame Error Counter */ -#define PHY_82555_EOF_COUNTER 0x18 /* 82555 end of frame error counter */ -#define PHY_82555_MDI_EQUALIZER_CSR 0x1a /* 82555 specific equalizer reg. */ - -/* 82555 CSR bits */ -#define PHY_82555_SPEED_BIT BIT_1 -#define PHY_82555_POLARITY_BIT BIT_8 - -/* 82555 equalizer reg. opcodes */ -#define ENABLE_ZERO_FORCING 0x2010 /* write to ASD conf. reg. 0 */ -#define DISABLE_ZERO_FORCING 0x2000 /* write to ASD conf. reg. 0 */ - -/* 82555 special control reg. opcodes */ -#define DISABLE_AUTO_POLARITY 0x0010 -#define EXTENDED_SQUELCH_BIT BIT_2 - -/* ############End of 82555 specific defines##################### */ - -/* Auto-Negotiation advertisement register bit definitions*/ -#define NWAY_AD_FC_SUPPORTED 0x0400 /* Flow Control supported */ - -/* Auto-Negotiation link partner ability register bit definitions*/ -#define NWAY_LP_ABILITY 0x07e0 /* technologies supported */ - -/* PHY 100 Extended Register 0 bit definitions*/ -#define PHY_100_ER0_FDX_INDIC BIT_0 /* 1 = FDX, 0 = half duplex */ -#define PHY_100_ER0_SPEED_INDIC BIT_1 /* 1 = 100Mbps, 0= 10Mbps */ - -/* National Semiconductor TX phy congestion control register bit definitions*/ -#define NSC_TX_CONG_TXREADY BIT_10 /* Makes TxReady an input */ -#define NSC_TX_CONG_ENABLE BIT_8 /* Enables congestion control */ - -/* National Semiconductor TX phy speed indication register bit definitions*/ -#define NSC_TX_SPD_INDC_SPEED BIT_6 /* 0 = 100Mbps, 1=10Mbps */ - -/************* function prototypes ************/ -extern unsigned char e100_phy_init(struct e100_private *bdp); -extern unsigned char e100_update_link_state(struct e100_private *bdp); -extern unsigned char e100_phy_check(struct e100_private *bdp); -extern void e100_phy_set_speed_duplex(struct e100_private *bdp, - unsigned char force_restart); -extern void e100_phy_autoneg(struct e100_private *bdp); -extern void e100_phy_reset(struct e100_private *bdp); -extern void e100_phy_set_loopback(struct e100_private *bdp); -extern int e100_mdi_write(struct e100_private *, u32, u32, u16); -extern int e100_mdi_read(struct e100_private *, u32, u32, u16 *); - -#endif diff --git a/xen/drivers/net/e100/e100_test.c b/xen/drivers/net/e100/e100_test.c deleted file mode 100644 index 0ff7266ef8..0000000000 --- a/xen/drivers/net/e100/e100_test.c +++ /dev/null @@ -1,435 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -#include "e100.h" -#include "e100_config.h" - -extern u16 e100_eeprom_read(struct e100_private *, u16); -extern int e100_wait_exec_cmplx(struct e100_private *, u32,u8, u8); -extern void e100_phy_reset(struct e100_private *bdp); -extern void e100_phy_autoneg(struct e100_private *bdp); -extern void e100_phy_set_loopback(struct e100_private *bdp); -extern void e100_force_speed_duplex(struct e100_private *bdp); - -static u8 e100_diag_selftest(struct net_device *); -static u8 e100_diag_eeprom(struct net_device *); -static u8 e100_diag_loopback(struct net_device *); - -static u8 e100_diag_one_loopback (struct net_device *, u8); -static u8 e100_diag_rcv_loopback_pkt(struct e100_private *); -static void e100_diag_config_loopback(struct e100_private *, u8, u8, u8 *,u8 *); -static u8 e100_diag_loopback_alloc(struct e100_private *); -static void e100_diag_loopback_cu_ru_exec(struct e100_private *); -static u8 e100_diag_check_pkt(u8 *); -static void e100_diag_loopback_free(struct e100_private *); - -#define LB_PACKET_SIZE 1500 - -/** - * e100_run_diag - main test execution handler - checks mask of requests and calls the diag routines - * @dev: atapter's net device data struct - * @test_info: array with test request mask also used to store test results - * - * RETURNS: updated flags field of struct ethtool_test - */ -u32 -e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags) -{ - struct e100_private* bdp = dev->priv; - u8 test_result = true; - - e100_isolate_driver(bdp); - - if (flags & ETH_TEST_FL_OFFLINE) { - u8 fail_mask; - - fail_mask = e100_diag_selftest(dev); - if (fail_mask) { - test_result = false; - if (fail_mask & REGISTER_TEST_FAIL) - test_info [E100_REG_TEST_FAIL] = true; - if (fail_mask & ROM_TEST_FAIL) - test_info [E100_ROM_TEST_FAIL] = true; - if (fail_mask & SELF_TEST_FAIL) - test_info [E100_MAC_TEST_FAIL] = true; - if (fail_mask & TEST_TIMEOUT) - test_info [E100_CHIP_TIMEOUT] = true; - } - - fail_mask = e100_diag_loopback(dev); - if (fail_mask) { - test_result = false; - if (fail_mask & PHY_LOOPBACK) - test_info [E100_LPBK_PHY_FAIL] = true; - if (fail_mask & MAC_LOOPBACK) - test_info [E100_LPBK_MAC_FAIL] = true; - } - } - - if (!e100_diag_eeprom(dev)) { - test_result = false; - test_info [E100_EEPROM_TEST_FAIL] = true; - } - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ * 2); - e100_deisolate_driver(bdp, false); - - return flags | (test_result ? 0 : ETH_TEST_FL_FAILED); -} - -/** - * e100_diag_selftest - run hardware selftest - * @dev: atapter's net device data struct - */ -static u8 -e100_diag_selftest(struct net_device *dev) -{ - struct e100_private *bdp = dev->priv; - u32 st_timeout, st_result; - u8 retval = 0; - - if (!e100_selftest(bdp, &st_timeout, &st_result)) { - if (!st_timeout) { - if (st_result & CB_SELFTEST_REGISTER_BIT) - retval |= REGISTER_TEST_FAIL; - if (st_result & CB_SELFTEST_DIAG_BIT) - retval |= SELF_TEST_FAIL; - if (st_result & CB_SELFTEST_ROM_BIT) - retval |= ROM_TEST_FAIL; - } else { - retval = TEST_TIMEOUT; - } - } - - e100_configure_device(bdp); - - return retval; -} - -/** - * e100_diag_eeprom - validate eeprom checksum correctness - * @dev: atapter's net device data struct - * - */ -static u8 -e100_diag_eeprom (struct net_device *dev) -{ - struct e100_private *bdp = dev->priv; - u16 i, eeprom_sum, eeprom_actual_csm; - - for (i = 0, eeprom_sum = 0; i < (bdp->eeprom_size - 1); i++) { - eeprom_sum += e100_eeprom_read(bdp, i); - } - - eeprom_actual_csm = e100_eeprom_read(bdp, bdp->eeprom_size - 1); - - if (eeprom_actual_csm == (u16)(EEPROM_SUM - eeprom_sum)) { - return true; - } - - return false; -} - -/** - * e100_diag_loopback - performs loopback test - * @dev: atapter's net device data struct - */ -static u8 -e100_diag_loopback (struct net_device *dev) -{ - u8 rc = 0; - - printk(KERN_DEBUG "%s: PHY loopback test starts\n", dev->name); - e100_sw_reset(dev->priv, PORT_SELECTIVE_RESET); - if (!e100_diag_one_loopback(dev, PHY_LOOPBACK)) { - rc |= PHY_LOOPBACK; - } - printk(KERN_DEBUG "%s: PHY loopback test ends\n", dev->name); - - printk(KERN_DEBUG "%s: MAC loopback test starts\n", dev->name); - e100_sw_reset(dev->priv, PORT_SELECTIVE_RESET); - if (!e100_diag_one_loopback(dev, MAC_LOOPBACK)) { - rc |= MAC_LOOPBACK; - } - printk(KERN_DEBUG "%s: MAC loopback test ends\n", dev->name); - - return rc; -} - -/** - * e100_diag_loopback - performs loopback test - * @dev: atapter's net device data struct - * @mode: lopback test type - */ -static u8 -e100_diag_one_loopback (struct net_device *dev, u8 mode) -{ - struct e100_private *bdp = dev->priv; - u8 res = false; - u8 saved_dynamic_tbd = false; - u8 saved_extended_tcb = false; - - if (!e100_diag_loopback_alloc(bdp)) - return false; - - /* change the config block to standard tcb and the correct loopback */ - e100_diag_config_loopback(bdp, true, mode, - &saved_extended_tcb, &saved_dynamic_tbd); - - e100_diag_loopback_cu_ru_exec(bdp); - - if (e100_diag_rcv_loopback_pkt(bdp)) { - res = true; - } - - e100_diag_loopback_free(bdp); - - /* change the config block to previous tcb mode and the no loopback */ - e100_diag_config_loopback(bdp, false, mode, - &saved_extended_tcb, &saved_dynamic_tbd); - return res; -} - -/** - * e100_diag_config_loopback - setup/clear loopback before/after lpbk test - * @bdp: atapter's private data struct - * @set_loopback: true if the function is called to set lb - * @loopback_mode: the loopback mode(MAC or PHY) - * @tcb_extended: true if need to set extended tcb mode after clean loopback - * @dynamic_tbd: true if needed to set dynamic tbd mode after clean loopback - * - */ -void -e100_diag_config_loopback(struct e100_private* bdp, - u8 set_loopback, - u8 loopback_mode, - u8* tcb_extended, - u8* dynamic_tbd) -{ - /* if set_loopback == true - we want to clear tcb_extended/dynamic_tbd. - * the previous values are saved in the params tcb_extended/dynamic_tbd - * if set_loopback == false - we want to restore previous value. - */ - if (set_loopback || (*tcb_extended)) - *tcb_extended = e100_config_tcb_ext_enable(bdp,*tcb_extended); - - if (set_loopback || (*dynamic_tbd)) - *dynamic_tbd = e100_config_dynamic_tbd(bdp,*dynamic_tbd); - - if (set_loopback) { - /* ICH PHY loopback is broken */ - if (bdp->flags & IS_ICH && loopback_mode == PHY_LOOPBACK) - loopback_mode = MAC_LOOPBACK; - /* Configure loopback on MAC */ - e100_config_loopback_mode(bdp,loopback_mode); - } else { - e100_config_loopback_mode(bdp,NO_LOOPBACK); - } - - e100_config(bdp); - - if (loopback_mode == PHY_LOOPBACK) { - if (set_loopback) - /* Set PHY loopback mode */ - e100_phy_set_loopback(bdp); - else { /* Back to normal speed and duplex */ - if (bdp->params.e100_speed_duplex == E100_AUTONEG) - /* Reset PHY and do autoneg */ - e100_phy_autoneg(bdp); - else - /* Reset PHY and force speed and duplex */ - e100_force_speed_duplex(bdp); - } - /* Wait for PHY state change */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ); - } else { /* For MAC loopback wait 500 msec to take effect */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 2); - } -} - -/** - * e100_diag_loopback_alloc - alloc & initate tcb and rfd for the loopback - * @bdp: atapter's private data struct - * - */ -static u8 -e100_diag_loopback_alloc(struct e100_private *bdp) -{ - dma_addr_t dma_handle; - tcb_t *tcb; - rfd_t *rfd; - tbd_t *tbd; - - /* tcb, tbd and transmit buffer are allocated */ - tcb = pci_alloc_consistent(bdp->pdev, - (sizeof (tcb_t) + sizeof (tbd_t) + - LB_PACKET_SIZE), - &dma_handle); - if (tcb == NULL) - return false; - - memset(tcb, 0x00, sizeof (tcb_t) + sizeof (tbd_t) + LB_PACKET_SIZE); - tcb->tcb_phys = dma_handle; - tcb->tcb_hdr.cb_status = 0; - tcb->tcb_hdr.cb_cmd = - cpu_to_le16(CB_EL_BIT | CB_TRANSMIT | CB_TX_SF_BIT); - /* Next command is null */ - tcb->tcb_hdr.cb_lnk_ptr = cpu_to_le32(0xffffffff); - tcb->tcb_cnt = 0; - tcb->tcb_thrshld = bdp->tx_thld; - tcb->tcb_tbd_num = 1; - /* Set up tcb tbd pointer */ - tcb->tcb_tbd_ptr = cpu_to_le32(tcb->tcb_phys + sizeof (tcb_t)); - tbd = (tbd_t *) ((u8 *) tcb + sizeof (tcb_t)); - /* Set up tbd transmit buffer */ - tbd->tbd_buf_addr = - cpu_to_le32(le32_to_cpu(tcb->tcb_tbd_ptr) + sizeof (tbd_t)); - tbd->tbd_buf_cnt = __constant_cpu_to_le16(1024); - /* The value of first 512 bytes is FF */ - memset((void *) ((u8 *) tbd + sizeof (tbd_t)), 0xFF, 512); - /* The value of second 512 bytes is BA */ - memset((void *) ((u8 *) tbd + sizeof (tbd_t) + 512), 0xBA, 512); - wmb(); - rfd = pci_alloc_consistent(bdp->pdev, sizeof (rfd_t), &dma_handle); - - if (rfd == NULL) { - pci_free_consistent(bdp->pdev, - sizeof (tcb_t) + sizeof (tbd_t) + - LB_PACKET_SIZE, tcb, tcb->tcb_phys); - return false; - } - - memset(rfd, 0x00, sizeof (rfd_t)); - - /* init all fields in rfd */ - rfd->rfd_header.cb_cmd = cpu_to_le16(RFD_EL_BIT); - rfd->rfd_sz = cpu_to_le16(ETH_FRAME_LEN + CHKSUM_SIZE); - /* dma_handle is physical address of rfd */ - bdp->loopback.dma_handle = dma_handle; - bdp->loopback.tcb = tcb; - bdp->loopback.rfd = rfd; - wmb(); - return true; -} - -/** - * e100_diag_loopback_cu_ru_exec - activates cu and ru to send & receive the pkt - * @bdp: atapter's private data struct - * - */ -static void -e100_diag_loopback_cu_ru_exec(struct e100_private *bdp) -{ - /*load CU & RU base */ - if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0)) - printk(KERN_ERR "e100: SCB_CUC_LOAD_BASE failed\n"); - if(!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0)) - printk(KERN_ERR "e100: SCB_RUC_LOAD_BASE failed!\n"); - if(!e100_wait_exec_cmplx(bdp, bdp->loopback.dma_handle, SCB_RUC_START, 0)) - printk(KERN_ERR "e100: SCB_RUC_START failed!\n"); - - bdp->next_cu_cmd = START_WAIT; - e100_start_cu(bdp, bdp->loopback.tcb); - bdp->last_tcb = NULL; - rmb(); -} -/** - * e100_diag_check_pkt - checks if a given packet is a loopback packet - * @bdp: atapter's private data struct - * - * Returns true if OK false otherwise. - */ -static u8 -e100_diag_check_pkt(u8 *datap) -{ - int i; - for (i = 0; i<512; i++) { - if( !((*datap)==0xFF && (*(datap + 512) == 0xBA)) ) { - printk (KERN_ERR "e100: check loopback packet failed at: %x\n", i); - return false; - } - } - printk (KERN_DEBUG "e100: Check received loopback packet OK\n"); - return true; -} - -/** - * e100_diag_rcv_loopback_pkt - waits for receive and checks lpbk packet - * @bdp: atapter's private data struct - * - * Returns true if OK false otherwise. - */ -static u8 -e100_diag_rcv_loopback_pkt(struct e100_private* bdp) -{ - rfd_t *rfdp; - u16 rfd_status; - unsigned long expires = jiffies + HZ * 2; - - rfdp =bdp->loopback.rfd; - - rfd_status = le16_to_cpu(rfdp->rfd_header.cb_status); - - while (!(rfd_status & RFD_STATUS_COMPLETE)) { - if (time_before(jiffies, expires)) { - yield(); - rmb(); - rfd_status = le16_to_cpu(rfdp->rfd_header.cb_status); - } else { - break; - } - } - - if (rfd_status & RFD_STATUS_COMPLETE) { - printk(KERN_DEBUG "e100: Loopback packet received\n"); - return e100_diag_check_pkt(((u8 *)rfdp+bdp->rfd_size)); - } - else { - printk(KERN_ERR "e100: Loopback packet not received\n"); - return false; - } -} - -/** - * e100_diag_loopback_free - free data allocated for loopback pkt send/receive - * @bdp: atapter's private data struct - * - */ -static void -e100_diag_loopback_free (struct e100_private *bdp) -{ - pci_free_consistent(bdp->pdev, - sizeof(tcb_t) + sizeof(tbd_t) + LB_PACKET_SIZE, - bdp->loopback.tcb, bdp->loopback.tcb->tcb_phys); - - pci_free_consistent(bdp->pdev, sizeof(rfd_t), bdp->loopback.rfd, - bdp->loopback.dma_handle); -} - diff --git a/xen/drivers/net/e100/e100_ucode.h b/xen/drivers/net/e100/e100_ucode.h deleted file mode 100644 index ccbcd05583..0000000000 --- a/xen/drivers/net/e100/e100_ucode.h +++ /dev/null @@ -1,365 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -#ifndef _E100_UCODE_H_ -#define _E100_UCODE_H_ - -/* -e100_ucode.h - -This file contains the loadable micro code arrays to implement receive -bundling on the D101 A-step, D101 B-step, D101M (B-step only), D101S, -D102 B-step, D102 B-step with TCO work around and D102 C-step. - -Each controller has its own specific micro code array. The array for one -controller is totally incompatible with any other controller, and if used -will most likely cause the controller to lock up and stop responding to -the driver. Each micro code array has its own parameter offsets (described -below), and they each have their own version number. -*/ - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change algorithm. -* -* CPUSAVER_DWORD - This is the location of the instruction that loads -* the dead-man timer with its inital value. By writing a 16-bit -* value to the low word of this instruction, the driver can change -* the timer value. The current default is either x600 or x800; -* experiments show that the value probably should stay within the -* range of x200 - x1000. -* -* CPUSAVER_BUNDLE_MAX_DWORD - This is the location of the instruction -* that sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* CPUSAVER_MIN_SIZE_DWORD - This is the location of the instruction -* that contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -#ifndef UCODE_MAX_DWORDS -#define UCODE_MAX_DWORDS 134 -#endif - -/********************************************************/ -/* CPUSaver micro code for the D101A */ -/********************************************************/ - -/* Version 2.0 */ - -/* This value is the same for both A and B step of 558. */ - -#define D101_CPUSAVER_TIMER_DWORD 72 -#define D101_CPUSAVER_BUNDLE_DWORD UCODE_MAX_DWORDS -#define D101_CPUSAVER_MIN_SIZE_DWORD UCODE_MAX_DWORDS - -#define D101_A_RCVBUNDLE_UCODE \ -{\ -0x03B301BB, 0x0046FFFF, 0xFFFFFFFF, 0x051DFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ -0x000C0001, 0x00101212, 0x000C0008, 0x003801BC, \ -0x00000000, 0x00124818, 0x000C1000, 0x00220809, \ -0x00010200, 0x00124818, 0x000CFFFC, 0x003803B5, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x0024B81D, 0x00130836, 0x000C0001, \ -0x0026081C, 0x0020C81B, 0x00130824, 0x00222819, \ -0x00101213, 0x00041000, 0x003A03B3, 0x00010200, \ -0x00101B13, 0x00238081, 0x00213049, 0x0038003B, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x0024B83E, 0x00130826, 0x000C0001, \ -0x0026083B, 0x00010200, 0x00134824, 0x000C0001, \ -0x00101213, 0x00041000, 0x0038051E, 0x00101313, \ -0x00010400, 0x00380521, 0x00050600, 0x00100824, \ -0x00101310, 0x00041000, 0x00080600, 0x00101B10, \ -0x0038051E, 0x00000000, 0x00000000, 0x00000000 \ -} - -/********************************************************/ -/* CPUSaver micro code for the D101B */ -/********************************************************/ - -/* Version 2.0 */ - -#define D101_B0_RCVBUNDLE_UCODE \ -{\ -0x03B401BC, 0x0047FFFF, 0xFFFFFFFF, 0x051EFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ -0x000C0001, 0x00101B92, 0x000C0008, 0x003801BD, \ -0x00000000, 0x00124818, 0x000C1000, 0x00220809, \ -0x00010200, 0x00124818, 0x000CFFFC, 0x003803B6, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x0024B81D, 0x0013082F, 0x000C0001, \ -0x0026081C, 0x0020C81B, 0x00130837, 0x00222819, \ -0x00101B93, 0x00041000, 0x003A03B4, 0x00010200, \ -0x00101793, 0x00238082, 0x0021304A, 0x0038003C, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x0024B83E, 0x00130826, 0x000C0001, \ -0x0026083B, 0x00010200, 0x00134837, 0x000C0001, \ -0x00101B93, 0x00041000, 0x0038051F, 0x00101313, \ -0x00010400, 0x00380522, 0x00050600, 0x00100837, \ -0x00101310, 0x00041000, 0x00080600, 0x00101790, \ -0x0038051F, 0x00000000, 0x00000000, 0x00000000 \ -} - -/********************************************************/ -/* CPUSaver micro code for the D101M (B-step only) */ -/********************************************************/ - -/* Version 2.10.1 */ - -/* Parameter values for the D101M B-step */ -#define D101M_CPUSAVER_TIMER_DWORD 78 -#define D101M_CPUSAVER_BUNDLE_DWORD 65 -#define D101M_CPUSAVER_MIN_SIZE_DWORD 126 - -#define D101M_B_RCVBUNDLE_UCODE \ -{\ -0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \ -0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \ -0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \ -0x00380438, 0x00000000, 0x00140000, 0x00380555, \ -0x00308000, 0x00100662, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \ -0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \ -0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \ -0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \ -0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \ -0x00041000, 0x00010004, 0x00130826, 0x000C0006, \ -0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380C34, 0x00000000, 0x00000000, \ -0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \ -0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \ -0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \ -0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \ -0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \ -0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \ -0x00130826, 0x000C0001, 0x00220559, 0x00101313, \ -0x00380559, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00130831, 0x0010090B, 0x00124813, \ -0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \ -0x003806A8, 0x00000000, 0x00000000, 0x00000000, \ -} - -/********************************************************/ -/* CPUSaver micro code for the D101S */ -/********************************************************/ - -/* Version 1.20.1 */ - -/* Parameter values for the D101S */ -#define D101S_CPUSAVER_TIMER_DWORD 78 -#define D101S_CPUSAVER_BUNDLE_DWORD 67 -#define D101S_CPUSAVER_MIN_SIZE_DWORD 128 - -#define D101S_RCVBUNDLE_UCODE \ -{\ -0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \ -0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \ -0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \ -0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \ -0x00308000, 0x00100610, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \ -0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \ -0x003A047E, 0x00044010, 0x00380819, 0x00000000, \ -0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \ -0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \ -0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \ -0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \ -0x00101313, 0x00380700, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \ -0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \ -0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \ -0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \ -0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \ -0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \ -0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \ -0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \ -0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00130831, \ -0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \ -0x00041000, 0x00010004, 0x00380700 \ -} - -/********************************************************/ -/* CPUSaver micro code for the D102 B-step */ -/********************************************************/ - -/* Version 2.0 */ -/* Parameter values for the D102 B-step */ -#define D102_B_CPUSAVER_TIMER_DWORD 82 -#define D102_B_CPUSAVER_BUNDLE_DWORD 106 -#define D102_B_CPUSAVER_MIN_SIZE_DWORD 70 - -#define D102_B_RCVBUNDLE_UCODE \ -{\ -0x006F0276, 0x0EF71FFF, 0x0ED30F86, 0x0D250ED9, 0x1FFF1FFF, 0x1FFF04D2, \ -0x00300001, 0x0140D871, 0x00300008, 0x00E00277, \ -0x01406C57, 0x00816073, 0x008700FA, 0x00E00070, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x01406CBA, 0x00807F9A, 0x00901F9A, 0x0024FFFF, \ -0x014B6F6F, 0x0030FFFE, 0x01407172, 0x01496FBA, \ -0x014B6F72, 0x00308000, 0x01406C52, 0x00912EFC, \ -0x00E00EF8, 0x00000000, 0x00000000, 0x00000000, \ -0x00906F8C, 0x00900F8C, 0x00E00F87, 0x00000000, \ -0x00906ED8, 0x01406C55, 0x00E00ED4, 0x00000000, \ -0x01406C51, 0x0080DFC2, 0x01406C52, 0x00815FC2, \ -0x01406C57, 0x00917FCC, 0x00E01FDD, 0x00000000, \ -0x00822D30, 0x01406C51, 0x0080CD26, 0x01406C52, \ -0x00814D26, 0x01406C57, 0x00916D26, 0x014C6FD7, \ -0x00300000, 0x00841FD2, 0x00300001, 0x0140D772, \ -0x00E012B3, 0x014C6F91, 0x0150710B, 0x01496F72, \ -0x0030FF80, 0x00940EDD, 0x00102000, 0x00038400, \ -0x00E00EDA, 0x00000000, 0x00000000, 0x00000000, \ -0x01406C57, 0x00917FE9, 0x00001000, 0x00E01FE9, \ -0x00200600, 0x0140D76F, 0x00138400, 0x01406FD8, \ -0x0140D96F, 0x00E01FDD, 0x00038400, 0x00102000, \ -0x00971FD7, 0x00101000, 0x00050200, 0x00E804D2, \ -0x014C6FD8, 0x00300001, 0x00840D26, 0x0140D872, \ -0x00E00D26, 0x014C6FD9, 0x00300001, 0x0140D972, \ -0x00941FBD, 0x00102000, 0x00038400, 0x014C6FD8, \ -0x00300006, 0x00840EDA, 0x014F71D8, 0x0140D872, \ -0x00E00EDA, 0x01496F50, 0x00E004D3, 0x00000000, \ -} - -/********************************************************/ -/* Micro code for the D102 C-step */ -/********************************************************/ - -/* Parameter values for the D102 C-step */ -#define D102_C_CPUSAVER_TIMER_DWORD 46 -#define D102_C_CPUSAVER_BUNDLE_DWORD 74 -#define D102_C_CPUSAVER_MIN_SIZE_DWORD 54 - -#define D102_C_RCVBUNDLE_UCODE \ -{ \ -0x00700279, 0x0E6604E2, 0x02BF0CAE, 0x1508150C, 0x15190E5B, 0x0E840F13, \ -0x00E014D8, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014DC, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014F4, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014E0, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014E7, 0x00000000, 0x00000000, 0x00000000, \ -0x00141000, 0x015D6F0D, 0x00E002C0, 0x00000000, \ -0x00200600, 0x00E0150D, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0030FF80, 0x00940E6A, 0x00038200, 0x00102000, \ -0x00E00E67, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00906E65, 0x00800E60, 0x00E00E5D, 0x00000000, \ -0x00300006, 0x00E0151A, 0x00000000, 0x00000000, \ -0x00906F19, 0x00900F19, 0x00E00F14, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x01406CBA, 0x00807FDA, 0x00901FDA, 0x0024FFFF, \ -0x014B6F6F, 0x0030FFFE, 0x01407172, 0x01496FBA, \ -0x014B6F72, 0x00308000, 0x01406C52, 0x00912E89, \ -0x00E00E85, 0x00000000, 0x00000000, 0x00000000 \ -} - -/********************************************************/ -/* Micro code for the D102 E-step */ -/********************************************************/ - -/* Parameter values for the D102 E-step */ -#define D102_E_CPUSAVER_TIMER_DWORD 42 -#define D102_E_CPUSAVER_BUNDLE_DWORD 54 -#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46 - -#define D102_E_RCVBUNDLE_UCODE \ -{\ -0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x1FFF1FFF, 0x1FFF1FFF, \ -0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \ -0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \ -0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \ -0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \ -0x00300006, 0x00E014FB, 0x00000000, 0x00000000 \ -} - -#endif /* _E100_UCODE_H_ */ diff --git a/xen/drivers/net/e1000/LICENSE b/xen/drivers/net/e1000/LICENSE deleted file mode 100644 index 5f297e5bb4..0000000000 --- a/xen/drivers/net/e1000/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - -"This software program is licensed subject to the GNU General Public License -(GPL). Version 2, June 1991, available at -" - -GNU General Public License - -Version 2, June 1991 - -Copyright (C) 1989, 1991 Free Software Foundation, Inc. -59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - -Everyone is permitted to copy and distribute verbatim copies of this license -document, but changing it is not allowed. - -Preamble - -The licenses for most software are designed to take away your freedom to -share and change it. By contrast, the GNU General Public License is intended -to guarantee your freedom to share and change free software--to make sure -the software is free for all its users. This General Public License applies -to most of the Free Software Foundation's software and to any other program -whose authors commit to using it. (Some other Free Software Foundation -software is covered by the GNU Library General Public License instead.) You -can apply it to your programs, too. - -When we speak of free software, we are referring to freedom, not price. Our -General Public Licenses are designed to make sure that you have the freedom -to distribute copies of free software (and charge for this service if you -wish), that you receive source code or can get it if you want it, that you -can change the software or use pieces of it in new free programs; and that -you know you can do these things. - -To protect your rights, we need to make restrictions that forbid anyone to -deny you these rights or to ask you to surrender the rights. These -restrictions translate to certain responsibilities for you if you distribute -copies of the software, or if you modify it. - -For example, if you distribute copies of such a program, whether gratis or -for a fee, you must give the recipients all the rights that you have. You -must make sure that they, too, receive or can get the source code. And you -must show them these terms so they know their rights. - -We protect your rights with two steps: (1) copyright the software, and (2) -offer you this license which gives you legal permission to copy, distribute -and/or modify the software. - -Also, for each author's protection and ours, we want to make certain that -everyone understands that there is no warranty for this free software. If -the software is modified by someone else and passed on, we want its -recipients to know that what they have is not the original, so that any -problems introduced by others will not reflect on the original authors' -reputations. - -Finally, any free program is threatened constantly by software patents. We -wish to avoid the danger that redistributors of a free program will -individually obtain patent licenses, in effect making the program -proprietary. To prevent this, we have made it clear that any patent must be -licensed for everyone's free use or not licensed at all. - -The precise terms and conditions for copying, distribution and modification -follow. - -TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - -0. This License applies to any program or other work which contains a notice - placed by the copyright holder saying it may be distributed under the - terms of this General Public License. The "Program", below, refers to any - such program or work, and a "work based on the Program" means either the - Program or any derivative work under copyright law: that is to say, a - work containing the Program or a portion of it, either verbatim or with - modifications and/or translated into another language. (Hereinafter, - translation is included without limitation in the term "modification".) - Each licensee is addressed as "you". - - Activities other than copying, distribution and modification are not - covered by this License; they are outside its scope. The act of running - the Program is not restricted, and the output from the Program is covered - only if its contents constitute a work based on the Program (independent - of having been made by running the Program). Whether that is true depends - on what the Program does. - -1. You may copy and distribute verbatim copies of the Program's source code - as you receive it, in any medium, provided that you conspicuously and - appropriately publish on each copy an appropriate copyright notice and - disclaimer of warranty; keep intact all the notices that refer to this - License and to the absence of any warranty; and give any other recipients - of the Program a copy of this License along with the Program. - - You may charge a fee for the physical act of transferring a copy, and you - may at your option offer warranty protection in exchange for a fee. - -2. You may modify your copy or copies of the Program or any portion of it, - thus forming a work based on the Program, and copy and distribute such - modifications or work under the terms of Section 1 above, provided that - you also meet all of these conditions: - - * a) You must cause the modified files to carry prominent notices stating - that you changed the files and the date of any change. - - * b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any part - thereof, to be licensed as a whole at no charge to all third parties - under the terms of this License. - - * c) If the modified program normally reads commands interactively when - run, you must cause it, when started running for such interactive - use in the most ordinary way, to print or display an announcement - including an appropriate copyright notice and a notice that there is - no warranty (or else, saying that you provide a warranty) and that - users may redistribute the program under these conditions, and - telling the user how to view a copy of this License. (Exception: if - the Program itself is interactive but does not normally print such - an announcement, your work based on the Program is not required to - print an announcement.) - - These requirements apply to the modified work as a whole. If identifiable - sections of that work are not derived from the Program, and can be - reasonably considered independent and separate works in themselves, then - this License, and its terms, do not apply to those sections when you - distribute them as separate works. But when you distribute the same - sections as part of a whole which is a work based on the Program, the - distribution of the whole must be on the terms of this License, whose - permissions for other licensees extend to the entire whole, and thus to - each and every part regardless of who wrote it. - - Thus, it is not the intent of this section to claim rights or contest - your rights to work written entirely by you; rather, the intent is to - exercise the right to control the distribution of derivative or - collective works based on the Program. - - In addition, mere aggregation of another work not based on the Program - with the Program (or with a work based on the Program) on a volume of a - storage or distribution medium does not bring the other work under the - scope of this License. - -3. You may copy and distribute the Program (or a work based on it, under - Section 2) in object code or executable form under the terms of Sections - 1 and 2 above provided that you also do one of the following: - - * a) Accompany it with the complete corresponding machine-readable source - code, which must be distributed under the terms of Sections 1 and 2 - above on a medium customarily used for software interchange; or, - - * b) Accompany it with a written offer, valid for at least three years, - to give any third party, for a charge no more than your cost of - physically performing source distribution, a complete machine- - readable copy of the corresponding source code, to be distributed - under the terms of Sections 1 and 2 above on a medium customarily - used for software interchange; or, - - * c) Accompany it with the information you received as to the offer to - distribute corresponding source code. (This alternative is allowed - only for noncommercial distribution and only if you received the - program in object code or executable form with such an offer, in - accord with Subsection b above.) - - The source code for a work means the preferred form of the work for - making modifications to it. For an executable work, complete source code - means all the source code for all modules it contains, plus any - associated interface definition files, plus the scripts used to control - compilation and installation of the executable. However, as a special - exception, the source code distributed need not include anything that is - normally distributed (in either source or binary form) with the major - components (compiler, kernel, and so on) of the operating system on which - the executable runs, unless that component itself accompanies the - executable. - - If distribution of executable or object code is made by offering access - to copy from a designated place, then offering equivalent access to copy - the source code from the same place counts as distribution of the source - code, even though third parties are not compelled to copy the source - along with the object code. - -4. You may not copy, modify, sublicense, or distribute the Program except as - expressly provided under this License. Any attempt otherwise to copy, - modify, sublicense or distribute the Program is void, and will - automatically terminate your rights under this License. However, parties - who have received copies, or rights, from you under this License will not - have their licenses terminated so long as such parties remain in full - compliance. - -5. You are not required to accept this License, since you have not signed - it. However, nothing else grants you permission to modify or distribute - the Program or its derivative works. These actions are prohibited by law - if you do not accept this License. Therefore, by modifying or - distributing the Program (or any work based on the Program), you - indicate your acceptance of this License to do so, and all its terms and - conditions for copying, distributing or modifying the Program or works - based on it. - -6. Each time you redistribute the Program (or any work based on the - Program), the recipient automatically receives a license from the - original licensor to copy, distribute or modify the Program subject to - these terms and conditions. You may not impose any further restrictions - on the recipients' exercise of the rights granted herein. You are not - responsible for enforcing compliance by third parties to this License. - -7. If, as a consequence of a court judgment or allegation of patent - infringement or for any other reason (not limited to patent issues), - conditions are imposed on you (whether by court order, agreement or - otherwise) that contradict the conditions of this License, they do not - excuse you from the conditions of this License. If you cannot distribute - so as to satisfy simultaneously your obligations under this License and - any other pertinent obligations, then as a consequence you may not - distribute the Program at all. For example, if a patent license would - not permit royalty-free redistribution of the Program by all those who - receive copies directly or indirectly through you, then the only way you - could satisfy both it and this License would be to refrain entirely from - distribution of the Program. - - If any portion of this section is held invalid or unenforceable under any - particular circumstance, the balance of the section is intended to apply - and the section as a whole is intended to apply in other circumstances. - - It is not the purpose of this section to induce you to infringe any - patents or other property right claims or to contest validity of any - such claims; this section has the sole purpose of protecting the - integrity of the free software distribution system, which is implemented - by public license practices. Many people have made generous contributions - to the wide range of software distributed through that system in - reliance on consistent application of that system; it is up to the - author/donor to decide if he or she is willing to distribute software - through any other system and a licensee cannot impose that choice. - - This section is intended to make thoroughly clear what is believed to be - a consequence of the rest of this License. - -8. If the distribution and/or use of the Program is restricted in certain - countries either by patents or by copyrighted interfaces, the original - copyright holder who places the Program under this License may add an - explicit geographical distribution limitation excluding those countries, - so that distribution is permitted only in or among countries not thus - excluded. In such case, this License incorporates the limitation as if - written in the body of this License. - -9. The Free Software Foundation may publish revised and/or new versions of - the General Public License from time to time. Such new versions will be - similar in spirit to the present version, but may differ in detail to - address new problems or concerns. - - Each version is given a distinguishing version number. If the Program - specifies a version number of this License which applies to it and "any - later version", you have the option of following the terms and - conditions either of that version or of any later version published by - the Free Software Foundation. If the Program does not specify a version - number of this License, you may choose any version ever published by the - Free Software Foundation. - -10. If you wish to incorporate parts of the Program into other free programs - whose distribution conditions are different, write to the author to ask - for permission. For software which is copyrighted by the Free Software - Foundation, write to the Free Software Foundation; we sometimes make - exceptions for this. Our decision will be guided by the two goals of - preserving the free status of all derivatives of our free software and - of promoting the sharing and reuse of software generally. - - NO WARRANTY - -11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY - FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN - OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES - PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER - EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE - ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH - YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL - NECESSARY SERVICING, REPAIR OR CORRECTION. - -12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING - WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR - REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR - DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL - DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM - (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED - INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF - THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR - OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -END OF TERMS AND CONDITIONS - -How to Apply These Terms to Your New Programs - -If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it free -software which everyone can redistribute and change under these terms. - -To do so, attach the following notices to the program. It is safest to -attach them to the start of each source file to most effectively convey the -exclusion of warranty; and each file should have at least the "copyright" -line and a pointer to where the full notice is found. - -one line to give the program's name and an idea of what it does. -Copyright (C) yyyy name of author - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your option) -any later version. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 -Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this when -it starts in an interactive mode: - -Gnomovision version 69, Copyright (C) year name of author Gnomovision comes -with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free -software, and you are welcome to redistribute it under certain conditions; -type 'show c' for details. - -The hypothetical commands 'show w' and 'show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may be -called something other than 'show w' and 'show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - -Yoyodyne, Inc., hereby disclaims all copyright interest in the program -'Gnomovision' (which makes passes at compilers) written by James Hacker. - -signature of Ty Coon, 1 April 1989 -Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General Public -License instead of this License. diff --git a/xen/drivers/net/e1000/Makefile b/xen/drivers/net/e1000/Makefile deleted file mode 100644 index f262fcf32b..0000000000 --- a/xen/drivers/net/e1000/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -################################################################################ -# -# -# Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 59 -# Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# The full GNU General Public License is included in this distribution in the -# file called LICENSE. -# -# Contact Information: -# Linux NICS -# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -# -################################################################################ - -# -# Makefile for the Intel(R) PRO/1000 ethernet driver -# - -include $(BASEDIR)/Rules.mk - -default: $(OBJS) - $(LD) -r -o e1000.o $(OBJS) - -clean: - rm -f *.o *~ core diff --git a/xen/drivers/net/e1000/e1000.h b/xen/drivers/net/e1000/e1000.h deleted file mode 100644 index b3e2818fcc..0000000000 --- a/xen/drivers/net/e1000/e1000.h +++ /dev/null @@ -1,259 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - - -/* Linux PRO/1000 Ethernet Driver main header file */ - -#ifndef _E1000_H_ -#define _E1000_H_ - -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -#include -#include -#include -//#include -#include -//#include -//#include -//#include -//#include -#include -#include -#ifdef NETIF_F_TSO -#include -#endif -#ifdef SIOCGMIIPHY -#include -#endif -#ifdef SIOCETHTOOL -#include -#endif -#ifdef NETIF_F_HW_VLAN_TX -#include -#endif - -#define BAR_0 0 -#define BAR_1 1 -#define BAR_5 5 -#define PCI_DMA_64BIT 0xffffffffffffffffULL -#define PCI_DMA_32BIT 0x00000000ffffffffULL - -#include "kcompat.h" - -struct e1000_adapter; - -#include "e1000_hw.h" - -#if DBG -#define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args) -#else -#define E1000_DBG(args...) -#endif - -#define E1000_ERR(args...) printk(KERN_ERR "e1000: " args) - -#define E1000_MAX_INTR 10 - -/* Supported Rx Buffer Sizes */ -#define E1000_RXBUFFER_2048 2048 -#define E1000_RXBUFFER_4096 4096 -#define E1000_RXBUFFER_8192 8192 -#define E1000_RXBUFFER_16384 16384 - -/* SmartSpeed delimiters */ -#define E1000_SMARTSPEED_DOWNSHIFT 3 -#define E1000_SMARTSPEED_MAX 15 - -/* Packet Buffer allocations */ -#define E1000_TX_FIFO_SIZE_SHIFT 0xA -#define E1000_TX_HEAD_ADDR_SHIFT 7 -#define E1000_PBA_TX_MASK 0xFFFF0000 - -/* Flow Control High-Watermark: 43464 bytes */ -#define E1000_FC_HIGH_THRESH 0xA9C8 - -/* Flow Control Low-Watermark: 43456 bytes */ -#define E1000_FC_LOW_THRESH 0xA9C0 - -/* Flow Control Pause Time: 858 usec */ -#define E1000_FC_PAUSE_TIME 0x0680 - -/* How many Tx Descriptors do we need to call netif_wake_queue ? */ -#define E1000_TX_QUEUE_WAKE 16 -/* How many Rx Buffers do we bundle into one write to the hardware ? */ -#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ - -#define AUTO_ALL_MODES 0 -#define E1000_EEPROM_APME 0x0400 - -#ifndef E1000_MASTER_SLAVE -/* Switch to override PHY master/slave setting */ -#define E1000_MASTER_SLAVE e1000_ms_hw_default -#endif - -/* only works for sizes that are powers of 2 */ -#define E1000_ROUNDUP(i, size) ((i) = (((i) + (size) - 1) & ~((size) - 1))) - -/* wrapper around a pointer to a socket buffer, - * so a DMA handle can be stored along with the buffer */ -struct e1000_buffer { - struct sk_buff *skb; - uint64_t dma; - unsigned long length; - unsigned long time_stamp; - unsigned int next_to_watch; -}; - -struct e1000_desc_ring { - /* pointer to the descriptor ring memory */ - void *desc; - /* physical address of the descriptor ring */ - dma_addr_t dma; - /* length of descriptor ring in bytes */ - unsigned int size; - /* number of descriptors in the ring */ - unsigned int count; - /* next descriptor to associate a buffer with */ - unsigned int next_to_use; - /* next descriptor to check for DD status bit */ - unsigned int next_to_clean; - /* array of buffer information structs */ - struct e1000_buffer *buffer_info; -}; - -#define E1000_DESC_UNUSED(R) \ - ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \ - (R)->next_to_clean - (R)->next_to_use - 1) - -#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) -#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc) -#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc) -#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc) - -/* board specific private data structure */ - -struct e1000_adapter { - struct timer_list tx_fifo_stall_timer; - struct timer_list watchdog_timer; - struct timer_list phy_info_timer; -#ifdef NETIF_F_HW_VLAN_TX - struct vlan_group *vlgrp; -#endif - uint32_t bd_number; - uint32_t rx_buffer_len; - uint32_t part_num; - uint32_t wol; - uint32_t smartspeed; - uint16_t link_speed; - uint16_t link_duplex; - spinlock_t stats_lock; - atomic_t irq_sem; - struct work_struct tx_timeout_task; - uint8_t fc_autoneg; - -#ifdef ETHTOOL_PHYS_ID - struct timer_list blink_timer; - unsigned long led_status; -#endif - - /* TX */ - struct e1000_desc_ring tx_ring; - uint32_t txd_cmd; - uint32_t tx_int_delay; - uint32_t tx_abs_int_delay; - uint32_t gotcl; - uint32_t tx_fifo_head; - uint32_t tx_head_addr; - uint32_t tx_fifo_size; - atomic_t tx_fifo_stall; - boolean_t pcix_82544; - - /* RX */ - struct e1000_desc_ring rx_ring; - uint64_t hw_csum_err; - uint64_t hw_csum_good; - uint32_t rx_int_delay; - uint32_t rx_abs_int_delay; - boolean_t rx_csum; - uint32_t gorcl; - - /* Interrupt Throttle Rate */ - uint32_t itr; - - /* OS defined structs */ - struct net_device *netdev; - struct pci_dev *pdev; - struct net_device_stats net_stats; - - /* structs defined in e1000_hw.h */ - struct e1000_hw hw; - struct e1000_hw_stats stats; - struct e1000_phy_info phy_info; - struct e1000_phy_stats phy_stats; - -#ifdef ETHTOOL_TEST - uint32_t test_icr; - struct e1000_desc_ring test_tx_ring; - struct e1000_desc_ring test_rx_ring; -#endif - -#ifdef E1000_COUNT_ICR - uint64_t icr_txdw; - uint64_t icr_txqe; - uint64_t icr_lsc; - uint64_t icr_rxseq; - uint64_t icr_rxdmt; - uint64_t icr_rxo; - uint64_t icr_rxt; - uint64_t icr_mdac; - uint64_t icr_rxcfg; - uint64_t icr_gpi; -#endif - - uint32_t pci_state[16]; -}; -#endif /* _E1000_H_ */ diff --git a/xen/drivers/net/e1000/e1000_ethtool.c b/xen/drivers/net/e1000/e1000_ethtool.c deleted file mode 100644 index fdfaa80733..0000000000 --- a/xen/drivers/net/e1000/e1000_ethtool.c +++ /dev/null @@ -1,1749 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* ethtool support for e1000 */ - -#include "e1000.h" - -#ifdef SIOCETHTOOL -#include - -extern char e1000_driver_name[]; -extern char e1000_driver_version[]; - -extern int e1000_up(struct e1000_adapter *adapter); -extern void e1000_down(struct e1000_adapter *adapter); -extern void e1000_reset(struct e1000_adapter *adapter); -extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx); - -#ifndef ETH_GSTRING_LEN -#define ETH_GSTRING_LEN 32 -#endif -#ifdef ETHTOOL_GSTATS -struct e1000_stats { - char stat_string[ETH_GSTRING_LEN]; - int sizeof_stat; - int stat_offset; -}; - -#define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \ - offsetof(struct e1000_adapter, m) -static struct e1000_stats e1000_gstrings_stats[] = { - { "rx_packets", E1000_STAT(net_stats.rx_packets) }, - { "tx_packets", E1000_STAT(net_stats.tx_packets) }, - { "rx_bytes", E1000_STAT(net_stats.rx_bytes) }, - { "tx_bytes", E1000_STAT(net_stats.tx_bytes) }, - { "rx_errors", E1000_STAT(net_stats.rx_errors) }, - { "tx_errors", E1000_STAT(net_stats.tx_errors) }, - { "rx_dropped", E1000_STAT(net_stats.rx_dropped) }, - { "tx_dropped", E1000_STAT(net_stats.tx_dropped) }, - { "multicast", E1000_STAT(net_stats.multicast) }, - { "collisions", E1000_STAT(net_stats.collisions) }, - { "rx_length_errors", E1000_STAT(net_stats.rx_length_errors) }, - { "rx_over_errors", E1000_STAT(net_stats.rx_over_errors) }, - { "rx_crc_errors", E1000_STAT(net_stats.rx_crc_errors) }, - { "rx_frame_errors", E1000_STAT(net_stats.rx_frame_errors) }, - { "rx_fifo_errors", E1000_STAT(net_stats.rx_fifo_errors) }, - { "rx_missed_errors", E1000_STAT(net_stats.rx_missed_errors) }, - { "tx_aborted_errors", E1000_STAT(net_stats.tx_aborted_errors) }, - { "tx_carrier_errors", E1000_STAT(net_stats.tx_carrier_errors) }, - { "tx_fifo_errors", E1000_STAT(net_stats.tx_fifo_errors) }, - { "tx_heartbeat_errors", E1000_STAT(net_stats.tx_heartbeat_errors) }, - { "tx_window_errors", E1000_STAT(net_stats.tx_window_errors) }, - { "tx_abort_late_coll", E1000_STAT(stats.latecol) }, - { "tx_deferred_ok", E1000_STAT(stats.dc) }, - { "tx_single_coll_ok", E1000_STAT(stats.scc) }, - { "tx_multi_coll_ok", E1000_STAT(stats.mcc) }, - { "rx_long_length_errors", E1000_STAT(stats.roc) }, - { "rx_short_length_errors", E1000_STAT(stats.ruc) }, - { "rx_align_errors", E1000_STAT(stats.algnerrc) }, - { "tx_tcp_seg_good", E1000_STAT(stats.tsctc) }, - { "tx_tcp_seg_failed", E1000_STAT(stats.tsctfc) }, - { "rx_flow_control_xon", E1000_STAT(stats.xonrxc) }, - { "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) }, - { "tx_flow_control_xon", E1000_STAT(stats.xontxc) }, - { "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) }, - { "rx_csum_offload_good", E1000_STAT(hw_csum_good) }, - { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) } -}; -#define E1000_STATS_LEN \ - sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats) -#endif /* ETHTOOL_GSTATS */ -#ifdef ETHTOOL_TEST -static char e1000_gstrings_test[][ETH_GSTRING_LEN] = { - "Register test (offline)", "Eeprom test (offline)", - "Interrupt test (offline)", "Loopback test (offline)", - "Link test (on/offline)" -}; -#define E1000_TEST_LEN sizeof(e1000_gstrings_test) / ETH_GSTRING_LEN -#endif /* ETHTOOL_TEST */ - -static void -e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) -{ - struct e1000_hw *hw = &adapter->hw; - - if(hw->media_type == e1000_media_type_copper) { - - ecmd->supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full| - SUPPORTED_Autoneg | - SUPPORTED_TP); - - ecmd->advertising = ADVERTISED_TP; - - if(hw->autoneg == 1) { - ecmd->advertising |= ADVERTISED_Autoneg; - - /* the e1000 autoneg seems to match ethtool nicely */ - - ecmd->advertising |= hw->autoneg_advertised; - } - - ecmd->port = PORT_TP; - ecmd->phy_address = hw->phy_addr; - - if(hw->mac_type == e1000_82543) - ecmd->transceiver = XCVR_EXTERNAL; - else - ecmd->transceiver = XCVR_INTERNAL; - - } else { - ecmd->supported = (SUPPORTED_1000baseT_Full | - SUPPORTED_FIBRE | - SUPPORTED_Autoneg); - - ecmd->advertising = (SUPPORTED_1000baseT_Full | - SUPPORTED_FIBRE | - SUPPORTED_Autoneg); - - ecmd->port = PORT_FIBRE; - - if(hw->mac_type >= e1000_82545) - ecmd->transceiver = XCVR_INTERNAL; - else - ecmd->transceiver = XCVR_EXTERNAL; - } - - if(netif_carrier_ok(adapter->netdev)) { - - e1000_get_speed_and_duplex(hw, &adapter->link_speed, - &adapter->link_duplex); - ecmd->speed = adapter->link_speed; - - /* unfortunatly FULL_DUPLEX != DUPLEX_FULL - * and HALF_DUPLEX != DUPLEX_HALF */ - - if(adapter->link_duplex == FULL_DUPLEX) - ecmd->duplex = DUPLEX_FULL; - else - ecmd->duplex = DUPLEX_HALF; - } else { - ecmd->speed = -1; - ecmd->duplex = -1; - } - - ecmd->autoneg = (hw->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); -} - -static int -e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) -{ - struct e1000_hw *hw = &adapter->hw; - - if(ecmd->autoneg == AUTONEG_ENABLE) { - hw->autoneg = 1; - hw->autoneg_advertised = 0x002F; - ecmd->advertising = 0x002F; - } else - if(e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) - return -EINVAL; - - /* reset the link */ - - if(netif_running(adapter->netdev)) { - e1000_down(adapter); - e1000_up(adapter); - } else - e1000_reset(adapter); - - return 0; -} - -#ifdef ETHTOOL_GPAUSEPARAM -static int -e1000_ethtool_gpause(struct e1000_adapter *adapter, - struct ethtool_pauseparam *epause) -{ - struct e1000_hw *hw = &adapter->hw; - - epause->autoneg = - (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); - - if(hw->fc == e1000_fc_rx_pause) - epause->rx_pause = 1; - else if(hw->fc == e1000_fc_tx_pause) - epause->tx_pause = 1; - else if(hw->fc == e1000_fc_full) { - epause->rx_pause = 1; - epause->tx_pause = 1; - } - - return 0; -} -#endif /* ETHTOOL_GPAUSEPARAM */ - -#ifdef ETHTOOL_SPAUSEPARAM -static int -e1000_ethtool_spause(struct e1000_adapter *adapter, - struct ethtool_pauseparam *epause) -{ - struct e1000_hw *hw = &adapter->hw; - - adapter->fc_autoneg = epause->autoneg; - - if(epause->rx_pause && epause->tx_pause) - hw->fc = e1000_fc_full; - else if(epause->rx_pause && !epause->tx_pause) - hw->fc = e1000_fc_rx_pause; - else if(!epause->rx_pause && epause->tx_pause) - hw->fc = e1000_fc_tx_pause; - else if(!epause->rx_pause && !epause->tx_pause) - hw->fc = e1000_fc_none; - - hw->original_fc = hw->fc; - - if(netif_running(adapter->netdev)) { - e1000_down(adapter); - e1000_up(adapter); - } else - e1000_reset(adapter); - - return 0; -} -#endif /* ETHTOOL_SPAUSEPARAM */ - -#ifdef ETHTOOL_GDRVINFO -static void -e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter, - struct ethtool_drvinfo *drvinfo) -{ - strncpy(drvinfo->driver, e1000_driver_name, 32); - strncpy(drvinfo->version, e1000_driver_version, 32); - strncpy(drvinfo->fw_version, "N/A", 32); - strncpy(drvinfo->bus_info, adapter->pdev->slot_name, 32); -#ifdef ETHTOOL_GSTATS - drvinfo->n_stats = E1000_STATS_LEN; -#endif /* ETHTOOL_GSTATS */ -#ifdef ETHTOOL_TEST - drvinfo->testinfo_len = E1000_TEST_LEN; -#endif /* ETHTOOL_TEST */ -#ifdef ETHTOOL_GEEPROM /* GREGS broken in earlier ethtool.h */ -#ifdef ETHTOOL_GREGS -#define E1000_REGS_LEN 32 - drvinfo->regdump_len = E1000_REGS_LEN * sizeof(uint32_t); -#endif /* ETHTOOL_GREGS */ -#endif /* ETHTOOL_GEEPROM */ -#ifdef ETHTOOL_GEEPROM - drvinfo->eedump_len = adapter->hw.eeprom.word_size * 2; -#endif /* ETHTOOL_GEEPROM */ -} -#endif /* ETHTOOL_GDRVINFO */ - -#ifdef ETHTOOL_GEEPROM /* GREGS broken in earlier ethtool.h */ -#ifdef ETHTOOL_GREGS -static void -e1000_ethtool_gregs(struct e1000_adapter *adapter, - struct ethtool_regs *regs, uint32_t *regs_buff) -{ - struct e1000_hw *hw = &adapter->hw; - uint16_t phy_data; - - regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; - - regs_buff[0] = E1000_READ_REG(hw, CTRL); - regs_buff[1] = E1000_READ_REG(hw, STATUS); - - regs_buff[2] = E1000_READ_REG(hw, RCTL); - regs_buff[3] = E1000_READ_REG(hw, RDLEN); - regs_buff[4] = E1000_READ_REG(hw, RDH); - regs_buff[5] = E1000_READ_REG(hw, RDT); - regs_buff[6] = E1000_READ_REG(hw, RDTR); - - regs_buff[7] = E1000_READ_REG(hw, TCTL); - regs_buff[8] = E1000_READ_REG(hw, TDLEN); - regs_buff[9] = E1000_READ_REG(hw, TDH); - regs_buff[10] = E1000_READ_REG(hw, TDT); - regs_buff[11] = E1000_READ_REG(hw, TIDV); - - regs_buff[12] = adapter->hw.phy_type; /* PHY type (IGP=1, M88=0) */ - if(hw->phy_type == e1000_phy_igp) { - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_AGC_A); - e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_A & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[13] = (uint32_t)phy_data; /* cable length */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_AGC_B); - e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_B & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[14] = (uint32_t)phy_data; /* cable length */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_AGC_C); - e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_C & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[15] = (uint32_t)phy_data; /* cable length */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_AGC_D); - e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_D & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[16] = (uint32_t)phy_data; /* cable length */ - regs_buff[17] = 0; /* extended 10bt distance (not needed) */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0); - e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[18] = (uint32_t)phy_data; /* cable polarity */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_PCS_INIT_REG); - e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[19] = (uint32_t)phy_data; /* cable polarity */ - regs_buff[20] = 0; /* polarity correction enabled (always) */ - regs_buff[22] = 0; /* phy receive errors (unavailable) */ - regs_buff[23] = regs_buff[18]; /* mdix mode */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0); - } else { - e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - regs_buff[13] = (uint32_t)phy_data; /* cable length */ - regs_buff[14] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - regs_buff[15] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - regs_buff[16] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - regs_buff[17] = (uint32_t)phy_data; /* extended 10bt distance */ - regs_buff[18] = regs_buff[13]; /* cable polarity */ - regs_buff[19] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - regs_buff[20] = regs_buff[17]; /* polarity correction */ - /* phy receive errors */ - regs_buff[22] = adapter->phy_stats.receive_errors; - regs_buff[23] = regs_buff[13]; /* mdix mode */ - } - regs_buff[21] = adapter->phy_stats.idle_errors; /* phy idle errors */ - e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); - regs_buff[24] = (uint32_t)phy_data; /* phy local receiver status */ - regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ - - return; -} -#endif /* ETHTOOL_GREGS */ -#endif /* ETHTOOL_GEEPROM */ - -#ifdef ETHTOOL_GEEPROM -static int -e1000_ethtool_geeprom(struct e1000_adapter *adapter, - struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff) -{ - struct e1000_hw *hw = &adapter->hw; - int first_word, last_word; - int ret_val = 0; - - if(eeprom->len == 0) { - ret_val = -EINVAL; - goto geeprom_error; - } - - eeprom->magic = hw->vendor_id | (hw->device_id << 16); - - if(eeprom->offset > eeprom->offset + eeprom->len) { - ret_val = -EINVAL; - goto geeprom_error; - } - - if((eeprom->offset + eeprom->len) > (hw->eeprom.word_size * 2)) - eeprom->len = ((hw->eeprom.word_size * 2) - eeprom->offset); - - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - - if(hw->eeprom.type == e1000_eeprom_spi) - ret_val = e1000_read_eeprom(hw, first_word, - last_word - first_word + 1, - eeprom_buff); - else { - uint16_t i; - for (i = 0; i < last_word - first_word + 1; i++) - if((ret_val = e1000_read_eeprom(hw, first_word + i, 1, - &eeprom_buff[i]))) - break; - } -geeprom_error: - return ret_val; -} -#endif /* ETHTOOL_GEEPROM */ - -#ifdef ETHTOOL_SEEPROM -static int -e1000_ethtool_seeprom(struct e1000_adapter *adapter, - struct ethtool_eeprom *eeprom, void *user_data) -{ - struct e1000_hw *hw = &adapter->hw; - uint16_t *eeprom_buff; - void *ptr; - int max_len, first_word, last_word, ret_val = 0; - - if(eeprom->len == 0) - return -EOPNOTSUPP; - - if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) - return -EFAULT; - - max_len = hw->eeprom.word_size * 2; - - if((eeprom->offset + eeprom->len) > max_len) - eeprom->len = (max_len - eeprom->offset); - - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff = kmalloc(max_len, GFP_KERNEL); - if(!eeprom_buff) - return -ENOMEM; - - ptr = (void *)eeprom_buff; - - if(eeprom->offset & 1) { - /* need read/modify/write of first changed EEPROM word */ - /* only the second byte of the word is being modified */ - ret_val = e1000_read_eeprom(hw, first_word, 1, - &eeprom_buff[0]); - ptr++; - } - if(((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) { - /* need read/modify/write of last changed EEPROM word */ - /* only the first byte of the word is being modified */ - ret_val = e1000_read_eeprom(hw, last_word, 1, - &eeprom_buff[last_word - first_word]); - } - if((ret_val != 0) || copy_from_user(ptr, user_data, eeprom->len)) { - ret_val = -EFAULT; - goto seeprom_error; - } - - ret_val = e1000_write_eeprom(hw, first_word, - last_word - first_word + 1, eeprom_buff); - - /* Update the checksum over the first part of the EEPROM if needed */ - if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG) - e1000_update_eeprom_checksum(hw); - -seeprom_error: - kfree(eeprom_buff); - return ret_val; -} -#endif /* ETHTOOL_SEEPROM */ - -#ifdef ETHTOOL_TEST -#define REG_PATTERN_TEST(R, M, W) \ -{ \ - uint32_t pat, value; \ - uint32_t test[] = \ - {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \ - for(pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) { \ - E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \ - value = E1000_READ_REG(&adapter->hw, R); \ - if(value != (test[pat] & W & M)) { \ - *data = (adapter->hw.mac_type < e1000_82543) ? \ - E1000_82542_##R : E1000_##R; \ - return 1; \ - } \ - } \ -} - -#define REG_SET_AND_CHECK(R, M, W) \ -{ \ - uint32_t value; \ - E1000_WRITE_REG(&adapter->hw, R, W & M); \ - value = E1000_READ_REG(&adapter->hw, R); \ - if ((W & M) != (value & M)) { \ - *data = (adapter->hw.mac_type < e1000_82543) ? \ - E1000_82542_##R : E1000_##R; \ - return 1; \ - } \ -} - -static int -e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) -{ - uint32_t value; - uint32_t i; - - /* The status register is Read Only, so a write should fail. - * Some bits that get toggled are ignored. - */ - value = (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833)); - E1000_WRITE_REG(&adapter->hw, STATUS, (0xFFFFFFFF)); - if(value != (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833))) { - *data = 1; - return 1; - } - - REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(RDTR, 0x0000FFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(RDBAH, 0xFFFFFFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(RDLEN, 0x000FFF80, 0x000FFFFF); - REG_PATTERN_TEST(RDH, 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(RDT, 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(FCRTH, 0x0000FFF8, 0x0000FFF8); - REG_PATTERN_TEST(FCTTV, 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(TIPG, 0x3FFFFFFF, 0x3FFFFFFF); - REG_PATTERN_TEST(TDBAH, 0xFFFFFFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(TDLEN, 0x000FFF80, 0x000FFFFF); - - REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000); - REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0x003FFFFB); - REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000); - - if(adapter->hw.mac_type >= e1000_82543) { - - REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0xFFFFFFFF); - REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF); - REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF); - REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF); - - for(i = 0; i < E1000_RAR_ENTRIES; i++) { - REG_PATTERN_TEST(RA + ((i << 1) << 2), 0xFFFFFFFF, - 0xFFFFFFFF); - REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF, - 0xFFFFFFFF); - } - - } else { - - REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x01FFFFFF); - REG_PATTERN_TEST(RDBAL, 0xFFFFF000, 0xFFFFFFFF); - REG_PATTERN_TEST(TXCW, 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(TDBAL, 0xFFFFF000, 0xFFFFFFFF); - - } - - for(i = 0; i < E1000_MC_TBL_SIZE; i++) - REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF); - - return 0; -} - -static int -e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data) -{ - uint16_t temp; - uint16_t checksum = 0; - uint16_t i; - - *data = 0; - /* Read and add up the contents of the EEPROM */ - for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { - if((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) { - *data = 1; - break; - } - checksum += temp; - } - - /* If Checksum is not Correct return error else test passed */ - if((checksum != (uint16_t) EEPROM_SUM) && !(*data)) - *data = 2; - - return *data; -} - -static irqreturn_t -e1000_test_intr(int irq, - void *data, - struct pt_regs *regs) -{ - struct net_device *netdev = (struct net_device *) data; - struct e1000_adapter *adapter = netdev->priv; - - adapter->test_icr |= E1000_READ_REG(&adapter->hw, ICR); - - return IRQ_HANDLED; -} - -static int -e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) -{ - struct net_device *netdev = adapter->netdev; - uint32_t icr, mask, i=0; - - *data = 0; - - /* Hook up test interrupt handler just for this test */ - if(request_irq - (netdev->irq, &e1000_test_intr, SA_SHIRQ, netdev->name, netdev)) { - *data = 1; - return -1; - } - - /* Disable all the interrupts */ - E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF); - msec_delay(10); - - /* Interrupts are disabled, so read interrupt cause - * register (icr) twice to verify that there are no interrupts - * pending. icr is clear on read. - */ - icr = E1000_READ_REG(&adapter->hw, ICR); - icr = E1000_READ_REG(&adapter->hw, ICR); - - if(icr != 0) { - /* if icr is non-zero, there is no point - * running other interrupt tests. - */ - *data = 2; - i = 10; - } - - /* Test each interrupt */ - for(; i < 10; i++) { - - /* Interrupt to test */ - mask = 1 << i; - - /* Disable the interrupt to be reported in - * the cause register and then force the same - * interrupt and see if one gets posted. If - * an interrupt was posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - E1000_WRITE_REG(&adapter->hw, IMC, mask); - E1000_WRITE_REG(&adapter->hw, ICS, mask); - msec_delay(10); - - if(adapter->test_icr & mask) { - *data = 3; - break; - } - - /* Enable the interrupt to be reported in - * the cause register and then force the same - * interrupt and see if one gets posted. If - * an interrupt was not posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - E1000_WRITE_REG(&adapter->hw, IMS, mask); - E1000_WRITE_REG(&adapter->hw, ICS, mask); - msec_delay(10); - - if(!(adapter->test_icr & mask)) { - *data = 4; - break; - } - - /* Disable the other interrupts to be reported in - * the cause register and then force the other - * interrupts and see if any get posted. If - * an interrupt was posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - E1000_WRITE_REG(&adapter->hw, IMC, ~mask); - E1000_WRITE_REG(&adapter->hw, ICS, ~mask); - msec_delay(10); - - if(adapter->test_icr) { - *data = 5; - break; - } - } - - /* Disable all the interrupts */ - E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF); - msec_delay(10); - - /* Unhook test interrupt handler */ - free_irq(netdev->irq, netdev); - - return *data; -} - -static void -e1000_free_desc_rings(struct e1000_adapter *adapter) -{ - struct e1000_desc_ring *txdr = &adapter->test_tx_ring; - struct e1000_desc_ring *rxdr = &adapter->test_rx_ring; - struct pci_dev *pdev = adapter->pdev; - int i; - - if(txdr->desc && txdr->buffer_info) { - for(i = 0; i < txdr->count; i++) { - if(txdr->buffer_info[i].dma) - pci_unmap_single(pdev, txdr->buffer_info[i].dma, - txdr->buffer_info[i].length, - PCI_DMA_TODEVICE); - if(txdr->buffer_info[i].skb) - dev_kfree_skb(txdr->buffer_info[i].skb); - } - } - - if(rxdr->desc && rxdr->buffer_info) { - for(i = 0; i < rxdr->count; i++) { - if(rxdr->buffer_info[i].dma) - pci_unmap_single(pdev, rxdr->buffer_info[i].dma, - rxdr->buffer_info[i].length, - PCI_DMA_FROMDEVICE); - if(rxdr->buffer_info[i].skb) - dev_kfree_skb(rxdr->buffer_info[i].skb); - } - } - - if(txdr->desc) - pci_free_consistent(pdev, txdr->size, txdr->desc, txdr->dma); - if(rxdr->desc) - pci_free_consistent(pdev, rxdr->size, rxdr->desc, rxdr->dma); - - if(txdr->buffer_info) - kfree(txdr->buffer_info); - if(rxdr->buffer_info) - kfree(rxdr->buffer_info); - - return; -} - -static int -e1000_setup_desc_rings(struct e1000_adapter *adapter) -{ - struct e1000_desc_ring *txdr = &adapter->test_tx_ring; - struct e1000_desc_ring *rxdr = &adapter->test_rx_ring; - struct pci_dev *pdev = adapter->pdev; - uint32_t rctl; - int size, i, ret_val; - - /* Setup Tx descriptor ring and Tx buffers */ - - txdr->count = 80; - - size = txdr->count * sizeof(struct e1000_buffer); - if(!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) { - ret_val = 1; - goto err_nomem; - } - memset(txdr->buffer_info, 0, size); - - txdr->size = txdr->count * sizeof(struct e1000_tx_desc); - E1000_ROUNDUP(txdr->size, 4096); - if(!(txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma))) { - ret_val = 2; - goto err_nomem; - } - memset(txdr->desc, 0, txdr->size); - txdr->next_to_use = txdr->next_to_clean = 0; - - E1000_WRITE_REG(&adapter->hw, TDBAL, - ((uint64_t) txdr->dma & 0x00000000FFFFFFFF)); - E1000_WRITE_REG(&adapter->hw, TDBAH, ((uint64_t) txdr->dma >> 32)); - E1000_WRITE_REG(&adapter->hw, TDLEN, - txdr->count * sizeof(struct e1000_tx_desc)); - E1000_WRITE_REG(&adapter->hw, TDH, 0); - E1000_WRITE_REG(&adapter->hw, TDT, 0); - E1000_WRITE_REG(&adapter->hw, TCTL, - E1000_TCTL_PSP | E1000_TCTL_EN | - E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT | - E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT); - - for(i = 0; i < txdr->count; i++) { - struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*txdr, i); - struct sk_buff *skb; - unsigned int size = 1024; - - if(!(skb = alloc_skb(size, GFP_KERNEL))) { - ret_val = 3; - goto err_nomem; - } - skb_put(skb, size); - txdr->buffer_info[i].skb = skb; - txdr->buffer_info[i].length = skb->len; - txdr->buffer_info[i].dma = - pci_map_single(pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); - tx_desc->buffer_addr = cpu_to_le64(txdr->buffer_info[i].dma); - tx_desc->lower.data = cpu_to_le32(skb->len); - tx_desc->lower.data |= E1000_TXD_CMD_EOP; - tx_desc->lower.data |= E1000_TXD_CMD_IFCS; - tx_desc->lower.data |= E1000_TXD_CMD_RPS; - tx_desc->upper.data = 0; - } - - /* Setup Rx descriptor ring and Rx buffers */ - - rxdr->count = 80; - - size = rxdr->count * sizeof(struct e1000_buffer); - if(!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) { - ret_val = 4; - goto err_nomem; - } - memset(rxdr->buffer_info, 0, size); - - rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc); - if(!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) { - ret_val = 5; - goto err_nomem; - } - memset(rxdr->desc, 0, rxdr->size); - rxdr->next_to_use = rxdr->next_to_clean = 0; - - rctl = E1000_READ_REG(&adapter->hw, RCTL); - E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN); - E1000_WRITE_REG(&adapter->hw, RDBAL, - ((uint64_t) rxdr->dma & 0xFFFFFFFF)); - E1000_WRITE_REG(&adapter->hw, RDBAH, ((uint64_t) rxdr->dma >> 32)); - E1000_WRITE_REG(&adapter->hw, RDLEN, rxdr->size); - E1000_WRITE_REG(&adapter->hw, RDH, 0); - E1000_WRITE_REG(&adapter->hw, RDT, 0); - rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 | - E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | - (adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT); - E1000_WRITE_REG(&adapter->hw, RCTL, rctl); - - for(i = 0; i < rxdr->count; i++) { - struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i); - struct sk_buff *skb; - - if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + 2, GFP_KERNEL))) { - ret_val = 6; - goto err_nomem; - } - skb_reserve(skb, 2); - rxdr->buffer_info[i].skb = skb; - rxdr->buffer_info[i].length = E1000_RXBUFFER_2048; - rxdr->buffer_info[i].dma = - pci_map_single(pdev, skb->data, E1000_RXBUFFER_2048, - PCI_DMA_FROMDEVICE); - rx_desc->buffer_addr = cpu_to_le64(rxdr->buffer_info[i].dma); - memset(skb->data, 0x00, skb->len); - } - - return 0; - - err_nomem: - e1000_free_desc_rings(adapter); - return ret_val; -} - -static void -e1000_phy_disable_receiver(struct e1000_adapter *adapter) -{ - /* Write out to PHY registers 29 and 30 to disable the Receiver. */ - e1000_write_phy_reg(&adapter->hw, 29, 0x001F); - e1000_write_phy_reg(&adapter->hw, 30, 0x8FFC); - e1000_write_phy_reg(&adapter->hw, 29, 0x001A); - e1000_write_phy_reg(&adapter->hw, 30, 0x8FF0); - - return; -} - -static void -e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter) -{ - uint16_t phy_reg; - - /* Because we reset the PHY above, we need to re-force TX_CLK in the - * Extended PHY Specific Control Register to 25MHz clock. This - * value defaults back to a 2.5MHz clock when the PHY is reset. - */ - e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg); - phy_reg |= M88E1000_EPSCR_TX_CLK_25; - e1000_write_phy_reg(&adapter->hw, - M88E1000_EXT_PHY_SPEC_CTRL, phy_reg); - - /* In addition, because of the s/w reset above, we need to enable - * CRS on TX. This must be set for both full and half duplex - * operation. - */ - e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg); - phy_reg |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - e1000_write_phy_reg(&adapter->hw, - M88E1000_PHY_SPEC_CTRL, phy_reg); -} - -static int -e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter) -{ - uint32_t ctrl_reg; - uint16_t phy_reg; - - /* Setup the Device Control Register for PHY loopback test. */ - - ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL); - ctrl_reg |= (E1000_CTRL_ILOS | /* Invert Loss-Of-Signal */ - E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ - E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ - E1000_CTRL_SPD_1000 | /* Force Speed to 1000 */ - E1000_CTRL_FD); /* Force Duplex to FULL */ - - E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg); - - /* Read the PHY Specific Control Register (0x10) */ - e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg); - - /* Clear Auto-Crossover bits in PHY Specific Control Register - * (bits 6:5). - */ - phy_reg &= ~M88E1000_PSCR_AUTO_X_MODE; - e1000_write_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, phy_reg); - - /* Perform software reset on the PHY */ - e1000_phy_reset(&adapter->hw); - - /* Have to setup TX_CLK and TX_CRS after software reset */ - e1000_phy_reset_clk_and_crs(adapter); - - e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8100); - - /* Wait for reset to complete. */ - usec_delay(500); - - /* Have to setup TX_CLK and TX_CRS after software reset */ - e1000_phy_reset_clk_and_crs(adapter); - - /* Write out to PHY registers 29 and 30 to disable the Receiver. */ - e1000_phy_disable_receiver(adapter); - - /* Set the loopback bit in the PHY control register. */ - e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg); - phy_reg |= MII_CR_LOOPBACK; - e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg); - - /* Setup TX_CLK and TX_CRS one more time. */ - e1000_phy_reset_clk_and_crs(adapter); - - /* Check Phy Configuration */ - e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg); - if(phy_reg != 0x4100) - return 9; - - e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg); - if(phy_reg != 0x0070) - return 10; - - e1000_read_phy_reg(&adapter->hw, 29, &phy_reg); - if(phy_reg != 0x001A) - return 11; - - return 0; -} - -static int -e1000_integrated_phy_loopback(struct e1000_adapter *adapter) -{ - uint32_t ctrl_reg = 0; - uint32_t stat_reg = 0; - - adapter->hw.autoneg = FALSE; - - if(adapter->hw.phy_type == e1000_phy_m88) { - /* Auto-MDI/MDIX Off */ - e1000_write_phy_reg(&adapter->hw, - M88E1000_PHY_SPEC_CTRL, 0x0808); - /* reset to update Auto-MDI/MDIX */ - e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x9140); - /* autoneg off */ - e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8140); - } - /* force 1000, set loopback */ - e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x4140); - - /* Now set up the MAC to the same speed/duplex as the PHY. */ - ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL); - ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ - ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ - E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ - E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */ - E1000_CTRL_FD); /* Force Duplex to FULL */ - - if(adapter->hw.media_type == e1000_media_type_copper && - adapter->hw.phy_type == e1000_phy_m88) { - ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ - } else { - /* Set the ILOS bit on the fiber Nic is half - * duplex link is detected. */ - stat_reg = E1000_READ_REG(&adapter->hw, STATUS); - if((stat_reg & E1000_STATUS_FD) == 0) - ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU); - } - - E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg); - - /* Disable the receiver on the PHY so when a cable is plugged in, the - * PHY does not begin to autoneg when a cable is reconnected to the NIC. - */ - if(adapter->hw.phy_type == e1000_phy_m88) - e1000_phy_disable_receiver(adapter); - - usec_delay(500); - - return 0; -} - -static int -e1000_set_phy_loopback(struct e1000_adapter *adapter) -{ - uint16_t phy_reg = 0; - uint16_t count = 0; - - switch (adapter->hw.mac_type) { - case e1000_82543: - if(adapter->hw.media_type == e1000_media_type_copper) { - /* Attempt to setup Loopback mode on Non-integrated PHY. - * Some PHY registers get corrupted at random, so - * attempt this 10 times. - */ - while(e1000_nonintegrated_phy_loopback(adapter) && - count++ < 10); - if(count < 11) - return 0; - } - break; - - case e1000_82544: - case e1000_82540: - case e1000_82545: - case e1000_82545_rev_3: - case e1000_82546: - case e1000_82546_rev_3: - case e1000_82541: - case e1000_82541_rev_2: - case e1000_82547: - case e1000_82547_rev_2: - return e1000_integrated_phy_loopback(adapter); - break; - - default: - /* Default PHY loopback work is to read the MII - * control register and assert bit 14 (loopback mode). - */ - e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg); - phy_reg |= MII_CR_LOOPBACK; - e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg); - return 0; - break; - } - - return 8; -} - -static int -e1000_setup_loopback_test(struct e1000_adapter *adapter) -{ - uint32_t rctl; - - if(adapter->hw.media_type == e1000_media_type_fiber || - adapter->hw.media_type == e1000_media_type_internal_serdes) { - if(adapter->hw.mac_type == e1000_82545 || - adapter->hw.mac_type == e1000_82546 || - adapter->hw.mac_type == e1000_82545_rev_3 || - adapter->hw.mac_type == e1000_82546_rev_3) - return e1000_set_phy_loopback(adapter); - else { - rctl = E1000_READ_REG(&adapter->hw, RCTL); - rctl |= E1000_RCTL_LBM_TCVR; - E1000_WRITE_REG(&adapter->hw, RCTL, rctl); - return 0; - } - } else if(adapter->hw.media_type == e1000_media_type_copper) - return e1000_set_phy_loopback(adapter); - - return 7; -} - -static void -e1000_loopback_cleanup(struct e1000_adapter *adapter) -{ - uint32_t rctl; - uint16_t phy_reg; - - rctl = E1000_READ_REG(&adapter->hw, RCTL); - rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); - E1000_WRITE_REG(&adapter->hw, RCTL, rctl); - - if(adapter->hw.media_type == e1000_media_type_copper || - ((adapter->hw.media_type == e1000_media_type_fiber || - adapter->hw.media_type == e1000_media_type_internal_serdes) && - (adapter->hw.mac_type == e1000_82545 || - adapter->hw.mac_type == e1000_82546 || - adapter->hw.mac_type == e1000_82545_rev_3 || - adapter->hw.mac_type == e1000_82546_rev_3))) { - adapter->hw.autoneg = TRUE; - e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg); - if(phy_reg & MII_CR_LOOPBACK) { - phy_reg &= ~MII_CR_LOOPBACK; - e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg); - e1000_phy_reset(&adapter->hw); - } - } -} - -static void -e1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size) -{ - memset(skb->data, 0xFF, frame_size); - frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size; - memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1); - memset(&skb->data[frame_size / 2 + 10], 0xBE, 1); - memset(&skb->data[frame_size / 2 + 12], 0xAF, 1); -} - -static int -e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size) -{ - frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size; - if(*(skb->data + 3) == 0xFF) { - if((*(skb->data + frame_size / 2 + 10) == 0xBE) && - (*(skb->data + frame_size / 2 + 12) == 0xAF)) { - return 0; - } - } - return 13; -} - -static int -e1000_run_loopback_test(struct e1000_adapter *adapter) -{ - struct e1000_desc_ring *txdr = &adapter->test_tx_ring; - struct e1000_desc_ring *rxdr = &adapter->test_rx_ring; - struct pci_dev *pdev = adapter->pdev; - int i; - - E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1); - - for(i = 0; i < 64; i++) { - e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 1024); - pci_dma_sync_single(pdev, txdr->buffer_info[i].dma, - txdr->buffer_info[i].length, - PCI_DMA_TODEVICE); - } - E1000_WRITE_REG(&adapter->hw, TDT, i); - - msec_delay(200); - - pci_dma_sync_single(pdev, rxdr->buffer_info[0].dma, - rxdr->buffer_info[0].length, PCI_DMA_FROMDEVICE); - - return e1000_check_lbtest_frame(rxdr->buffer_info[0].skb, 1024); -} - -static int -e1000_loopback_test(struct e1000_adapter *adapter, uint64_t *data) -{ - if((*data = e1000_setup_desc_rings(adapter))) goto err_loopback; - if((*data = e1000_setup_loopback_test(adapter))) goto err_loopback; - *data = e1000_run_loopback_test(adapter); - e1000_loopback_cleanup(adapter); - e1000_free_desc_rings(adapter); -err_loopback: - return *data; -} - -static int -e1000_link_test(struct e1000_adapter *adapter, uint64_t *data) -{ - *data = 0; - e1000_check_for_link(&adapter->hw); - - if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) { - *data = 1; - } - return *data; -} - -static int -e1000_ethtool_test(struct e1000_adapter *adapter, - struct ethtool_test *eth_test, uint64_t *data) -{ - boolean_t if_running = netif_running(adapter->netdev); - - if(eth_test->flags == ETH_TEST_FL_OFFLINE) { - /* Offline tests */ - - /* Link test performed before hardware reset so autoneg doesn't - * interfere with test result */ - if(e1000_link_test(adapter, &data[4])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - if(if_running) - e1000_down(adapter); - else - e1000_reset(adapter); - - if(e1000_reg_test(adapter, &data[0])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - e1000_reset(adapter); - if(e1000_eeprom_test(adapter, &data[1])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - e1000_reset(adapter); - if(e1000_intr_test(adapter, &data[2])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - e1000_reset(adapter); - if(e1000_loopback_test(adapter, &data[3])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - e1000_reset(adapter); - if(if_running) - e1000_up(adapter); - } else { - /* Online tests */ - if(e1000_link_test(adapter, &data[4])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - /* Offline tests aren't run; pass by default */ - data[0] = 0; - data[1] = 0; - data[2] = 0; - data[3] = 0; - } - return 0; -} -#endif /* ETHTOOL_TEST */ - -#ifdef ETHTOOL_GWOL -static void -e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) -{ - struct e1000_hw *hw = &adapter->hw; - - switch(adapter->hw.device_id) { - case E1000_DEV_ID_82542: - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - wol->supported = 0; - wol->wolopts = 0; - return; - - case E1000_DEV_ID_82546EB_FIBER: - case E1000_DEV_ID_82546GB_FIBER: - /* Wake events only supported on port A for dual fiber */ - if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) { - wol->supported = 0; - wol->wolopts = 0; - return; - } - /* Fall Through */ - - default: - wol->supported = WAKE_UCAST | WAKE_MCAST | - WAKE_BCAST | WAKE_MAGIC; - - wol->wolopts = 0; - if(adapter->wol & E1000_WUFC_EX) - wol->wolopts |= WAKE_UCAST; - if(adapter->wol & E1000_WUFC_MC) - wol->wolopts |= WAKE_MCAST; - if(adapter->wol & E1000_WUFC_BC) - wol->wolopts |= WAKE_BCAST; - if(adapter->wol & E1000_WUFC_MAG) - wol->wolopts |= WAKE_MAGIC; - return; - } -} -#endif /* ETHTOOL_GWOL */ - -#ifdef ETHTOOL_SWOL -static int -e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) -{ - struct e1000_hw *hw = &adapter->hw; - - switch(adapter->hw.device_id) { - case E1000_DEV_ID_82542: - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - return wol->wolopts ? -EOPNOTSUPP : 0; - - case E1000_DEV_ID_82546EB_FIBER: - case E1000_DEV_ID_82546GB_FIBER: - /* Wake events only supported on port A for dual fiber */ - if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) - return wol->wolopts ? -EOPNOTSUPP : 0; - /* Fall Through */ - - default: - if(wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) - return -EOPNOTSUPP; - - adapter->wol = 0; - - if(wol->wolopts & WAKE_UCAST) - adapter->wol |= E1000_WUFC_EX; - if(wol->wolopts & WAKE_MCAST) - adapter->wol |= E1000_WUFC_MC; - if(wol->wolopts & WAKE_BCAST) - adapter->wol |= E1000_WUFC_BC; - if(wol->wolopts & WAKE_MAGIC) - adapter->wol |= E1000_WUFC_MAG; - } - - return 0; -} -#endif /* ETHTOOL_SWOL */ - -#ifdef ETHTOOL_PHYS_ID - -/* toggle LED 4 times per second = 2 "blinks" per second */ -#define E1000_ID_INTERVAL (HZ/4) - -/* bit defines for adapter->led_status */ -#define E1000_LED_ON 0 - -static void -e1000_led_blink_callback(unsigned long data) -{ - struct e1000_adapter *adapter = (struct e1000_adapter *) data; - - if(test_and_change_bit(E1000_LED_ON, &adapter->led_status)) - e1000_led_off(&adapter->hw); - else - e1000_led_on(&adapter->hw); - - mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL); -} - -static int -e1000_ethtool_led_blink(struct e1000_adapter *adapter, struct ethtool_value *id) -{ - if(!adapter->blink_timer.function) { - init_timer(&adapter->blink_timer); - adapter->blink_timer.function = e1000_led_blink_callback; - adapter->blink_timer.data = (unsigned long) adapter; - } - - e1000_setup_led(&adapter->hw); - mod_timer(&adapter->blink_timer, jiffies); - - set_current_state(TASK_INTERRUPTIBLE); - if(id->data) - schedule_timeout(id->data * HZ); - else - schedule_timeout(MAX_SCHEDULE_TIMEOUT); - - del_timer_sync(&adapter->blink_timer); - e1000_led_off(&adapter->hw); - clear_bit(E1000_LED_ON, &adapter->led_status); - e1000_cleanup_led(&adapter->hw); - - return 0; -} -#endif /* ETHTOOL_PHYS_ID */ - -int -e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr) -{ - struct e1000_adapter *adapter = netdev->priv; - void *addr = ifr->ifr_data; - uint32_t cmd; - - if(get_user(cmd, (uint32_t *) addr)) - return -EFAULT; - - switch(cmd) { - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = {ETHTOOL_GSET}; - e1000_ethtool_gset(adapter, &ecmd); - if(copy_to_user(addr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSET: { - struct ethtool_cmd ecmd; - if(copy_from_user(&ecmd, addr, sizeof(ecmd))) - return -EFAULT; - return e1000_ethtool_sset(adapter, &ecmd); - } -#ifdef ETHTOOL_GDRVINFO - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo drvinfo = {ETHTOOL_GDRVINFO}; - e1000_ethtool_gdrvinfo(adapter, &drvinfo); - if(copy_to_user(addr, &drvinfo, sizeof(drvinfo))) - return -EFAULT; - return 0; - } -#endif /* ETHTOOL_GDRVINFO */ -#ifdef ETHTOOL_GSTRINGS - case ETHTOOL_GSTRINGS: { - struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS }; - char *strings = NULL; - int err = 0; - - if(copy_from_user(&gstrings, addr, sizeof(gstrings))) - return -EFAULT; - switch(gstrings.string_set) { -#ifdef ETHTOOL_TEST - case ETH_SS_TEST: - gstrings.len = E1000_TEST_LEN; - strings = kmalloc(E1000_TEST_LEN * ETH_GSTRING_LEN, - GFP_KERNEL); - if(!strings) - return -ENOMEM; - memcpy(strings, e1000_gstrings_test, E1000_TEST_LEN * - ETH_GSTRING_LEN); - break; -#endif /* ETHTOOL_TEST */ -#ifdef ETHTOOL_GSTATS - case ETH_SS_STATS: { - int i; - gstrings.len = E1000_STATS_LEN; - strings = kmalloc(E1000_STATS_LEN * ETH_GSTRING_LEN, - GFP_KERNEL); - if(!strings) - return -ENOMEM; - for(i=0; i < E1000_STATS_LEN; i++) { - memcpy(&strings[i * ETH_GSTRING_LEN], - e1000_gstrings_stats[i].stat_string, - ETH_GSTRING_LEN); - } - break; - } -#endif /* ETHTOOL_GSTATS */ - default: - return -EOPNOTSUPP; - } - if(copy_to_user(addr, &gstrings, sizeof(gstrings))) - err = -EFAULT; - addr += offsetof(struct ethtool_gstrings, data); - if(!err && copy_to_user(addr, strings, - gstrings.len * ETH_GSTRING_LEN)) - err = -EFAULT; - - kfree(strings); - return err; - } -#endif /* ETHTOOL_GSTRINGS */ -#ifdef ETHTOOL_GEEPROM /* GREGS broken in earlier ethtool.h */ -#ifdef ETHTOOL_GREGS - case ETHTOOL_GREGS: { - struct ethtool_regs regs = {ETHTOOL_GREGS}; - uint32_t regs_buff[E1000_REGS_LEN]; - - if(copy_from_user(®s, addr, sizeof(regs))) - return -EFAULT; - e1000_ethtool_gregs(adapter, ®s, regs_buff); - if(copy_to_user(addr, ®s, sizeof(regs))) - return -EFAULT; - - addr += offsetof(struct ethtool_regs, data); - if(copy_to_user(addr, regs_buff, regs.len)) - return -EFAULT; - - return 0; - } -#endif /* ETHTOOL_GREGS */ -#endif /* ETHTOOL_GEEPROM */ -#ifdef ETHTOOL_NWAY_RST - case ETHTOOL_NWAY_RST: { - if(netif_running(netdev)) { - e1000_down(adapter); - e1000_up(adapter); - } - return 0; - } -#endif /* ETHTOOL_NWAY_RST */ -#ifdef ETHTOOL_PHYS_ID - case ETHTOOL_PHYS_ID: { - struct ethtool_value id; - if(copy_from_user(&id, addr, sizeof(id))) - return -EFAULT; - return e1000_ethtool_led_blink(adapter, &id); - } -#endif /* ETHTOOL_PHYS_ID */ -#ifdef ETHTOOL_GLINK - case ETHTOOL_GLINK: { - struct ethtool_value link = {ETHTOOL_GLINK}; - link.data = netif_carrier_ok(netdev); - if(copy_to_user(addr, &link, sizeof(link))) - return -EFAULT; - return 0; - } -#endif /* ETHTOOL_GLINK */ -#ifdef ETHTOOL_GWOL - case ETHTOOL_GWOL: { - struct ethtool_wolinfo wol = {ETHTOOL_GWOL}; - e1000_ethtool_gwol(adapter, &wol); - if(copy_to_user(addr, &wol, sizeof(wol)) != 0) - return -EFAULT; - return 0; - } -#endif /* ETHTOOL_GWOL */ -#ifdef ETHTOOL_SWOL - case ETHTOOL_SWOL: { - struct ethtool_wolinfo wol; - if(copy_from_user(&wol, addr, sizeof(wol)) != 0) - return -EFAULT; - return e1000_ethtool_swol(adapter, &wol); - } -#endif /* ETHTOOL_SWOL */ -#ifdef ETHTOOL_GEEPROM - case ETHTOOL_GEEPROM: { - struct ethtool_eeprom eeprom = {ETHTOOL_GEEPROM}; - struct e1000_hw *hw = &adapter->hw; - uint16_t *eeprom_buff; - void *ptr; - int err = 0; - - if(copy_from_user(&eeprom, addr, sizeof(eeprom))) - return -EFAULT; - - eeprom_buff = kmalloc(hw->eeprom.word_size * 2, GFP_KERNEL); - - if(!eeprom_buff) - return -ENOMEM; - - if((err = e1000_ethtool_geeprom(adapter, &eeprom, - eeprom_buff))) - goto err_geeprom_ioctl; - - if(copy_to_user(addr, &eeprom, sizeof(eeprom))) { - err = -EFAULT; - goto err_geeprom_ioctl; - } - - addr += offsetof(struct ethtool_eeprom, data); - ptr = ((void *)eeprom_buff) + (eeprom.offset & 1); - - if(copy_to_user(addr, ptr, eeprom.len)) - err = -EFAULT; - -err_geeprom_ioctl: - kfree(eeprom_buff); - return err; - } -#endif /* ETHTOOL_GEEPROM */ -#ifdef ETHTOOL_SEEPROM - case ETHTOOL_SEEPROM: { - struct ethtool_eeprom eeprom; - - if(copy_from_user(&eeprom, addr, sizeof(eeprom))) - return -EFAULT; - - addr += offsetof(struct ethtool_eeprom, data); - return e1000_ethtool_seeprom(adapter, &eeprom, addr); - } -#endif /* ETHTOOL_SEEPROM */ -#ifdef ETHTOOL_GPAUSEPARAM - case ETHTOOL_GPAUSEPARAM: { - struct ethtool_pauseparam epause = {ETHTOOL_GPAUSEPARAM}; - e1000_ethtool_gpause(adapter, &epause); - if(copy_to_user(addr, &epause, sizeof(epause))) - return -EFAULT; - return 0; - } -#endif /* ETHTOOL_GPAUSEPARAM */ -#ifdef ETHTOOL_SPAUSEPARAM - case ETHTOOL_SPAUSEPARAM: { - struct ethtool_pauseparam epause; - if(copy_from_user(&epause, addr, sizeof(epause))) - return -EFAULT; - return e1000_ethtool_spause(adapter, &epause); - } -#endif /* ETHTOOL_SPAUSEPARAM */ -#ifdef ETHTOOL_GSTATS - case ETHTOOL_GSTATS: { - struct { - struct ethtool_stats eth_stats; - uint64_t data[E1000_STATS_LEN]; - } stats = { {ETHTOOL_GSTATS, E1000_STATS_LEN} }; - int i; - - for(i = 0; i < E1000_STATS_LEN; i++) - stats.data[i] = (e1000_gstrings_stats[i].sizeof_stat == - sizeof(uint64_t)) ? - *(uint64_t *)((char *)adapter + - e1000_gstrings_stats[i].stat_offset) : - *(uint32_t *)((char *)adapter + - e1000_gstrings_stats[i].stat_offset); - if(copy_to_user(addr, &stats, sizeof(stats))) - return -EFAULT; - return 0; - } -#endif /* ETHTOOL_GSTATS */ -#ifdef ETHTOOL_TEST - case ETHTOOL_TEST: { - struct { - struct ethtool_test eth_test; - uint64_t data[E1000_TEST_LEN]; - } test = { {ETHTOOL_TEST} }; - int err; - - if(copy_from_user(&test.eth_test, addr, sizeof(test.eth_test))) - return -EFAULT; - - test.eth_test.len = E1000_TEST_LEN; - - if((err = e1000_ethtool_test(adapter, &test.eth_test, - test.data))) - return err; - - if(copy_to_user(addr, &test, sizeof(test)) != 0) - return -EFAULT; - return 0; - } -#endif /* ETHTOOL_TEST */ -#ifdef ETHTOOL_GRXCSUM - case ETHTOOL_GRXCSUM: { - struct ethtool_value edata = { ETHTOOL_GRXCSUM }; - - edata.data = adapter->rx_csum; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } -#endif /* ETHTOOL_GRXCSUM */ -#ifdef ETHTOOL_SRXCSUM - case ETHTOOL_SRXCSUM: { - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - adapter->rx_csum = edata.data; - if(netif_running(netdev)) { - e1000_down(adapter); - e1000_up(adapter); - } else - e1000_reset(adapter); - return 0; - } -#endif /* ETHTOOL_SRXCSUM */ -#ifdef ETHTOOL_GTXCSUM - case ETHTOOL_GTXCSUM: { - struct ethtool_value edata = { ETHTOOL_GTXCSUM }; - - edata.data = - (netdev->features & NETIF_F_HW_CSUM) != 0; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } -#endif /* ETHTOOL_GTXCSUM */ -#ifdef ETHTOOL_STXCSUM - case ETHTOOL_STXCSUM: { - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - - if(adapter->hw.mac_type < e1000_82543) { - if (edata.data != 0) - return -EINVAL; - return 0; - } - - if (edata.data) - netdev->features |= NETIF_F_HW_CSUM; - else - netdev->features &= ~NETIF_F_HW_CSUM; - - return 0; - } -#endif /* ETHTOOL_STXCSUM */ -#ifdef ETHTOOL_GSG - case ETHTOOL_GSG: { - struct ethtool_value edata = { ETHTOOL_GSG }; - - edata.data = - (netdev->features & NETIF_F_SG) != 0; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } -#endif /* ETHTOOL_GSG */ -#ifdef ETHTOOL_SSG - case ETHTOOL_SSG: { - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - - if (edata.data) - netdev->features |= NETIF_F_SG; - else - netdev->features &= ~NETIF_F_SG; - - return 0; - } -#endif /* ETHTOOL_SSG */ -#ifdef NETIF_F_TSO -#ifdef ETHTOOL_GTSO - case ETHTOOL_GTSO: { - struct ethtool_value edata = { ETHTOOL_GTSO }; - - edata.data = (netdev->features & NETIF_F_TSO) != 0; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } -#endif /* ETHTOOL_GTSO */ -#ifdef ETHTOOL_STSO - case ETHTOOL_STSO: { - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - - if ((adapter->hw.mac_type < e1000_82544) || - (adapter->hw.mac_type == e1000_82547)) { - if (edata.data != 0) - return -EINVAL; - return 0; - } - - if (edata.data) - netdev->features |= NETIF_F_TSO; - else - netdev->features &= ~NETIF_F_TSO; - - return 0; - } -#endif /* ETHTOOL_STSO */ -#endif - default: - return -EOPNOTSUPP; - } -} - -#endif /* SIOCETHTOOL */ - diff --git a/xen/drivers/net/e1000/e1000_hw.c b/xen/drivers/net/e1000/e1000_hw.c deleted file mode 100644 index 303651e115..0000000000 --- a/xen/drivers/net/e1000/e1000_hw.c +++ /dev/null @@ -1,5095 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* e1000_hw.c - * Shared functions for accessing and configuring the MAC - */ - -#include "e1000_hw.h" - -static int32_t e1000_set_phy_type(struct e1000_hw *hw); -static void e1000_phy_init_script(struct e1000_hw *hw); -static int32_t e1000_setup_copper_link(struct e1000_hw *hw); -static int32_t e1000_setup_fiber_serdes_link(struct e1000_hw *hw); -static int32_t e1000_adjust_serdes_amplitude(struct e1000_hw *hw); -static int32_t e1000_phy_force_speed_duplex(struct e1000_hw *hw); -static int32_t e1000_config_mac_to_phy(struct e1000_hw *hw); -static void e1000_raise_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl); -static void e1000_lower_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl); -static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data, - uint16_t count); -static uint16_t e1000_shift_in_mdi_bits(struct e1000_hw *hw); -static int32_t e1000_phy_reset_dsp(struct e1000_hw *hw); -static int32_t e1000_write_eeprom_spi(struct e1000_hw *hw, uint16_t offset, - uint16_t words, uint16_t *data); -static int32_t e1000_write_eeprom_microwire(struct e1000_hw *hw, - uint16_t offset, uint16_t words, - uint16_t *data); -static int32_t e1000_spi_eeprom_ready(struct e1000_hw *hw); -static void e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t *eecd); -static void e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t *eecd); -static void e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data, - uint16_t count); -static int32_t e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr, - uint16_t phy_data); -static int32_t e1000_read_phy_reg_ex(struct e1000_hw *hw,uint32_t reg_addr, - uint16_t *phy_data); -static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw, uint16_t count); -static int32_t e1000_acquire_eeprom(struct e1000_hw *hw); -static void e1000_release_eeprom(struct e1000_hw *hw); -static void e1000_standby_eeprom(struct e1000_hw *hw); -static int32_t e1000_id_led_init(struct e1000_hw * hw); -static int32_t e1000_set_vco_speed(struct e1000_hw *hw); - -/* IGP cable length table */ -static const -uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = - { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, - 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90, - 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120}; - - -/****************************************************************************** - * Set the phy type member in the hw struct. - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -int32_t -e1000_set_phy_type(struct e1000_hw *hw) -{ - DEBUGFUNC("e1000_set_phy_type"); - - switch(hw->phy_id) { - case M88E1000_E_PHY_ID: - case M88E1000_I_PHY_ID: - case M88E1011_I_PHY_ID: - hw->phy_type = e1000_phy_m88; - break; - case IGP01E1000_I_PHY_ID: - hw->phy_type = e1000_phy_igp; - break; - default: - /* Should never have loaded on this device */ - hw->phy_type = e1000_phy_undefined; - return -E1000_ERR_PHY_TYPE; - } - - return E1000_SUCCESS; -} - -/****************************************************************************** - * IGP phy init script - initializes the GbE PHY - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -static void -e1000_phy_init_script(struct e1000_hw *hw) -{ - DEBUGFUNC("e1000_phy_init_script"); - - if(hw->phy_init_script) { - msec_delay(20); - - e1000_write_phy_reg(hw,0x0000,0x0140); - - msec_delay(5); - - if(hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547) { - e1000_write_phy_reg(hw, 0x1F95, 0x0001); - - e1000_write_phy_reg(hw, 0x1F71, 0xBD21); - - e1000_write_phy_reg(hw, 0x1F79, 0x0018); - - e1000_write_phy_reg(hw, 0x1F30, 0x1600); - - e1000_write_phy_reg(hw, 0x1F31, 0x0014); - - e1000_write_phy_reg(hw, 0x1F32, 0x161C); - - e1000_write_phy_reg(hw, 0x1F94, 0x0003); - - e1000_write_phy_reg(hw, 0x1F96, 0x003F); - - e1000_write_phy_reg(hw, 0x2010, 0x0008); - } else { - e1000_write_phy_reg(hw, 0x1F73, 0x0099); - } - - e1000_write_phy_reg(hw, 0x0000, 0x3300); - - - if(hw->mac_type == e1000_82547) { - uint16_t fused, fine, coarse; - - /* Move to analog registers page */ - e1000_read_phy_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused); - - if(!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) { - e1000_read_phy_reg(hw, IGP01E1000_ANALOG_FUSE_STATUS, &fused); - - fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK; - coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK; - - if(coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) { - coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10; - fine -= IGP01E1000_ANALOG_FUSE_FINE_1; - } else if(coarse == IGP01E1000_ANALOG_FUSE_COARSE_THRESH) - fine -= IGP01E1000_ANALOG_FUSE_FINE_10; - - fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) | - (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) | - (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK); - - e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_CONTROL, fused); - e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_BYPASS, - IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL); - } - } - } -} - -/****************************************************************************** - * Set the mac type member in the hw struct. - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -int32_t -e1000_set_mac_type(struct e1000_hw *hw) -{ - DEBUGFUNC("e1000_set_mac_type"); - - switch (hw->device_id) { - case E1000_DEV_ID_82542: - switch (hw->revision_id) { - case E1000_82542_2_0_REV_ID: - hw->mac_type = e1000_82542_rev2_0; - break; - case E1000_82542_2_1_REV_ID: - hw->mac_type = e1000_82542_rev2_1; - break; - default: - /* Invalid 82542 revision ID */ - return -E1000_ERR_MAC_TYPE; - } - break; - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - hw->mac_type = e1000_82543; - break; - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: - hw->mac_type = e1000_82544; - break; - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - hw->mac_type = e1000_82540; - break; - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82545EM_FIBER: - hw->mac_type = e1000_82545; - break; - case E1000_DEV_ID_82545GM_COPPER: - case E1000_DEV_ID_82545GM_FIBER: - case E1000_DEV_ID_82545GM_SERDES: - hw->mac_type = e1000_82545_rev_3; - break; - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_FIBER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - hw->mac_type = e1000_82546; - break; - case E1000_DEV_ID_82546GB_COPPER: - case E1000_DEV_ID_82546GB_FIBER: - case E1000_DEV_ID_82546GB_SERDES: - hw->mac_type = e1000_82546_rev_3; - break; - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EI_MOBILE: - hw->mac_type = e1000_82541; - break; - case E1000_DEV_ID_82541ER: - case E1000_DEV_ID_82541GI: - case E1000_DEV_ID_82541GI_MOBILE: - hw->mac_type = e1000_82541_rev_2; - break; - case E1000_DEV_ID_82547EI: - hw->mac_type = e1000_82547; - break; - case E1000_DEV_ID_82547GI: - hw->mac_type = e1000_82547_rev_2; - break; - default: - /* Should never have loaded on this device */ - return -E1000_ERR_MAC_TYPE; - } - - return E1000_SUCCESS; -} - -/***************************************************************************** - * Set media type and TBI compatibility. - * - * hw - Struct containing variables accessed by shared code - * **************************************************************************/ -void -e1000_set_media_type(struct e1000_hw *hw) -{ - uint32_t status; - - DEBUGFUNC("e1000_set_media_type"); - - if(hw->mac_type != e1000_82543) { - /* tbi_compatibility is only valid on 82543 */ - hw->tbi_compatibility_en = FALSE; - } - - switch (hw->device_id) { - case E1000_DEV_ID_82545GM_SERDES: - case E1000_DEV_ID_82546GB_SERDES: - hw->media_type = e1000_media_type_internal_serdes; - break; - default: - if(hw->mac_type >= e1000_82543) { - status = E1000_READ_REG(hw, STATUS); - if(status & E1000_STATUS_TBIMODE) { - hw->media_type = e1000_media_type_fiber; - /* tbi_compatibility not valid on fiber */ - hw->tbi_compatibility_en = FALSE; - } else { - hw->media_type = e1000_media_type_copper; - } - } else { - /* This is an 82542 (fiber only) */ - hw->media_type = e1000_media_type_fiber; - } - } -} - -/****************************************************************************** - * Reset the transmit and receive units; mask and clear all interrupts. - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -int32_t -e1000_reset_hw(struct e1000_hw *hw) -{ - uint32_t ctrl; - uint32_t ctrl_ext; - uint32_t icr; - uint32_t manc; - uint32_t led_ctrl; - - DEBUGFUNC("e1000_reset_hw"); - - /* For 82542 (rev 2.0), disable MWI before issuing a device reset */ - if(hw->mac_type == e1000_82542_rev2_0) { - DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); - e1000_pci_clear_mwi(hw); - } - - /* Clear interrupt mask to stop board from generating interrupts */ - DEBUGOUT("Masking off all interrupts\n"); - E1000_WRITE_REG(hw, IMC, 0xffffffff); - - /* Disable the Transmit and Receive units. Then delay to allow - * any pending transactions to complete before we hit the MAC with - * the global reset. - */ - E1000_WRITE_REG(hw, RCTL, 0); - E1000_WRITE_REG(hw, TCTL, E1000_TCTL_PSP); - E1000_WRITE_FLUSH(hw); - - /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */ - hw->tbi_compatibility_on = FALSE; - - /* Delay to allow any outstanding PCI transactions to complete before - * resetting the device - */ - msec_delay(10); - - ctrl = E1000_READ_REG(hw, CTRL); - - /* Must reset the PHY before resetting the MAC */ - if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { - E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST)); - msec_delay(5); - } - - /* Issue a global reset to the MAC. This will reset the chip's - * transmit, receive, DMA, and link units. It will not effect - * the current PCI configuration. The global reset bit is self- - * clearing, and should clear within a microsecond. - */ - DEBUGOUT("Issuing a global reset to MAC\n"); - - switch(hw->mac_type) { - case e1000_82544: - case e1000_82540: - case e1000_82545: - case e1000_82546: - case e1000_82541: - case e1000_82541_rev_2: - /* These controllers can't ack the 64-bit write when issuing the - * reset, so use IO-mapping as a workaround to issue the reset */ - E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); - break; - case e1000_82545_rev_3: - case e1000_82546_rev_3: - /* Reset is performed on a shadow of the control register */ - E1000_WRITE_REG(hw, CTRL_DUP, (ctrl | E1000_CTRL_RST)); - break; - default: - E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST)); - break; - } - - /* After MAC reset, force reload of EEPROM to restore power-on settings to - * device. Later controllers reload the EEPROM automatically, so just wait - * for reload to complete. - */ - switch(hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - case e1000_82544: - /* Wait for reset to complete */ - usec_delay(10); - ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_EE_RST; - E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(hw); - /* Wait for EEPROM reload */ - msec_delay(2); - break; - case e1000_82541: - case e1000_82541_rev_2: - case e1000_82547: - case e1000_82547_rev_2: - /* Wait for EEPROM reload */ - msec_delay(20); - break; - default: - /* Wait for EEPROM reload (it happens automatically) */ - msec_delay(5); - break; - } - - /* Disable HW ARPs on ASF enabled adapters */ - if(hw->mac_type >= e1000_82540) { - manc = E1000_READ_REG(hw, MANC); - manc &= ~(E1000_MANC_ARP_EN); - E1000_WRITE_REG(hw, MANC, manc); - } - - if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { - e1000_phy_init_script(hw); - - /* Configure activity LED after PHY reset */ - led_ctrl = E1000_READ_REG(hw, LEDCTL); - led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - E1000_WRITE_REG(hw, LEDCTL, led_ctrl); - } - - /* Clear interrupt mask to stop board from generating interrupts */ - DEBUGOUT("Masking off all interrupts\n"); - E1000_WRITE_REG(hw, IMC, 0xffffffff); - - /* Clear any pending interrupt events. */ - icr = E1000_READ_REG(hw, ICR); - - /* If MWI was previously enabled, reenable it. */ - if(hw->mac_type == e1000_82542_rev2_0) { - if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) - e1000_pci_set_mwi(hw); - } - - return E1000_SUCCESS; -} - -/****************************************************************************** - * Performs basic configuration of the adapter. - * - * hw - Struct containing variables accessed by shared code - * - * Assumes that the controller has previously been reset and is in a - * post-reset uninitialized state. Initializes the receive address registers, - * multicast table, and VLAN filter table. Calls routines to setup link - * configuration and flow control settings. Clears all on-chip counters. Leaves - * the transmit and receive units disabled and uninitialized. - *****************************************************************************/ -int32_t -e1000_init_hw(struct e1000_hw *hw) -{ - uint32_t ctrl; - uint32_t i; - int32_t ret_val; - uint16_t pcix_cmd_word; - uint16_t pcix_stat_hi_word; - uint16_t cmd_mmrbc; - uint16_t stat_mmrbc; - - DEBUGFUNC("e1000_init_hw"); - - /* Initialize Identification LED */ - if((ret_val = e1000_id_led_init(hw))) { - DEBUGOUT("Error Initializing Identification LED\n"); - return ret_val; - } - - /* Set the media type and TBI compatibility */ - e1000_set_media_type(hw); - - /* Disabling VLAN filtering. */ - DEBUGOUT("Initializing the IEEE VLAN\n"); - E1000_WRITE_REG(hw, VET, 0); - - e1000_clear_vfta(hw); - - /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */ - if(hw->mac_type == e1000_82542_rev2_0) { - DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); - e1000_pci_clear_mwi(hw); - E1000_WRITE_REG(hw, RCTL, E1000_RCTL_RST); - E1000_WRITE_FLUSH(hw); - msec_delay(5); - } - - /* Setup the receive address. This involves initializing all of the Receive - * Address Registers (RARs 0 - 15). - */ - e1000_init_rx_addrs(hw); - - /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */ - if(hw->mac_type == e1000_82542_rev2_0) { - E1000_WRITE_REG(hw, RCTL, 0); - E1000_WRITE_FLUSH(hw); - msec_delay(1); - if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) - e1000_pci_set_mwi(hw); - } - - /* Zero out the Multicast HASH table */ - DEBUGOUT("Zeroing the MTA\n"); - for(i = 0; i < E1000_MC_TBL_SIZE; i++) - E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); - - /* Set the PCI priority bit correctly in the CTRL register. This - * determines if the adapter gives priority to receives, or if it - * gives equal priority to transmits and receives. - */ - if(hw->dma_fairness) { - ctrl = E1000_READ_REG(hw, CTRL); - E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR); - } - - switch(hw->mac_type) { - case e1000_82545_rev_3: - case e1000_82546_rev_3: - break; - default: - /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */ - if(hw->bus_type == e1000_bus_type_pcix) { - e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word); - e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, - &pcix_stat_hi_word); - cmd_mmrbc = (pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >> - PCIX_COMMAND_MMRBC_SHIFT; - stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >> - PCIX_STATUS_HI_MMRBC_SHIFT; - if(stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K) - stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K; - if(cmd_mmrbc > stat_mmrbc) { - pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK; - pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT; - e1000_write_pci_cfg(hw, PCIX_COMMAND_REGISTER, - &pcix_cmd_word); - } - } - break; - } - - /* Call a subroutine to configure the link and setup flow control. */ - ret_val = e1000_setup_link(hw); - - /* Set the transmit descriptor write-back policy */ - if(hw->mac_type > e1000_82544) { - ctrl = E1000_READ_REG(hw, TXDCTL); - ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB; - E1000_WRITE_REG(hw, TXDCTL, ctrl); - } - - /* Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - e1000_clear_hw_cntrs(hw); - - return ret_val; -} - -/****************************************************************************** - * Adjust SERDES output amplitude based on EEPROM setting. - * - * hw - Struct containing variables accessed by shared code. - *****************************************************************************/ -static int32_t -e1000_adjust_serdes_amplitude(struct e1000_hw *hw) -{ - uint16_t eeprom_data; - int32_t ret_val; - - DEBUGFUNC("e1000_adjust_serdes_amplitude"); - - if(hw->media_type != e1000_media_type_internal_serdes) - return E1000_SUCCESS; - - switch(hw->mac_type) { - case e1000_82545_rev_3: - case e1000_82546_rev_3: - break; - default: - return E1000_SUCCESS; - } - - if ((ret_val = e1000_read_eeprom(hw, EEPROM_SERDES_AMPLITUDE, 1, - &eeprom_data))) { - return ret_val; - } - - if(eeprom_data != EEPROM_RESERVED_WORD) { - /* Adjust SERDES output amplitude only. */ - eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK; - if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, - eeprom_data))) - return ret_val; - } - - return E1000_SUCCESS; -} - -/****************************************************************************** - * Configures flow control and link settings. - * - * hw - Struct containing variables accessed by shared code - * - * Determines which flow control settings to use. Calls the apropriate media- - * specific link configuration function. Configures the flow control settings. - * Assuming the adapter has a valid link partner, a valid link should be - * established. Assumes the hardware has previously been reset and the - * transmitter and receiver are not enabled. - *****************************************************************************/ -int32_t -e1000_setup_link(struct e1000_hw *hw) -{ - uint32_t ctrl_ext; - int32_t ret_val; - uint16_t eeprom_data; - - DEBUGFUNC("e1000_setup_link"); - - /* Read and store word 0x0F of the EEPROM. This word contains bits - * that determine the hardware's default PAUSE (flow control) mode, - * a bit that determines whether the HW defaults to enabling or - * disabling auto-negotiation, and the direction of the - * SW defined pins. If there is no SW over-ride of the flow - * control setting, then the variable hw->fc will - * be initialized based on a value in the EEPROM. - */ - if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data) < 0) { - DEBUGOUT("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - - if(hw->fc == e1000_fc_default) { - if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0) - hw->fc = e1000_fc_none; - else if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == - EEPROM_WORD0F_ASM_DIR) - hw->fc = e1000_fc_tx_pause; - else - hw->fc = e1000_fc_full; - } - - /* We want to save off the original Flow Control configuration just - * in case we get disconnected and then reconnected into a different - * hub or switch with different Flow Control capabilities. - */ - if(hw->mac_type == e1000_82542_rev2_0) - hw->fc &= (~e1000_fc_tx_pause); - - if((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1)) - hw->fc &= (~e1000_fc_rx_pause); - - hw->original_fc = hw->fc; - - DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc); - - /* Take the 4 bits from EEPROM word 0x0F that determine the initial - * polarity value for the SW controlled pins, and setup the - * Extended Device Control reg with that info. - * This is needed because one of the SW controlled pins is used for - * signal detection. So this should be done before e1000_setup_pcs_link() - * or e1000_phy_setup() is called. - */ - if(hw->mac_type == e1000_82543) { - ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) << - SWDPIO__EXT_SHIFT); - E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); - } - - /* Call the necessary subroutine to configure the link. */ - ret_val = (hw->media_type == e1000_media_type_copper) ? - e1000_setup_copper_link(hw) : - e1000_setup_fiber_serdes_link(hw); - - /* Initialize the flow control address, type, and PAUSE timer - * registers to their default values. This is done even if flow - * control is disabled, because it does not hurt anything to - * initialize these registers. - */ - DEBUGOUT("Initializing the Flow Control address, type and timer regs\n"); - - E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW); - E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH); - E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE); - E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time); - - /* Set the flow control receive threshold registers. Normally, - * these registers will be set to a default threshold that may be - * adjusted later by the driver's runtime code. However, if the - * ability to transmit pause frames in not enabled, then these - * registers will be set to 0. - */ - if(!(hw->fc & e1000_fc_tx_pause)) { - E1000_WRITE_REG(hw, FCRTL, 0); - E1000_WRITE_REG(hw, FCRTH, 0); - } else { - /* We need to set up the Receive Threshold high and low water marks - * as well as (optionally) enabling the transmission of XON frames. - */ - if(hw->fc_send_xon) { - E1000_WRITE_REG(hw, FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE)); - E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water); - } else { - E1000_WRITE_REG(hw, FCRTL, hw->fc_low_water); - E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water); - } - } - return ret_val; -} - -/****************************************************************************** - * Sets up link for a fiber based or serdes based adapter - * - * hw - Struct containing variables accessed by shared code - * - * Manipulates Physical Coding Sublayer functions in order to configure - * link. Assumes the hardware has been previously reset and the transmitter - * and receiver are not enabled. - *****************************************************************************/ -static int32_t -e1000_setup_fiber_serdes_link(struct e1000_hw *hw) -{ - uint32_t ctrl; - uint32_t status; - uint32_t txcw = 0; - uint32_t i; - uint32_t signal = 0; - int32_t ret_val; - - DEBUGFUNC("e1000_setup_fiber_serdes_link"); - - /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be - * set when the optics detect a signal. On older adapters, it will be - * cleared when there is a signal. This applies to fiber media only. - * If we're on serdes media, adjust the output amplitude to value set in - * the EEPROM. - */ - ctrl = E1000_READ_REG(hw, CTRL); - if(hw->media_type == e1000_media_type_fiber) - signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0; - - if((ret_val = e1000_adjust_serdes_amplitude(hw))) - return ret_val; - - /* Take the link out of reset */ - ctrl &= ~(E1000_CTRL_LRST); - - /* Adjust VCO speed to improve BER performance */ - if((ret_val = e1000_set_vco_speed(hw))) - return ret_val; - - e1000_config_collision_dist(hw); - - /* Check for a software override of the flow control settings, and setup - * the device accordingly. If auto-negotiation is enabled, then software - * will have to set the "PAUSE" bits to the correct value in the Tranmsit - * Config Word Register (TXCW) and re-start auto-negotiation. However, if - * auto-negotiation is disabled, then software will have to manually - * configure the two flow control enable bits in the CTRL register. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames, but - * not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames but we do - * not support receiving pause frames). - * 3: Both Rx and TX flow control (symmetric) are enabled. - */ - switch (hw->fc) { - case e1000_fc_none: - /* Flow control is completely disabled by a software over-ride. */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); - break; - case e1000_fc_rx_pause: - /* RX Flow control is enabled and TX Flow control is disabled by a - * software over-ride. Since there really isn't a way to advertise - * that we are capable of RX Pause ONLY, we will advertise that we - * support both symmetric and asymmetric RX PAUSE. Later, we will - * disable the adapter's ability to send PAUSE frames. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - case e1000_fc_tx_pause: - /* TX Flow control is enabled, and RX Flow control is disabled, by a - * software over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); - break; - case e1000_fc_full: - /* Flow control (both RX and TX) is enabled by a software over-ride. */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - default: - DEBUGOUT("Flow control param set incorrectly\n"); - return -E1000_ERR_CONFIG; - break; - } - - /* Since auto-negotiation is enabled, take the link out of reset (the link - * will be in reset, because we previously reset the chip). This will - * restart auto-negotiation. If auto-neogtiation is successful then the - * link-up status bit will be set and the flow control enable bits (RFCE - * and TFCE) will be set according to their negotiated value. - */ - DEBUGOUT("Auto-negotiation enabled\n"); - - E1000_WRITE_REG(hw, TXCW, txcw); - E1000_WRITE_REG(hw, CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - - hw->txcw = txcw; - msec_delay(1); - - /* If we have a signal (the cable is plugged in) then poll for a "Link-Up" - * indication in the Device Status Register. Time-out if a link isn't - * seen in 500 milliseconds seconds (Auto-negotiation should complete in - * less than 500 milliseconds even if the other end is doing it in SW). - * For internal serdes, we just assume a signal is present, then poll. - */ - if(hw->media_type == e1000_media_type_internal_serdes || - (E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) { - DEBUGOUT("Looking for Link\n"); - for(i = 0; i < (LINK_UP_TIMEOUT / 10); i++) { - msec_delay(10); - status = E1000_READ_REG(hw, STATUS); - if(status & E1000_STATUS_LU) break; - } - if(i == (LINK_UP_TIMEOUT / 10)) { - DEBUGOUT("Never got a valid link from auto-neg!!!\n"); - hw->autoneg_failed = 1; - if(hw->media_type == e1000_media_type_fiber) { - /* AutoNeg failed to achieve a link, so we'll call - * e1000_check_for_link. This routine will force the link up if - * we detect a signal. This will allow us to communicate with - * non-autonegotiating link partners. - */ - if((ret_val = e1000_check_for_link(hw))) { - DEBUGOUT("Error while checking for link\n"); - return ret_val; - } - hw->autoneg_failed = 0; - } - } else { - hw->autoneg_failed = 0; - DEBUGOUT("Valid Link Found\n"); - } - } else { - DEBUGOUT("No Signal Detected\n"); - } - return E1000_SUCCESS; -} - -/****************************************************************************** -* Detects which PHY is present and the speed and duplex -* -* hw - Struct containing variables accessed by shared code -******************************************************************************/ -static int32_t -e1000_setup_copper_link(struct e1000_hw *hw) -{ - uint32_t ctrl; - uint32_t led_ctrl; - int32_t ret_val; - uint16_t i; - uint16_t phy_data; - - DEBUGFUNC("e1000_setup_copper_link"); - - ctrl = E1000_READ_REG(hw, CTRL); - /* With 82543, we need to force speed and duplex on the MAC equal to what - * the PHY speed and duplex configuration is. In addition, we need to - * perform a hardware reset on the PHY to take it out of reset. - */ - if(hw->mac_type > e1000_82543) { - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - E1000_WRITE_REG(hw, CTRL, ctrl); - } else { - ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU); - E1000_WRITE_REG(hw, CTRL, ctrl); - e1000_phy_hw_reset(hw); - } - - /* Make sure we have a valid PHY */ - if((ret_val = e1000_detect_gig_phy(hw))) { - DEBUGOUT("Error, did not detect valid phy.\n"); - return ret_val; - } - DEBUGOUT1("Phy ID = %x \n", hw->phy_id); - - if(hw->mac_type <= e1000_82543 || - hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 || - hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) - hw->phy_reset_disable = FALSE; - - if(!hw->phy_reset_disable) { - if (hw->phy_type == e1000_phy_igp) { - - if((ret_val = e1000_phy_reset(hw))) { - DEBUGOUT("Error Resetting the PHY\n"); - return ret_val; - } - - /* Wait 10ms for MAC to configure PHY from eeprom settings */ - msec_delay(15); - - /* Configure activity LED after PHY reset */ - led_ctrl = E1000_READ_REG(hw, LEDCTL); - led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - E1000_WRITE_REG(hw, LEDCTL, led_ctrl); - - /* disable lplu d3 during driver init */ - if((ret_val = e1000_set_d3_lplu_state(hw, FALSE))) { - DEBUGOUT("Error Disabling LPLU D3\n"); - return ret_val; - } - - /* Configure mdi-mdix settings */ - if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, - &phy_data))) - return ret_val; - - if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { - hw->dsp_config_state = e1000_dsp_config_disabled; - /* Force MDI for IGP B-0 PHY */ - phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | - IGP01E1000_PSCR_FORCE_MDI_MDIX); - hw->mdix = 1; - - } else { - hw->dsp_config_state = e1000_dsp_config_enabled; - phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; - - switch (hw->mdix) { - case 1: - phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 2: - phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 0: - default: - phy_data |= IGP01E1000_PSCR_AUTO_MDIX; - break; - } - } - if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, - phy_data))) - return ret_val; - - /* set auto-master slave resolution settings */ - if(hw->autoneg) { - e1000_ms_type phy_ms_setting = hw->master_slave; - - if(hw->ffe_config_state == e1000_ffe_config_active) - hw->ffe_config_state = e1000_ffe_config_enabled; - - if(hw->dsp_config_state == e1000_dsp_config_activated) - hw->dsp_config_state = e1000_dsp_config_enabled; - - /* when autonegotiation advertisment is only 1000Mbps then we - * should disable SmartSpeed and enable Auto MasterSlave - * resolution as hardware default. */ - if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { - /* Disable SmartSpeed */ - if((ret_val = e1000_read_phy_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - &phy_data))) - return ret_val; - phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; - if((ret_val = e1000_write_phy_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - phy_data))) - return ret_val; - /* Set auto Master/Slave resolution process */ - if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, - &phy_data))) - return ret_val; - phy_data &= ~CR_1000T_MS_ENABLE; - if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, - phy_data))) - return ret_val; - } - - if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, - &phy_data))) - return ret_val; - - /* load defaults for future use */ - hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ? - ((phy_data & CR_1000T_MS_VALUE) ? - e1000_ms_force_master : - e1000_ms_force_slave) : - e1000_ms_auto; - - switch (phy_ms_setting) { - case e1000_ms_force_master: - phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); - break; - case e1000_ms_force_slave: - phy_data |= CR_1000T_MS_ENABLE; - phy_data &= ~(CR_1000T_MS_VALUE); - break; - case e1000_ms_auto: - phy_data &= ~CR_1000T_MS_ENABLE; - default: - break; - } - if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, - phy_data))) - return ret_val; - } - } else { - /* Enable CRS on TX. This must be set for half-duplex operation. */ - if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - &phy_data))) - return ret_val; - - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - - /* Options: - * MDI/MDI-X = 0 (default) - * 0 - Auto for all speeds - * 1 - MDI mode - * 2 - MDI-X mode - * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - - switch (hw->mdix) { - case 1: - phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; - break; - case 2: - phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; - break; - case 3: - phy_data |= M88E1000_PSCR_AUTO_X_1000T; - break; - case 0: - default: - phy_data |= M88E1000_PSCR_AUTO_X_MODE; - break; - } - - /* Options: - * disable_polarity_correction = 0 (default) - * Automatic Correction for Reversed Cable Polarity - * 0 - Disabled - * 1 - Enabled - */ - phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; - if(hw->disable_polarity_correction == 1) - phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - phy_data))) - return ret_val; - - /* Force TX_CLK in the Extended PHY Specific Control Register - * to 25MHz clock. - */ - if((ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - &phy_data))) - return ret_val; - - phy_data |= M88E1000_EPSCR_TX_CLK_25; - - if (hw->phy_revision < M88E1011_I_REV_4) { - /* Configure Master and Slave downshift values */ - phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); - phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); - if((ret_val = e1000_write_phy_reg(hw, - M88E1000_EXT_PHY_SPEC_CTRL, - phy_data))) - return ret_val; - } - - /* SW Reset the PHY so all changes take effect */ - if((ret_val = e1000_phy_reset(hw))) { - DEBUGOUT("Error Resetting the PHY\n"); - return ret_val; - } - } - - /* Options: - * autoneg = 1 (default) - * PHY will advertise value(s) parsed from - * autoneg_advertised and fc - * autoneg = 0 - * PHY will be set to 10H, 10F, 100H, or 100F - * depending on value parsed from forced_speed_duplex. - */ - - /* Is autoneg enabled? This is enabled by default or by software - * override. If so, call e1000_phy_setup_autoneg routine to parse the - * autoneg_advertised and fc options. If autoneg is NOT enabled, then - * the user should have provided a speed/duplex override. If so, then - * call e1000_phy_force_speed_duplex to parse and set this up. - */ - if(hw->autoneg) { - /* Perform some bounds checking on the hw->autoneg_advertised - * parameter. If this variable is zero, then set it to the default. - */ - hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT; - - /* If autoneg_advertised is zero, we assume it was not defaulted - * by the calling code so we set to advertise full capability. - */ - if(hw->autoneg_advertised == 0) - hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT; - - DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); - if((ret_val = e1000_phy_setup_autoneg(hw))) { - DEBUGOUT("Error Setting up Auto-Negotiation\n"); - return ret_val; - } - DEBUGOUT("Restarting Auto-Neg\n"); - - /* Restart auto-negotiation by setting the Auto Neg Enable bit and - * the Auto Neg Restart bit in the PHY control register. - */ - if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data))) - return ret_val; - - phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); - if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data))) - return ret_val; - - /* Does the user want to wait for Auto-Neg to complete here, or - * check at a later time (for example, callback routine). - */ - if(hw->wait_autoneg_complete) { - if((ret_val = e1000_wait_autoneg(hw))) { - DEBUGOUT("Error while waiting for autoneg to complete\n"); - return ret_val; - } - } - hw->get_link_status = TRUE; - } else { - DEBUGOUT("Forcing speed and duplex\n"); - if((ret_val = e1000_phy_force_speed_duplex(hw))) { - DEBUGOUT("Error Forcing Speed and Duplex\n"); - return ret_val; - } - } - } /* !hw->phy_reset_disable */ - - /* Check link status. Wait up to 100 microseconds for link to become - * valid. - */ - for(i = 0; i < 10; i++) { - if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) - return ret_val; - if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) - return ret_val; - - if(phy_data & MII_SR_LINK_STATUS) { - /* We have link, so we need to finish the config process: - * 1) Set up the MAC to the current PHY speed/duplex - * if we are on 82543. If we - * are on newer silicon, we only need to configure - * collision distance in the Transmit Control Register. - * 2) Set up flow control on the MAC to that established with - * the link partner. - */ - if(hw->mac_type >= e1000_82544) { - e1000_config_collision_dist(hw); - } else { - if((ret_val = e1000_config_mac_to_phy(hw))) { - DEBUGOUT("Error configuring MAC to PHY settings\n"); - return ret_val; - } - } - if((ret_val = e1000_config_fc_after_link_up(hw))) { - DEBUGOUT("Error Configuring Flow Control\n"); - return ret_val; - } - DEBUGOUT("Valid link established!!!\n"); - - if(hw->phy_type == e1000_phy_igp) { - if((ret_val = e1000_config_dsp_after_link_change(hw, TRUE))) { - DEBUGOUT("Error Configuring DSP after link up\n"); - return ret_val; - } - } - DEBUGOUT("Valid link established!!!\n"); - return E1000_SUCCESS; - } - usec_delay(10); - } - - DEBUGOUT("Unable to establish link!!!\n"); - return E1000_SUCCESS; -} - -/****************************************************************************** -* Configures PHY autoneg and flow control advertisement settings -* -* hw - Struct containing variables accessed by shared code -******************************************************************************/ -int32_t -e1000_phy_setup_autoneg(struct e1000_hw *hw) -{ - int32_t ret_val; - uint16_t mii_autoneg_adv_reg; - uint16_t mii_1000t_ctrl_reg; - - DEBUGFUNC("e1000_phy_setup_autoneg"); - - /* Read the MII Auto-Neg Advertisement Register (Address 4). */ - if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, - &mii_autoneg_adv_reg))) - return ret_val; - - /* Read the MII 1000Base-T Control Register (Address 9). */ - if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg))) - return ret_val; - - /* Need to parse both autoneg_advertised and fc and set up - * the appropriate PHY registers. First we will parse for - * autoneg_advertised software override. Since we can advertise - * a plethora of combinations, we need to check each bit - * individually. - */ - - /* First we clear all the 10/100 mb speed bits in the Auto-Neg - * Advertisement Register (Address 4) and the 1000 mb speed bits in - * the 1000Base-T Control Register (Address 9). - */ - mii_autoneg_adv_reg &= ~REG4_SPEED_MASK; - mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK; - - DEBUGOUT1("autoneg_advertised %x\n", hw->autoneg_advertised); - - /* Do we want to advertise 10 Mb Half Duplex? */ - if(hw->autoneg_advertised & ADVERTISE_10_HALF) { - DEBUGOUT("Advertise 10mb Half duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; - } - - /* Do we want to advertise 10 Mb Full Duplex? */ - if(hw->autoneg_advertised & ADVERTISE_10_FULL) { - DEBUGOUT("Advertise 10mb Full duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; - } - - /* Do we want to advertise 100 Mb Half Duplex? */ - if(hw->autoneg_advertised & ADVERTISE_100_HALF) { - DEBUGOUT("Advertise 100mb Half duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; - } - - /* Do we want to advertise 100 Mb Full Duplex? */ - if(hw->autoneg_advertised & ADVERTISE_100_FULL) { - DEBUGOUT("Advertise 100mb Full duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; - } - - /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ - if(hw->autoneg_advertised & ADVERTISE_1000_HALF) { - DEBUGOUT("Advertise 1000mb Half duplex requested, request denied!\n"); - } - - /* Do we want to advertise 1000 Mb Full Duplex? */ - if(hw->autoneg_advertised & ADVERTISE_1000_FULL) { - DEBUGOUT("Advertise 1000mb Full duplex\n"); - mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; - } - - /* Check for a software override of the flow control settings, and - * setup the PHY advertisement registers accordingly. If - * auto-negotiation is enabled, then software will have to set the - * "PAUSE" bits to the correct value in the Auto-Negotiation - * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-negotiation. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames - * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * but we do not support receiving pause frames). - * 3: Both Rx and TX flow control (symmetric) are enabled. - * other: No software override. The flow control configuration - * in the EEPROM is used. - */ - switch (hw->fc) { - case e1000_fc_none: /* 0 */ - /* Flow control (RX & TX) is completely disabled by a - * software over-ride. - */ - mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - case e1000_fc_rx_pause: /* 1 */ - /* RX Flow control is enabled, and TX Flow control is - * disabled, by a software over-ride. - */ - /* Since there really isn't a way to advertise that we are - * capable of RX Pause ONLY, we will advertise that we - * support both symmetric and asymmetric RX PAUSE. Later - * (in e1000_config_fc_after_link_up) we will disable the - *hw's ability to send PAUSE frames. - */ - mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - case e1000_fc_tx_pause: /* 2 */ - /* TX Flow control is enabled, and RX Flow control is - * disabled, by a software over-ride. - */ - mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; - mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; - break; - case e1000_fc_full: /* 3 */ - /* Flow control (both RX and TX) is enabled by a software - * over-ride. - */ - mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - default: - DEBUGOUT("Flow control param set incorrectly\n"); - return -E1000_ERR_CONFIG; - } - - if((ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, - mii_autoneg_adv_reg))) - return ret_val; - - DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); - - if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg))) - return ret_val; - - return E1000_SUCCESS; -} - -/****************************************************************************** -* Force PHY speed and duplex settings to hw->forced_speed_duplex -* -* hw - Struct containing variables accessed by shared code -******************************************************************************/ -static int32_t -e1000_phy_force_speed_duplex(struct e1000_hw *hw) -{ - uint32_t ctrl; - int32_t ret_val; - uint16_t mii_ctrl_reg; - uint16_t mii_status_reg; - uint16_t phy_data; - uint16_t i; - - DEBUGFUNC("e1000_phy_force_speed_duplex"); - - /* Turn off Flow control if we are forcing speed and duplex. */ - hw->fc = e1000_fc_none; - - DEBUGOUT1("hw->fc = %d\n", hw->fc); - - /* Read the Device Control Register. */ - ctrl = E1000_READ_REG(hw, CTRL); - - /* Set the bits to Force Speed and Duplex in the Device Ctrl Reg. */ - ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ctrl &= ~(DEVICE_SPEED_MASK); - - /* Clear the Auto Speed Detect Enable bit. */ - ctrl &= ~E1000_CTRL_ASDE; - - /* Read the MII Control Register. */ - if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg))) - return ret_val; - - /* We need to disable autoneg in order to force link and duplex. */ - - mii_ctrl_reg &= ~MII_CR_AUTO_NEG_EN; - - /* Are we forcing Full or Half Duplex? */ - if(hw->forced_speed_duplex == e1000_100_full || - hw->forced_speed_duplex == e1000_10_full) { - /* We want to force full duplex so we SET the full duplex bits in the - * Device and MII Control Registers. - */ - ctrl |= E1000_CTRL_FD; - mii_ctrl_reg |= MII_CR_FULL_DUPLEX; - DEBUGOUT("Full Duplex\n"); - } else { - /* We want to force half duplex so we CLEAR the full duplex bits in - * the Device and MII Control Registers. - */ - ctrl &= ~E1000_CTRL_FD; - mii_ctrl_reg &= ~MII_CR_FULL_DUPLEX; - DEBUGOUT("Half Duplex\n"); - } - - /* Are we forcing 100Mbps??? */ - if(hw->forced_speed_duplex == e1000_100_full || - hw->forced_speed_duplex == e1000_100_half) { - /* Set the 100Mb bit and turn off the 1000Mb and 10Mb bits. */ - ctrl |= E1000_CTRL_SPD_100; - mii_ctrl_reg |= MII_CR_SPEED_100; - mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10); - DEBUGOUT("Forcing 100mb "); - } else { - /* Set the 10Mb bit and turn off the 1000Mb and 100Mb bits. */ - ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); - mii_ctrl_reg |= MII_CR_SPEED_10; - mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100); - DEBUGOUT("Forcing 10mb "); - } - - e1000_config_collision_dist(hw); - - /* Write the configured values back to the Device Control Reg. */ - E1000_WRITE_REG(hw, CTRL, ctrl); - - if (hw->phy_type == e1000_phy_m88) { - if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - &phy_data))) - return ret_val; - - /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI - * forced whenever speed are duplex are forced. - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - phy_data))) - return ret_val; - - DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data); - - /* Need to reset the PHY or these changes will be ignored */ - mii_ctrl_reg |= MII_CR_RESET; - } else { - /* Clear Auto-Crossover to force MDI manually. IGP requires MDI - * forced whenever speed or duplex are forced. - */ - if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, - &phy_data))) - return ret_val; - - phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; - phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - - if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, - phy_data))) - return ret_val; - } - - /* Write back the modified PHY MII control register. */ - if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg))) - return ret_val; - - usec_delay(1); - - /* The wait_autoneg_complete flag may be a little misleading here. - * Since we are forcing speed and duplex, Auto-Neg is not enabled. - * But we do want to delay for a period while forcing only so we - * don't generate false No Link messages. So we will wait here - * only if the user has set wait_autoneg_complete to 1, which is - * the default. - */ - if(hw->wait_autoneg_complete) { - /* We will wait for autoneg to complete. */ - DEBUGOUT("Waiting for forced speed/duplex link.\n"); - mii_status_reg = 0; - - /* We will wait for autoneg to complete or 4.5 seconds to expire. */ - for(i = PHY_FORCE_TIME; i > 0; i--) { - /* Read the MII Status Register and wait for Auto-Neg Complete bit - * to be set. - */ - if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) - return ret_val; - - if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) - return ret_val; - - if(mii_status_reg & MII_SR_LINK_STATUS) break; - msec_delay(100); - } - if(i == 0) { /* We didn't get link */ - /* Reset the DSP and wait again for link. */ - if((ret_val = e1000_phy_reset_dsp(hw))) { - DEBUGOUT("Error Resetting PHY DSP\n"); - return ret_val; - } - } - /* This loop will early-out if the link condition has been met. */ - for(i = PHY_FORCE_TIME; i > 0; i--) { - if(mii_status_reg & MII_SR_LINK_STATUS) break; - msec_delay(100); - /* Read the MII Status Register and wait for Auto-Neg Complete bit - * to be set. - */ - if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) - return ret_val; - - if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) - return ret_val; - } - } - - if (hw->phy_type == e1000_phy_m88) { - /* Because we reset the PHY above, we need to re-force TX_CLK in the - * Extended PHY Specific Control Register to 25MHz clock. This value - * defaults back to a 2.5MHz clock when the PHY is reset. - */ - if((ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - &phy_data))) - return ret_val; - - phy_data |= M88E1000_EPSCR_TX_CLK_25; - if((ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - phy_data))) - return ret_val; - - /* In addition, because of the s/w reset above, we need to enable CRS on - * TX. This must be set for both full and half duplex operation. - */ - if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - &phy_data))) - return ret_val; - - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - phy_data))) - return ret_val; - - } - return E1000_SUCCESS; -} - -/****************************************************************************** -* Sets the collision distance in the Transmit Control register -* -* hw - Struct containing variables accessed by shared code -* -* Link should have been established previously. Reads the speed and duplex -* information from the Device Status register. -******************************************************************************/ -void -e1000_config_collision_dist(struct e1000_hw *hw) -{ - uint32_t tctl; - - DEBUGFUNC("e1000_config_collision_dist"); - - tctl = E1000_READ_REG(hw, TCTL); - - tctl &= ~E1000_TCTL_COLD; - tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; - - E1000_WRITE_REG(hw, TCTL, tctl); - E1000_WRITE_FLUSH(hw); -} - -/****************************************************************************** -* Sets MAC speed and duplex settings to reflect the those in the PHY -* -* hw - Struct containing variables accessed by shared code -* mii_reg - data to write to the MII control register -* -* The contents of the PHY register containing the needed information need to -* be passed in. -******************************************************************************/ -static int32_t -e1000_config_mac_to_phy(struct e1000_hw *hw) -{ - uint32_t ctrl; - int32_t ret_val; - uint16_t phy_data; - - DEBUGFUNC("e1000_config_mac_to_phy"); - - /* Read the Device Control Register and set the bits to Force Speed - * and Duplex. - */ - ctrl = E1000_READ_REG(hw, CTRL); - ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS); - - /* Set up duplex in the Device Control and Transmit Control - * registers depending on negotiated values. - */ - if (hw->phy_type == e1000_phy_igp) { - if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, - &phy_data))) - return ret_val; - - if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) ctrl |= E1000_CTRL_FD; - else ctrl &= ~E1000_CTRL_FD; - - e1000_config_collision_dist(hw); - - /* Set up speed in the Device Control register depending on - * negotiated values. - */ - if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) - ctrl |= E1000_CTRL_SPD_1000; - else if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_100MBPS) - ctrl |= E1000_CTRL_SPD_100; - } else { - if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, - &phy_data))) - return ret_val; - - if(phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD; - else ctrl &= ~E1000_CTRL_FD; - - e1000_config_collision_dist(hw); - - /* Set up speed in the Device Control register depending on - * negotiated values. - */ - if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) - ctrl |= E1000_CTRL_SPD_1000; - else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) - ctrl |= E1000_CTRL_SPD_100; - } - /* Write the configured values back to the Device Control Reg. */ - E1000_WRITE_REG(hw, CTRL, ctrl); - return E1000_SUCCESS; -} - -/****************************************************************************** - * Forces the MAC's flow control settings. - * - * hw - Struct containing variables accessed by shared code - * - * Sets the TFCE and RFCE bits in the device control register to reflect - * the adapter settings. TFCE and RFCE need to be explicitly set by - * software when a Copper PHY is used because autonegotiation is managed - * by the PHY rather than the MAC. Software must also configure these - * bits when link is forced on a fiber connection. - *****************************************************************************/ -int32_t -e1000_force_mac_fc(struct e1000_hw *hw) -{ - uint32_t ctrl; - - DEBUGFUNC("e1000_force_mac_fc"); - - /* Get the current configuration of the Device Control Register */ - ctrl = E1000_READ_REG(hw, CTRL); - - /* Because we didn't get link via the internal auto-negotiation - * mechanism (we either forced link or we got link via PHY - * auto-neg), we have to manually enable/disable transmit an - * receive flow control. - * - * The "Case" statement below enables/disable flow control - * according to the "hw->fc" parameter. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause - * frames but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * frames but we do not receive pause frames). - * 3: Both Rx and TX flow control (symmetric) is enabled. - * other: No other values should be possible at this point. - */ - - switch (hw->fc) { - case e1000_fc_none: - ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); - break; - case e1000_fc_rx_pause: - ctrl &= (~E1000_CTRL_TFCE); - ctrl |= E1000_CTRL_RFCE; - break; - case e1000_fc_tx_pause: - ctrl &= (~E1000_CTRL_RFCE); - ctrl |= E1000_CTRL_TFCE; - break; - case e1000_fc_full: - ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); - break; - default: - DEBUGOUT("Flow control param set incorrectly\n"); - return -E1000_ERR_CONFIG; - } - - /* Disable TX Flow Control for 82542 (rev 2.0) */ - if(hw->mac_type == e1000_82542_rev2_0) - ctrl &= (~E1000_CTRL_TFCE); - - E1000_WRITE_REG(hw, CTRL, ctrl); - return E1000_SUCCESS; -} - -/****************************************************************************** - * Configures flow control settings after link is established - * - * hw - Struct containing variables accessed by shared code - * - * Should be called immediately after a valid link has been established. - * Forces MAC flow control settings if link was forced. When in MII/GMII mode - * and autonegotiation is enabled, the MAC flow control settings will be set - * based on the flow control negotiated by the PHY. In TBI mode, the TFCE - * and RFCE bits will be automaticaly set to the negotiated flow control mode. - *****************************************************************************/ -int32_t -e1000_config_fc_after_link_up(struct e1000_hw *hw) -{ - int32_t ret_val; - uint16_t mii_status_reg; - uint16_t mii_nway_adv_reg; - uint16_t mii_nway_lp_ability_reg; - uint16_t speed; - uint16_t duplex; - - DEBUGFUNC("e1000_config_fc_after_link_up"); - - /* Check for the case where we have fiber media and auto-neg failed - * so we had to force link. In this case, we need to force the - * configuration of the MAC to match the "fc" parameter. - */ - if(((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed)) || - ((hw->media_type == e1000_media_type_internal_serdes) && (hw->autoneg_failed)) || - ((hw->media_type == e1000_media_type_copper) && (!hw->autoneg))) { - if((ret_val = e1000_force_mac_fc(hw))) { - DEBUGOUT("Error forcing flow control settings\n"); - return ret_val; - } - } - - /* Check for the case where we have copper media and auto-neg is - * enabled. In this case, we need to check and see if Auto-Neg - * has completed, and if so, how the PHY and link partner has - * flow control configured. - */ - if((hw->media_type == e1000_media_type_copper) && hw->autoneg) { - /* Read the MII Status Register and check to see if AutoNeg - * has completed. We read this twice because this reg has - * some "sticky" (latched) bits. - */ - if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) - return ret_val; - if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) - return ret_val; - - if(mii_status_reg & MII_SR_AUTONEG_COMPLETE) { - /* The AutoNeg process has completed, so we now need to - * read both the Auto Negotiation Advertisement Register - * (Address 4) and the Auto_Negotiation Base Page Ability - * Register (Address 5) to determine how flow control was - * negotiated. - */ - if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, - &mii_nway_adv_reg))) - return ret_val; - if((ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY, - &mii_nway_lp_ability_reg))) - return ret_val; - - /* Two bits in the Auto Negotiation Advertisement Register - * (Address 4) and two bits in the Auto Negotiation Base - * Page Ability Register (Address 5) determine flow control - * for both the PHY and the link partner. The following - * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, - * 1999, describes these PAUSE resolution bits and how flow - * control is determined based upon these settings. - * NOTE: DC = Don't Care - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution - *-------|---------|-------|---------|-------------------- - * 0 | 0 | DC | DC | e1000_fc_none - * 0 | 1 | 0 | DC | e1000_fc_none - * 0 | 1 | 1 | 0 | e1000_fc_none - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - * 1 | 0 | 0 | DC | e1000_fc_none - * 1 | DC | 1 | DC | e1000_fc_full - * 1 | 1 | 0 | 0 | e1000_fc_none - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - * - */ - /* Are both PAUSE bits set to 1? If so, this implies - * Symmetric Flow Control is enabled at both ends. The - * ASM_DIR bits are irrelevant per the spec. - * - * For Symmetric Flow Control: - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | DC | 1 | DC | e1000_fc_full - * - */ - if((mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { - /* Now we need to check if the user selected RX ONLY - * of pause frames. In this case, we had to advertise - * FULL flow control because we could not advertise RX - * ONLY. Hence, we must now check to see if we need to - * turn OFF the TRANSMISSION of PAUSE frames. - */ - if(hw->original_fc == e1000_fc_full) { - hw->fc = e1000_fc_full; - DEBUGOUT("Flow Control = FULL.\r\n"); - } else { - hw->fc = e1000_fc_rx_pause; - DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); - } - } - /* For receiving PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - * - */ - else if(!(mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && - (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { - hw->fc = e1000_fc_tx_pause; - DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n"); - } - /* For transmitting PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - * - */ - else if((mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && - !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { - hw->fc = e1000_fc_rx_pause; - DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); - } - /* Per the IEEE spec, at this point flow control should be - * disabled. However, we want to consider that we could - * be connected to a legacy switch that doesn't advertise - * desired flow control, but can be forced on the link - * partner. So if we advertised no flow control, that is - * what we will resolve to. If we advertised some kind of - * receive capability (Rx Pause Only or Full Flow Control) - * and the link partner advertised none, we will configure - * ourselves to enable Rx Flow Control only. We can do - * this safely for two reasons: If the link partner really - * didn't want flow control enabled, and we enable Rx, no - * harm done since we won't be receiving any PAUSE frames - * anyway. If the intent on the link partner was to have - * flow control enabled, then by us enabling RX only, we - * can at least receive pause frames and process them. - * This is a good idea because in most cases, since we are - * predominantly a server NIC, more times than not we will - * be asked to delay transmission of packets than asking - * our link partner to pause transmission of frames. - */ - else if(hw->original_fc == e1000_fc_none || - hw->original_fc == e1000_fc_tx_pause) { - hw->fc = e1000_fc_none; - DEBUGOUT("Flow Control = NONE.\r\n"); - } else if(!hw->fc_strict_ieee) { - hw->fc = e1000_fc_rx_pause; - DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); - } - - /* Now we need to do one last check... If we auto- - * negotiated to HALF DUPLEX, flow control should not be - * enabled per IEEE 802.3 spec. - */ - if((ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex))) { - DEBUGOUT("Error getting link speed and duplex\n"); - return ret_val; - } - - if(duplex == HALF_DUPLEX) - hw->fc = e1000_fc_none; - - /* Now we call a subroutine to actually force the MAC - * controller to use the correct flow control settings. - */ - if((ret_val = e1000_force_mac_fc(hw))) { - DEBUGOUT("Error forcing flow control settings\n"); - return ret_val; - } - } else { - DEBUGOUT("Copper PHY and Auto Neg has not completed.\r\n"); - } - } - return E1000_SUCCESS; -} - -/****************************************************************************** - * Checks to see if the link status of the hardware has changed. - * - * hw - Struct containing variables accessed by shared code - * - * Called by any function that needs to check the link status of the adapter. - *****************************************************************************/ -int32_t -e1000_check_for_link(struct e1000_hw *hw) -{ - uint32_t rxcw; - uint32_t ctrl; - uint32_t status; - uint32_t rctl; - uint32_t signal = 0; - int32_t ret_val; - uint16_t phy_data; - uint16_t lp_capability; - - DEBUGFUNC("e1000_check_for_link"); - - /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be - * set when the optics detect a signal. On older adapters, it will be - * cleared when there is a signal. This applies to fiber media only. - */ - if(hw->media_type == e1000_media_type_fiber) - signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0; - - ctrl = E1000_READ_REG(hw, CTRL); - status = E1000_READ_REG(hw, STATUS); - rxcw = E1000_READ_REG(hw, RXCW); - - /* If we have a copper PHY then we only want to go out to the PHY - * registers to see if Auto-Neg has completed and/or if our link - * status has changed. The get_link_status flag will be set if we - * receive a Link Status Change interrupt or we have Rx Sequence - * Errors. - */ - if((hw->media_type == e1000_media_type_copper) && hw->get_link_status) { - /* First we want to see if the MII Status Register reports - * link. If so, then we want to get the current speed/duplex - * of the PHY. - * Read the register twice since the link bit is sticky. - */ - if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) - return ret_val; - if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) - return ret_val; - - if(phy_data & MII_SR_LINK_STATUS) { - hw->get_link_status = FALSE; - /* Check if there was DownShift, must be checked immediately after - * link-up */ - e1000_check_downshift(hw); - - } else { - /* No link detected */ - e1000_config_dsp_after_link_change(hw, FALSE); - return 0; - } - - /* If we are forcing speed/duplex, then we simply return since - * we have already determined whether we have link or not. - */ - if(!hw->autoneg) return -E1000_ERR_CONFIG; - - /* optimize the dsp settings for the igp phy */ - e1000_config_dsp_after_link_change(hw, TRUE); - - /* We have a M88E1000 PHY and Auto-Neg is enabled. If we - * have Si on board that is 82544 or newer, Auto - * Speed Detection takes care of MAC speed/duplex - * configuration. So we only need to configure Collision - * Distance in the MAC. Otherwise, we need to force - * speed/duplex on the MAC to the current PHY speed/duplex - * settings. - */ - if(hw->mac_type >= e1000_82544) - e1000_config_collision_dist(hw); - else { - if((ret_val = e1000_config_mac_to_phy(hw))) { - DEBUGOUT("Error configuring MAC to PHY settings\n"); - return ret_val; - } - } - - /* Configure Flow Control now that Auto-Neg has completed. First, we - * need to restore the desired flow control settings because we may - * have had to re-autoneg with a different link partner. - */ - if((ret_val = e1000_config_fc_after_link_up(hw))) { - DEBUGOUT("Error configuring flow control\n"); - return ret_val; - } - - /* At this point we know that we are on copper and we have - * auto-negotiated link. These are conditions for checking the link - * parter capability register. We use the link partner capability to - * determine if TBI Compatibility needs to be turned on or off. If - * the link partner advertises any speed in addition to Gigabit, then - * we assume that they are GMII-based, and TBI compatibility is not - * needed. If no other speeds are advertised, we assume the link - * partner is TBI-based, and we turn on TBI Compatibility. - */ - if(hw->tbi_compatibility_en) { - if((ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY, - &lp_capability))) - return ret_val; - if(lp_capability & (NWAY_LPAR_10T_HD_CAPS | - NWAY_LPAR_10T_FD_CAPS | - NWAY_LPAR_100TX_HD_CAPS | - NWAY_LPAR_100TX_FD_CAPS | - NWAY_LPAR_100T4_CAPS)) { - /* If our link partner advertises anything in addition to - * gigabit, we do not need to enable TBI compatibility. - */ - if(hw->tbi_compatibility_on) { - /* If we previously were in the mode, turn it off. */ - rctl = E1000_READ_REG(hw, RCTL); - rctl &= ~E1000_RCTL_SBP; - E1000_WRITE_REG(hw, RCTL, rctl); - hw->tbi_compatibility_on = FALSE; - } - } else { - /* If TBI compatibility is was previously off, turn it on. For - * compatibility with a TBI link partner, we will store bad - * packets. Some frames have an additional byte on the end and - * will look like CRC errors to to the hardware. - */ - if(!hw->tbi_compatibility_on) { - hw->tbi_compatibility_on = TRUE; - rctl = E1000_READ_REG(hw, RCTL); - rctl |= E1000_RCTL_SBP; - E1000_WRITE_REG(hw, RCTL, rctl); - } - } - } - } - /* If we don't have link (auto-negotiation failed or link partner cannot - * auto-negotiate), the cable is plugged in (we have signal), and our - * link partner is not trying to auto-negotiate with us (we are receiving - * idles or data), we need to force link up. We also need to give - * auto-negotiation time to complete, in case the cable was just plugged - * in. The autoneg_failed flag does this. - */ - else if((hw->media_type == e1000_media_type_fiber) && - (!(status & E1000_STATUS_LU)) && - ((ctrl & E1000_CTRL_SWDPIN1) == signal) && - (!(rxcw & E1000_RXCW_C))) { - if(hw->autoneg_failed == 0) { - hw->autoneg_failed = 1; - return 0; - } - DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n"); - - /* Disable auto-negotiation in the TXCW register */ - E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE)); - - /* Force link-up and also force full-duplex. */ - ctrl = E1000_READ_REG(hw, CTRL); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - E1000_WRITE_REG(hw, CTRL, ctrl); - - /* Configure Flow Control after forcing link up. */ - if((ret_val = e1000_config_fc_after_link_up(hw))) { - DEBUGOUT("Error configuring flow control\n"); - return ret_val; - } - } - /* If we are forcing link and we are receiving /C/ ordered sets, re-enable - * auto-negotiation in the TXCW register and disable forced link in the - * Device Control register in an attempt to auto-negotiate with our link - * partner. - */ - else if((hw->media_type == e1000_media_type_fiber) && - (ctrl & E1000_CTRL_SLU) && - (rxcw & E1000_RXCW_C)) { - DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\r\n"); - E1000_WRITE_REG(hw, TXCW, hw->txcw); - E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU)); - } - return E1000_SUCCESS; -} - -/****************************************************************************** - * Detects the current speed and duplex settings of the hardware. - * - * hw - Struct containing variables accessed by shared code - * speed - Speed of the connection - * duplex - Duplex setting of the connection - *****************************************************************************/ -int32_t -e1000_get_speed_and_duplex(struct e1000_hw *hw, - uint16_t *speed, - uint16_t *duplex) -{ - uint32_t status; - int32_t ret_val; - uint16_t phy_data; - - DEBUGFUNC("e1000_get_speed_and_duplex"); - - if(hw->mac_type >= e1000_82543) { - status = E1000_READ_REG(hw, STATUS); - if(status & E1000_STATUS_SPEED_1000) { - *speed = SPEED_1000; - DEBUGOUT("1000 Mbs, "); - } else if(status & E1000_STATUS_SPEED_100) { - *speed = SPEED_100; - DEBUGOUT("100 Mbs, "); - } else { - *speed = SPEED_10; - DEBUGOUT("10 Mbs, "); - } - - if(status & E1000_STATUS_FD) { - *duplex = FULL_DUPLEX; - DEBUGOUT("Full Duplex\r\n"); - } else { - *duplex = HALF_DUPLEX; - DEBUGOUT(" Half Duplex\r\n"); - } - } else { - DEBUGOUT("1000 Mbs, Full Duplex\r\n"); - *speed = SPEED_1000; - *duplex = FULL_DUPLEX; - } - - /* IGP01 PHY may advertise full duplex operation after speed downgrade even - * if it is operating at half duplex. Here we set the duplex settings to - * match the duplex in the link partner's capabilities. - */ - if(hw->phy_type == e1000_phy_igp && hw->speed_downgraded) { - if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data))) - return ret_val; - - if(!(phy_data & NWAY_ER_LP_NWAY_CAPS)) - *duplex = HALF_DUPLEX; - else { - if((ret_val == e1000_read_phy_reg(hw, PHY_LP_ABILITY, &phy_data))) - return ret_val; - if((*speed == SPEED_100 && !(phy_data & NWAY_LPAR_100TX_FD_CAPS)) || - (*speed == SPEED_10 && !(phy_data & NWAY_LPAR_10T_FD_CAPS))) - *duplex = HALF_DUPLEX; - } - } - - return E1000_SUCCESS; -} - -/****************************************************************************** -* Blocks until autoneg completes or times out (~4.5 seconds) -* -* hw - Struct containing variables accessed by shared code -******************************************************************************/ -int32_t -e1000_wait_autoneg(struct e1000_hw *hw) -{ - int32_t ret_val; - uint16_t i; - uint16_t phy_data; - - DEBUGFUNC("e1000_wait_autoneg"); - DEBUGOUT("Waiting for Auto-Neg to complete.\n"); - - /* We will wait for autoneg to complete or 4.5 seconds to expire. */ - for(i = PHY_AUTO_NEG_TIME; i > 0; i--) { - /* Read the MII Status Register and wait for Auto-Neg - * Complete bit to be set. - */ - if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) - return ret_val; - if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) - return ret_val; - if(phy_data & MII_SR_AUTONEG_COMPLETE) { - return E1000_SUCCESS; - } - msec_delay(100); - } - return E1000_SUCCESS; -} - -/****************************************************************************** -* Raises the Management Data Clock -* -* hw - Struct containing variables accessed by shared code -* ctrl - Device control register's current value -******************************************************************************/ -static void -e1000_raise_mdi_clk(struct e1000_hw *hw, - uint32_t *ctrl) -{ - /* Raise the clock input to the Management Data Clock (by setting the MDC - * bit), and then delay 10 microseconds. - */ - E1000_WRITE_REG(hw, CTRL, (*ctrl | E1000_CTRL_MDC)); - E1000_WRITE_FLUSH(hw); - usec_delay(10); -} - -/****************************************************************************** -* Lowers the Management Data Clock -* -* hw - Struct containing variables accessed by shared code -* ctrl - Device control register's current value -******************************************************************************/ -static void -e1000_lower_mdi_clk(struct e1000_hw *hw, - uint32_t *ctrl) -{ - /* Lower the clock input to the Management Data Clock (by clearing the MDC - * bit), and then delay 10 microseconds. - */ - E1000_WRITE_REG(hw, CTRL, (*ctrl & ~E1000_CTRL_MDC)); - E1000_WRITE_FLUSH(hw); - usec_delay(10); -} - -/****************************************************************************** -* Shifts data bits out to the PHY -* -* hw - Struct containing variables accessed by shared code -* data - Data to send out to the PHY -* count - Number of bits to shift out -* -* Bits are shifted out in MSB to LSB order. -******************************************************************************/ -static void -e1000_shift_out_mdi_bits(struct e1000_hw *hw, - uint32_t data, - uint16_t count) -{ - uint32_t ctrl; - uint32_t mask; - - /* We need to shift "count" number of bits out to the PHY. So, the value - * in the "data" parameter will be shifted out to the PHY one bit at a - * time. In order to do this, "data" must be broken down into bits. - */ - mask = 0x01; - mask <<= (count - 1); - - ctrl = E1000_READ_REG(hw, CTRL); - - /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */ - ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR); - - while(mask) { - /* A "1" is shifted out to the PHY by setting the MDIO bit to "1" and - * then raising and lowering the Management Data Clock. A "0" is - * shifted out to the PHY by setting the MDIO bit to "0" and then - * raising and lowering the clock. - */ - if(data & mask) ctrl |= E1000_CTRL_MDIO; - else ctrl &= ~E1000_CTRL_MDIO; - - E1000_WRITE_REG(hw, CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - - usec_delay(10); - - e1000_raise_mdi_clk(hw, &ctrl); - e1000_lower_mdi_clk(hw, &ctrl); - - mask = mask >> 1; - } -} - -/****************************************************************************** -* Shifts data bits in from the PHY -* -* hw - Struct containing variables accessed by shared code -* -* Bits are shifted in in MSB to LSB order. -******************************************************************************/ -static uint16_t -e1000_shift_in_mdi_bits(struct e1000_hw *hw) -{ - uint32_t ctrl; - uint16_t data = 0; - uint8_t i; - - /* In order to read a register from the PHY, we need to shift in a total - * of 18 bits from the PHY. The first two bit (turnaround) times are used - * to avoid contention on the MDIO pin when a read operation is performed. - * These two bits are ignored by us and thrown away. Bits are "shifted in" - * by raising the input to the Management Data Clock (setting the MDC bit), - * and then reading the value of the MDIO bit. - */ - ctrl = E1000_READ_REG(hw, CTRL); - - /* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as input. */ - ctrl &= ~E1000_CTRL_MDIO_DIR; - ctrl &= ~E1000_CTRL_MDIO; - - E1000_WRITE_REG(hw, CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - - /* Raise and Lower the clock before reading in the data. This accounts for - * the turnaround bits. The first clock occurred when we clocked out the - * last bit of the Register Address. - */ - e1000_raise_mdi_clk(hw, &ctrl); - e1000_lower_mdi_clk(hw, &ctrl); - - for(data = 0, i = 0; i < 16; i++) { - data = data << 1; - e1000_raise_mdi_clk(hw, &ctrl); - ctrl = E1000_READ_REG(hw, CTRL); - /* Check to see if we shifted in a "1". */ - if(ctrl & E1000_CTRL_MDIO) data |= 1; - e1000_lower_mdi_clk(hw, &ctrl); - } - - e1000_raise_mdi_clk(hw, &ctrl); - e1000_lower_mdi_clk(hw, &ctrl); - - return data; -} - -/***************************************************************************** -* Reads the value from a PHY register, if the value is on a specific non zero -* page, sets the page first. -* hw - Struct containing variables accessed by shared code -* reg_addr - address of the PHY register to read -******************************************************************************/ -int32_t -e1000_read_phy_reg(struct e1000_hw *hw, - uint32_t reg_addr, - uint16_t *phy_data) -{ - uint32_t ret_val; - - DEBUGFUNC("e1000_read_phy_reg"); - - if(hw->phy_type == e1000_phy_igp && - (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { - if((ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, - (uint16_t)reg_addr))) - return ret_val; - } - - ret_val = e1000_read_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr, - phy_data); - - return ret_val; -} - -int32_t -e1000_read_phy_reg_ex(struct e1000_hw *hw, - uint32_t reg_addr, - uint16_t *phy_data) -{ - uint32_t i; - uint32_t mdic = 0; - const uint32_t phy_addr = 1; - - DEBUGFUNC("e1000_read_phy_reg_ex"); - - if(reg_addr > MAX_PHY_REG_ADDRESS) { - DEBUGOUT1("PHY Address %d is out of range\n", reg_addr); - return -E1000_ERR_PARAM; - } - - if(hw->mac_type > e1000_82543) { - /* Set up Op-code, Phy Address, and register address in the MDI - * Control register. The MAC will take care of interfacing with the - * PHY to retrieve the desired data. - */ - mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) | - (phy_addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_READ)); - - E1000_WRITE_REG(hw, MDIC, mdic); - - /* Poll the ready bit to see if the MDI read completed */ - for(i = 0; i < 64; i++) { - usec_delay(50); - mdic = E1000_READ_REG(hw, MDIC); - if(mdic & E1000_MDIC_READY) break; - } - if(!(mdic & E1000_MDIC_READY)) { - DEBUGOUT("MDI Read did not complete\n"); - return -E1000_ERR_PHY; - } - if(mdic & E1000_MDIC_ERROR) { - DEBUGOUT("MDI Error\n"); - return -E1000_ERR_PHY; - } - *phy_data = (uint16_t) mdic; - } else { - /* We must first send a preamble through the MDIO pin to signal the - * beginning of an MII instruction. This is done by sending 32 - * consecutive "1" bits. - */ - e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); - - /* Now combine the next few fields that are required for a read - * operation. We use this method instead of calling the - * e1000_shift_out_mdi_bits routine five different times. The format of - * a MII read instruction consists of a shift out of 14 bits and is - * defined as follows: - * - * followed by a shift in of 18 bits. This first two bits shifted in - * are TurnAround bits used to avoid contention on the MDIO pin when a - * READ operation is performed. These two bits are thrown away - * followed by a shift in of 16 bits which contains the desired data. - */ - mdic = ((reg_addr) | (phy_addr << 5) | - (PHY_OP_READ << 10) | (PHY_SOF << 12)); - - e1000_shift_out_mdi_bits(hw, mdic, 14); - - /* Now that we've shifted out the read command to the MII, we need to - * "shift in" the 16-bit value (18 total bits) of the requested PHY - * register address. - */ - *phy_data = e1000_shift_in_mdi_bits(hw); - } - return E1000_SUCCESS; -} - -/****************************************************************************** -* Writes a value to a PHY register -* -* hw - Struct containing variables accessed by shared code -* reg_addr - address of the PHY register to write -* data - data to write to the PHY -******************************************************************************/ -int32_t -e1000_write_phy_reg(struct e1000_hw *hw, - uint32_t reg_addr, - uint16_t phy_data) -{ - uint32_t ret_val; - - DEBUGFUNC("e1000_write_phy_reg"); - - if(hw->phy_type == e1000_phy_igp && - (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { - if((ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, - (uint16_t)reg_addr))) - return ret_val; - } - - ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr, - phy_data); - - return ret_val; -} - -int32_t -e1000_write_phy_reg_ex(struct e1000_hw *hw, - uint32_t reg_addr, - uint16_t phy_data) -{ - uint32_t i; - uint32_t mdic = 0; - const uint32_t phy_addr = 1; - - DEBUGFUNC("e1000_write_phy_reg_ex"); - - if(reg_addr > MAX_PHY_REG_ADDRESS) { - DEBUGOUT1("PHY Address %d is out of range\n", reg_addr); - return -E1000_ERR_PARAM; - } - - if(hw->mac_type > e1000_82543) { - /* Set up Op-code, Phy Address, register address, and data intended - * for the PHY register in the MDI Control register. The MAC will take - * care of interfacing with the PHY to send the desired data. - */ - mdic = (((uint32_t) phy_data) | - (reg_addr << E1000_MDIC_REG_SHIFT) | - (phy_addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_WRITE)); - - E1000_WRITE_REG(hw, MDIC, mdic); - - /* Poll the ready bit to see if the MDI read completed */ - for(i = 0; i < 64; i++) { - usec_delay(50); - mdic = E1000_READ_REG(hw, MDIC); - if(mdic & E1000_MDIC_READY) break; - } - if(!(mdic & E1000_MDIC_READY)) { - DEBUGOUT("MDI Write did not complete\n"); - return -E1000_ERR_PHY; - } - } else { - /* We'll need to use the SW defined pins to shift the write command - * out to the PHY. We first send a preamble to the PHY to signal the - * beginning of the MII instruction. This is done by sending 32 - * consecutive "1" bits. - */ - e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); - - /* Now combine the remaining required fields that will indicate a - * write operation. We use this method instead of calling the - * e1000_shift_out_mdi_bits routine for each field in the command. The - * format of a MII write instruction is as follows: - * . - */ - mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) | - (PHY_OP_WRITE << 12) | (PHY_SOF << 14)); - mdic <<= 16; - mdic |= (uint32_t) phy_data; - - e1000_shift_out_mdi_bits(hw, mdic, 32); - } - - return E1000_SUCCESS; -} - -/****************************************************************************** -* Returns the PHY to the power-on reset state -* -* hw - Struct containing variables accessed by shared code -******************************************************************************/ -void -e1000_phy_hw_reset(struct e1000_hw *hw) -{ - uint32_t ctrl, ctrl_ext; - uint32_t led_ctrl; - - DEBUGFUNC("e1000_phy_hw_reset"); - - DEBUGOUT("Resetting Phy...\n"); - - if(hw->mac_type > e1000_82543) { - /* Read the device control register and assert the E1000_CTRL_PHY_RST - * bit. Then, take it out of reset. - */ - ctrl = E1000_READ_REG(hw, CTRL); - E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST); - E1000_WRITE_FLUSH(hw); - msec_delay(10); - E1000_WRITE_REG(hw, CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - } else { - /* Read the Extended Device Control Register, assert the PHY_RESET_DIR - * bit to put the PHY into reset. Then, take it out of reset. - */ - ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR; - ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA; - E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(hw); - msec_delay(10); - ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA; - E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(hw); - } - usec_delay(150); - - if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { - /* Configure activity LED after PHY reset */ - led_ctrl = E1000_READ_REG(hw, LEDCTL); - led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - E1000_WRITE_REG(hw, LEDCTL, led_ctrl); - } -} - -/****************************************************************************** -* Resets the PHY -* -* hw - Struct containing variables accessed by shared code -* -* Sets bit 15 of the MII Control regiser -******************************************************************************/ -int32_t -e1000_phy_reset(struct e1000_hw *hw) -{ - int32_t ret_val; - uint16_t phy_data; - - DEBUGFUNC("e1000_phy_reset"); - - if(hw->mac_type != e1000_82541_rev_2) { - if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data))) - return ret_val; - - phy_data |= MII_CR_RESET; - if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data))) - return ret_val; - - usec_delay(1); - } else e1000_phy_hw_reset(hw); - - if(hw->phy_type == e1000_phy_igp) - e1000_phy_init_script(hw); - - return E1000_SUCCESS; -} - -/****************************************************************************** -* Probes the expected PHY address for known PHY IDs -* -* hw - Struct containing variables accessed by shared code -******************************************************************************/ -int32_t -e1000_detect_gig_phy(struct e1000_hw *hw) -{ - int32_t phy_init_status, ret_val; - uint16_t phy_id_high, phy_id_low; - boolean_t match = FALSE; - - DEBUGFUNC("e1000_detect_gig_phy"); - - /* Read the PHY ID Registers to identify which PHY is onboard. */ - if((ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high))) - return ret_val; - - hw->phy_id = (uint32_t) (phy_id_high << 16); - usec_delay(20); - if((ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low))) - return ret_val; - - hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK); - hw->phy_revision = (uint32_t) phy_id_low & ~PHY_REVISION_MASK; - - switch(hw->mac_type) { - case e1000_82543: - if(hw->phy_id == M88E1000_E_PHY_ID) match = TRUE; - break; - case e1000_82544: - if(hw->phy_id == M88E1000_I_PHY_ID) match = TRUE; - break; - case e1000_82540: - case e1000_82545: - case e1000_82545_rev_3: - case e1000_82546: - case e1000_82546_rev_3: - if(hw->phy_id == M88E1011_I_PHY_ID) match = TRUE; - break; - case e1000_82541: - case e1000_82541_rev_2: - case e1000_82547: - case e1000_82547_rev_2: - if(hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE; - break; - default: - DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type); - return -E1000_ERR_CONFIG; - } - phy_init_status = e1000_set_phy_type(hw); - - if ((match) && (phy_init_status == E1000_SUCCESS)) { - DEBUGOUT1("PHY ID 0x%X detected\n", hw->phy_id); - return E1000_SUCCESS; - } - DEBUGOUT1("Invalid PHY ID 0x%X\n", hw->phy_id); - return -E1000_ERR_PHY; -} - -/****************************************************************************** -* Resets the PHY's DSP -* -* hw - Struct containing variables accessed by shared code -******************************************************************************/ -static int32_t -e1000_phy_reset_dsp(struct e1000_hw *hw) -{ - int32_t ret_val; - DEBUGFUNC("e1000_phy_reset_dsp"); - - do { - if((ret_val = e1000_write_phy_reg(hw, 29, 0x001d))) break; - if((ret_val = e1000_write_phy_reg(hw, 30, 0x00c1))) break; - if((ret_val = e1000_write_phy_reg(hw, 30, 0x0000))) break; - ret_val = E1000_SUCCESS; - } while(0); - - return ret_val; -} - -/****************************************************************************** -* Get PHY information from various PHY registers for igp PHY only. -* -* hw - Struct containing variables accessed by shared code -* phy_info - PHY information structure -******************************************************************************/ -int32_t -e1000_phy_igp_get_info(struct e1000_hw *hw, - struct e1000_phy_info *phy_info) -{ - int32_t ret_val; - uint16_t phy_data, polarity, min_length, max_length, average; - - DEBUGFUNC("e1000_phy_igp_get_info"); - - /* The downshift status is checked only once, after link is established, - * and it stored in the hw->speed_downgraded parameter. */ - phy_info->downshift = hw->speed_downgraded; - - /* IGP01E1000 does not need to support it. */ - phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_normal; - - /* IGP01E1000 always correct polarity reversal */ - phy_info->polarity_correction = e1000_polarity_reversal_enabled; - - /* Check polarity status */ - if((ret_val = e1000_check_polarity(hw, &polarity))) - return ret_val; - - phy_info->cable_polarity = polarity; - - if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, - &phy_data))) - return ret_val; - - phy_info->mdix_mode = (phy_data & IGP01E1000_PSSR_MDIX) >> - IGP01E1000_PSSR_MDIX_SHIFT; - - if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) { - /* Local/Remote Receiver Information are only valid at 1000 Mbps */ - if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data))) - return ret_val; - - phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >> - SR_1000T_LOCAL_RX_STATUS_SHIFT; - phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) >> - SR_1000T_REMOTE_RX_STATUS_SHIFT; - - /* Get cable length */ - if((ret_val = e1000_get_cable_length(hw, &min_length, &max_length))) - return ret_val; - - /* transalte to old method */ - average = (max_length + min_length) / 2; - - if(average <= e1000_igp_cable_length_50) - phy_info->cable_length = e1000_cable_length_50; - else if(average <= e1000_igp_cable_length_80) - phy_info->cable_length = e1000_cable_length_50_80; - else if(average <= e1000_igp_cable_length_110) - phy_info->cable_length = e1000_cable_length_80_110; - else if(average <= e1000_igp_cable_length_140) - phy_info->cable_length = e1000_cable_length_110_140; - else - phy_info->cable_length = e1000_cable_length_140; - } - - return E1000_SUCCESS; -} - -/****************************************************************************** -* Get PHY information from various PHY registers fot m88 PHY only. -* -* hw - Struct containing variables accessed by shared code -* phy_info - PHY information structure -******************************************************************************/ -int32_t -e1000_phy_m88_get_info(struct e1000_hw *hw, - struct e1000_phy_info *phy_info) -{ - int32_t ret_val; - uint16_t phy_data, polarity; - - DEBUGFUNC("e1000_phy_m88_get_info"); - - /* The downshift status is checked only once, after link is established, - * and it stored in the hw->speed_downgraded parameter. */ - phy_info->downshift = hw->speed_downgraded; - - if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data))) - return ret_val; - - phy_info->extended_10bt_distance = - (phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >> - M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT; - phy_info->polarity_correction = - (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) >> - M88E1000_PSCR_POLARITY_REVERSAL_SHIFT; - - /* Check polarity status */ - if((ret_val = e1000_check_polarity(hw, &polarity))) - return ret_val; - - phy_info->cable_polarity = polarity; - - if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data))) - return ret_val; - - phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >> - M88E1000_PSSR_MDIX_SHIFT; - - if(phy_data & M88E1000_PSSR_1000MBS) { - /* Cable Length Estimation and Local/Remote Receiver Informatoion - * are only valid at 1000 Mbps - */ - phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> - M88E1000_PSSR_CABLE_LENGTH_SHIFT); - - if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data))) - return ret_val; - - phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >> - SR_1000T_LOCAL_RX_STATUS_SHIFT; - - phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) >> - SR_1000T_REMOTE_RX_STATUS_SHIFT; - } - - return E1000_SUCCESS; -} - -/****************************************************************************** -* Get PHY information from various PHY registers -* -* hw - Struct containing variables accessed by shared code -* phy_info - PHY information structure -******************************************************************************/ -int32_t -e1000_phy_get_info(struct e1000_hw *hw, - struct e1000_phy_info *phy_info) -{ - int32_t ret_val; - uint16_t phy_data; - - DEBUGFUNC("e1000_phy_get_info"); - - phy_info->cable_length = e1000_cable_length_undefined; - phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_undefined; - phy_info->cable_polarity = e1000_rev_polarity_undefined; - phy_info->downshift = e1000_downshift_undefined; - phy_info->polarity_correction = e1000_polarity_reversal_undefined; - phy_info->mdix_mode = e1000_auto_x_mode_undefined; - phy_info->local_rx = e1000_1000t_rx_status_undefined; - phy_info->remote_rx = e1000_1000t_rx_status_undefined; - - if(hw->media_type != e1000_media_type_copper) { - DEBUGOUT("PHY info is only valid for copper media\n"); - return -E1000_ERR_CONFIG; - } - - if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) - return ret_val; - - if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) - return ret_val; - - if((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) { - DEBUGOUT("PHY info is only valid if link is up\n"); - return -E1000_ERR_CONFIG; - } - - if(hw->phy_type == e1000_phy_igp) - return e1000_phy_igp_get_info(hw, phy_info); - else - return e1000_phy_m88_get_info(hw, phy_info); -} - -int32_t -e1000_validate_mdi_setting(struct e1000_hw *hw) -{ - DEBUGFUNC("e1000_validate_mdi_settings"); - - if(!hw->autoneg && (hw->mdix == 0 || hw->mdix == 3)) { - DEBUGOUT("Invalid MDI setting detected\n"); - hw->mdix = 1; - return -E1000_ERR_CONFIG; - } - return E1000_SUCCESS; -} - - -/****************************************************************************** - * Sets up eeprom variables in the hw struct. Must be called after mac_type - * is configured. - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -void -e1000_init_eeprom_params(struct e1000_hw *hw) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - uint32_t eecd = E1000_READ_REG(hw, EECD); - uint16_t eeprom_size; - - DEBUGFUNC("e1000_init_eeprom_params"); - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - case e1000_82544: - eeprom->type = e1000_eeprom_microwire; - eeprom->word_size = 64; - eeprom->opcode_bits = 3; - eeprom->address_bits = 6; - eeprom->delay_usec = 50; - break; - case e1000_82540: - case e1000_82545: - case e1000_82545_rev_3: - case e1000_82546: - case e1000_82546_rev_3: - eeprom->type = e1000_eeprom_microwire; - eeprom->opcode_bits = 3; - eeprom->delay_usec = 50; - if(eecd & E1000_EECD_SIZE) { - eeprom->word_size = 256; - eeprom->address_bits = 8; - } else { - eeprom->word_size = 64; - eeprom->address_bits = 6; - } - break; - case e1000_82541: - case e1000_82541_rev_2: - case e1000_82547: - case e1000_82547_rev_2: - if (eecd & E1000_EECD_TYPE) { - eeprom->type = e1000_eeprom_spi; - eeprom->opcode_bits = 8; - eeprom->delay_usec = 1; - if (eecd & E1000_EECD_ADDR_BITS) { - eeprom->page_size = 32; - eeprom->address_bits = 16; - } else { - eeprom->page_size = 8; - eeprom->address_bits = 8; - } - } else { - eeprom->type = e1000_eeprom_microwire; - eeprom->opcode_bits = 3; - eeprom->delay_usec = 50; - if (eecd & E1000_EECD_ADDR_BITS) { - eeprom->word_size = 256; - eeprom->address_bits = 8; - } else { - eeprom->word_size = 64; - eeprom->address_bits = 6; - } - } - break; - default: - eeprom->type = e1000_eeprom_spi; - eeprom->opcode_bits = 8; - eeprom->delay_usec = 1; - if (eecd & E1000_EECD_ADDR_BITS) { - eeprom->page_size = 32; - eeprom->address_bits = 16; - } else { - eeprom->page_size = 8; - eeprom->address_bits = 8; - } - break; - } - - if (eeprom->type == e1000_eeprom_spi) { - eeprom->word_size = 64; - if (e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size) == 0) { - eeprom_size &= EEPROM_SIZE_MASK; - - switch (eeprom_size) { - case EEPROM_SIZE_16KB: - eeprom->word_size = 8192; - break; - case EEPROM_SIZE_8KB: - eeprom->word_size = 4096; - break; - case EEPROM_SIZE_4KB: - eeprom->word_size = 2048; - break; - case EEPROM_SIZE_2KB: - eeprom->word_size = 1024; - break; - case EEPROM_SIZE_1KB: - eeprom->word_size = 512; - break; - case EEPROM_SIZE_512B: - eeprom->word_size = 256; - break; - case EEPROM_SIZE_128B: - default: - eeprom->word_size = 64; - break; - } - } - } -} - -/****************************************************************************** - * Raises the EEPROM's clock input. - * - * hw - Struct containing variables accessed by shared code - * eecd - EECD's current value - *****************************************************************************/ -static void -e1000_raise_ee_clk(struct e1000_hw *hw, - uint32_t *eecd) -{ - /* Raise the clock input to the EEPROM (by setting the SK bit), and then - * wait microseconds. - */ - *eecd = *eecd | E1000_EECD_SK; - E1000_WRITE_REG(hw, EECD, *eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(hw->eeprom.delay_usec); -} - -/****************************************************************************** - * Lowers the EEPROM's clock input. - * - * hw - Struct containing variables accessed by shared code - * eecd - EECD's current value - *****************************************************************************/ -static void -e1000_lower_ee_clk(struct e1000_hw *hw, - uint32_t *eecd) -{ - /* Lower the clock input to the EEPROM (by clearing the SK bit), and then - * wait 50 microseconds. - */ - *eecd = *eecd & ~E1000_EECD_SK; - E1000_WRITE_REG(hw, EECD, *eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(hw->eeprom.delay_usec); -} - -/****************************************************************************** - * Shift data bits out to the EEPROM. - * - * hw - Struct containing variables accessed by shared code - * data - data to send to the EEPROM - * count - number of bits to shift out - *****************************************************************************/ -static void -e1000_shift_out_ee_bits(struct e1000_hw *hw, - uint16_t data, - uint16_t count) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - uint32_t eecd; - uint32_t mask; - - /* We need to shift "count" bits out to the EEPROM. So, value in the - * "data" parameter will be shifted out to the EEPROM one bit at a time. - * In order to do this, "data" must be broken down into bits. - */ - mask = 0x01 << (count - 1); - eecd = E1000_READ_REG(hw, EECD); - if (eeprom->type == e1000_eeprom_microwire) { - eecd &= ~E1000_EECD_DO; - } else if (eeprom->type == e1000_eeprom_spi) { - eecd |= E1000_EECD_DO; - } - do { - /* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1", - * and then raising and then lowering the clock (the SK bit controls - * the clock input to the EEPROM). A "0" is shifted out to the EEPROM - * by setting "DI" to "0" and then raising and then lowering the clock. - */ - eecd &= ~E1000_EECD_DI; - - if(data & mask) - eecd |= E1000_EECD_DI; - - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - - usec_delay(eeprom->delay_usec); - - e1000_raise_ee_clk(hw, &eecd); - e1000_lower_ee_clk(hw, &eecd); - - mask = mask >> 1; - - } while(mask); - - /* We leave the "DI" bit set to "0" when we leave this routine. */ - eecd &= ~E1000_EECD_DI; - E1000_WRITE_REG(hw, EECD, eecd); -} - -/****************************************************************************** - * Shift data bits in from the EEPROM - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -static uint16_t -e1000_shift_in_ee_bits(struct e1000_hw *hw, - uint16_t count) -{ - uint32_t eecd; - uint32_t i; - uint16_t data; - - /* In order to read a register from the EEPROM, we need to shift 'count' - * bits in from the EEPROM. Bits are "shifted in" by raising the clock - * input to the EEPROM (setting the SK bit), and then reading the value of - * the "DO" bit. During this "shifting in" process the "DI" bit should - * always be clear. - */ - - eecd = E1000_READ_REG(hw, EECD); - - eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); - data = 0; - - for(i = 0; i < count; i++) { - data = data << 1; - e1000_raise_ee_clk(hw, &eecd); - - eecd = E1000_READ_REG(hw, EECD); - - eecd &= ~(E1000_EECD_DI); - if(eecd & E1000_EECD_DO) - data |= 1; - - e1000_lower_ee_clk(hw, &eecd); - } - - return data; -} - -/****************************************************************************** - * Prepares EEPROM for access - * - * hw - Struct containing variables accessed by shared code - * - * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This - * function should be called before issuing a command to the EEPROM. - *****************************************************************************/ -static int32_t -e1000_acquire_eeprom(struct e1000_hw *hw) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - uint32_t eecd, i=0; - - DEBUGFUNC("e1000_acquire_eeprom"); - - eecd = E1000_READ_REG(hw, EECD); - - /* Request EEPROM Access */ - if(hw->mac_type > e1000_82544) { - eecd |= E1000_EECD_REQ; - E1000_WRITE_REG(hw, EECD, eecd); - eecd = E1000_READ_REG(hw, EECD); - while((!(eecd & E1000_EECD_GNT)) && - (i < E1000_EEPROM_GRANT_ATTEMPTS)) { - i++; - usec_delay(5); - eecd = E1000_READ_REG(hw, EECD); - } - if(!(eecd & E1000_EECD_GNT)) { - eecd &= ~E1000_EECD_REQ; - E1000_WRITE_REG(hw, EECD, eecd); - DEBUGOUT("Could not acquire EEPROM grant\n"); - return -E1000_ERR_EEPROM; - } - } - - /* Setup EEPROM for Read/Write */ - - if (eeprom->type == e1000_eeprom_microwire) { - /* Clear SK and DI */ - eecd &= ~(E1000_EECD_DI | E1000_EECD_SK); - E1000_WRITE_REG(hw, EECD, eecd); - - /* Set CS */ - eecd |= E1000_EECD_CS; - E1000_WRITE_REG(hw, EECD, eecd); - } else if (eeprom->type == e1000_eeprom_spi) { - /* Clear SK and CS */ - eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); - E1000_WRITE_REG(hw, EECD, eecd); - usec_delay(1); - } - - return E1000_SUCCESS; -} - -/****************************************************************************** - * Returns EEPROM to a "standby" state - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -static void -e1000_standby_eeprom(struct e1000_hw *hw) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - uint32_t eecd; - - eecd = E1000_READ_REG(hw, EECD); - - if(eeprom->type == e1000_eeprom_microwire) { - eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(eeprom->delay_usec); - - /* Clock high */ - eecd |= E1000_EECD_SK; - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(eeprom->delay_usec); - - /* Select EEPROM */ - eecd |= E1000_EECD_CS; - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(eeprom->delay_usec); - - /* Clock low */ - eecd &= ~E1000_EECD_SK; - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(eeprom->delay_usec); - } else if(eeprom->type == e1000_eeprom_spi) { - /* Toggle CS to flush commands */ - eecd |= E1000_EECD_CS; - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(eeprom->delay_usec); - eecd &= ~E1000_EECD_CS; - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(eeprom->delay_usec); - } -} - -/****************************************************************************** - * Terminates a command by inverting the EEPROM's chip select pin - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -static void -e1000_release_eeprom(struct e1000_hw *hw) -{ - uint32_t eecd; - - DEBUGFUNC("e1000_release_eeprom"); - - eecd = E1000_READ_REG(hw, EECD); - - if (hw->eeprom.type == e1000_eeprom_spi) { - eecd |= E1000_EECD_CS; /* Pull CS high */ - eecd &= ~E1000_EECD_SK; /* Lower SCK */ - - E1000_WRITE_REG(hw, EECD, eecd); - - usec_delay(hw->eeprom.delay_usec); - } else if(hw->eeprom.type == e1000_eeprom_microwire) { - /* cleanup eeprom */ - - /* CS on Microwire is active-high */ - eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); - - E1000_WRITE_REG(hw, EECD, eecd); - - /* Rising edge of clock */ - eecd |= E1000_EECD_SK; - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(hw->eeprom.delay_usec); - - /* Falling edge of clock */ - eecd &= ~E1000_EECD_SK; - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(hw->eeprom.delay_usec); - } - - /* Stop requesting EEPROM access */ - if(hw->mac_type > e1000_82544) { - eecd &= ~E1000_EECD_REQ; - E1000_WRITE_REG(hw, EECD, eecd); - } -} - -/****************************************************************************** - * Reads a 16 bit word from the EEPROM. - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -int32_t -e1000_spi_eeprom_ready(struct e1000_hw *hw) -{ - uint16_t retry_count = 0; - uint8_t spi_stat_reg; - - DEBUGFUNC("e1000_spi_eeprom_ready"); - - /* Read "Status Register" repeatedly until the LSB is cleared. The - * EEPROM will signal that the command has been completed by clearing - * bit 0 of the internal status register. If it's not cleared within - * 5 milliseconds, then error out. - */ - retry_count = 0; - do { - e1000_shift_out_ee_bits(hw, EEPROM_RDSR_OPCODE_SPI, - hw->eeprom.opcode_bits); - spi_stat_reg = (uint8_t)e1000_shift_in_ee_bits(hw, 8); - if (!(spi_stat_reg & EEPROM_STATUS_RDY_SPI)) - break; - - usec_delay(5); - retry_count += 5; - - } while(retry_count < EEPROM_MAX_RETRY_SPI); - - /* ATMEL SPI write time could vary from 0-20mSec on 3.3V devices (and - * only 0-5mSec on 5V devices) - */ - if(retry_count >= EEPROM_MAX_RETRY_SPI) { - DEBUGOUT("SPI EEPROM Status error\n"); - return -E1000_ERR_EEPROM; - } - - return E1000_SUCCESS; -} - -/****************************************************************************** - * Reads a 16 bit word from the EEPROM. - * - * hw - Struct containing variables accessed by shared code - * offset - offset of word in the EEPROM to read - * data - word read from the EEPROM - * words - number of words to read - *****************************************************************************/ -int32_t -e1000_read_eeprom(struct e1000_hw *hw, - uint16_t offset, - uint16_t words, - uint16_t *data) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - uint32_t i = 0; - - DEBUGFUNC("e1000_read_eeprom"); - - /* A check for invalid values: offset too large, too many words, and not - * enough words. - */ - if((offset > eeprom->word_size) || (words > eeprom->word_size - offset) || - (words == 0)) { - DEBUGOUT("\"words\" parameter out of bounds\n"); - return -E1000_ERR_EEPROM; - } - - /* Prepare the EEPROM for reading */ - if(e1000_acquire_eeprom(hw) != E1000_SUCCESS) - return -E1000_ERR_EEPROM; - - if(eeprom->type == e1000_eeprom_spi) { - uint16_t word_in; - uint8_t read_opcode = EEPROM_READ_OPCODE_SPI; - - if(e1000_spi_eeprom_ready(hw)) { - e1000_release_eeprom(hw); - return -E1000_ERR_EEPROM; - } - - e1000_standby_eeprom(hw); - - /* Some SPI eeproms use the 8th address bit embedded in the opcode */ - if((eeprom->address_bits == 8) && (offset >= 128)) - read_opcode |= EEPROM_A8_OPCODE_SPI; - - /* Send the READ command (opcode + addr) */ - e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits); - e1000_shift_out_ee_bits(hw, (uint16_t)(offset*2), eeprom->address_bits); - - /* Read the data. The address of the eeprom internally increments with - * each byte (spi) being read, saving on the overhead of eeprom setup - * and tear-down. The address counter will roll over if reading beyond - * the size of the eeprom, thus allowing the entire memory to be read - * starting from any offset. */ - for (i = 0; i < words; i++) { - word_in = e1000_shift_in_ee_bits(hw, 16); - data[i] = (word_in >> 8) | (word_in << 8); - } - } else if(eeprom->type == e1000_eeprom_microwire) { - for (i = 0; i < words; i++) { - /* Send the READ command (opcode + addr) */ - e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE_MICROWIRE, - eeprom->opcode_bits); - e1000_shift_out_ee_bits(hw, (uint16_t)(offset + i), - eeprom->address_bits); - - /* Read the data. For microwire, each word requires the overhead - * of eeprom setup and tear-down. */ - data[i] = e1000_shift_in_ee_bits(hw, 16); - e1000_standby_eeprom(hw); - } - } - - /* End this read operation */ - e1000_release_eeprom(hw); - - return E1000_SUCCESS; -} - -/****************************************************************************** - * Verifies that the EEPROM has a valid checksum - * - * hw - Struct containing variables accessed by shared code - * - * Reads the first 64 16 bit words of the EEPROM and sums the values read. - * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is - * valid. - *****************************************************************************/ -int32_t -e1000_validate_eeprom_checksum(struct e1000_hw *hw) -{ - uint16_t checksum = 0; - uint16_t i, eeprom_data; - - DEBUGFUNC("e1000_validate_eeprom_checksum"); - - for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { - if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) { - DEBUGOUT("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - checksum += eeprom_data; - } - - if(checksum == (uint16_t) EEPROM_SUM) - return E1000_SUCCESS; - else { - DEBUGOUT("EEPROM Checksum Invalid\n"); - return -E1000_ERR_EEPROM; - } -} - -/****************************************************************************** - * Calculates the EEPROM checksum and writes it to the EEPROM - * - * hw - Struct containing variables accessed by shared code - * - * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA. - * Writes the difference to word offset 63 of the EEPROM. - *****************************************************************************/ -int32_t -e1000_update_eeprom_checksum(struct e1000_hw *hw) -{ - uint16_t checksum = 0; - uint16_t i, eeprom_data; - - DEBUGFUNC("e1000_update_eeprom_checksum"); - - for(i = 0; i < EEPROM_CHECKSUM_REG; i++) { - if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) { - DEBUGOUT("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - checksum += eeprom_data; - } - checksum = (uint16_t) EEPROM_SUM - checksum; - if(e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) { - DEBUGOUT("EEPROM Write Error\n"); - return -E1000_ERR_EEPROM; - } - return E1000_SUCCESS; -} - -/****************************************************************************** - * Parent function for writing words to the different EEPROM types. - * - * hw - Struct containing variables accessed by shared code - * offset - offset within the EEPROM to be written to - * words - number of words to write - * data - 16 bit word to be written to the EEPROM - * - * If e1000_update_eeprom_checksum is not called after this function, the - * EEPROM will most likely contain an invalid checksum. - *****************************************************************************/ -int32_t -e1000_write_eeprom(struct e1000_hw *hw, - uint16_t offset, - uint16_t words, - uint16_t *data) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - int32_t status = 0; - - DEBUGFUNC("e1000_write_eeprom"); - - /* A check for invalid values: offset too large, too many words, and not - * enough words. - */ - if((offset > eeprom->word_size) || (words > eeprom->word_size - offset) || - (words == 0)) { - DEBUGOUT("\"words\" parameter out of bounds\n"); - return -E1000_ERR_EEPROM; - } - - /* Prepare the EEPROM for writing */ - if (e1000_acquire_eeprom(hw) != E1000_SUCCESS) - return -E1000_ERR_EEPROM; - - if(eeprom->type == e1000_eeprom_microwire) - status = e1000_write_eeprom_microwire(hw, offset, words, data); - else - status = e1000_write_eeprom_spi(hw, offset, words, data); - - /* Done with writing */ - e1000_release_eeprom(hw); - - return status; -} - -/****************************************************************************** - * Writes a 16 bit word to a given offset in an SPI EEPROM. - * - * hw - Struct containing variables accessed by shared code - * offset - offset within the EEPROM to be written to - * words - number of words to write - * data - pointer to array of 8 bit words to be written to the EEPROM - * - *****************************************************************************/ -int32_t -e1000_write_eeprom_spi(struct e1000_hw *hw, - uint16_t offset, - uint16_t words, - uint16_t *data) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - uint16_t widx = 0; - - DEBUGFUNC("e1000_write_eeprom_spi"); - - while (widx < words) { - uint8_t write_opcode = EEPROM_WRITE_OPCODE_SPI; - - if(e1000_spi_eeprom_ready(hw)) return -E1000_ERR_EEPROM; - - e1000_standby_eeprom(hw); - - /* Send the WRITE ENABLE command (8 bit opcode ) */ - e1000_shift_out_ee_bits(hw, EEPROM_WREN_OPCODE_SPI, - eeprom->opcode_bits); - - e1000_standby_eeprom(hw); - - /* Some SPI eeproms use the 8th address bit embedded in the opcode */ - if((eeprom->address_bits == 8) && (offset >= 128)) - write_opcode |= EEPROM_A8_OPCODE_SPI; - - /* Send the Write command (8-bit opcode + addr) */ - e1000_shift_out_ee_bits(hw, write_opcode, eeprom->opcode_bits); - - e1000_shift_out_ee_bits(hw, (uint16_t)((offset + widx)*2), - eeprom->address_bits); - - /* Send the data */ - - /* Loop to allow for up to whole page write (32 bytes) of eeprom */ - while (widx < words) { - uint16_t word_out = data[widx]; - word_out = (word_out >> 8) | (word_out << 8); - e1000_shift_out_ee_bits(hw, word_out, 16); - widx++; - - /* Some larger eeprom sizes are capable of a 32-byte PAGE WRITE - * operation, while the smaller eeproms are capable of an 8-byte - * PAGE WRITE operation. Break the inner loop to pass new address - */ - if((((offset + widx)*2) % eeprom->page_size) == 0) { - e1000_standby_eeprom(hw); - break; - } - } - } - - return E1000_SUCCESS; -} - -/****************************************************************************** - * Writes a 16 bit word to a given offset in a Microwire EEPROM. - * - * hw - Struct containing variables accessed by shared code - * offset - offset within the EEPROM to be written to - * words - number of words to write - * data - pointer to array of 16 bit words to be written to the EEPROM - * - *****************************************************************************/ -int32_t -e1000_write_eeprom_microwire(struct e1000_hw *hw, - uint16_t offset, - uint16_t words, - uint16_t *data) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - uint32_t eecd; - uint16_t words_written = 0; - uint16_t i = 0; - - DEBUGFUNC("e1000_write_eeprom_microwire"); - - /* Send the write enable command to the EEPROM (3-bit opcode plus - * 6/8-bit dummy address beginning with 11). It's less work to include - * the 11 of the dummy address as part of the opcode than it is to shift - * it over the correct number of bits for the address. This puts the - * EEPROM into write/erase mode. - */ - e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE_MICROWIRE, - (uint16_t)(eeprom->opcode_bits + 2)); - - e1000_shift_out_ee_bits(hw, 0, (uint16_t)(eeprom->address_bits - 2)); - - /* Prepare the EEPROM */ - e1000_standby_eeprom(hw); - - while (words_written < words) { - /* Send the Write command (3-bit opcode + addr) */ - e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE_MICROWIRE, - eeprom->opcode_bits); - - e1000_shift_out_ee_bits(hw, (uint16_t)(offset + words_written), - eeprom->address_bits); - - /* Send the data */ - e1000_shift_out_ee_bits(hw, data[words_written], 16); - - /* Toggle the CS line. This in effect tells the EEPROM to execute - * the previous command. - */ - e1000_standby_eeprom(hw); - - /* Read DO repeatedly until it is high (equal to '1'). The EEPROM will - * signal that the command has been completed by raising the DO signal. - * If DO does not go high in 10 milliseconds, then error out. - */ - for(i = 0; i < 200; i++) { - eecd = E1000_READ_REG(hw, EECD); - if(eecd & E1000_EECD_DO) break; - usec_delay(50); - } - if(i == 200) { - DEBUGOUT("EEPROM Write did not complete\n"); - return -E1000_ERR_EEPROM; - } - - /* Recover from write */ - e1000_standby_eeprom(hw); - - words_written++; - } - - /* Send the write disable command to the EEPROM (3-bit opcode plus - * 6/8-bit dummy address beginning with 10). It's less work to include - * the 10 of the dummy address as part of the opcode than it is to shift - * it over the correct number of bits for the address. This takes the - * EEPROM out of write/erase mode. - */ - e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE_MICROWIRE, - (uint16_t)(eeprom->opcode_bits + 2)); - - e1000_shift_out_ee_bits(hw, 0, (uint16_t)(eeprom->address_bits - 2)); - - return E1000_SUCCESS; -} - -/****************************************************************************** - * Reads the adapter's part number from the EEPROM - * - * hw - Struct containing variables accessed by shared code - * part_num - Adapter's part number - *****************************************************************************/ -int32_t -e1000_read_part_num(struct e1000_hw *hw, - uint32_t *part_num) -{ - uint16_t offset = EEPROM_PBA_BYTE_1; - uint16_t eeprom_data; - - DEBUGFUNC("e1000_read_part_num"); - - /* Get word 0 from EEPROM */ - if(e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) { - DEBUGOUT("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - /* Save word 0 in upper half of part_num */ - *part_num = (uint32_t) (eeprom_data << 16); - - /* Get word 1 from EEPROM */ - if(e1000_read_eeprom(hw, ++offset, 1, &eeprom_data) < 0) { - DEBUGOUT("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - /* Save word 1 in lower half of part_num */ - *part_num |= eeprom_data; - - return E1000_SUCCESS; -} - -/****************************************************************************** - * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the - * second function of dual function devices - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -int32_t -e1000_read_mac_addr(struct e1000_hw * hw) -{ - uint16_t offset; - uint16_t eeprom_data, i; - - DEBUGFUNC("e1000_read_mac_addr"); - - for(i = 0; i < NODE_ADDRESS_SIZE; i += 2) { - offset = i >> 1; - if(e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) { - DEBUGOUT("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF); - hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8); - } - if(((hw->mac_type == e1000_82546) || (hw->mac_type == e1000_82546_rev_3)) && - (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { - if(hw->perm_mac_addr[5] & 0x01) - hw->perm_mac_addr[5] &= ~(0x01); - else - hw->perm_mac_addr[5] |= 0x01; - } - for(i = 0; i < NODE_ADDRESS_SIZE; i++) - hw->mac_addr[i] = hw->perm_mac_addr[i]; - return E1000_SUCCESS; -} - -/****************************************************************************** - * Initializes receive address filters. - * - * hw - Struct containing variables accessed by shared code - * - * Places the MAC address in receive address register 0 and clears the rest - * of the receive addresss registers. Clears the multicast table. Assumes - * the receiver is in reset when the routine is called. - *****************************************************************************/ -void -e1000_init_rx_addrs(struct e1000_hw *hw) -{ - uint32_t i; - uint32_t addr_low; - uint32_t addr_high; - - DEBUGFUNC("e1000_init_rx_addrs"); - - /* Setup the receive address. */ - DEBUGOUT("Programming MAC Address into RAR[0]\n"); - addr_low = (hw->mac_addr[0] | - (hw->mac_addr[1] << 8) | - (hw->mac_addr[2] << 16) | (hw->mac_addr[3] << 24)); - - addr_high = (hw->mac_addr[4] | - (hw->mac_addr[5] << 8) | E1000_RAH_AV); - - E1000_WRITE_REG_ARRAY(hw, RA, 0, addr_low); - E1000_WRITE_REG_ARRAY(hw, RA, 1, addr_high); - - /* Zero out the other 15 receive addresses. */ - DEBUGOUT("Clearing RAR[1-15]\n"); - for(i = 1; i < E1000_RAR_ENTRIES; i++) { - E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0); - E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0); - } -} - -/****************************************************************************** - * Updates the MAC's list of multicast addresses. - * - * hw - Struct containing variables accessed by shared code - * mc_addr_list - the list of new multicast addresses - * mc_addr_count - number of addresses - * pad - number of bytes between addresses in the list - * - * The given list replaces any existing list. Clears the last 15 receive - * address registers and the multicast table. Uses receive address registers - * for the first 15 multicast addresses, and hashes the rest into the - * multicast table. - *****************************************************************************/ -void -e1000_mc_addr_list_update(struct e1000_hw *hw, - uint8_t *mc_addr_list, - uint32_t mc_addr_count, - uint32_t pad) -{ - uint32_t hash_value; - uint32_t i; - uint32_t rar_used_count = 1; /* RAR[0] is used for our MAC address */ - - DEBUGFUNC("e1000_mc_addr_list_update"); - - /* Set the new number of MC addresses that we are being requested to use. */ - hw->num_mc_addrs = mc_addr_count; - - /* Clear RAR[1-15] */ - DEBUGOUT(" Clearing RAR[1-15]\n"); - for(i = rar_used_count; i < E1000_RAR_ENTRIES; i++) { - E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0); - E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0); - } - - /* Clear the MTA */ - DEBUGOUT(" Clearing MTA\n"); - for(i = 0; i < E1000_NUM_MTA_REGISTERS; i++) { - E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); - } - - /* Add the new addresses */ - for(i = 0; i < mc_addr_count; i++) { - DEBUGOUT(" Adding the multicast addresses:\n"); - DEBUGOUT7(" MC Addr #%d =%.2X %.2X %.2X %.2X %.2X %.2X\n", i, - mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad)], - mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 1], - mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 2], - mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 3], - mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 4], - mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 5]); - - hash_value = e1000_hash_mc_addr(hw, - mc_addr_list + - (i * (ETH_LENGTH_OF_ADDRESS + pad))); - - DEBUGOUT1(" Hash value = 0x%03X\n", hash_value); - - /* Place this multicast address in the RAR if there is room, * - * else put it in the MTA - */ - if(rar_used_count < E1000_RAR_ENTRIES) { - e1000_rar_set(hw, - mc_addr_list + (i * (ETH_LENGTH_OF_ADDRESS + pad)), - rar_used_count); - rar_used_count++; - } else { - e1000_mta_set(hw, hash_value); - } - } - DEBUGOUT("MC Update Complete\n"); -} - -/****************************************************************************** - * Hashes an address to determine its location in the multicast table - * - * hw - Struct containing variables accessed by shared code - * mc_addr - the multicast address to hash - *****************************************************************************/ -uint32_t -e1000_hash_mc_addr(struct e1000_hw *hw, - uint8_t *mc_addr) -{ - uint32_t hash_value = 0; - - /* The portion of the address that is used for the hash table is - * determined by the mc_filter_type setting. - */ - switch (hw->mc_filter_type) { - /* [0] [1] [2] [3] [4] [5] - * 01 AA 00 12 34 56 - * LSB MSB - */ - case 0: - /* [47:36] i.e. 0x563 for above example address */ - hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4)); - break; - case 1: - /* [46:35] i.e. 0xAC6 for above example address */ - hash_value = ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5)); - break; - case 2: - /* [45:34] i.e. 0x5D8 for above example address */ - hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6)); - break; - case 3: - /* [43:32] i.e. 0x634 for above example address */ - hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8)); - break; - } - - hash_value &= 0xFFF; - return hash_value; -} - -/****************************************************************************** - * Sets the bit in the multicast table corresponding to the hash value. - * - * hw - Struct containing variables accessed by shared code - * hash_value - Multicast address hash value - *****************************************************************************/ -void -e1000_mta_set(struct e1000_hw *hw, - uint32_t hash_value) -{ - uint32_t hash_bit, hash_reg; - uint32_t mta; - uint32_t temp; - - /* The MTA is a register array of 128 32-bit registers. - * It is treated like an array of 4096 bits. We want to set - * bit BitArray[hash_value]. So we figure out what register - * the bit is in, read it, OR in the new bit, then write - * back the new value. The register is determined by the - * upper 7 bits of the hash value and the bit within that - * register are determined by the lower 5 bits of the value. - */ - hash_reg = (hash_value >> 5) & 0x7F; - hash_bit = hash_value & 0x1F; - - mta = E1000_READ_REG_ARRAY(hw, MTA, hash_reg); - - mta |= (1 << hash_bit); - - /* If we are on an 82544 and we are trying to write an odd offset - * in the MTA, save off the previous entry before writing and - * restore the old value after writing. - */ - if((hw->mac_type == e1000_82544) && ((hash_reg & 0x1) == 1)) { - temp = E1000_READ_REG_ARRAY(hw, MTA, (hash_reg - 1)); - E1000_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta); - E1000_WRITE_REG_ARRAY(hw, MTA, (hash_reg - 1), temp); - } else { - E1000_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta); - } -} - -/****************************************************************************** - * Puts an ethernet address into a receive address register. - * - * hw - Struct containing variables accessed by shared code - * addr - Address to put into receive address register - * index - Receive address register to write - *****************************************************************************/ -void -e1000_rar_set(struct e1000_hw *hw, - uint8_t *addr, - uint32_t index) -{ - uint32_t rar_low, rar_high; - - /* HW expects these in little endian so we reverse the byte order - * from network order (big endian) to little endian - */ - rar_low = ((uint32_t) addr[0] | - ((uint32_t) addr[1] << 8) | - ((uint32_t) addr[2] << 16) | ((uint32_t) addr[3] << 24)); - - rar_high = ((uint32_t) addr[4] | ((uint32_t) addr[5] << 8) | E1000_RAH_AV); - - E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low); - E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high); -} - -/****************************************************************************** - * Writes a value to the specified offset in the VLAN filter table. - * - * hw - Struct containing variables accessed by shared code - * offset - Offset in VLAN filer table to write - * value - Value to write into VLAN filter table - *****************************************************************************/ -void -e1000_write_vfta(struct e1000_hw *hw, - uint32_t offset, - uint32_t value) -{ - uint32_t temp; - - if((hw->mac_type == e1000_82544) && ((offset & 0x1) == 1)) { - temp = E1000_READ_REG_ARRAY(hw, VFTA, (offset - 1)); - E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value); - E1000_WRITE_REG_ARRAY(hw, VFTA, (offset - 1), temp); - } else { - E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value); - } -} - -/****************************************************************************** - * Clears the VLAN filer table - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -void -e1000_clear_vfta(struct e1000_hw *hw) -{ - uint32_t offset; - - for(offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) - E1000_WRITE_REG_ARRAY(hw, VFTA, offset, 0); -} - -static int32_t -e1000_id_led_init(struct e1000_hw * hw) -{ - uint32_t ledctl; - const uint32_t ledctl_mask = 0x000000FF; - const uint32_t ledctl_on = E1000_LEDCTL_MODE_LED_ON; - const uint32_t ledctl_off = E1000_LEDCTL_MODE_LED_OFF; - uint16_t eeprom_data, i, temp; - const uint16_t led_mask = 0x0F; - - DEBUGFUNC("e1000_id_led_init"); - - if(hw->mac_type < e1000_82540) { - /* Nothing to do */ - return E1000_SUCCESS; - } - - ledctl = E1000_READ_REG(hw, LEDCTL); - hw->ledctl_default = ledctl; - hw->ledctl_mode1 = hw->ledctl_default; - hw->ledctl_mode2 = hw->ledctl_default; - - if(e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, 1, &eeprom_data) < 0) { - DEBUGOUT("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - if((eeprom_data== ID_LED_RESERVED_0000) || - (eeprom_data == ID_LED_RESERVED_FFFF)) eeprom_data = ID_LED_DEFAULT; - for(i = 0; i < 4; i++) { - temp = (eeprom_data >> (i << 2)) & led_mask; - switch(temp) { - case ID_LED_ON1_DEF2: - case ID_LED_ON1_ON2: - case ID_LED_ON1_OFF2: - hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); - hw->ledctl_mode1 |= ledctl_on << (i << 3); - break; - case ID_LED_OFF1_DEF2: - case ID_LED_OFF1_ON2: - case ID_LED_OFF1_OFF2: - hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); - hw->ledctl_mode1 |= ledctl_off << (i << 3); - break; - default: - /* Do nothing */ - break; - } - switch(temp) { - case ID_LED_DEF1_ON2: - case ID_LED_ON1_ON2: - case ID_LED_OFF1_ON2: - hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); - hw->ledctl_mode2 |= ledctl_on << (i << 3); - break; - case ID_LED_DEF1_OFF2: - case ID_LED_ON1_OFF2: - case ID_LED_OFF1_OFF2: - hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); - hw->ledctl_mode2 |= ledctl_off << (i << 3); - break; - default: - /* Do nothing */ - break; - } - } - return E1000_SUCCESS; -} - -/****************************************************************************** - * Prepares SW controlable LED for use and saves the current state of the LED. - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -int32_t -e1000_setup_led(struct e1000_hw *hw) -{ - uint32_t ledctl; - int32_t ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_setup_led"); - - switch(hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - case e1000_82544: - /* No setup necessary */ - break; - case e1000_82541: - case e1000_82547: - case e1000_82541_rev_2: - case e1000_82547_rev_2: - /* Turn off PHY Smart Power Down (if enabled) */ - if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, - &hw->phy_spd_default))) - return ret_val; - if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, - (uint16_t)(hw->phy_spd_default & - ~IGP01E1000_GMII_SPD)))) - return ret_val; - /* Fall Through */ - default: - if(hw->media_type == e1000_media_type_fiber) { - ledctl = E1000_READ_REG(hw, LEDCTL); - /* Save current LEDCTL settings */ - hw->ledctl_default = ledctl; - /* Turn off LED0 */ - ledctl &= ~(E1000_LEDCTL_LED0_IVRT | - E1000_LEDCTL_LED0_BLINK | - E1000_LEDCTL_LED0_MODE_MASK); - ledctl |= (E1000_LEDCTL_MODE_LED_OFF << - E1000_LEDCTL_LED0_MODE_SHIFT); - E1000_WRITE_REG(hw, LEDCTL, ledctl); - } else if(hw->media_type == e1000_media_type_copper) - E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); - break; - } - - return E1000_SUCCESS; -} - -/****************************************************************************** - * Restores the saved state of the SW controlable LED. - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -int32_t -e1000_cleanup_led(struct e1000_hw *hw) -{ - int32_t ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_cleanup_led"); - - switch(hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - case e1000_82544: - /* No cleanup necessary */ - break; - case e1000_82541: - case e1000_82547: - case e1000_82541_rev_2: - case e1000_82547_rev_2: - /* Turn on PHY Smart Power Down (if previously enabled) */ - if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, - hw->phy_spd_default))) - return ret_val; - /* Fall Through */ - default: - /* Restore LEDCTL settings */ - E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_default); - break; - } - - return E1000_SUCCESS; -} - -/****************************************************************************** - * Turns on the software controllable LED - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -int32_t -e1000_led_on(struct e1000_hw *hw) -{ - uint32_t ctrl = E1000_READ_REG(hw, CTRL); - - DEBUGFUNC("e1000_led_on"); - - switch(hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - /* Set SW Defineable Pin 0 to turn on the LED */ - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - break; - case e1000_82544: - if(hw->media_type == e1000_media_type_fiber) { - /* Set SW Defineable Pin 0 to turn on the LED */ - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } else { - /* Clear SW Defineable Pin 0 to turn on the LED */ - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } - break; - default: - if(hw->media_type == e1000_media_type_fiber) { - /* Clear SW Defineable Pin 0 to turn on the LED */ - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } else if(hw->media_type == e1000_media_type_copper) { - E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2); - return E1000_SUCCESS; - } - break; - } - - E1000_WRITE_REG(hw, CTRL, ctrl); - - return E1000_SUCCESS; -} - -/****************************************************************************** - * Turns off the software controllable LED - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -int32_t -e1000_led_off(struct e1000_hw *hw) -{ - uint32_t ctrl = E1000_READ_REG(hw, CTRL); - - DEBUGFUNC("e1000_led_off"); - - switch(hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - /* Clear SW Defineable Pin 0 to turn off the LED */ - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - break; - case e1000_82544: - if(hw->media_type == e1000_media_type_fiber) { - /* Clear SW Defineable Pin 0 to turn off the LED */ - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } else { - /* Set SW Defineable Pin 0 to turn off the LED */ - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } - break; - default: - if(hw->media_type == e1000_media_type_fiber) { - /* Set SW Defineable Pin 0 to turn off the LED */ - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } else if(hw->media_type == e1000_media_type_copper) { - E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); - return E1000_SUCCESS; - } - break; - } - - E1000_WRITE_REG(hw, CTRL, ctrl); - - return E1000_SUCCESS; -} - -/****************************************************************************** - * Clears all hardware statistics counters. - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -void -e1000_clear_hw_cntrs(struct e1000_hw *hw) -{ - volatile uint32_t temp; - - temp = E1000_READ_REG(hw, CRCERRS); - temp = E1000_READ_REG(hw, SYMERRS); - temp = E1000_READ_REG(hw, MPC); - temp = E1000_READ_REG(hw, SCC); - temp = E1000_READ_REG(hw, ECOL); - temp = E1000_READ_REG(hw, MCC); - temp = E1000_READ_REG(hw, LATECOL); - temp = E1000_READ_REG(hw, COLC); - temp = E1000_READ_REG(hw, DC); - temp = E1000_READ_REG(hw, SEC); - temp = E1000_READ_REG(hw, RLEC); - temp = E1000_READ_REG(hw, XONRXC); - temp = E1000_READ_REG(hw, XONTXC); - temp = E1000_READ_REG(hw, XOFFRXC); - temp = E1000_READ_REG(hw, XOFFTXC); - temp = E1000_READ_REG(hw, FCRUC); - temp = E1000_READ_REG(hw, PRC64); - temp = E1000_READ_REG(hw, PRC127); - temp = E1000_READ_REG(hw, PRC255); - temp = E1000_READ_REG(hw, PRC511); - temp = E1000_READ_REG(hw, PRC1023); - temp = E1000_READ_REG(hw, PRC1522); - temp = E1000_READ_REG(hw, GPRC); - temp = E1000_READ_REG(hw, BPRC); - temp = E1000_READ_REG(hw, MPRC); - temp = E1000_READ_REG(hw, GPTC); - temp = E1000_READ_REG(hw, GORCL); - temp = E1000_READ_REG(hw, GORCH); - temp = E1000_READ_REG(hw, GOTCL); - temp = E1000_READ_REG(hw, GOTCH); - temp = E1000_READ_REG(hw, RNBC); - temp = E1000_READ_REG(hw, RUC); - temp = E1000_READ_REG(hw, RFC); - temp = E1000_READ_REG(hw, ROC); - temp = E1000_READ_REG(hw, RJC); - temp = E1000_READ_REG(hw, TORL); - temp = E1000_READ_REG(hw, TORH); - temp = E1000_READ_REG(hw, TOTL); - temp = E1000_READ_REG(hw, TOTH); - temp = E1000_READ_REG(hw, TPR); - temp = E1000_READ_REG(hw, TPT); - temp = E1000_READ_REG(hw, PTC64); - temp = E1000_READ_REG(hw, PTC127); - temp = E1000_READ_REG(hw, PTC255); - temp = E1000_READ_REG(hw, PTC511); - temp = E1000_READ_REG(hw, PTC1023); - temp = E1000_READ_REG(hw, PTC1522); - temp = E1000_READ_REG(hw, MPTC); - temp = E1000_READ_REG(hw, BPTC); - - if(hw->mac_type < e1000_82543) return; - - temp = E1000_READ_REG(hw, ALGNERRC); - temp = E1000_READ_REG(hw, RXERRC); - temp = E1000_READ_REG(hw, TNCRS); - temp = E1000_READ_REG(hw, CEXTERR); - temp = E1000_READ_REG(hw, TSCTC); - temp = E1000_READ_REG(hw, TSCTFC); - - if(hw->mac_type <= e1000_82544) return; - - temp = E1000_READ_REG(hw, MGTPRC); - temp = E1000_READ_REG(hw, MGTPDC); - temp = E1000_READ_REG(hw, MGTPTC); -} - -/****************************************************************************** - * Resets Adaptive IFS to its default state. - * - * hw - Struct containing variables accessed by shared code - * - * Call this after e1000_init_hw. You may override the IFS defaults by setting - * hw->ifs_params_forced to TRUE. However, you must initialize hw-> - * current_ifs_val, ifs_min_val, ifs_max_val, ifs_step_size, and ifs_ratio - * before calling this function. - *****************************************************************************/ -void -e1000_reset_adaptive(struct e1000_hw *hw) -{ - DEBUGFUNC("e1000_reset_adaptive"); - - if(hw->adaptive_ifs) { - if(!hw->ifs_params_forced) { - hw->current_ifs_val = 0; - hw->ifs_min_val = IFS_MIN; - hw->ifs_max_val = IFS_MAX; - hw->ifs_step_size = IFS_STEP; - hw->ifs_ratio = IFS_RATIO; - } - hw->in_ifs_mode = FALSE; - E1000_WRITE_REG(hw, AIT, 0); - } else { - DEBUGOUT("Not in Adaptive IFS mode!\n"); - } -} - -/****************************************************************************** - * Called during the callback/watchdog routine to update IFS value based on - * the ratio of transmits to collisions. - * - * hw - Struct containing variables accessed by shared code - * tx_packets - Number of transmits since last callback - * total_collisions - Number of collisions since last callback - *****************************************************************************/ -void -e1000_update_adaptive(struct e1000_hw *hw) -{ - DEBUGFUNC("e1000_update_adaptive"); - - if(hw->adaptive_ifs) { - if((hw->collision_delta * hw->ifs_ratio) > hw->tx_packet_delta) { - if(hw->tx_packet_delta > MIN_NUM_XMITS) { - hw->in_ifs_mode = TRUE; - if(hw->current_ifs_val < hw->ifs_max_val) { - if(hw->current_ifs_val == 0) - hw->current_ifs_val = hw->ifs_min_val; - else - hw->current_ifs_val += hw->ifs_step_size; - E1000_WRITE_REG(hw, AIT, hw->current_ifs_val); - } - } - } else { - if(hw->in_ifs_mode && (hw->tx_packet_delta <= MIN_NUM_XMITS)) { - hw->current_ifs_val = 0; - hw->in_ifs_mode = FALSE; - E1000_WRITE_REG(hw, AIT, 0); - } - } - } else { - DEBUGOUT("Not in Adaptive IFS mode!\n"); - } -} - -/****************************************************************************** - * Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT - * - * hw - Struct containing variables accessed by shared code - * frame_len - The length of the frame in question - * mac_addr - The Ethernet destination address of the frame in question - *****************************************************************************/ -void -e1000_tbi_adjust_stats(struct e1000_hw *hw, - struct e1000_hw_stats *stats, - uint32_t frame_len, - uint8_t *mac_addr) -{ - uint64_t carry_bit; - - /* First adjust the frame length. */ - frame_len--; - /* We need to adjust the statistics counters, since the hardware - * counters overcount this packet as a CRC error and undercount - * the packet as a good packet - */ - /* This packet should not be counted as a CRC error. */ - stats->crcerrs--; - /* This packet does count as a Good Packet Received. */ - stats->gprc++; - - /* Adjust the Good Octets received counters */ - carry_bit = 0x80000000 & stats->gorcl; - stats->gorcl += frame_len; - /* If the high bit of Gorcl (the low 32 bits of the Good Octets - * Received Count) was one before the addition, - * AND it is zero after, then we lost the carry out, - * need to add one to Gorch (Good Octets Received Count High). - * This could be simplified if all environments supported - * 64-bit integers. - */ - if(carry_bit && ((stats->gorcl & 0x80000000) == 0)) - stats->gorch++; - /* Is this a broadcast or multicast? Check broadcast first, - * since the test for a multicast frame will test positive on - * a broadcast frame. - */ - if((mac_addr[0] == (uint8_t) 0xff) && (mac_addr[1] == (uint8_t) 0xff)) - /* Broadcast packet */ - stats->bprc++; - else if(*mac_addr & 0x01) - /* Multicast packet */ - stats->mprc++; - - if(frame_len == hw->max_frame_size) { - /* In this case, the hardware has overcounted the number of - * oversize frames. - */ - if(stats->roc > 0) - stats->roc--; - } - - /* Adjust the bin counters when the extra byte put the frame in the - * wrong bin. Remember that the frame_len was adjusted above. - */ - if(frame_len == 64) { - stats->prc64++; - stats->prc127--; - } else if(frame_len == 127) { - stats->prc127++; - stats->prc255--; - } else if(frame_len == 255) { - stats->prc255++; - stats->prc511--; - } else if(frame_len == 511) { - stats->prc511++; - stats->prc1023--; - } else if(frame_len == 1023) { - stats->prc1023++; - stats->prc1522--; - } else if(frame_len == 1522) { - stats->prc1522++; - } -} - -/****************************************************************************** - * Gets the current PCI bus type, speed, and width of the hardware - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -void -e1000_get_bus_info(struct e1000_hw *hw) -{ - uint32_t status; - - if(hw->mac_type < e1000_82543) { - hw->bus_type = e1000_bus_type_unknown; - hw->bus_speed = e1000_bus_speed_unknown; - hw->bus_width = e1000_bus_width_unknown; - return; - } - - status = E1000_READ_REG(hw, STATUS); - hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ? - e1000_bus_type_pcix : e1000_bus_type_pci; - - if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) { - hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ? - e1000_bus_speed_66 : e1000_bus_speed_120; - } else if(hw->bus_type == e1000_bus_type_pci) { - hw->bus_speed = (status & E1000_STATUS_PCI66) ? - e1000_bus_speed_66 : e1000_bus_speed_33; - } else { - switch (status & E1000_STATUS_PCIX_SPEED) { - case E1000_STATUS_PCIX_SPEED_66: - hw->bus_speed = e1000_bus_speed_66; - break; - case E1000_STATUS_PCIX_SPEED_100: - hw->bus_speed = e1000_bus_speed_100; - break; - case E1000_STATUS_PCIX_SPEED_133: - hw->bus_speed = e1000_bus_speed_133; - break; - default: - hw->bus_speed = e1000_bus_speed_reserved; - break; - } - } - hw->bus_width = (status & E1000_STATUS_BUS64) ? - e1000_bus_width_64 : e1000_bus_width_32; -} -/****************************************************************************** - * Reads a value from one of the devices registers using port I/O (as opposed - * memory mapped I/O). Only 82544 and newer devices support port I/O. - * - * hw - Struct containing variables accessed by shared code - * offset - offset to read from - *****************************************************************************/ -uint32_t -e1000_read_reg_io(struct e1000_hw *hw, - uint32_t offset) -{ - uint32_t io_addr = hw->io_base; - uint32_t io_data = hw->io_base + 4; - - e1000_io_write(hw, io_addr, offset); - return e1000_io_read(hw, io_data); -} - -/****************************************************************************** - * Writes a value to one of the devices registers using port I/O (as opposed to - * memory mapped I/O). Only 82544 and newer devices support port I/O. - * - * hw - Struct containing variables accessed by shared code - * offset - offset to write to - * value - value to write - *****************************************************************************/ -void -e1000_write_reg_io(struct e1000_hw *hw, - uint32_t offset, - uint32_t value) -{ - uint32_t io_addr = hw->io_base; - uint32_t io_data = hw->io_base + 4; - - e1000_io_write(hw, io_addr, offset); - e1000_io_write(hw, io_data, value); -} - - -/****************************************************************************** - * Estimates the cable length. - * - * hw - Struct containing variables accessed by shared code - * min_length - The estimated minimum length - * max_length - The estimated maximum length - * - * returns: - E1000_ERR_XXX - * E1000_SUCCESS - * - * This function always returns a ranged length (minimum & maximum). - * So for M88 phy's, this function interprets the one value returned from the - * register to the minimum and maximum range. - * For IGP phy's, the function calculates the range by the AGC registers. - *****************************************************************************/ -int32_t -e1000_get_cable_length(struct e1000_hw *hw, - uint16_t *min_length, - uint16_t *max_length) -{ - int32_t ret_val; - uint16_t agc_value = 0; - uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE; - uint16_t i, phy_data; - - DEBUGFUNC("e1000_get_cable_length"); - - *min_length = *max_length = 0; - - /* Use old method for Phy older than IGP */ - if(hw->phy_type == e1000_phy_m88) { - if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, - &phy_data))) - return ret_val; - - /* Convert the enum value to ranged values */ - switch((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> - M88E1000_PSSR_CABLE_LENGTH_SHIFT) { - case e1000_cable_length_50: - *min_length = 0; - *max_length = e1000_igp_cable_length_50; - break; - case e1000_cable_length_50_80: - *min_length = e1000_igp_cable_length_50; - *max_length = e1000_igp_cable_length_80; - break; - case e1000_cable_length_80_110: - *min_length = e1000_igp_cable_length_80; - *max_length = e1000_igp_cable_length_110; - break; - case e1000_cable_length_110_140: - *min_length = e1000_igp_cable_length_110; - *max_length = e1000_igp_cable_length_140; - break; - case e1000_cable_length_140: - *min_length = e1000_igp_cable_length_140; - *max_length = e1000_igp_cable_length_170; - break; - default: - return -E1000_ERR_PHY; - break; - } - } else if(hw->phy_type == e1000_phy_igp) { /* For IGP PHY */ - uint16_t agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = - {IGP01E1000_PHY_AGC_A, - IGP01E1000_PHY_AGC_B, - IGP01E1000_PHY_AGC_C, - IGP01E1000_PHY_AGC_D}; - /* Read the AGC registers for all channels */ - for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { - - if((ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data))) - return ret_val; - - cur_agc = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT; - - /* Array bound check. */ - if((cur_agc >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) || - (cur_agc == 0)) - return -E1000_ERR_PHY; - - agc_value += cur_agc; - - /* Update minimal AGC value. */ - if(min_agc > cur_agc) - min_agc = cur_agc; - } - - /* Remove the minimal AGC result for length < 50m */ - if(agc_value < IGP01E1000_PHY_CHANNEL_NUM * e1000_igp_cable_length_50) { - agc_value -= min_agc; - - /* Get the average length of the remaining 3 channels */ - agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1); - } else { - /* Get the average length of all the 4 channels. */ - agc_value /= IGP01E1000_PHY_CHANNEL_NUM; - } - - /* Set the range of the calculated length. */ - *min_length = ((e1000_igp_cable_length_table[agc_value] - - IGP01E1000_AGC_RANGE) > 0) ? - (e1000_igp_cable_length_table[agc_value] - - IGP01E1000_AGC_RANGE) : 0; - *max_length = e1000_igp_cable_length_table[agc_value] + - IGP01E1000_AGC_RANGE; - } - - return E1000_SUCCESS; -} - -/****************************************************************************** - * Check the cable polarity - * - * hw - Struct containing variables accessed by shared code - * polarity - output parameter : 0 - Polarity is not reversed - * 1 - Polarity is reversed. - * - * returns: - E1000_ERR_XXX - * E1000_SUCCESS - * - * For phy's older then IGP, this function simply reads the polarity bit in the - * Phy Status register. For IGP phy's, this bit is valid only if link speed is - * 10 Mbps. If the link speed is 100 Mbps there is no polarity so this bit will - * return 0. If the link speed is 1000 Mbps the polarity status is in the - * IGP01E1000_PHY_PCS_INIT_REG. - *****************************************************************************/ -int32_t -e1000_check_polarity(struct e1000_hw *hw, - uint16_t *polarity) -{ - int32_t ret_val; - uint16_t phy_data; - - DEBUGFUNC("e1000_check_polarity"); - - if(hw->phy_type == e1000_phy_m88) { - /* return the Polarity bit in the Status register. */ - if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, - &phy_data))) - return ret_val; - *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >> - M88E1000_PSSR_REV_POLARITY_SHIFT; - } else if(hw->phy_type == e1000_phy_igp) { - /* Read the Status register to check the speed */ - if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, - &phy_data))) - return ret_val; - - /* If speed is 1000 Mbps, must read the IGP01E1000_PHY_PCS_INIT_REG to - * find the polarity status */ - if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) { - - /* Read the GIG initialization PCS register (0x00B4) */ - if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG, - &phy_data))) - return ret_val; - - /* Check the polarity bits */ - *polarity = (phy_data & IGP01E1000_PHY_POLARITY_MASK) ? 1 : 0; - } else { - /* For 10 Mbps, read the polarity bit in the status register. (for - * 100 Mbps this bit is always 0) */ - *polarity = phy_data & IGP01E1000_PSSR_POLARITY_REVERSED; - } - } - return E1000_SUCCESS; -} - -/****************************************************************************** - * Check if Downshift occured - * - * hw - Struct containing variables accessed by shared code - * downshift - output parameter : 0 - No Downshift ocured. - * 1 - Downshift ocured. - * - * returns: - E1000_ERR_XXX - * E1000_SUCCESS - * - * For phy's older then IGP, this function reads the Downshift bit in the Phy - * Specific Status register. For IGP phy's, it reads the Downgrade bit in the - * Link Health register. In IGP this bit is latched high, so the driver must - * read it immediately after link is established. - *****************************************************************************/ -int32_t -e1000_check_downshift(struct e1000_hw *hw) -{ - int32_t ret_val; - uint16_t phy_data; - - DEBUGFUNC("e1000_check_downshift"); - - if(hw->phy_type == e1000_phy_igp) { - if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH, - &phy_data))) - return ret_val; - - hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0; - } - else if(hw->phy_type == e1000_phy_m88) { - if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, - &phy_data))) - return ret_val; - - hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >> - M88E1000_PSSR_DOWNSHIFT_SHIFT; - } - return E1000_SUCCESS; -} - -/***************************************************************************** - * - * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a - * gigabit link is achieved to improve link quality. - * - * hw: Struct containing variables accessed by shared code - * - * returns: - E1000_ERR_PHY if fail to read/write the PHY - * E1000_SUCCESS at any other case. - * - ****************************************************************************/ - -int32_t -e1000_config_dsp_after_link_change(struct e1000_hw *hw, - boolean_t link_up) -{ - int32_t ret_val; - uint16_t phy_data, speed, duplex, i; - uint16_t dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = - {IGP01E1000_PHY_AGC_PARAM_A, - IGP01E1000_PHY_AGC_PARAM_B, - IGP01E1000_PHY_AGC_PARAM_C, - IGP01E1000_PHY_AGC_PARAM_D}; - uint16_t min_length, max_length; - - DEBUGFUNC("e1000_config_dsp_after_link_change"); - - if(hw->phy_type != e1000_phy_igp) - return E1000_SUCCESS; - - if(link_up) { - if((ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex))) { - DEBUGOUT("Error getting link speed and duplex\n"); - return ret_val; - } - - if(speed == SPEED_1000) { - - e1000_get_cable_length(hw, &min_length, &max_length); - - if((hw->dsp_config_state == e1000_dsp_config_enabled) && - min_length >= e1000_igp_cable_length_50) { - - for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { - if((ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i], - &phy_data))) - return ret_val; - - phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; - - if((ret_val = e1000_write_phy_reg(hw, dsp_reg_array[i], - phy_data))) - return ret_val; - } - hw->dsp_config_state = e1000_dsp_config_activated; - } - - if((hw->ffe_config_state == e1000_ffe_config_enabled) && - (min_length < e1000_igp_cable_length_50)) { - - uint16_t ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20; - uint32_t idle_errs = 0; - - /* clear previous idle error counts */ - if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, - &phy_data))) - return ret_val; - - for(i = 0; i < ffe_idle_err_timeout; i++) { - usec_delay(1000); - if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, - &phy_data))) - return ret_val; - - idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT); - if(idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) { - hw->ffe_config_state = e1000_ffe_config_active; - - if((ret_val = e1000_write_phy_reg(hw, - IGP01E1000_PHY_DSP_FFE, - IGP01E1000_PHY_DSP_FFE_CM_CP))) - return ret_val; - break; - } - - if(idle_errs) - ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_100; - } - } - } - } else { - if(hw->dsp_config_state == e1000_dsp_config_activated) { - if((ret_val = e1000_write_phy_reg(hw, 0x0000, - IGP01E1000_IEEE_FORCE_GIGA))) - return ret_val; - for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { - if((ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i], - &phy_data))) - return ret_val; - - phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; - phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS; - - if((ret_val = e1000_write_phy_reg(hw,dsp_reg_array[i], - phy_data))) - return ret_val; - } - - if((ret_val = e1000_write_phy_reg(hw, 0x0000, - IGP01E1000_IEEE_RESTART_AUTONEG))) - return ret_val; - - hw->dsp_config_state = e1000_dsp_config_enabled; - } - - if(hw->ffe_config_state == e1000_ffe_config_active) { - if((ret_val = e1000_write_phy_reg(hw, 0x0000, - IGP01E1000_IEEE_FORCE_GIGA))) - return ret_val; - if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE, - IGP01E1000_PHY_DSP_FFE_DEFAULT))) - return ret_val; - - if((ret_val = e1000_write_phy_reg(hw, 0x0000, - IGP01E1000_IEEE_RESTART_AUTONEG))) - return ret_val; - hw->ffe_config_state = e1000_ffe_config_enabled; - } - } - return E1000_SUCCESS; -} - -/*************************************************************************** - * - * Workaround for the 82547 long TTL on noisy 100HD hubs. - * - * This function, specific to 82547 hardware only, needs to be called every - * second. It checks if a parallel detect fault has occurred. If a fault - * occurred, disable/enable the DSP reset mechanism up to 5 times (once per - * second). If link is established, stop the workaround and ensure the DSP - * reset is enabled. - * - * hw: Struct containing variables accessed by shared code - * - * returns: - E1000_ERR_PHY if fail to read/write the PHY - * E1000_SUCCESS in any other case - * - ****************************************************************************/ -int32_t -e1000_igp_ttl_workaround(struct e1000_hw *hw) -{ - int32_t ret_val; - uint16_t phy_data = 0; - uint16_t dsp_value = DSP_RESET_ENABLE; - - if(((hw->mac_type != e1000_82541) && (hw->mac_type != e1000_82547)) || - (!hw->ttl_wa_activation)) { - return E1000_SUCCESS; - } - - /* Check for link first */ - if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) - return ret_val; - - if(phy_data & MII_SR_LINK_STATUS) { - /* If link is established during the workaround, the DSP mechanism must - * be enabled. */ - if(hw->dsp_reset_counter) { - hw->dsp_reset_counter = 0; - dsp_value = DSP_RESET_ENABLE; - } else - return E1000_SUCCESS; - } else { - if(hw->dsp_reset_counter == 0) { - /* Workaround not activated, check if it needs activation */ - if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data))) - return ret_val; - /* Activate the workaround if there was a parallel detect fault */ - if(phy_data & NWAY_ER_PAR_DETECT_FAULT) - hw->dsp_reset_counter++; - else - return E1000_SUCCESS; - } - - if(hw->dsp_reset_counter) { - /* After 5 times, stop the workaround */ - if(hw->dsp_reset_counter > E1000_MAX_DSP_RESETS) { - hw->dsp_reset_counter = 0; - dsp_value = DSP_RESET_ENABLE; - } else { - dsp_value = (hw->dsp_reset_counter & 1) ? DSP_RESET_DISABLE : - DSP_RESET_ENABLE; - hw->dsp_reset_counter++; - } - } - } - - if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_DSP_RESET, dsp_value))) - return ret_val; - - return E1000_SUCCESS; -} - -/***************************************************************************** - * - * This function sets the lplu state according to the active flag. When - * activating lplu this function also disables smart speed and vise versa. - * lplu will not be activated unless the device autonegotiation advertisment - * meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes. - * hw: Struct containing variables accessed by shared code - * active - true to enable lplu false to disable lplu. - * - * returns: - E1000_ERR_PHY if fail to read/write the PHY - * E1000_SUCCESS at any other case. - * - ****************************************************************************/ - -int32_t -e1000_set_d3_lplu_state(struct e1000_hw *hw, - boolean_t active) -{ - int32_t ret_val; - uint16_t phy_data; - DEBUGFUNC("e1000_set_d3_lplu_state"); - - if(!((hw->mac_type == e1000_82541_rev_2) || - (hw->mac_type == e1000_82547_rev_2))) - return E1000_SUCCESS; - - /* During driver activity LPLU should not be used or it will attain link - * from the lowest speeds starting from 10Mbps. The capability is used for - * Dx transitions and states */ - if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data))) - return ret_val; - - if(!active) { - phy_data &= ~IGP01E1000_GMII_FLEX_SPD; - if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data))) - return ret_val; - - /* LPLU and SmartSpeed are mutually exclusive. LPLU is used during - * Dx states where the power conservation is most important. During - * driver activity we should enable SmartSpeed, so performance is - * maintained. */ - if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - &phy_data))) - return ret_val; - - phy_data |= IGP01E1000_PSCFR_SMART_SPEED; - if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - phy_data))) - return ret_val; - - } else if((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) || - (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL ) || - (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) { - - phy_data |= IGP01E1000_GMII_FLEX_SPD; - if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data))) - return ret_val; - - /* When LPLU is enabled we should disable SmartSpeed */ - if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - &phy_data))) - return ret_val; - - phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; - if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - phy_data))) - return ret_val; - - } - return E1000_SUCCESS; -} - -/****************************************************************************** - * Change VCO speed register to improve Bit Error Rate performance of SERDES. - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -static int32_t -e1000_set_vco_speed(struct e1000_hw *hw) -{ - int32_t ret_val; - uint16_t default_page = 0; - uint16_t phy_data; - - DEBUGFUNC("e1000_set_vco_speed"); - - switch(hw->mac_type) { - case e1000_82545_rev_3: - case e1000_82546_rev_3: - break; - default: - return E1000_SUCCESS; - } - - /* Set PHY register 30, page 5, bit 8 to 0 */ - - if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, - &default_page))) - return ret_val; - - if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005))) - return ret_val; - - if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data))) - return ret_val; - - phy_data &= ~M88E1000_PHY_VCO_REG_BIT8; - if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data))) - return ret_val; - - /* Set PHY register 30, page 4, bit 11 to 1 */ - - if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004))) - return ret_val; - - if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data))) - return ret_val; - - phy_data |= M88E1000_PHY_VCO_REG_BIT11; - if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data))) - return ret_val; - - if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, - default_page))) - return ret_val; - - return E1000_SUCCESS; -} - diff --git a/xen/drivers/net/e1000/e1000_hw.h b/xen/drivers/net/e1000/e1000_hw.h deleted file mode 100644 index 4976a3c084..0000000000 --- a/xen/drivers/net/e1000/e1000_hw.h +++ /dev/null @@ -1,2121 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* e1000_hw.h - * Structures, enums, and macros for the MAC - */ - -#ifndef _E1000_HW_H_ -#define _E1000_HW_H_ - -#include "e1000_osdep.h" - - -/* Forward declarations of structures used by the shared code */ -struct e1000_hw; -struct e1000_hw_stats; - -/* Enumerated types specific to the e1000 hardware */ -/* Media Access Controlers */ -typedef enum { - e1000_undefined = 0, - e1000_82542_rev2_0, - e1000_82542_rev2_1, - e1000_82543, - e1000_82544, - e1000_82540, - e1000_82545, - e1000_82545_rev_3, - e1000_82546, - e1000_82546_rev_3, - e1000_82541, - e1000_82541_rev_2, - e1000_82547, - e1000_82547_rev_2, - e1000_num_macs -} e1000_mac_type; - -typedef enum { - e1000_eeprom_uninitialized = 0, - e1000_eeprom_spi, - e1000_eeprom_microwire, - e1000_num_eeprom_types -} e1000_eeprom_type; - -/* Media Types */ -typedef enum { - e1000_media_type_copper = 0, - e1000_media_type_fiber = 1, - e1000_media_type_internal_serdes = 2, - e1000_num_media_types -} e1000_media_type; - -typedef enum { - e1000_10_half = 0, - e1000_10_full = 1, - e1000_100_half = 2, - e1000_100_full = 3 -} e1000_speed_duplex_type; - -/* Flow Control Settings */ -typedef enum { - e1000_fc_none = 0, - e1000_fc_rx_pause = 1, - e1000_fc_tx_pause = 2, - e1000_fc_full = 3, - e1000_fc_default = 0xFF -} e1000_fc_type; - -/* PCI bus types */ -typedef enum { - e1000_bus_type_unknown = 0, - e1000_bus_type_pci, - e1000_bus_type_pcix, - e1000_bus_type_reserved -} e1000_bus_type; - -/* PCI bus speeds */ -typedef enum { - e1000_bus_speed_unknown = 0, - e1000_bus_speed_33, - e1000_bus_speed_66, - e1000_bus_speed_100, - e1000_bus_speed_120, - e1000_bus_speed_133, - e1000_bus_speed_reserved -} e1000_bus_speed; - -/* PCI bus widths */ -typedef enum { - e1000_bus_width_unknown = 0, - e1000_bus_width_32, - e1000_bus_width_64, - e1000_bus_width_reserved -} e1000_bus_width; - -/* PHY status info structure and supporting enums */ -typedef enum { - e1000_cable_length_50 = 0, - e1000_cable_length_50_80, - e1000_cable_length_80_110, - e1000_cable_length_110_140, - e1000_cable_length_140, - e1000_cable_length_undefined = 0xFF -} e1000_cable_length; - -typedef enum { - e1000_igp_cable_length_10 = 10, - e1000_igp_cable_length_20 = 20, - e1000_igp_cable_length_30 = 30, - e1000_igp_cable_length_40 = 40, - e1000_igp_cable_length_50 = 50, - e1000_igp_cable_length_60 = 60, - e1000_igp_cable_length_70 = 70, - e1000_igp_cable_length_80 = 80, - e1000_igp_cable_length_90 = 90, - e1000_igp_cable_length_100 = 100, - e1000_igp_cable_length_110 = 110, - e1000_igp_cable_length_120 = 120, - e1000_igp_cable_length_130 = 130, - e1000_igp_cable_length_140 = 140, - e1000_igp_cable_length_150 = 150, - e1000_igp_cable_length_160 = 160, - e1000_igp_cable_length_170 = 170, - e1000_igp_cable_length_180 = 180 -} e1000_igp_cable_length; - -typedef enum { - e1000_10bt_ext_dist_enable_normal = 0, - e1000_10bt_ext_dist_enable_lower, - e1000_10bt_ext_dist_enable_undefined = 0xFF -} e1000_10bt_ext_dist_enable; - -typedef enum { - e1000_rev_polarity_normal = 0, - e1000_rev_polarity_reversed, - e1000_rev_polarity_undefined = 0xFF -} e1000_rev_polarity; - -typedef enum { - e1000_downshift_normal = 0, - e1000_downshift_activated, - e1000_downshift_undefined = 0xFF -} e1000_downshift; - -typedef enum { - e1000_polarity_reversal_enabled = 0, - e1000_polarity_reversal_disabled, - e1000_polarity_reversal_undefined = 0xFF -} e1000_polarity_reversal; - -typedef enum { - e1000_auto_x_mode_manual_mdi = 0, - e1000_auto_x_mode_manual_mdix, - e1000_auto_x_mode_auto1, - e1000_auto_x_mode_auto2, - e1000_auto_x_mode_undefined = 0xFF -} e1000_auto_x_mode; - -typedef enum { - e1000_1000t_rx_status_not_ok = 0, - e1000_1000t_rx_status_ok, - e1000_1000t_rx_status_undefined = 0xFF -} e1000_1000t_rx_status; - -typedef enum { - e1000_phy_m88 = 0, - e1000_phy_igp, - e1000_phy_undefined = 0xFF -} e1000_phy_type; - -typedef enum { - e1000_ms_hw_default = 0, - e1000_ms_force_master, - e1000_ms_force_slave, - e1000_ms_auto -} e1000_ms_type; - -typedef enum { - e1000_ffe_config_enabled = 0, - e1000_ffe_config_active, - e1000_ffe_config_blocked -} e1000_ffe_config; - -typedef enum { - e1000_dsp_config_disabled = 0, - e1000_dsp_config_enabled, - e1000_dsp_config_activated, - e1000_dsp_config_undefined = 0xFF -} e1000_dsp_config; - -struct e1000_phy_info { - e1000_cable_length cable_length; - e1000_10bt_ext_dist_enable extended_10bt_distance; - e1000_rev_polarity cable_polarity; - e1000_downshift downshift; - e1000_polarity_reversal polarity_correction; - e1000_auto_x_mode mdix_mode; - e1000_1000t_rx_status local_rx; - e1000_1000t_rx_status remote_rx; -}; - -struct e1000_phy_stats { - uint32_t idle_errors; - uint32_t receive_errors; -}; - -struct e1000_eeprom_info { - e1000_eeprom_type type; - uint16_t word_size; - uint16_t opcode_bits; - uint16_t address_bits; - uint16_t delay_usec; - uint16_t page_size; -}; - - - -/* Error Codes */ -#define E1000_SUCCESS 0 -#define E1000_ERR_EEPROM 1 -#define E1000_ERR_PHY 2 -#define E1000_ERR_CONFIG 3 -#define E1000_ERR_PARAM 4 -#define E1000_ERR_MAC_TYPE 5 -#define E1000_ERR_PHY_TYPE 6 - -/* Function prototypes */ -/* Initialization */ -int32_t e1000_reset_hw(struct e1000_hw *hw); -int32_t e1000_init_hw(struct e1000_hw *hw); -int32_t e1000_set_mac_type(struct e1000_hw *hw); -void e1000_set_media_type(struct e1000_hw *hw); - -/* Link Configuration */ -int32_t e1000_setup_link(struct e1000_hw *hw); -int32_t e1000_phy_setup_autoneg(struct e1000_hw *hw); -void e1000_config_collision_dist(struct e1000_hw *hw); -int32_t e1000_config_fc_after_link_up(struct e1000_hw *hw); -int32_t e1000_check_for_link(struct e1000_hw *hw); -int32_t e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t * speed, uint16_t * duplex); -int32_t e1000_wait_autoneg(struct e1000_hw *hw); -int32_t e1000_force_mac_fc(struct e1000_hw *hw); - -/* PHY */ -int32_t e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy_data); -int32_t e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data); -void e1000_phy_hw_reset(struct e1000_hw *hw); -int32_t e1000_phy_reset(struct e1000_hw *hw); -int32_t e1000_detect_gig_phy(struct e1000_hw *hw); -int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info); -int32_t e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info); -int32_t e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info); -int32_t e1000_get_cable_length(struct e1000_hw *hw, uint16_t *min_length, uint16_t *max_length); -int32_t e1000_check_polarity(struct e1000_hw *hw, uint16_t *polarity); -int32_t e1000_check_downshift(struct e1000_hw *hw); -int32_t e1000_validate_mdi_setting(struct e1000_hw *hw); - -/* EEPROM Functions */ -void e1000_init_eeprom_params(struct e1000_hw *hw); -int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data); -int32_t e1000_validate_eeprom_checksum(struct e1000_hw *hw); -int32_t e1000_update_eeprom_checksum(struct e1000_hw *hw); -int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data); -int32_t e1000_read_part_num(struct e1000_hw *hw, uint32_t * part_num); -int32_t e1000_read_mac_addr(struct e1000_hw * hw); - -/* Filters (multicast, vlan, receive) */ -void e1000_init_rx_addrs(struct e1000_hw *hw); -void e1000_mc_addr_list_update(struct e1000_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad); -uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, uint8_t * mc_addr); -void e1000_mta_set(struct e1000_hw *hw, uint32_t hash_value); -void e1000_rar_set(struct e1000_hw *hw, uint8_t * mc_addr, uint32_t rar_index); -void e1000_write_vfta(struct e1000_hw *hw, uint32_t offset, uint32_t value); -void e1000_clear_vfta(struct e1000_hw *hw); - -/* LED functions */ -int32_t e1000_setup_led(struct e1000_hw *hw); -int32_t e1000_cleanup_led(struct e1000_hw *hw); -int32_t e1000_led_on(struct e1000_hw *hw); -int32_t e1000_led_off(struct e1000_hw *hw); - -/* Adaptive IFS Functions */ - -/* Everything else */ -void e1000_clear_hw_cntrs(struct e1000_hw *hw); -void e1000_reset_adaptive(struct e1000_hw *hw); -void e1000_update_adaptive(struct e1000_hw *hw); -void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats, uint32_t frame_len, uint8_t * mac_addr); -void e1000_get_bus_info(struct e1000_hw *hw); -void e1000_pci_set_mwi(struct e1000_hw *hw); -void e1000_pci_clear_mwi(struct e1000_hw *hw); -void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value); -void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value); -/* Port I/O is only supported on 82544 and newer */ -uint32_t e1000_io_read(struct e1000_hw *hw, uint32_t port); -uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset); -void e1000_io_write(struct e1000_hw *hw, uint32_t port, uint32_t value); -void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value); -int32_t e1000_config_dsp_after_link_change(struct e1000_hw *hw, boolean_t link_up); -int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active); -int32_t e1000_igp_ttl_workaround(struct e1000_hw *hw); - -#define E1000_READ_REG_IO(a, reg) \ - e1000_read_reg_io((a), E1000_##reg) -#define E1000_WRITE_REG_IO(a, reg, val) \ - e1000_write_reg_io((a), E1000_##reg, val) - -/* PCI Device IDs */ -#define E1000_DEV_ID_82542 0x1000 -#define E1000_DEV_ID_82543GC_FIBER 0x1001 -#define E1000_DEV_ID_82543GC_COPPER 0x1004 -#define E1000_DEV_ID_82544EI_COPPER 0x1008 -#define E1000_DEV_ID_82544EI_FIBER 0x1009 -#define E1000_DEV_ID_82544GC_COPPER 0x100C -#define E1000_DEV_ID_82544GC_LOM 0x100D -#define E1000_DEV_ID_82540EM 0x100E -#define E1000_DEV_ID_82540EM_LOM 0x1015 -#define E1000_DEV_ID_82540EP_LOM 0x1016 -#define E1000_DEV_ID_82540EP 0x1017 -#define E1000_DEV_ID_82540EP_LP 0x101E -#define E1000_DEV_ID_82545EM_COPPER 0x100F -#define E1000_DEV_ID_82545EM_FIBER 0x1011 -#define E1000_DEV_ID_82545GM_COPPER 0x1026 -#define E1000_DEV_ID_82545GM_FIBER 0x1027 -#define E1000_DEV_ID_82545GM_SERDES 0x1028 -#define E1000_DEV_ID_82546EB_COPPER 0x1010 -#define E1000_DEV_ID_82546EB_FIBER 0x1012 -#define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D -#define E1000_DEV_ID_82541EI 0x1013 -#define E1000_DEV_ID_82541EI_MOBILE 0x1018 -#define E1000_DEV_ID_82541ER 0x1078 -#define E1000_DEV_ID_82547GI 0x1075 -#define E1000_DEV_ID_82541GI 0x1076 -#define E1000_DEV_ID_82541GI_MOBILE 0x1077 -#define E1000_DEV_ID_82546GB_COPPER 0x1079 -#define E1000_DEV_ID_82546GB_FIBER 0x107A -#define E1000_DEV_ID_82546GB_SERDES 0x107B -#define E1000_DEV_ID_82547EI 0x1019 - -#define NODE_ADDRESS_SIZE 6 -#define ETH_LENGTH_OF_ADDRESS 6 - -/* MAC decode size is 128K - This is the size of BAR0 */ -#define MAC_DECODE_SIZE (128 * 1024) - -#define E1000_82542_2_0_REV_ID 2 -#define E1000_82542_2_1_REV_ID 3 - -#define SPEED_10 10 -#define SPEED_100 100 -#define SPEED_1000 1000 -#define HALF_DUPLEX 1 -#define FULL_DUPLEX 2 - -/* The sizes (in bytes) of a ethernet packet */ -#define ENET_HEADER_SIZE 14 -#define MAXIMUM_ETHERNET_FRAME_SIZE 1518 /* With FCS */ -#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* With FCS */ -#define ETHERNET_FCS_SIZE 4 -#define MAXIMUM_ETHERNET_PACKET_SIZE \ - (MAXIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE) -#define MINIMUM_ETHERNET_PACKET_SIZE \ - (MINIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE) -#define CRC_LENGTH ETHERNET_FCS_SIZE -#define MAX_JUMBO_FRAME_SIZE 0x3F00 - - -/* 802.1q VLAN Packet Sizes */ -#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMAed) */ - -/* Ethertype field values */ -#define ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.3ac packet */ -#define ETHERNET_IP_TYPE 0x0800 /* IP packets */ -#define ETHERNET_ARP_TYPE 0x0806 /* Address Resolution Protocol (ARP) */ - -/* Packet Header defines */ -#define IP_PROTOCOL_TCP 6 -#define IP_PROTOCOL_UDP 0x11 - -/* This defines the bits that are set in the Interrupt Mask - * Set/Read Register. Each bit is documented below: - * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) - * o RXSEQ = Receive Sequence Error - */ -#define POLL_IMS_ENABLE_MASK ( \ - E1000_IMS_RXDMT0 | \ - E1000_IMS_RXSEQ) - -/* This defines the bits that are set in the Interrupt Mask - * Set/Read Register. Each bit is documented below: - * o RXT0 = Receiver Timer Interrupt (ring 0) - * o TXDW = Transmit Descriptor Written Back - * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) - * o RXSEQ = Receive Sequence Error - * o LSC = Link Status Change - */ -#define IMS_ENABLE_MASK ( \ - E1000_IMS_RXT0 | \ - E1000_IMS_TXDW | \ - E1000_IMS_RXDMT0 | \ - E1000_IMS_RXSEQ | \ - E1000_IMS_LSC) - -/* Number of high/low register pairs in the RAR. The RAR (Receive Address - * Registers) holds the directed and multicast addresses that we monitor. We - * reserve one of these spots for our directed address, allowing us room for - * E1000_RAR_ENTRIES - 1 multicast addresses. - */ -#define E1000_RAR_ENTRIES 15 - -#define MIN_NUMBER_OF_DESCRIPTORS 8 -#define MAX_NUMBER_OF_DESCRIPTORS 0xFFF8 - -/* Receive Descriptor */ -struct e1000_rx_desc { - uint64_t buffer_addr; /* Address of the descriptor's data buffer */ - uint16_t length; /* Length of data DMAed into data buffer */ - uint16_t csum; /* Packet checksum */ - uint8_t status; /* Descriptor status */ - uint8_t errors; /* Descriptor Errors */ - uint16_t special; -}; - -/* Receive Decriptor bit definitions */ -#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */ -#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */ -#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */ -#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ -#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ -#define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */ -#define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */ -#define E1000_RXD_ERR_CE 0x01 /* CRC Error */ -#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ -#define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ -#define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */ -#define E1000_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */ -#define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */ -#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */ -#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ -#define E1000_RXD_SPC_PRI_MASK 0xE000 /* Priority is in upper 3 bits */ -#define E1000_RXD_SPC_PRI_SHIFT 0x000D /* Priority is in upper 3 of 16 */ -#define E1000_RXD_SPC_CFI_MASK 0x1000 /* CFI is bit 12 */ -#define E1000_RXD_SPC_CFI_SHIFT 0x000C /* CFI is bit 12 */ - -/* mask to determine if packets should be dropped due to frame errors */ -#define E1000_RXD_ERR_FRAME_ERR_MASK ( \ - E1000_RXD_ERR_CE | \ - E1000_RXD_ERR_SE | \ - E1000_RXD_ERR_SEQ | \ - E1000_RXD_ERR_CXE | \ - E1000_RXD_ERR_RXE) - -/* Transmit Descriptor */ -struct e1000_tx_desc { - uint64_t buffer_addr; /* Address of the descriptor's data buffer */ - union { - uint32_t data; - struct { - uint16_t length; /* Data buffer length */ - uint8_t cso; /* Checksum offset */ - uint8_t cmd; /* Descriptor control */ - } flags; - } lower; - union { - uint32_t data; - struct { - uint8_t status; /* Descriptor status */ - uint8_t css; /* Checksum start */ - uint16_t special; - } fields; - } upper; -}; - -/* Transmit Descriptor bit definitions */ -#define E1000_TXD_DTYP_D 0x00100000 /* Data Descriptor */ -#define E1000_TXD_DTYP_C 0x00000000 /* Context Descriptor */ -#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */ -#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */ -#define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */ -#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ -#define E1000_TXD_CMD_IC 0x04000000 /* Insert Checksum */ -#define E1000_TXD_CMD_RS 0x08000000 /* Report Status */ -#define E1000_TXD_CMD_RPS 0x10000000 /* Report Packet Sent */ -#define E1000_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */ -#define E1000_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */ -#define E1000_TXD_CMD_IDE 0x80000000 /* Enable Tidv register */ -#define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */ -#define E1000_TXD_STAT_EC 0x00000002 /* Excess Collisions */ -#define E1000_TXD_STAT_LC 0x00000004 /* Late Collisions */ -#define E1000_TXD_STAT_TU 0x00000008 /* Transmit underrun */ -#define E1000_TXD_CMD_TCP 0x01000000 /* TCP packet */ -#define E1000_TXD_CMD_IP 0x02000000 /* IP packet */ -#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ -#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */ - -/* Offload Context Descriptor */ -struct e1000_context_desc { - union { - uint32_t ip_config; - struct { - uint8_t ipcss; /* IP checksum start */ - uint8_t ipcso; /* IP checksum offset */ - uint16_t ipcse; /* IP checksum end */ - } ip_fields; - } lower_setup; - union { - uint32_t tcp_config; - struct { - uint8_t tucss; /* TCP checksum start */ - uint8_t tucso; /* TCP checksum offset */ - uint16_t tucse; /* TCP checksum end */ - } tcp_fields; - } upper_setup; - uint32_t cmd_and_length; /* */ - union { - uint32_t data; - struct { - uint8_t status; /* Descriptor status */ - uint8_t hdr_len; /* Header length */ - uint16_t mss; /* Maximum segment size */ - } fields; - } tcp_seg_setup; -}; - -/* Offload data descriptor */ -struct e1000_data_desc { - uint64_t buffer_addr; /* Address of the descriptor's buffer address */ - union { - uint32_t data; - struct { - uint16_t length; /* Data buffer length */ - uint8_t typ_len_ext; /* */ - uint8_t cmd; /* */ - } flags; - } lower; - union { - uint32_t data; - struct { - uint8_t status; /* Descriptor status */ - uint8_t popts; /* Packet Options */ - uint16_t special; /* */ - } fields; - } upper; -}; - -/* Filters */ -#define E1000_NUM_UNICAST 16 /* Unicast filter entries */ -#define E1000_MC_TBL_SIZE 128 /* Multicast Filter Table (4096 bits) */ -#define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ - - -/* Receive Address Register */ -struct e1000_rar { - volatile uint32_t low; /* receive address low */ - volatile uint32_t high; /* receive address high */ -}; - -/* Number of entries in the Multicast Table Array (MTA). */ -#define E1000_NUM_MTA_REGISTERS 128 - -/* IPv4 Address Table Entry */ -struct e1000_ipv4_at_entry { - volatile uint32_t ipv4_addr; /* IP Address (RW) */ - volatile uint32_t reserved; -}; - -/* Four wakeup IP addresses are supported */ -#define E1000_WAKEUP_IP_ADDRESS_COUNT_MAX 4 -#define E1000_IP4AT_SIZE E1000_WAKEUP_IP_ADDRESS_COUNT_MAX -#define E1000_IP6AT_SIZE 1 - -/* IPv6 Address Table Entry */ -struct e1000_ipv6_at_entry { - volatile uint8_t ipv6_addr[16]; -}; - -/* Flexible Filter Length Table Entry */ -struct e1000_fflt_entry { - volatile uint32_t length; /* Flexible Filter Length (RW) */ - volatile uint32_t reserved; -}; - -/* Flexible Filter Mask Table Entry */ -struct e1000_ffmt_entry { - volatile uint32_t mask; /* Flexible Filter Mask (RW) */ - volatile uint32_t reserved; -}; - -/* Flexible Filter Value Table Entry */ -struct e1000_ffvt_entry { - volatile uint32_t value; /* Flexible Filter Value (RW) */ - volatile uint32_t reserved; -}; - -/* Four Flexible Filters are supported */ -#define E1000_FLEXIBLE_FILTER_COUNT_MAX 4 - -/* Each Flexible Filter is at most 128 (0x80) bytes in length */ -#define E1000_FLEXIBLE_FILTER_SIZE_MAX 128 - -#define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX -#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX -#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX - -/* Register Set. (82543, 82544) - * - * Registers are defined to be 32 bits and should be accessed as 32 bit values. - * These registers are physically located on the NIC, but are mapped into the - * host memory address space. - * - * RW - register is both readable and writable - * RO - register is read only - * WO - register is write only - * R/clr - register is read only and is cleared when read - * A - register array - */ -#define E1000_CTRL 0x00000 /* Device Control - RW */ -#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */ -#define E1000_STATUS 0x00008 /* Device Status - RO */ -#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ -#define E1000_EERD 0x00014 /* EEPROM Read - RW */ -#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ -#define E1000_FLA 0x0001C /* Flash Access - RW */ -#define E1000_MDIC 0x00020 /* MDI Control - RW */ -#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ -#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ -#define E1000_FCT 0x00030 /* Flow Control Type - RW */ -#define E1000_VET 0x00038 /* VLAN Ether Type - RW */ -#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */ -#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */ -#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ -#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ -#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ -#define E1000_RCTL 0x00100 /* RX Control - RW */ -#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ -#define E1000_TXCW 0x00178 /* TX Configuration Word - RW */ -#define E1000_RXCW 0x00180 /* RX Configuration Word - RO */ -#define E1000_TCTL 0x00400 /* TX Control - RW */ -#define E1000_TIPG 0x00410 /* TX Inter-packet gap -RW */ -#define E1000_TBT 0x00448 /* TX Burst Timer - RW */ -#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ -#define E1000_LEDCTL 0x00E00 /* LED Control - RW */ -#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ -#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ -#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ -#define E1000_RDBAL 0x02800 /* RX Descriptor Base Address Low - RW */ -#define E1000_RDBAH 0x02804 /* RX Descriptor Base Address High - RW */ -#define E1000_RDLEN 0x02808 /* RX Descriptor Length - RW */ -#define E1000_RDH 0x02810 /* RX Descriptor Head - RW */ -#define E1000_RDT 0x02818 /* RX Descriptor Tail - RW */ -#define E1000_RDTR 0x02820 /* RX Delay Timer - RW */ -#define E1000_RXDCTL 0x02828 /* RX Descriptor Control - RW */ -#define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */ -#define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */ -#define E1000_TXDMAC 0x03000 /* TX DMA Control - RW */ -#define E1000_TDFH 0x03410 /* TX Data FIFO Head - RW */ -#define E1000_TDFT 0x03418 /* TX Data FIFO Tail - RW */ -#define E1000_TDFHS 0x03420 /* TX Data FIFO Head Saved - RW */ -#define E1000_TDFTS 0x03428 /* TX Data FIFO Tail Saved - RW */ -#define E1000_TDFPC 0x03430 /* TX Data FIFO Packet Count - RW */ -#define E1000_TDBAL 0x03800 /* TX Descriptor Base Address Low - RW */ -#define E1000_TDBAH 0x03804 /* TX Descriptor Base Address High - RW */ -#define E1000_TDLEN 0x03808 /* TX Descriptor Length - RW */ -#define E1000_TDH 0x03810 /* TX Descriptor Head - RW */ -#define E1000_TDT 0x03818 /* TX Descripotr Tail - RW */ -#define E1000_TIDV 0x03820 /* TX Interrupt Delay Value - RW */ -#define E1000_TXDCTL 0x03828 /* TX Descriptor Control - RW */ -#define E1000_TADV 0x0382C /* TX Interrupt Absolute Delay Val - RW */ -#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */ -#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */ -#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ -#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */ -#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */ -#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */ -#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */ -#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */ -#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */ -#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */ -#define E1000_COLC 0x04028 /* Collision Count - R/clr */ -#define E1000_DC 0x04030 /* Defer Count - R/clr */ -#define E1000_TNCRS 0x04034 /* TX-No CRS - R/clr */ -#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */ -#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */ -#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */ -#define E1000_XONRXC 0x04048 /* XON RX Count - R/clr */ -#define E1000_XONTXC 0x0404C /* XON TX Count - R/clr */ -#define E1000_XOFFRXC 0x04050 /* XOFF RX Count - R/clr */ -#define E1000_XOFFTXC 0x04054 /* XOFF TX Count - R/clr */ -#define E1000_FCRUC 0x04058 /* Flow Control RX Unsupported Count- R/clr */ -#define E1000_PRC64 0x0405C /* Packets RX (64 bytes) - R/clr */ -#define E1000_PRC127 0x04060 /* Packets RX (65-127 bytes) - R/clr */ -#define E1000_PRC255 0x04064 /* Packets RX (128-255 bytes) - R/clr */ -#define E1000_PRC511 0x04068 /* Packets RX (255-511 bytes) - R/clr */ -#define E1000_PRC1023 0x0406C /* Packets RX (512-1023 bytes) - R/clr */ -#define E1000_PRC1522 0x04070 /* Packets RX (1024-1522 bytes) - R/clr */ -#define E1000_GPRC 0x04074 /* Good Packets RX Count - R/clr */ -#define E1000_BPRC 0x04078 /* Broadcast Packets RX Count - R/clr */ -#define E1000_MPRC 0x0407C /* Multicast Packets RX Count - R/clr */ -#define E1000_GPTC 0x04080 /* Good Packets TX Count - R/clr */ -#define E1000_GORCL 0x04088 /* Good Octets RX Count Low - R/clr */ -#define E1000_GORCH 0x0408C /* Good Octets RX Count High - R/clr */ -#define E1000_GOTCL 0x04090 /* Good Octets TX Count Low - R/clr */ -#define E1000_GOTCH 0x04094 /* Good Octets TX Count High - R/clr */ -#define E1000_RNBC 0x040A0 /* RX No Buffers Count - R/clr */ -#define E1000_RUC 0x040A4 /* RX Undersize Count - R/clr */ -#define E1000_RFC 0x040A8 /* RX Fragment Count - R/clr */ -#define E1000_ROC 0x040AC /* RX Oversize Count - R/clr */ -#define E1000_RJC 0x040B0 /* RX Jabber Count - R/clr */ -#define E1000_MGTPRC 0x040B4 /* Management Packets RX Count - R/clr */ -#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */ -#define E1000_MGTPTC 0x040BC /* Management Packets TX Count - R/clr */ -#define E1000_TORL 0x040C0 /* Total Octets RX Low - R/clr */ -#define E1000_TORH 0x040C4 /* Total Octets RX High - R/clr */ -#define E1000_TOTL 0x040C8 /* Total Octets TX Low - R/clr */ -#define E1000_TOTH 0x040CC /* Total Octets TX High - R/clr */ -#define E1000_TPR 0x040D0 /* Total Packets RX - R/clr */ -#define E1000_TPT 0x040D4 /* Total Packets TX - R/clr */ -#define E1000_PTC64 0x040D8 /* Packets TX (64 bytes) - R/clr */ -#define E1000_PTC127 0x040DC /* Packets TX (65-127 bytes) - R/clr */ -#define E1000_PTC255 0x040E0 /* Packets TX (128-255 bytes) - R/clr */ -#define E1000_PTC511 0x040E4 /* Packets TX (256-511 bytes) - R/clr */ -#define E1000_PTC1023 0x040E8 /* Packets TX (512-1023 bytes) - R/clr */ -#define E1000_PTC1522 0x040EC /* Packets TX (1024-1522 Bytes) - R/clr */ -#define E1000_MPTC 0x040F0 /* Multicast Packets TX Count - R/clr */ -#define E1000_BPTC 0x040F4 /* Broadcast Packets TX Count - R/clr */ -#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context TX - R/clr */ -#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context TX Fail - R/clr */ -#define E1000_RXCSUM 0x05000 /* RX Checksum Control - RW */ -#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */ -#define E1000_RA 0x05400 /* Receive Address - RW Array */ -#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */ -#define E1000_WUC 0x05800 /* Wakeup Control - RW */ -#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */ -#define E1000_WUS 0x05810 /* Wakeup Status - RO */ -#define E1000_MANC 0x05820 /* Management Control - RW */ -#define E1000_IPAV 0x05838 /* IP Address Valid - RW */ -#define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */ -#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */ -#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */ -#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */ -#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */ -#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */ -#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */ - -/* Register Set (82542) - * - * Some of the 82542 registers are located at different offsets than they are - * in more current versions of the 8254x. Despite the difference in location, - * the registers function in the same manner. - */ -#define E1000_82542_CTRL E1000_CTRL -#define E1000_82542_CTRL_DUP E1000_CTRL_DUP -#define E1000_82542_STATUS E1000_STATUS -#define E1000_82542_EECD E1000_EECD -#define E1000_82542_EERD E1000_EERD -#define E1000_82542_CTRL_EXT E1000_CTRL_EXT -#define E1000_82542_FLA E1000_FLA -#define E1000_82542_MDIC E1000_MDIC -#define E1000_82542_FCAL E1000_FCAL -#define E1000_82542_FCAH E1000_FCAH -#define E1000_82542_FCT E1000_FCT -#define E1000_82542_VET E1000_VET -#define E1000_82542_RA 0x00040 -#define E1000_82542_ICR E1000_ICR -#define E1000_82542_ITR E1000_ITR -#define E1000_82542_ICS E1000_ICS -#define E1000_82542_IMS E1000_IMS -#define E1000_82542_IMC E1000_IMC -#define E1000_82542_RCTL E1000_RCTL -#define E1000_82542_RDTR 0x00108 -#define E1000_82542_RDBAL 0x00110 -#define E1000_82542_RDBAH 0x00114 -#define E1000_82542_RDLEN 0x00118 -#define E1000_82542_RDH 0x00120 -#define E1000_82542_RDT 0x00128 -#define E1000_82542_FCRTH 0x00160 -#define E1000_82542_FCRTL 0x00168 -#define E1000_82542_FCTTV E1000_FCTTV -#define E1000_82542_TXCW E1000_TXCW -#define E1000_82542_RXCW E1000_RXCW -#define E1000_82542_MTA 0x00200 -#define E1000_82542_TCTL E1000_TCTL -#define E1000_82542_TIPG E1000_TIPG -#define E1000_82542_TDBAL 0x00420 -#define E1000_82542_TDBAH 0x00424 -#define E1000_82542_TDLEN 0x00428 -#define E1000_82542_TDH 0x00430 -#define E1000_82542_TDT 0x00438 -#define E1000_82542_TIDV 0x00440 -#define E1000_82542_TBT E1000_TBT -#define E1000_82542_AIT E1000_AIT -#define E1000_82542_VFTA 0x00600 -#define E1000_82542_LEDCTL E1000_LEDCTL -#define E1000_82542_PBA E1000_PBA -#define E1000_82542_RXDCTL E1000_RXDCTL -#define E1000_82542_RADV E1000_RADV -#define E1000_82542_RSRPD E1000_RSRPD -#define E1000_82542_TXDMAC E1000_TXDMAC -#define E1000_82542_TDFHS E1000_TDFHS -#define E1000_82542_TDFTS E1000_TDFTS -#define E1000_82542_TDFPC E1000_TDFPC -#define E1000_82542_TXDCTL E1000_TXDCTL -#define E1000_82542_TADV E1000_TADV -#define E1000_82542_TSPMT E1000_TSPMT -#define E1000_82542_CRCERRS E1000_CRCERRS -#define E1000_82542_ALGNERRC E1000_ALGNERRC -#define E1000_82542_SYMERRS E1000_SYMERRS -#define E1000_82542_RXERRC E1000_RXERRC -#define E1000_82542_MPC E1000_MPC -#define E1000_82542_SCC E1000_SCC -#define E1000_82542_ECOL E1000_ECOL -#define E1000_82542_MCC E1000_MCC -#define E1000_82542_LATECOL E1000_LATECOL -#define E1000_82542_COLC E1000_COLC -#define E1000_82542_DC E1000_DC -#define E1000_82542_TNCRS E1000_TNCRS -#define E1000_82542_SEC E1000_SEC -#define E1000_82542_CEXTERR E1000_CEXTERR -#define E1000_82542_RLEC E1000_RLEC -#define E1000_82542_XONRXC E1000_XONRXC -#define E1000_82542_XONTXC E1000_XONTXC -#define E1000_82542_XOFFRXC E1000_XOFFRXC -#define E1000_82542_XOFFTXC E1000_XOFFTXC -#define E1000_82542_FCRUC E1000_FCRUC -#define E1000_82542_PRC64 E1000_PRC64 -#define E1000_82542_PRC127 E1000_PRC127 -#define E1000_82542_PRC255 E1000_PRC255 -#define E1000_82542_PRC511 E1000_PRC511 -#define E1000_82542_PRC1023 E1000_PRC1023 -#define E1000_82542_PRC1522 E1000_PRC1522 -#define E1000_82542_GPRC E1000_GPRC -#define E1000_82542_BPRC E1000_BPRC -#define E1000_82542_MPRC E1000_MPRC -#define E1000_82542_GPTC E1000_GPTC -#define E1000_82542_GORCL E1000_GORCL -#define E1000_82542_GORCH E1000_GORCH -#define E1000_82542_GOTCL E1000_GOTCL -#define E1000_82542_GOTCH E1000_GOTCH -#define E1000_82542_RNBC E1000_RNBC -#define E1000_82542_RUC E1000_RUC -#define E1000_82542_RFC E1000_RFC -#define E1000_82542_ROC E1000_ROC -#define E1000_82542_RJC E1000_RJC -#define E1000_82542_MGTPRC E1000_MGTPRC -#define E1000_82542_MGTPDC E1000_MGTPDC -#define E1000_82542_MGTPTC E1000_MGTPTC -#define E1000_82542_TORL E1000_TORL -#define E1000_82542_TORH E1000_TORH -#define E1000_82542_TOTL E1000_TOTL -#define E1000_82542_TOTH E1000_TOTH -#define E1000_82542_TPR E1000_TPR -#define E1000_82542_TPT E1000_TPT -#define E1000_82542_PTC64 E1000_PTC64 -#define E1000_82542_PTC127 E1000_PTC127 -#define E1000_82542_PTC255 E1000_PTC255 -#define E1000_82542_PTC511 E1000_PTC511 -#define E1000_82542_PTC1023 E1000_PTC1023 -#define E1000_82542_PTC1522 E1000_PTC1522 -#define E1000_82542_MPTC E1000_MPTC -#define E1000_82542_BPTC E1000_BPTC -#define E1000_82542_TSCTC E1000_TSCTC -#define E1000_82542_TSCTFC E1000_TSCTFC -#define E1000_82542_RXCSUM E1000_RXCSUM -#define E1000_82542_WUC E1000_WUC -#define E1000_82542_WUFC E1000_WUFC -#define E1000_82542_WUS E1000_WUS -#define E1000_82542_MANC E1000_MANC -#define E1000_82542_IPAV E1000_IPAV -#define E1000_82542_IP4AT E1000_IP4AT -#define E1000_82542_IP6AT E1000_IP6AT -#define E1000_82542_WUPL E1000_WUPL -#define E1000_82542_WUPM E1000_WUPM -#define E1000_82542_FFLT E1000_FFLT -#define E1000_82542_TDFH 0x08010 -#define E1000_82542_TDFT 0x08018 -#define E1000_82542_FFMT E1000_FFMT -#define E1000_82542_FFVT E1000_FFVT - -/* Statistics counters collected by the MAC */ -struct e1000_hw_stats { - uint64_t crcerrs; - uint64_t algnerrc; - uint64_t symerrs; - uint64_t rxerrc; - uint64_t mpc; - uint64_t scc; - uint64_t ecol; - uint64_t mcc; - uint64_t latecol; - uint64_t colc; - uint64_t dc; - uint64_t tncrs; - uint64_t sec; - uint64_t cexterr; - uint64_t rlec; - uint64_t xonrxc; - uint64_t xontxc; - uint64_t xoffrxc; - uint64_t xofftxc; - uint64_t fcruc; - uint64_t prc64; - uint64_t prc127; - uint64_t prc255; - uint64_t prc511; - uint64_t prc1023; - uint64_t prc1522; - uint64_t gprc; - uint64_t bprc; - uint64_t mprc; - uint64_t gptc; - uint64_t gorcl; - uint64_t gorch; - uint64_t gotcl; - uint64_t gotch; - uint64_t rnbc; - uint64_t ruc; - uint64_t rfc; - uint64_t roc; - uint64_t rjc; - uint64_t mgprc; - uint64_t mgpdc; - uint64_t mgptc; - uint64_t torl; - uint64_t torh; - uint64_t totl; - uint64_t toth; - uint64_t tpr; - uint64_t tpt; - uint64_t ptc64; - uint64_t ptc127; - uint64_t ptc255; - uint64_t ptc511; - uint64_t ptc1023; - uint64_t ptc1522; - uint64_t mptc; - uint64_t bptc; - uint64_t tsctc; - uint64_t tsctfc; -}; - -/* Structure containing variables used by the shared code (e1000_hw.c) */ -struct e1000_hw { - uint8_t *hw_addr; - e1000_mac_type mac_type; - e1000_phy_type phy_type; - uint32_t phy_init_script; - e1000_media_type media_type; - void *back; - e1000_fc_type fc; - e1000_bus_speed bus_speed; - e1000_bus_width bus_width; - e1000_bus_type bus_type; - struct e1000_eeprom_info eeprom; - e1000_ms_type master_slave; - e1000_ms_type original_master_slave; - e1000_ffe_config ffe_config_state; - uint32_t io_base; - uint32_t phy_id; - uint32_t phy_revision; - uint32_t phy_addr; - uint32_t original_fc; - uint32_t txcw; - uint32_t autoneg_failed; - uint32_t max_frame_size; - uint32_t min_frame_size; - uint32_t mc_filter_type; - uint32_t num_mc_addrs; - uint32_t collision_delta; - uint32_t tx_packet_delta; - uint32_t ledctl_default; - uint32_t ledctl_mode1; - uint32_t ledctl_mode2; - uint16_t phy_spd_default; - uint16_t dsp_reset_counter; - uint16_t autoneg_advertised; - uint16_t pci_cmd_word; - uint16_t fc_high_water; - uint16_t fc_low_water; - uint16_t fc_pause_time; - uint16_t current_ifs_val; - uint16_t ifs_min_val; - uint16_t ifs_max_val; - uint16_t ifs_step_size; - uint16_t ifs_ratio; - uint16_t device_id; - uint16_t vendor_id; - uint16_t subsystem_id; - uint16_t subsystem_vendor_id; - uint8_t revision_id; - uint8_t autoneg; - uint8_t mdix; - uint8_t forced_speed_duplex; - uint8_t wait_autoneg_complete; - uint8_t dma_fairness; - uint8_t mac_addr[NODE_ADDRESS_SIZE]; - uint8_t perm_mac_addr[NODE_ADDRESS_SIZE]; - boolean_t disable_polarity_correction; - boolean_t speed_downgraded; - boolean_t ttl_wa_activation; - e1000_dsp_config dsp_config_state; - boolean_t get_link_status; - boolean_t tbi_compatibility_en; - boolean_t tbi_compatibility_on; - boolean_t phy_reset_disable; - boolean_t fc_send_xon; - boolean_t fc_strict_ieee; - boolean_t report_tx_early; - boolean_t adaptive_ifs; - boolean_t ifs_params_forced; - boolean_t in_ifs_mode; -}; - - -#define E1000_EEPROM_SWDPIN0 0x0001 /* SWDPIN 0 EEPROM Value */ -#define E1000_EEPROM_LED_LOGIC 0x0020 /* Led Logic Word */ - -/* Register Bit Masks */ -/* Device Control */ -#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */ -#define E1000_CTRL_BEM 0x00000002 /* Endian Mode.0=little,1=big */ -#define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */ -#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */ -#define E1000_CTRL_TME 0x00000010 /* Test mode. 0=normal,1=test */ -#define E1000_CTRL_SLE 0x00000020 /* Serial Link on 0=dis,1=en */ -#define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */ -#define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */ -#define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */ -#define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */ -#define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */ -#define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */ -#define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */ -#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */ -#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */ -#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ -#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ -#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ -#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */ -#define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */ -#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ -#define E1000_CTRL_SWDPIO1 0x00800000 /* SWDPIN 1 input or output */ -#define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */ -#define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */ -#define E1000_CTRL_RST 0x04000000 /* Global reset */ -#define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ -#define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */ -#define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */ -#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ -#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ - -/* Device Status */ -#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ -#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ -#define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */ -#define E1000_STATUS_FUNC_0 0x00000000 /* Function 0 */ -#define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */ -#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */ -#define E1000_STATUS_TBIMODE 0x00000020 /* TBI mode */ -#define E1000_STATUS_SPEED_MASK 0x000000C0 -#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */ -#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ -#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ -#define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */ -#define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */ -#define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */ -#define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */ -#define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */ -#define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */ - -/* Constants used to intrepret the masked PCI-X bus speed. */ -#define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus speed 50-66 MHz */ -#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed 66-100 MHz */ -#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /* PCI-X bus speed 100-133 MHz */ - -/* EEPROM/Flash Control */ -#define E1000_EECD_SK 0x00000001 /* EEPROM Clock */ -#define E1000_EECD_CS 0x00000002 /* EEPROM Chip Select */ -#define E1000_EECD_DI 0x00000004 /* EEPROM Data In */ -#define E1000_EECD_DO 0x00000008 /* EEPROM Data Out */ -#define E1000_EECD_FWE_MASK 0x00000030 -#define E1000_EECD_FWE_DIS 0x00000010 /* Disable FLASH writes */ -#define E1000_EECD_FWE_EN 0x00000020 /* Enable FLASH writes */ -#define E1000_EECD_FWE_SHIFT 4 -#define E1000_EECD_REQ 0x00000040 /* EEPROM Access Request */ -#define E1000_EECD_GNT 0x00000080 /* EEPROM Access Grant */ -#define E1000_EECD_PRES 0x00000100 /* EEPROM Present */ -#define E1000_EECD_SIZE 0x00000200 /* EEPROM Size (0=64 word 1=256 word) */ -#define E1000_EECD_ADDR_BITS 0x00000400 /* EEPROM Addressing bits based on type - * (0-small, 1-large) */ -#define E1000_EECD_TYPE 0x00002000 /* EEPROM Type (1-SPI, 0-Microwire) */ -#ifndef E1000_EEPROM_GRANT_ATTEMPTS -#define E1000_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */ -#endif - -/* EEPROM Read */ -#define E1000_EERD_START 0x00000001 /* Start Read */ -#define E1000_EERD_DONE 0x00000010 /* Read Done */ -#define E1000_EERD_ADDR_SHIFT 8 -#define E1000_EERD_ADDR_MASK 0x0000FF00 /* Read Address */ -#define E1000_EERD_DATA_SHIFT 16 -#define E1000_EERD_DATA_MASK 0xFFFF0000 /* Read Data */ - -/* SPI EEPROM Status Register */ -#define EEPROM_STATUS_RDY_SPI 0x01 -#define EEPROM_STATUS_WEN_SPI 0x02 -#define EEPROM_STATUS_BP0_SPI 0x04 -#define EEPROM_STATUS_BP1_SPI 0x08 -#define EEPROM_STATUS_WPEN_SPI 0x80 - -/* Extended Device Control */ -#define E1000_CTRL_EXT_GPI0_EN 0x00000001 /* Maps SDP4 to GPI0 */ -#define E1000_CTRL_EXT_GPI1_EN 0x00000002 /* Maps SDP5 to GPI1 */ -#define E1000_CTRL_EXT_PHYINT_EN E1000_CTRL_EXT_GPI1_EN -#define E1000_CTRL_EXT_GPI2_EN 0x00000004 /* Maps SDP6 to GPI2 */ -#define E1000_CTRL_EXT_GPI3_EN 0x00000008 /* Maps SDP7 to GPI3 */ -#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Defineable Pin 4 */ -#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Defineable Pin 5 */ -#define E1000_CTRL_EXT_PHY_INT E1000_CTRL_EXT_SDP5_DATA -#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Defineable Pin 6 */ -#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */ -#define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */ -#define E1000_CTRL_EXT_SDP5_DIR 0x00000200 /* Direction of SDP5 0=in 1=out */ -#define E1000_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */ -#define E1000_CTRL_EXT_SDP7_DIR 0x00000800 /* Direction of SDP7 0=in 1=out */ -#define E1000_CTRL_EXT_ASDCHK 0x00001000 /* Initiate an ASD sequence */ -#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ -#define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */ -#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ -#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 -#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000 -#define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000 -#define E1000_CTRL_EXT_WR_WMARK_MASK 0x03000000 -#define E1000_CTRL_EXT_WR_WMARK_256 0x00000000 -#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000 -#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000 -#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000 - -/* MDI Control */ -#define E1000_MDIC_DATA_MASK 0x0000FFFF -#define E1000_MDIC_REG_MASK 0x001F0000 -#define E1000_MDIC_REG_SHIFT 16 -#define E1000_MDIC_PHY_MASK 0x03E00000 -#define E1000_MDIC_PHY_SHIFT 21 -#define E1000_MDIC_OP_WRITE 0x04000000 -#define E1000_MDIC_OP_READ 0x08000000 -#define E1000_MDIC_READY 0x10000000 -#define E1000_MDIC_INT_EN 0x20000000 -#define E1000_MDIC_ERROR 0x40000000 - -/* LED Control */ -#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F -#define E1000_LEDCTL_LED0_MODE_SHIFT 0 -#define E1000_LEDCTL_LED0_IVRT 0x00000040 -#define E1000_LEDCTL_LED0_BLINK 0x00000080 -#define E1000_LEDCTL_LED1_MODE_MASK 0x00000F00 -#define E1000_LEDCTL_LED1_MODE_SHIFT 8 -#define E1000_LEDCTL_LED1_IVRT 0x00004000 -#define E1000_LEDCTL_LED1_BLINK 0x00008000 -#define E1000_LEDCTL_LED2_MODE_MASK 0x000F0000 -#define E1000_LEDCTL_LED2_MODE_SHIFT 16 -#define E1000_LEDCTL_LED2_IVRT 0x00400000 -#define E1000_LEDCTL_LED2_BLINK 0x00800000 -#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000 -#define E1000_LEDCTL_LED3_MODE_SHIFT 24 -#define E1000_LEDCTL_LED3_IVRT 0x40000000 -#define E1000_LEDCTL_LED3_BLINK 0x80000000 - -#define E1000_LEDCTL_MODE_LINK_10_1000 0x0 -#define E1000_LEDCTL_MODE_LINK_100_1000 0x1 -#define E1000_LEDCTL_MODE_LINK_UP 0x2 -#define E1000_LEDCTL_MODE_ACTIVITY 0x3 -#define E1000_LEDCTL_MODE_LINK_ACTIVITY 0x4 -#define E1000_LEDCTL_MODE_LINK_10 0x5 -#define E1000_LEDCTL_MODE_LINK_100 0x6 -#define E1000_LEDCTL_MODE_LINK_1000 0x7 -#define E1000_LEDCTL_MODE_PCIX_MODE 0x8 -#define E1000_LEDCTL_MODE_FULL_DUPLEX 0x9 -#define E1000_LEDCTL_MODE_COLLISION 0xA -#define E1000_LEDCTL_MODE_BUS_SPEED 0xB -#define E1000_LEDCTL_MODE_BUS_SIZE 0xC -#define E1000_LEDCTL_MODE_PAUSED 0xD -#define E1000_LEDCTL_MODE_LED_ON 0xE -#define E1000_LEDCTL_MODE_LED_OFF 0xF - -/* Receive Address */ -#define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */ - -/* Interrupt Cause Read */ -#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ -#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */ -#define E1000_ICR_LSC 0x00000004 /* Link Status Change */ -#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */ -#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */ -#define E1000_ICR_RXO 0x00000040 /* rx overrun */ -#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */ -#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */ -#define E1000_ICR_RXCFG 0x00000400 /* RX /c/ ordered set */ -#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */ -#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */ -#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */ -#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */ -#define E1000_ICR_TXD_LOW 0x00008000 -#define E1000_ICR_SRPD 0x00010000 - -/* Interrupt Cause Set */ -#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_ICS_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_ICS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_ICS_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_ICS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_ICS_SRPD E1000_ICR_SRPD - -/* Interrupt Mask Set */ -#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_IMS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_IMS_SRPD E1000_ICR_SRPD - -/* Interrupt Mask Clear */ -#define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_IMC_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_IMC_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_IMC_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_IMC_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_IMC_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_IMC_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_IMC_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_IMC_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_IMC_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_IMC_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_IMC_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_IMC_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_IMC_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_IMC_SRPD E1000_ICR_SRPD - -/* Receive Control */ -#define E1000_RCTL_RST 0x00000001 /* Software reset */ -#define E1000_RCTL_EN 0x00000002 /* enable */ -#define E1000_RCTL_SBP 0x00000004 /* store bad packet */ -#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */ -#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */ -#define E1000_RCTL_LPE 0x00000020 /* long packet enable */ -#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ -#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ -#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */ -#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ -#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */ -#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */ -#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */ -#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ -#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */ -#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */ -#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2 */ -#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ -#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */ -#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ -/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */ -#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */ -#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */ -#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */ -#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */ -/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */ -#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */ -#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */ -#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */ -#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */ -#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */ -#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */ -#define E1000_RCTL_DPF 0x00400000 /* discard pause frames */ -#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */ -#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ - -/* Receive Descriptor */ -#define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */ -#define E1000_RDT_FPDB 0x80000000 /* Flush descriptor block */ -#define E1000_RDLEN_LEN 0x0007ff80 /* descriptor length */ -#define E1000_RDH_RDH 0x0000ffff /* receive descriptor head */ -#define E1000_RDT_RDT 0x0000ffff /* receive descriptor tail */ - -/* Flow Control */ -#define E1000_FCRTH_RTH 0x0000FFF8 /* Mask Bits[15:3] for RTH */ -#define E1000_FCRTH_XFCE 0x80000000 /* External Flow Control Enable */ -#define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */ -#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */ - -/* Receive Descriptor Control */ -#define E1000_RXDCTL_PTHRESH 0x0000003F /* RXDCTL Prefetch Threshold */ -#define E1000_RXDCTL_HTHRESH 0x00003F00 /* RXDCTL Host Threshold */ -#define E1000_RXDCTL_WTHRESH 0x003F0000 /* RXDCTL Writeback Threshold */ -#define E1000_RXDCTL_GRAN 0x01000000 /* RXDCTL Granularity */ - -/* Transmit Descriptor Control */ -#define E1000_TXDCTL_PTHRESH 0x000000FF /* TXDCTL Prefetch Threshold */ -#define E1000_TXDCTL_HTHRESH 0x0000FF00 /* TXDCTL Host Threshold */ -#define E1000_TXDCTL_WTHRESH 0x00FF0000 /* TXDCTL Writeback Threshold */ -#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */ -#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */ -#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */ - -/* Transmit Configuration Word */ -#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */ -#define E1000_TXCW_HD 0x00000040 /* TXCW half duplex */ -#define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */ -#define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */ -#define E1000_TXCW_PAUSE_MASK 0x00000180 /* TXCW pause request mask */ -#define E1000_TXCW_RF 0x00003000 /* TXCW remote fault */ -#define E1000_TXCW_NP 0x00008000 /* TXCW next page */ -#define E1000_TXCW_CW 0x0000ffff /* TxConfigWord mask */ -#define E1000_TXCW_TXC 0x40000000 /* Transmit Config control */ -#define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */ - -/* Receive Configuration Word */ -#define E1000_RXCW_CW 0x0000ffff /* RxConfigWord mask */ -#define E1000_RXCW_NC 0x04000000 /* Receive config no carrier */ -#define E1000_RXCW_IV 0x08000000 /* Receive config invalid */ -#define E1000_RXCW_CC 0x10000000 /* Receive config change */ -#define E1000_RXCW_C 0x20000000 /* Receive config */ -#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ -#define E1000_RXCW_ANC 0x80000000 /* Auto-neg complete */ - -/* Transmit Control */ -#define E1000_TCTL_RST 0x00000001 /* software reset */ -#define E1000_TCTL_EN 0x00000002 /* enable tx */ -#define E1000_TCTL_BCE 0x00000004 /* busy check enable */ -#define E1000_TCTL_PSP 0x00000008 /* pad short packets */ -#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */ -#define E1000_TCTL_COLD 0x003ff000 /* collision distance */ -#define E1000_TCTL_SWXOFF 0x00400000 /* SW Xoff transmission */ -#define E1000_TCTL_PBE 0x00800000 /* Packet Burst Enable */ -#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ -#define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */ - -/* Receive Checksum Control */ -#define E1000_RXCSUM_PCSS_MASK 0x000000FF /* Packet Checksum Start */ -#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */ -#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ -#define E1000_RXCSUM_IPV6OFL 0x00000400 /* IPv6 checksum offload */ - -/* Definitions for power management and wakeup registers */ -/* Wake Up Control */ -#define E1000_WUC_APME 0x00000001 /* APM Enable */ -#define E1000_WUC_PME_EN 0x00000002 /* PME Enable */ -#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */ -#define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */ -#define E1000_WUC_SPM 0x80000000 /* Enable SPM */ - -/* Wake Up Filter Control */ -#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ -#define E1000_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ -#define E1000_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ -#define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */ -#define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ -#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ -#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */ -#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */ -#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */ -#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */ -#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */ -#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */ -#define E1000_WUFC_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */ -#define E1000_WUFC_FLX_OFFSET 16 /* Offset to the Flexible Filters bits */ -#define E1000_WUFC_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */ - -/* Wake Up Status */ -#define E1000_WUS_LNKC 0x00000001 /* Link Status Changed */ -#define E1000_WUS_MAG 0x00000002 /* Magic Packet Received */ -#define E1000_WUS_EX 0x00000004 /* Directed Exact Received */ -#define E1000_WUS_MC 0x00000008 /* Directed Multicast Received */ -#define E1000_WUS_BC 0x00000010 /* Broadcast Received */ -#define E1000_WUS_ARP 0x00000020 /* ARP Request Packet Received */ -#define E1000_WUS_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Received */ -#define E1000_WUS_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Received */ -#define E1000_WUS_FLX0 0x00010000 /* Flexible Filter 0 Match */ -#define E1000_WUS_FLX1 0x00020000 /* Flexible Filter 1 Match */ -#define E1000_WUS_FLX2 0x00040000 /* Flexible Filter 2 Match */ -#define E1000_WUS_FLX3 0x00080000 /* Flexible Filter 3 Match */ -#define E1000_WUS_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */ - -/* Management Control */ -#define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */ -#define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */ -#define E1000_MANC_R_ON_FORCE 0x00000004 /* Reset on Force TCO - RO */ -#define E1000_MANC_RMCP_EN 0x00000100 /* Enable RCMP 026Fh Filtering */ -#define E1000_MANC_0298_EN 0x00000200 /* Enable RCMP 0298h Filtering */ -#define E1000_MANC_IPV4_EN 0x00000400 /* Enable IPv4 */ -#define E1000_MANC_IPV6_EN 0x00000800 /* Enable IPv6 */ -#define E1000_MANC_SNAP_EN 0x00001000 /* Accept LLC/SNAP */ -#define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */ -#define E1000_MANC_NEIGHBOR_EN 0x00004000 /* Enable Neighbor Discovery - * Filtering */ -#define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */ -#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ -#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */ -#define E1000_MANC_SMB_REQ 0x01000000 /* SMBus Request */ -#define E1000_MANC_SMB_GNT 0x02000000 /* SMBus Grant */ -#define E1000_MANC_SMB_CLK_IN 0x04000000 /* SMBus Clock In */ -#define E1000_MANC_SMB_DATA_IN 0x08000000 /* SMBus Data In */ -#define E1000_MANC_SMB_DATA_OUT 0x10000000 /* SMBus Data Out */ -#define E1000_MANC_SMB_CLK_OUT 0x20000000 /* SMBus Clock Out */ - -#define E1000_MANC_SMB_DATA_OUT_SHIFT 28 /* SMBus Data Out Shift */ -#define E1000_MANC_SMB_CLK_OUT_SHIFT 29 /* SMBus Clock Out Shift */ - -/* Wake Up Packet Length */ -#define E1000_WUPL_LENGTH_MASK 0x0FFF /* Only the lower 12 bits are valid */ - -#define E1000_MDALIGN 4096 - -/* EEPROM Commands - Microwire */ -#define EEPROM_READ_OPCODE_MICROWIRE 0x6 /* EEPROM read opcode */ -#define EEPROM_WRITE_OPCODE_MICROWIRE 0x5 /* EEPROM write opcode */ -#define EEPROM_ERASE_OPCODE_MICROWIRE 0x7 /* EEPROM erase opcode */ -#define EEPROM_EWEN_OPCODE_MICROWIRE 0x13 /* EEPROM erase/write enable */ -#define EEPROM_EWDS_OPCODE_MICROWIRE 0x10 /* EEPROM erast/write disable */ - -/* EEPROM Commands - SPI */ -#define EEPROM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */ -#define EEPROM_READ_OPCODE_SPI 0x3 /* EEPROM read opcode */ -#define EEPROM_WRITE_OPCODE_SPI 0x2 /* EEPROM write opcode */ -#define EEPROM_A8_OPCODE_SPI 0x8 /* opcode bit-3 = address bit-8 */ -#define EEPROM_WREN_OPCODE_SPI 0x6 /* EEPROM set Write Enable latch */ -#define EEPROM_WRDI_OPCODE_SPI 0x4 /* EEPROM reset Write Enable latch */ -#define EEPROM_RDSR_OPCODE_SPI 0x5 /* EEPROM read Status register */ -#define EEPROM_WRSR_OPCODE_SPI 0x1 /* EEPROM write Status register */ - -/* EEPROM Size definitions */ -#define EEPROM_SIZE_16KB 0x1800 -#define EEPROM_SIZE_8KB 0x1400 -#define EEPROM_SIZE_4KB 0x1000 -#define EEPROM_SIZE_2KB 0x0C00 -#define EEPROM_SIZE_1KB 0x0800 -#define EEPROM_SIZE_512B 0x0400 -#define EEPROM_SIZE_128B 0x0000 -#define EEPROM_SIZE_MASK 0x1C00 - -/* EEPROM Word Offsets */ -#define EEPROM_COMPAT 0x0003 -#define EEPROM_ID_LED_SETTINGS 0x0004 -#define EEPROM_SERDES_AMPLITUDE 0x0006 /* For SERDES output amplitude adjustment. */ -#define EEPROM_INIT_CONTROL1_REG 0x000A -#define EEPROM_INIT_CONTROL2_REG 0x000F -#define EEPROM_INIT_CONTROL3_PORT_B 0x0014 -#define EEPROM_INIT_CONTROL3_PORT_A 0x0024 -#define EEPROM_CFG 0x0012 -#define EEPROM_FLASH_VERSION 0x0032 -#define EEPROM_CHECKSUM_REG 0x003F - -/* Word definitions for ID LED Settings */ -#define ID_LED_RESERVED_0000 0x0000 -#define ID_LED_RESERVED_FFFF 0xFFFF -#define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \ - (ID_LED_OFF1_OFF2 << 8) | \ - (ID_LED_DEF1_DEF2 << 4) | \ - (ID_LED_DEF1_DEF2)) -#define ID_LED_DEF1_DEF2 0x1 -#define ID_LED_DEF1_ON2 0x2 -#define ID_LED_DEF1_OFF2 0x3 -#define ID_LED_ON1_DEF2 0x4 -#define ID_LED_ON1_ON2 0x5 -#define ID_LED_ON1_OFF2 0x6 -#define ID_LED_OFF1_DEF2 0x7 -#define ID_LED_OFF1_ON2 0x8 -#define ID_LED_OFF1_OFF2 0x9 - -#define IGP_ACTIVITY_LED_MASK 0xFFFFF0FF -#define IGP_ACTIVITY_LED_ENABLE 0x0300 -#define IGP_LED3_MODE 0x07000000 - - -/* Mask bits for SERDES amplitude adjustment in Word 6 of the EEPROM */ -#define EEPROM_SERDES_AMPLITUDE_MASK 0x000F - -/* Mask bits for fields in Word 0x0a of the EEPROM */ -#define EEPROM_WORD0A_ILOS 0x0010 -#define EEPROM_WORD0A_SWDPIO 0x01E0 -#define EEPROM_WORD0A_LRST 0x0200 -#define EEPROM_WORD0A_FD 0x0400 -#define EEPROM_WORD0A_66MHZ 0x0800 - -/* Mask bits for fields in Word 0x0f of the EEPROM */ -#define EEPROM_WORD0F_PAUSE_MASK 0x3000 -#define EEPROM_WORD0F_PAUSE 0x1000 -#define EEPROM_WORD0F_ASM_DIR 0x2000 -#define EEPROM_WORD0F_ANE 0x0800 -#define EEPROM_WORD0F_SWPDIO_EXT 0x00F0 - -/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */ -#define EEPROM_SUM 0xBABA - -/* EEPROM Map defines (WORD OFFSETS)*/ -#define EEPROM_NODE_ADDRESS_BYTE_0 0 -#define EEPROM_PBA_BYTE_1 8 - -#define EEPROM_RESERVED_WORD 0xFFFF - -/* EEPROM Map Sizes (Byte Counts) */ -#define PBA_SIZE 4 - -/* Collision related configuration parameters */ -#define E1000_COLLISION_THRESHOLD 16 -#define E1000_CT_SHIFT 4 -#define E1000_COLLISION_DISTANCE 64 -#define E1000_FDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE -#define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE -#define E1000_COLD_SHIFT 12 - -/* Number of Transmit and Receive Descriptors must be a multiple of 8 */ -#define REQ_TX_DESCRIPTOR_MULTIPLE 8 -#define REQ_RX_DESCRIPTOR_MULTIPLE 8 - -/* Default values for the transmit IPG register */ -#define DEFAULT_82542_TIPG_IPGT 10 -#define DEFAULT_82543_TIPG_IPGT_FIBER 9 -#define DEFAULT_82543_TIPG_IPGT_COPPER 8 - -#define E1000_TIPG_IPGT_MASK 0x000003FF -#define E1000_TIPG_IPGR1_MASK 0x000FFC00 -#define E1000_TIPG_IPGR2_MASK 0x3FF00000 - -#define DEFAULT_82542_TIPG_IPGR1 2 -#define DEFAULT_82543_TIPG_IPGR1 8 -#define E1000_TIPG_IPGR1_SHIFT 10 - -#define DEFAULT_82542_TIPG_IPGR2 10 -#define DEFAULT_82543_TIPG_IPGR2 6 -#define E1000_TIPG_IPGR2_SHIFT 20 - -#define E1000_TXDMAC_DPP 0x00000001 - -/* Adaptive IFS defines */ -#define TX_THRESHOLD_START 8 -#define TX_THRESHOLD_INCREMENT 10 -#define TX_THRESHOLD_DECREMENT 1 -#define TX_THRESHOLD_STOP 190 -#define TX_THRESHOLD_DISABLE 0 -#define TX_THRESHOLD_TIMER_MS 10000 -#define MIN_NUM_XMITS 1000 -#define IFS_MAX 80 -#define IFS_STEP 10 -#define IFS_MIN 40 -#define IFS_RATIO 4 - -/* PBA constants */ -#define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */ -#define E1000_PBA_22K 0x0016 -#define E1000_PBA_24K 0x0018 -#define E1000_PBA_30K 0x001E -#define E1000_PBA_40K 0x0028 -#define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */ - -/* Flow Control Constants */ -#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001 -#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100 -#define FLOW_CONTROL_TYPE 0x8808 - -/* The historical defaults for the flow control values are given below. */ -#define FC_DEFAULT_HI_THRESH (0x8000) /* 32KB */ -#define FC_DEFAULT_LO_THRESH (0x4000) /* 16KB */ -#define FC_DEFAULT_TX_TIMER (0x100) /* ~130 us */ - -/* PCIX Config space */ -#define PCIX_COMMAND_REGISTER 0xE6 -#define PCIX_STATUS_REGISTER_LO 0xE8 -#define PCIX_STATUS_REGISTER_HI 0xEA - -#define PCIX_COMMAND_MMRBC_MASK 0x000C -#define PCIX_COMMAND_MMRBC_SHIFT 0x2 -#define PCIX_STATUS_HI_MMRBC_MASK 0x0060 -#define PCIX_STATUS_HI_MMRBC_SHIFT 0x5 -#define PCIX_STATUS_HI_MMRBC_4K 0x3 -#define PCIX_STATUS_HI_MMRBC_2K 0x2 - - -/* Number of bits required to shift right the "pause" bits from the - * EEPROM (bits 13:12) to the "pause" (bits 8:7) field in the TXCW register. - */ -#define PAUSE_SHIFT 5 - -/* Number of bits required to shift left the "SWDPIO" bits from the - * EEPROM (bits 8:5) to the "SWDPIO" (bits 25:22) field in the CTRL register. - */ -#define SWDPIO_SHIFT 17 - -/* Number of bits required to shift left the "SWDPIO_EXT" bits from the - * EEPROM word F (bits 7:4) to the bits 11:8 of The Extended CTRL register. - */ -#define SWDPIO__EXT_SHIFT 4 - -/* Number of bits required to shift left the "ILOS" bit from the EEPROM - * (bit 4) to the "ILOS" (bit 7) field in the CTRL register. - */ -#define ILOS_SHIFT 3 - - -#define RECEIVE_BUFFER_ALIGN_SIZE (256) - -/* Number of milliseconds we wait for auto-negotiation to complete */ -#define LINK_UP_TIMEOUT 500 - -#define E1000_TX_BUFFER_SIZE ((uint32_t)1514) - -/* The carrier extension symbol, as received by the NIC. */ -#define CARRIER_EXTENSION 0x0F - -/* TBI_ACCEPT macro definition: - * - * This macro requires: - * adapter = a pointer to struct e1000_hw - * status = the 8 bit status field of the RX descriptor with EOP set - * error = the 8 bit error field of the RX descriptor with EOP set - * length = the sum of all the length fields of the RX descriptors that - * make up the current frame - * last_byte = the last byte of the frame DMAed by the hardware - * max_frame_length = the maximum frame length we want to accept. - * min_frame_length = the minimum frame length we want to accept. - * - * This macro is a conditional that should be used in the interrupt - * handler's Rx processing routine when RxErrors have been detected. - * - * Typical use: - * ... - * if (TBI_ACCEPT) { - * accept_frame = TRUE; - * e1000_tbi_adjust_stats(adapter, MacAddress); - * frame_length--; - * } else { - * accept_frame = FALSE; - * } - * ... - */ - -#define TBI_ACCEPT(adapter, status, errors, length, last_byte) \ - ((adapter)->tbi_compatibility_on && \ - (((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \ - ((last_byte) == CARRIER_EXTENSION) && \ - (((status) & E1000_RXD_STAT_VP) ? \ - (((length) > ((adapter)->min_frame_size - VLAN_TAG_SIZE)) && \ - ((length) <= ((adapter)->max_frame_size + 1))) : \ - (((length) > (adapter)->min_frame_size) && \ - ((length) <= ((adapter)->max_frame_size + VLAN_TAG_SIZE + 1))))) - - -/* Structures, enums, and macros for the PHY */ - -/* Bit definitions for the Management Data IO (MDIO) and Management Data - * Clock (MDC) pins in the Device Control Register. - */ -#define E1000_CTRL_PHY_RESET_DIR E1000_CTRL_SWDPIO0 -#define E1000_CTRL_PHY_RESET E1000_CTRL_SWDPIN0 -#define E1000_CTRL_MDIO_DIR E1000_CTRL_SWDPIO2 -#define E1000_CTRL_MDIO E1000_CTRL_SWDPIN2 -#define E1000_CTRL_MDC_DIR E1000_CTRL_SWDPIO3 -#define E1000_CTRL_MDC E1000_CTRL_SWDPIN3 -#define E1000_CTRL_PHY_RESET_DIR4 E1000_CTRL_EXT_SDP4_DIR -#define E1000_CTRL_PHY_RESET4 E1000_CTRL_EXT_SDP4_DATA - -/* PHY 1000 MII Register/Bit Definitions */ -/* PHY Registers defined by IEEE */ -#define PHY_CTRL 0x00 /* Control Register */ -#define PHY_STATUS 0x01 /* Status Regiser */ -#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */ -#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ -#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ -#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */ -#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */ -#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */ -#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */ -#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */ -#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ -#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ - -/* M88E1000 Specific Registers */ -#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */ -#define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Register */ -#define M88E1000_INT_ENABLE 0x12 /* Interrupt Enable Register */ -#define M88E1000_INT_STATUS 0x13 /* Interrupt Status Register */ -#define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */ -#define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */ - -#define M88E1000_PHY_EXT_CTRL 0x1A /* PHY extend control register */ -#define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for page number setting */ -#define M88E1000_PHY_GEN_CONTROL 0x1E /* Its meaning depends on reg 29 */ -#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */ -#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */ - -#define IGP01E1000_IEEE_REGS_PAGE 0x0000 -#define IGP01E1000_IEEE_RESTART_AUTONEG 0x3300 -#define IGP01E1000_IEEE_FORCE_GIGA 0x0140 - -/* IGP01E1000 Specific Registers */ -#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* PHY Specific Port Config Register */ -#define IGP01E1000_PHY_PORT_STATUS 0x11 /* PHY Specific Status Register */ -#define IGP01E1000_PHY_PORT_CTRL 0x12 /* PHY Specific Control Register */ -#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health Register */ -#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO Register */ -#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality Register */ -#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* PHY Page Select Core Register */ - -/* IGP01E1000 AGC Registers - stores the cable length values*/ -#define IGP01E1000_PHY_AGC_A 0x1172 -#define IGP01E1000_PHY_AGC_B 0x1272 -#define IGP01E1000_PHY_AGC_C 0x1472 -#define IGP01E1000_PHY_AGC_D 0x1872 - -/* IGP01E1000 DSP Reset Register */ -#define IGP01E1000_PHY_DSP_RESET 0x1F33 -#define IGP01E1000_PHY_DSP_SET 0x1F71 -#define IGP01E1000_PHY_DSP_FFE 0x1F35 - -#define IGP01E1000_PHY_CHANNEL_NUM 4 -#define IGP01E1000_PHY_AGC_PARAM_A 0x1171 -#define IGP01E1000_PHY_AGC_PARAM_B 0x1271 -#define IGP01E1000_PHY_AGC_PARAM_C 0x1471 -#define IGP01E1000_PHY_AGC_PARAM_D 0x1871 - -#define IGP01E1000_PHY_EDAC_MU_INDEX 0xC000 -#define IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS 0x8000 - -#define IGP01E1000_PHY_ANALOG_TX_STATE 0x2890 -#define IGP01E1000_PHY_ANALOG_CLASS_A 0x2000 -#define IGP01E1000_PHY_FORCE_ANALOG_ENABLE 0x0004 -#define IGP01E1000_PHY_DSP_FFE_CM_CP 0x0069 - -#define IGP01E1000_PHY_DSP_FFE_DEFAULT 0x002A -/* IGP01E1000 PCS Initialization register - stores the polarity status when - * speed = 1000 Mbps. */ -#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 -#define IGP01E1000_PHY_PCS_CTRL_REG 0x00B5 - -#define IGP01E1000_ANALOG_REGS_PAGE 0x20C0 - -#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ -#define MAX_PHY_MULTI_PAGE_REG 0xF /*Registers that are equal on all pages*/ -/* PHY Control Register */ -#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ -#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ -#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ -#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ -#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */ -#define MII_CR_POWER_DOWN 0x0800 /* Power down */ -#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ -#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */ -#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ -#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ - -/* PHY Status Register */ -#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */ -#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */ -#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */ -#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */ -#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */ -#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */ -#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */ -#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */ -#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */ -#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */ -#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */ -#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */ -#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */ -#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */ -#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */ - -/* Autoneg Advertisement Register */ -#define NWAY_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */ -#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */ -#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */ -#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */ -#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */ -#define NWAY_AR_100T4_CAPS 0x0200 /* 100T4 Capable */ -#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */ -#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */ -#define NWAY_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */ -#define NWAY_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */ - -/* Link Partner Ability Register (Base Page) */ -#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */ -#define NWAY_LPAR_10T_HD_CAPS 0x0020 /* LP is 10T Half Duplex Capable */ -#define NWAY_LPAR_10T_FD_CAPS 0x0040 /* LP is 10T Full Duplex Capable */ -#define NWAY_LPAR_100TX_HD_CAPS 0x0080 /* LP is 100TX Half Duplex Capable */ -#define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP is 100TX Full Duplex Capable */ -#define NWAY_LPAR_100T4_CAPS 0x0200 /* LP is 100T4 Capable */ -#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */ -#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */ -#define NWAY_LPAR_REMOTE_FAULT 0x2000 /* LP has detected Remote Fault */ -#define NWAY_LPAR_ACKNOWLEDGE 0x4000 /* LP has rx'd link code word */ -#define NWAY_LPAR_NEXT_PAGE 0x8000 /* Next Page ability supported */ - -/* Autoneg Expansion Register */ -#define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */ -#define NWAY_ER_PAGE_RXD 0x0002 /* LP is 10T Half Duplex Capable */ -#define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP is 10T Full Duplex Capable */ -#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */ -#define NWAY_ER_PAR_DETECT_FAULT 0x0010 /* LP is 100TX Full Duplex Capable */ - -/* Next Page TX Register */ -#define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ -#define NPTX_TOGGLE 0x0800 /* Toggles between exchanges - * of different NP - */ -#define NPTX_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg - * 0 = cannot comply with msg - */ -#define NPTX_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ -#define NPTX_NEXT_PAGE 0x8000 /* 1 = addition NP will follow - * 0 = sending last NP - */ - -/* Link Partner Next Page Register */ -#define LP_RNPR_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ -#define LP_RNPR_TOGGLE 0x0800 /* Toggles between exchanges - * of different NP - */ -#define LP_RNPR_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg - * 0 = cannot comply with msg - */ -#define LP_RNPR_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ -#define LP_RNPR_ACKNOWLDGE 0x4000 /* 1 = ACK / 0 = NO ACK */ -#define LP_RNPR_NEXT_PAGE 0x8000 /* 1 = addition NP will follow - * 0 = sending last NP - */ - -/* 1000BASE-T Control Register */ -#define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */ -#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */ -#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */ -#define CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */ - /* 0=DTE device */ -#define CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */ - /* 0=Configure PHY as Slave */ -#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */ - /* 0=Automatic Master/Slave config */ -#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */ -#define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */ -#define CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */ -#define CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */ -#define CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */ - -/* 1000BASE-T Status Register */ -#define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle errors since last read */ -#define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asymmetric pause direction bit */ -#define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */ -#define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */ -#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */ -#define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */ -#define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */ -#define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */ -#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12 -#define SR_1000T_LOCAL_RX_STATUS_SHIFT 13 -#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5 -#define FFE_IDLE_ERR_COUNT_TIMEOUT_20 20 -#define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100 - -/* Extended Status Register */ -#define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */ -#define IEEE_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */ -#define IEEE_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */ -#define IEEE_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */ - -#define PHY_TX_POLARITY_MASK 0x0100 /* register 10h bit 8 (polarity bit) */ -#define PHY_TX_NORMAL_POLARITY 0 /* register 10h bit 8 (normal polarity) */ - -#define AUTO_POLARITY_DISABLE 0x0010 /* register 11h bit 4 */ - /* (0=enable, 1=disable) */ - -/* M88E1000 PHY Specific Control Register */ -#define M88E1000_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */ -#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */ -#define M88E1000_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */ -#define M88E1000_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low, - * 0=CLK125 toggling - */ -#define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */ - /* Manual MDI configuration */ -#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */ -#define M88E1000_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover, - * 100BASE-TX/10BASE-T: - * MDI Mode - */ -#define M88E1000_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled - * all speeds. - */ -#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE 0x0080 - /* 1=Enable Extended 10BASE-T distance - * (Lower 10BASE-T RX Threshold) - * 0=Normal 10BASE-T RX Threshold */ -#define M88E1000_PSCR_MII_5BIT_ENABLE 0x0100 - /* 1=5-Bit interface in 100BASE-TX - * 0=MII interface in 100BASE-TX */ -#define M88E1000_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */ -#define M88E1000_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */ -#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */ - -#define M88E1000_PSCR_POLARITY_REVERSAL_SHIFT 1 -#define M88E1000_PSCR_AUTO_X_MODE_SHIFT 5 -#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7 - -/* M88E1000 PHY Specific Status Register */ -#define M88E1000_PSSR_JABBER 0x0001 /* 1=Jabber */ -#define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */ -#define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */ -#define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */ -#define M88E1000_PSSR_CABLE_LENGTH 0x0380 /* 0=<50M;1=50-80M;2=80-110M; - * 3=110-140M;4=>140M */ -#define M88E1000_PSSR_LINK 0x0400 /* 1=Link up, 0=Link down */ -#define M88E1000_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */ -#define M88E1000_PSSR_PAGE_RCVD 0x1000 /* 1=Page received */ -#define M88E1000_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */ -#define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ -#define M88E1000_PSSR_10MBS 0x0000 /* 00=10Mbs */ -#define M88E1000_PSSR_100MBS 0x4000 /* 01=100Mbs */ -#define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ - -#define M88E1000_PSSR_REV_POLARITY_SHIFT 1 -#define M88E1000_PSSR_DOWNSHIFT_SHIFT 5 -#define M88E1000_PSSR_MDIX_SHIFT 6 -#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7 - -/* M88E1000 Extended PHY Specific Control Register */ -#define M88E1000_EPSCR_FIBER_LOOPBACK 0x4000 /* 1=Fiber loopback */ -#define M88E1000_EPSCR_DOWN_NO_IDLE 0x8000 /* 1=Lost lock detect enabled. - * Will assert lost lock and bring - * link down if idle not seen - * within 1ms in 1000BASE-T - */ -/* Number of times we will attempt to autonegotiate before downshifting if we - * are the master */ -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_2X 0x0400 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_3X 0x0800 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_4X 0x0C00 -/* Number of times we will attempt to autonegotiate before downshifting if we - * are the slave */ -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_DIS 0x0000 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_2X 0x0200 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_3X 0x0300 -#define M88E1000_EPSCR_TX_CLK_2_5 0x0060 /* 2.5 MHz TX_CLK */ -#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ -#define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */ - -/* IGP01E1000 Specific Port Config Register - R/W */ -#define IGP01E1000_PSCFR_AUTO_MDIX_PAR_DETECT 0x0010 -#define IGP01E1000_PSCFR_PRE_EN 0x0020 -#define IGP01E1000_PSCFR_SMART_SPEED 0x0080 -#define IGP01E1000_PSCFR_DISABLE_TPLOOPBACK 0x0100 -#define IGP01E1000_PSCFR_DISABLE_JABBER 0x0400 -#define IGP01E1000_PSCFR_DISABLE_TRANSMIT 0x2000 - -/* IGP01E1000 Specific Port Status Register - R/O */ -#define IGP01E1000_PSSR_AUTONEG_FAILED 0x0001 /* RO LH SC */ -#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 -#define IGP01E1000_PSSR_CABLE_LENGTH 0x007C -#define IGP01E1000_PSSR_FULL_DUPLEX 0x0200 -#define IGP01E1000_PSSR_LINK_UP 0x0400 -#define IGP01E1000_PSSR_MDIX 0x0800 -#define IGP01E1000_PSSR_SPEED_MASK 0xC000 /* speed bits mask */ -#define IGP01E1000_PSSR_SPEED_10MBPS 0x4000 -#define IGP01E1000_PSSR_SPEED_100MBPS 0x8000 -#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 -#define IGP01E1000_PSSR_CABLE_LENGTH_SHIFT 0x0002 /* shift right 2 */ -#define IGP01E1000_PSSR_MDIX_SHIFT 0x000B /* shift right 11 */ - -/* IGP01E1000 Specific Port Control Register - R/W */ -#define IGP01E1000_PSCR_TP_LOOPBACK 0x0001 -#define IGP01E1000_PSCR_CORRECT_NC_SCMBLR 0x0200 -#define IGP01E1000_PSCR_TEN_CRS_SELECT 0x0400 -#define IGP01E1000_PSCR_FLIP_CHIP 0x0800 -#define IGP01E1000_PSCR_AUTO_MDIX 0x1000 -#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0-MDI, 1-MDIX */ - -/* IGP01E1000 Specific Port Link Health Register */ -#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 -#define IGP01E1000_PLHR_GIG_SCRAMBLER_ERROR 0x4000 -#define IGP01E1000_PLHR_GIG_REM_RCVR_NOK 0x0800 /* LH */ -#define IGP01E1000_PLHR_IDLE_ERROR_CNT_OFLOW 0x0400 /* LH */ -#define IGP01E1000_PLHR_DATA_ERR_1 0x0200 /* LH */ -#define IGP01E1000_PLHR_DATA_ERR_0 0x0100 -#define IGP01E1000_PLHR_AUTONEG_FAULT 0x0010 -#define IGP01E1000_PLHR_AUTONEG_ACTIVE 0x0008 -#define IGP01E1000_PLHR_VALID_CHANNEL_D 0x0004 -#define IGP01E1000_PLHR_VALID_CHANNEL_C 0x0002 -#define IGP01E1000_PLHR_VALID_CHANNEL_B 0x0001 -#define IGP01E1000_PLHR_VALID_CHANNEL_A 0x0000 - -/* IGP01E1000 Channel Quality Register */ -#define IGP01E1000_MSE_CHANNEL_D 0x000F -#define IGP01E1000_MSE_CHANNEL_C 0x00F0 -#define IGP01E1000_MSE_CHANNEL_B 0x0F00 -#define IGP01E1000_MSE_CHANNEL_A 0xF000 - -/* IGP01E1000 DSP reset macros */ -#define DSP_RESET_ENABLE 0x0 -#define DSP_RESET_DISABLE 0x2 -#define E1000_MAX_DSP_RESETS 10 - -/* IGP01E1000 AGC Registers */ - -#define IGP01E1000_AGC_LENGTH_SHIFT 7 /* Coarse - 13:11, Fine - 10:7 */ - -/* 7 bits (3 Coarse + 4 Fine) --> 128 optional values */ -#define IGP01E1000_AGC_LENGTH_TABLE_SIZE 128 - -/* The precision of the length is +/- 10 meters */ -#define IGP01E1000_AGC_RANGE 10 - -/* IGP01E1000 PCS Initialization register */ -/* bits 3:6 in the PCS registers stores the channels polarity */ -#define IGP01E1000_PHY_POLARITY_MASK 0x0078 - -/* IGP01E1000 GMII FIFO Register */ -#define IGP01E1000_GMII_FLEX_SPD 0x10 /* Enable flexible speed - * on Link-Up */ -#define IGP01E1000_GMII_SPD 0x20 /* Enable SPD */ - -/* IGP01E1000 Analog Register */ -#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS 0x20D1 -#define IGP01E1000_ANALOG_FUSE_STATUS 0x20D0 -#define IGP01E1000_ANALOG_FUSE_CONTROL 0x20DC -#define IGP01E1000_ANALOG_FUSE_BYPASS 0x20DE - -#define IGP01E1000_ANALOG_FUSE_POLY_MASK 0xF000 -#define IGP01E1000_ANALOG_FUSE_FINE_MASK 0x0F80 -#define IGP01E1000_ANALOG_FUSE_COARSE_MASK 0x0070 -#define IGP01E1000_ANALOG_SPARE_FUSE_ENABLED 0x0100 -#define IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL 0x0002 - -#define IGP01E1000_ANALOG_FUSE_COARSE_THRESH 0x0040 -#define IGP01E1000_ANALOG_FUSE_COARSE_10 0x0010 -#define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080 -#define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500 - -/* Bit definitions for valid PHY IDs. */ -#define M88E1000_E_PHY_ID 0x01410C50 -#define M88E1000_I_PHY_ID 0x01410C30 -#define M88E1011_I_PHY_ID 0x01410C20 -#define IGP01E1000_I_PHY_ID 0x02A80380 -#define M88E1000_12_PHY_ID M88E1000_E_PHY_ID -#define M88E1000_14_PHY_ID M88E1000_E_PHY_ID -#define M88E1011_I_REV_4 0x04 - -/* Miscellaneous PHY bit definitions. */ -#define PHY_PREAMBLE 0xFFFFFFFF -#define PHY_SOF 0x01 -#define PHY_OP_READ 0x02 -#define PHY_OP_WRITE 0x01 -#define PHY_TURNAROUND 0x02 -#define PHY_PREAMBLE_SIZE 32 -#define MII_CR_SPEED_1000 0x0040 -#define MII_CR_SPEED_100 0x2000 -#define MII_CR_SPEED_10 0x0000 -#define E1000_PHY_ADDRESS 0x01 -#define PHY_AUTO_NEG_TIME 45 /* 4.5 Seconds */ -#define PHY_FORCE_TIME 20 /* 2.0 Seconds */ -#define PHY_REVISION_MASK 0xFFFFFFF0 -#define DEVICE_SPEED_MASK 0x00000300 /* Device Ctrl Reg Speed Mask */ -#define REG4_SPEED_MASK 0x01E0 -#define REG9_SPEED_MASK 0x0300 -#define ADVERTISE_10_HALF 0x0001 -#define ADVERTISE_10_FULL 0x0002 -#define ADVERTISE_100_HALF 0x0004 -#define ADVERTISE_100_FULL 0x0008 -#define ADVERTISE_1000_HALF 0x0010 -#define ADVERTISE_1000_FULL 0x0020 -#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F /* Everything but 1000-Half */ -#define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds*/ -#define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds*/ - -#define TANAX_TTL_WA_RESET(hw) { \ - if((hw)->dsp_reset_counter) { \ - e1000_write_phy_reg((hw), IGP01E1000_PHY_DSP_RESET, 0x0000); \ - (hw)->dsp_reset_counter = 0; \ - } \ -} - -#endif /* _E1000_HW_H_ */ diff --git a/xen/drivers/net/e1000/e1000_main.c b/xen/drivers/net/e1000/e1000_main.c deleted file mode 100644 index 4b29541b8d..0000000000 --- a/xen/drivers/net/e1000/e1000_main.c +++ /dev/null @@ -1,2940 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#include "e1000.h" - -/* Change Log - * - * 5.2.16 8/8/03 - * o Added support for new controllers: 82545GM, 82546GB, 82541/7_B1 - * o Bug fix: reset h/w before first EEPROM read because we don't know - * who may have been messing with the device before we got there. - * [Dave Johnson (ddj -a-t- cascv.brown.edu)] - * o Bug fix: read the correct work from EEPROM to detect programmed - * WoL settings. - * o Bug fix: TSO would hang if space left in FIFO was being miscalculated - * when mss dropped without a correspoding drop in the DMA buffer size. - * o ASF for Fiber nics isn't supported. - * o Bug fix: Workaround added for potential hang with 82544 running in - * PCI-X if send buffer terminates within an evenly-aligned dword. - * o Feature: Add support for ethtool flow control setting. - * o Feature: Add support for ethtool TSO setting. - * o Feature: Increase default Tx Descriptor count to 1024 for >= 82544. - * - * 5.1.13 5/28/03 - * o Bug fix: request_irq() failure resulted in freeing resources twice! - * [Don Fry (brazilnut@us.ibm.com)] - * o Bug fix: fix VLAN support on ppc64 [Mark Rakes (mrakes@vivato.net)] - * o Bug fix: missing Tx cleanup opportunities during interrupt handling. - * o Bug fix: alloc_etherdev failure didn't cleanup regions in probe. - * o Cleanup: s/int/unsigned int/ for descriptor ring indexes. - * - * 5.1.11 5/6/03 - */ - -char e1000_driver_name[] = "e1000"; -char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; -char e1000_driver_version[] = "5.2.16"; -char e1000_copyright[] = "Copyright (c) 1999-2003 Intel Corporation."; - -/* e1000_pci_tbl - PCI Device ID Table - * - * Wildcard entries (PCI_ANY_ID) should come last - * Last entry must be all 0s - * - * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, - * Class, Class Mask, private data (not used) } - */ -static struct pci_device_id e1000_pci_tbl[] __devinitdata = { - {0x8086, 0x1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x100C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x100D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x100E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x100F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1015, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1018, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1026, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1027, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1075, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1076, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1077, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1078, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1079, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x107A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x107B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - /* required last entry */ - {0,} -}; - -MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); - -/* Local Function Prototypes */ - -int e1000_up(struct e1000_adapter *adapter); -void e1000_down(struct e1000_adapter *adapter); -void e1000_reset(struct e1000_adapter *adapter); -int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx); - -static int e1000_init_module(void); -static void e1000_exit_module(void); -static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent); -static void __devexit e1000_remove(struct pci_dev *pdev); -static int e1000_sw_init(struct e1000_adapter *adapter); -static int e1000_open(struct net_device *netdev); -static int e1000_close(struct net_device *netdev); -static int e1000_setup_tx_resources(struct e1000_adapter *adapter); -static int e1000_setup_rx_resources(struct e1000_adapter *adapter); -static void e1000_configure_tx(struct e1000_adapter *adapter); -static void e1000_configure_rx(struct e1000_adapter *adapter); -static void e1000_setup_rctl(struct e1000_adapter *adapter); -static void e1000_clean_tx_ring(struct e1000_adapter *adapter); -static void e1000_clean_rx_ring(struct e1000_adapter *adapter); -static void e1000_free_tx_resources(struct e1000_adapter *adapter); -static void e1000_free_rx_resources(struct e1000_adapter *adapter); -static void e1000_set_multi(struct net_device *netdev); -static void e1000_update_phy_info(unsigned long data); -static void e1000_watchdog(unsigned long data); -static void e1000_82547_tx_fifo_stall(unsigned long data); -static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev); -static struct net_device_stats * e1000_get_stats(struct net_device *netdev); -static int e1000_change_mtu(struct net_device *netdev, int new_mtu); -static int e1000_set_mac(struct net_device *netdev, void *p); -static void e1000_update_stats(struct e1000_adapter *adapter); -static inline void e1000_irq_disable(struct e1000_adapter *adapter); -static inline void e1000_irq_enable(struct e1000_adapter *adapter); -static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs); -static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter); -#ifdef CONFIG_E1000_NAPI -static int e1000_clean(struct net_device *netdev, int *budget); -static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter, - int *work_done, int work_to_do); -#else -static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter); -#endif -static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter); -static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); -#ifdef SIOCGMIIPHY -static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, - int cmd); -#endif -static void e1000_enter_82542_rst(struct e1000_adapter *adapter); -static void e1000_leave_82542_rst(struct e1000_adapter *adapter); -static inline void e1000_rx_checksum(struct e1000_adapter *adapter, - struct e1000_rx_desc *rx_desc, - struct sk_buff *skb); -static void e1000_tx_timeout(struct net_device *dev); -static void e1000_tx_timeout_task(struct net_device *dev); -static void e1000_smartspeed(struct e1000_adapter *adapter); -static inline int e1000_82547_fifo_workaround(struct e1000_adapter *adapter, - struct sk_buff *skb); - -#ifdef NETIF_F_HW_VLAN_TX -static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); -static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); -static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); -static void e1000_restore_vlan(struct e1000_adapter *adapter); -#endif - -static int e1000_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); -static int e1000_suspend(struct pci_dev *pdev, uint32_t state); -#ifdef CONFIG_PM -static int e1000_resume(struct pci_dev *pdev); -#endif - -struct notifier_block e1000_notifier_reboot = { - .notifier_call = e1000_notify_reboot, - .next = NULL, - .priority = 0 -}; - -/* Exported from other modules */ - -extern void e1000_check_options(struct e1000_adapter *adapter); -extern int e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr); - -static struct pci_driver e1000_driver = { - .name = e1000_driver_name, - .id_table = e1000_pci_tbl, - .probe = e1000_probe, - .remove = __devexit_p(e1000_remove), - /* Power Managment Hooks */ -#ifdef CONFIG_PM - .suspend = e1000_suspend, - .resume = e1000_resume -#endif -}; - -MODULE_AUTHOR("Intel Corporation, "); -MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver"); -MODULE_LICENSE("GPL"); - -/** - * e1000_init_module - Driver Registration Routine - * - * e1000_init_module is the first routine called when the driver is - * loaded. All it does is register with the PCI subsystem. - **/ - -static int __init -e1000_init_module(void) -{ - int ret; - - ret = pci_module_init(&e1000_driver); - if(ret >= 0) { - printk(KERN_INFO "%s - version %s\n", - e1000_driver_string, e1000_driver_version); - printk(KERN_INFO "%s\n", e1000_copyright); - //register_reboot_notifier(&e1000_notifier_reboot); - } - return ret; -} - -module_init(e1000_init_module); - -/** - * e1000_exit_module - Driver Exit Cleanup Routine - * - * e1000_exit_module is called just before the driver is removed - * from memory. - **/ - -static void __exit -e1000_exit_module(void) -{ - unregister_reboot_notifier(&e1000_notifier_reboot); - pci_unregister_driver(&e1000_driver); -} - -module_exit(e1000_exit_module); - - -int -e1000_up(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - - /* hardware has been reset, we need to reload some things */ - - e1000_set_multi(netdev); - -#ifdef NETIF_F_HW_VLAN_TX - e1000_restore_vlan(adapter); -#endif - - e1000_configure_tx(adapter); - e1000_setup_rctl(adapter); - e1000_configure_rx(adapter); - e1000_alloc_rx_buffers(adapter); - - if(request_irq(netdev->irq, &e1000_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, - netdev->name, netdev)) - return -1; - - mod_timer(&adapter->watchdog_timer, jiffies); - e1000_irq_enable(adapter); - - return 0; -} - -void -e1000_down(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - - e1000_irq_disable(adapter); - free_irq(netdev->irq, netdev); - del_timer_sync(&adapter->tx_fifo_stall_timer); - del_timer_sync(&adapter->watchdog_timer); - del_timer_sync(&adapter->phy_info_timer); - adapter->link_speed = 0; - adapter->link_duplex = 0; - netif_carrier_off(netdev); - netif_stop_queue(netdev); - - e1000_reset(adapter); - e1000_clean_tx_ring(adapter); - e1000_clean_rx_ring(adapter); -} - -void -e1000_reset(struct e1000_adapter *adapter) -{ - uint32_t pba; - /* Repartition Pba for greater than 9k mtu - * To take effect CTRL.RST is required. - */ - - if(adapter->hw.mac_type < e1000_82547) { - if(adapter->rx_buffer_len > E1000_RXBUFFER_8192) - pba = E1000_PBA_40K; - else - pba = E1000_PBA_48K; - } else { - if(adapter->rx_buffer_len > E1000_RXBUFFER_8192) - pba = E1000_PBA_22K; - else - pba = E1000_PBA_30K; - adapter->tx_fifo_head = 0; - adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT; - adapter->tx_fifo_size = - (E1000_PBA_40K - pba) << E1000_TX_FIFO_SIZE_SHIFT; - atomic_set(&adapter->tx_fifo_stall, 0); - } - E1000_WRITE_REG(&adapter->hw, PBA, pba); - - adapter->hw.fc = adapter->hw.original_fc; - e1000_reset_hw(&adapter->hw); - if(adapter->hw.mac_type >= e1000_82544) - E1000_WRITE_REG(&adapter->hw, WUC, 0); - e1000_init_hw(&adapter->hw); - e1000_reset_adaptive(&adapter->hw); - e1000_phy_get_info(&adapter->hw, &adapter->phy_info); -} - -/** - * e1000_probe - Device Initialization Routine - * @pdev: PCI device information struct - * @ent: entry in e1000_pci_tbl - * - * Returns 0 on success, negative on failure - * - * e1000_probe initializes an adapter identified by a pci_dev structure. - * The OS initialization, configuring of the adapter private structure, - * and a hardware reset occur. - **/ - -static int __devinit -e1000_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct e1000_adapter *adapter; - static int cards_found = 0; - unsigned long mmio_start; - int mmio_len; - int pci_using_dac; - int i; - uint16_t eeprom_data; - - if((i = pci_enable_device(pdev))) - return i; - - if(!(i = pci_set_dma_mask(pdev, PCI_DMA_64BIT))) { - pci_using_dac = 1; - } else { - if((i = pci_set_dma_mask(pdev, PCI_DMA_32BIT))) { - E1000_ERR("No usable DMA configuration, aborting\n"); - return i; - } - pci_using_dac = 0; - } - - if((i = pci_request_regions(pdev, e1000_driver_name))) - return i; - - pci_set_master(pdev); - - netdev = alloc_etherdev(sizeof(struct e1000_adapter)); - if(!netdev) - goto err_alloc_etherdev; - - SET_MODULE_OWNER(netdev); - SET_NETDEV_DEV(netdev, &pdev->dev); - - pci_set_drvdata(pdev, netdev); - adapter = netdev->priv; - adapter->netdev = netdev; - adapter->pdev = pdev; - adapter->hw.back = adapter; - - mmio_start = pci_resource_start(pdev, BAR_0); - mmio_len = pci_resource_len(pdev, BAR_0); - - adapter->hw.hw_addr = ioremap(mmio_start, mmio_len); - if(!adapter->hw.hw_addr) - goto err_ioremap; - - for(i = BAR_1; i <= BAR_5; i++) { - if(pci_resource_len(pdev, i) == 0) - continue; - if(pci_resource_flags(pdev, i) & IORESOURCE_IO) { - adapter->hw.io_base = pci_resource_start(pdev, i); - break; - } - } - - netdev->open = &e1000_open; - netdev->stop = &e1000_close; - netdev->hard_start_xmit = &e1000_xmit_frame; - netdev->get_stats = &e1000_get_stats; - netdev->set_multicast_list = &e1000_set_multi; - netdev->set_mac_address = &e1000_set_mac; - netdev->change_mtu = &e1000_change_mtu; - netdev->do_ioctl = &e1000_ioctl; -#ifdef HAVE_TX_TIMEOUT - netdev->tx_timeout = &e1000_tx_timeout; - netdev->watchdog_timeo = 5 * HZ; -#endif -#ifdef CONFIG_E1000_NAPI - netdev->poll = &e1000_clean; - netdev->weight = 64; -#endif -#ifdef NETIF_F_HW_VLAN_TX - netdev->vlan_rx_register = e1000_vlan_rx_register; - netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid; - netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid; -#endif - - netdev->irq = pdev->irq; - netdev->mem_start = mmio_start; - netdev->mem_end = mmio_start + mmio_len; - netdev->base_addr = adapter->hw.io_base; - - adapter->bd_number = cards_found; - - /* setup the private structure */ - - if(e1000_sw_init(adapter)) - goto err_sw_init; - -#ifdef MAX_SKB_FRAGS - if(adapter->hw.mac_type >= e1000_82543) { -#ifdef NETIF_F_HW_VLAN_TX - netdev->features = NETIF_F_SG | - NETIF_F_HW_CSUM | - NETIF_F_HW_VLAN_TX | - NETIF_F_HW_VLAN_RX | - NETIF_F_HW_VLAN_FILTER; -#else - netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM; -#endif - } else { - netdev->features = NETIF_F_SG; - } - -#ifdef NETIF_F_TSO - if((adapter->hw.mac_type >= e1000_82544) && - (adapter->hw.mac_type != e1000_82547)) - netdev->features |= NETIF_F_TSO; -#endif - - if(pci_using_dac) - netdev->features |= NETIF_F_HIGHDMA; -#endif - - /* before reading the EEPROM, reset the controller to - * put the device in a known good starting state */ - - e1000_reset_hw(&adapter->hw); - - /* make sure the EEPROM is good */ - - if(e1000_validate_eeprom_checksum(&adapter->hw) < 0) { - printk(KERN_ERR "The EEPROM Checksum Is Not Valid\n"); - goto err_eeprom; - } - - /* copy the MAC address out of the EEPROM */ - - e1000_read_mac_addr(&adapter->hw); - memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); - - if(!is_valid_ether_addr(netdev->dev_addr)) - goto err_eeprom; - - e1000_read_part_num(&adapter->hw, &(adapter->part_num)); - - e1000_get_bus_info(&adapter->hw); - - init_timer(&adapter->tx_fifo_stall_timer); - adapter->tx_fifo_stall_timer.function = &e1000_82547_tx_fifo_stall; - adapter->tx_fifo_stall_timer.data = (unsigned long) adapter; - - init_timer(&adapter->watchdog_timer); - adapter->watchdog_timer.function = &e1000_watchdog; - adapter->watchdog_timer.data = (unsigned long) adapter; - - init_timer(&adapter->phy_info_timer); - adapter->phy_info_timer.function = &e1000_update_phy_info; - adapter->phy_info_timer.data = (unsigned long) adapter; - - INIT_WORK(&adapter->tx_timeout_task, - (void (*)(void *))e1000_tx_timeout_task, netdev); - - register_netdev(netdev); - - /* we're going to reset, so assume we have no link for now */ - - netif_carrier_off(netdev); - netif_stop_queue(netdev); - - printk(KERN_INFO "%s: Intel(R) PRO/1000 Network Connection\n", - netdev->name); - e1000_check_options(adapter); - - /* Initial Wake on LAN setting - * If APM wake is enabled in the EEPROM, - * enable the ACPI Magic Packet filter - */ - - switch(adapter->hw.mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - break; - case e1000_82546: - case e1000_82546_rev_3: - if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1) - && (adapter->hw.media_type == e1000_media_type_copper)) { - e1000_read_eeprom(&adapter->hw, - EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); - break; - } - /* Fall Through */ - default: - e1000_read_eeprom(&adapter->hw, - EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); - break; - } - if(eeprom_data & E1000_EEPROM_APME) - adapter->wol |= E1000_WUFC_MAG; - - /* reset the hardware with the new settings */ - - e1000_reset(adapter); - - cards_found++; - return 0; - -err_sw_init: -err_eeprom: - iounmap(adapter->hw.hw_addr); -err_ioremap: - kfree(netdev); -err_alloc_etherdev: - pci_release_regions(pdev); - return -ENOMEM; -} - -/** - * e1000_remove - Device Removal Routine - * @pdev: PCI device information struct - * - * e1000_remove is called by the PCI subsystem to alert the driver - * that it should release a PCI device. The could be caused by a - * Hot-Plug event, or because the driver is going to be removed from - * memory. - **/ - -static void __devexit -e1000_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev->priv; - uint32_t manc; - - if(adapter->hw.mac_type >= e1000_82540 && - adapter->hw.media_type == e1000_media_type_copper) { - manc = E1000_READ_REG(&adapter->hw, MANC); - if(manc & E1000_MANC_SMBUS_EN) { - manc |= E1000_MANC_ARP_EN; - E1000_WRITE_REG(&adapter->hw, MANC, manc); - } - } - - unregister_netdev(netdev); - - e1000_phy_hw_reset(&adapter->hw); - - iounmap(adapter->hw.hw_addr); - pci_release_regions(pdev); - - kfree(netdev); -} - -/** - * e1000_sw_init - Initialize general software structures (struct e1000_adapter) - * @adapter: board private structure to initialize - * - * e1000_sw_init initializes the Adapter private data structure. - * Fields are initialized based on PCI device information and - * OS network device settings (MTU size). - **/ - -static int __devinit -e1000_sw_init(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - - /* PCI config space info */ - - hw->vendor_id = pdev->vendor; - hw->device_id = pdev->device; - hw->subsystem_vendor_id = pdev->subsystem_vendor; - hw->subsystem_id = pdev->subsystem_device; - - pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); - - pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); - - adapter->rx_buffer_len = E1000_RXBUFFER_2048; - hw->max_frame_size = netdev->mtu + - ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; - hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; - - /* identify the MAC */ - - if (e1000_set_mac_type(hw)) { - E1000_ERR("Unknown MAC Type\n"); - return -1; - } - - /* initialize eeprom parameters */ - - e1000_init_eeprom_params(hw); - - /* flow control settings */ - - hw->fc_high_water = E1000_FC_HIGH_THRESH; - hw->fc_low_water = E1000_FC_LOW_THRESH; - hw->fc_pause_time = E1000_FC_PAUSE_TIME; - hw->fc_send_xon = 1; - - if((hw->mac_type == e1000_82541) || - (hw->mac_type == e1000_82547) || - (hw->mac_type == e1000_82541_rev_2) || - (hw->mac_type == e1000_82547_rev_2)) - hw->phy_init_script = 1; - - e1000_set_media_type(hw); - - if(hw->mac_type < e1000_82543) - hw->report_tx_early = 0; - else - hw->report_tx_early = 1; - - hw->wait_autoneg_complete = FALSE; - hw->tbi_compatibility_en = TRUE; - hw->adaptive_ifs = TRUE; - - /* Copper options */ - - if(hw->media_type == e1000_media_type_copper) { - hw->mdix = AUTO_ALL_MODES; - hw->disable_polarity_correction = FALSE; - hw->master_slave = E1000_MASTER_SLAVE; - } - - atomic_set(&adapter->irq_sem, 1); - spin_lock_init(&adapter->stats_lock); - - return 0; -} - -/** - * e1000_open - Called when a network interface is made active - * @netdev: network interface device structure - * - * Returns 0 on success, negative value on failure - * - * The open entry point is called when a network interface is made - * active by the system (IFF_UP). At this point all resources needed - * for transmit and receive operations are allocated, the interrupt - * handler is registered with the OS, the watchdog timer is started, - * and the stack is notified that the interface is ready. - **/ - -static int -e1000_open(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev->priv; - - /* allocate transmit descriptors */ - - if(e1000_setup_tx_resources(adapter)) - goto err_setup_tx; - - /* allocate receive descriptors */ - - if(e1000_setup_rx_resources(adapter)) - goto err_setup_rx; - - if(e1000_up(adapter)) - goto err_up; - - return 0; - -err_up: - e1000_free_rx_resources(adapter); -err_setup_rx: - e1000_free_tx_resources(adapter); -err_setup_tx: - e1000_reset(adapter); - - return -EBUSY; -} - -/** - * e1000_close - Disables a network interface - * @netdev: network interface device structure - * - * Returns 0, this is not allowed to fail - * - * The close entry point is called when an interface is de-activated - * by the OS. The hardware is still under the drivers control, but - * needs to be disabled. A global MAC reset is issued to stop the - * hardware, and all transmit and receive resources are freed. - **/ - -static int -e1000_close(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev->priv; - - e1000_down(adapter); - - e1000_free_tx_resources(adapter); - e1000_free_rx_resources(adapter); - - return 0; -} - -/** - * e1000_setup_tx_resources - allocate Tx resources (Descriptors) - * @adapter: board private structure - * - * Return 0 on success, negative on failure - **/ - -static int -e1000_setup_tx_resources(struct e1000_adapter *adapter) -{ - struct e1000_desc_ring *txdr = &adapter->tx_ring; - struct pci_dev *pdev = adapter->pdev; - int size; - - size = sizeof(struct e1000_buffer) * txdr->count; - txdr->buffer_info = kmalloc(size, GFP_KERNEL); - if(!txdr->buffer_info) { - return -ENOMEM; - } - memset(txdr->buffer_info, 0, size); - - /* round up to nearest 4K */ - - txdr->size = txdr->count * sizeof(struct e1000_tx_desc); - E1000_ROUNDUP(txdr->size, 4096); - - txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); - if(!txdr->desc) { - kfree(txdr->buffer_info); - return -ENOMEM; - } - memset(txdr->desc, 0, txdr->size); - - txdr->next_to_use = 0; - txdr->next_to_clean = 0; - - return 0; -} - -/** - * e1000_configure_tx - Configure 8254x Transmit Unit after Reset - * @adapter: board private structure - * - * Configure the Tx unit of the MAC after a reset. - **/ - -static void -e1000_configure_tx(struct e1000_adapter *adapter) -{ - uint64_t tdba = adapter->tx_ring.dma; - uint32_t tdlen = adapter->tx_ring.count * sizeof(struct e1000_tx_desc); - uint32_t tctl, tipg; - - E1000_WRITE_REG(&adapter->hw, TDBAL, (tdba & 0x00000000ffffffffULL)); - E1000_WRITE_REG(&adapter->hw, TDBAH, (tdba >> 32)); - - E1000_WRITE_REG(&adapter->hw, TDLEN, tdlen); - - /* Setup the HW Tx Head and Tail descriptor pointers */ - - E1000_WRITE_REG(&adapter->hw, TDH, 0); - E1000_WRITE_REG(&adapter->hw, TDT, 0); - - /* Set the default values for the Tx Inter Packet Gap timer */ - - switch (adapter->hw.mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - tipg = DEFAULT_82542_TIPG_IPGT; - tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; - tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; - break; - default: - if(adapter->hw.media_type == e1000_media_type_fiber || - adapter->hw.media_type == e1000_media_type_internal_serdes) - tipg = DEFAULT_82543_TIPG_IPGT_FIBER; - else - tipg = DEFAULT_82543_TIPG_IPGT_COPPER; - tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; - tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; - } - E1000_WRITE_REG(&adapter->hw, TIPG, tipg); - - /* Set the Tx Interrupt Delay register */ - - E1000_WRITE_REG(&adapter->hw, TIDV, adapter->tx_int_delay); - if(adapter->hw.mac_type >= e1000_82540) - E1000_WRITE_REG(&adapter->hw, TADV, adapter->tx_abs_int_delay); - - /* Program the Transmit Control Register */ - - tctl = E1000_READ_REG(&adapter->hw, TCTL); - - tctl &= ~E1000_TCTL_CT; - tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | - (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); - - E1000_WRITE_REG(&adapter->hw, TCTL, tctl); - - e1000_config_collision_dist(&adapter->hw); - - /* Setup Transmit Descriptor Settings for eop descriptor */ - adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP | - E1000_TXD_CMD_IFCS; - - if(adapter->hw.report_tx_early == 1) - adapter->txd_cmd |= E1000_TXD_CMD_RS; - else - adapter->txd_cmd |= E1000_TXD_CMD_RPS; - - /* Cache if we're 82544 running in PCI-X because we'll - * need this to apply a workaround later in the send path. */ - if(adapter->hw.mac_type == e1000_82544 && - adapter->hw.bus_type == e1000_bus_type_pcix) - adapter->pcix_82544 = 1; -} - -/** - * e1000_setup_rx_resources - allocate Rx resources (Descriptors) - * @adapter: board private structure - * - * Returns 0 on success, negative on failure - **/ - -static int -e1000_setup_rx_resources(struct e1000_adapter *adapter) -{ - struct e1000_desc_ring *rxdr = &adapter->rx_ring; - struct pci_dev *pdev = adapter->pdev; - int size; - - size = sizeof(struct e1000_buffer) * rxdr->count; - rxdr->buffer_info = kmalloc(size, GFP_KERNEL); - if(!rxdr->buffer_info) { - return -ENOMEM; - } - memset(rxdr->buffer_info, 0, size); - - /* Round up to nearest 4K */ - - rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc); - E1000_ROUNDUP(rxdr->size, 4096); - - rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); - - if(!rxdr->desc) { - kfree(rxdr->buffer_info); - return -ENOMEM; - } - memset(rxdr->desc, 0, rxdr->size); - - rxdr->next_to_clean = 0; - rxdr->next_to_use = 0; - - return 0; -} - -/** - * e1000_setup_rctl - configure the receive control register - * @adapter: Board private structure - **/ - -static void -e1000_setup_rctl(struct e1000_adapter *adapter) -{ - uint32_t rctl; - - rctl = E1000_READ_REG(&adapter->hw, RCTL); - - rctl &= ~(3 << E1000_RCTL_MO_SHIFT); - - rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | - E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | - (adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT); - - if(adapter->hw.tbi_compatibility_on == 1) - rctl |= E1000_RCTL_SBP; - else - rctl &= ~E1000_RCTL_SBP; - - rctl &= ~(E1000_RCTL_SZ_4096); - switch (adapter->rx_buffer_len) { - case E1000_RXBUFFER_2048: - default: - rctl |= E1000_RCTL_SZ_2048; - rctl &= ~(E1000_RCTL_BSEX | E1000_RCTL_LPE); - break; - case E1000_RXBUFFER_4096: - rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX | E1000_RCTL_LPE; - break; - case E1000_RXBUFFER_8192: - rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX | E1000_RCTL_LPE; - break; - case E1000_RXBUFFER_16384: - rctl |= E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX | E1000_RCTL_LPE; - break; - } - - E1000_WRITE_REG(&adapter->hw, RCTL, rctl); -} - -/** - * e1000_configure_rx - Configure 8254x Receive Unit after Reset - * @adapter: board private structure - * - * Configure the Rx unit of the MAC after a reset. - **/ - -static void -e1000_configure_rx(struct e1000_adapter *adapter) -{ - uint64_t rdba = adapter->rx_ring.dma; - uint32_t rdlen = adapter->rx_ring.count * sizeof(struct e1000_rx_desc); - uint32_t rctl; - uint32_t rxcsum; - - /* make sure receives are disabled while setting up the descriptors */ - - rctl = E1000_READ_REG(&adapter->hw, RCTL); - E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN); - - /* set the Receive Delay Timer Register */ - - E1000_WRITE_REG(&adapter->hw, RDTR, adapter->rx_int_delay); - - if(adapter->hw.mac_type >= e1000_82540) { - E1000_WRITE_REG(&adapter->hw, RADV, adapter->rx_abs_int_delay); - if(adapter->itr > 1) - E1000_WRITE_REG(&adapter->hw, ITR, - 1000000000 / (adapter->itr * 256)); - } - - /* Setup the Base and Length of the Rx Descriptor Ring */ - - E1000_WRITE_REG(&adapter->hw, RDBAL, (rdba & 0x00000000ffffffffULL)); - E1000_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32)); - - E1000_WRITE_REG(&adapter->hw, RDLEN, rdlen); - - /* Setup the HW Rx Head and Tail Descriptor Pointers */ - E1000_WRITE_REG(&adapter->hw, RDH, 0); - E1000_WRITE_REG(&adapter->hw, RDT, 0); - - /* Enable 82543 Receive Checksum Offload for TCP and UDP */ - if((adapter->hw.mac_type >= e1000_82543) && - (adapter->rx_csum == TRUE)) { - rxcsum = E1000_READ_REG(&adapter->hw, RXCSUM); - rxcsum |= E1000_RXCSUM_TUOFL; - E1000_WRITE_REG(&adapter->hw, RXCSUM, rxcsum); - } - - /* Enable Receives */ - - E1000_WRITE_REG(&adapter->hw, RCTL, rctl); -} - -/** - * e1000_free_tx_resources - Free Tx Resources - * @adapter: board private structure - * - * Free all transmit software resources - **/ - -static void -e1000_free_tx_resources(struct e1000_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - - e1000_clean_tx_ring(adapter); - - kfree(adapter->tx_ring.buffer_info); - adapter->tx_ring.buffer_info = NULL; - - pci_free_consistent(pdev, adapter->tx_ring.size, - adapter->tx_ring.desc, adapter->tx_ring.dma); - - adapter->tx_ring.desc = NULL; -} - -/** - * e1000_clean_tx_ring - Free Tx Buffers - * @adapter: board private structure - **/ - -static void -e1000_clean_tx_ring(struct e1000_adapter *adapter) -{ - struct e1000_desc_ring *tx_ring = &adapter->tx_ring; - struct e1000_buffer *buffer_info; - struct pci_dev *pdev = adapter->pdev; - unsigned long size; - unsigned int i; - - /* Free all the Tx ring sk_buffs */ - - for(i = 0; i < tx_ring->count; i++) { - buffer_info = &tx_ring->buffer_info[i]; - if(buffer_info->skb) { - - pci_unmap_page(pdev, - buffer_info->dma, - buffer_info->length, - PCI_DMA_TODEVICE); - - dev_kfree_skb(buffer_info->skb); - - buffer_info->skb = NULL; - } - } - - size = sizeof(struct e1000_buffer) * tx_ring->count; - memset(tx_ring->buffer_info, 0, size); - - /* Zero out the descriptor ring */ - - memset(tx_ring->desc, 0, tx_ring->size); - - tx_ring->next_to_use = 0; - tx_ring->next_to_clean = 0; - - E1000_WRITE_REG(&adapter->hw, TDH, 0); - E1000_WRITE_REG(&adapter->hw, TDT, 0); -} - -/** - * e1000_free_rx_resources - Free Rx Resources - * @adapter: board private structure - * - * Free all receive software resources - **/ - -static void -e1000_free_rx_resources(struct e1000_adapter *adapter) -{ - struct e1000_desc_ring *rx_ring = &adapter->rx_ring; - struct pci_dev *pdev = adapter->pdev; - - e1000_clean_rx_ring(adapter); - - kfree(rx_ring->buffer_info); - rx_ring->buffer_info = NULL; - - pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma); - - rx_ring->desc = NULL; -} - -/** - * e1000_clean_rx_ring - Free Rx Buffers - * @adapter: board private structure - **/ - -static void -e1000_clean_rx_ring(struct e1000_adapter *adapter) -{ - struct e1000_desc_ring *rx_ring = &adapter->rx_ring; - struct e1000_buffer *buffer_info; - struct pci_dev *pdev = adapter->pdev; - unsigned long size; - unsigned int i; - - /* Free all the Rx ring sk_buffs */ - - for(i = 0; i < rx_ring->count; i++) { - buffer_info = &rx_ring->buffer_info[i]; - if(buffer_info->skb) { - - pci_unmap_single(pdev, - buffer_info->dma, - buffer_info->length, - PCI_DMA_FROMDEVICE); - - dev_kfree_skb(buffer_info->skb); - - buffer_info->skb = NULL; - } - } - - size = sizeof(struct e1000_buffer) * rx_ring->count; - memset(rx_ring->buffer_info, 0, size); - - /* Zero out the descriptor ring */ - - memset(rx_ring->desc, 0, rx_ring->size); - - rx_ring->next_to_clean = 0; - rx_ring->next_to_use = 0; - - E1000_WRITE_REG(&adapter->hw, RDH, 0); - E1000_WRITE_REG(&adapter->hw, RDT, 0); -} - -/* The 82542 2.0 (revision 2) needs to have the receive unit in reset - * and memory write and invalidate disabled for certain operations - */ -static void -e1000_enter_82542_rst(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - uint32_t rctl; - - e1000_pci_clear_mwi(&adapter->hw); - - rctl = E1000_READ_REG(&adapter->hw, RCTL); - rctl |= E1000_RCTL_RST; - E1000_WRITE_REG(&adapter->hw, RCTL, rctl); - E1000_WRITE_FLUSH(&adapter->hw); - mdelay(5); - - if(netif_running(netdev)) - e1000_clean_rx_ring(adapter); -} - -static void -e1000_leave_82542_rst(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - uint32_t rctl; - - rctl = E1000_READ_REG(&adapter->hw, RCTL); - rctl &= ~E1000_RCTL_RST; - E1000_WRITE_REG(&adapter->hw, RCTL, rctl); - E1000_WRITE_FLUSH(&adapter->hw); - mdelay(5); - - if(adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE) - e1000_pci_set_mwi(&adapter->hw); - - if(netif_running(netdev)) { - e1000_configure_rx(adapter); - e1000_alloc_rx_buffers(adapter); - } -} - -/** - * e1000_set_mac - Change the Ethernet Address of the NIC - * @netdev: network interface device structure - * @p: pointer to an address structure - * - * Returns 0 on success, negative on failure - **/ - -static int -e1000_set_mac(struct net_device *netdev, void *p) -{ - struct e1000_adapter *adapter = netdev->priv; - struct sockaddr *addr = p; - - if(!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - /* 82542 2.0 needs to be in reset to write receive address registers */ - - if(adapter->hw.mac_type == e1000_82542_rev2_0) - e1000_enter_82542_rst(adapter); - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); - - e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0); - - if(adapter->hw.mac_type == e1000_82542_rev2_0) - e1000_leave_82542_rst(adapter); - - return 0; -} - -/** - * e1000_set_multi - Multicast and Promiscuous mode set - * @netdev: network interface device structure - * - * The set_multi entry point is called whenever the multicast address - * list or the network interface flags are updated. This routine is - * responsible for configuring the hardware for proper multicast, - * promiscuous mode, and all-multi behavior. - **/ - -static void -e1000_set_multi(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev->priv; - struct e1000_hw *hw = &adapter->hw; - struct dev_mc_list *mc_ptr; - uint32_t rctl; - uint32_t hash_value; - int i; - - /* Check for Promiscuous and All Multicast modes */ - - rctl = E1000_READ_REG(hw, RCTL); - - if(netdev->flags & IFF_PROMISC) { - rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); - } else if(netdev->flags & IFF_ALLMULTI) { - rctl |= E1000_RCTL_MPE; - rctl &= ~E1000_RCTL_UPE; - } else { - rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); - } - - E1000_WRITE_REG(hw, RCTL, rctl); - - /* 82542 2.0 needs to be in reset to write receive address registers */ - - if(hw->mac_type == e1000_82542_rev2_0) - e1000_enter_82542_rst(adapter); - - /* load the first 14 multicast address into the exact filters 1-14 - * RAR 0 is used for the station MAC adddress - * if there are not 14 addresses, go ahead and clear the filters - */ - mc_ptr = netdev->mc_list; - - for(i = 1; i < E1000_RAR_ENTRIES; i++) { - if(mc_ptr) { - e1000_rar_set(hw, mc_ptr->dmi_addr, i); - mc_ptr = mc_ptr->next; - } else { - E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0); - E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0); - } - } - - /* clear the old settings from the multicast hash table */ - - for(i = 0; i < E1000_NUM_MTA_REGISTERS; i++) - E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); - - /* load any remaining addresses into the hash table */ - - for(; mc_ptr; mc_ptr = mc_ptr->next) { - hash_value = e1000_hash_mc_addr(hw, mc_ptr->dmi_addr); - e1000_mta_set(hw, hash_value); - } - - if(hw->mac_type == e1000_82542_rev2_0) - e1000_leave_82542_rst(adapter); -} - -static void -e1000_tx_flush(struct e1000_adapter *adapter) -{ - uint32_t ctrl, tctl, txcw, icr; - - e1000_irq_disable(adapter); - - if(adapter->hw.mac_type < e1000_82543) { - /* Transmit Unit Reset */ - tctl = E1000_READ_REG(&adapter->hw, TCTL); - E1000_WRITE_REG(&adapter->hw, TCTL, tctl | E1000_TCTL_RST); - E1000_WRITE_REG(&adapter->hw, TCTL, tctl); - e1000_clean_tx_ring(adapter); - e1000_configure_tx(adapter); - } else { - txcw = E1000_READ_REG(&adapter->hw, TXCW); - E1000_WRITE_REG(&adapter->hw, TXCW, txcw & ~E1000_TXCW_ANE); - - ctrl = E1000_READ_REG(&adapter->hw, CTRL); - E1000_WRITE_REG(&adapter->hw, CTRL, ctrl | E1000_CTRL_SLU | - E1000_CTRL_ILOS); - - mdelay(10); - - e1000_clean_tx_irq(adapter); - E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); - E1000_WRITE_REG(&adapter->hw, TXCW, txcw); - - /* clear the link status change interrupts this caused */ - icr = E1000_READ_REG(&adapter->hw, ICR); - } - - e1000_irq_enable(adapter); -} - -/* need to wait a few seconds after link up to get diagnostic information from the phy */ - -static void -e1000_update_phy_info(unsigned long data) -{ - struct e1000_adapter *adapter = (struct e1000_adapter *) data; - e1000_phy_get_info(&adapter->hw, &adapter->phy_info); -} - -/** - * e1000_82547_tx_fifo_stall - Timer Call-back - * @data: pointer to adapter cast into an unsigned long - **/ - -static void -e1000_82547_tx_fifo_stall(unsigned long data) -{ - struct e1000_adapter *adapter = (struct e1000_adapter *) data; - struct net_device *netdev = adapter->netdev; - uint32_t tctl; - - if(atomic_read(&adapter->tx_fifo_stall)) { - if((E1000_READ_REG(&adapter->hw, TDT) == - E1000_READ_REG(&adapter->hw, TDH)) && - (E1000_READ_REG(&adapter->hw, TDFT) == - E1000_READ_REG(&adapter->hw, TDFH)) && - (E1000_READ_REG(&adapter->hw, TDFTS) == - E1000_READ_REG(&adapter->hw, TDFHS))) { - tctl = E1000_READ_REG(&adapter->hw, TCTL); - E1000_WRITE_REG(&adapter->hw, TCTL, - tctl & ~E1000_TCTL_EN); - E1000_WRITE_REG(&adapter->hw, TDFT, - adapter->tx_head_addr); - E1000_WRITE_REG(&adapter->hw, TDFH, - adapter->tx_head_addr); - E1000_WRITE_REG(&adapter->hw, TDFTS, - adapter->tx_head_addr); - E1000_WRITE_REG(&adapter->hw, TDFHS, - adapter->tx_head_addr); - E1000_WRITE_REG(&adapter->hw, TCTL, tctl); - E1000_WRITE_FLUSH(&adapter->hw); - - adapter->tx_fifo_head = 0; - atomic_set(&adapter->tx_fifo_stall, 0); - netif_wake_queue(netdev); - } else { - mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1); - } - } -} - -/** - * e1000_watchdog - Timer Call-back - * @data: pointer to netdev cast into an unsigned long - **/ - -static void -e1000_watchdog(unsigned long data) -{ - struct e1000_adapter *adapter = (struct e1000_adapter *) data; - struct net_device *netdev = adapter->netdev; - struct e1000_desc_ring *txdr = &adapter->tx_ring; - unsigned int i; - - e1000_check_for_link(&adapter->hw); - - if(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU) { - if(!netif_carrier_ok(netdev)) { - e1000_get_speed_and_duplex(&adapter->hw, - &adapter->link_speed, - &adapter->link_duplex); - - printk(KERN_INFO - "e1000: %s NIC Link is Up %d Mbps %s\n", - netdev->name, adapter->link_speed, - adapter->link_duplex == FULL_DUPLEX ? - "Full Duplex" : "Half Duplex"); - - netif_carrier_on(netdev); - netif_wake_queue(netdev); - mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ); - adapter->smartspeed = 0; - } - } else { - if(netif_carrier_ok(netdev)) { - adapter->link_speed = 0; - adapter->link_duplex = 0; - printk(KERN_INFO - "e1000: %s NIC Link is Down\n", - netdev->name); - netif_carrier_off(netdev); - netif_stop_queue(netdev); - mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ); - } - - e1000_smartspeed(adapter); - } - - e1000_update_stats(adapter); - e1000_update_adaptive(&adapter->hw); - - if(!netif_carrier_ok(netdev)) { - if(E1000_DESC_UNUSED(txdr) + 1 < txdr->count) { - unsigned long flags; - spin_lock_irqsave(&netdev->xmit_lock, flags); - e1000_tx_flush(adapter); - spin_unlock_irqrestore(&netdev->xmit_lock, flags); - } - } - - /* Dynamic mode for Interrupt Throttle Rate (ITR) */ - if(adapter->hw.mac_type >= e1000_82540 && adapter->itr == 1) { - /* Symmetric Tx/Rx gets a reduced ITR=2000; Total - * asymmetrical Tx or Rx gets ITR=8000; everyone - * else is between 2000-8000. */ - uint32_t goc = (adapter->gotcl + adapter->gorcl) / 10000; - uint32_t dif = (adapter->gotcl > adapter->gorcl ? - adapter->gotcl - adapter->gorcl : - adapter->gorcl - adapter->gotcl) / 10000; - uint32_t itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000; - E1000_WRITE_REG(&adapter->hw, ITR, 1000000000 / (itr * 256)); - } - - /* Cause software interrupt to ensure rx ring is cleaned */ - E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0); - - /* Early detection of hung controller */ - i = txdr->next_to_clean; - if(txdr->buffer_info[i].dma && - time_after(jiffies, txdr->buffer_info[i].time_stamp + HZ) && - !(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF)) - netif_stop_queue(netdev); - - /* Reset the timer */ - mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); -} - -#define E1000_TX_FLAGS_CSUM 0x00000001 -#define E1000_TX_FLAGS_VLAN 0x00000002 -#define E1000_TX_FLAGS_TSO 0x00000004 -#define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 -#define E1000_TX_FLAGS_VLAN_SHIFT 16 - -static inline boolean_t -e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb) -{ -#ifdef NETIF_F_TSO - struct e1000_context_desc *context_desc; - unsigned int i; - uint8_t ipcss, ipcso, tucss, tucso, hdr_len; - uint16_t ipcse, tucse, mss; - - if(skb_shinfo(skb)->tso_size) { - hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); - mss = skb_shinfo(skb)->tso_size; - skb->nh.iph->tot_len = 0; - skb->nh.iph->check = 0; - skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr, - skb->nh.iph->daddr, - 0, - IPPROTO_TCP, - 0); - ipcss = skb->nh.raw - skb->data; - ipcso = (void *)&(skb->nh.iph->check) - (void *)skb->data; - ipcse = skb->h.raw - skb->data - 1; - tucss = skb->h.raw - skb->data; - tucso = (void *)&(skb->h.th->check) - (void *)skb->data; - tucse = 0; - - i = adapter->tx_ring.next_to_use; - context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i); - - context_desc->lower_setup.ip_fields.ipcss = ipcss; - context_desc->lower_setup.ip_fields.ipcso = ipcso; - context_desc->lower_setup.ip_fields.ipcse = cpu_to_le16(ipcse); - context_desc->upper_setup.tcp_fields.tucss = tucss; - context_desc->upper_setup.tcp_fields.tucso = tucso; - context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse); - context_desc->tcp_seg_setup.fields.mss = cpu_to_le16(mss); - context_desc->tcp_seg_setup.fields.hdr_len = hdr_len; - context_desc->cmd_and_length = cpu_to_le32( - E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | - E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP | - (skb->len - (hdr_len))); - - if(++i == adapter->tx_ring.count) i = 0; - adapter->tx_ring.next_to_use = i; - - return TRUE; - } -#endif - - return FALSE; -} - -static inline boolean_t -e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) -{ - struct e1000_context_desc *context_desc; - unsigned int i; - uint8_t css, cso; - - if(skb->ip_summed == CHECKSUM_HW) { - css = skb->h.raw - skb->data; - cso = (skb->h.raw + skb->csum) - skb->data; - - i = adapter->tx_ring.next_to_use; - context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i); - - context_desc->upper_setup.tcp_fields.tucss = css; - context_desc->upper_setup.tcp_fields.tucso = cso; - context_desc->upper_setup.tcp_fields.tucse = 0; - context_desc->tcp_seg_setup.data = 0; - context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT); - - if(++i == adapter->tx_ring.count) i = 0; - adapter->tx_ring.next_to_use = i; - - return TRUE; - } - - return FALSE; -} - -#define E1000_MAX_TXD_PWR 12 -#define E1000_MAX_DATA_PER_TXD (1<tx_ring; - struct e1000_buffer *buffer_info; - unsigned int len = skb->len, max_per_txd = E1000_MAX_DATA_PER_TXD; - unsigned int offset = 0, size, count = 0, i; - -#ifdef MAX_SKB_FRAGS -#ifdef NETIF_F_TSO - unsigned int mss = skb_shinfo(skb)->tso_size; - /* The controller does a simple calculation to - * make sure there is enough room in the FIFO before - * initiating the DMA for each buffer. The calc is: - * 4 = ceil(buffer len/mss). To make sure we don't - * overrun the FIFO, adjust the max buffer len if mss - * drops. */ - if(mss) max_per_txd = min(mss << 2, max_per_txd); -#endif - unsigned int nr_frags = skb_shinfo(skb)->nr_frags; - unsigned int f; - len -= skb->data_len; -#endif - - i = tx_ring->next_to_use; - - while(len) { - buffer_info = &tx_ring->buffer_info[i]; - size = min(len, max_per_txd); -#ifdef NETIF_F_TSO - /* Workaround for premature desc write-backs - * in TSO mode. Append 4-byte sentinel desc */ - if(mss && !nr_frags && size == len && size > 8) - size -= 4; -#endif - /* Workaround for potential 82544 hang in PCI-X. Avoid - * terminating buffers within evenly-aligned dwords. */ - if(adapter->pcix_82544 && - !((unsigned long)(skb->data + offset + size - 1) & 4) && - size > 4) - size -= 4; - - buffer_info->length = size; - buffer_info->dma = - pci_map_single(adapter->pdev, - skb->data + offset, - size, - PCI_DMA_TODEVICE); - buffer_info->time_stamp = jiffies; - - len -= size; - offset += size; - count++; - if(++i == tx_ring->count) i = 0; - } - -#ifdef MAX_SKB_FRAGS - for(f = 0; f < nr_frags; f++) { - struct skb_frag_struct *frag; - - frag = &skb_shinfo(skb)->frags[f]; - len = frag->size; - offset = frag->page_offset; - - while(len) { - buffer_info = &tx_ring->buffer_info[i]; - size = min(len, max_per_txd); -#ifdef NETIF_F_TSO - /* Workaround for premature desc write-backs - * in TSO mode. Append 4-byte sentinel desc */ - if(mss && f == (nr_frags-1) && size == len && size > 8) - size -= 4; -#endif - /* Workaround for potential 82544 hang in PCI-X. - * Avoid terminating buffers within evenly-aligned - * dwords. */ - if(adapter->pcix_82544 && - !((unsigned long)(frag->page+offset+size-1) & 4) && - size > 4) - size -= 4; - - buffer_info->length = size; - buffer_info->dma = - pci_map_page(adapter->pdev, - frag->page, - offset, - size, - PCI_DMA_TODEVICE); - buffer_info->time_stamp = jiffies; - - len -= size; - offset += size; - count++; - if(++i == tx_ring->count) i = 0; - } - } -#endif - - if(E1000_DESC_UNUSED(&adapter->tx_ring) < count) { - - /* There aren't enough descriptors available to queue up - * this send, so undo the mapping and abort the send. - * We could have done the check before we mapped the skb, - * but because of all the workarounds (above), it's too - * difficult to predict how many we're going to need.*/ - i = first; - - while(count--) { - buffer_info = &tx_ring->buffer_info[i]; - if(buffer_info->dma) { - pci_unmap_page(adapter->pdev, - buffer_info->dma, - buffer_info->length, - PCI_DMA_TODEVICE); - buffer_info->dma = 0; - } - if(++i == tx_ring->count) i = 0; - } - - return 0; - } - - i = (i == 0) ? tx_ring->count - 1 : i - 1; - tx_ring->buffer_info[i].skb = skb; - tx_ring->buffer_info[first].next_to_watch = i; - - return count; -} - -static inline void -e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags) -{ - struct e1000_desc_ring *tx_ring = &adapter->tx_ring; - struct e1000_tx_desc *tx_desc = NULL; - struct e1000_buffer *buffer_info; - uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS; - unsigned int i; - - if(tx_flags & E1000_TX_FLAGS_TSO) { - txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | - E1000_TXD_CMD_TSE; - txd_upper |= (E1000_TXD_POPTS_IXSM | E1000_TXD_POPTS_TXSM) << 8; - } - - if(tx_flags & E1000_TX_FLAGS_CSUM) { - txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; - txd_upper |= E1000_TXD_POPTS_TXSM << 8; - } - - if(tx_flags & E1000_TX_FLAGS_VLAN) { - txd_lower |= E1000_TXD_CMD_VLE; - txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK); - } - - i = tx_ring->next_to_use; - - while(count--) { - buffer_info = &tx_ring->buffer_info[i]; - tx_desc = E1000_TX_DESC(*tx_ring, i); - tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - tx_desc->lower.data = - cpu_to_le32(txd_lower | buffer_info->length); - tx_desc->upper.data = cpu_to_le32(txd_upper); - if(++i == tx_ring->count) i = 0; - } - - tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd); - - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). */ - wmb(); - - tx_ring->next_to_use = i; - E1000_WRITE_REG(&adapter->hw, TDT, i); -} - -/** - * 82547 workaround to avoid controller hang in half-duplex environment. - * The workaround is to avoid queuing a large packet that would span - * the internal Tx FIFO ring boundary by notifying the stack to resend - * the packet at a later time. This gives the Tx FIFO an opportunity to - * flush all packets. When that occurs, we reset the Tx FIFO pointers - * to the beginning of the Tx FIFO. - **/ - -#define E1000_FIFO_HDR 0x10 -#define E1000_82547_PAD_LEN 0x3E0 - -static inline int -e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb) -{ - uint32_t fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head; - uint32_t skb_fifo_len = skb->len + E1000_FIFO_HDR; - - E1000_ROUNDUP(skb_fifo_len, E1000_FIFO_HDR); - - if(adapter->link_duplex != HALF_DUPLEX) - goto no_fifo_stall_required; - - if(atomic_read(&adapter->tx_fifo_stall)) - return 1; - - if(skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) { - atomic_set(&adapter->tx_fifo_stall, 1); - return 1; - } - -no_fifo_stall_required: - adapter->tx_fifo_head += skb_fifo_len; - if(adapter->tx_fifo_head >= adapter->tx_fifo_size) - adapter->tx_fifo_head -= adapter->tx_fifo_size; - return 0; -} - -static int -e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev->priv; - unsigned int first; - unsigned int tx_flags = 0; - int count; - - if(skb->len <= 0) { - dev_kfree_skb_any(skb); - return 0; - } - - if(adapter->hw.mac_type == e1000_82547) { - if(e1000_82547_fifo_workaround(adapter, skb)) { - netif_stop_queue(netdev); - mod_timer(&adapter->tx_fifo_stall_timer, jiffies); - return 1; - } - } - -#ifdef NETIF_F_HW_VLAN_TX - if(adapter->vlgrp && vlan_tx_tag_present(skb)) { - tx_flags |= E1000_TX_FLAGS_VLAN; - tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT); - } -#endif - - first = adapter->tx_ring.next_to_use; - - if(e1000_tso(adapter, skb)) - tx_flags |= E1000_TX_FLAGS_TSO; - else if(e1000_tx_csum(adapter, skb)) - tx_flags |= E1000_TX_FLAGS_CSUM; - - if((count = e1000_tx_map(adapter, skb, first))) - e1000_tx_queue(adapter, count, tx_flags); - else { - netif_stop_queue(netdev); - return 1; - } - - netdev->trans_start = jiffies; - - return 0; -} - -/** - * e1000_tx_timeout - Respond to a Tx Hang - * @netdev: network interface device structure - **/ - -static void -e1000_tx_timeout(struct net_device *netdev) -{ -#if 0 - struct e1000_adapter *adapter = netdev->priv; - - /* Do the reset outside of interrupt context */ - schedule_work(&adapter->tx_timeout_task); -#endif - e1000_tx_timeout_task(netdev); // XXXX HACK!!! XEN -} - -static void -e1000_tx_timeout_task(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev->priv; - - netif_device_detach(netdev); - e1000_down(adapter); - e1000_up(adapter); - netif_device_attach(netdev); -} - -/** - * e1000_get_stats - Get System Network Statistics - * @netdev: network interface device structure - * - * Returns the address of the device statistics structure. - * The statistics are actually updated from the timer callback. - **/ - -static struct net_device_stats * -e1000_get_stats(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev->priv; - - return &adapter->net_stats; -} - -/** - * e1000_change_mtu - Change the Maximum Transfer Unit - * @netdev: network interface device structure - * @new_mtu: new value for maximum frame size - * - * Returns 0 on success, negative on failure - **/ - -static int -e1000_change_mtu(struct net_device *netdev, int new_mtu) -{ - struct e1000_adapter *adapter = netdev->priv; - int old_mtu = adapter->rx_buffer_len; - int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; - - if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || - (max_frame > MAX_JUMBO_FRAME_SIZE)) { - E1000_ERR("Invalid MTU setting\n"); - return -EINVAL; - } - - if(max_frame <= MAXIMUM_ETHERNET_FRAME_SIZE) { - adapter->rx_buffer_len = E1000_RXBUFFER_2048; - - } else if(adapter->hw.mac_type < e1000_82543) { - E1000_ERR("Jumbo Frames not supported on 82542\n"); - return -EINVAL; - - } else if(max_frame <= E1000_RXBUFFER_4096) { - adapter->rx_buffer_len = E1000_RXBUFFER_4096; - - } else if(max_frame <= E1000_RXBUFFER_8192) { - adapter->rx_buffer_len = E1000_RXBUFFER_8192; - - } else { - adapter->rx_buffer_len = E1000_RXBUFFER_16384; - } - - if(old_mtu != adapter->rx_buffer_len && netif_running(netdev)) { - - e1000_down(adapter); - e1000_up(adapter); - } - - netdev->mtu = new_mtu; - adapter->hw.max_frame_size = max_frame; - - return 0; -} - -/** - * e1000_update_stats - Update the board statistics counters - * @adapter: board private structure - **/ - -static void -e1000_update_stats(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - unsigned long flags; - uint16_t phy_tmp; - -#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF - - spin_lock_irqsave(&adapter->stats_lock, flags); - - /* these counters are modified from e1000_adjust_tbi_stats, - * called from the interrupt context, so they must only - * be written while holding adapter->stats_lock - */ - - adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS); - adapter->stats.gprc += E1000_READ_REG(hw, GPRC); - adapter->gorcl = E1000_READ_REG(hw, GORCL); - adapter->stats.gorcl += adapter->gorcl; - adapter->stats.gorch += E1000_READ_REG(hw, GORCH); - adapter->stats.bprc += E1000_READ_REG(hw, BPRC); - adapter->stats.mprc += E1000_READ_REG(hw, MPRC); - adapter->stats.roc += E1000_READ_REG(hw, ROC); - adapter->stats.prc64 += E1000_READ_REG(hw, PRC64); - adapter->stats.prc127 += E1000_READ_REG(hw, PRC127); - adapter->stats.prc255 += E1000_READ_REG(hw, PRC255); - adapter->stats.prc511 += E1000_READ_REG(hw, PRC511); - adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023); - adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522); - - spin_unlock_irqrestore(&adapter->stats_lock, flags); - - /* the rest of the counters are only modified here */ - - adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS); - adapter->stats.mpc += E1000_READ_REG(hw, MPC); - adapter->stats.scc += E1000_READ_REG(hw, SCC); - adapter->stats.ecol += E1000_READ_REG(hw, ECOL); - adapter->stats.mcc += E1000_READ_REG(hw, MCC); - adapter->stats.latecol += E1000_READ_REG(hw, LATECOL); - adapter->stats.dc += E1000_READ_REG(hw, DC); - adapter->stats.sec += E1000_READ_REG(hw, SEC); - adapter->stats.rlec += E1000_READ_REG(hw, RLEC); - adapter->stats.xonrxc += E1000_READ_REG(hw, XONRXC); - adapter->stats.xontxc += E1000_READ_REG(hw, XONTXC); - adapter->stats.xoffrxc += E1000_READ_REG(hw, XOFFRXC); - adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC); - adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC); - adapter->stats.gptc += E1000_READ_REG(hw, GPTC); - adapter->gotcl = E1000_READ_REG(hw, GOTCL); - adapter->stats.gotcl += adapter->gotcl; - adapter->stats.gotch += E1000_READ_REG(hw, GOTCH); - adapter->stats.rnbc += E1000_READ_REG(hw, RNBC); - adapter->stats.ruc += E1000_READ_REG(hw, RUC); - adapter->stats.rfc += E1000_READ_REG(hw, RFC); - adapter->stats.rjc += E1000_READ_REG(hw, RJC); - adapter->stats.torl += E1000_READ_REG(hw, TORL); - adapter->stats.torh += E1000_READ_REG(hw, TORH); - adapter->stats.totl += E1000_READ_REG(hw, TOTL); - adapter->stats.toth += E1000_READ_REG(hw, TOTH); - adapter->stats.tpr += E1000_READ_REG(hw, TPR); - adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64); - adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127); - adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255); - adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511); - adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023); - adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522); - adapter->stats.mptc += E1000_READ_REG(hw, MPTC); - adapter->stats.bptc += E1000_READ_REG(hw, BPTC); - - /* used for adaptive IFS */ - - hw->tx_packet_delta = E1000_READ_REG(hw, TPT); - adapter->stats.tpt += hw->tx_packet_delta; - hw->collision_delta = E1000_READ_REG(hw, COLC); - adapter->stats.colc += hw->collision_delta; - - if(hw->mac_type >= e1000_82543) { - adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC); - adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC); - adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS); - adapter->stats.cexterr += E1000_READ_REG(hw, CEXTERR); - adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC); - adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC); - } - - /* Fill out the OS statistics structure */ - - adapter->net_stats.rx_packets = adapter->stats.gprc; - adapter->net_stats.tx_packets = adapter->stats.gptc; - adapter->net_stats.rx_bytes = adapter->stats.gorcl; - adapter->net_stats.tx_bytes = adapter->stats.gotcl; - adapter->net_stats.multicast = adapter->stats.mprc; - adapter->net_stats.collisions = adapter->stats.colc; - - /* Rx Errors */ - - adapter->net_stats.rx_errors = adapter->stats.rxerrc + - adapter->stats.crcerrs + adapter->stats.algnerrc + - adapter->stats.rlec + adapter->stats.rnbc + - adapter->stats.mpc + adapter->stats.cexterr; - adapter->net_stats.rx_dropped = adapter->stats.rnbc; - adapter->net_stats.rx_length_errors = adapter->stats.rlec; - adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; - adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc; - adapter->net_stats.rx_fifo_errors = adapter->stats.mpc; - adapter->net_stats.rx_missed_errors = adapter->stats.mpc; - - /* Tx Errors */ - - adapter->net_stats.tx_errors = adapter->stats.ecol + - adapter->stats.latecol; - adapter->net_stats.tx_aborted_errors = adapter->stats.ecol; - adapter->net_stats.tx_window_errors = adapter->stats.latecol; - adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs; - - /* Tx Dropped needs to be maintained elsewhere */ - - /* Phy Stats */ - - if(hw->media_type == e1000_media_type_copper) { - if((adapter->link_speed == SPEED_1000) && - (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) { - phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; - adapter->phy_stats.idle_errors += phy_tmp; - } - - if((hw->mac_type <= e1000_82546) && - (hw->phy_type == e1000_phy_m88) && - !e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp)) - adapter->phy_stats.receive_errors += phy_tmp; - } -} - -/** - * e1000_irq_disable - Mask off interrupt generation on the NIC - * @adapter: board private structure - **/ - -static inline void -e1000_irq_disable(struct e1000_adapter *adapter) -{ - atomic_inc(&adapter->irq_sem); - E1000_WRITE_REG(&adapter->hw, IMC, ~0); - E1000_WRITE_FLUSH(&adapter->hw); - synchronize_irq(adapter->netdev->irq); -} - -/** - * e1000_irq_enable - Enable default interrupt generation settings - * @adapter: board private structure - **/ - -static inline void -e1000_irq_enable(struct e1000_adapter *adapter) -{ - if(atomic_dec_and_test(&adapter->irq_sem)) { - E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK); - E1000_WRITE_FLUSH(&adapter->hw); - } -} - -/** - * e1000_intr - Interrupt Handler - * @irq: interrupt number - * @data: pointer to a network interface device structure - * @pt_regs: CPU registers structure - **/ - -static irqreturn_t -e1000_intr(int irq, void *data, struct pt_regs *regs) -{ - struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev->priv; - uint32_t icr = E1000_READ_REG(&adapter->hw, ICR); -#ifndef CONFIG_E1000_NAPI - unsigned int i; -#endif - - if(!icr) - return IRQ_NONE; /* Not our interrupt */ - - if(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { - adapter->hw.get_link_status = 1; - mod_timer(&adapter->watchdog_timer, jiffies); - } - -#ifdef CONFIG_E1000_NAPI - if(netif_rx_schedule_prep(netdev)) { - - /* Disable interrupts and register for poll. The flush - of the posted write is intentionally left out. - */ - - atomic_inc(&adapter->irq_sem); - E1000_WRITE_REG(&adapter->hw, IMC, ~0); - __netif_rx_schedule(netdev); - } -#else - for(i = 0; i < E1000_MAX_INTR; i++) - if(!e1000_clean_rx_irq(adapter) & - !e1000_clean_tx_irq(adapter)) - break; -#endif -#ifdef E1000_COUNT_ICR - adapter->icr_txdw += icr & 0x01; - icr >>= 1; - adapter->icr_txqe += icr & 0x01; - icr >>= 1; - adapter->icr_lsc += icr & 0x01; - icr >>= 1; - adapter->icr_rxseq += icr & 0x01; - icr >>= 1; - adapter->icr_rxdmt += icr & 0x01; - icr >>= 2; - adapter->icr_rxo += icr & 0x01; - icr >>= 1; - adapter->icr_rxt += icr & 0x01; - icr >>= 2; - adapter->icr_mdac += icr & 0x01; - icr >>= 1; - adapter->icr_rxcfg += icr & 0x01; - icr >>= 1; - adapter->icr_gpi += icr & 0x01; -#endif - - return IRQ_HANDLED; -} - -#ifdef CONFIG_E1000_NAPI -/** - * e1000_clean - NAPI Rx polling callback - * @adapter: board private structure - **/ - -static int -e1000_clean(struct net_device *netdev, int *budget) -{ - struct e1000_adapter *adapter = netdev->priv; - int work_to_do = min(*budget, netdev->quota); - int work_done = 0; - - e1000_clean_tx_irq(adapter); - e1000_clean_rx_irq(adapter, &work_done, work_to_do); - - *budget -= work_done; - netdev->quota -= work_done; - - if(work_done < work_to_do) { - netif_rx_complete(netdev); - e1000_irq_enable(adapter); - } - - return (work_done >= work_to_do); -} -#endif - -/** - * e1000_clean_tx_irq - Reclaim resources after transmit completes - * @adapter: board private structure - **/ - -static boolean_t -e1000_clean_tx_irq(struct e1000_adapter *adapter) -{ - struct e1000_desc_ring *tx_ring = &adapter->tx_ring; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_tx_desc *tx_desc, *eop_desc; - struct e1000_buffer *buffer_info; - unsigned int i, eop; - boolean_t cleaned = FALSE; - - i = tx_ring->next_to_clean; - eop = tx_ring->buffer_info[i].next_to_watch; - eop_desc = E1000_TX_DESC(*tx_ring, eop); - - while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { - - for(cleaned = FALSE; !cleaned; ) { - tx_desc = E1000_TX_DESC(*tx_ring, i); - buffer_info = &tx_ring->buffer_info[i]; - - if(buffer_info->dma) { - - pci_unmap_page(pdev, - buffer_info->dma, - buffer_info->length, - PCI_DMA_TODEVICE); - - buffer_info->dma = 0; - } - - if(buffer_info->skb) { - - dev_kfree_skb_any(buffer_info->skb); - - buffer_info->skb = NULL; - } - - tx_desc->buffer_addr = 0; - tx_desc->lower.data = 0; - tx_desc->upper.data = 0; - - cleaned = (i == eop); - if(++i == tx_ring->count) i = 0; - } - - eop = tx_ring->buffer_info[i].next_to_watch; - eop_desc = E1000_TX_DESC(*tx_ring, eop); - } - - tx_ring->next_to_clean = i; - - if(cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) - netif_wake_queue(netdev); - - return cleaned; -} - -/** - * e1000_clean_rx_irq - Send received data up the network stack, - * @adapter: board private structure - **/ - -static boolean_t -#ifdef CONFIG_E1000_NAPI -e1000_clean_rx_irq(struct e1000_adapter *adapter, int *work_done, - int work_to_do) -#else -e1000_clean_rx_irq(struct e1000_adapter *adapter) -#endif -{ - struct e1000_desc_ring *rx_ring = &adapter->rx_ring; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_rx_desc *rx_desc; - struct e1000_buffer *buffer_info; - struct sk_buff *skb; - unsigned long flags; - uint32_t length; - uint8_t last_byte; - unsigned int i; - boolean_t cleaned = FALSE; - - i = rx_ring->next_to_clean; - rx_desc = E1000_RX_DESC(*rx_ring, i); - - while(rx_desc->status & E1000_RXD_STAT_DD) { - buffer_info = &rx_ring->buffer_info[i]; - -#ifdef CONFIG_E1000_NAPI - if(*work_done >= work_to_do) - break; - - (*work_done)++; -#endif - - cleaned = TRUE; - - pci_unmap_single(pdev, - buffer_info->dma, - buffer_info->length, - PCI_DMA_FROMDEVICE); - - skb = buffer_info->skb; - length = le16_to_cpu(rx_desc->length); - - if(!(rx_desc->status & E1000_RXD_STAT_EOP)) { - - /* All receives must fit into a single buffer */ - - E1000_DBG("Receive packet consumed multiple buffers\n"); - - dev_kfree_skb_irq(skb); - rx_desc->status = 0; - buffer_info->skb = NULL; - - if(++i == rx_ring->count) i = 0; - - rx_desc = E1000_RX_DESC(*rx_ring, i); - continue; - } - - if(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) { - - last_byte = *(skb->data + length - 1); - - if(TBI_ACCEPT(&adapter->hw, rx_desc->status, - rx_desc->errors, length, last_byte)) { - - spin_lock_irqsave(&adapter->stats_lock, flags); - - e1000_tbi_adjust_stats(&adapter->hw, - &adapter->stats, - length, skb->data); - - spin_unlock_irqrestore(&adapter->stats_lock, - flags); - length--; - } else { - - dev_kfree_skb_irq(skb); - rx_desc->status = 0; - buffer_info->skb = NULL; - - if(++i == rx_ring->count) i = 0; - - rx_desc = E1000_RX_DESC(*rx_ring, i); - continue; - } - } - - /* Good Receive */ - skb_put(skb, length - ETHERNET_FCS_SIZE); - - /* Receive Checksum Offload */ - e1000_rx_checksum(adapter, rx_desc, skb); - - skb->protocol = eth_type_trans(skb, netdev); -#ifdef CONFIG_E1000_NAPI -#ifdef NETIF_F_HW_VLAN_TX - if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) { - vlan_hwaccel_receive_skb(skb, adapter->vlgrp, - le16_to_cpu(rx_desc->special & - E1000_RXD_SPC_VLAN_MASK)); - } else { - netif_receive_skb(skb); - } -#else - netif_receive_skb(skb); -#endif -#else /* CONFIG_E1000_NAPI */ -#ifdef NETIF_F_HW_VLAN_TX - if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) { - vlan_hwaccel_rx(skb, adapter->vlgrp, - le16_to_cpu(rx_desc->special & - E1000_RXD_SPC_VLAN_MASK)); - } else { - netif_rx(skb); - } -#else - netif_rx(skb); -#endif -#endif /* CONFIG_E1000_NAPI */ - netdev->last_rx = jiffies; - - rx_desc->status = 0; - buffer_info->skb = NULL; - - if(++i == rx_ring->count) i = 0; - - rx_desc = E1000_RX_DESC(*rx_ring, i); - } - - rx_ring->next_to_clean = i; - - e1000_alloc_rx_buffers(adapter); - - return cleaned; -} - -/** - * e1000_alloc_rx_buffers - Replace used receive buffers - * @data: address of board private structure - **/ - -static void -e1000_alloc_rx_buffers(struct e1000_adapter *adapter) -{ - struct e1000_desc_ring *rx_ring = &adapter->rx_ring; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_rx_desc *rx_desc; - struct e1000_buffer *buffer_info; - struct sk_buff *skb; - int reserve_len = 2; - unsigned int i; - - i = rx_ring->next_to_use; - buffer_info = &rx_ring->buffer_info[i]; - - while(!buffer_info->skb) { - rx_desc = E1000_RX_DESC(*rx_ring, i); - - skb = dev_alloc_skb(adapter->rx_buffer_len + reserve_len); - - if(!skb) { - /* Better luck next round */ - break; - } - - /* Make buffer alignment 2 beyond a 16 byte boundary - * this will result in a 16 byte aligned IP header after - * the 14 byte MAC header is removed - */ - skb_reserve(skb, reserve_len); - - skb->dev = netdev; - - buffer_info->skb = skb; - buffer_info->length = adapter->rx_buffer_len; - buffer_info->dma = - pci_map_single(pdev, - skb->data, - adapter->rx_buffer_len, - PCI_DMA_FROMDEVICE); - - rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - - if((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i) { - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). */ - wmb(); - - E1000_WRITE_REG(&adapter->hw, RDT, i); - } - - if(++i == rx_ring->count) i = 0; - buffer_info = &rx_ring->buffer_info[i]; - } - - rx_ring->next_to_use = i; -} - -/** - * e1000_smartspeed - Workaround for SmartSpeed on 82541 and 82547 controllers. - * @adapter: - **/ - -static void -e1000_smartspeed(struct e1000_adapter *adapter) -{ - uint16_t phy_status; - uint16_t phy_ctrl; - - if((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg || - !(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL)) - return; - - if(adapter->smartspeed == 0) { - /* If Master/Slave config fault is asserted twice, - * we assume back-to-back */ - e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); - if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return; - e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); - if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return; - e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); - if(phy_ctrl & CR_1000T_MS_ENABLE) { - phy_ctrl &= ~CR_1000T_MS_ENABLE; - e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, - phy_ctrl); - adapter->smartspeed++; - if(!e1000_phy_setup_autoneg(&adapter->hw) && - !e1000_read_phy_reg(&adapter->hw, PHY_CTRL, - &phy_ctrl)) { - phy_ctrl |= (MII_CR_AUTO_NEG_EN | - MII_CR_RESTART_AUTO_NEG); - e1000_write_phy_reg(&adapter->hw, PHY_CTRL, - phy_ctrl); - } - } - return; - } else if(adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) { - /* If still no link, perhaps using 2/3 pair cable */ - e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); - phy_ctrl |= CR_1000T_MS_ENABLE; - e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl); - if(!e1000_phy_setup_autoneg(&adapter->hw) && - !e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) { - phy_ctrl |= (MII_CR_AUTO_NEG_EN | - MII_CR_RESTART_AUTO_NEG); - e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_ctrl); - } - } - /* Restart process after E1000_SMARTSPEED_MAX iterations */ - if(adapter->smartspeed++ == E1000_SMARTSPEED_MAX) - adapter->smartspeed = 0; -} - -/** - * e1000_ioctl - - * @netdev: - * @ifreq: - * @cmd: - **/ - -static int -e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { -#ifdef SIOCGMIIPHY - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: - return e1000_mii_ioctl(netdev, ifr, cmd); -#endif -#ifdef SIOCETHTOOL - case SIOCETHTOOL: - return e1000_ethtool_ioctl(netdev, ifr); -#endif - default: - return -EOPNOTSUPP; - } -} - -#ifdef SIOCGMIIPHY -/** - * e1000_mii_ioctl - - * @netdev: - * @ifreq: - * @cmd: - **/ - -static int -e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct e1000_adapter *adapter = netdev->priv; - struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data; - int retval; - uint16_t mii_reg; - uint16_t spddplx; - - if(adapter->hw.media_type != e1000_media_type_copper) - return -EOPNOTSUPP; - - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = adapter->hw.phy_addr; - break; - case SIOCGMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, - &data->val_out)) - return -EIO; - break; - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (data->reg_num & ~(0x1F)) - return -EFAULT; - mii_reg = data->val_in; - if (e1000_write_phy_reg(&adapter->hw, data->reg_num, - data->val_in)) - return -EIO; - if (adapter->hw.phy_type == e1000_phy_m88) { - switch (data->reg_num) { - case PHY_CTRL: - if(data->val_in & MII_CR_AUTO_NEG_EN) { - adapter->hw.autoneg = 1; - adapter->hw.autoneg_advertised = 0x2F; - } else { - if (data->val_in & 0x40) - spddplx = SPEED_1000; - else if (data->val_in & 0x2000) - spddplx = SPEED_100; - else - spddplx = SPEED_10; - spddplx += (data->val_in & 0x100) - ? FULL_DUPLEX : - HALF_DUPLEX; - retval = e1000_set_spd_dplx(adapter, - spddplx); - if(retval) - return retval; - } - if(netif_running(adapter->netdev)) { - e1000_down(adapter); - e1000_up(adapter); - } else - e1000_reset(adapter); - break; - case M88E1000_PHY_SPEC_CTRL: - case M88E1000_EXT_PHY_SPEC_CTRL: - if (e1000_phy_reset(&adapter->hw)) - return -EIO; - break; - } - } - break; - default: - return -EOPNOTSUPP; - } - return E1000_SUCCESS; -} -#endif - -/** - * e1000_rx_checksum - Receive Checksum Offload for 82543 - * @adapter: board private structure - * @rx_desc: receive descriptor - * @sk_buff: socket buffer with received data - **/ - -static inline void -e1000_rx_checksum(struct e1000_adapter *adapter, - struct e1000_rx_desc *rx_desc, - struct sk_buff *skb) -{ - /* 82543 or newer only */ - if((adapter->hw.mac_type < e1000_82543) || - /* Ignore Checksum bit is set */ - (rx_desc->status & E1000_RXD_STAT_IXSM) || - /* TCP Checksum has not been calculated */ - (!(rx_desc->status & E1000_RXD_STAT_TCPCS))) { - skb->ip_summed = CHECKSUM_NONE; - return; - } - - /* At this point we know the hardware did the TCP checksum */ - /* now look at the TCP checksum error bit */ - if(rx_desc->errors & E1000_RXD_ERR_TCPE) { - /* let the stack verify checksum errors */ - skb->ip_summed = CHECKSUM_NONE; - adapter->hw_csum_err++; - } else { - /* TCP checksum is good */ - skb->ip_summed = CHECKSUM_UNNECESSARY; - adapter->hw_csum_good++; - } -} - -void -e1000_pci_set_mwi(struct e1000_hw *hw) -{ - struct e1000_adapter *adapter = hw->back; - -#ifdef HAVE_PCI_SET_MWI - pci_set_mwi(adapter->pdev); -#else - pci_write_config_word(adapter->pdev, PCI_COMMAND, - adapter->hw.pci_cmd_word | - PCI_COMMAND_INVALIDATE); -#endif -} - -void -e1000_pci_clear_mwi(struct e1000_hw *hw) -{ - struct e1000_adapter *adapter = hw->back; - -#ifdef HAVE_PCI_SET_MWI - pci_clear_mwi(adapter->pdev); -#else - pci_write_config_word(adapter->pdev, PCI_COMMAND, - adapter->hw.pci_cmd_word & - ~PCI_COMMAND_INVALIDATE); -#endif -} - -void -e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value) -{ - struct e1000_adapter *adapter = hw->back; - - pci_read_config_word(adapter->pdev, reg, value); -} - -void -e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value) -{ - struct e1000_adapter *adapter = hw->back; - - pci_write_config_word(adapter->pdev, reg, *value); -} - -uint32_t -e1000_io_read(struct e1000_hw *hw, uint32_t port) -{ - return inl(port); -} - -void -e1000_io_write(struct e1000_hw *hw, uint32_t port, uint32_t value) -{ - outl(value, port); -} - -#ifdef NETIF_F_HW_VLAN_TX -static void -e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) -{ - struct e1000_adapter *adapter = netdev->priv; - uint32_t ctrl, rctl; - - e1000_irq_disable(adapter); - adapter->vlgrp = grp; - - if(grp) { - /* enable VLAN tag insert/strip */ - - E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE); - - ctrl = E1000_READ_REG(&adapter->hw, CTRL); - ctrl |= E1000_CTRL_VME; - E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); - - /* enable VLAN receive filtering */ - - rctl = E1000_READ_REG(&adapter->hw, RCTL); - rctl |= E1000_RCTL_VFE; - rctl &= ~E1000_RCTL_CFIEN; - E1000_WRITE_REG(&adapter->hw, RCTL, rctl); - } else { - /* disable VLAN tag insert/strip */ - - ctrl = E1000_READ_REG(&adapter->hw, CTRL); - ctrl &= ~E1000_CTRL_VME; - E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); - - /* disable VLAN filtering */ - - rctl = E1000_READ_REG(&adapter->hw, RCTL); - rctl &= ~E1000_RCTL_VFE; - E1000_WRITE_REG(&adapter->hw, RCTL, rctl); - } - - e1000_irq_enable(adapter); -} - -static void -e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid) -{ - struct e1000_adapter *adapter = netdev->priv; - uint32_t vfta, index; - - /* add VID to filter table */ - - index = (vid >> 5) & 0x7F; - vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); - vfta |= (1 << (vid & 0x1F)); - e1000_write_vfta(&adapter->hw, index, vfta); -} - -static void -e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) -{ - struct e1000_adapter *adapter = netdev->priv; - uint32_t vfta, index; - - e1000_irq_disable(adapter); - - if(adapter->vlgrp) - adapter->vlgrp->vlan_devices[vid] = NULL; - - e1000_irq_enable(adapter); - - /* remove VID from filter table*/ - - index = (vid >> 5) & 0x7F; - vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); - vfta &= ~(1 << (vid & 0x1F)); - e1000_write_vfta(&adapter->hw, index, vfta); -} - -static void -e1000_restore_vlan(struct e1000_adapter *adapter) -{ - e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp); - - if(adapter->vlgrp) { - uint16_t vid; - for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { - if(!adapter->vlgrp->vlan_devices[vid]) - continue; - e1000_vlan_rx_add_vid(adapter->netdev, vid); - } - } -} -#endif - -int -e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx) -{ - adapter->hw.autoneg = 0; - - switch(spddplx) { - case SPEED_10 + DUPLEX_HALF: - adapter->hw.forced_speed_duplex = e1000_10_half; - break; - case SPEED_10 + DUPLEX_FULL: - adapter->hw.forced_speed_duplex = e1000_10_full; - break; - case SPEED_100 + DUPLEX_HALF: - adapter->hw.forced_speed_duplex = e1000_100_half; - break; - case SPEED_100 + DUPLEX_FULL: - adapter->hw.forced_speed_duplex = e1000_100_full; - break; - case SPEED_1000 + DUPLEX_FULL: - adapter->hw.autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; - break; - case SPEED_1000 + DUPLEX_HALF: /* not supported */ - default: - return -EINVAL; - } - return 0; -} - -static int -e1000_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) -{ - struct pci_dev *pdev = NULL; - - switch(event) { - case SYS_DOWN: - case SYS_HALT: - case SYS_POWER_OFF: - while((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { - if(pci_dev_driver(pdev) == &e1000_driver) - e1000_suspend(pdev, 3); - } - } - return NOTIFY_DONE; -} - -static int -e1000_suspend(struct pci_dev *pdev, uint32_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev->priv; - uint32_t ctrl, ctrl_ext, rctl, manc, status; - uint32_t wufc = adapter->wol; - - netif_device_detach(netdev); - - if(netif_running(netdev)) - e1000_down(adapter); - - status = E1000_READ_REG(&adapter->hw, STATUS); - if(status & E1000_STATUS_LU) - wufc &= ~E1000_WUFC_LNKC; - - if(wufc) { - e1000_setup_rctl(adapter); - e1000_set_multi(netdev); - - /* turn on all-multi mode if wake on multicast is enabled */ - if(adapter->wol & E1000_WUFC_MC) { - rctl = E1000_READ_REG(&adapter->hw, RCTL); - rctl |= E1000_RCTL_MPE; - E1000_WRITE_REG(&adapter->hw, RCTL, rctl); - } - - if(adapter->hw.mac_type >= e1000_82540) { - ctrl = E1000_READ_REG(&adapter->hw, CTRL); - /* advertise wake from D3Cold */ - #define E1000_CTRL_ADVD3WUC 0x00100000 - /* phy power management enable */ - #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 - ctrl |= E1000_CTRL_ADVD3WUC | - E1000_CTRL_EN_PHY_PWR_MGMT; - E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); - } - - if(adapter->hw.media_type == e1000_media_type_fiber || - adapter->hw.media_type == e1000_media_type_internal_serdes) { - /* keep the laser running in D3 */ - ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA; - E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext); - } - - E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN); - E1000_WRITE_REG(&adapter->hw, WUFC, wufc); - pci_enable_wake(pdev, 3, 1); - pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */ - } else { - E1000_WRITE_REG(&adapter->hw, WUC, 0); - E1000_WRITE_REG(&adapter->hw, WUFC, 0); - pci_enable_wake(pdev, 3, 0); - pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */ - } - - pci_save_state(pdev, adapter->pci_state); - - if(adapter->hw.mac_type >= e1000_82540 && - adapter->hw.media_type == e1000_media_type_copper) { - manc = E1000_READ_REG(&adapter->hw, MANC); - if(manc & E1000_MANC_SMBUS_EN) { - manc |= E1000_MANC_ARP_EN; - E1000_WRITE_REG(&adapter->hw, MANC, manc); - pci_enable_wake(pdev, 3, 1); - pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */ - } - } - - state = (state > 0) ? 3 : 0; - pci_set_power_state(pdev, state); - - return 0; -} - -#ifdef CONFIG_PM -static int -e1000_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev->priv; - uint32_t manc; - - pci_set_power_state(pdev, 0); - pci_restore_state(pdev, adapter->pci_state); - - pci_enable_wake(pdev, 3, 0); - pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */ - - e1000_reset(adapter); - E1000_WRITE_REG(&adapter->hw, WUS, ~0); - - if(netif_running(netdev)) - e1000_up(adapter); - - netif_device_attach(netdev); - - if(adapter->hw.mac_type >= e1000_82540 && - adapter->hw.media_type == e1000_media_type_copper) { - manc = E1000_READ_REG(&adapter->hw, MANC); - manc &= ~(E1000_MANC_ARP_EN); - E1000_WRITE_REG(&adapter->hw, MANC, manc); - } - - return 0; -} -#endif - -/* e1000_main.c */ diff --git a/xen/drivers/net/e1000/e1000_osdep.h b/xen/drivers/net/e1000/e1000_osdep.h deleted file mode 100644 index 4ed5949692..0000000000 --- a/xen/drivers/net/e1000/e1000_osdep.h +++ /dev/null @@ -1,104 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - - -/* glue for the OS independent part of e1000 - * includes register access macros - */ - -#ifndef _E1000_OSDEP_H_ -#define _E1000_OSDEP_H_ - -#include -#include -#include -#include -#include -#include -#include "kcompat.h" - -#define usec_delay(x) udelay(x) -#ifndef msec_delay -#define msec_delay(x) do { if(in_interrupt()) { \ - /* Don't mdelay in interrupt context! */ \ - BUG(); \ - } else { \ - set_current_state(TASK_UNINTERRUPTIBLE); \ - schedule_timeout((x * HZ)/1000); \ - } } while(0) -#endif - -#define PCI_COMMAND_REGISTER PCI_COMMAND -#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE - -typedef enum { -#undef FALSE - FALSE = 0, -#undef TRUE - TRUE = 1 -} boolean_t; - -#undef ASSERT -#define ASSERT(x) if(!(x)) BUG() -#define MSGOUT(S, A, B) printk(KERN_DEBUG S "\n", A, B) - -#if DBG -#define DEBUGOUT(S) printk(KERN_DEBUG S "\n") -#define DEBUGOUT1(S, A...) printk(KERN_DEBUG S "\n", A) -#else -#define DEBUGOUT(S) -#define DEBUGOUT1(S, A...) -#endif - -#define DEBUGFUNC(F) DEBUGOUT(F) -#define DEBUGOUT2 DEBUGOUT1 -#define DEBUGOUT3 DEBUGOUT2 -#define DEBUGOUT7 DEBUGOUT3 - - -#define E1000_WRITE_REG(a, reg, value) ( \ - writel((value), ((a)->hw_addr + \ - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg)))) - -#define E1000_READ_REG(a, reg) ( \ - readl((a)->hw_addr + \ - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg))) - -#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \ - writel((value), ((a)->hw_addr + \ - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ - ((offset) << 2)))) - -#define E1000_READ_REG_ARRAY(a, reg, offset) ( \ - readl((a)->hw_addr + \ - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ - ((offset) << 2))) - -#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS) - -#endif /* _E1000_OSDEP_H_ */ diff --git a/xen/drivers/net/e1000/e1000_param.c b/xen/drivers/net/e1000/e1000_param.c deleted file mode 100644 index d57f9ff558..0000000000 --- a/xen/drivers/net/e1000/e1000_param.c +++ /dev/null @@ -1,698 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#include "e1000.h" - -/* This is the only thing that needs to be changed to adjust the - * maximum number of ports that the driver can manage. - */ - -#define E1000_MAX_NIC 32 - -#define OPTION_UNSET -1 -#define OPTION_DISABLED 0 -#define OPTION_ENABLED 1 - -/* Module Parameters are always initialized to -1, so that the driver - * can tell the difference between no user specified value or the - * user asking for the default value. - * The true default values are loaded in when e1000_check_options is called. - * - * This is a GCC extension to ANSI C. - * See the item "Labeled Elements in Initializers" in the section - * "Extensions to the C Language Family" of the GCC documentation. - */ - -#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET } - -/* All parameters are treated the same, as an integer array of values. - * This macro just reduces the need to repeat the same declaration code - * over and over (plus this helps to avoid typo bugs). - */ - -#define E1000_PARAM(X, S) \ -static const int __devinitdata X[E1000_MAX_NIC + 1] = E1000_PARAM_INIT; \ -MODULE_PARM(X, "1-" __MODULE_STRING(E1000_MAX_NIC) "i"); \ -MODULE_PARM_DESC(X, S); - -/* Transmit Descriptor Count - * - * Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers - * Valid Range: 80-4096 for 82544 and newer - * - * Default Value: 256 for 82542 and 82543 gigabit ethernet controllers - * Default Value: 1024 for 82544 and newer - */ - -E1000_PARAM(TxDescriptors, "Number of transmit descriptors"); - -/* Receive Descriptor Count - * - * Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers - * Valid Range: 80-4096 for 82544 and newer - * - * Default Value: 256 - */ - -E1000_PARAM(RxDescriptors, "Number of receive descriptors"); - -/* User Specified Speed Override - * - * Valid Range: 0, 10, 100, 1000 - * - 0 - auto-negotiate at all supported speeds - * - 10 - only link at 10 Mbps - * - 100 - only link at 100 Mbps - * - 1000 - only link at 1000 Mbps - * - * Default Value: 0 - */ - -E1000_PARAM(Speed, "Speed setting"); - -/* User Specified Duplex Override - * - * Valid Range: 0-2 - * - 0 - auto-negotiate for duplex - * - 1 - only link at half duplex - * - 2 - only link at full duplex - * - * Default Value: 0 - */ - -E1000_PARAM(Duplex, "Duplex setting"); - -/* Auto-negotiation Advertisement Override - * - * Valid Range: 0x01-0x0F, 0x20-0x2F - * - * The AutoNeg value is a bit mask describing which speed and duplex - * combinations should be advertised during auto-negotiation. - * The supported speed and duplex modes are listed below - * - * Bit 7 6 5 4 3 2 1 0 - * Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10 - * Duplex Full Full Half Full Half - * - * Default Value: 0x2F - */ - -E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting"); - -/* User Specified Flow Control Override - * - * Valid Range: 0-3 - * - 0 - No Flow Control - * - 1 - Rx only, respond to PAUSE frames but do not generate them - * - 2 - Tx only, generate PAUSE frames but ignore them on receive - * - 3 - Full Flow Control Support - * - * Default Value: Read flow control settings from the EEPROM - */ - -E1000_PARAM(FlowControl, "Flow Control setting"); - -/* XsumRX - Receive Checksum Offload Enable/Disable - * - * Valid Range: 0, 1 - * - 0 - disables all checksum offload - * - 1 - enables receive IP/TCP/UDP checksum offload - * on 82543 and newer -based NICs - * - * Default Value: 1 - */ - -E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload"); - -/* Transmit Interrupt Delay in units of 1.024 microseconds - * - * Valid Range: 0-65535 - * - * Default Value: 64 - */ - -E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay"); - -/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds - * - * Valid Range: 0-65535 - * - * Default Value: 0 - */ - -E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay"); - -/* Receive Interrupt Delay in units of 1.024 microseconds - * - * Valid Range: 0-65535 - * - * Default Value: 0 - */ - -E1000_PARAM(RxIntDelay, "Receive Interrupt Delay"); - -/* Receive Absolute Interrupt Delay in units of 1.024 microseconds - * - * Valid Range: 0-65535 - * - * Default Value: 128 - */ - -E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay"); - -/* Interrupt Throttle Rate (interrupts/sec) - * - * Valid Range: 100-100000 (0=off, 1=dynamic) - * - * Default Value: 1 - */ - -E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate"); - -#define AUTONEG_ADV_DEFAULT 0x2F -#define AUTONEG_ADV_MASK 0x2F -#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL - -#define DEFAULT_TXD 256 -#define MAX_TXD 256 -#define MIN_TXD 80 -#define MAX_82544_TXD 4096 -#define DEFAULT_82544_TXD 1024 - -#define DEFAULT_RXD 256 -#define MAX_RXD 256 -#define MIN_RXD 80 -#define MAX_82544_RXD 4096 - -#define DEFAULT_RDTR 0 -#define MAX_RXDELAY 0xFFFF -#define MIN_RXDELAY 0 - -#define DEFAULT_RADV 128 -#define MAX_RXABSDELAY 0xFFFF -#define MIN_RXABSDELAY 0 - -#define DEFAULT_TIDV 64 -#define MAX_TXDELAY 0xFFFF -#define MIN_TXDELAY 0 - -#define DEFAULT_TADV 64 -#define MAX_TXABSDELAY 0xFFFF -#define MIN_TXABSDELAY 0 - -#define DEFAULT_ITR 1 -#define MAX_ITR 100000 -#define MIN_ITR 100 - -struct e1000_option { - enum { enable_option, range_option, list_option } type; - char *name; - char *err; - int def; - union { - struct { /* range_option info */ - int min; - int max; - } r; - struct { /* list_option info */ - int nr; - struct e1000_opt_list { int i; char *str; } *p; - } l; - } arg; -}; - -static int __devinit -e1000_validate_option(int *value, struct e1000_option *opt) -{ - if(*value == OPTION_UNSET) { - *value = opt->def; - return 0; - } - - switch (opt->type) { - case enable_option: - switch (*value) { - case OPTION_ENABLED: - printk(KERN_INFO "%s Enabled\n", opt->name); - return 0; - case OPTION_DISABLED: - printk(KERN_INFO "%s Disabled\n", opt->name); - return 0; - } - break; - case range_option: - if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) { - printk(KERN_INFO "%s set to %i\n", opt->name, *value); - return 0; - } - break; - case list_option: { - int i; - struct e1000_opt_list *ent; - - for(i = 0; i < opt->arg.l.nr; i++) { - ent = &opt->arg.l.p[i]; - if(*value == ent->i) { - if(ent->str[0] != '\0') - printk(KERN_INFO "%s\n", ent->str); - return 0; - } - } - } - break; - default: - BUG(); - } - - printk(KERN_INFO "Invalid %s specified (%i) %s\n", - opt->name, *value, opt->err); - *value = opt->def; - return -1; -} - -static void e1000_check_fiber_options(struct e1000_adapter *adapter); -static void e1000_check_copper_options(struct e1000_adapter *adapter); - -/** - * e1000_check_options - Range Checking for Command Line Parameters - * @adapter: board private structure - * - * This routine checks all command line paramters for valid user - * input. If an invalid value is given, or if no user specified - * value exists, a default value is used. The final value is stored - * in a variable in the adapter structure. - **/ - -void __devinit -e1000_check_options(struct e1000_adapter *adapter) -{ - int bd = adapter->bd_number; - if(bd >= E1000_MAX_NIC) { - printk(KERN_NOTICE - "Warning: no configuration for board #%i\n", bd); - printk(KERN_NOTICE "Using defaults for all values\n"); - bd = E1000_MAX_NIC; - } - - { /* Transmit Descriptor Count */ - struct e1000_option opt = { - .type = range_option, - .name = "Transmit Descriptors", - .arg = { .r = { .min = MIN_TXD }} - }; - struct e1000_desc_ring *tx_ring = &adapter->tx_ring; - e1000_mac_type mac_type = adapter->hw.mac_type; - opt.err = mac_type < e1000_82544 ? - "using default of " __MODULE_STRING(DEFAULT_TXD) : - "using default of " __MODULE_STRING(DEFAULT_82544_TXD); - opt.def = mac_type < e1000_82544 ? - DEFAULT_TXD : DEFAULT_82544_TXD; - opt.arg.r.max = mac_type < e1000_82544 ? - MAX_TXD : MAX_82544_TXD; - - tx_ring->count = TxDescriptors[bd]; - e1000_validate_option(&tx_ring->count, &opt); - E1000_ROUNDUP(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE); - } - { /* Receive Descriptor Count */ - struct e1000_option opt = { - .type = range_option, - .name = "Receive Descriptors", - .err = "using default of " __MODULE_STRING(DEFAULT_RXD), - .def = DEFAULT_RXD, - .arg = { .r = { .min = MIN_RXD }} - }; - struct e1000_desc_ring *rx_ring = &adapter->rx_ring; - e1000_mac_type mac_type = adapter->hw.mac_type; - opt.arg.r.max = mac_type < e1000_82544 ? MAX_RXD : MAX_82544_RXD; - - rx_ring->count = RxDescriptors[bd]; - e1000_validate_option(&rx_ring->count, &opt); - E1000_ROUNDUP(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE); - } - { /* Checksum Offload Enable/Disable */ - struct e1000_option opt = { - .type = enable_option, - .name = "Checksum Offload", - .err = "defaulting to Enabled", - .def = OPTION_ENABLED - }; - - int rx_csum = XsumRX[bd]; - e1000_validate_option(&rx_csum, &opt); - adapter->rx_csum = rx_csum; - } - { /* Flow Control */ - - struct e1000_opt_list fc_list[] = - {{ e1000_fc_none, "Flow Control Disabled" }, - { e1000_fc_rx_pause,"Flow Control Receive Only" }, - { e1000_fc_tx_pause,"Flow Control Transmit Only" }, - { e1000_fc_full, "Flow Control Enabled" }, - { e1000_fc_default, "Flow Control Hardware Default" }}; - - struct e1000_option opt = { - .type = list_option, - .name = "Flow Control", - .err = "reading default settings from EEPROM", - .def = e1000_fc_default, - .arg = { .l = { .nr = ARRAY_SIZE(fc_list), - .p = fc_list }} - }; - - int fc = FlowControl[bd]; - e1000_validate_option(&fc, &opt); - adapter->hw.fc = adapter->hw.original_fc = fc; - } - { /* Transmit Interrupt Delay */ - struct e1000_option opt = { - .type = range_option, - .name = "Transmit Interrupt Delay", - .err = "using default of " __MODULE_STRING(DEFAULT_TIDV), - .def = DEFAULT_TIDV, - .arg = { .r = { .min = MIN_TXDELAY, - .max = MAX_TXDELAY }} - }; - - adapter->tx_int_delay = TxIntDelay[bd]; - e1000_validate_option(&adapter->tx_int_delay, &opt); - } - { /* Transmit Absolute Interrupt Delay */ - struct e1000_option opt = { - .type = range_option, - .name = "Transmit Absolute Interrupt Delay", - .err = "using default of " __MODULE_STRING(DEFAULT_TADV), - .def = DEFAULT_TADV, - .arg = { .r = { .min = MIN_TXABSDELAY, - .max = MAX_TXABSDELAY }} - }; - - adapter->tx_abs_int_delay = TxAbsIntDelay[bd]; - e1000_validate_option(&adapter->tx_abs_int_delay, &opt); - } - { /* Receive Interrupt Delay */ - struct e1000_option opt = { - .type = range_option, - .name = "Receive Interrupt Delay", - .err = "using default of " __MODULE_STRING(DEFAULT_RDTR), - .def = DEFAULT_RDTR, - .arg = { .r = { .min = MIN_RXDELAY, - .max = MAX_RXDELAY }} - }; - - adapter->rx_int_delay = RxIntDelay[bd]; - e1000_validate_option(&adapter->rx_int_delay, &opt); - } - { /* Receive Absolute Interrupt Delay */ - struct e1000_option opt = { - .type = range_option, - .name = "Receive Absolute Interrupt Delay", - .err = "using default of " __MODULE_STRING(DEFAULT_RADV), - .def = DEFAULT_RADV, - .arg = { .r = { .min = MIN_RXABSDELAY, - .max = MAX_RXABSDELAY }} - }; - - adapter->rx_abs_int_delay = RxAbsIntDelay[bd]; - e1000_validate_option(&adapter->rx_abs_int_delay, &opt); - } - { /* Interrupt Throttling Rate */ - struct e1000_option opt = { - .type = range_option, - .name = "Interrupt Throttling Rate (ints/sec)", - .err = "using default of " __MODULE_STRING(DEFAULT_ITR), - .def = DEFAULT_ITR, - .arg = { .r = { .min = MIN_ITR, - .max = MAX_ITR }} - }; - - adapter->itr = InterruptThrottleRate[bd]; - if(adapter->itr == 0) { - printk(KERN_INFO "%s turned off\n", opt.name); - } else if(adapter->itr == 1 || adapter->itr == -1) { - /* Dynamic mode */ - adapter->itr = 1; - } else { - e1000_validate_option(&adapter->itr, &opt); - } - } - - switch(adapter->hw.media_type) { - case e1000_media_type_fiber: - case e1000_media_type_internal_serdes: - e1000_check_fiber_options(adapter); - break; - case e1000_media_type_copper: - e1000_check_copper_options(adapter); - break; - default: - BUG(); - } -} - -/** - * e1000_check_fiber_options - Range Checking for Link Options, Fiber Version - * @adapter: board private structure - * - * Handles speed and duplex options on fiber adapters - **/ - -static void __devinit -e1000_check_fiber_options(struct e1000_adapter *adapter) -{ - int bd = adapter->bd_number; - bd = bd > E1000_MAX_NIC ? E1000_MAX_NIC : bd; - - if((Speed[bd] != OPTION_UNSET)) { - printk(KERN_INFO "Speed not valid for fiber adapters, " - "parameter ignored\n"); - } - if((Duplex[bd] != OPTION_UNSET)) { - printk(KERN_INFO "Duplex not valid for fiber adapters, " - "parameter ignored\n"); - } - if((AutoNeg[bd] != OPTION_UNSET)) { - printk(KERN_INFO "AutoNeg not valid for fiber adapters, " - "parameter ignored\n"); - } -} - -/** - * e1000_check_copper_options - Range Checking for Link Options, Copper Version - * @adapter: board private structure - * - * Handles speed and duplex options on copper adapters - **/ - -static void __devinit -e1000_check_copper_options(struct e1000_adapter *adapter) -{ - int speed, dplx; - int bd = adapter->bd_number; - bd = bd > E1000_MAX_NIC ? E1000_MAX_NIC : bd; - - { /* Speed */ - struct e1000_opt_list speed_list[] = {{ 0, "" }, - { SPEED_10, "" }, - { SPEED_100, "" }, - { SPEED_1000, "" }}; - - struct e1000_option opt = { - .type = list_option, - .name = "Speed", - .err = "parameter ignored", - .def = 0, - .arg = { .l = { .nr = ARRAY_SIZE(speed_list), - .p = speed_list }} - }; - - speed = Speed[bd]; - e1000_validate_option(&speed, &opt); - } - { /* Duplex */ - struct e1000_opt_list dplx_list[] = {{ 0, "" }, - { HALF_DUPLEX, "" }, - { FULL_DUPLEX, "" }}; - - struct e1000_option opt = { - .type = list_option, - .name = "Duplex", - .err = "parameter ignored", - .def = 0, - .arg = { .l = { .nr = ARRAY_SIZE(dplx_list), - .p = dplx_list }} - }; - - dplx = Duplex[bd]; - e1000_validate_option(&dplx, &opt); - } - - if(AutoNeg[bd] != OPTION_UNSET && (speed != 0 || dplx != 0)) { - printk(KERN_INFO - "AutoNeg specified along with Speed or Duplex, " - "parameter ignored\n"); - adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT; - } else { /* Autoneg */ - struct e1000_opt_list an_list[] = - #define AA "AutoNeg advertising " - {{ 0x01, AA "10/HD" }, - { 0x02, AA "10/FD" }, - { 0x03, AA "10/FD, 10/HD" }, - { 0x04, AA "100/HD" }, - { 0x05, AA "100/HD, 10/HD" }, - { 0x06, AA "100/HD, 10/FD" }, - { 0x07, AA "100/HD, 10/FD, 10/HD" }, - { 0x08, AA "100/FD" }, - { 0x09, AA "100/FD, 10/HD" }, - { 0x0a, AA "100/FD, 10/FD" }, - { 0x0b, AA "100/FD, 10/FD, 10/HD" }, - { 0x0c, AA "100/FD, 100/HD" }, - { 0x0d, AA "100/FD, 100/HD, 10/HD" }, - { 0x0e, AA "100/FD, 100/HD, 10/FD" }, - { 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" }, - { 0x20, AA "1000/FD" }, - { 0x21, AA "1000/FD, 10/HD" }, - { 0x22, AA "1000/FD, 10/FD" }, - { 0x23, AA "1000/FD, 10/FD, 10/HD" }, - { 0x24, AA "1000/FD, 100/HD" }, - { 0x25, AA "1000/FD, 100/HD, 10/HD" }, - { 0x26, AA "1000/FD, 100/HD, 10/FD" }, - { 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" }, - { 0x28, AA "1000/FD, 100/FD" }, - { 0x29, AA "1000/FD, 100/FD, 10/HD" }, - { 0x2a, AA "1000/FD, 100/FD, 10/FD" }, - { 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" }, - { 0x2c, AA "1000/FD, 100/FD, 100/HD" }, - { 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" }, - { 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" }, - { 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }}; - - struct e1000_option opt = { - .type = list_option, - .name = "AutoNeg", - .err = "parameter ignored", - .def = AUTONEG_ADV_DEFAULT, - .arg = { .l = { .nr = ARRAY_SIZE(an_list), - .p = an_list }} - }; - - int an = AutoNeg[bd]; - e1000_validate_option(&an, &opt); - adapter->hw.autoneg_advertised = an; - } - - switch (speed + dplx) { - case 0: - adapter->hw.autoneg = adapter->fc_autoneg = 1; - if(Speed[bd] != OPTION_UNSET || Duplex[bd] != OPTION_UNSET) - printk(KERN_INFO - "Speed and duplex autonegotiation enabled\n"); - break; - case HALF_DUPLEX: - printk(KERN_INFO "Half Duplex specified without Speed\n"); - printk(KERN_INFO "Using Autonegotiation at Half Duplex only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_10_HALF | - ADVERTISE_100_HALF; - break; - case FULL_DUPLEX: - printk(KERN_INFO "Full Duplex specified without Speed\n"); - printk(KERN_INFO "Using Autonegotiation at Full Duplex only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_10_FULL | - ADVERTISE_100_FULL | - ADVERTISE_1000_FULL; - break; - case SPEED_10: - printk(KERN_INFO "10 Mbps Speed specified without Duplex\n"); - printk(KERN_INFO "Using Autonegotiation at 10 Mbps only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_10_HALF | - ADVERTISE_10_FULL; - break; - case SPEED_10 + HALF_DUPLEX: - printk(KERN_INFO "Forcing to 10 Mbps Half Duplex\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 0; - adapter->hw.forced_speed_duplex = e1000_10_half; - adapter->hw.autoneg_advertised = 0; - break; - case SPEED_10 + FULL_DUPLEX: - printk(KERN_INFO "Forcing to 10 Mbps Full Duplex\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 0; - adapter->hw.forced_speed_duplex = e1000_10_full; - adapter->hw.autoneg_advertised = 0; - break; - case SPEED_100: - printk(KERN_INFO "100 Mbps Speed specified without Duplex\n"); - printk(KERN_INFO "Using Autonegotiation at 100 Mbps only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_100_HALF | - ADVERTISE_100_FULL; - break; - case SPEED_100 + HALF_DUPLEX: - printk(KERN_INFO "Forcing to 100 Mbps Half Duplex\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 0; - adapter->hw.forced_speed_duplex = e1000_100_half; - adapter->hw.autoneg_advertised = 0; - break; - case SPEED_100 + FULL_DUPLEX: - printk(KERN_INFO "Forcing to 100 Mbps Full Duplex\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 0; - adapter->hw.forced_speed_duplex = e1000_100_full; - adapter->hw.autoneg_advertised = 0; - break; - case SPEED_1000: - printk(KERN_INFO "1000 Mbps Speed specified without Duplex\n"); - printk(KERN_INFO - "Using Autonegotiation at 1000 Mbps Full Duplex only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; - break; - case SPEED_1000 + HALF_DUPLEX: - printk(KERN_INFO "Half Duplex is not supported at 1000 Mbps\n"); - printk(KERN_INFO - "Using Autonegotiation at 1000 Mbps Full Duplex only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; - break; - case SPEED_1000 + FULL_DUPLEX: - printk(KERN_INFO - "Using Autonegotiation at 1000 Mbps Full Duplex only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; - break; - default: - BUG(); - } - - /* Speed, AutoNeg and MDI/MDI-X must all play nice */ - if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) { - printk(KERN_INFO "Speed, AutoNeg and MDI-X specifications are " - "incompatible. Setting MDI-X to a compatible value.\n"); - } -} - diff --git a/xen/drivers/net/e1000/kcompat.c b/xen/drivers/net/e1000/kcompat.c deleted file mode 100644 index 384b1f782f..0000000000 --- a/xen/drivers/net/e1000/kcompat.c +++ /dev/null @@ -1,170 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#include "kcompat.h" - -/*****************************************************************************/ -/* 2.4.13 => 2.4.3 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) ) - -/**************************************/ -/* PCI DMA MAPPING */ - -#if defined(CONFIG_HIGHMEM) - -#ifndef PCI_DRAM_OFFSET -#define PCI_DRAM_OFFSET 0 -#endif - -u64 _kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, size_t size, int direction) -{ - return (((u64)(page - mem_map) << PAGE_SHIFT) + offset + PCI_DRAM_OFFSET); -} - -#else /* CONFIG_HIGHMEM */ - -u64 _kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, size_t size, int direction) -{ - return pci_map_single(dev, (void *)page_address(page) + offset, size, direction); -} - -#endif /* CONFIG_HIGHMEM */ - -void _kc_pci_unmap_page(struct pci_dev *dev, u64 dma_addr, size_t size, int direction) -{ - return pci_unmap_single(dev, dma_addr, size, direction); -} - -#endif /* 2.4.13 => 2.4.3 */ - - -/*****************************************************************************/ -/* 2.4.3 => 2.4.0 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) ) - -/**************************************/ -/* PCI DRIVER API */ - -int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask) -{ - if(!pci_dma_supported(dev, mask)) - return -EIO; - dev->dma_mask = mask; - return 0; -} - -int _kc_pci_request_regions(struct pci_dev *dev, char *res_name) -{ - int i; - - for (i = 0; i < 6; i++) { - if (pci_resource_len(dev, i) == 0) - continue; - - if (pci_resource_flags(dev, i) & IORESOURCE_IO) { - if (!request_region(pci_resource_start(dev, i), pci_resource_len(dev, i), res_name)) { - pci_release_regions(dev); - return -EBUSY; - } - } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) { - if (!request_mem_region(pci_resource_start(dev, i), pci_resource_len(dev, i), res_name)) { - pci_release_regions(dev); - return -EBUSY; - } - } - } - return 0; -} - -void _kc_pci_release_regions(struct pci_dev *dev) -{ - int i; - - for (i = 0; i < 6; i++) { - if (pci_resource_len(dev, i) == 0) - continue; - - if (pci_resource_flags(dev, i) & IORESOURCE_IO) - release_region(pci_resource_start(dev, i), pci_resource_len(dev, i)); - - else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) - release_mem_region(pci_resource_start(dev, i), pci_resource_len(dev, i)); - } -} - -/**************************************/ -/* NETWORK DRIVER API */ - -struct net_device * _kc_alloc_etherdev(int sizeof_priv) -{ - struct net_device *dev; - int alloc_size; - - alloc_size = sizeof (*dev) + sizeof_priv + IFNAMSIZ + 31; - - dev = kmalloc(alloc_size, GFP_KERNEL); - - if (!dev) return NULL; - - memset(dev, 0, alloc_size); - - if (sizeof_priv) - dev->priv = (void *) (((unsigned long)(dev + 1) + 31) & ~31); - - dev->name[0] = '\0'; - - ether_setup(dev); - - return dev; -} - -int _kc_is_valid_ether_addr(u8 *addr) -{ - const char zaddr[6] = {0,}; - - return !(addr[0]&1) && memcmp( addr, zaddr, 6); -} - -#endif /* 2.4.3 => 2.4.0 */ - - -/*****************************************************************************/ -/* 2.4.6 => 2.4.3 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) ) - -int _kc_pci_set_power_state(struct pci_dev *dev, int state) -{ return 0; } -int _kc_pci_save_state(struct pci_dev *dev, u32 *buffer) -{ return 0; } -int _kc_pci_restore_state(struct pci_dev *pdev, u32 *buffer) -{ return 0; } -int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable) -{ return 0; } - -#endif /* 2.4.6 => 2.4.3 */ - diff --git a/xen/drivers/net/e1000/kcompat.h b/xen/drivers/net/e1000/kcompat.h deleted file mode 100644 index cb44a63be1..0000000000 --- a/xen/drivers/net/e1000/kcompat.h +++ /dev/null @@ -1,307 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#ifndef _KCOMPAT_H_ -#define _KCOMPAT_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -//#include -#include -#include -#include - -#ifndef IRQ_HANDLED -#define irqreturn_t void -#define IRQ_HANDLED -#define IRQ_NONE -#endif - -#ifndef SET_NETDEV_DEV -#define SET_NETDEV_DEV(net, pdev) -#endif - -/*****************************************************************************/ -#ifndef unlikely -#define unlikely(_x) _x -#define likely(_x) _x -#endif -/*****************************************************************************/ - -/*****************************************************************************/ -/* Installations with ethtool version without eeprom, adapter id, or statistics - * support */ -#ifndef ETHTOOL_GSTATS -#define ETHTOOL_GSTATS 0x1d -#undef ethtool_drvinfo -#define ethtool_drvinfo k_ethtool_drvinfo -struct k_ethtool_drvinfo { - uint32_t cmd; - char driver[32]; - char version[32]; - char fw_version[32]; - char bus_info[32]; - char reserved1[32]; - char reserved2[16]; - uint32_t n_stats; - uint32_t testinfo_len; - uint32_t eedump_len; - uint32_t regdump_len; -}; - -struct ethtool_stats { - uint32_t cmd; - uint32_t n_stats; - uint64_t data[0]; -}; - -#ifndef ETHTOOL_PHYS_ID -#define ETHTOOL_PHYS_ID 0x1c -#ifndef ETHTOOL_GSTRINGS -#define ETHTOOL_GSTRINGS 0x1b -enum ethtool_stringset { - ETH_SS_TEST = 0, - ETH_SS_STATS, -}; -struct ethtool_gstrings { - u32 cmd; /* ETHTOOL_GSTRINGS */ - u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ - u32 len; /* number of strings in the string set */ - u8 data[0]; -}; -#ifndef ETHTOOL_TEST -#define ETHTOOL_TEST 0x1a -enum ethtool_test_flags { - ETH_TEST_FL_OFFLINE = (1 << 0), - ETH_TEST_FL_FAILED = (1 << 1), -}; -struct ethtool_test { - uint32_t cmd; - uint32_t flags; - uint32_t reserved; - uint32_t len; - uint64_t data[0]; -}; -#ifndef ETHTOOL_GEEPROM -#define ETHTOOL_GEEPROM 0xb -#undef ETHTOOL_GREGS -struct ethtool_eeprom { - uint32_t cmd; - uint32_t magic; - uint32_t offset; - uint32_t len; - uint8_t data[0]; -}; - -struct ethtool_value { - uint32_t cmd; - uint32_t data; -}; - -#ifndef ETHTOOL_GLINK -#define ETHTOOL_GLINK 0xa -#endif /* Ethtool version without link support */ -#endif /* Ethtool version without eeprom support */ -#endif /* Ethtool version without test support */ -#endif /* Ethtool version without strings support */ -#endif /* Ethtool version wihtout adapter id support */ -#endif /* Ethtool version without statistics support */ - -/*****************************************************************************/ -/* 2.4.3 => 2.4.0 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) ) - -/**************************************/ -/* PCI DRIVER API */ - -#ifndef pci_set_dma_mask -#define pci_set_dma_mask _kc_pci_set_dma_mask -extern int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask); -#endif - -#ifndef pci_request_regions -#define pci_request_regions _kc_pci_request_regions -extern int _kc_pci_request_regions(struct pci_dev *pdev, char *res_name); -#endif - -#ifndef pci_release_regions -#define pci_release_regions _kc_pci_release_regions -extern void _kc_pci_release_regions(struct pci_dev *pdev); -#endif - -/**************************************/ -/* NETWORK DRIVER API */ - -#ifndef alloc_etherdev -#define alloc_etherdev _kc_alloc_etherdev -extern struct net_device * _kc_alloc_etherdev(int sizeof_priv); -#endif - -#ifndef is_valid_ether_addr -#define is_valid_ether_addr _kc_is_valid_ether_addr -extern int _kc_is_valid_ether_addr(u8 *addr); -#endif - -/**************************************/ -/* MISCELLANEOUS */ - -#ifndef INIT_TQUEUE -#define INIT_TQUEUE(_tq, _routine, _data) \ - do { \ - INIT_LIST_HEAD(&(_tq)->list); \ - (_tq)->sync = 0; \ - (_tq)->routine = _routine; \ - (_tq)->data = _data; \ - } while(0) -#endif - -#endif /* 2.4.3 => 2.4.0 */ - -/*****************************************************************************/ -/* 2.4.6 => 2.4.3 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) ) - -#ifndef pci_set_power_state -#define pci_set_power_state _kc_pci_set_power_state -extern int _kc_pci_set_power_state(struct pci_dev *dev, int state); -#endif - -#ifndef pci_save_state -#define pci_save_state _kc_pci_save_state -extern int _kc_pci_save_state(struct pci_dev *dev, u32 *buffer); -#endif - -#ifndef pci_restore_state -#define pci_restore_state _kc_pci_restore_state -extern int _kc_pci_restore_state(struct pci_dev *pdev, u32 *buffer); -#endif - -#ifndef pci_enable_wake -#define pci_enable_wake _kc_pci_enable_wake -extern int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable); -#endif - -/* PCI PM entry point syntax changed, so don't support suspend/resume */ -#undef CONFIG_PM - -#endif /* 2.4.6 => 2.4.3 */ - -/*****************************************************************************/ -/* 2.4.10 => 2.4.6 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) ) - -/**************************************/ -/* MODULE API */ - -#ifndef MODULE_LICENSE - #define MODULE_LICENSE(X) -#endif - -/**************************************/ -/* OTHER */ - -#undef min -#define min(x,y) ({ \ - const typeof(x) _x = (x); \ - const typeof(y) _y = (y); \ - (void) (&_x == &_y); \ - _x < _y ? _x : _y; }) - -#undef max -#define max(x,y) ({ \ - const typeof(x) _x = (x); \ - const typeof(y) _y = (y); \ - (void) (&_x == &_y); \ - _x > _y ? _x : _y; }) - -#endif /* 2.4.10 -> 2.4.6 */ - - -/*****************************************************************************/ -/* 2.4.13 => 2.4.10 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) ) - -/**************************************/ -/* PCI DMA MAPPING */ - -#ifndef virt_to_page - #define virt_to_page(v) (mem_map + (virt_to_phys(v) >> PAGE_SHIFT)) -#endif - -#ifndef pci_map_page -#define pci_map_page _kc_pci_map_page -extern u64 _kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, size_t size, int direction); -#endif - -#ifndef pci_unmap_page -#define pci_unmap_page _kc_pci_unmap_page -extern void _kc_pci_unmap_page(struct pci_dev *dev, u64 dma_addr, size_t size, int direction); -#endif - -/* pci_set_dma_mask takes dma_addr_t, which is only 32-bits prior to 2.4.13 */ - -#undef PCI_DMA_32BIT -#define PCI_DMA_32BIT 0xffffffff -#undef PCI_DMA_64BIT -#define PCI_DMA_64BIT 0xffffffff - -#endif /* 2.4.13 => 2.4.10 */ - -/*****************************************************************************/ -/* 2.4.17 => 2.4.12 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,17) ) - -#ifndef __devexit_p - #define __devexit_p(x) &(x) -#endif - -#endif /* 2.4.17 => 2.4.13 */ - -/*****************************************************************************/ -/* 2.5.28 => 2.4.17 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) - -static inline void _kc_synchronize_irq() { synchronize_irq(); } -#undef synchronize_irq -#define synchronize_irq(X) _kc_synchronize_irq() - -#include -#define work_struct tq_struct -#define INIT_WORK INIT_TQUEUE -#define schedule_work schedule_task - -#endif /* 2.5.28 => 2.4.17 */ - -#endif /* _KCOMPAT_H_ */ - diff --git a/xen/drivers/net/net_init.c b/xen/drivers/net/net_init.c deleted file mode 100644 index c3fef3633a..0000000000 --- a/xen/drivers/net/net_init.c +++ /dev/null @@ -1,745 +0,0 @@ -/* net_init.c: Initialization for network devices. */ -/* - Written 1993,1994,1995 by Donald Becker. - - The author may be reached as becker@scyld.com, or C/O - Scyld Computing Corporation - 410 Severn Ave., Suite 210 - Annapolis MD 21403 - - This file contains the initialization for the "pl14+" style ethernet - drivers. It should eventually replace most of drivers/net/Space.c. - It's primary advantage is that it's able to allocate low-memory buffers. - A secondary advantage is that the dangerous NE*000 netcards can reserve - their I/O port region before the SCSI probes start. - - Modifications/additions by Bjorn Ekwall : - ethdev_index[MAX_ETH_CARDS] - register_netdev() / unregister_netdev() - - Modifications by Wolfgang Walter - Use dev_close cleanly so we always shut things down tidily. - - Changed 29/10/95, Alan Cox to pass sockaddr's around for mac addresses. - - 14/06/96 - Paul Gortmaker: Add generic eth_change_mtu() function. - 24/09/96 - Paul Norton: Add token-ring variants of the netdev functions. - - 08/11/99 - Alan Cox: Got fed up of the mess in this file and cleaned it - up. We now share common code and have regularised name - allocation setups. Abolished the 16 card limits. - 03/19/2000 - jgarzik and Urban Widmark: init_etherdev 32-byte align - 03/21/2001 - jgarzik: alloc_etherdev and friends - -*/ - -#include -#include -#include -//#include -#include -#include -//#include -#include -#include -#include -#include -#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include - -#define rtnl_lock() ((void)0) -#define rtnl_unlock() ((void)0) - -/* The network devices currently exist only in the socket namespace, so these - entries are unused. The only ones that make sense are - open start the ethercard - close stop the ethercard - ioctl To get statistics, perhaps set the interface port (AUI, BNC, etc.) - One can also imagine getting raw packets using - read & write - but this is probably better handled by a raw packet socket. - - Given that almost all of these functions are handled in the current - socket-based scheme, putting ethercard devices in /dev/ seems pointless. - - [Removed all support for /dev network devices. When someone adds - streams then by magic we get them, but otherwise they are un-needed - and a space waste] -*/ - - -static struct net_device *alloc_netdev(int sizeof_priv, const char *mask, - void (*setup)(struct net_device *)) -{ - struct net_device *dev; - int alloc_size; - - /* ensure 32-byte alignment of the private area */ - alloc_size = sizeof (*dev) + sizeof_priv + 31; - - dev = (struct net_device *) kmalloc (alloc_size, GFP_KERNEL); - if (dev == NULL) - { - printk(KERN_ERR "alloc_dev: Unable to allocate device memory.\n"); - return NULL; - } - - memset(dev, 0, alloc_size); - - if (sizeof_priv) - dev->priv = (void *) (((long)(dev + 1) + 31) & ~31); - - setup(dev); - strcpy(dev->name, mask); - - return dev; -} - -static struct net_device *init_alloc_dev(int sizeof_priv) -{ - struct net_device *dev; - int alloc_size; - - /* ensure 32-byte alignment of the private area */ - alloc_size = sizeof (*dev) + sizeof_priv + 31; - - dev = (struct net_device *) kmalloc (alloc_size, GFP_KERNEL); - if (dev == NULL) - { - printk(KERN_ERR "alloc_dev: Unable to allocate device memory.\n"); - return NULL; - } - - memset(dev, 0, alloc_size); - - if (sizeof_priv) - dev->priv = (void *) (((long)(dev + 1) + 31) & ~31); - - return dev; -} - -/* - * Create and name a device from a prototype, then perform any needed - * setup. - */ - -static struct net_device *init_netdev(struct net_device *dev, int sizeof_priv, - char *mask, void (*setup)(struct net_device *)) -{ - int new_device = 0; - - /* - * Allocate a device if one is not provided. - */ - - if (dev == NULL) { - dev=init_alloc_dev(sizeof_priv); - if(dev==NULL) - return NULL; - new_device = 1; - } - - /* - * Allocate a name - */ - - if (dev->name[0] == '\0' || dev->name[0] == ' ') { - strcpy(dev->name, mask); - if (dev_alloc_name(dev, mask)<0) { - if (new_device) - kfree(dev); - return NULL; - } - } - - //netdev_boot_setup_check(dev); - - /* - * Configure via the caller provided setup function then - * register if needed. - */ - - setup(dev); - - if (new_device) { - int err; - - rtnl_lock(); - err = register_netdevice(dev); - rtnl_unlock(); - - if (err < 0) { - kfree(dev); - dev = NULL; - } - } - return dev; -} - -#if defined(CONFIG_HIPPI) || defined(CONFIG_TR) || defined(CONFIG_NET_FC) -static int __register_netdev(struct net_device *dev) -{ - if (dev->init && dev->init(dev) != 0) { - unregister_netdev(dev); - return -EIO; - } - return 0; -} -#endif - -/** - * init_etherdev - Register ethernet device - * @dev: An ethernet device structure to be filled in, or %NULL if a new - * struct should be allocated. - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this ethernet device - * - * Fill in the fields of the device structure with ethernet-generic values. - * - * If no device structure is passed, a new one is constructed, complete with - * a private data area of size @sizeof_priv. A 32-byte (not bit) - * alignment is enforced for this private data area. - * - * If an empty string area is passed as dev->name, or a new structure is made, - * a new name string is constructed. - */ - -struct net_device *init_etherdev(struct net_device *dev, int sizeof_priv) -{ - return init_netdev(dev, sizeof_priv, "eth%d", ether_setup); -} - -/** - * alloc_etherdev - Allocates and sets up an ethernet device - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this ethernet device - * - * Fill in the fields of the device structure with ethernet-generic - * values. Basically does everything except registering the device. - * - * Constructs a new net device, complete with a private data area of - * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for - * this private data area. - */ - -struct net_device *alloc_etherdev(int sizeof_priv) -{ - return alloc_netdev(sizeof_priv, "eth%d", ether_setup); -} - -EXPORT_SYMBOL(init_etherdev); -EXPORT_SYMBOL(alloc_etherdev); - -static int eth_mac_addr(struct net_device *dev, void *p) -{ - struct sockaddr *addr=p; - if (netif_running(dev)) - return -EBUSY; - memcpy(dev->dev_addr, addr->sa_data,dev->addr_len); - return 0; -} - -static int eth_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > 1500)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - -#ifdef CONFIG_FDDI - -/** - * init_fddidev - Register FDDI device - * @dev: A FDDI device structure to be filled in, or %NULL if a new - * struct should be allocated. - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this ethernet device - * - * Fill in the fields of the device structure with FDDI-generic values. - * - * If no device structure is passed, a new one is constructed, complete with - * a private data area of size @sizeof_priv. A 32-byte (not bit) - * alignment is enforced for this private data area. - * - * If an empty string area is passed as dev->name, or a new structure is made, - * a new name string is constructed. - */ - -struct net_device *init_fddidev(struct net_device *dev, int sizeof_priv) -{ - return init_netdev(dev, sizeof_priv, "fddi%d", fddi_setup); -} - -/** - * alloc_fddidev - Register FDDI device - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this FDDI device - * - * Fill in the fields of the device structure with FDDI-generic values. - * - * Constructs a new net device, complete with a private data area of - * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for - * this private data area. - */ - -struct net_device *alloc_fddidev(int sizeof_priv) -{ - return alloc_netdev(sizeof_priv, "fddi%d", fddi_setup); -} - -EXPORT_SYMBOL(init_fddidev); -EXPORT_SYMBOL(alloc_fddidev); - -static int fddi_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < FDDI_K_SNAP_HLEN) || (new_mtu > FDDI_K_SNAP_DLEN)) - return(-EINVAL); - dev->mtu = new_mtu; - return(0); -} - -#endif /* CONFIG_FDDI */ - -#ifdef CONFIG_HIPPI - -static int hippi_change_mtu(struct net_device *dev, int new_mtu) -{ - /* - * HIPPI's got these nice large MTUs. - */ - if ((new_mtu < 68) || (new_mtu > 65280)) - return -EINVAL; - dev->mtu = new_mtu; - return(0); -} - - -/* - * For HIPPI we will actually use the lower 4 bytes of the hardware - * address as the I-FIELD rather than the actual hardware address. - */ -static int hippi_mac_addr(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - if (netif_running(dev)) - return -EBUSY; - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - return 0; -} - - -/** - * init_hippi_dev - Register HIPPI device - * @dev: A HIPPI device structure to be filled in, or %NULL if a new - * struct should be allocated. - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this ethernet device - * - * Fill in the fields of the device structure with HIPPI-generic values. - * - * If no device structure is passed, a new one is constructed, complete with - * a private data area of size @sizeof_priv. A 32-byte (not bit) - * alignment is enforced for this private data area. - * - * If an empty string area is passed as dev->name, or a new structure is made, - * a new name string is constructed. - */ - -struct net_device *init_hippi_dev(struct net_device *dev, int sizeof_priv) -{ - return init_netdev(dev, sizeof_priv, "hip%d", hippi_setup); -} - -/** - * alloc_hippi_dev - Register HIPPI device - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this HIPPI device - * - * Fill in the fields of the device structure with HIPPI-generic values. - * - * Constructs a new net device, complete with a private data area of - * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for - * this private data area. - */ - -struct net_device *alloc_hippi_dev(int sizeof_priv) -{ - return alloc_netdev(sizeof_priv, "hip%d", hippi_setup); -} - -int register_hipdev(struct net_device *dev) -{ - return __register_netdev(dev); -} - -void unregister_hipdev(struct net_device *dev) -{ - unregister_netdev(dev); -} - -EXPORT_SYMBOL(init_hippi_dev); -EXPORT_SYMBOL(alloc_hippi_dev); -EXPORT_SYMBOL(register_hipdev); -EXPORT_SYMBOL(unregister_hipdev); - -static int hippi_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p) -{ - /* Never send broadcast/multicast ARP messages */ - p->mcast_probes = 0; - - /* In IPv6 unicast probes are valid even on NBMA, - * because they are encapsulated in normal IPv6 protocol. - * Should be a generic flag. - */ - if (p->tbl->family != AF_INET6) - p->ucast_probes = 0; - return 0; -} - -#endif /* CONFIG_HIPPI */ - -void ether_setup(struct net_device *dev) -{ - /* Fill in the fields of the device structure with ethernet-generic values. - This should be in a common file instead of per-driver. */ - - dev->change_mtu = eth_change_mtu; - dev->hard_header = eth_header; - dev->rebuild_header = eth_rebuild_header; - dev->set_mac_address = eth_mac_addr; - dev->hard_header_cache = eth_header_cache; - dev->header_cache_update= eth_header_cache_update; - dev->hard_header_parse = eth_header_parse; - - dev->type = 0; //ARPHRD_ETHER; - dev->hard_header_len = ETH_HLEN; - dev->mtu = 1500; /* eth_mtu */ - dev->addr_len = ETH_ALEN; - - memset(dev->broadcast,0xFF, ETH_ALEN); - - /* New-style flags. */ - dev->flags = IFF_BROADCAST|IFF_MULTICAST; -} -EXPORT_SYMBOL(ether_setup); - -#ifdef CONFIG_FDDI - -void fddi_setup(struct net_device *dev) -{ - /* - * Fill in the fields of the device structure with FDDI-generic values. - * This should be in a common file instead of per-driver. - */ - - dev->change_mtu = fddi_change_mtu; - dev->hard_header = fddi_header; - dev->rebuild_header = fddi_rebuild_header; - - dev->type = ARPHRD_FDDI; - dev->hard_header_len = FDDI_K_SNAP_HLEN+3; /* Assume 802.2 SNAP hdr len + 3 pad bytes */ - dev->mtu = FDDI_K_SNAP_DLEN; /* Assume max payload of 802.2 SNAP frame */ - dev->addr_len = FDDI_K_ALEN; - - memset(dev->broadcast, 0xFF, FDDI_K_ALEN); - - /* New-style flags */ - dev->flags = IFF_BROADCAST | IFF_MULTICAST; -} -EXPORT_SYMBOL(fddi_setup); - -#endif /* CONFIG_FDDI */ - -#ifdef CONFIG_HIPPI -void hippi_setup(struct net_device *dev) -{ - dev->set_multicast_list = NULL; - dev->change_mtu = hippi_change_mtu; - dev->hard_header = hippi_header; - dev->rebuild_header = hippi_rebuild_header; - dev->set_mac_address = hippi_mac_addr; - dev->hard_header_parse = NULL; - dev->hard_header_cache = NULL; - dev->header_cache_update = NULL; - dev->neigh_setup = hippi_neigh_setup_dev; - - /* - * We don't support HIPPI `ARP' for the time being, and probably - * never will unless someone else implements it. However we - * still need a fake ARPHRD to make ifconfig and friends play ball. - */ - dev->type = ARPHRD_HIPPI; - dev->hard_header_len = HIPPI_HLEN; - dev->mtu = 65280; - dev->addr_len = HIPPI_ALEN; - - memset(dev->broadcast, 0xFF, HIPPI_ALEN); - - /* - * HIPPI doesn't support broadcast+multicast and we only use - * static ARP tables. ARP is disabled by hippi_neigh_setup_dev. - */ - dev->flags = 0; -} -EXPORT_SYMBOL(hippi_setup); -#endif /* CONFIG_HIPPI */ - -#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE) - -static int ltalk_change_mtu(struct net_device *dev, int mtu) -{ - return -EINVAL; -} - -static int ltalk_mac_addr(struct net_device *dev, void *addr) -{ - return -EINVAL; -} - - -void ltalk_setup(struct net_device *dev) -{ - /* Fill in the fields of the device structure with localtalk-generic values. */ - - dev->change_mtu = ltalk_change_mtu; - dev->hard_header = NULL; - dev->rebuild_header = NULL; - dev->set_mac_address = ltalk_mac_addr; - dev->hard_header_cache = NULL; - dev->header_cache_update= NULL; - - dev->type = ARPHRD_LOCALTLK; - dev->hard_header_len = LTALK_HLEN; - dev->mtu = LTALK_MTU; - dev->addr_len = LTALK_ALEN; - - dev->broadcast[0] = 0xFF; - - dev->flags = IFF_BROADCAST|IFF_MULTICAST|IFF_NOARP; -} -EXPORT_SYMBOL(ltalk_setup); - -#endif /* CONFIG_ATALK || CONFIG_ATALK_MODULE */ - -int register_netdev(struct net_device *dev) -{ - int err; - - rtnl_lock(); - - /* - * If the name is a format string the caller wants us to - * do a name allocation - */ - - if (strchr(dev->name, '%')) - { - err = dev_alloc_name(dev, dev->name); - if (err < 0) - goto out; - } - - /* - * Back compatibility hook. Kill this one in 2.5 - */ - - if (dev->name[0]==0 || dev->name[0]==' ') - { - err = dev_alloc_name(dev, "eth%d"); - if (err < 0) - goto out; - } - - err = register_netdevice(dev); - -out: - rtnl_unlock(); - return err; -} - -void unregister_netdev(struct net_device *dev) -{ - rtnl_lock(); - unregister_netdevice(dev); - rtnl_unlock(); -} - -EXPORT_SYMBOL(register_netdev); -EXPORT_SYMBOL(unregister_netdev); - - -void alert_slow_netdevice(struct net_device *dev, char *nictype) -{ - printk("***************************\n"); - printk("* WARNING FOR NET DEVICE %s (NIC type '%s'):\n", - dev->name, nictype); - printk("* This NIC cannot support fully efficient networking in Xen.\n"); - printk("* In particular, extra packet copies will be incurred!\n"); - printk("* See documentation for a list of recommended NIC types\n"); - printk("***************************\n"); -} - - -#ifdef CONFIG_TR - -void tr_setup(struct net_device *dev) -{ - /* - * Configure and register - */ - - dev->hard_header = tr_header; - dev->rebuild_header = tr_rebuild_header; - - dev->type = ARPHRD_IEEE802_TR; - dev->hard_header_len = TR_HLEN; - dev->mtu = 2000; - dev->addr_len = TR_ALEN; - - memset(dev->broadcast,0xFF, TR_ALEN); - - /* New-style flags. */ - dev->flags = IFF_BROADCAST | IFF_MULTICAST ; -} - -/** - * init_trdev - Register token ring device - * @dev: A token ring device structure to be filled in, or %NULL if a new - * struct should be allocated. - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this ethernet device - * - * Fill in the fields of the device structure with token ring-generic values. - * - * If no device structure is passed, a new one is constructed, complete with - * a private data area of size @sizeof_priv. A 32-byte (not bit) - * alignment is enforced for this private data area. - * - * If an empty string area is passed as dev->name, or a new structure is made, - * a new name string is constructed. - */ - -struct net_device *init_trdev(struct net_device *dev, int sizeof_priv) -{ - return init_netdev(dev, sizeof_priv, "tr%d", tr_setup); -} - -/** - * alloc_trdev - Register token ring device - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this token ring device - * - * Fill in the fields of the device structure with token ring-generic values. - * - * Constructs a new net device, complete with a private data area of - * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for - * this private data area. - */ - -struct net_device *alloc_trdev(int sizeof_priv) -{ - return alloc_netdev(sizeof_priv, "tr%d", tr_setup); -} - -int register_trdev(struct net_device *dev) -{ - return __register_netdev(dev); -} - -void unregister_trdev(struct net_device *dev) -{ - unregister_netdev(dev); -} - -EXPORT_SYMBOL(tr_setup); -EXPORT_SYMBOL(init_trdev); -EXPORT_SYMBOL(alloc_trdev); -EXPORT_SYMBOL(register_trdev); -EXPORT_SYMBOL(unregister_trdev); - -#endif /* CONFIG_TR */ - - -#ifdef CONFIG_NET_FC - -void fc_setup(struct net_device *dev) -{ - dev->hard_header = fc_header; - dev->rebuild_header = fc_rebuild_header; - - dev->type = ARPHRD_IEEE802; - dev->hard_header_len = FC_HLEN; - dev->mtu = 2024; - dev->addr_len = FC_ALEN; - - memset(dev->broadcast,0xFF, FC_ALEN); - - /* New-style flags. */ - dev->flags = IFF_BROADCAST; -} - -/** - * init_fcdev - Register fibre channel device - * @dev: A fibre channel device structure to be filled in, or %NULL if a new - * struct should be allocated. - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this ethernet device - * - * Fill in the fields of the device structure with fibre channel-generic values. - * - * If no device structure is passed, a new one is constructed, complete with - * a private data area of size @sizeof_priv. A 32-byte (not bit) - * alignment is enforced for this private data area. - * - * If an empty string area is passed as dev->name, or a new structure is made, - * a new name string is constructed. - */ - -struct net_device *init_fcdev(struct net_device *dev, int sizeof_priv) -{ - return init_netdev(dev, sizeof_priv, "fc%d", fc_setup); -} - -/** - * alloc_fcdev - Register fibre channel device - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this fibre channel device - * - * Fill in the fields of the device structure with fibre channel-generic values. - * - * Constructs a new net device, complete with a private data area of - * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for - * this private data area. - */ - -struct net_device *alloc_fcdev(int sizeof_priv) -{ - return alloc_netdev(sizeof_priv, "fc%d", fc_setup); -} - -int register_fcdev(struct net_device *dev) -{ - return __register_netdev(dev); -} - -void unregister_fcdev(struct net_device *dev) -{ - unregister_netdev(dev); -} - -EXPORT_SYMBOL(fc_setup); -EXPORT_SYMBOL(init_fcdev); -EXPORT_SYMBOL(alloc_fcdev); -EXPORT_SYMBOL(register_fcdev); -EXPORT_SYMBOL(unregister_fcdev); - -#endif /* CONFIG_NET_FC */ - diff --git a/xen/drivers/net/pcnet32.c b/xen/drivers/net/pcnet32.c deleted file mode 100644 index dad41fc9ed..0000000000 --- a/xen/drivers/net/pcnet32.c +++ /dev/null @@ -1,1761 +0,0 @@ -/* pcnet32.c: An AMD PCnet32 ethernet driver for linux. */ -/* - * Copyright 1996-1999 Thomas Bogendoerfer - * - * Derived from the lance driver written 1993,1994,1995 by Donald Becker. - * - * Copyright 1993 United States Government as represented by the - * Director, National Security Agency. - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * This driver is for PCnet32 and PCnetPCI based ethercards - */ -/************************************************************************** - * 23 Oct, 2000. - * Fixed a few bugs, related to running the controller in 32bit mode. - * - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - *************************************************************************/ - -#define DRV_NAME "pcnet32" -#define DRV_VERSION "1.27a" -#define DRV_RELDATE "10.02.2002" -#define PFX DRV_NAME ": " - -static const char *version = -DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n"; - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#undef TX_RING_SIZE -#undef RX_RING_SIZE - -/* - * PCI device identifiers for "new style" Linux PCI Device Drivers - */ -static struct pci_device_id pcnet32_pci_tbl[] __devinitdata = { - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { 0, } -}; - -MODULE_DEVICE_TABLE (pci, pcnet32_pci_tbl); - -int cards_found __initdata; - -/* - * VLB I/O addresses - */ -static unsigned int pcnet32_portlist[] __initdata = - { 0x300, 0x320, 0x340, 0x360, 0 }; - - - -static int pcnet32_debug = 1; -static int tx_start = 1; /* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */ -static int pcnet32vlb; /* check for VLB cards ? */ - -static struct net_device *pcnet32_dev; - -static int max_interrupt_work = 80; -#ifdef COPYBREAK -static int rx_copybreak = 200; -#endif - -#define PCNET32_PORT_AUI 0x00 -#define PCNET32_PORT_10BT 0x01 -#define PCNET32_PORT_GPSI 0x02 -#define PCNET32_PORT_MII 0x03 - -#define PCNET32_PORT_PORTSEL 0x03 -#define PCNET32_PORT_ASEL 0x04 -#define PCNET32_PORT_100 0x40 -#define PCNET32_PORT_FD 0x80 - -#define PCNET32_DMA_MASK 0xffffffff - -/* - * table to translate option values from tulip - * to internal options - */ -static unsigned char options_mapping[] = { - PCNET32_PORT_ASEL, /* 0 Auto-select */ - PCNET32_PORT_AUI, /* 1 BNC/AUI */ - PCNET32_PORT_AUI, /* 2 AUI/BNC */ - PCNET32_PORT_ASEL, /* 3 not supported */ - PCNET32_PORT_10BT | PCNET32_PORT_FD, /* 4 10baseT-FD */ - PCNET32_PORT_ASEL, /* 5 not supported */ - PCNET32_PORT_ASEL, /* 6 not supported */ - PCNET32_PORT_ASEL, /* 7 not supported */ - PCNET32_PORT_ASEL, /* 8 not supported */ - PCNET32_PORT_MII, /* 9 MII 10baseT */ - PCNET32_PORT_MII | PCNET32_PORT_FD, /* 10 MII 10baseT-FD */ - PCNET32_PORT_MII, /* 11 MII (autosel) */ - PCNET32_PORT_10BT, /* 12 10BaseT */ - PCNET32_PORT_MII | PCNET32_PORT_100, /* 13 MII 100BaseTx */ - PCNET32_PORT_MII | PCNET32_PORT_100 | PCNET32_PORT_FD, /* 14 MII 100BaseTx-FD */ - PCNET32_PORT_ASEL /* 15 not supported */ -}; - -#define MAX_UNITS 8 /* More are supported, limit only on options */ -static int options[MAX_UNITS]; -static int full_duplex[MAX_UNITS]; - -/* - * Theory of Operation - * - * This driver uses the same software structure as the normal lance - * driver. So look for a verbose description in lance.c. The differences - * to the normal lance driver is the use of the 32bit mode of PCnet32 - * and PCnetPCI chips. Because these chips are 32bit chips, there is no - * 16MB limitation and we don't need bounce buffers. - */ - -/* - * History: - * v0.01: Initial version - * only tested on Alpha Noname Board - * v0.02: changed IRQ handling for new interrupt scheme (dev_id) - * tested on a ASUS SP3G - * v0.10: fixed an odd problem with the 79C974 in a Compaq Deskpro XL - * looks like the 974 doesn't like stopping and restarting in a - * short period of time; now we do a reinit of the lance; the - * bug was triggered by doing ifconfig eth0 broadcast - * and hangs the machine (thanks to Klaus Liedl for debugging) - * v0.12: by suggestion from Donald Becker: Renamed driver to pcnet32, - * made it standalone (no need for lance.c) - * v0.13: added additional PCI detecting for special PCI devices (Compaq) - * v0.14: stripped down additional PCI probe (thanks to David C Niemi - * and sveneric@xs4all.nl for testing this on their Compaq boxes) - * v0.15: added 79C965 (VLB) probe - * added interrupt sharing for PCI chips - * v0.16: fixed set_multicast_list on Alpha machines - * v0.17: removed hack from dev.c; now pcnet32 uses ethif_probe in Space.c - * v0.19: changed setting of autoselect bit - * v0.20: removed additional Compaq PCI probe; there is now a working one - * in arch/i386/bios32.c - * v0.21: added endian conversion for ppc, from work by cort@cs.nmt.edu - * v0.22: added printing of status to ring dump - * v0.23: changed enet_statistics to net_devive_stats - * v0.90: added multicast filter - * added module support - * changed irq probe to new style - * added PCnetFast chip id - * added fix for receive stalls with Intel saturn chipsets - * added in-place rx skbs like in the tulip driver - * minor cleanups - * v0.91: added PCnetFast+ chip id - * back port to 2.0.x - * v1.00: added some stuff from Donald Becker's 2.0.34 version - * added support for byte counters in net_dev_stats - * v1.01: do ring dumps, only when debugging the driver - * increased the transmit timeout - * v1.02: fixed memory leak in pcnet32_init_ring() - * v1.10: workaround for stopped transmitter - * added port selection for modules - * detect special T1/E1 WAN card and setup port selection - * v1.11: fixed wrong checking of Tx errors - * v1.20: added check of return value kmalloc (cpeterso@cs.washington.edu) - * added save original kmalloc addr for freeing (mcr@solidum.com) - * added support for PCnetHome chip (joe@MIT.EDU) - * rewritten PCI card detection - * added dwio mode to get driver working on some PPC machines - * v1.21: added mii selection and mii ioctl - * v1.22: changed pci scanning code to make PPC people happy - * fixed switching to 32bit mode in pcnet32_open() (thanks - * to Michael Richard for noticing this one) - * added sub vendor/device id matching (thanks again to - * Michael Richard ) - * added chip id for 79c973/975 (thanks to Zach Brown ) - * v1.23 fixed small bug, when manual selecting MII speed/duplex - * v1.24 Applied Thomas' patch to use TxStartPoint and thus decrease TxFIFO - * underflows. Added tx_start_pt module parameter. Increased - * TX_RING_SIZE from 16 to 32. Added #ifdef'd code to use DXSUFLO - * for FAST[+] chipsets. - * v1.24ac Added SMP spinlocking - Alan Cox - * v1.25kf Added No Interrupt on successful Tx for some Tx's - * v1.26 Converted to pci_alloc_consistent, Jamey Hicks / George France - * - * - Fixed a few bugs, related to running the controller in 32bit mode. - * 23 Oct, 2000. Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * v1.26p Fix oops on rmmod+insmod; plug i/o resource leak - Paul Gortmaker - * v1.27 improved CSR/PROM address detection, lots of cleanups, - * new pcnet32vlb module option, HP-PARISC support, - * added module parameter descriptions, - * initial ethtool support - Helge Deller - * v1.27a Sun Feb 10 2002 Go Taniguchi - * use alloc_etherdev and register_netdev - * fix pci probe not increment cards_found - * FD auto negotiate error workaround for xSeries250 - * clean up and using new mii module - */ - - -/* - * Set the number of Tx and Rx buffers, using Log_2(# buffers). - * Reasonable default values are 4 Tx buffers, and 16 Rx buffers. - * That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4). - */ -#ifndef PCNET32_LOG_TX_BUFFERS -#define PCNET32_LOG_TX_BUFFERS 4 -#define PCNET32_LOG_RX_BUFFERS 5 -#endif - -#define TX_RING_SIZE (1 << (PCNET32_LOG_TX_BUFFERS)) -#define TX_RING_MOD_MASK (TX_RING_SIZE - 1) -#define TX_RING_LEN_BITS ((PCNET32_LOG_TX_BUFFERS) << 12) - -#define RX_RING_SIZE (1 << (PCNET32_LOG_RX_BUFFERS)) -#define RX_RING_MOD_MASK (RX_RING_SIZE - 1) -#define RX_RING_LEN_BITS ((PCNET32_LOG_RX_BUFFERS) << 4) - -#define PKT_BUF_SZ 1544 - -/* Offsets from base I/O address. */ -#define PCNET32_WIO_RDP 0x10 -#define PCNET32_WIO_RAP 0x12 -#define PCNET32_WIO_RESET 0x14 -#define PCNET32_WIO_BDP 0x16 - -#define PCNET32_DWIO_RDP 0x10 -#define PCNET32_DWIO_RAP 0x14 -#define PCNET32_DWIO_RESET 0x18 -#define PCNET32_DWIO_BDP 0x1C - -#define PCNET32_TOTAL_SIZE 0x20 - -/* The PCNET32 Rx and Tx ring descriptors. */ -struct pcnet32_rx_head { - u32 base; - s16 buf_length; - s16 status; - u32 msg_length; - u32 reserved; -}; - -struct pcnet32_tx_head { - u32 base; - s16 length; - s16 status; - u32 misc; - u32 reserved; -}; - -/* The PCNET32 32-Bit initialization block, described in databook. */ -struct pcnet32_init_block { - u16 mode; - u16 tlen_rlen; - u8 phys_addr[6]; - u16 reserved; - u32 filter[2]; - /* Receive and transmit ring base, along with extra bits. */ - u32 rx_ring; - u32 tx_ring; -}; - -/* PCnet32 access functions */ -struct pcnet32_access { - u16 (*read_csr)(unsigned long, int); - void (*write_csr)(unsigned long, int, u16); - u16 (*read_bcr)(unsigned long, int); - void (*write_bcr)(unsigned long, int, u16); - u16 (*read_rap)(unsigned long); - void (*write_rap)(unsigned long, u16); - void (*reset)(unsigned long); -}; - -/* - * The first three fields of pcnet32_private are read by the ethernet device - * so we allocate the structure should be allocated by pci_alloc_consistent(). - */ -struct pcnet32_private { - /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */ - struct pcnet32_rx_head rx_ring[RX_RING_SIZE]; - struct pcnet32_tx_head tx_ring[TX_RING_SIZE]; - struct pcnet32_init_block init_block; - dma_addr_t dma_addr; /* DMA address of beginning of this object, - returned by pci_alloc_consistent */ - struct pci_dev *pci_dev; /* Pointer to the associated pci device structure */ - const char *name; - /* The saved address of a sent-in-place packet/buffer, for skfree(). */ - struct sk_buff *tx_skbuff[TX_RING_SIZE]; - struct sk_buff *rx_skbuff[RX_RING_SIZE]; - dma_addr_t tx_dma_addr[TX_RING_SIZE]; - dma_addr_t rx_dma_addr[RX_RING_SIZE]; - struct pcnet32_access a; - spinlock_t lock; /* Guard lock */ - unsigned int cur_rx, cur_tx; /* The next free ring entry */ - unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ - struct net_device_stats stats; - char tx_full; - int options; - int shared_irq:1, /* shared irq possible */ - ltint:1, /* enable TxDone-intr inhibitor */ - dxsuflo:1, /* disable transmit stop on uflo */ - mii:1; /* mii port available */ - struct net_device *next; - struct mii_if_info mii_if; -}; - -static void pcnet32_probe_vlbus(void); -static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *); -static int pcnet32_probe1(unsigned long, unsigned int, int, struct pci_dev *); -static int pcnet32_open(struct net_device *); -static int pcnet32_init_ring(struct net_device *); -static int pcnet32_start_xmit(struct sk_buff *, struct net_device *); -static int pcnet32_rx(struct net_device *); -static void pcnet32_tx_timeout (struct net_device *dev); -static void pcnet32_interrupt(int, void *, struct pt_regs *); -static int pcnet32_close(struct net_device *); -static struct net_device_stats *pcnet32_get_stats(struct net_device *); -static void pcnet32_set_multicast_list(struct net_device *); -#if 0 -static int pcnet32_ioctl(struct net_device *, struct ifreq *, int); -#endif -static int mdio_read(struct net_device *dev, int phy_id, int reg_num); -static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val); - -enum pci_flags_bit { - PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, - PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, -}; - - -static u16 pcnet32_wio_read_csr (unsigned long addr, int index) -{ - outw (index, addr+PCNET32_WIO_RAP); - return inw (addr+PCNET32_WIO_RDP); -} - -static void pcnet32_wio_write_csr (unsigned long addr, int index, u16 val) -{ - outw (index, addr+PCNET32_WIO_RAP); - outw (val, addr+PCNET32_WIO_RDP); -} - -static u16 pcnet32_wio_read_bcr (unsigned long addr, int index) -{ - outw (index, addr+PCNET32_WIO_RAP); - return inw (addr+PCNET32_WIO_BDP); -} - -static void pcnet32_wio_write_bcr (unsigned long addr, int index, u16 val) -{ - outw (index, addr+PCNET32_WIO_RAP); - outw (val, addr+PCNET32_WIO_BDP); -} - -static u16 pcnet32_wio_read_rap (unsigned long addr) -{ - return inw (addr+PCNET32_WIO_RAP); -} - -static void pcnet32_wio_write_rap (unsigned long addr, u16 val) -{ - outw (val, addr+PCNET32_WIO_RAP); -} - -static void pcnet32_wio_reset (unsigned long addr) -{ - inw (addr+PCNET32_WIO_RESET); -} - -static int pcnet32_wio_check (unsigned long addr) -{ - outw (88, addr+PCNET32_WIO_RAP); - return (inw (addr+PCNET32_WIO_RAP) == 88); -} - -static struct pcnet32_access pcnet32_wio = { - read_csr: pcnet32_wio_read_csr, - write_csr: pcnet32_wio_write_csr, - read_bcr: pcnet32_wio_read_bcr, - write_bcr: pcnet32_wio_write_bcr, - read_rap: pcnet32_wio_read_rap, - write_rap: pcnet32_wio_write_rap, - reset: pcnet32_wio_reset -}; - -static u16 pcnet32_dwio_read_csr (unsigned long addr, int index) -{ - outl (index, addr+PCNET32_DWIO_RAP); - return (inl (addr+PCNET32_DWIO_RDP) & 0xffff); -} - -static void pcnet32_dwio_write_csr (unsigned long addr, int index, u16 val) -{ - outl (index, addr+PCNET32_DWIO_RAP); - outl (val, addr+PCNET32_DWIO_RDP); -} - -static u16 pcnet32_dwio_read_bcr (unsigned long addr, int index) -{ - outl (index, addr+PCNET32_DWIO_RAP); - return (inl (addr+PCNET32_DWIO_BDP) & 0xffff); -} - -static void pcnet32_dwio_write_bcr (unsigned long addr, int index, u16 val) -{ - outl (index, addr+PCNET32_DWIO_RAP); - outl (val, addr+PCNET32_DWIO_BDP); -} - -static u16 pcnet32_dwio_read_rap (unsigned long addr) -{ - return (inl (addr+PCNET32_DWIO_RAP) & 0xffff); -} - -static void pcnet32_dwio_write_rap (unsigned long addr, u16 val) -{ - outl (val, addr+PCNET32_DWIO_RAP); -} - -static void pcnet32_dwio_reset (unsigned long addr) -{ - inl (addr+PCNET32_DWIO_RESET); -} - -static int pcnet32_dwio_check (unsigned long addr) -{ - outl (88, addr+PCNET32_DWIO_RAP); - return ((inl (addr+PCNET32_DWIO_RAP) & 0xffff) == 88); -} - -static struct pcnet32_access pcnet32_dwio = { - read_csr: pcnet32_dwio_read_csr, - write_csr: pcnet32_dwio_write_csr, - read_bcr: pcnet32_dwio_read_bcr, - write_bcr: pcnet32_dwio_write_bcr, - read_rap: pcnet32_dwio_read_rap, - write_rap: pcnet32_dwio_write_rap, - reset: pcnet32_dwio_reset -}; - - - -/* only probes for non-PCI devices, the rest are handled by - * pci_register_driver via pcnet32_probe_pci */ - -static void __devinit -pcnet32_probe_vlbus(void) -{ - unsigned int *port, ioaddr; - - /* search for PCnet32 VLB cards at known addresses */ - for (port = pcnet32_portlist; (ioaddr = *port); port++) { - if (!check_region(ioaddr, PCNET32_TOTAL_SIZE)) { - /* check if there is really a pcnet chip on that ioaddr */ - if ((inb(ioaddr + 14) == 0x57) && (inb(ioaddr + 15) == 0x57)) - pcnet32_probe1(ioaddr, 0, 0, NULL); - } - } -} - - -static int __devinit -pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - unsigned long ioaddr; - int err; - - err = pci_enable_device(pdev); - if (err < 0) { - printk(KERN_ERR PFX "failed to enable device -- err=%d\n", err); - return err; - } - pci_set_master(pdev); - - ioaddr = pci_resource_start (pdev, 0); - if (!ioaddr) { - printk (KERN_ERR PFX "card has no PCI IO resources, aborting\n"); - return -ENODEV; - } - - if (!pci_dma_supported(pdev, PCNET32_DMA_MASK)) { - printk(KERN_ERR PFX "architecture does not support 32bit PCI busmaster DMA\n"); - return -ENODEV; - } - - return pcnet32_probe1(ioaddr, pdev->irq, 1, pdev); -} - - -/* pcnet32_probe1 - * Called from both pcnet32_probe_vlbus and pcnet_probe_pci. - * pdev will be NULL when called from pcnet32_probe_vlbus. - */ -static int __devinit -pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, - struct pci_dev *pdev) -{ - struct pcnet32_private *lp; - dma_addr_t lp_dma_addr; - int i, media; - int fdx, mii, fset, dxsuflo, ltint; - int chip_version; - char *chipname; - struct net_device *dev; - struct pcnet32_access *a = NULL; - u8 promaddr[6]; - - /* reset the chip */ - pcnet32_wio_reset(ioaddr); - - /* NOTE: 16-bit check is first, otherwise some older PCnet chips fail */ - if (pcnet32_wio_read_csr(ioaddr, 0) == 4 && pcnet32_wio_check(ioaddr)) { - a = &pcnet32_wio; - } else { - pcnet32_dwio_reset(ioaddr); - if (pcnet32_dwio_read_csr(ioaddr, 0) == 4 && pcnet32_dwio_check(ioaddr)) { - a = &pcnet32_dwio; - } else - return -ENODEV; - } - - chip_version = a->read_csr(ioaddr, 88) | (a->read_csr(ioaddr,89) << 16); - if (pcnet32_debug > 2) - printk(KERN_INFO " PCnet chip version is %#x.\n", chip_version); - if ((chip_version & 0xfff) != 0x003) - return -ENODEV; - - /* initialize variables */ - fdx = mii = fset = dxsuflo = ltint = 0; - chip_version = (chip_version >> 12) & 0xffff; - - switch (chip_version) { - case 0x2420: - chipname = "PCnet/PCI 79C970"; /* PCI */ - break; - case 0x2430: - if (shared) - chipname = "PCnet/PCI 79C970"; /* 970 gives the wrong chip id back */ - else - chipname = "PCnet/32 79C965"; /* 486/VL bus */ - break; - case 0x2621: - chipname = "PCnet/PCI II 79C970A"; /* PCI */ - fdx = 1; - break; - case 0x2623: - chipname = "PCnet/FAST 79C971"; /* PCI */ - fdx = 1; mii = 1; fset = 1; - ltint = 1; - break; - case 0x2624: - chipname = "PCnet/FAST+ 79C972"; /* PCI */ - fdx = 1; mii = 1; fset = 1; - break; - case 0x2625: - chipname = "PCnet/FAST III 79C973"; /* PCI */ - fdx = 1; mii = 1; - break; - case 0x2626: - chipname = "PCnet/Home 79C978"; /* PCI */ - fdx = 1; - /* - * This is based on specs published at www.amd.com. This section - * assumes that a card with a 79C978 wants to go into 1Mb HomePNA - * mode. The 79C978 can also go into standard ethernet, and there - * probably should be some sort of module option to select the - * mode by which the card should operate - */ - /* switch to home wiring mode */ - media = a->read_bcr(ioaddr, 49); -#if 0 - if (pcnet32_debug > 2) - printk(KERN_DEBUG PFX "media value %#x.\n", media); - media &= ~3; - media |= 1; -#endif - if (pcnet32_debug > 2) - printk(KERN_DEBUG PFX "media reset to %#x.\n", media); - a->write_bcr(ioaddr, 49, media); - break; - case 0x2627: - chipname = "PCnet/FAST III 79C975"; /* PCI */ - fdx = 1; mii = 1; - break; - default: - printk(KERN_INFO PFX "PCnet version %#x, no PCnet32 chip.\n", - chip_version); - return -ENODEV; - } - - /* - * On selected chips turn on the BCR18:NOUFLO bit. This stops transmit - * starting until the packet is loaded. Strike one for reliability, lose - * one for latency - although on PCI this isnt a big loss. Older chips - * have FIFO's smaller than a packet, so you can't do this. - */ - - if(fset) - { - a->write_bcr(ioaddr, 18, (a->read_bcr(ioaddr, 18) | 0x0800)); - a->write_csr(ioaddr, 80, (a->read_csr(ioaddr, 80) & 0x0C00) | 0x0c00); - dxsuflo = 1; - ltint = 1; - } - - dev = alloc_etherdev(0); - if(!dev) - return -ENOMEM; - - printk(KERN_INFO PFX "%s at %#3lx,", chipname, ioaddr); - - /* In most chips, after a chip reset, the ethernet address is read from the - * station address PROM at the base address and programmed into the - * "Physical Address Registers" CSR12-14. - * As a precautionary measure, we read the PROM values and complain if - * they disagree with the CSRs. Either way, we use the CSR values, and - * double check that they are valid. - */ - for (i = 0; i < 3; i++) { - unsigned int val; - val = a->read_csr(ioaddr, i+12) & 0x0ffff; - /* There may be endianness issues here. */ - dev->dev_addr[2*i] = val & 0x0ff; - dev->dev_addr[2*i+1] = (val >> 8) & 0x0ff; - } - - /* read PROM address and compare with CSR address */ - for (i = 0; i < 6; i++) - promaddr[i] = inb(ioaddr + i); - - if( memcmp( promaddr, dev->dev_addr, 6) - || !is_valid_ether_addr(dev->dev_addr) ) { -#ifndef __powerpc__ - if( is_valid_ether_addr(promaddr) ){ -#else - if( !is_valid_ether_addr(dev->dev_addr) - && is_valid_ether_addr(promaddr)) { -#endif - printk(" warning: CSR address invalid,\n"); - printk(KERN_INFO " using instead PROM address of"); - memcpy(dev->dev_addr, promaddr, 6); - } - } - - /* if the ethernet address is not valid, force to 00:00:00:00:00:00 */ - if( !is_valid_ether_addr(dev->dev_addr) ) - memset(dev->dev_addr, 0, sizeof(dev->dev_addr)); - - for (i = 0; i < 6; i++) - printk(" %2.2x", dev->dev_addr[i] ); - - if (((chip_version + 1) & 0xfffe) == 0x2624) { /* Version 0x2623 or 0x2624 */ - i = a->read_csr(ioaddr, 80) & 0x0C00; /* Check tx_start_pt */ - printk("\n" KERN_INFO " tx_start_pt(0x%04x):",i); - switch(i>>10) { - case 0: printk(" 20 bytes,"); break; - case 1: printk(" 64 bytes,"); break; - case 2: printk(" 128 bytes,"); break; - case 3: printk("~220 bytes,"); break; - } - i = a->read_bcr(ioaddr, 18); /* Check Burst/Bus control */ - printk(" BCR18(%x):",i&0xffff); - if (i & (1<<5)) printk("BurstWrEn "); - if (i & (1<<6)) printk("BurstRdEn "); - if (i & (1<<7)) printk("DWordIO "); - if (i & (1<<11)) printk("NoUFlow "); - i = a->read_bcr(ioaddr, 25); - printk("\n" KERN_INFO " SRAMSIZE=0x%04x,",i<<8); - i = a->read_bcr(ioaddr, 26); - printk(" SRAM_BND=0x%04x,",i<<8); - i = a->read_bcr(ioaddr, 27); - if (i & (1<<14)) printk("LowLatRx"); - } - - dev->base_addr = ioaddr; - if (request_region(ioaddr, PCNET32_TOTAL_SIZE, chipname) == NULL) - return -EBUSY; - - /* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */ - if ((lp = pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) { - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return -ENOMEM; - } - - memset(lp, 0, sizeof(*lp)); - lp->dma_addr = lp_dma_addr; - lp->pci_dev = pdev; - - spin_lock_init(&lp->lock); - - dev->priv = lp; - lp->name = chipname; - lp->shared_irq = shared; - lp->mii_if.full_duplex = fdx; - lp->dxsuflo = dxsuflo; - lp->ltint = ltint; - lp->mii = mii; - if ((cards_found >= MAX_UNITS) || (options[cards_found] > sizeof(options_mapping))) - lp->options = PCNET32_PORT_ASEL; - else - lp->options = options_mapping[options[cards_found]]; - lp->mii_if.dev = dev; - lp->mii_if.mdio_read = mdio_read; - lp->mii_if.mdio_write = mdio_write; - - if (fdx && !(lp->options & PCNET32_PORT_ASEL) && - ((cards_found>=MAX_UNITS) || full_duplex[cards_found])) - lp->options |= PCNET32_PORT_FD; - - if (!a) { - printk(KERN_ERR PFX "No access methods\n"); - pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return -ENODEV; - } - lp->a = *a; - - /* detect special T1/E1 WAN card by checking for MAC address */ - if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0 && dev->dev_addr[2] == 0x75) - lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI; - - lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */ - lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS); - for (i = 0; i < 6; i++) - lp->init_block.phys_addr[i] = dev->dev_addr[i]; - lp->init_block.filter[0] = 0x00000000; - lp->init_block.filter[1] = 0x00000000; - lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr + offsetof(struct pcnet32_private, rx_ring)); - lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)); - - /* switch pcnet32 to 32bit mode */ - a->write_bcr (ioaddr, 20, 2); - - a->write_csr (ioaddr, 1, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) & 0xffff); - a->write_csr (ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) >> 16); - - if (irq_line) { - dev->irq = irq_line; - } - - if (dev->irq >= 2) - printk(" assigned IRQ %d.\n", dev->irq); - else { - unsigned long irq_mask = probe_irq_on(); - - /* - * To auto-IRQ we enable the initialization-done and DMA error - * interrupts. For ISA boards we get a DMA error, but VLB and PCI - * boards will work. - */ - /* Trigger an initialization just for the interrupt. */ - a->write_csr (ioaddr, 0, 0x41); - mdelay (1); - - dev->irq = probe_irq_off (irq_mask); - if (dev->irq) - printk(", probed IRQ %d.\n", dev->irq); - else { - printk(", failed to detect IRQ line.\n"); - pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return -ENODEV; - } - } - - - /* The PCNET32-specific entries in the device structure. */ - dev->open = &pcnet32_open; - dev->hard_start_xmit = &pcnet32_start_xmit; - dev->stop = &pcnet32_close; - dev->get_stats = &pcnet32_get_stats; - dev->set_multicast_list = &pcnet32_set_multicast_list; -#if 0 - dev->do_ioctl = &pcnet32_ioctl; -#endif - dev->tx_timeout = pcnet32_tx_timeout; - dev->watchdog_timeo = (5*HZ); - - lp->next = pcnet32_dev; - pcnet32_dev = dev; - - /* Fill in the generic fields of the device structure. */ - register_netdev(dev); - printk(KERN_INFO "%s: registered as %s\n",dev->name, lp->name); - cards_found++; - - alert_slow_netdevice(dev, "PCnet32/lance"); - - return 0; -} - - -static int -pcnet32_open(struct net_device *dev) -{ - struct pcnet32_private *lp = dev->priv; - unsigned long ioaddr = dev->base_addr; - u16 val; - int i; - - if (dev->irq == 0 || - request_irq(dev->irq, &pcnet32_interrupt, - lp->shared_irq ? SA_SHIRQ : 0, lp->name, (void *)dev)) { - return -EAGAIN; - } - - /* Check for a valid station address */ - if( !is_valid_ether_addr(dev->dev_addr) ) - return -EINVAL; - - /* Reset the PCNET32 */ - lp->a.reset (ioaddr); - - /* switch pcnet32 to 32bit mode */ - lp->a.write_bcr (ioaddr, 20, 2); - - if (pcnet32_debug > 1) - printk(KERN_DEBUG "%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n", - dev->name, dev->irq, - (u32) (lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)), - (u32) (lp->dma_addr + offsetof(struct pcnet32_private, rx_ring)), - (u32) (lp->dma_addr + offsetof(struct pcnet32_private, init_block))); - - /* set/reset autoselect bit */ - val = lp->a.read_bcr (ioaddr, 2) & ~2; - if (lp->options & PCNET32_PORT_ASEL) - val |= 2; - lp->a.write_bcr (ioaddr, 2, val); - - /* handle full duplex setting */ - if (lp->mii_if.full_duplex) { - val = lp->a.read_bcr (ioaddr, 9) & ~3; - if (lp->options & PCNET32_PORT_FD) { - val |= 1; - if (lp->options == (PCNET32_PORT_FD | PCNET32_PORT_AUI)) - val |= 2; - } else if (lp->options & PCNET32_PORT_ASEL) { - /* workaround of xSeries250, turn on for 79C975 only */ - i = ((lp->a.read_csr(ioaddr, 88) | (lp->a.read_csr(ioaddr,89) << 16)) >> 12) & 0xffff; - if (i == 0x2627) val |= 3; - } - lp->a.write_bcr (ioaddr, 9, val); - } - - /* set/reset GPSI bit in test register */ - val = lp->a.read_csr (ioaddr, 124) & ~0x10; - if ((lp->options & PCNET32_PORT_PORTSEL) == PCNET32_PORT_GPSI) - val |= 0x10; - lp->a.write_csr (ioaddr, 124, val); - - if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) { - val = lp->a.read_bcr (ioaddr, 32) & ~0x38; /* disable Auto Negotiation, set 10Mpbs, HD */ - if (lp->options & PCNET32_PORT_FD) - val |= 0x10; - if (lp->options & PCNET32_PORT_100) - val |= 0x08; - lp->a.write_bcr (ioaddr, 32, val); - } else { - if (lp->options & PCNET32_PORT_ASEL) { /* enable auto negotiate, setup, disable fd */ - val = lp->a.read_bcr(ioaddr, 32) & ~0x98; - val |= 0x20; - lp->a.write_bcr(ioaddr, 32, val); - } - } - -#ifdef DO_DXSUFLO - if (lp->dxsuflo) { /* Disable transmit stop on underflow */ - val = lp->a.read_csr (ioaddr, 3); - val |= 0x40; - lp->a.write_csr (ioaddr, 3, val); - } -#endif - - if (lp->ltint) { /* Enable TxDone-intr inhibitor */ - val = lp->a.read_csr (ioaddr, 5); - val |= (1<<14); - lp->a.write_csr (ioaddr, 5, val); - } - - lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); - lp->init_block.filter[0] = 0x00000000; - lp->init_block.filter[1] = 0x00000000; - if (pcnet32_init_ring(dev)) - return -ENOMEM; - - /* Re-initialize the PCNET32, and start it when done. */ - lp->a.write_csr (ioaddr, 1, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) &0xffff); - lp->a.write_csr (ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) >> 16); - - lp->a.write_csr (ioaddr, 4, 0x0915); - lp->a.write_csr (ioaddr, 0, 0x0001); - - netif_start_queue(dev); - - i = 0; - while (i++ < 100) - if (lp->a.read_csr (ioaddr, 0) & 0x0100) - break; - /* - * We used to clear the InitDone bit, 0x0100, here but Mark Stockton - * reports that doing so triggers a bug in the '974. - */ - lp->a.write_csr (ioaddr, 0, 0x0042); - - if (pcnet32_debug > 2) - printk(KERN_DEBUG "%s: pcnet32 open after %d ticks, init block %#x csr0 %4.4x.\n", - dev->name, i, (u32) (lp->dma_addr + offsetof(struct pcnet32_private, init_block)), - lp->a.read_csr(ioaddr, 0)); - - - MOD_INC_USE_COUNT; - - return 0; /* Always succeed */ -} - -/* - * The LANCE has been halted for one reason or another (busmaster memory - * arbitration error, Tx FIFO underflow, driver stopped it to reconfigure, - * etc.). Modern LANCE variants always reload their ring-buffer - * configuration when restarted, so we must reinitialize our ring - * context before restarting. As part of this reinitialization, - * find all packets still on the Tx ring and pretend that they had been - * sent (in effect, drop the packets on the floor) - the higher-level - * protocols will time out and retransmit. It'd be better to shuffle - * these skbs to a temp list and then actually re-Tx them after - * restarting the chip, but I'm too lazy to do so right now. dplatt@3do.com - */ - -static void -pcnet32_purge_tx_ring(struct net_device *dev) -{ - struct pcnet32_private *lp = dev->priv; - int i; - - for (i = 0; i < TX_RING_SIZE; i++) { - if (lp->tx_skbuff[i]) { - pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE); - dev_kfree_skb_any(lp->tx_skbuff[i]); - lp->tx_skbuff[i] = NULL; - lp->tx_dma_addr[i] = 0; - } - } -} - - -/* Initialize the PCNET32 Rx and Tx rings. */ -static int -pcnet32_init_ring(struct net_device *dev) -{ - struct pcnet32_private *lp = dev->priv; - int i; - - lp->tx_full = 0; - lp->cur_rx = lp->cur_tx = 0; - lp->dirty_rx = lp->dirty_tx = 0; - - for (i = 0; i < RX_RING_SIZE; i++) { - struct sk_buff *rx_skbuff = lp->rx_skbuff[i]; - if (rx_skbuff == NULL) { - if (!(rx_skbuff = lp->rx_skbuff[i] = dev_alloc_skb (PKT_BUF_SZ))) { - /* there is not much, we can do at this point */ - printk(KERN_ERR "%s: pcnet32_init_ring dev_alloc_skb failed.\n",dev->name); - return -1; - } - skb_reserve (rx_skbuff, 2); - } - lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->tail, rx_skbuff->len, PCI_DMA_FROMDEVICE); - lp->rx_ring[i].base = (u32)le32_to_cpu(lp->rx_dma_addr[i]); - lp->rx_ring[i].buf_length = le16_to_cpu(-PKT_BUF_SZ); - lp->rx_ring[i].status = le16_to_cpu(0x8000); - } - /* The Tx buffer address is filled in as needed, but we do need to clear - the upper ownership bit. */ - for (i = 0; i < TX_RING_SIZE; i++) { - lp->tx_ring[i].base = 0; - lp->tx_ring[i].status = 0; - lp->tx_dma_addr[i] = 0; - } - - lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS); - for (i = 0; i < 6; i++) - lp->init_block.phys_addr[i] = dev->dev_addr[i]; - lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr + offsetof(struct pcnet32_private, rx_ring)); - lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)); - return 0; -} - -static void -pcnet32_restart(struct net_device *dev, unsigned int csr0_bits) -{ - struct pcnet32_private *lp = dev->priv; - unsigned long ioaddr = dev->base_addr; - int i; - - pcnet32_purge_tx_ring(dev); - if (pcnet32_init_ring(dev)) - return; - - /* ReInit Ring */ - lp->a.write_csr (ioaddr, 0, 1); - i = 0; - while (i++ < 100) - if (lp->a.read_csr (ioaddr, 0) & 0x0100) - break; - - lp->a.write_csr (ioaddr, 0, csr0_bits); -} - - -static void -pcnet32_tx_timeout (struct net_device *dev) -{ - struct pcnet32_private *lp = dev->priv; - unsigned long ioaddr = dev->base_addr, flags; - - spin_lock_irqsave(&lp->lock, flags); - /* Transmitter timeout, serious problems. */ - printk(KERN_ERR "%s: transmit timed out, status %4.4x, resetting.\n", - dev->name, lp->a.read_csr(ioaddr, 0)); - lp->a.write_csr (ioaddr, 0, 0x0004); - lp->stats.tx_errors++; - if (pcnet32_debug > 2) { - int i; - printk(KERN_DEBUG " Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.", - lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "", - lp->cur_rx); - for (i = 0 ; i < RX_RING_SIZE; i++) - printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", - lp->rx_ring[i].base, -lp->rx_ring[i].buf_length, - lp->rx_ring[i].msg_length, (unsigned)lp->rx_ring[i].status); - for (i = 0 ; i < TX_RING_SIZE; i++) - printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", - lp->tx_ring[i].base, -lp->tx_ring[i].length, - lp->tx_ring[i].misc, (unsigned)lp->tx_ring[i].status); - printk("\n"); - } - pcnet32_restart(dev, 0x0042); - - dev->trans_start = jiffies; - netif_start_queue(dev); - - spin_unlock_irqrestore(&lp->lock, flags); -} - - -static int -pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct pcnet32_private *lp = dev->priv; - unsigned long ioaddr = dev->base_addr; - u16 status; - int entry; - unsigned long flags; - - if (pcnet32_debug > 3) { - printk(KERN_DEBUG "%s: pcnet32_start_xmit() called, csr0 %4.4x.\n", - dev->name, lp->a.read_csr(ioaddr, 0)); - } - - if (skb_shinfo(skb)->nr_frags != 0) - BUG(); - - spin_lock_irqsave(&lp->lock, flags); - - /* Default status -- will not enable Successful-TxDone - * interrupt when that option is available to us. - */ - status = 0x8300; - if ((lp->ltint) && - ((lp->cur_tx - lp->dirty_tx == TX_RING_SIZE/2) || - (lp->cur_tx - lp->dirty_tx >= TX_RING_SIZE-2))) - { - /* Enable Successful-TxDone interrupt if we have - * 1/2 of, or nearly all of, our ring buffer Tx'd - * but not yet cleaned up. Thus, most of the time, - * we will not enable Successful-TxDone interrupts. - */ - status = 0x9300; - } - - /* Fill in a Tx ring entry */ - - /* Mask to ring buffer boundary. */ - entry = lp->cur_tx & TX_RING_MOD_MASK; - - /* Caution: the write order is important here, set the base address - with the "ownership" bits last. */ - - lp->tx_ring[entry].length = le16_to_cpu(-skb->len); - - lp->tx_ring[entry].misc = 0x00000000; - - lp->tx_skbuff[entry] = skb; - lp->tx_dma_addr[entry] = pci_map_single(lp->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE); - lp->tx_ring[entry].base = (u32)le32_to_cpu(lp->tx_dma_addr[entry]); - lp->tx_ring[entry].status = le16_to_cpu(status); - - lp->cur_tx++; - lp->stats.tx_bytes += skb->len; - - /* Trigger an immediate send poll. */ - lp->a.write_csr (ioaddr, 0, 0x0048); - - dev->trans_start = jiffies; - - if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0) - netif_start_queue(dev); - else { - lp->tx_full = 1; - netif_stop_queue(dev); - } - spin_unlock_irqrestore(&lp->lock, flags); - return 0; -} - -/* The PCNET32 interrupt handler. */ -static void -pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) -{ - struct net_device *dev = dev_id; - struct pcnet32_private *lp; - unsigned long ioaddr; - u16 csr0,rap; - int boguscnt = max_interrupt_work; - int must_restart; - - if (!dev) { - printk (KERN_DEBUG "%s(): irq %d for unknown device\n", - __FUNCTION__, irq); - return; - } - - ioaddr = dev->base_addr; - lp = dev->priv; - - spin_lock(&lp->lock); - - rap = lp->a.read_rap(ioaddr); - while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8600 && --boguscnt >= 0) { - /* Acknowledge all of the current interrupt sources ASAP. */ - lp->a.write_csr (ioaddr, 0, csr0 & ~0x004f); - - must_restart = 0; - - if (pcnet32_debug > 5) - printk(KERN_DEBUG "%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", - dev->name, csr0, lp->a.read_csr (ioaddr, 0)); - - if (csr0 & 0x0400) /* Rx interrupt */ - pcnet32_rx(dev); - - if (csr0 & 0x0200) { /* Tx-done interrupt */ - unsigned int dirty_tx = lp->dirty_tx; - - while (dirty_tx < lp->cur_tx) { - int entry = dirty_tx & TX_RING_MOD_MASK; - int status = (short)le16_to_cpu(lp->tx_ring[entry].status); - - if (status < 0) - break; /* It still hasn't been Txed */ - - lp->tx_ring[entry].base = 0; - - if (status & 0x4000) { - /* There was an major error, log it. */ - int err_status = le32_to_cpu(lp->tx_ring[entry].misc); - lp->stats.tx_errors++; - if (err_status & 0x04000000) lp->stats.tx_aborted_errors++; - if (err_status & 0x08000000) lp->stats.tx_carrier_errors++; - if (err_status & 0x10000000) lp->stats.tx_window_errors++; -#ifndef DO_DXSUFLO - if (err_status & 0x40000000) { - lp->stats.tx_fifo_errors++; - /* Ackk! On FIFO errors the Tx unit is turned off! */ - /* Remove this verbosity later! */ - printk(KERN_ERR "%s: Tx FIFO error! CSR0=%4.4x\n", - dev->name, csr0); - must_restart = 1; - } -#else - if (err_status & 0x40000000) { - lp->stats.tx_fifo_errors++; - if (! lp->dxsuflo) { /* If controller doesn't recover ... */ - /* Ackk! On FIFO errors the Tx unit is turned off! */ - /* Remove this verbosity later! */ - printk(KERN_ERR "%s: Tx FIFO error! CSR0=%4.4x\n", - dev->name, csr0); - must_restart = 1; - } - } -#endif - } else { - if (status & 0x1800) - lp->stats.collisions++; - lp->stats.tx_packets++; - } - - /* We must free the original skb */ - if (lp->tx_skbuff[entry]) { - pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[entry], - lp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(lp->tx_skbuff[entry]); - lp->tx_skbuff[entry] = 0; - lp->tx_dma_addr[entry] = 0; - } - dirty_tx++; - } - - if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) { - printk(KERN_ERR "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n", - dev->name, dirty_tx, lp->cur_tx, lp->tx_full); - dirty_tx += TX_RING_SIZE; - } - - if (lp->tx_full && - netif_queue_stopped(dev) && - dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { - /* The ring is no longer full, clear tbusy. */ - lp->tx_full = 0; - netif_wake_queue (dev); - } - lp->dirty_tx = dirty_tx; - } - - /* Log misc errors. */ - if (csr0 & 0x4000) lp->stats.tx_errors++; /* Tx babble. */ - if (csr0 & 0x1000) { - /* - * this happens when our receive ring is full. This shouldn't - * be a problem as we will see normal rx interrupts for the frames - * in the receive ring. But there are some PCI chipsets (I can reproduce - * this on SP3G with Intel saturn chipset) which have sometimes problems - * and will fill up the receive ring with error descriptors. In this - * situation we don't get a rx interrupt, but a missed frame interrupt sooner - * or later. So we try to clean up our receive ring here. - */ - pcnet32_rx(dev); - lp->stats.rx_errors++; /* Missed a Rx frame. */ - } - if (csr0 & 0x0800) { - printk(KERN_ERR "%s: Bus master arbitration failure, status %4.4x.\n", - dev->name, csr0); - /* unlike for the lance, there is no restart needed */ - } - - if (must_restart) { - /* stop the chip to clear the error condition, then restart */ - lp->a.write_csr (ioaddr, 0, 0x0004); - pcnet32_restart(dev, 0x0002); - } - } - - /* Clear any other interrupt, and set interrupt enable. */ - lp->a.write_csr (ioaddr, 0, 0x7940); - lp->a.write_rap (ioaddr,rap); - - if (pcnet32_debug > 4) - printk(KERN_DEBUG "%s: exiting interrupt, csr0=%#4.4x.\n", - dev->name, lp->a.read_csr (ioaddr, 0)); - - spin_unlock(&lp->lock); -} - -static int -pcnet32_rx(struct net_device *dev) -{ - struct pcnet32_private *lp = dev->priv; - int entry = lp->cur_rx & RX_RING_MOD_MASK; - - /* If we own the next entry, it's a new packet. Send it up. */ - while ((short)le16_to_cpu(lp->rx_ring[entry].status) >= 0) { - int status = (short)le16_to_cpu(lp->rx_ring[entry].status) >> 8; - - if (status != 0x03) { /* There was an error. */ - /* - * There is a tricky error noted by John Murphy, - * to Russ Nelson: Even with full-sized - * buffers it's possible for a jabber packet to use two - * buffers, with only the last correctly noting the error. - */ - if (status & 0x01) /* Only count a general error at the */ - lp->stats.rx_errors++; /* end of a packet.*/ - if (status & 0x20) lp->stats.rx_frame_errors++; - if (status & 0x10) lp->stats.rx_over_errors++; - if (status & 0x08) lp->stats.rx_crc_errors++; - if (status & 0x04) lp->stats.rx_fifo_errors++; - lp->rx_ring[entry].status &= le16_to_cpu(0x03ff); - } else { - /* Malloc up new buffer, compatible with net-2e. */ - short pkt_len = (le32_to_cpu(lp->rx_ring[entry].msg_length) & 0xfff)-4; - struct sk_buff *skb; - - if(pkt_len < 60) { - printk(KERN_ERR "%s: Runt packet!\n",dev->name); - lp->stats.rx_errors++; - } else { - int rx_in_place = 0; - -#ifdef COPYBREAK - if (pkt_len > rx_copybreak) { -#else - { -#endif - struct sk_buff *newskb; - - if ((newskb = dev_alloc_skb (PKT_BUF_SZ))) { - skb_reserve (newskb, 2); - skb = lp->rx_skbuff[entry]; - pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[entry], skb->len, PCI_DMA_FROMDEVICE); - skb_put (skb, pkt_len); - lp->rx_skbuff[entry] = newskb; - newskb->dev = dev; - lp->rx_dma_addr[entry] = - pci_map_single(lp->pci_dev, newskb->tail, - newskb->len, PCI_DMA_FROMDEVICE); - lp->rx_ring[entry].base = le32_to_cpu(lp->rx_dma_addr[entry]); - rx_in_place = 1; - } else - skb = NULL; - } -#ifdef COPYBREAK - else { - skb = dev_alloc_skb(pkt_len+2); - } -#endif - - if (skb == NULL) { - int i; - printk(KERN_ERR "%s: Memory squeeze, deferring packet.\n", dev->name); - for (i = 0; i < RX_RING_SIZE; i++) - if ((short)le16_to_cpu(lp->rx_ring[(entry+i) & RX_RING_MOD_MASK].status) < 0) - break; - - if (i > RX_RING_SIZE -2) { - lp->stats.rx_dropped++; - lp->rx_ring[entry].status |= le16_to_cpu(0x8000); - lp->cur_rx++; - } - break; - } - skb->dev = dev; -#ifdef COPYBREAK - if (!rx_in_place) { - skb_reserve(skb,2); /* 16 byte align */ - skb_put(skb,pkt_len); /* Make room */ - eth_copy_and_sum(skb, - (unsigned char *)(lp->rx_skbuff[entry]->tail), - pkt_len,0); - } -#endif - lp->stats.rx_bytes += skb->len; - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - dev->last_rx = jiffies; - lp->stats.rx_packets++; - } - } - /* - * The docs say that the buffer length isn't touched, but Andrew Boyd - * of QNX reports that some revs of the 79C965 clear it. - */ - lp->rx_ring[entry].buf_length = le16_to_cpu(-PKT_BUF_SZ); - lp->rx_ring[entry].status |= le16_to_cpu(0x8000); - entry = (++lp->cur_rx) & RX_RING_MOD_MASK; - } - - return 0; -} - -static int -pcnet32_close(struct net_device *dev) -{ - unsigned long ioaddr = dev->base_addr; - struct pcnet32_private *lp = dev->priv; - int i; - - netif_stop_queue(dev); - - lp->stats.rx_missed_errors = lp->a.read_csr (ioaddr, 112); - - if (pcnet32_debug > 1) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, lp->a.read_csr (ioaddr, 0)); - - /* We stop the PCNET32 here -- it occasionally polls memory if we don't. */ - lp->a.write_csr (ioaddr, 0, 0x0004); - - /* - * Switch back to 16bit mode to avoid problems with dumb - * DOS packet driver after a warm reboot - */ - lp->a.write_bcr (ioaddr, 20, 4); - - free_irq(dev->irq, dev); - - /* free all allocated skbuffs */ - for (i = 0; i < RX_RING_SIZE; i++) { - lp->rx_ring[i].status = 0; - if (lp->rx_skbuff[i]) { - pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], lp->rx_skbuff[i]->len, PCI_DMA_FROMDEVICE); - dev_kfree_skb(lp->rx_skbuff[i]); - } - lp->rx_skbuff[i] = NULL; - lp->rx_dma_addr[i] = 0; - } - - for (i = 0; i < TX_RING_SIZE; i++) { - if (lp->tx_skbuff[i]) { - pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE); - dev_kfree_skb(lp->tx_skbuff[i]); - } - lp->tx_skbuff[i] = NULL; - lp->tx_dma_addr[i] = 0; - } - - MOD_DEC_USE_COUNT; - - return 0; -} - -static struct net_device_stats * -pcnet32_get_stats(struct net_device *dev) -{ - struct pcnet32_private *lp = dev->priv; - unsigned long ioaddr = dev->base_addr; - u16 saved_addr; - unsigned long flags; - - spin_lock_irqsave(&lp->lock, flags); - saved_addr = lp->a.read_rap(ioaddr); - lp->stats.rx_missed_errors = lp->a.read_csr (ioaddr, 112); - lp->a.write_rap(ioaddr, saved_addr); - spin_unlock_irqrestore(&lp->lock, flags); - - return &lp->stats; -} - -/* taken from the sunlance driver, which it took from the depca driver */ -static void pcnet32_load_multicast (struct net_device *dev) -{ - struct pcnet32_private *lp = dev->priv; - volatile struct pcnet32_init_block *ib = &lp->init_block; - volatile u16 *mcast_table = (u16 *)&ib->filter; - struct dev_mc_list *dmi=dev->mc_list; - char *addrs; - int i; - u32 crc; - - /* set all multicast bits */ - if (dev->flags & IFF_ALLMULTI){ - ib->filter[0] = 0xffffffff; - ib->filter[1] = 0xffffffff; - return; - } - /* clear the multicast filter */ - ib->filter[0] = 0; - ib->filter[1] = 0; - - /* Add addresses */ - for (i = 0; i < dev->mc_count; i++){ - addrs = dmi->dmi_addr; - dmi = dmi->next; - - /* multicast address? */ - if (!(*addrs & 1)) - continue; - - crc = ether_crc_le(6, addrs); - crc = crc >> 26; - mcast_table [crc >> 4] |= cpu_to_le16(1 << (crc & 0xf)); - } - return; -} - - -/* - * Set or clear the multicast filter for this adaptor. - */ -static void pcnet32_set_multicast_list(struct net_device *dev) -{ - unsigned long ioaddr = dev->base_addr, flags; - struct pcnet32_private *lp = dev->priv; - - spin_lock_irqsave(&lp->lock, flags); - if (dev->flags&IFF_PROMISC) { - /* Log any net taps. */ - printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name); - lp->init_block.mode = le16_to_cpu(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) << 7); - } else { - lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); - pcnet32_load_multicast (dev); - } - - lp->a.write_csr (ioaddr, 0, 0x0004); /* Temporarily stop the lance. */ - - pcnet32_restart(dev, 0x0042); /* Resume normal operation */ - spin_unlock_irqrestore(&lp->lock, flags); -} - -static int mdio_read(struct net_device *dev, int phy_id, int reg_num) -{ - struct pcnet32_private *lp = dev->priv; - unsigned long ioaddr = dev->base_addr; - u16 val_out; - int phyaddr; - - if (!lp->mii) - return 0; - - phyaddr = lp->a.read_bcr(ioaddr, 33); - - lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f)); - val_out = lp->a.read_bcr(ioaddr, 34); - lp->a.write_bcr(ioaddr, 33, phyaddr); - - return val_out; -} - -static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val) -{ - struct pcnet32_private *lp = dev->priv; - unsigned long ioaddr = dev->base_addr; - int phyaddr; - - if (!lp->mii) - return; - - phyaddr = lp->a.read_bcr(ioaddr, 33); - - lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f)); - lp->a.write_bcr(ioaddr, 34, val); - lp->a.write_bcr(ioaddr, 33, phyaddr); -} - -#if 0 -static int pcnet32_ethtool_ioctl (struct net_device *dev, void *useraddr) -{ - struct pcnet32_private *lp = dev->priv; - u32 ethcmd; - int phyaddr = 0; - int phy_id = 0; - unsigned long ioaddr = dev->base_addr; - - if (lp->mii) { - phyaddr = lp->a.read_bcr (ioaddr, 33); - phy_id = (phyaddr >> 5) & 0x1f; - lp->mii_if.phy_id = phy_id; - } - - if (copy_from_user (ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy (info.driver, DRV_NAME); - strcpy (info.version, DRV_VERSION); - if (lp->pci_dev) - strcpy (info.bus_info, lp->pci_dev->slot_name); - else - sprintf(info.bus_info, "VLB 0x%lx", dev->base_addr); - if (copy_to_user (useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } - - /* get settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - spin_lock_irq(&lp->lock); - mii_ethtool_gset(&lp->mii_if, &ecmd); - spin_unlock_irq(&lp->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - /* set settings */ - case ETHTOOL_SSET: { - int r; - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - spin_lock_irq(&lp->lock); - r = mii_ethtool_sset(&lp->mii_if, &ecmd); - spin_unlock_irq(&lp->lock); - return r; - } - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - return mii_nway_restart(&lp->mii_if); - } - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - edata.data = mii_link_ok(&lp->mii_if); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - - /* get message-level */ - case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = {ETHTOOL_GMSGLVL}; - edata.data = pcnet32_debug; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - /* set message-level */ - case ETHTOOL_SMSGLVL: { - struct ethtool_value edata; - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - pcnet32_debug = edata.data; - return 0; - } - default: - break; - } - - return -EOPNOTSUPP; -} - -static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - unsigned long ioaddr = dev->base_addr; - struct pcnet32_private *lp = dev->priv; - struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data; - int phyaddr = lp->a.read_bcr (ioaddr, 33); - - if (cmd == SIOCETHTOOL) - return pcnet32_ethtool_ioctl(dev, (void *) rq->ifr_data); - - if (lp->mii) { - switch(cmd) { - case SIOCGMIIPHY: /* Get address of MII PHY in use. */ - data->phy_id = (phyaddr >> 5) & 0x1f; - /* Fall Through */ - case SIOCGMIIREG: /* Read MII PHY register. */ - lp->a.write_bcr (ioaddr, 33, ((data->phy_id & 0x1f) << 5) | (data->reg_num & 0x1f)); - data->val_out = lp->a.read_bcr (ioaddr, 34); - lp->a.write_bcr (ioaddr, 33, phyaddr); - return 0; - case SIOCSMIIREG: /* Write MII PHY register. */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - lp->a.write_bcr (ioaddr, 33, ((data->phy_id & 0x1f) << 5) | (data->reg_num & 0x1f)); - lp->a.write_bcr (ioaddr, 34, data->val_in); - lp->a.write_bcr (ioaddr, 33, phyaddr); - return 0; - default: - return -EOPNOTSUPP; - } - } - return -EOPNOTSUPP; -} -#endif - -static struct pci_driver pcnet32_driver = { - name: DRV_NAME, - probe: pcnet32_probe_pci, - id_table: pcnet32_pci_tbl, -}; - -MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, DRV_NAME " debug level (0-6)"); -MODULE_PARM(max_interrupt_work, "i"); -MODULE_PARM_DESC(max_interrupt_work, DRV_NAME " maximum events handled per interrupt"); -#ifdef COPYBREAK -MODULE_PARM(rx_copybreak, "i"); -MODULE_PARM_DESC(rx_copybreak, DRV_NAME " copy breakpoint for copy-only-tiny-frames"); -#endif -MODULE_PARM(tx_start_pt, "i"); -MODULE_PARM_DESC(tx_start_pt, DRV_NAME " transmit start point (0-3)"); -MODULE_PARM(pcnet32vlb, "i"); -MODULE_PARM_DESC(pcnet32vlb, DRV_NAME " Vesa local bus (VLB) support (0/1)"); -MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM_DESC(options, DRV_NAME " initial option setting(s) (0-15)"); -MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM_DESC(full_duplex, DRV_NAME " full duplex setting(s) (1)"); - -MODULE_AUTHOR("Thomas Bogendoerfer"); -MODULE_DESCRIPTION("Driver for PCnet32 and PCnetPCI based ethercards"); -MODULE_LICENSE("GPL"); - -/* An additional parameter that may be passed in... */ -static int debug = -1; -static int tx_start_pt = -1; - -static int __init pcnet32_init_module(void) -{ - if (debug > 0) - pcnet32_debug = debug; - - if ((tx_start_pt >= 0) && (tx_start_pt <= 3)) - tx_start = tx_start_pt; - - /* find the PCI devices */ - pci_module_init(&pcnet32_driver); - - /* should we find any remaining VLbus devices ? */ - if (pcnet32vlb) - pcnet32_probe_vlbus(); - - if (cards_found) { - printk(KERN_INFO "%s", version); - printk(KERN_INFO PFX "%d cards_found.\n", cards_found); - } - - return cards_found ? 0 : -ENODEV; -} - -static void __exit pcnet32_cleanup_module(void) -{ - struct net_device *next_dev; - - /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ - while (pcnet32_dev) { - struct pcnet32_private *lp = pcnet32_dev->priv; - next_dev = lp->next; - unregister_netdev(pcnet32_dev); - release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE); - if (lp->pci_dev) - pci_unregister_driver(&pcnet32_driver); - pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); - kfree(pcnet32_dev); - pcnet32_dev = next_dev; - } -} - -module_init(pcnet32_init_module); -module_exit(pcnet32_cleanup_module); - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c pcnet32.c" - * c-indent-level: 4 - * tab-width: 8 - * End: - */ diff --git a/xen/drivers/net/setup.c b/xen/drivers/net/setup.c deleted file mode 100644 index 5e3b6b3ac1..0000000000 --- a/xen/drivers/net/setup.c +++ /dev/null @@ -1,173 +0,0 @@ - -/* - * New style setup code for the network devices - */ - -#include -#include -#include -#include -//#include - -extern int slip_init_ctrl_dev(void); -extern int x25_asy_init_ctrl_dev(void); - -extern int dmascc_init(void); - -extern int awc4500_pci_probe(void); -extern int awc4500_isa_probe(void); -extern int awc4500_pnp_probe(void); -extern int awc4500_365_probe(void); -extern int arcnet_init(void); -extern int scc_enet_init(void); -extern int fec_enet_init(void); -extern int dlci_setup(void); -extern int sdla_setup(void); -extern int sdla_c_setup(void); -extern int comx_init(void); -extern int lmc_setup(void); - -extern int madgemc_probe(void); -extern int uml_net_probe(void); - -/* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is string of 9 zeros. */ -#define __PAD6 "\0\0\0\0\0\0\0\0\0" -#define __PAD5 __PAD6 "\0" -#define __PAD4 __PAD5 "\0" -#define __PAD3 __PAD4 "\0" -#define __PAD2 __PAD3 "\0" - - -/* - * Devices in this list must do new style probing. That is they must - * allocate their own device objects and do their own bus scans. - */ - -struct net_probe -{ - int (*probe)(void); - int status; /* non-zero if autoprobe has failed */ -}; - -static struct net_probe pci_probes[] __initdata = { - /* - * Early setup devices - */ - -#if defined(CONFIG_DMASCC) - {dmascc_init, 0}, -#endif -#if defined(CONFIG_DLCI) - {dlci_setup, 0}, -#endif -#if defined(CONFIG_SDLA) - {sdla_c_setup, 0}, -#endif -#if defined(CONFIG_ARCNET) - {arcnet_init, 0}, -#endif -#if defined(CONFIG_SCC_ENET) - {scc_enet_init, 0}, -#endif -#if defined(CONFIG_FEC_ENET) - {fec_enet_init, 0}, -#endif -#if defined(CONFIG_COMX) - {comx_init, 0}, -#endif - -#if defined(CONFIG_LANMEDIA) - {lmc_setup, 0}, -#endif - -/* -* -* Wireless non-HAM -* -*/ -#ifdef CONFIG_AIRONET4500_NONCS - -#ifdef CONFIG_AIRONET4500_PCI - {awc4500_pci_probe,0}, -#endif - -#ifdef CONFIG_AIRONET4500_PNP - {awc4500_pnp_probe,0}, -#endif - -#endif - -/* - * Token Ring Drivers - */ -#ifdef CONFIG_MADGEMC - {madgemc_probe, 0}, -#endif -#ifdef CONFIG_UML_NET - {uml_net_probe, 0}, -#endif - - {NULL, 0}, -}; - - -/* - * Run the updated device probes. These do not need a device passed - * into them. - */ - -static void __init network_probe(void) -{ - struct net_probe *p = pci_probes; - - while (p->probe != NULL) - { - p->status = p->probe(); - p++; - } -} - - -/* - * Initialise the line discipline drivers - */ - -static void __init network_ldisc_init(void) -{ -#if defined(CONFIG_SLIP) - slip_init_ctrl_dev(); -#endif -#if defined(CONFIG_X25_ASY) - x25_asy_init_ctrl_dev(); -#endif -} - - -static void __init special_device_init(void) -{ -#ifdef CONFIG_NET_SB1000 - { - extern int sb1000_probe(struct net_device *dev); - static struct net_device sb1000_dev = - { - "cm0" __PAD3, 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, sb1000_probe - }; - register_netdev(&sb1000_dev); - } -#endif -} - -/* - * Initialise network devices - */ - -void __init net_device_init(void) -{ - /* Devices supporting the new probing API */ - network_probe(); - /* Line disciplines */ - network_ldisc_init(); - /* Special devices */ - special_device_init(); - /* That kicks off the legacy init functions */ -} diff --git a/xen/drivers/net/tg3.c b/xen/drivers/net/tg3.c deleted file mode 100644 index 7a4d78a939..0000000000 --- a/xen/drivers/net/tg3.c +++ /dev/null @@ -1,7934 +0,0 @@ -/* - * tg3.c: Broadcom Tigon3 ethernet driver. - * - * Copyright (C) 2001, 2002, 2003 David S. Miller (davem@redhat.com) - * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com) - */ - -#include - -#include - -#include -#include -#include // Xen -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -//#include - -//#include - -#include -#include -#include -#include - -#ifdef CONFIG_SPARC64 -#include -#include -#include -#endif - -#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) -#define TG3_VLAN_TAG_USED 1 -#else -#define TG3_VLAN_TAG_USED 0 -#endif - -#ifdef NETIF_F_TSO -#define TG3_TSO_SUPPORT 1 -#else -#define TG3_TSO_SUPPORT 0 -#endif - -#include "tg3.h" - -#define DRV_MODULE_NAME "tg3" -#define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "2.3" -#define DRV_MODULE_RELDATE "November 5, 2003" - -#define TG3_DEF_MAC_MODE 0 -#define TG3_DEF_RX_MODE 0 -#define TG3_DEF_TX_MODE 0 -#define TG3_DEF_MSG_ENABLE \ - (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK | \ - NETIF_MSG_TIMER | \ - NETIF_MSG_IFDOWN | \ - NETIF_MSG_IFUP | \ - NETIF_MSG_RX_ERR | \ - NETIF_MSG_TX_ERR) - -/* length of time before we decide the hardware is borked, - * and dev->tx_timeout() should be called to fix the problem - */ -#define TG3_TX_TIMEOUT (5 * HZ) - -/* hardware minimum and maximum for a single frame's data payload */ -#define TG3_MIN_MTU 60 -#define TG3_MAX_MTU(tp) \ - (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 ? 9000 : 1500) - -/* These numbers seem to be hard coded in the NIC firmware somehow. - * You can't change the ring sizes, but you can change where you place - * them in the NIC onboard memory. - */ -#define TG3_RX_RING_SIZE 512 -#define TG3_DEF_RX_RING_PENDING 200 -#define TG3_RX_JUMBO_RING_SIZE 256 -#define TG3_DEF_RX_JUMBO_RING_PENDING 100 - -/* Do not place this n-ring entries value into the tp struct itself, - * we really want to expose these constants to GCC so that modulo et - * al. operations are done with shifts and masks instead of with - * hw multiply/modulo instructions. Another solution would be to - * replace things like '% foo' with '& (foo - 1)'. - */ -#define TG3_RX_RCB_RING_SIZE(tp) \ - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ? \ - 512 : 1024) - -#define TG3_TX_RING_SIZE 512 -#define TG3_DEF_TX_RING_PENDING (TG3_TX_RING_SIZE - 1) - -#define TG3_RX_RING_BYTES (sizeof(struct tg3_rx_buffer_desc) * \ - TG3_RX_RING_SIZE) -#define TG3_RX_JUMBO_RING_BYTES (sizeof(struct tg3_rx_buffer_desc) * \ - TG3_RX_JUMBO_RING_SIZE) -#define TG3_RX_RCB_RING_BYTES(tp) (sizeof(struct tg3_rx_buffer_desc) * \ - TG3_RX_RCB_RING_SIZE(tp)) -#define TG3_TX_RING_BYTES (sizeof(struct tg3_tx_buffer_desc) * \ - TG3_TX_RING_SIZE) -#define TX_RING_GAP(TP) \ - (TG3_TX_RING_SIZE - (TP)->tx_pending) -#define TX_BUFFS_AVAIL(TP) \ - (((TP)->tx_cons <= (TP)->tx_prod) ? \ - (TP)->tx_cons + (TP)->tx_pending - (TP)->tx_prod : \ - (TP)->tx_cons - (TP)->tx_prod - TX_RING_GAP(TP)) -#define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1)) - -#define RX_PKT_BUF_SZ (1536 + tp->rx_offset + 64) -#define RX_JUMBO_PKT_BUF_SZ (9046 + tp->rx_offset + 64) - -/* minimum number of free TX descriptors required to wake up TX process */ -#define TG3_TX_WAKEUP_THRESH (TG3_TX_RING_SIZE / 4) - -static char version[] __devinitdata = - DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; - -MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox.com)"); -MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_PARM(tg3_debug, "i"); -MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value"); - -static int tg3_debug = -1; /* -1 == use TG3_DEF_MSG_ENABLE as value */ - -static struct pci_device_id tg3_pci_tbl[] = { - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702FE, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705_2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M_2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702X, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703X, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702A3, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703A3, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1001, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1003, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, tg3_pci_tbl); - -static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) -{ - if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) { - unsigned long flags; - - spin_lock_irqsave(&tp->indirect_lock, flags); - pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off); - pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val); - spin_unlock_irqrestore(&tp->indirect_lock, flags); - } else { - writel(val, tp->regs + off); - if ((tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG) != 0) - readl(tp->regs + off); - } -} - -#define tw32(reg,val) tg3_write_indirect_reg32(tp,(reg),(val)) -#define tw32_mailbox(reg, val) writel(((val) & 0xffffffff), tp->regs + (reg)) -#define tw16(reg,val) writew(((val) & 0xffff), tp->regs + (reg)) -#define tw8(reg,val) writeb(((val) & 0xff), tp->regs + (reg)) -#define tr32(reg) readl(tp->regs + (reg)) -#define tr16(reg) readw(tp->regs + (reg)) -#define tr8(reg) readb(tp->regs + (reg)) - -static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) -{ - unsigned long flags; - - spin_lock_irqsave(&tp->indirect_lock, flags); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); - - /* Always leave this as zero. */ - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); - spin_unlock_irqrestore(&tp->indirect_lock, flags); -} - -static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) -{ - unsigned long flags; - - spin_lock_irqsave(&tp->indirect_lock, flags); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); - pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); - - /* Always leave this as zero. */ - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); - spin_unlock_irqrestore(&tp->indirect_lock, flags); -} - -static void tg3_disable_ints(struct tg3 *tp) -{ - tw32(TG3PCI_MISC_HOST_CTRL, - (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT)); - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); - tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); -} - -static inline void tg3_cond_int(struct tg3 *tp) -{ - if (tp->hw_status->status & SD_STATUS_UPDATED) - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT); -} - -static void tg3_enable_ints(struct tg3 *tp) -{ - tw32(TG3PCI_MISC_HOST_CTRL, - (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT)); - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000); - tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); - - tg3_cond_int(tp); -} - -static inline void netif_tx_disable(struct net_device *dev) -{ - spin_lock_bh(&dev->xmit_lock); - netif_stop_queue(dev); - spin_unlock_bh(&dev->xmit_lock); -} - -static inline void tg3_netif_stop(struct tg3 *tp) -{ -#ifdef NAPI - netif_poll_disable(tp->dev); -#endif - netif_tx_disable(tp->dev); -} - -static inline void tg3_netif_start(struct tg3 *tp) -{ - netif_wake_queue(tp->dev); - /* NOTE: unconditional netif_wake_queue is only appropriate - * so long as all callers are assured to have free tx slots - * (such as after tg3_init_hw) - */ -#ifdef NAPI - netif_poll_enable(tp->dev); -#endif - tg3_cond_int(tp); -} - -static void tg3_switch_clocks(struct tg3 *tp) -{ - u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL); - u32 orig_clock_ctrl; - - orig_clock_ctrl = clock_ctrl; - clock_ctrl &= (CLOCK_CTRL_FORCE_CLKRUN | - CLOCK_CTRL_CLKRUN_OENABLE | - 0x1f); - tp->pci_clock_ctrl = clock_ctrl; - - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && - (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) { - tw32(TG3PCI_CLOCK_CTRL, - clock_ctrl | - (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK)); - tr32(TG3PCI_CLOCK_CTRL); - udelay(40); - tw32(TG3PCI_CLOCK_CTRL, - clock_ctrl | (CLOCK_CTRL_ALTCLK)); - tr32(TG3PCI_CLOCK_CTRL); - udelay(40); - } - tw32(TG3PCI_CLOCK_CTRL, clock_ctrl); - tr32(TG3PCI_CLOCK_CTRL); - udelay(40); -} - -#define PHY_BUSY_LOOPS 5000 - -static int tg3_readphy(struct tg3 *tp, int reg, u32 *val) -{ - u32 frame_val; - int loops, ret; - - if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { - tw32(MAC_MI_MODE, - (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL)); - tr32(MAC_MI_MODE); - udelay(40); - } - - *val = 0xffffffff; - - frame_val = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) & - MI_COM_PHY_ADDR_MASK); - frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) & - MI_COM_REG_ADDR_MASK); - frame_val |= (MI_COM_CMD_READ | MI_COM_START); - - tw32(MAC_MI_COM, frame_val); - tr32(MAC_MI_COM); - - loops = PHY_BUSY_LOOPS; - while (loops-- > 0) { - udelay(10); - frame_val = tr32(MAC_MI_COM); - - if ((frame_val & MI_COM_BUSY) == 0) { - udelay(5); - frame_val = tr32(MAC_MI_COM); - break; - } - } - - ret = -EBUSY; - if (loops > 0) { - *val = frame_val & MI_COM_DATA_MASK; - ret = 0; - } - - if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { - tw32(MAC_MI_MODE, tp->mi_mode); - tr32(MAC_MI_MODE); - udelay(40); - } - - return ret; -} - -static int tg3_writephy(struct tg3 *tp, int reg, u32 val) -{ - u32 frame_val; - int loops, ret; - - if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { - tw32(MAC_MI_MODE, - (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL)); - tr32(MAC_MI_MODE); - udelay(40); - } - - frame_val = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) & - MI_COM_PHY_ADDR_MASK); - frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) & - MI_COM_REG_ADDR_MASK); - frame_val |= (val & MI_COM_DATA_MASK); - frame_val |= (MI_COM_CMD_WRITE | MI_COM_START); - - tw32(MAC_MI_COM, frame_val); - tr32(MAC_MI_COM); - - loops = PHY_BUSY_LOOPS; - while (loops-- > 0) { - udelay(10); - frame_val = tr32(MAC_MI_COM); - if ((frame_val & MI_COM_BUSY) == 0) { - udelay(5); - frame_val = tr32(MAC_MI_COM); - break; - } - } - - ret = -EBUSY; - if (loops > 0) - ret = 0; - - if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { - tw32(MAC_MI_MODE, tp->mi_mode); - tr32(MAC_MI_MODE); - udelay(40); - } - - return ret; -} - -static void tg3_phy_set_wirespeed(struct tg3 *tp) -{ - u32 val; - - if (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) - return; - - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007); - tg3_readphy(tp, MII_TG3_AUX_CTRL, &val); - tg3_writephy(tp, MII_TG3_AUX_CTRL, (val | (1 << 15) | (1 << 4))); -} - -static int tg3_bmcr_reset(struct tg3 *tp) -{ - u32 phy_control; - int limit, err; - - /* OK, reset it, and poll the BMCR_RESET bit until it - * clears or we time out. - */ - phy_control = BMCR_RESET; - err = tg3_writephy(tp, MII_BMCR, phy_control); - if (err != 0) - return -EBUSY; - - limit = 5000; - while (limit--) { - err = tg3_readphy(tp, MII_BMCR, &phy_control); - if (err != 0) - return -EBUSY; - - if ((phy_control & BMCR_RESET) == 0) { - udelay(40); - break; - } - udelay(10); - } - if (limit <= 0) - return -EBUSY; - - return 0; -} - -static int tg3_wait_macro_done(struct tg3 *tp) -{ - int limit = 100; - - while (limit--) { - u32 tmp32; - - tg3_readphy(tp, 0x16, &tmp32); - if ((tmp32 & 0x1000) == 0) - break; - } - if (limit <= 0) - return -EBUSY; - - return 0; -} - -static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp) -{ - static const u32 test_pat[4][6] = { - { 0x00005555, 0x00000005, 0x00002aaa, 0x0000000a, 0x00003456, 0x00000003 }, - { 0x00002aaa, 0x0000000a, 0x00003333, 0x00000003, 0x0000789a, 0x00000005 }, - { 0x00005a5a, 0x00000005, 0x00002a6a, 0x0000000a, 0x00001bcd, 0x00000003 }, - { 0x00002a5a, 0x0000000a, 0x000033c3, 0x00000003, 0x00002ef1, 0x00000005 } - }; - int chan; - - for (chan = 0; chan < 4; chan++) { - int i; - - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, - (chan * 0x2000) | 0x0200); - tg3_writephy(tp, 0x16, 0x0002); - - for (i = 0; i < 6; i++) - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, - test_pat[chan][i]); - - tg3_writephy(tp, 0x16, 0x0202); - if (tg3_wait_macro_done(tp)) { - *resetp = 1; - return -EBUSY; - } - - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, - (chan * 0x2000) | 0x0200); - tg3_writephy(tp, 0x16, 0x0082); - if (tg3_wait_macro_done(tp)) { - *resetp = 1; - return -EBUSY; - } - - tg3_writephy(tp, 0x16, 0x0802); - if (tg3_wait_macro_done(tp)) { - *resetp = 1; - return -EBUSY; - } - - for (i = 0; i < 6; i += 2) { - u32 low, high; - - tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low); - tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high); - if (tg3_wait_macro_done(tp)) { - *resetp = 1; - return -EBUSY; - } - low &= 0x7fff; - high &= 0x000f; - if (low != test_pat[chan][i] || - high != test_pat[chan][i+1]) { - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000b); - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4001); - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4005); - - return -EBUSY; - } - } - } - - return 0; -} - -static int tg3_phy_reset_chanpat(struct tg3 *tp) -{ - int chan; - - for (chan = 0; chan < 4; chan++) { - int i; - - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, - (chan * 0x2000) | 0x0200); - tg3_writephy(tp, 0x16, 0x0002); - for (i = 0; i < 6; i++) - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000); - tg3_writephy(tp, 0x16, 0x0202); - if (tg3_wait_macro_done(tp)) - return -EBUSY; - } - - return 0; -} - -static int tg3_phy_reset_5703_4_5(struct tg3 *tp) -{ - u32 reg32, phy9_orig; - int retries, do_phy_reset, err; - - retries = 10; - do_phy_reset = 1; - do { - if (do_phy_reset) { - err = tg3_bmcr_reset(tp); - if (err) - return err; - do_phy_reset = 0; - } - - /* Disable transmitter and interrupt. */ - tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32); - reg32 |= 0x3000; - tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); - - /* Set full-duplex, 1000 mbps. */ - tg3_writephy(tp, MII_BMCR, - BMCR_FULLDPLX | TG3_BMCR_SPEED1000); - - /* Set to master mode. */ - tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig); - tg3_writephy(tp, MII_TG3_CTRL, - (MII_TG3_CTRL_AS_MASTER | - MII_TG3_CTRL_ENABLE_AS_MASTER)); - - /* Enable SM_DSP_CLOCK and 6dB. */ - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); - - /* Block the PHY control access. */ - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005); - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0800); - - err = tg3_phy_write_and_check_testpat(tp, &do_phy_reset); - if (!err) - break; - } while (--retries); - - err = tg3_phy_reset_chanpat(tp); - if (err) - return err; - - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005); - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0000); - - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200); - tg3_writephy(tp, 0x16, 0x0000); - - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); - - tg3_writephy(tp, MII_TG3_CTRL, phy9_orig); - - tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32); - reg32 &= ~0x3000; - tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); - - return err; -} - -/* This will reset the tigon3 PHY if there is no valid - * link unless the FORCE argument is non-zero. - */ -static int tg3_phy_reset(struct tg3 *tp, int force) -{ - u32 phy_status; - int err; - - err = tg3_readphy(tp, MII_BMSR, &phy_status); - err |= tg3_readphy(tp, MII_BMSR, &phy_status); - if (err != 0) - return -EBUSY; - - /* If we have link, and not forcing a reset, then nothing - * to do. - */ - if ((phy_status & BMSR_LSTATUS) != 0 && (force == 0)) - return 0; - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { - err = tg3_phy_reset_5703_4_5(tp); - if (err) - return err; - goto out; - } - - err = tg3_bmcr_reset(tp); - if (err) - return err; - -out: - tg3_phy_set_wirespeed(tp); - return 0; -} - -static void tg3_frob_aux_power(struct tg3 *tp) -{ - struct tg3 *tp_peer = tp; - - if ((tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) != 0) - return; - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { - tp_peer = pci_get_drvdata(tp->pdev_peer); - if (!tp_peer) - BUG(); - } - - - if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 || - (tp_peer->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - (GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT0 | - GRC_LCLCTRL_GPIO_OUTPUT1)); - tr32(GRC_LOCAL_CTRL); - udelay(100); - } else { - if (tp_peer != tp && - (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0) - return; - - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - (GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT1 | - GRC_LCLCTRL_GPIO_OUTPUT2)); - tr32(GRC_LOCAL_CTRL); - udelay(100); - - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - (GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT0 | - GRC_LCLCTRL_GPIO_OUTPUT1 | - GRC_LCLCTRL_GPIO_OUTPUT2)); - tr32(GRC_LOCAL_CTRL); - udelay(100); - - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - (GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT0 | - GRC_LCLCTRL_GPIO_OUTPUT1)); - tr32(GRC_LOCAL_CTRL); - udelay(100); - } - } else { - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) { - if (tp_peer != tp && - (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0) - return; - - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - (GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OUTPUT1)); - tr32(GRC_LOCAL_CTRL); - udelay(100); - - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - (GRC_LCLCTRL_GPIO_OE1)); - tr32(GRC_LOCAL_CTRL); - udelay(100); - - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - (GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OUTPUT1)); - tr32(GRC_LOCAL_CTRL); - udelay(100); - } - } -} - -static int tg3_setup_phy(struct tg3 *); - -static int tg3_set_power_state(struct tg3 *tp, int state) -{ - u32 misc_host_ctrl; - u16 power_control, power_caps; - int pm = tp->pm_cap; - - /* Make sure register accesses (indirect or otherwise) - * will function correctly. - */ - pci_write_config_dword(tp->pdev, - TG3PCI_MISC_HOST_CTRL, - tp->misc_host_ctrl); - - pci_read_config_word(tp->pdev, - pm + PCI_PM_CTRL, - &power_control); - power_control |= PCI_PM_CTRL_PME_STATUS; - power_control &= ~(PCI_PM_CTRL_STATE_MASK); - switch (state) { - case 0: - power_control |= 0; - pci_write_config_word(tp->pdev, - pm + PCI_PM_CTRL, - power_control); - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl); - tr32(GRC_LOCAL_CTRL); - udelay(100); - - return 0; - - case 1: - power_control |= 1; - break; - - case 2: - power_control |= 2; - break; - - case 3: - power_control |= 3; - break; - - default: - printk(KERN_WARNING PFX "%s: Invalid power state (%d) " - "requested.\n", - tp->dev->name, state); - return -EINVAL; - }; - - power_control |= PCI_PM_CTRL_PME_ENABLE; - - misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL); - tw32(TG3PCI_MISC_HOST_CTRL, - misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT); - - if (tp->link_config.phy_is_low_power == 0) { - tp->link_config.phy_is_low_power = 1; - tp->link_config.orig_speed = tp->link_config.speed; - tp->link_config.orig_duplex = tp->link_config.duplex; - tp->link_config.orig_autoneg = tp->link_config.autoneg; - } - - if (tp->phy_id != PHY_ID_SERDES) { - tp->link_config.speed = SPEED_10; - tp->link_config.duplex = DUPLEX_HALF; - tp->link_config.autoneg = AUTONEG_ENABLE; - tg3_setup_phy(tp); - } - - pci_read_config_word(tp->pdev, pm + PCI_PM_PMC, &power_caps); - - if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) { - u32 mac_mode; - - if (tp->phy_id != PHY_ID_SERDES) { - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a); - udelay(40); - - mac_mode = MAC_MODE_PORT_MODE_MII; - - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 || - !(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB)) - mac_mode |= MAC_MODE_LINK_POLARITY; - } else { - mac_mode = MAC_MODE_PORT_MODE_TBI; - } - - - if (((power_caps & PCI_PM_CAP_PME_D3cold) && - (tp->tg3_flags & TG3_FLAG_WOL_ENABLE))) - mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE; - - tw32(MAC_MODE, mac_mode); - tr32(MAC_MODE); - udelay(100); - - tw32(MAC_RX_MODE, RX_MODE_ENABLE); - tr32(MAC_RX_MODE); - udelay(10); - } - - if (!(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB) && - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) { - u32 base_val; - - base_val = tp->pci_clock_ctrl; - base_val |= (CLOCK_CTRL_RXCLK_DISABLE | - CLOCK_CTRL_TXCLK_DISABLE); - - tw32(TG3PCI_CLOCK_CTRL, base_val | - CLOCK_CTRL_ALTCLK | - CLOCK_CTRL_PWRDOWN_PLL133); - tr32(TG3PCI_CLOCK_CTRL); - udelay(40); - } else { - u32 newbits1, newbits2; - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { - newbits1 = (CLOCK_CTRL_RXCLK_DISABLE | - CLOCK_CTRL_TXCLK_DISABLE | - CLOCK_CTRL_ALTCLK); - newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE; - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { - newbits1 = CLOCK_CTRL_625_CORE; - newbits2 = newbits1 | CLOCK_CTRL_ALTCLK; - } else { - newbits1 = CLOCK_CTRL_ALTCLK; - newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE; - } - - tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1); - tr32(TG3PCI_CLOCK_CTRL); - udelay(40); - - tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2); - tr32(TG3PCI_CLOCK_CTRL); - udelay(40); - - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { - u32 newbits3; - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { - newbits3 = (CLOCK_CTRL_RXCLK_DISABLE | - CLOCK_CTRL_TXCLK_DISABLE | - CLOCK_CTRL_44MHZ_CORE); - } else { - newbits3 = CLOCK_CTRL_44MHZ_CORE; - } - - tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits3); - tr32(TG3PCI_CLOCK_CTRL); - udelay(40); - } - } - - tg3_frob_aux_power(tp); - - /* Finally, set the new power state. */ - pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control); - - return 0; -} - -static void tg3_link_report(struct tg3 *tp) -{ - if (!netif_carrier_ok(tp->dev)) { - printk(KERN_INFO PFX "%s: Link is down.\n", tp->dev->name); - } else { - printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n", - tp->dev->name, - (tp->link_config.active_speed == SPEED_1000 ? - 1000 : - (tp->link_config.active_speed == SPEED_100 ? - 100 : 10)), - (tp->link_config.active_duplex == DUPLEX_FULL ? - "full" : "half")); - - printk(KERN_INFO PFX "%s: Flow control is %s for TX and " - "%s for RX.\n", - tp->dev->name, - (tp->tg3_flags & TG3_FLAG_TX_PAUSE) ? "on" : "off", - (tp->tg3_flags & TG3_FLAG_RX_PAUSE) ? "on" : "off"); - } -} - -static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv) -{ - u32 new_tg3_flags = 0; - - if (local_adv & ADVERTISE_PAUSE_CAP) { - if (local_adv & ADVERTISE_PAUSE_ASYM) { - if (remote_adv & LPA_PAUSE_CAP) - new_tg3_flags |= - (TG3_FLAG_RX_PAUSE | - TG3_FLAG_TX_PAUSE); - else if (remote_adv & LPA_PAUSE_ASYM) - new_tg3_flags |= - (TG3_FLAG_RX_PAUSE); - } else { - if (remote_adv & LPA_PAUSE_CAP) - new_tg3_flags |= - (TG3_FLAG_RX_PAUSE | - TG3_FLAG_TX_PAUSE); - } - } else if (local_adv & ADVERTISE_PAUSE_ASYM) { - if ((remote_adv & LPA_PAUSE_CAP) && - (remote_adv & LPA_PAUSE_ASYM)) - new_tg3_flags |= TG3_FLAG_TX_PAUSE; - } - - tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE); - tp->tg3_flags |= new_tg3_flags; - - if (new_tg3_flags & TG3_FLAG_RX_PAUSE) - tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE; - else - tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE; - - if (new_tg3_flags & TG3_FLAG_TX_PAUSE) - tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE; - else - tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE; -} - -static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex) -{ - switch (val & MII_TG3_AUX_STAT_SPDMASK) { - case MII_TG3_AUX_STAT_10HALF: - *speed = SPEED_10; - *duplex = DUPLEX_HALF; - break; - - case MII_TG3_AUX_STAT_10FULL: - *speed = SPEED_10; - *duplex = DUPLEX_FULL; - break; - - case MII_TG3_AUX_STAT_100HALF: - *speed = SPEED_100; - *duplex = DUPLEX_HALF; - break; - - case MII_TG3_AUX_STAT_100FULL: - *speed = SPEED_100; - *duplex = DUPLEX_FULL; - break; - - case MII_TG3_AUX_STAT_1000HALF: - *speed = SPEED_1000; - *duplex = DUPLEX_HALF; - break; - - case MII_TG3_AUX_STAT_1000FULL: - *speed = SPEED_1000; - *duplex = DUPLEX_FULL; - break; - - default: - *speed = SPEED_INVALID; - *duplex = DUPLEX_INVALID; - break; - }; -} - -static int tg3_phy_copper_begin(struct tg3 *tp, int wait_for_link) -{ - u32 new_adv; - int i; - - if (tp->link_config.phy_is_low_power) { - /* Entering low power mode. Disable gigabit and - * 100baseT advertisements. - */ - tg3_writephy(tp, MII_TG3_CTRL, 0); - - new_adv = (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); - if (tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB) - new_adv |= (ADVERTISE_100HALF | ADVERTISE_100FULL); - - tg3_writephy(tp, MII_ADVERTISE, new_adv); - } else if (tp->link_config.speed == SPEED_INVALID) { - tp->link_config.advertising = - (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | - ADVERTISED_Autoneg | ADVERTISED_MII); - - if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) - tp->link_config.advertising &= - ~(ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full); - - new_adv = (ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); - if (tp->link_config.advertising & ADVERTISED_10baseT_Half) - new_adv |= ADVERTISE_10HALF; - if (tp->link_config.advertising & ADVERTISED_10baseT_Full) - new_adv |= ADVERTISE_10FULL; - if (tp->link_config.advertising & ADVERTISED_100baseT_Half) - new_adv |= ADVERTISE_100HALF; - if (tp->link_config.advertising & ADVERTISED_100baseT_Full) - new_adv |= ADVERTISE_100FULL; - tg3_writephy(tp, MII_ADVERTISE, new_adv); - - if (tp->link_config.advertising & - (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full)) { - new_adv = 0; - if (tp->link_config.advertising & ADVERTISED_1000baseT_Half) - new_adv |= MII_TG3_CTRL_ADV_1000_HALF; - if (tp->link_config.advertising & ADVERTISED_1000baseT_Full) - new_adv |= MII_TG3_CTRL_ADV_1000_FULL; - if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY) && - (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)) - new_adv |= (MII_TG3_CTRL_AS_MASTER | - MII_TG3_CTRL_ENABLE_AS_MASTER); - tg3_writephy(tp, MII_TG3_CTRL, new_adv); - } else { - tg3_writephy(tp, MII_TG3_CTRL, 0); - } - } else { - /* Asking for a specific link mode. */ - if (tp->link_config.speed == SPEED_1000) { - new_adv = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP; - tg3_writephy(tp, MII_ADVERTISE, new_adv); - - if (tp->link_config.duplex == DUPLEX_FULL) - new_adv = MII_TG3_CTRL_ADV_1000_FULL; - else - new_adv = MII_TG3_CTRL_ADV_1000_HALF; - if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) - new_adv |= (MII_TG3_CTRL_AS_MASTER | - MII_TG3_CTRL_ENABLE_AS_MASTER); - tg3_writephy(tp, MII_TG3_CTRL, new_adv); - } else { - tg3_writephy(tp, MII_TG3_CTRL, 0); - - new_adv = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP; - if (tp->link_config.speed == SPEED_100) { - if (tp->link_config.duplex == DUPLEX_FULL) - new_adv |= ADVERTISE_100FULL; - else - new_adv |= ADVERTISE_100HALF; - } else { - if (tp->link_config.duplex == DUPLEX_FULL) - new_adv |= ADVERTISE_10FULL; - else - new_adv |= ADVERTISE_10HALF; - } - tg3_writephy(tp, MII_ADVERTISE, new_adv); - } - } - - if (tp->link_config.autoneg == AUTONEG_DISABLE && - tp->link_config.speed != SPEED_INVALID) { - u32 bmcr, orig_bmcr; - - tp->link_config.active_speed = tp->link_config.speed; - tp->link_config.active_duplex = tp->link_config.duplex; - - bmcr = 0; - switch (tp->link_config.speed) { - default: - case SPEED_10: - break; - - case SPEED_100: - bmcr |= BMCR_SPEED100; - break; - - case SPEED_1000: - bmcr |= TG3_BMCR_SPEED1000; - break; - }; - - if (tp->link_config.duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - - tg3_readphy(tp, MII_BMCR, &orig_bmcr); - if (bmcr != orig_bmcr) { - tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK); - for (i = 0; i < 15000; i++) { - u32 tmp; - - udelay(10); - tg3_readphy(tp, MII_BMSR, &tmp); - tg3_readphy(tp, MII_BMSR, &tmp); - if (!(tmp & BMSR_LSTATUS)) { - udelay(40); - break; - } - } - tg3_writephy(tp, MII_BMCR, bmcr); - udelay(40); - } - } else { - tg3_writephy(tp, MII_BMCR, - BMCR_ANENABLE | BMCR_ANRESTART); - } - - if (wait_for_link) { - tp->link_config.active_speed = SPEED_INVALID; - tp->link_config.active_duplex = DUPLEX_INVALID; - for (i = 0; i < 300000; i++) { - u32 tmp; - - udelay(10); - tg3_readphy(tp, MII_BMSR, &tmp); - tg3_readphy(tp, MII_BMSR, &tmp); - if (!(tmp & BMSR_LSTATUS)) - continue; - - tg3_readphy(tp, MII_TG3_AUX_STAT, &tmp); - tg3_aux_stat_to_speed_duplex(tp, tmp, - &tp->link_config.active_speed, - &tp->link_config.active_duplex); - } - if (tp->link_config.active_speed == SPEED_INVALID) - return -EINVAL; - } - - return 0; -} - -static int tg3_init_5401phy_dsp(struct tg3 *tp) -{ - int err; - - /* Turn off tap power management. */ - err = tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c20); - - err |= tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x0012); - err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x1804); - - err |= tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x0013); - err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x1204); - - err |= tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8006); - err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0132); - - err |= tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8006); - err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0232); - - err |= tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f); - err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0a20); - - udelay(40); - - return err; -} - -static int tg3_setup_copper_phy(struct tg3 *tp) -{ - int current_link_up; - u32 bmsr, dummy; - u16 current_speed; - u8 current_duplex; - int i, err; - - tw32(MAC_STATUS, - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)); - tr32(MAC_STATUS); - udelay(40); - - tp->mi_mode = MAC_MI_MODE_BASE; - tw32(MAC_MI_MODE, tp->mi_mode); - tr32(MAC_MI_MODE); - udelay(40); - - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x02); - - /* Some third-party PHYs need to be reset on link going - * down. - */ - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || - tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) && - netif_carrier_ok(tp->dev)) { - tg3_readphy(tp, MII_BMSR, &bmsr); - tg3_readphy(tp, MII_BMSR, &bmsr); - if (!(bmsr & BMSR_LSTATUS)) - tg3_phy_reset(tp, 1); - } - - if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { - tg3_readphy(tp, MII_BMSR, &bmsr); - tg3_readphy(tp, MII_BMSR, &bmsr); - - if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) - bmsr = 0; - - if (!(bmsr & BMSR_LSTATUS)) { - err = tg3_init_5401phy_dsp(tp); - if (err) - return err; - - tg3_readphy(tp, MII_BMSR, &bmsr); - for (i = 0; i < 1000; i++) { - udelay(10); - tg3_readphy(tp, MII_BMSR, &bmsr); - if (bmsr & BMSR_LSTATUS) { - udelay(40); - break; - } - } - - if ((tp->phy_id & PHY_ID_REV_MASK) == PHY_REV_BCM5401_B0 && - !(bmsr & BMSR_LSTATUS) && - tp->link_config.active_speed == SPEED_1000) { - err = tg3_phy_reset(tp, 1); - if (!err) - err = tg3_init_5401phy_dsp(tp); - if (err) - return err; - } - } - } else if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) { - /* 5701 {A0,B0} CRC bug workaround */ - tg3_writephy(tp, 0x15, 0x0a75); - tg3_writephy(tp, 0x1c, 0x8c68); - tg3_writephy(tp, 0x1c, 0x8d68); - tg3_writephy(tp, 0x1c, 0x8c68); - } - - /* Clear pending interrupts... */ - tg3_readphy(tp, MII_TG3_ISTAT, &dummy); - tg3_readphy(tp, MII_TG3_ISTAT, &dummy); - - if (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) - tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG); - else - tg3_writephy(tp, MII_TG3_IMASK, ~0); - - if (tp->led_mode == led_mode_three_link) - tg3_writephy(tp, MII_TG3_EXT_CTRL, - MII_TG3_EXT_CTRL_LNK3_LED_MODE); - else - tg3_writephy(tp, MII_TG3_EXT_CTRL, 0); - - current_link_up = 0; - current_speed = SPEED_INVALID; - current_duplex = DUPLEX_INVALID; - - tg3_readphy(tp, MII_BMSR, &bmsr); - tg3_readphy(tp, MII_BMSR, &bmsr); - - if (bmsr & BMSR_LSTATUS) { - u32 aux_stat, bmcr; - - tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat); - for (i = 0; i < 2000; i++) { - udelay(10); - tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat); - if (aux_stat) - break; - } - - tg3_aux_stat_to_speed_duplex(tp, aux_stat, - ¤t_speed, - ¤t_duplex); - tg3_readphy(tp, MII_BMCR, &bmcr); - tg3_readphy(tp, MII_BMCR, &bmcr); - if (tp->link_config.autoneg == AUTONEG_ENABLE) { - if (bmcr & BMCR_ANENABLE) { - u32 gig_ctrl; - - current_link_up = 1; - - /* Force autoneg restart if we are exiting - * low power mode. - */ - tg3_readphy(tp, MII_TG3_CTRL, &gig_ctrl); - if (!(gig_ctrl & (MII_TG3_CTRL_ADV_1000_HALF | - MII_TG3_CTRL_ADV_1000_FULL))) { - current_link_up = 0; - } - } else { - current_link_up = 0; - } - } else { - if (!(bmcr & BMCR_ANENABLE) && - tp->link_config.speed == current_speed && - tp->link_config.duplex == current_duplex) { - current_link_up = 1; - } else { - current_link_up = 0; - } - } - - tp->link_config.active_speed = current_speed; - tp->link_config.active_duplex = current_duplex; - } - - if (current_link_up == 1 && - (tp->link_config.active_duplex == DUPLEX_FULL) && - (tp->link_config.autoneg == AUTONEG_ENABLE)) { - u32 local_adv, remote_adv; - - tg3_readphy(tp, MII_ADVERTISE, &local_adv); - local_adv &= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); - - tg3_readphy(tp, MII_LPA, &remote_adv); - remote_adv &= (LPA_PAUSE_CAP | LPA_PAUSE_ASYM); - - /* If we are not advertising full pause capability, - * something is wrong. Bring the link down and reconfigure. - */ - if (local_adv != ADVERTISE_PAUSE_CAP) { - current_link_up = 0; - } else { - tg3_setup_flow_control(tp, local_adv, remote_adv); - } - } - - if (current_link_up == 0) { - u32 tmp; - - tg3_phy_copper_begin(tp, 0); - - tg3_readphy(tp, MII_BMSR, &tmp); - tg3_readphy(tp, MII_BMSR, &tmp); - if (tmp & BMSR_LSTATUS) - current_link_up = 1; - } - - tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK; - if (current_link_up == 1) { - if (tp->link_config.active_speed == SPEED_100 || - tp->link_config.active_speed == SPEED_10) - tp->mac_mode |= MAC_MODE_PORT_MODE_MII; - else - tp->mac_mode |= MAC_MODE_PORT_MODE_GMII; - } else - tp->mac_mode |= MAC_MODE_PORT_MODE_GMII; - - tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX; - if (tp->link_config.active_duplex == DUPLEX_HALF) - tp->mac_mode |= MAC_MODE_HALF_DUPLEX; - - tp->mac_mode &= ~MAC_MODE_LINK_POLARITY; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) { - if ((tp->led_mode == led_mode_link10) || - (current_link_up == 1 && - tp->link_config.active_speed == SPEED_10)) - tp->mac_mode |= MAC_MODE_LINK_POLARITY; - } else { - if (current_link_up == 1) - tp->mac_mode |= MAC_MODE_LINK_POLARITY; - tw32(MAC_LED_CTRL, LED_CTRL_PHY_MODE_1); - } - - /* ??? Without this setting Netgear GA302T PHY does not - * ??? send/receive packets... - */ - if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411 && - tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) { - tp->mi_mode |= MAC_MI_MODE_AUTO_POLL; - tw32(MAC_MI_MODE, tp->mi_mode); - tr32(MAC_MI_MODE); - udelay(40); - } - - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); - udelay(40); - - if (tp->tg3_flags & - (TG3_FLAG_USE_LINKCHG_REG | - TG3_FLAG_POLL_SERDES)) { - /* Polled via timer. */ - tw32(MAC_EVENT, 0); - } else { - tw32(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); - } - tr32(MAC_EVENT); - udelay(40); - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 && - current_link_up == 1 && - tp->link_config.active_speed == SPEED_1000 && - ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) || - (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED))) { - udelay(120); - tw32(MAC_STATUS, - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)); - tr32(MAC_STATUS); - udelay(40); - tg3_write_mem(tp, - NIC_SRAM_FIRMWARE_MBOX, - NIC_SRAM_FIRMWARE_MBOX_MAGIC2); - } - - if (current_link_up != netif_carrier_ok(tp->dev)) { - if (current_link_up) - netif_carrier_on(tp->dev); - else - netif_carrier_off(tp->dev); - tg3_link_report(tp); - } - - return 0; -} - -struct tg3_fiber_aneginfo { - int state; -#define ANEG_STATE_UNKNOWN 0 -#define ANEG_STATE_AN_ENABLE 1 -#define ANEG_STATE_RESTART_INIT 2 -#define ANEG_STATE_RESTART 3 -#define ANEG_STATE_DISABLE_LINK_OK 4 -#define ANEG_STATE_ABILITY_DETECT_INIT 5 -#define ANEG_STATE_ABILITY_DETECT 6 -#define ANEG_STATE_ACK_DETECT_INIT 7 -#define ANEG_STATE_ACK_DETECT 8 -#define ANEG_STATE_COMPLETE_ACK_INIT 9 -#define ANEG_STATE_COMPLETE_ACK 10 -#define ANEG_STATE_IDLE_DETECT_INIT 11 -#define ANEG_STATE_IDLE_DETECT 12 -#define ANEG_STATE_LINK_OK 13 -#define ANEG_STATE_NEXT_PAGE_WAIT_INIT 14 -#define ANEG_STATE_NEXT_PAGE_WAIT 15 - - u32 flags; -#define MR_AN_ENABLE 0x00000001 -#define MR_RESTART_AN 0x00000002 -#define MR_AN_COMPLETE 0x00000004 -#define MR_PAGE_RX 0x00000008 -#define MR_NP_LOADED 0x00000010 -#define MR_TOGGLE_TX 0x00000020 -#define MR_LP_ADV_FULL_DUPLEX 0x00000040 -#define MR_LP_ADV_HALF_DUPLEX 0x00000080 -#define MR_LP_ADV_SYM_PAUSE 0x00000100 -#define MR_LP_ADV_ASYM_PAUSE 0x00000200 -#define MR_LP_ADV_REMOTE_FAULT1 0x00000400 -#define MR_LP_ADV_REMOTE_FAULT2 0x00000800 -#define MR_LP_ADV_NEXT_PAGE 0x00001000 -#define MR_TOGGLE_RX 0x00002000 -#define MR_NP_RX 0x00004000 - -#define MR_LINK_OK 0x80000000 - - unsigned long link_time, cur_time; - - u32 ability_match_cfg; - int ability_match_count; - - char ability_match, idle_match, ack_match; - - u32 txconfig, rxconfig; -#define ANEG_CFG_NP 0x00000080 -#define ANEG_CFG_ACK 0x00000040 -#define ANEG_CFG_RF2 0x00000020 -#define ANEG_CFG_RF1 0x00000010 -#define ANEG_CFG_PS2 0x00000001 -#define ANEG_CFG_PS1 0x00008000 -#define ANEG_CFG_HD 0x00004000 -#define ANEG_CFG_FD 0x00002000 -#define ANEG_CFG_INVAL 0x00001f06 - -}; -#define ANEG_OK 0 -#define ANEG_DONE 1 -#define ANEG_TIMER_ENAB 2 -#define ANEG_FAILED -1 - -#define ANEG_STATE_SETTLE_TIME 10000 - -static int tg3_fiber_aneg_smachine(struct tg3 *tp, - struct tg3_fiber_aneginfo *ap) -{ - unsigned long delta; - u32 rx_cfg_reg; - int ret; - - if (ap->state == ANEG_STATE_UNKNOWN) { - ap->rxconfig = 0; - ap->link_time = 0; - ap->cur_time = 0; - ap->ability_match_cfg = 0; - ap->ability_match_count = 0; - ap->ability_match = 0; - ap->idle_match = 0; - ap->ack_match = 0; - } - ap->cur_time++; - - if (tr32(MAC_STATUS) & MAC_STATUS_RCVD_CFG) { - rx_cfg_reg = tr32(MAC_RX_AUTO_NEG); - - if (rx_cfg_reg != ap->ability_match_cfg) { - ap->ability_match_cfg = rx_cfg_reg; - ap->ability_match = 0; - ap->ability_match_count = 0; - } else { - if (++ap->ability_match_count > 1) { - ap->ability_match = 1; - ap->ability_match_cfg = rx_cfg_reg; - } - } - if (rx_cfg_reg & ANEG_CFG_ACK) - ap->ack_match = 1; - else - ap->ack_match = 0; - - ap->idle_match = 0; - } else { - ap->idle_match = 1; - ap->ability_match_cfg = 0; - ap->ability_match_count = 0; - ap->ability_match = 0; - ap->ack_match = 0; - - rx_cfg_reg = 0; - } - - ap->rxconfig = rx_cfg_reg; - ret = ANEG_OK; - - switch(ap->state) { - case ANEG_STATE_UNKNOWN: - if (ap->flags & (MR_AN_ENABLE | MR_RESTART_AN)) - ap->state = ANEG_STATE_AN_ENABLE; - - /* fallthru */ - case ANEG_STATE_AN_ENABLE: - ap->flags &= ~(MR_AN_COMPLETE | MR_PAGE_RX); - if (ap->flags & MR_AN_ENABLE) { - ap->link_time = 0; - ap->cur_time = 0; - ap->ability_match_cfg = 0; - ap->ability_match_count = 0; - ap->ability_match = 0; - ap->idle_match = 0; - ap->ack_match = 0; - - ap->state = ANEG_STATE_RESTART_INIT; - } else { - ap->state = ANEG_STATE_DISABLE_LINK_OK; - } - break; - - case ANEG_STATE_RESTART_INIT: - ap->link_time = ap->cur_time; - ap->flags &= ~(MR_NP_LOADED); - ap->txconfig = 0; - tw32(MAC_TX_AUTO_NEG, 0); - tp->mac_mode |= MAC_MODE_SEND_CONFIGS; - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); - udelay(40); - - ret = ANEG_TIMER_ENAB; - ap->state = ANEG_STATE_RESTART; - - /* fallthru */ - case ANEG_STATE_RESTART: - delta = ap->cur_time - ap->link_time; - if (delta > ANEG_STATE_SETTLE_TIME) { - ap->state = ANEG_STATE_ABILITY_DETECT_INIT; - } else { - ret = ANEG_TIMER_ENAB; - } - break; - - case ANEG_STATE_DISABLE_LINK_OK: - ret = ANEG_DONE; - break; - - case ANEG_STATE_ABILITY_DETECT_INIT: - ap->flags &= ~(MR_TOGGLE_TX); - ap->txconfig = (ANEG_CFG_FD | ANEG_CFG_PS1); - tw32(MAC_TX_AUTO_NEG, ap->txconfig); - tp->mac_mode |= MAC_MODE_SEND_CONFIGS; - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); - udelay(40); - - ap->state = ANEG_STATE_ABILITY_DETECT; - break; - - case ANEG_STATE_ABILITY_DETECT: - if (ap->ability_match != 0 && ap->rxconfig != 0) { - ap->state = ANEG_STATE_ACK_DETECT_INIT; - } - break; - - case ANEG_STATE_ACK_DETECT_INIT: - ap->txconfig |= ANEG_CFG_ACK; - tw32(MAC_TX_AUTO_NEG, ap->txconfig); - tp->mac_mode |= MAC_MODE_SEND_CONFIGS; - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); - udelay(40); - - ap->state = ANEG_STATE_ACK_DETECT; - - /* fallthru */ - case ANEG_STATE_ACK_DETECT: - if (ap->ack_match != 0) { - if ((ap->rxconfig & ~ANEG_CFG_ACK) == - (ap->ability_match_cfg & ~ANEG_CFG_ACK)) { - ap->state = ANEG_STATE_COMPLETE_ACK_INIT; - } else { - ap->state = ANEG_STATE_AN_ENABLE; - } - } else if (ap->ability_match != 0 && - ap->rxconfig == 0) { - ap->state = ANEG_STATE_AN_ENABLE; - } - break; - - case ANEG_STATE_COMPLETE_ACK_INIT: - if (ap->rxconfig & ANEG_CFG_INVAL) { - ret = ANEG_FAILED; - break; - } - ap->flags &= ~(MR_LP_ADV_FULL_DUPLEX | - MR_LP_ADV_HALF_DUPLEX | - MR_LP_ADV_SYM_PAUSE | - MR_LP_ADV_ASYM_PAUSE | - MR_LP_ADV_REMOTE_FAULT1 | - MR_LP_ADV_REMOTE_FAULT2 | - MR_LP_ADV_NEXT_PAGE | - MR_TOGGLE_RX | - MR_NP_RX); - if (ap->rxconfig & ANEG_CFG_FD) - ap->flags |= MR_LP_ADV_FULL_DUPLEX; - if (ap->rxconfig & ANEG_CFG_HD) - ap->flags |= MR_LP_ADV_HALF_DUPLEX; - if (ap->rxconfig & ANEG_CFG_PS1) - ap->flags |= MR_LP_ADV_SYM_PAUSE; - if (ap->rxconfig & ANEG_CFG_PS2) - ap->flags |= MR_LP_ADV_ASYM_PAUSE; - if (ap->rxconfig & ANEG_CFG_RF1) - ap->flags |= MR_LP_ADV_REMOTE_FAULT1; - if (ap->rxconfig & ANEG_CFG_RF2) - ap->flags |= MR_LP_ADV_REMOTE_FAULT2; - if (ap->rxconfig & ANEG_CFG_NP) - ap->flags |= MR_LP_ADV_NEXT_PAGE; - - ap->link_time = ap->cur_time; - - ap->flags ^= (MR_TOGGLE_TX); - if (ap->rxconfig & 0x0008) - ap->flags |= MR_TOGGLE_RX; - if (ap->rxconfig & ANEG_CFG_NP) - ap->flags |= MR_NP_RX; - ap->flags |= MR_PAGE_RX; - - ap->state = ANEG_STATE_COMPLETE_ACK; - ret = ANEG_TIMER_ENAB; - break; - - case ANEG_STATE_COMPLETE_ACK: - if (ap->ability_match != 0 && - ap->rxconfig == 0) { - ap->state = ANEG_STATE_AN_ENABLE; - break; - } - delta = ap->cur_time - ap->link_time; - if (delta > ANEG_STATE_SETTLE_TIME) { - if (!(ap->flags & (MR_LP_ADV_NEXT_PAGE))) { - ap->state = ANEG_STATE_IDLE_DETECT_INIT; - } else { - if ((ap->txconfig & ANEG_CFG_NP) == 0 && - !(ap->flags & MR_NP_RX)) { - ap->state = ANEG_STATE_IDLE_DETECT_INIT; - } else { - ret = ANEG_FAILED; - } - } - } - break; - - case ANEG_STATE_IDLE_DETECT_INIT: - ap->link_time = ap->cur_time; - tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS; - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); - udelay(40); - - ap->state = ANEG_STATE_IDLE_DETECT; - ret = ANEG_TIMER_ENAB; - break; - - case ANEG_STATE_IDLE_DETECT: - if (ap->ability_match != 0 && - ap->rxconfig == 0) { - ap->state = ANEG_STATE_AN_ENABLE; - break; - } - delta = ap->cur_time - ap->link_time; - if (delta > ANEG_STATE_SETTLE_TIME) { - /* XXX another gem from the Broadcom driver :( */ - ap->state = ANEG_STATE_LINK_OK; - } - break; - - case ANEG_STATE_LINK_OK: - ap->flags |= (MR_AN_COMPLETE | MR_LINK_OK); - ret = ANEG_DONE; - break; - - case ANEG_STATE_NEXT_PAGE_WAIT_INIT: - /* ??? unimplemented */ - break; - - case ANEG_STATE_NEXT_PAGE_WAIT: - /* ??? unimplemented */ - break; - - default: - ret = ANEG_FAILED; - break; - }; - - return ret; -} - -static int tg3_setup_fiber_phy(struct tg3 *tp) -{ - u32 orig_pause_cfg; - u16 orig_active_speed; - u8 orig_active_duplex; - int current_link_up; - int i; - - orig_pause_cfg = - (tp->tg3_flags & (TG3_FLAG_RX_PAUSE | - TG3_FLAG_TX_PAUSE)); - orig_active_speed = tp->link_config.active_speed; - orig_active_duplex = tp->link_config.active_duplex; - - tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX); - tp->mac_mode |= MAC_MODE_PORT_MODE_TBI; - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); - udelay(40); - - /* Reset when initting first time or we have a link. */ - if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) || - (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) { - /* Set PLL lock range. */ - tg3_writephy(tp, 0x16, 0x8007); - - /* SW reset */ - tg3_writephy(tp, MII_BMCR, BMCR_RESET); - - /* Wait for reset to complete. */ - /* XXX schedule_timeout() ... */ - for (i = 0; i < 500; i++) - udelay(10); - - /* Config mode; select PMA/Ch 1 regs. */ - tg3_writephy(tp, 0x10, 0x8411); - - /* Enable auto-lock and comdet, select txclk for tx. */ - tg3_writephy(tp, 0x11, 0x0a10); - - tg3_writephy(tp, 0x18, 0x00a0); - tg3_writephy(tp, 0x16, 0x41ff); - - /* Assert and deassert POR. */ - tg3_writephy(tp, 0x13, 0x0400); - udelay(40); - tg3_writephy(tp, 0x13, 0x0000); - - tg3_writephy(tp, 0x11, 0x0a50); - udelay(40); - tg3_writephy(tp, 0x11, 0x0a10); - - /* Wait for signal to stabilize */ - /* XXX schedule_timeout() ... */ - for (i = 0; i < 15000; i++) - udelay(10); - - /* Deselect the channel register so we can read the PHYID - * later. - */ - tg3_writephy(tp, 0x10, 0x8011); - } - - /* Enable link change interrupt unless serdes polling. */ - if (!(tp->tg3_flags & TG3_FLAG_POLL_SERDES)) - tw32(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); - else - tw32(MAC_EVENT, 0); - tr32(MAC_EVENT); - udelay(40); - - current_link_up = 0; - if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) { - if (tp->link_config.autoneg == AUTONEG_ENABLE && - !(tp->tg3_flags & TG3_FLAG_GOT_SERDES_FLOWCTL)) { - struct tg3_fiber_aneginfo aninfo; - int status = ANEG_FAILED; - unsigned int tick; - u32 tmp; - - memset(&aninfo, 0, sizeof(aninfo)); - aninfo.flags |= (MR_AN_ENABLE); - - tw32(MAC_TX_AUTO_NEG, 0); - - tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK; - tw32(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII); - tr32(MAC_MODE); - udelay(40); - - tw32(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS); - tr32(MAC_MODE); - udelay(40); - - aninfo.state = ANEG_STATE_UNKNOWN; - aninfo.cur_time = 0; - tick = 0; - while (++tick < 195000) { - status = tg3_fiber_aneg_smachine(tp, &aninfo); - if (status == ANEG_DONE || - status == ANEG_FAILED) - break; - - udelay(1); - } - - tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS; - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); - udelay(40); - - if (status == ANEG_DONE && - (aninfo.flags & - (MR_AN_COMPLETE | MR_LINK_OK | - MR_LP_ADV_FULL_DUPLEX))) { - u32 local_adv, remote_adv; - - local_adv = ADVERTISE_PAUSE_CAP; - remote_adv = 0; - if (aninfo.flags & MR_LP_ADV_SYM_PAUSE) - remote_adv |= LPA_PAUSE_CAP; - if (aninfo.flags & MR_LP_ADV_ASYM_PAUSE) - remote_adv |= LPA_PAUSE_ASYM; - - tg3_setup_flow_control(tp, local_adv, remote_adv); - - tp->tg3_flags |= - TG3_FLAG_GOT_SERDES_FLOWCTL; - current_link_up = 1; - } - for (i = 0; i < 60; i++) { - udelay(20); - tw32(MAC_STATUS, - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)); - tr32(MAC_STATUS); - udelay(40); - if ((tr32(MAC_STATUS) & - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)) == 0) - break; - } - if (current_link_up == 0 && - (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) { - current_link_up = 1; - } - } else { - /* Forcing 1000FD link up. */ - current_link_up = 1; - } - } - - tp->mac_mode &= ~MAC_MODE_LINK_POLARITY; - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); - udelay(40); - - tp->hw_status->status = - (SD_STATUS_UPDATED | - (tp->hw_status->status & ~SD_STATUS_LINK_CHG)); - - for (i = 0; i < 100; i++) { - udelay(20); - tw32(MAC_STATUS, - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)); - tr32(MAC_STATUS); - udelay(40); - if ((tr32(MAC_STATUS) & - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)) == 0) - break; - } - - if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) - current_link_up = 0; - - if (current_link_up == 1) { - tp->link_config.active_speed = SPEED_1000; - tp->link_config.active_duplex = DUPLEX_FULL; - } else { - tp->link_config.active_speed = SPEED_INVALID; - tp->link_config.active_duplex = DUPLEX_INVALID; - } - - if (current_link_up != netif_carrier_ok(tp->dev)) { - if (current_link_up) - netif_carrier_on(tp->dev); - else - netif_carrier_off(tp->dev); - tg3_link_report(tp); - } else { - u32 now_pause_cfg = - tp->tg3_flags & (TG3_FLAG_RX_PAUSE | - TG3_FLAG_TX_PAUSE); - if (orig_pause_cfg != now_pause_cfg || - orig_active_speed != tp->link_config.active_speed || - orig_active_duplex != tp->link_config.active_duplex) - tg3_link_report(tp); - } - - if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) { - tw32(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY); - tr32(MAC_MODE); - udelay(40); - if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) { - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); - udelay(40); - } - } - - return 0; -} - -static int tg3_setup_phy(struct tg3 *tp) -{ - int err; - - if (tp->phy_id == PHY_ID_SERDES) { - err = tg3_setup_fiber_phy(tp); - } else { - err = tg3_setup_copper_phy(tp); - } - - if (tp->link_config.active_speed == SPEED_1000 && - tp->link_config.active_duplex == DUPLEX_HALF) - tw32(MAC_TX_LENGTHS, - ((2 << TX_LENGTHS_IPG_CRS_SHIFT) | - (6 << TX_LENGTHS_IPG_SHIFT) | - (0xff << TX_LENGTHS_SLOT_TIME_SHIFT))); - else - tw32(MAC_TX_LENGTHS, - ((2 << TX_LENGTHS_IPG_CRS_SHIFT) | - (6 << TX_LENGTHS_IPG_SHIFT) | - (32 << TX_LENGTHS_SLOT_TIME_SHIFT))); - - return err; -} - -/* Tigon3 never reports partial packet sends. So we do not - * need special logic to handle SKBs that have not had all - * of their frags sent yet, like SunGEM does. - */ -static void tg3_tx(struct tg3 *tp) -{ - u32 hw_idx = tp->hw_status->idx[0].tx_consumer; - u32 sw_idx = tp->tx_cons; - - while (sw_idx != hw_idx) { - struct tx_ring_info *ri = &tp->tx_buffers[sw_idx]; - struct sk_buff *skb = ri->skb; - int i; - - if (unlikely(skb == NULL)) - BUG(); - - pci_unmap_single(tp->pdev, - pci_unmap_addr(ri, mapping), - skb_headlen(skb), - PCI_DMA_TODEVICE); - - ri->skb = NULL; - - sw_idx = NEXT_TX(sw_idx); - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - if (unlikely(sw_idx == hw_idx)) - BUG(); - - ri = &tp->tx_buffers[sw_idx]; - if (unlikely(ri->skb != NULL)) - BUG(); - - pci_unmap_page(tp->pdev, - pci_unmap_addr(ri, mapping), - skb_shinfo(skb)->frags[i].size, - PCI_DMA_TODEVICE); - - sw_idx = NEXT_TX(sw_idx); - } - - dev_kfree_skb_irq(skb); - } - - tp->tx_cons = sw_idx; - - if (netif_queue_stopped(tp->dev) && - (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)) - netif_wake_queue(tp->dev); -} - -/* Returns size of skb allocated or < 0 on error. - * - * We only need to fill in the address because the other members - * of the RX descriptor are invariant, see tg3_init_rings. - * - * Note the purposeful assymetry of cpu vs. chip accesses. For - * posting buffers we only dirty the first cache line of the RX - * descriptor (containing the address). Whereas for the RX status - * buffers the cpu only reads the last cacheline of the RX descriptor - * (to fetch the error flags, vlan tag, checksum, and opaque cookie). - */ -static int tg3_alloc_rx_skb(struct tg3 *tp, u32 opaque_key, - int src_idx, u32 dest_idx_unmasked) -{ - struct tg3_rx_buffer_desc *desc; - struct ring_info *map, *src_map; - struct sk_buff *skb; - dma_addr_t mapping; - int skb_size, dest_idx; - - src_map = NULL; - switch (opaque_key) { - case RXD_OPAQUE_RING_STD: - dest_idx = dest_idx_unmasked % TG3_RX_RING_SIZE; - desc = &tp->rx_std[dest_idx]; - map = &tp->rx_std_buffers[dest_idx]; - if (src_idx >= 0) - src_map = &tp->rx_std_buffers[src_idx]; - skb_size = RX_PKT_BUF_SZ; - break; - - case RXD_OPAQUE_RING_JUMBO: - dest_idx = dest_idx_unmasked % TG3_RX_JUMBO_RING_SIZE; - desc = &tp->rx_jumbo[dest_idx]; - map = &tp->rx_jumbo_buffers[dest_idx]; - if (src_idx >= 0) - src_map = &tp->rx_jumbo_buffers[src_idx]; - skb_size = RX_JUMBO_PKT_BUF_SZ; - break; - - default: - return -EINVAL; - }; - - /* Do not overwrite any of the map or rp information - * until we are sure we can commit to a new buffer. - * - * Callers depend upon this behavior and assume that - * we leave everything unchanged if we fail. - */ - skb = dev_alloc_skb(skb_size); - if (skb == NULL) - return -ENOMEM; - - skb->dev = tp->dev; - skb_reserve(skb, tp->rx_offset); - - mapping = pci_map_single(tp->pdev, skb->data, - skb_size - tp->rx_offset, - PCI_DMA_FROMDEVICE); - - map->skb = skb; - pci_unmap_addr_set(map, mapping, mapping); - - if (src_map != NULL) - src_map->skb = NULL; - - desc->addr_hi = ((u64)mapping >> 32); - desc->addr_lo = ((u64)mapping & 0xffffffff); - - return skb_size; -} - -/* We only need to move over in the address because the other - * members of the RX descriptor are invariant. See notes above - * tg3_alloc_rx_skb for full details. - */ -static void tg3_recycle_rx(struct tg3 *tp, u32 opaque_key, - int src_idx, u32 dest_idx_unmasked) -{ - struct tg3_rx_buffer_desc *src_desc, *dest_desc; - struct ring_info *src_map, *dest_map; - int dest_idx; - - switch (opaque_key) { - case RXD_OPAQUE_RING_STD: - dest_idx = dest_idx_unmasked % TG3_RX_RING_SIZE; - dest_desc = &tp->rx_std[dest_idx]; - dest_map = &tp->rx_std_buffers[dest_idx]; - src_desc = &tp->rx_std[src_idx]; - src_map = &tp->rx_std_buffers[src_idx]; - break; - - case RXD_OPAQUE_RING_JUMBO: - dest_idx = dest_idx_unmasked % TG3_RX_JUMBO_RING_SIZE; - dest_desc = &tp->rx_jumbo[dest_idx]; - dest_map = &tp->rx_jumbo_buffers[dest_idx]; - src_desc = &tp->rx_jumbo[src_idx]; - src_map = &tp->rx_jumbo_buffers[src_idx]; - break; - - default: - return; - }; - - dest_map->skb = src_map->skb; - pci_unmap_addr_set(dest_map, mapping, - pci_unmap_addr(src_map, mapping)); - dest_desc->addr_hi = src_desc->addr_hi; - dest_desc->addr_lo = src_desc->addr_lo; - - src_map->skb = NULL; -} - -#if TG3_VLAN_TAG_USED -static int tg3_vlan_rx(struct tg3 *tp, struct sk_buff *skb, u16 vlan_tag) -{ - return vlan_hwaccel_receive_skb(skb, tp->vlgrp, vlan_tag); -} -#endif - -/* The RX ring scheme is composed of multiple rings which post fresh - * buffers to the chip, and one special ring the chip uses to report - * status back to the host. - * - * The special ring reports the status of received packets to the - * host. The chip does not write into the original descriptor the - * RX buffer was obtained from. The chip simply takes the original - * descriptor as provided by the host, updates the status and length - * field, then writes this into the next status ring entry. - * - * Each ring the host uses to post buffers to the chip is described - * by a TG3_BDINFO entry in the chips SRAM area. When a packet arrives, - * it is first placed into the on-chip ram. When the packet's length - * is known, it walks down the TG3_BDINFO entries to select the ring. - * Each TG3_BDINFO specifies a MAXLEN field and the first TG3_BDINFO - * which is within the range of the new packet's length is chosen. - * - * The "separate ring for rx status" scheme may sound queer, but it makes - * sense from a cache coherency perspective. If only the host writes - * to the buffer post rings, and only the chip writes to the rx status - * rings, then cache lines never move beyond shared-modified state. - * If both the host and chip were to write into the same ring, cache line - * eviction could occur since both entities want it in an exclusive state. - */ -static int tg3_rx(struct tg3 *tp, int budget) -{ - u32 work_mask; - u32 rx_rcb_ptr = tp->rx_rcb_ptr; - u16 hw_idx, sw_idx; - int received; - - hw_idx = tp->hw_status->idx[0].rx_producer; - sw_idx = rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp); - work_mask = 0; - received = 0; - while (sw_idx != hw_idx && budget > 0) { - struct tg3_rx_buffer_desc *desc = &tp->rx_rcb[sw_idx]; - unsigned int len; - struct sk_buff *skb; - dma_addr_t dma_addr; - u32 opaque_key, desc_idx, *post_ptr; - - desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK; - opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK; - if (opaque_key == RXD_OPAQUE_RING_STD) { - dma_addr = pci_unmap_addr(&tp->rx_std_buffers[desc_idx], - mapping); - skb = tp->rx_std_buffers[desc_idx].skb; - post_ptr = &tp->rx_std_ptr; - } else if (opaque_key == RXD_OPAQUE_RING_JUMBO) { - dma_addr = pci_unmap_addr(&tp->rx_jumbo_buffers[desc_idx], - mapping); - skb = tp->rx_jumbo_buffers[desc_idx].skb; - post_ptr = &tp->rx_jumbo_ptr; - } - else { - goto next_pkt_nopost; - } - - work_mask |= opaque_key; - - if ((desc->err_vlan & RXD_ERR_MASK) != 0 && - (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) { - drop_it: - tg3_recycle_rx(tp, opaque_key, - desc_idx, *post_ptr); - drop_it_no_recycle: - /* Other statistics kept track of by card. */ - tp->net_stats.rx_dropped++; - goto next_pkt; - } - - len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; /* omit crc */ - - if (len > RX_COPY_THRESHOLD) { - int skb_size; - - skb_size = tg3_alloc_rx_skb(tp, opaque_key, - desc_idx, *post_ptr); - if (skb_size < 0) - goto drop_it; - - pci_unmap_single(tp->pdev, dma_addr, - skb_size - tp->rx_offset, - PCI_DMA_FROMDEVICE); - - skb_put(skb, len); - } else { - struct sk_buff *copy_skb; - - tg3_recycle_rx(tp, opaque_key, - desc_idx, *post_ptr); - - copy_skb = dev_alloc_skb(len + 2); - if (copy_skb == NULL) - goto drop_it_no_recycle; - - copy_skb->dev = tp->dev; - skb_reserve(copy_skb, 2); - skb_put(copy_skb, len); - pci_dma_sync_single(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE); - memcpy(copy_skb->data, skb->data, len); - - /* We'll reuse the original ring buffer. */ - skb = copy_skb; - } - - if ((tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) && - (desc->type_flags & RXD_FLAG_TCPUDP_CSUM) && - (((desc->ip_tcp_csum & RXD_TCPCSUM_MASK) - >> RXD_TCPCSUM_SHIFT) == 0xffff)) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - - skb->protocol = eth_type_trans(skb, tp->dev); -#if TG3_VLAN_TAG_USED - if (tp->vlgrp != NULL && - desc->type_flags & RXD_FLAG_VLAN) { - tg3_vlan_rx(tp, skb, - desc->err_vlan & RXD_VLAN_MASK); - } else -#endif -#ifdef NAPI - netif_receive_skb(skb); -#else - netif_rx(skb); -#endif - tp->dev->last_rx = jiffies; - received++; - budget--; - -next_pkt: - (*post_ptr)++; -next_pkt_nopost: - rx_rcb_ptr++; - sw_idx = rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp); - } - - /* ACK the status ring. */ - tp->rx_rcb_ptr = rx_rcb_ptr; - tw32_mailbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, - (rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp))); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW); - - /* Refill RX ring(s). */ - if (work_mask & RXD_OPAQUE_RING_STD) { - sw_idx = tp->rx_std_ptr % TG3_RX_RING_SIZE; - tw32_mailbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW, - sw_idx); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW); - } - if (work_mask & RXD_OPAQUE_RING_JUMBO) { - sw_idx = tp->rx_jumbo_ptr % TG3_RX_JUMBO_RING_SIZE; - tw32_mailbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW, - sw_idx); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW); - } - - return received; -} - -static int tg3_poll(struct net_device *netdev, int *budget) -{ - struct tg3 *tp = netdev->priv; - struct tg3_hw_status *sblk = tp->hw_status; - int done; - -#ifdef NAPI - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); -#endif - /* handle link change and other phy events */ - if (!(tp->tg3_flags & - (TG3_FLAG_USE_LINKCHG_REG | - TG3_FLAG_POLL_SERDES))) { - if (sblk->status & SD_STATUS_LINK_CHG) { - sblk->status = SD_STATUS_UPDATED | - (sblk->status & ~SD_STATUS_LINK_CHG); - tg3_setup_phy(tp); - } - } - - /* run TX completion thread */ - if (sblk->idx[0].tx_consumer != tp->tx_cons) { - spin_lock(&tp->tx_lock); - tg3_tx(tp); - spin_unlock(&tp->tx_lock); - } -#ifdef NAPI - spin_unlock_irqrestore(&tp->lock, flags); -#endif - /* run RX thread, within the bounds set by NAPI. - * All RX "locking" is done by ensuring outside - * code synchronizes with dev->poll() - */ - done = 1; - if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr) { - int work_done; -#ifdef NAPI - int orig_budget = *budget; - - if (orig_budget > netdev->quota) - orig_budget = netdev->quota; - - work_done = tg3_rx(tp, orig_budget); - - *budget -= work_done; - netdev->quota -= work_done; - - if (work_done >= orig_budget) - done = 0; -#else - work_done = tg3_rx(tp, 1000); -#endif - } -#ifdef NAPI - /* if no more work, tell net stack and NIC we're done */ - if (done) { - spin_lock_irqsave(&tp->lock, flags); - __netif_rx_complete(netdev); - tg3_enable_ints(tp); - spin_unlock_irqrestore(&tp->lock, flags); - } -#endif - return (done ? 0 : 1); -} - -static inline unsigned int tg3_has_work(struct net_device *dev, struct tg3 *tp) -{ - struct tg3_hw_status *sblk = tp->hw_status; - unsigned int work_exists = 0; - - /* check for phy events */ - if (!(tp->tg3_flags & - (TG3_FLAG_USE_LINKCHG_REG | - TG3_FLAG_POLL_SERDES))) { - if (sblk->status & SD_STATUS_LINK_CHG) - work_exists = 1; - } - /* check for RX/TX work to do */ - if (sblk->idx[0].tx_consumer != tp->tx_cons || - sblk->idx[0].rx_producer != tp->rx_rcb_ptr) - work_exists = 1; - - return work_exists; -} - -static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = dev_id; - struct tg3 *tp = dev->priv; - struct tg3_hw_status *sblk = tp->hw_status; - unsigned long flags; - unsigned int handled = 1; - - spin_lock_irqsave(&tp->lock, flags); -#ifdef NAPI - if (sblk->status & SD_STATUS_UPDATED) { - /* - * writing any value to intr-mbox-0 clears PCI INTA# and - * chip-internal interrupt pending events. - * writing non-zero to intr-mbox-0 additional tells the - * NIC to stop sending us irqs, engaging "in-intr-handler" - * event coalescing. - */ - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, - 0x00000001); - /* - * Flush PCI write. This also guarantees that our - * status block has been flushed to host memory. - */ - tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); - sblk->status &= ~SD_STATUS_UPDATED; - - if (likely(tg3_has_work(dev, tp))) - netif_rx_schedule(dev); /* schedule NAPI poll */ - else { - /* no work, shared interrupt perhaps? re-enable - * interrupts, and flush that PCI write - */ - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, - 0x00000000); - tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); - } - } - else { /* shared interrupt */ - handled = 0; - } -#else - if (sblk->status & SD_STATUS_UPDATED) { - int budget = 1000; - tg3_poll( dev, &budget ); - - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, - 0x00000000); - tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); - } - else { /* shared interrupt */ - handled = 0; - } -#endif - - spin_unlock_irqrestore(&tp->lock, flags); - - return IRQ_RETVAL(handled); -} - -static int tg3_init_hw(struct tg3 *); -static int tg3_halt(struct tg3 *); - -static void tg3_reset_task(void *_data) -{ - struct tg3 *tp = _data; - unsigned int restart_timer; - - tg3_netif_stop(tp); - - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - - restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER; - tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER; - - tg3_halt(tp); - tg3_init_hw(tp); - - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - - tg3_netif_start(tp); - - if (restart_timer) - mod_timer(&tp->timer, jiffies + 1); -} - -static void tg3_tx_timeout(struct net_device *dev) -{ - struct tg3 *tp = dev->priv; - - printk(KERN_ERR PFX "%s: transmit timed out, resetting\n", - dev->name); - - //schedule_task(&tp->reset_task); - tg3_reset_task(tp); -} - -static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32); - -static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, - u32 guilty_entry, int guilty_len, - u32 last_plus_one, u32 *start, u32 mss) -{ - struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC); - dma_addr_t new_addr; - u32 entry = *start; - int i; - - if (!new_skb) { - dev_kfree_skb(skb); - return -1; - } - - /* New SKB is guaranteed to be linear. */ - entry = *start; - new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len, - PCI_DMA_TODEVICE); - tg3_set_txd(tp, entry, new_addr, new_skb->len, - (skb->ip_summed == CHECKSUM_HW) ? - TXD_FLAG_TCPUDP_CSUM : 0, 1 | (mss << 1)); - *start = NEXT_TX(entry); - - /* Now clean up the sw ring entries. */ - i = 0; - while (entry != last_plus_one) { - int len; - - if (i == 0) - len = skb_headlen(skb); - else - len = skb_shinfo(skb)->frags[i-1].size; - pci_unmap_single(tp->pdev, - pci_unmap_addr(&tp->tx_buffers[entry], mapping), - len, PCI_DMA_TODEVICE); - if (i == 0) { - tp->tx_buffers[entry].skb = new_skb; - pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, new_addr); - } else { - tp->tx_buffers[entry].skb = NULL; - } - entry = NEXT_TX(entry); - } - - dev_kfree_skb(skb); - - return 0; -} - -static void tg3_set_txd(struct tg3 *tp, int entry, - dma_addr_t mapping, int len, u32 flags, - u32 mss_and_is_end) -{ - int is_end = (mss_and_is_end & 0x1); - u32 mss = (mss_and_is_end >> 1); - u32 vlan_tag = 0; - - if (is_end) - flags |= TXD_FLAG_END; - if (flags & TXD_FLAG_VLAN) { - vlan_tag = flags >> 16; - flags &= 0xffff; - } - vlan_tag |= (mss << TXD_MSS_SHIFT); - if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { - struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry]; - - txd->addr_hi = ((u64) mapping >> 32); - txd->addr_lo = ((u64) mapping & 0xffffffff); - txd->len_flags = (len << TXD_LEN_SHIFT) | flags; - txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT; - } else { - struct tx_ring_info *txr = &tp->tx_buffers[entry]; - unsigned long txd; - - txd = (tp->regs + - NIC_SRAM_WIN_BASE + - NIC_SRAM_TX_BUFFER_DESC); - txd += (entry * TXD_SIZE); - - /* Save some PIOs */ - if (sizeof(dma_addr_t) != sizeof(u32)) - writel(((u64) mapping >> 32), - txd + TXD_ADDR + TG3_64BIT_REG_HIGH); - - writel(((u64) mapping & 0xffffffff), - txd + TXD_ADDR + TG3_64BIT_REG_LOW); - writel(len << TXD_LEN_SHIFT | flags, txd + TXD_LEN_FLAGS); - if (txr->prev_vlan_tag != vlan_tag) { - writel(vlan_tag << TXD_VLAN_TAG_SHIFT, txd + TXD_VLAN_TAG); - txr->prev_vlan_tag = vlan_tag; - } - } -} - -static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len) -{ - u32 base = (u32) mapping & 0xffffffff; - - return ((base > 0xffffdcc0) && - ((u64) mapping >> 32) == 0 && - (base + len + 8 < base)); -} - -static int tg3_start_xmit_4gbug(struct sk_buff *skb, struct net_device *dev) -{ - struct tg3 *tp = dev->priv; - dma_addr_t mapping; - unsigned int i; - u32 len, entry, base_flags, mss; - int would_hit_hwbug; - unsigned long flags; - - len = skb_headlen(skb); - - /* No BH disabling for tx_lock here. We are running in BH disabled - * context and TX reclaim runs via tp->poll inside of a software - * interrupt. Rejoice! - * - * Actually, things are not so simple. If we are to take a hw - * IRQ here, we can deadlock, consider: - * - * CPU1 CPU2 - * tg3_start_xmit - * take tp->tx_lock - * tg3_timer - * take tp->lock - * tg3_interrupt - * spin on tp->lock - * spin on tp->tx_lock - * - * So we really do need to disable interrupts when taking - * tx_lock here. - */ - spin_lock_irqsave(&tp->tx_lock, flags); - - /* This is a hard error, log it. */ - if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { - netif_stop_queue(dev); - spin_unlock_irqrestore(&tp->tx_lock, flags); - printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - return 1; - } - - entry = tp->tx_prod; - base_flags = 0; - if (skb->ip_summed == CHECKSUM_HW) - base_flags |= TXD_FLAG_TCPUDP_CSUM; -#if TG3_TSO_SUPPORT != 0 - mss = 0; - if (skb->len > (tp->dev->mtu + ETH_HLEN) && - (mss = skb_shinfo(skb)->tso_size) != 0) { - int tcp_opt_len, ip_tcp_len; - - tcp_opt_len = ((skb->h.th->doff - 5) * 4); - ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr); - - base_flags |= (TXD_FLAG_CPU_PRE_DMA | - TXD_FLAG_CPU_POST_DMA); - - skb->nh.iph->check = 0; - skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len); - skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr, - skb->nh.iph->daddr, - 0, IPPROTO_TCP, 0); - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { - if (tcp_opt_len || skb->nh.iph->ihl > 5) { - int tsflags; - - tsflags = ((skb->nh.iph->ihl - 5) + - (tcp_opt_len >> 2)); - mss |= (tsflags << 11); - } - } else { - mss += tcp_opt_len; - } - } -#else - mss = 0; -#endif -#if TG3_VLAN_TAG_USED - if (tp->vlgrp != NULL && vlan_tx_tag_present(skb)) - base_flags |= (TXD_FLAG_VLAN | - (vlan_tx_tag_get(skb) << 16)); -#endif - - /* Queue skb data, a.k.a. the main skb fragment. */ - mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_buffers[entry].skb = skb; - pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping); - - would_hit_hwbug = 0; - - if (tg3_4g_overflow_test(mapping, len)) - would_hit_hwbug = entry + 1; - - tg3_set_txd(tp, entry, mapping, len, base_flags, - (skb_shinfo(skb)->nr_frags == 0) | (mss << 1)); - - entry = NEXT_TX(entry); - - /* Now loop through additional data fragments, and queue them. */ - if (skb_shinfo(skb)->nr_frags > 0) { - unsigned int i, last; - - last = skb_shinfo(skb)->nr_frags - 1; - for (i = 0; i <= last; i++) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - - len = frag->size; - mapping = pci_map_page(tp->pdev, - frag->page, - frag->page_offset, - len, PCI_DMA_TODEVICE); - - tp->tx_buffers[entry].skb = NULL; - pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping); - - if (tg3_4g_overflow_test(mapping, len)) { - /* Only one should match. */ - if (would_hit_hwbug) - BUG(); - would_hit_hwbug = entry + 1; - } - - tg3_set_txd(tp, entry, mapping, len, - base_flags, (i == last)); - - entry = NEXT_TX(entry); - } - } - - if (would_hit_hwbug) { - u32 last_plus_one = entry; - u32 start; - unsigned int len = 0; - - would_hit_hwbug -= 1; - entry = entry - 1 - skb_shinfo(skb)->nr_frags; - entry &= (TG3_TX_RING_SIZE - 1); - start = entry; - i = 0; - while (entry != last_plus_one) { - if (i == 0) - len = skb_headlen(skb); - else - len = skb_shinfo(skb)->frags[i-1].size; - - if (entry == would_hit_hwbug) - break; - - i++; - entry = NEXT_TX(entry); - - } - - /* If the workaround fails due to memory/mapping - * failure, silently drop this packet. - */ - if (tigon3_4gb_hwbug_workaround(tp, skb, - entry, len, - last_plus_one, - &start, mss)) - goto out_unlock; - - entry = start; - } - - /* Packets are ready, update Tx producer idx local and on card. */ - if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { - tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 + - TG3_64BIT_REG_LOW), entry); - if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) - tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 + - TG3_64BIT_REG_LOW), entry); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_SNDHOST_PROD_IDX_0 + - TG3_64BIT_REG_LOW); - } else { - /* First, make sure tg3 sees last descriptor fully - * in SRAM. - */ - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_SNDNIC_PROD_IDX_0 + - TG3_64BIT_REG_LOW); - - tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 + - TG3_64BIT_REG_LOW), entry); - if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) - tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 + - TG3_64BIT_REG_LOW), entry); - - /* Now post the mailbox write itself. */ - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_SNDNIC_PROD_IDX_0 + - TG3_64BIT_REG_LOW); - } - - tp->tx_prod = entry; - if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) - netif_stop_queue(dev); - -out_unlock: - spin_unlock_irqrestore(&tp->tx_lock, flags); - - dev->trans_start = jiffies; - - return 0; -} - -static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct tg3 *tp = dev->priv; - dma_addr_t mapping; - u32 len, entry, base_flags, mss; - unsigned long flags; - - len = skb_headlen(skb); - - /* No BH disabling for tx_lock here. We are running in BH disabled - * context and TX reclaim runs via tp->poll inside of a software - * interrupt. Rejoice! - * - * Actually, things are not so simple. If we are to take a hw - * IRQ here, we can deadlock, consider: - * - * CPU1 CPU2 - * tg3_start_xmit - * take tp->tx_lock - * tg3_timer - * take tp->lock - * tg3_interrupt - * spin on tp->lock - * spin on tp->tx_lock - * - * So we really do need to disable interrupts when taking - * tx_lock here. - */ - spin_lock_irqsave(&tp->tx_lock, flags); - - /* This is a hard error, log it. */ - if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { - netif_stop_queue(dev); - spin_unlock_irqrestore(&tp->tx_lock, flags); - printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - return 1; - } - - entry = tp->tx_prod; - base_flags = 0; - if (skb->ip_summed == CHECKSUM_HW) - base_flags |= TXD_FLAG_TCPUDP_CSUM; -#if TG3_TSO_SUPPORT != 0 - mss = 0; - if (skb->len > (tp->dev->mtu + ETH_HLEN) && - (mss = skb_shinfo(skb)->tso_size) != 0) { - int tcp_opt_len, ip_tcp_len; - - tcp_opt_len = ((skb->h.th->doff - 5) * 4); - ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr); - - base_flags |= (TXD_FLAG_CPU_PRE_DMA | - TXD_FLAG_CPU_POST_DMA); - - skb->nh.iph->check = 0; - skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len); - skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr, - skb->nh.iph->daddr, - 0, IPPROTO_TCP, 0); - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { - if (tcp_opt_len || skb->nh.iph->ihl > 5) { - int tsflags; - - tsflags = ((skb->nh.iph->ihl - 5) + - (tcp_opt_len >> 2)); - mss |= (tsflags << 11); - } - } else { - mss += tcp_opt_len; - } - } -#else - mss = 0; -#endif -#if TG3_VLAN_TAG_USED - if (tp->vlgrp != NULL && vlan_tx_tag_present(skb)) - base_flags |= (TXD_FLAG_VLAN | - (vlan_tx_tag_get(skb) << 16)); -#endif - - /* Queue skb data, a.k.a. the main skb fragment. */ - mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_buffers[entry].skb = skb; - pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping); - - tg3_set_txd(tp, entry, mapping, len, base_flags, - (skb_shinfo(skb)->nr_frags == 0) | (mss << 1)); - - entry = NEXT_TX(entry); - - /* Now loop through additional data fragments, and queue them. */ - if (skb_shinfo(skb)->nr_frags > 0) { - unsigned int i, last; - - last = skb_shinfo(skb)->nr_frags - 1; - for (i = 0; i <= last; i++) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - - - len = frag->size; - mapping = pci_map_page(tp->pdev, - frag->page, - frag->page_offset, - len, PCI_DMA_TODEVICE); - - tp->tx_buffers[entry].skb = NULL; - pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping); - - tg3_set_txd(tp, entry, mapping, len, - base_flags, (i == last)); - - entry = NEXT_TX(entry); - } - } - - /* Packets are ready, update Tx producer idx local and on card. - * We know this is not a 5700 (by virtue of not being a chip - * requiring the 4GB overflow workaround) so we can safely omit - * the double-write bug tests. - */ - if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { - tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 + - TG3_64BIT_REG_LOW), entry); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_SNDHOST_PROD_IDX_0 + - TG3_64BIT_REG_LOW); - } else { - /* First, make sure tg3 sees last descriptor fully - * in SRAM. - */ - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_SNDNIC_PROD_IDX_0 + - TG3_64BIT_REG_LOW); - - tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 + - TG3_64BIT_REG_LOW), entry); - - /* Now post the mailbox write itself. */ - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_SNDNIC_PROD_IDX_0 + - TG3_64BIT_REG_LOW); - } - - tp->tx_prod = entry; - if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) - netif_stop_queue(dev); - - spin_unlock_irqrestore(&tp->tx_lock, flags); - - dev->trans_start = jiffies; - - return 0; -} - -static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp, - int new_mtu) -{ - dev->mtu = new_mtu; - - if (new_mtu > ETH_DATA_LEN) - tp->tg3_flags |= TG3_FLAG_JUMBO_ENABLE; - else - tp->tg3_flags &= ~TG3_FLAG_JUMBO_ENABLE; -} - -static int tg3_change_mtu(struct net_device *dev, int new_mtu) -{ - struct tg3 *tp = dev->priv; - - if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp)) - return -EINVAL; - - if (!netif_running(dev)) { - /* We'll just catch it later when the - * device is up'd. - */ - tg3_set_mtu(dev, tp, new_mtu); - return 0; - } - - tg3_netif_stop(tp); - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - - tg3_halt(tp); - - tg3_set_mtu(dev, tp, new_mtu); - - tg3_init_hw(tp); - - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - tg3_netif_start(tp); - - return 0; -} - -/* Free up pending packets in all rx/tx rings. - * - * The chip has been shut down and the driver detached from - * the networking, so no interrupts or new tx packets will - * end up in the driver. tp->{tx,}lock is not held and we are not - * in an interrupt context and thus may sleep. - */ -static void tg3_free_rings(struct tg3 *tp) -{ - struct ring_info *rxp; - int i; - - for (i = 0; i < TG3_RX_RING_SIZE; i++) { - rxp = &tp->rx_std_buffers[i]; - - if (rxp->skb == NULL) - continue; - pci_unmap_single(tp->pdev, - pci_unmap_addr(rxp, mapping), - RX_PKT_BUF_SZ - tp->rx_offset, - PCI_DMA_FROMDEVICE); - dev_kfree_skb_any(rxp->skb); - rxp->skb = NULL; - } - - for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++) { - rxp = &tp->rx_jumbo_buffers[i]; - - if (rxp->skb == NULL) - continue; - pci_unmap_single(tp->pdev, - pci_unmap_addr(rxp, mapping), - RX_JUMBO_PKT_BUF_SZ - tp->rx_offset, - PCI_DMA_FROMDEVICE); - dev_kfree_skb_any(rxp->skb); - rxp->skb = NULL; - } - - for (i = 0; i < TG3_TX_RING_SIZE; ) { - struct tx_ring_info *txp; - struct sk_buff *skb; - int j; - - txp = &tp->tx_buffers[i]; - skb = txp->skb; - - if (skb == NULL) { - i++; - continue; - } - - pci_unmap_single(tp->pdev, - pci_unmap_addr(txp, mapping), - skb_headlen(skb), - PCI_DMA_TODEVICE); - txp->skb = NULL; - - i++; - - for (j = 0; j < skb_shinfo(skb)->nr_frags; j++) { - txp = &tp->tx_buffers[i & (TG3_TX_RING_SIZE - 1)]; - pci_unmap_page(tp->pdev, - pci_unmap_addr(txp, mapping), - skb_shinfo(skb)->frags[j].size, - PCI_DMA_TODEVICE); - i++; - } - - dev_kfree_skb_any(skb); - } -} - -/* Initialize tx/rx rings for packet processing. - * - * The chip has been shut down and the driver detached from - * the networking, so no interrupts or new tx packets will - * end up in the driver. tp->{tx,}lock are held and thus - * we may not sleep. - */ -static void tg3_init_rings(struct tg3 *tp) -{ - unsigned long start, end; - u32 i; - - /* Free up all the SKBs. */ - tg3_free_rings(tp); - - /* Zero out all descriptors. */ - memset(tp->rx_std, 0, TG3_RX_RING_BYTES); - memset(tp->rx_jumbo, 0, TG3_RX_JUMBO_RING_BYTES); - memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); - - if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { - memset(tp->tx_ring, 0, TG3_TX_RING_BYTES); - } else { - start = (tp->regs + - NIC_SRAM_WIN_BASE + - NIC_SRAM_TX_BUFFER_DESC); - end = start + TG3_TX_RING_BYTES; - while (start < end) { - writel(0, start); - start += 4; - } - for (i = 0; i < TG3_TX_RING_SIZE; i++) - tp->tx_buffers[i].prev_vlan_tag = 0; - } - - /* Initialize invariants of the rings, we only set this - * stuff once. This works because the card does not - * write into the rx buffer posting rings. - */ - for (i = 0; i < TG3_RX_RING_SIZE; i++) { - struct tg3_rx_buffer_desc *rxd; - - rxd = &tp->rx_std[i]; - rxd->idx_len = (RX_PKT_BUF_SZ - tp->rx_offset - 64) - << RXD_LEN_SHIFT; - rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT); - rxd->opaque = (RXD_OPAQUE_RING_STD | - (i << RXD_OPAQUE_INDEX_SHIFT)); - } - - if (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) { - for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++) { - struct tg3_rx_buffer_desc *rxd; - - rxd = &tp->rx_jumbo[i]; - rxd->idx_len = (RX_JUMBO_PKT_BUF_SZ - tp->rx_offset - 64) - << RXD_LEN_SHIFT; - rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT) | - RXD_FLAG_JUMBO; - rxd->opaque = (RXD_OPAQUE_RING_JUMBO | - (i << RXD_OPAQUE_INDEX_SHIFT)); - } - } - - /* Now allocate fresh SKBs for each rx ring. */ - for (i = 0; i < tp->rx_pending; i++) { - if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_STD, - -1, i) < 0) - break; - } - - if (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) { - for (i = 0; i < tp->rx_jumbo_pending; i++) { - if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_JUMBO, - -1, i) < 0) - break; - } - } -} - -/* - * Must not be invoked with interrupt sources disabled and - * the hardware shutdown down. - */ -static void tg3_free_consistent(struct tg3 *tp) -{ - if (tp->rx_std_buffers) { - kfree(tp->rx_std_buffers); - tp->rx_std_buffers = NULL; - } - if (tp->rx_std) { - pci_free_consistent(tp->pdev, TG3_RX_RING_BYTES, - tp->rx_std, tp->rx_std_mapping); - tp->rx_std = NULL; - } - if (tp->rx_jumbo) { - pci_free_consistent(tp->pdev, TG3_RX_JUMBO_RING_BYTES, - tp->rx_jumbo, tp->rx_jumbo_mapping); - tp->rx_jumbo = NULL; - } - if (tp->rx_rcb) { - pci_free_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES(tp), - tp->rx_rcb, tp->rx_rcb_mapping); - tp->rx_rcb = NULL; - } - if (tp->tx_ring) { - pci_free_consistent(tp->pdev, TG3_TX_RING_BYTES, - tp->tx_ring, tp->tx_desc_mapping); - tp->tx_ring = NULL; - } - if (tp->hw_status) { - pci_free_consistent(tp->pdev, TG3_HW_STATUS_SIZE, - tp->hw_status, tp->status_mapping); - tp->hw_status = NULL; - } - if (tp->hw_stats) { - pci_free_consistent(tp->pdev, sizeof(struct tg3_hw_stats), - tp->hw_stats, tp->stats_mapping); - tp->hw_stats = NULL; - } -} - -/* - * Must not be invoked with interrupt sources disabled and - * the hardware shutdown down. Can sleep. - */ -static int tg3_alloc_consistent(struct tg3 *tp) -{ - tp->rx_std_buffers = kmalloc((sizeof(struct ring_info) * - (TG3_RX_RING_SIZE + - TG3_RX_JUMBO_RING_SIZE)) + - (sizeof(struct tx_ring_info) * - TG3_TX_RING_SIZE), - GFP_KERNEL); - if (!tp->rx_std_buffers) - return -ENOMEM; - - memset(tp->rx_std_buffers, 0, - (sizeof(struct ring_info) * - (TG3_RX_RING_SIZE + - TG3_RX_JUMBO_RING_SIZE)) + - (sizeof(struct tx_ring_info) * - TG3_TX_RING_SIZE)); - - tp->rx_jumbo_buffers = &tp->rx_std_buffers[TG3_RX_RING_SIZE]; - tp->tx_buffers = (struct tx_ring_info *) - &tp->rx_jumbo_buffers[TG3_RX_JUMBO_RING_SIZE]; - - tp->rx_std = pci_alloc_consistent(tp->pdev, TG3_RX_RING_BYTES, - &tp->rx_std_mapping); - if (!tp->rx_std) - goto err_out; - - tp->rx_jumbo = pci_alloc_consistent(tp->pdev, TG3_RX_JUMBO_RING_BYTES, - &tp->rx_jumbo_mapping); - - if (!tp->rx_jumbo) - goto err_out; - - tp->rx_rcb = pci_alloc_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES(tp), - &tp->rx_rcb_mapping); - if (!tp->rx_rcb) - goto err_out; - - if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { - tp->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES, - &tp->tx_desc_mapping); - if (!tp->tx_ring) - goto err_out; - } else { - tp->tx_ring = NULL; - tp->tx_desc_mapping = 0; - } - - tp->hw_status = pci_alloc_consistent(tp->pdev, - TG3_HW_STATUS_SIZE, - &tp->status_mapping); - if (!tp->hw_status) - goto err_out; - - tp->hw_stats = pci_alloc_consistent(tp->pdev, - sizeof(struct tg3_hw_stats), - &tp->stats_mapping); - if (!tp->hw_stats) - goto err_out; - - memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); - memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats)); - - return 0; - -err_out: - tg3_free_consistent(tp); - return -ENOMEM; -} - -#define MAX_WAIT_CNT 1000 - -/* To stop a block, clear the enable bit and poll till it - * clears. tp->lock is held. - */ -static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit) -{ - unsigned int i; - u32 val; - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { - switch (ofs) { - case RCVLSC_MODE: - case DMAC_MODE: - case MBFREE_MODE: - case BUFMGR_MODE: - case MEMARB_MODE: - /* We can't enable/disable these bits of the - * 5705, just say success. - */ - return 0; - - default: - break; - }; - } - - val = tr32(ofs); - val &= ~enable_bit; - tw32(ofs, val); - tr32(ofs); - - for (i = 0; i < MAX_WAIT_CNT; i++) { - udelay(100); - val = tr32(ofs); - if ((val & enable_bit) == 0) - break; - } - - if (i == MAX_WAIT_CNT) { - printk(KERN_ERR PFX "tg3_stop_block timed out, " - "ofs=%lx enable_bit=%x\n", - ofs, enable_bit); - return -ENODEV; - } - - return 0; -} - -/* tp->lock is held. */ -static int tg3_abort_hw(struct tg3 *tp) -{ - int i, err; - - tg3_disable_ints(tp); - - tp->rx_mode &= ~RX_MODE_ENABLE; - tw32(MAC_RX_MODE, tp->rx_mode); - tr32(MAC_RX_MODE); - udelay(10); - - err = tg3_stop_block(tp, RCVBDI_MODE, RCVBDI_MODE_ENABLE); - err |= tg3_stop_block(tp, RCVLPC_MODE, RCVLPC_MODE_ENABLE); - err |= tg3_stop_block(tp, RCVLSC_MODE, RCVLSC_MODE_ENABLE); - err |= tg3_stop_block(tp, RCVDBDI_MODE, RCVDBDI_MODE_ENABLE); - err |= tg3_stop_block(tp, RCVDCC_MODE, RCVDCC_MODE_ENABLE); - err |= tg3_stop_block(tp, RCVCC_MODE, RCVCC_MODE_ENABLE); - - err |= tg3_stop_block(tp, SNDBDS_MODE, SNDBDS_MODE_ENABLE); - err |= tg3_stop_block(tp, SNDBDI_MODE, SNDBDI_MODE_ENABLE); - err |= tg3_stop_block(tp, SNDDATAI_MODE, SNDDATAI_MODE_ENABLE); - err |= tg3_stop_block(tp, RDMAC_MODE, RDMAC_MODE_ENABLE); - err |= tg3_stop_block(tp, SNDDATAC_MODE, SNDDATAC_MODE_ENABLE); - err |= tg3_stop_block(tp, DMAC_MODE, DMAC_MODE_ENABLE); - err |= tg3_stop_block(tp, SNDBDC_MODE, SNDBDC_MODE_ENABLE); - if (err) - goto out; - - tp->mac_mode &= ~MAC_MODE_TDE_ENABLE; - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); - udelay(40); - - tp->tx_mode &= ~TX_MODE_ENABLE; - tw32(MAC_TX_MODE, tp->tx_mode); - tr32(MAC_TX_MODE); - - for (i = 0; i < MAX_WAIT_CNT; i++) { - udelay(100); - if (!(tr32(MAC_TX_MODE) & TX_MODE_ENABLE)) - break; - } - if (i >= MAX_WAIT_CNT) { - printk(KERN_ERR PFX "tg3_abort_hw timed out for %s, " - "TX_MODE_ENABLE will not clear MAC_TX_MODE=%08x\n", - tp->dev->name, tr32(MAC_TX_MODE)); - return -ENODEV; - } - - err = tg3_stop_block(tp, HOSTCC_MODE, HOSTCC_MODE_ENABLE); - err |= tg3_stop_block(tp, WDMAC_MODE, WDMAC_MODE_ENABLE); - err |= tg3_stop_block(tp, MBFREE_MODE, MBFREE_MODE_ENABLE); - - tw32(FTQ_RESET, 0xffffffff); - tw32(FTQ_RESET, 0x00000000); - - err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE); - err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE); - if (err) - goto out; - - memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); - -out: - return err; -} - -/* tp->lock is held. */ -static void tg3_chip_reset(struct tg3 *tp) -{ - u32 val; - u32 flags_save; - - if (!(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) { - /* Force NVRAM to settle. - * This deals with a chip bug which can result in EEPROM - * corruption. - */ - if (tp->tg3_flags & TG3_FLAG_NVRAM) { - int i; - - tw32(NVRAM_SWARB, SWARB_REQ_SET1); - for (i = 0; i < 100000; i++) { - if (tr32(NVRAM_SWARB) & SWARB_GNT1) - break; - udelay(10); - } - } - } - - /* - * We must avoid the readl() that normally takes place. - * It locks machines, causes machine checks, and other - * fun things. So, temporarily disable the 5701 - * hardware workaround, while we do the reset. - */ - flags_save = tp->tg3_flags; - tp->tg3_flags &= ~TG3_FLAG_5701_REG_WRITE_BUG; - - /* do the reset */ - val = GRC_MISC_CFG_CORECLK_RESET; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) - val |= GRC_MISC_CFG_KEEP_GPHY_POWER; - tw32(GRC_MISC_CFG, val); - - /* restore 5701 hardware bug workaround flag */ - tp->tg3_flags = flags_save; - - /* Flush PCI posted writes. The normal MMIO registers - * are inaccessible at this time so this is the only - * way to make this reliably. I tried to use indirect - * register read/write but this upset some 5701 variants. - */ - pci_read_config_dword(tp->pdev, PCI_COMMAND, &val); - - udelay(40); - udelay(40); - udelay(40); - - /* Re-enable indirect register accesses. */ - pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, - tp->misc_host_ctrl); - - /* Set MAX PCI retry to zero. */ - val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE); - if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && - (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) - val |= PCISTATE_RETRY_SAME_DMA; - pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val); - - pci_restore_state(tp->pdev, tp->pci_cfg_state); - - /* Make sure PCI-X relaxed ordering bit is clear. */ - pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val); - val &= ~PCIX_CAPS_RELAXED_ORDERING; - pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val); - - tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); - - if ((tp->nic_sram_data_cfg & NIC_SRAM_DATA_CFG_MINI_PCI) != 0 && - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { - tp->pci_clock_ctrl |= - (CLOCK_CTRL_FORCE_CLKRUN | CLOCK_CTRL_CLKRUN_OENABLE); - tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); - } - - tw32(TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl); -} - -/* tp->lock is held. */ -static void tg3_stop_fw(struct tg3 *tp) -{ - if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { - u32 val; - int i; - - tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW); - val = tr32(GRC_RX_CPU_EVENT); - val |= (1 << 14); - tw32(GRC_RX_CPU_EVENT, val); - - /* Wait for RX cpu to ACK the event. */ - for (i = 0; i < 100; i++) { - if (!(tr32(GRC_RX_CPU_EVENT) & (1 << 14))) - break; - udelay(1); - } - } -} - -/* tp->lock is held. */ -static int tg3_halt(struct tg3 *tp) -{ - u32 val; - int i; - - tg3_stop_fw(tp); - tg3_abort_hw(tp); - tg3_chip_reset(tp); - tg3_write_mem(tp, - NIC_SRAM_FIRMWARE_MBOX, - NIC_SRAM_FIRMWARE_MBOX_MAGIC1); - for (i = 0; i < 100000; i++) { - tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val); - if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1) - break; - udelay(10); - } - - if (i >= 100000 && - !(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) { - printk(KERN_ERR PFX "tg3_halt timed out for %s, " - "firmware will not restart magic=%08x\n", - tp->dev->name, val); - return -ENODEV; - } - - if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { - if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) - tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX, - DRV_STATE_WOL); - else - tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX, - DRV_STATE_UNLOAD); - } else - tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX, - DRV_STATE_SUSPEND); - - return 0; -} - -#define TG3_FW_RELEASE_MAJOR 0x0 -#define TG3_FW_RELASE_MINOR 0x0 -#define TG3_FW_RELEASE_FIX 0x0 -#define TG3_FW_START_ADDR 0x08000000 -#define TG3_FW_TEXT_ADDR 0x08000000 -#define TG3_FW_TEXT_LEN 0x9c0 -#define TG3_FW_RODATA_ADDR 0x080009c0 -#define TG3_FW_RODATA_LEN 0x60 -#define TG3_FW_DATA_ADDR 0x08000a40 -#define TG3_FW_DATA_LEN 0x20 -#define TG3_FW_SBSS_ADDR 0x08000a60 -#define TG3_FW_SBSS_LEN 0xc -#define TG3_FW_BSS_ADDR 0x08000a70 -#define TG3_FW_BSS_LEN 0x10 - -static u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = { - 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0800, - 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100000, 0x0e000018, 0x00000000, - 0x0000000d, 0x3c1d0800, 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100034, - 0x0e00021c, 0x00000000, 0x0000000d, 0x00000000, 0x00000000, 0x00000000, - 0x27bdffe0, 0x3c1cc000, 0xafbf0018, 0xaf80680c, 0x0e00004c, 0x241b2105, - 0x97850000, 0x97870002, 0x9782002c, 0x9783002e, 0x3c040800, 0x248409c0, - 0xafa00014, 0x00021400, 0x00621825, 0x00052c00, 0xafa30010, 0x8f860010, - 0x00e52825, 0x0e000060, 0x24070102, 0x3c02ac00, 0x34420100, 0x3c03ac01, - 0x34630100, 0xaf820490, 0x3c02ffff, 0xaf820494, 0xaf830498, 0xaf82049c, - 0x24020001, 0xaf825ce0, 0x0e00003f, 0xaf825d00, 0x0e000140, 0x00000000, - 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x2402ffff, 0xaf825404, 0x8f835400, - 0x34630400, 0xaf835400, 0xaf825404, 0x3c020800, 0x24420034, 0xaf82541c, - 0x03e00008, 0xaf805400, 0x00000000, 0x00000000, 0x3c020800, 0x34423000, - 0x3c030800, 0x34633000, 0x3c040800, 0x348437ff, 0x3c010800, 0xac220a64, - 0x24020040, 0x3c010800, 0xac220a68, 0x3c010800, 0xac200a60, 0xac600000, - 0x24630004, 0x0083102b, 0x5040fffd, 0xac600000, 0x03e00008, 0x00000000, - 0x00804821, 0x8faa0010, 0x3c020800, 0x8c420a60, 0x3c040800, 0x8c840a68, - 0x8fab0014, 0x24430001, 0x0044102b, 0x3c010800, 0xac230a60, 0x14400003, - 0x00004021, 0x3c010800, 0xac200a60, 0x3c020800, 0x8c420a60, 0x3c030800, - 0x8c630a64, 0x91240000, 0x00021140, 0x00431021, 0x00481021, 0x25080001, - 0xa0440000, 0x29020008, 0x1440fff4, 0x25290001, 0x3c020800, 0x8c420a60, - 0x3c030800, 0x8c630a64, 0x8f84680c, 0x00021140, 0x00431021, 0xac440008, - 0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0x02000008, 0x00000000, 0x0a0001e3, 0x3c0a0001, 0x0a0001e3, 0x3c0a0002, - 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, - 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, - 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, - 0x0a0001e3, 0x3c0a0007, 0x0a0001e3, 0x3c0a0008, 0x0a0001e3, 0x3c0a0009, - 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x3c0a000b, - 0x0a0001e3, 0x3c0a000c, 0x0a0001e3, 0x3c0a000d, 0x0a0001e3, 0x00000000, - 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x3c0a000e, 0x0a0001e3, 0x00000000, - 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, - 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, - 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x3c0a0013, 0x0a0001e3, 0x3c0a0014, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0x27bdffe0, 0x00001821, 0x00001021, 0xafbf0018, 0xafb10014, 0xafb00010, - 0x3c010800, 0x00220821, 0xac200a70, 0x3c010800, 0x00220821, 0xac200a74, - 0x3c010800, 0x00220821, 0xac200a78, 0x24630001, 0x1860fff5, 0x2442000c, - 0x24110001, 0x8f906810, 0x32020004, 0x14400005, 0x24040001, 0x3c020800, - 0x8c420a78, 0x18400003, 0x00002021, 0x0e000182, 0x00000000, 0x32020001, - 0x10400003, 0x00000000, 0x0e000169, 0x00000000, 0x0a000153, 0xaf915028, - 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3c050800, - 0x8ca50a70, 0x3c060800, 0x8cc60a80, 0x3c070800, 0x8ce70a78, 0x27bdffe0, - 0x3c040800, 0x248409d0, 0xafbf0018, 0xafa00010, 0x0e000060, 0xafa00014, - 0x0e00017b, 0x00002021, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x24020001, - 0x8f836810, 0x00821004, 0x00021027, 0x00621824, 0x03e00008, 0xaf836810, - 0x27bdffd8, 0xafbf0024, 0x1080002e, 0xafb00020, 0x8f825cec, 0xafa20018, - 0x8f825cec, 0x3c100800, 0x26100a78, 0xafa2001c, 0x34028000, 0xaf825cec, - 0x8e020000, 0x18400016, 0x00000000, 0x3c020800, 0x94420a74, 0x8fa3001c, - 0x000221c0, 0xac830004, 0x8fa2001c, 0x3c010800, 0x0e000201, 0xac220a74, - 0x10400005, 0x00000000, 0x8e020000, 0x24420001, 0x0a0001df, 0xae020000, - 0x3c020800, 0x8c420a70, 0x00021c02, 0x000321c0, 0x0a0001c5, 0xafa2001c, - 0x0e000201, 0x00000000, 0x1040001f, 0x00000000, 0x8e020000, 0x8fa3001c, - 0x24420001, 0x3c010800, 0xac230a70, 0x3c010800, 0xac230a74, 0x0a0001df, - 0xae020000, 0x3c100800, 0x26100a78, 0x8e020000, 0x18400028, 0x00000000, - 0x0e000201, 0x00000000, 0x14400024, 0x00000000, 0x8e020000, 0x3c030800, - 0x8c630a70, 0x2442ffff, 0xafa3001c, 0x18400006, 0xae020000, 0x00031402, - 0x000221c0, 0x8c820004, 0x3c010800, 0xac220a70, 0x97a2001e, 0x2442ff00, - 0x2c420300, 0x1440000b, 0x24024000, 0x3c040800, 0x248409dc, 0xafa00010, - 0xafa00014, 0x8fa6001c, 0x24050008, 0x0e000060, 0x00003821, 0x0a0001df, - 0x00000000, 0xaf825cf8, 0x3c020800, 0x8c420a40, 0x8fa3001c, 0x24420001, - 0xaf835cf8, 0x3c010800, 0xac220a40, 0x8fbf0024, 0x8fb00020, 0x03e00008, - 0x27bd0028, 0x27bdffe0, 0x3c040800, 0x248409e8, 0x00002821, 0x00003021, - 0x00003821, 0xafbf0018, 0xafa00010, 0x0e000060, 0xafa00014, 0x8fbf0018, - 0x03e00008, 0x27bd0020, 0x8f82680c, 0x8f85680c, 0x00021827, 0x0003182b, - 0x00031823, 0x00431024, 0x00441021, 0x00a2282b, 0x10a00006, 0x00000000, - 0x00401821, 0x8f82680c, 0x0043102b, 0x1440fffd, 0x00000000, 0x03e00008, - 0x00000000, 0x3c040800, 0x8c840000, 0x3c030800, 0x8c630a40, 0x0064102b, - 0x54400002, 0x00831023, 0x00641023, 0x2c420008, 0x03e00008, 0x38420001, - 0x27bdffe0, 0x00802821, 0x3c040800, 0x24840a00, 0x00003021, 0x00003821, - 0xafbf0018, 0xafa00010, 0x0e000060, 0xafa00014, 0x0a000216, 0x00000000, - 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x00000000, 0x27bdffe0, 0x3c1cc000, - 0xafbf0018, 0x0e00004c, 0xaf80680c, 0x3c040800, 0x24840a10, 0x03802821, - 0x00003021, 0x00003821, 0xafa00010, 0x0e000060, 0xafa00014, 0x2402ffff, - 0xaf825404, 0x3c0200aa, 0x0e000234, 0xaf825434, 0x8fbf0018, 0x03e00008, - 0x27bd0020, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe8, 0xafb00010, - 0x24100001, 0xafbf0014, 0x3c01c003, 0xac200000, 0x8f826810, 0x30422000, - 0x10400003, 0x00000000, 0x0e000246, 0x00000000, 0x0a00023a, 0xaf905428, - 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdfff8, 0x8f845d0c, - 0x3c0200ff, 0x3c030800, 0x8c630a50, 0x3442fff8, 0x00821024, 0x1043001e, - 0x3c0500ff, 0x34a5fff8, 0x3c06c003, 0x3c074000, 0x00851824, 0x8c620010, - 0x3c010800, 0xac230a50, 0x30420008, 0x10400005, 0x00871025, 0x8cc20000, - 0x24420001, 0xacc20000, 0x00871025, 0xaf825d0c, 0x8fa20000, 0x24420001, - 0xafa20000, 0x8fa20000, 0x8fa20000, 0x24420001, 0xafa20000, 0x8fa20000, - 0x8f845d0c, 0x3c030800, 0x8c630a50, 0x00851024, 0x1443ffe8, 0x00851824, - 0x27bd0008, 0x03e00008, 0x00000000, 0x00000000, 0x00000000 -}; - -static u32 tg3FwRodata[(TG3_FW_RODATA_LEN / sizeof(u32)) + 1] = { - 0x35373031, 0x726c7341, 0x00000000, 0x00000000, 0x53774576, 0x656e7430, - 0x00000000, 0x726c7045, 0x76656e74, 0x31000000, 0x556e6b6e, 0x45766e74, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x66617461, 0x6c457272, - 0x00000000, 0x00000000, 0x4d61696e, 0x43707542, 0x00000000, 0x00000000, - 0x00000000 -}; - -#if 0 /* All zeros, don't eat up space with it. */ -u32 tg3FwData[(TG3_FW_DATA_LEN / sizeof(u32)) + 1] = { - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000 -}; -#endif - -#define RX_CPU_SCRATCH_BASE 0x30000 -#define RX_CPU_SCRATCH_SIZE 0x04000 -#define TX_CPU_SCRATCH_BASE 0x34000 -#define TX_CPU_SCRATCH_SIZE 0x04000 - -/* tp->lock is held. */ -static int tg3_halt_cpu(struct tg3 *tp, u32 offset) -{ - int i; - - if (offset == TX_CPU_BASE && - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) - BUG(); - - if (offset == RX_CPU_BASE) { - for (i = 0; i < 10000; i++) { - tw32(offset + CPU_STATE, 0xffffffff); - tw32(offset + CPU_MODE, CPU_MODE_HALT); - if (tr32(offset + CPU_MODE) & CPU_MODE_HALT) - break; - } - - tw32(offset + CPU_STATE, 0xffffffff); - tw32(offset + CPU_MODE, CPU_MODE_HALT); - tr32(offset + CPU_MODE); - udelay(10); - } else { - for (i = 0; i < 10000; i++) { - tw32(offset + CPU_STATE, 0xffffffff); - tw32(offset + CPU_MODE, CPU_MODE_HALT); - if (tr32(offset + CPU_MODE) & CPU_MODE_HALT) - break; - } - } - - if (i >= 10000) { - printk(KERN_ERR PFX "tg3_reset_cpu timed out for %s, " - "and %s CPU\n", - tp->dev->name, - (offset == RX_CPU_BASE ? "RX" : "TX")); - return -ENODEV; - } - return 0; -} - -struct fw_info { - unsigned int text_base; - unsigned int text_len; - u32 *text_data; - unsigned int rodata_base; - unsigned int rodata_len; - u32 *rodata_data; - unsigned int data_base; - unsigned int data_len; - u32 *data_data; -}; - -/* tp->lock is held. */ -static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_base, - int cpu_scratch_size, struct fw_info *info) -{ - int err, i; - u32 orig_tg3_flags = tp->tg3_flags; - void (*write_op)(struct tg3 *, u32, u32); - - if (cpu_base == TX_CPU_BASE && - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { - printk(KERN_ERR PFX "tg3_load_firmware_cpu: Trying to load " - "TX cpu firmware on %s which is 5705.\n", - tp->dev->name); - return -EINVAL; - } - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) - write_op = tg3_write_mem; - else - write_op = tg3_write_indirect_reg32; - - /* Force use of PCI config space for indirect register - * write calls. - */ - tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG; - - err = tg3_halt_cpu(tp, cpu_base); - if (err) - goto out; - - for (i = 0; i < cpu_scratch_size; i += sizeof(u32)) - write_op(tp, cpu_scratch_base + i, 0); - tw32(cpu_base + CPU_STATE, 0xffffffff); - tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT); - for (i = 0; i < (info->text_len / sizeof(u32)); i++) - write_op(tp, (cpu_scratch_base + - (info->text_base & 0xffff) + - (i * sizeof(u32))), - (info->text_data ? - info->text_data[i] : 0)); - for (i = 0; i < (info->rodata_len / sizeof(u32)); i++) - write_op(tp, (cpu_scratch_base + - (info->rodata_base & 0xffff) + - (i * sizeof(u32))), - (info->rodata_data ? - info->rodata_data[i] : 0)); - for (i = 0; i < (info->data_len / sizeof(u32)); i++) - write_op(tp, (cpu_scratch_base + - (info->data_base & 0xffff) + - (i * sizeof(u32))), - (info->data_data ? - info->data_data[i] : 0)); - - err = 0; - -out: - tp->tg3_flags = orig_tg3_flags; - return err; -} - -/* tp->lock is held. */ -static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp) -{ - struct fw_info info; - int err, i; - - info.text_base = TG3_FW_TEXT_ADDR; - info.text_len = TG3_FW_TEXT_LEN; - info.text_data = &tg3FwText[0]; - info.rodata_base = TG3_FW_RODATA_ADDR; - info.rodata_len = TG3_FW_RODATA_LEN; - info.rodata_data = &tg3FwRodata[0]; - info.data_base = TG3_FW_DATA_ADDR; - info.data_len = TG3_FW_DATA_LEN; - info.data_data = NULL; - - err = tg3_load_firmware_cpu(tp, RX_CPU_BASE, - RX_CPU_SCRATCH_BASE, RX_CPU_SCRATCH_SIZE, - &info); - if (err) - return err; - - err = tg3_load_firmware_cpu(tp, TX_CPU_BASE, - TX_CPU_SCRATCH_BASE, TX_CPU_SCRATCH_SIZE, - &info); - if (err) - return err; - - /* Now startup only the RX cpu. */ - tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff); - tw32(RX_CPU_BASE + CPU_PC, TG3_FW_TEXT_ADDR); - - /* Flush posted writes. */ - tr32(RX_CPU_BASE + CPU_PC); - for (i = 0; i < 5; i++) { - if (tr32(RX_CPU_BASE + CPU_PC) == TG3_FW_TEXT_ADDR) - break; - tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff); - tw32(RX_CPU_BASE + CPU_MODE, CPU_MODE_HALT); - tw32(RX_CPU_BASE + CPU_PC, TG3_FW_TEXT_ADDR); - - /* Flush posted writes. */ - tr32(RX_CPU_BASE + CPU_PC); - - udelay(1000); - } - if (i >= 5) { - printk(KERN_ERR PFX "tg3_load_firmware fails for %s " - "to set RX CPU PC, is %08x should be %08x\n", - tp->dev->name, tr32(RX_CPU_BASE + CPU_PC), - TG3_FW_TEXT_ADDR); - return -ENODEV; - } - tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff); - tw32(RX_CPU_BASE + CPU_MODE, 0x00000000); - - /* Flush posted writes. */ - tr32(RX_CPU_BASE + CPU_MODE); - - return 0; -} - -#if TG3_TSO_SUPPORT != 0 - -#define TG3_TSO_FW_RELEASE_MAJOR 0x1 -#define TG3_TSO_FW_RELASE_MINOR 0x3 -#define TG3_TSO_FW_RELEASE_FIX 0x0 -#define TG3_TSO_FW_START_ADDR 0x08000000 -#define TG3_TSO_FW_TEXT_ADDR 0x08000000 -#define TG3_TSO_FW_TEXT_LEN 0x1ac0 -#define TG3_TSO_FW_RODATA_ADDR 0x08001650 -#define TG3_TSO_FW_RODATA_LEN 0x60 -#define TG3_TSO_FW_DATA_ADDR 0x080016a0 -#define TG3_TSO_FW_DATA_LEN 0x20 -#define TG3_TSO_FW_SBSS_ADDR 0x080016c0 -#define TG3_TSO_FW_SBSS_LEN 0x2c -#define TG3_TSO_FW_BSS_ADDR 0x080016e0 -#define TG3_TSO_FW_BSS_LEN 0x890 - -static u32 tg3TsoFwText[] = { - 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0800, - 0x37bd4000, 0x03a0f021, 0x3c100800, 0x26100000, 0x0e000010, 0x00000000, - 0x0000000d, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe0, 0x3c04fefe, - 0xafbf0018, 0x0e0005e0, 0x34840002, 0x0e000670, 0x00000000, 0x3c030800, - 0x90631b78, 0x24020002, 0x3c040800, 0x24841acc, 0x14620003, 0x24050001, - 0x3c040800, 0x24841ac0, 0x24060002, 0x00003821, 0xafa00010, 0x0e000684, - 0xafa00014, 0x8f625c50, 0x34420001, 0xaf625c50, 0x8f625c90, 0x34420001, - 0xaf625c90, 0x2402ffff, 0x0e000034, 0xaf625404, 0x8fbf0018, 0x03e00008, - 0x27bd0020, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe0, 0xafbf0018, - 0xafb10014, 0x0e000052, 0xafb00010, 0x24110001, 0x8f706820, 0x32020100, - 0x10400003, 0x00000000, 0x0e0000b2, 0x00000000, 0x8f706820, 0x32022000, - 0x10400004, 0x32020001, 0x0e0001e3, 0x24040001, 0x32020001, 0x10400003, - 0x00000000, 0x0e00009a, 0x00000000, 0x0a00003a, 0xaf715028, 0x8fbf0018, - 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe0, 0x3c040800, - 0x24841ae0, 0x00002821, 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, - 0x0e000684, 0xafa00014, 0x3c040800, 0x248423e8, 0xa4800000, 0x3c010800, - 0xa0201ba8, 0x3c010800, 0xac201bac, 0x3c010800, 0xac201bb0, 0x3c010800, - 0xac201bb4, 0x3c010800, 0xac201bbc, 0x3c010800, 0xac201bc8, 0x3c010800, - 0xac201bcc, 0x8f624434, 0x3c010800, 0xac221b98, 0x8f624438, 0x3c010800, - 0xac221b9c, 0x8f624410, 0xac80f7a8, 0x3c010800, 0xac201b94, 0x3c010800, - 0xac2023f0, 0x3c010800, 0xac2023d8, 0x3c010800, 0xac2023dc, 0x3c010800, - 0xac202410, 0x3c010800, 0xac221ba0, 0x8f620068, 0x24030007, 0x00021702, - 0x10430005, 0x00000000, 0x8f620068, 0x00021702, 0x14400004, 0x24020001, - 0x3c010800, 0x0a00008e, 0xac20241c, 0xac820034, 0x3c040800, 0x24841aec, - 0x3c050800, 0x8ca5241c, 0x00003021, 0x00003821, 0xafa00010, 0x0e000684, - 0xafa00014, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x27bdffe0, 0x3c040800, - 0x24841af8, 0x00002821, 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, - 0x0e000684, 0xafa00014, 0x0e000052, 0x00000000, 0x0e0000ab, 0x00002021, - 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x24020001, 0x8f636820, 0x00821004, - 0x00021027, 0x00621824, 0x03e00008, 0xaf636820, 0x27bdffd0, 0xafbf002c, - 0xafb60028, 0xafb50024, 0xafb40020, 0xafb3001c, 0xafb20018, 0xafb10014, - 0xafb00010, 0x8f665c5c, 0x3c030800, 0x24631bcc, 0x8c620000, 0x14460005, - 0x3c0200ff, 0x3c020800, 0x90421ba8, 0x14400115, 0x3c0200ff, 0x3442fff8, - 0x00c28824, 0xac660000, 0x00111902, 0x306300ff, 0x30c20003, 0x000211c0, - 0x00623825, 0x00e02821, 0x00061602, 0x3c030800, 0x90631ba8, 0x3044000f, - 0x1460002b, 0x00804021, 0x24020001, 0x3c010800, 0xa0221ba8, 0x00071100, - 0x00821025, 0x3c010800, 0xac201bac, 0x3c010800, 0xac201bb0, 0x3c010800, - 0xac201bb4, 0x3c010800, 0xac201bbc, 0x3c010800, 0xac201bc8, 0x3c010800, - 0xac201bc0, 0x3c010800, 0xac201bc4, 0x3c010800, 0xa42223e8, 0x9623000c, - 0x30628000, 0x10400008, 0x30627fff, 0x2442003e, 0x3c010800, 0xa4221ba6, - 0x24020001, 0x3c010800, 0x0a0000f9, 0xac222404, 0x24620036, 0x3c010800, - 0xa4221ba6, 0x3c010800, 0xac202404, 0x3c010800, 0xac202400, 0x3c010800, - 0x0a000101, 0xac202408, 0x9622000c, 0x3c010800, 0xa42223fc, 0x3c040800, - 0x24841bac, 0x8c820000, 0x00021100, 0x3c010800, 0x00220821, 0xac311bd8, - 0x8c820000, 0x00021100, 0x3c010800, 0x00220821, 0xac261bdc, 0x8c820000, - 0x24a30001, 0x306701ff, 0x00021100, 0x3c010800, 0x00220821, 0xac271be0, - 0x8c820000, 0x00021100, 0x3c010800, 0x00220821, 0xac281be4, 0x96230008, - 0x3c020800, 0x8c421bbc, 0x00432821, 0x3c010800, 0xac251bbc, 0x9622000a, - 0x30420004, 0x14400018, 0x00071100, 0x8f630c14, 0x3063000f, 0x2c620002, - 0x1440000b, 0x3c02c000, 0x8f630c14, 0x3c020800, 0x8c421b50, 0x3063000f, - 0x24420001, 0x3c010800, 0xac221b50, 0x2c620002, 0x1040fff7, 0x3c02c000, - 0x00c21825, 0xaf635c5c, 0x8f625c50, 0x30420002, 0x10400014, 0x00000000, - 0x0a000133, 0x00000000, 0x3c030800, 0x8c631b90, 0x3c040800, 0x94841ba4, - 0x01021025, 0x3c010800, 0xa42223ea, 0x24020001, 0x3c010800, 0xac221bc8, - 0x24630001, 0x0085202a, 0x3c010800, 0x10800003, 0xac231b90, 0x3c010800, - 0xa4251ba4, 0x3c060800, 0x24c61bac, 0x8cc20000, 0x24420001, 0xacc20000, - 0x28420080, 0x14400005, 0x00000000, 0x0e00065e, 0x24040002, 0x0a0001d9, - 0x00000000, 0x3c020800, 0x8c421bc8, 0x1040007f, 0x24020001, 0x3c040800, - 0x90841ba8, 0x14820077, 0x24020003, 0x3c150800, 0x96b51ba6, 0x3c050800, - 0x8ca51bbc, 0x32a3ffff, 0x00a3102a, 0x14400073, 0x00000000, 0x14a30003, - 0x00000000, 0x3c010800, 0xac242400, 0x10600061, 0x00009021, 0x24d60004, - 0x0060a021, 0x24d30014, 0x8ec20000, 0x00028100, 0x3c110800, 0x02308821, - 0x0e00062d, 0x8e311bd8, 0x00403021, 0x10c00059, 0x00000000, 0x9628000a, - 0x31020040, 0x10400004, 0x2407180c, 0x8e22000c, 0x2407188c, 0xacc20018, - 0x31021000, 0x10400004, 0x34e32000, 0x00081040, 0x3042c000, 0x00623825, - 0x3c030800, 0x00701821, 0x8c631be0, 0x3c020800, 0x00501021, 0x8c421be4, - 0x00031d00, 0x00021400, 0x00621825, 0xacc30014, 0x8ec30004, 0x96220008, - 0x00432023, 0x3242ffff, 0x3083ffff, 0x00431021, 0x0282102a, 0x14400002, - 0x02b22823, 0x00802821, 0x8e620000, 0x30a4ffff, 0x00441021, 0xae620000, - 0x8e220000, 0xacc20000, 0x8e220004, 0x8e63fff4, 0x00431021, 0xacc20004, - 0xa4c5000e, 0x8e62fff4, 0x00441021, 0xae62fff4, 0x96230008, 0x0043102a, - 0x14400005, 0x02459021, 0x8e62fff0, 0xae60fff4, 0x24420001, 0xae62fff0, - 0xacc00008, 0x3242ffff, 0x14540008, 0x24020305, 0x31020080, 0x54400001, - 0x34e70010, 0x24020905, 0xa4c2000c, 0x0a0001bc, 0x34e70020, 0xa4c2000c, - 0x3c020800, 0x8c422400, 0x10400003, 0x3c024b65, 0x0a0001c4, 0x34427654, - 0x3c02b49a, 0x344289ab, 0xacc2001c, 0x30e2ffff, 0xacc20010, 0x0e0005aa, - 0x00c02021, 0x3242ffff, 0x0054102b, 0x1440ffa4, 0x00000000, 0x24020002, - 0x3c010800, 0x0a0001d9, 0xa0221ba8, 0x8ec2083c, 0x24420001, 0x0a0001d9, - 0xaec2083c, 0x14820003, 0x00000000, 0x0e0004b9, 0x00000000, 0x8fbf002c, - 0x8fb60028, 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, - 0x8fb00010, 0x03e00008, 0x27bd0030, 0x27bdffd0, 0xafbf0028, 0xafb30024, - 0xafb20020, 0xafb1001c, 0xafb00018, 0x8f725c9c, 0x3c0200ff, 0x3442fff8, - 0x3c060800, 0x24c61bc4, 0x02428824, 0x9623000e, 0x8cc20000, 0x00431021, - 0xacc20000, 0x8e220010, 0x30420020, 0x14400011, 0x00809821, 0x0e000643, - 0x02202021, 0x3c02c000, 0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002, - 0x10400121, 0x00000000, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x1040011c, - 0x00000000, 0x0a000200, 0x00000000, 0x8e240008, 0x8e230014, 0x00041402, - 0x000241c0, 0x00031502, 0x304201ff, 0x2442ffff, 0x3042007f, 0x00031942, - 0x30637800, 0x00021100, 0x24424000, 0x00625021, 0x9542000a, 0x3084ffff, - 0x30420008, 0x104000b3, 0x000429c0, 0x3c020800, 0x8c422410, 0x1440002d, - 0x25050008, 0x95020014, 0x3c010800, 0xa42223e0, 0x8d070010, 0x00071402, - 0x3c010800, 0xa42223e2, 0x3c010800, 0xa42723e4, 0x9502000e, 0x30e3ffff, - 0x00431023, 0x3c010800, 0xac222418, 0x8f626800, 0x3c030010, 0x00431024, - 0x10400005, 0x00000000, 0x9503001a, 0x9502001c, 0x0a000235, 0x00431021, - 0x9502001a, 0x3c010800, 0xac22240c, 0x3c02c000, 0x02421825, 0x3c010800, - 0xac282410, 0x3c010800, 0xac322414, 0xaf635c9c, 0x8f625c90, 0x30420002, - 0x104000df, 0x00000000, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x104000da, - 0x00000000, 0x0a000242, 0x00000000, 0x9502000e, 0x3c030800, 0x946323e4, - 0x00434823, 0x3123ffff, 0x2c620008, 0x1040001c, 0x00000000, 0x95020014, - 0x24420028, 0x00a22821, 0x00031042, 0x1840000b, 0x00002021, 0x24c60848, - 0x00403821, 0x94a30000, 0x8cc20000, 0x24840001, 0x00431021, 0xacc20000, - 0x0087102a, 0x1440fff9, 0x24a50002, 0x31220001, 0x1040001f, 0x3c024000, - 0x3c040800, 0x2484240c, 0xa0a00001, 0x94a30000, 0x8c820000, 0x00431021, - 0x0a000281, 0xac820000, 0x8f626800, 0x3c030010, 0x00431024, 0x10400009, - 0x00000000, 0x9502001a, 0x3c030800, 0x8c63240c, 0x00431021, 0x3c010800, - 0xac22240c, 0x0a000282, 0x3c024000, 0x9502001a, 0x9504001c, 0x3c030800, - 0x8c63240c, 0x00441023, 0x00621821, 0x3c010800, 0xac23240c, 0x3c024000, - 0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x1440fffc, 0x00000000, - 0x9542000a, 0x30420010, 0x10400095, 0x00000000, 0x3c060800, 0x24c62410, - 0x3c020800, 0x944223e4, 0x8cc50000, 0x3c040800, 0x8c842418, 0x24420030, - 0x00a22821, 0x94a20004, 0x3c030800, 0x8c63240c, 0x00441023, 0x00621821, - 0x00603821, 0x00032402, 0x30e2ffff, 0x00823821, 0x00071402, 0x00e23821, - 0x00071027, 0x3c010800, 0xac23240c, 0xa4a20006, 0x3c030800, 0x8c632414, - 0x3c0200ff, 0x3442fff8, 0x00628824, 0x96220008, 0x24040001, 0x24034000, - 0x000241c0, 0x00e01021, 0xa502001a, 0xa500001c, 0xacc00000, 0x3c010800, - 0xac241b70, 0xaf635cb8, 0x8f625cb0, 0x30420002, 0x10400003, 0x00000000, - 0x3c010800, 0xac201b70, 0x8e220008, 0xaf625cb8, 0x8f625cb0, 0x30420002, - 0x10400003, 0x00000000, 0x3c010800, 0xac201b70, 0x3c020800, 0x8c421b70, - 0x1040ffec, 0x00000000, 0x3c040800, 0x0e000643, 0x8c842414, 0x0a000320, - 0x00000000, 0x3c030800, 0x90631ba8, 0x24020002, 0x14620003, 0x3c034b65, - 0x0a0002d7, 0x00008021, 0x8e22001c, 0x34637654, 0x10430002, 0x24100002, - 0x24100001, 0x01002021, 0x0e000346, 0x02003021, 0x24020003, 0x3c010800, - 0xa0221ba8, 0x24020002, 0x1202000a, 0x24020001, 0x3c030800, 0x8c632400, - 0x10620006, 0x00000000, 0x3c020800, 0x944223e8, 0x00021400, 0x0a000315, - 0xae220014, 0x3c040800, 0x248423ea, 0x94820000, 0x00021400, 0xae220014, - 0x3c020800, 0x8c421bcc, 0x3c03c000, 0x3c010800, 0xa0201ba8, 0x00431025, - 0xaf625c5c, 0x8f625c50, 0x30420002, 0x10400009, 0x00000000, 0x2484f7e2, - 0x8c820000, 0x00431025, 0xaf625c5c, 0x8f625c50, 0x30420002, 0x1440fffa, - 0x00000000, 0x3c020800, 0x24421b94, 0x8c430000, 0x24630001, 0xac430000, - 0x8f630c14, 0x3063000f, 0x2c620002, 0x1440000c, 0x3c024000, 0x8f630c14, - 0x3c020800, 0x8c421b50, 0x3063000f, 0x24420001, 0x3c010800, 0xac221b50, - 0x2c620002, 0x1040fff7, 0x00000000, 0x3c024000, 0x02421825, 0xaf635c9c, - 0x8f625c90, 0x30420002, 0x1440fffc, 0x00000000, 0x12600003, 0x00000000, - 0x0e0004b9, 0x00000000, 0x8fbf0028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, - 0x8fb00018, 0x03e00008, 0x27bd0030, 0x8f634450, 0x3c040800, 0x24841b98, - 0x8c820000, 0x00031c02, 0x0043102b, 0x14400007, 0x3c038000, 0x8c840004, - 0x8f624450, 0x00021c02, 0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444, - 0x8f624444, 0x00431024, 0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008, - 0x3042ffff, 0x3c024000, 0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002, - 0x1440fffc, 0x00000000, 0x03e00008, 0x00000000, 0x27bdffe0, 0x00805821, - 0x14c00017, 0x256e0008, 0x3c020800, 0x8c422404, 0x1040000a, 0x2402003e, - 0x3c010800, 0xa42223e0, 0x24020016, 0x3c010800, 0xa42223e2, 0x2402002a, - 0x3c010800, 0x0a000360, 0xa42223e4, 0x95620014, 0x3c010800, 0xa42223e0, - 0x8d670010, 0x00071402, 0x3c010800, 0xa42223e2, 0x3c010800, 0xa42723e4, - 0x3c040800, 0x948423e4, 0x3c030800, 0x946323e2, 0x95cf0006, 0x3c020800, - 0x944223e0, 0x00832023, 0x01e2c023, 0x3065ffff, 0x24a20028, 0x01c24821, - 0x3082ffff, 0x14c0001a, 0x01226021, 0x9582000c, 0x3042003f, 0x3c010800, - 0xa42223e6, 0x95820004, 0x95830006, 0x3c010800, 0xac2023f4, 0x3c010800, - 0xac2023f8, 0x00021400, 0x00431025, 0x3c010800, 0xac221bd0, 0x95220004, - 0x3c010800, 0xa4221bd4, 0x95230002, 0x01e51023, 0x0043102a, 0x10400010, - 0x24020001, 0x3c010800, 0x0a000394, 0xac222408, 0x3c030800, 0x8c6323f8, - 0x3c020800, 0x94421bd4, 0x00431021, 0xa5220004, 0x3c020800, 0x94421bd0, - 0xa5820004, 0x3c020800, 0x8c421bd0, 0xa5820006, 0x3c020800, 0x8c422400, - 0x3c0d0800, 0x8dad23f4, 0x3c0a0800, 0x144000e5, 0x8d4a23f8, 0x3c020800, - 0x94421bd4, 0x004a1821, 0x3063ffff, 0x0062182b, 0x24020002, 0x10c2000d, - 0x01435023, 0x3c020800, 0x944223e6, 0x30420009, 0x10400008, 0x00000000, - 0x9582000c, 0x3042fff6, 0xa582000c, 0x3c020800, 0x944223e6, 0x30420009, - 0x01a26823, 0x3c020800, 0x8c422408, 0x1040004a, 0x01203821, 0x3c020800, - 0x944223e2, 0x00004021, 0xa520000a, 0x01e21023, 0xa5220002, 0x3082ffff, - 0x00021042, 0x18400008, 0x00003021, 0x00401821, 0x94e20000, 0x25080001, - 0x00c23021, 0x0103102a, 0x1440fffb, 0x24e70002, 0x00061c02, 0x30c2ffff, - 0x00623021, 0x00061402, 0x00c23021, 0x00c02821, 0x00061027, 0xa522000a, - 0x00003021, 0x2527000c, 0x00004021, 0x94e20000, 0x25080001, 0x00c23021, - 0x2d020004, 0x1440fffb, 0x24e70002, 0x95220002, 0x00004021, 0x91230009, - 0x00442023, 0x01803821, 0x3082ffff, 0xa4e00010, 0x00621821, 0x00021042, - 0x18400010, 0x00c33021, 0x00404821, 0x94e20000, 0x24e70002, 0x00c23021, - 0x30e2007f, 0x14400006, 0x25080001, 0x8d630000, 0x3c02007f, 0x3442ff80, - 0x00625824, 0x25670008, 0x0109102a, 0x1440fff3, 0x00000000, 0x30820001, - 0x10400005, 0x00061c02, 0xa0e00001, 0x94e20000, 0x00c23021, 0x00061c02, - 0x30c2ffff, 0x00623021, 0x00061402, 0x00c23021, 0x0a000479, 0x30c6ffff, - 0x24020002, 0x14c20081, 0x00000000, 0x3c020800, 0x8c42241c, 0x14400007, - 0x00000000, 0x3c020800, 0x944223e2, 0x95230002, 0x01e21023, 0x10620077, - 0x00000000, 0x3c020800, 0x944223e2, 0x01e21023, 0xa5220002, 0x3c020800, - 0x8c42241c, 0x1040001a, 0x31e3ffff, 0x8dc70010, 0x3c020800, 0x94421ba6, - 0x00e04021, 0x00072c02, 0x00aa2021, 0x00431023, 0x00823823, 0x00072402, - 0x30e2ffff, 0x00823821, 0x00071027, 0xa522000a, 0x3102ffff, 0x3c040800, - 0x948423e4, 0x00453023, 0x00e02821, 0x00641823, 0x006d1821, 0x00c33021, - 0x00061c02, 0x30c2ffff, 0x0a000479, 0x00623021, 0x01203821, 0x00004021, - 0x3082ffff, 0x00021042, 0x18400008, 0x00003021, 0x00401821, 0x94e20000, - 0x25080001, 0x00c23021, 0x0103102a, 0x1440fffb, 0x24e70002, 0x00061c02, - 0x30c2ffff, 0x00623021, 0x00061402, 0x00c23021, 0x00c02821, 0x00061027, - 0xa522000a, 0x00003021, 0x2527000c, 0x00004021, 0x94e20000, 0x25080001, - 0x00c23021, 0x2d020004, 0x1440fffb, 0x24e70002, 0x95220002, 0x00004021, - 0x91230009, 0x00442023, 0x01803821, 0x3082ffff, 0xa4e00010, 0x3c040800, - 0x948423e4, 0x00621821, 0x00c33021, 0x00061c02, 0x30c2ffff, 0x00623021, - 0x00061c02, 0x3c020800, 0x944223e0, 0x00c34821, 0x00441023, 0x00021fc2, - 0x00431021, 0x00021043, 0x18400010, 0x00003021, 0x00402021, 0x94e20000, - 0x24e70002, 0x00c23021, 0x30e2007f, 0x14400006, 0x25080001, 0x8d630000, - 0x3c02007f, 0x3442ff80, 0x00625824, 0x25670008, 0x0104102a, 0x1440fff3, - 0x00000000, 0x3c020800, 0x944223fc, 0x00c23021, 0x3122ffff, 0x00c23021, - 0x00061c02, 0x30c2ffff, 0x00623021, 0x00061402, 0x00c23021, 0x00c04021, - 0x00061027, 0xa5820010, 0xadc00014, 0x0a000499, 0xadc00000, 0x8dc70010, - 0x00e04021, 0x11400007, 0x00072c02, 0x00aa3021, 0x00061402, 0x30c3ffff, - 0x00433021, 0x00061402, 0x00c22821, 0x00051027, 0xa522000a, 0x3c030800, - 0x946323e4, 0x3102ffff, 0x01e21021, 0x00433023, 0x00cd3021, 0x00061c02, - 0x30c2ffff, 0x00623021, 0x00061402, 0x00c23021, 0x00c04021, 0x00061027, - 0xa5820010, 0x3102ffff, 0x00051c00, 0x00431025, 0xadc20010, 0x3c020800, - 0x8c422404, 0x10400002, 0x25e2fff2, 0xa5c20034, 0x3c020800, 0x8c4223f8, - 0x3c040800, 0x8c8423f4, 0x24420001, 0x3c010800, 0xac2223f8, 0x3c020800, - 0x8c421bd0, 0x3303ffff, 0x00832021, 0x3c010800, 0xac2423f4, 0x00431821, - 0x0062102b, 0x10400003, 0x2482ffff, 0x3c010800, 0xac2223f4, 0x3c010800, - 0xac231bd0, 0x03e00008, 0x27bd0020, 0x27bdffb8, 0x3c050800, 0x24a51ba8, - 0xafbf0044, 0xafbe0040, 0xafb7003c, 0xafb60038, 0xafb50034, 0xafb40030, - 0xafb3002c, 0xafb20028, 0xafb10024, 0xafb00020, 0x90a30000, 0x24020003, - 0x146200d5, 0x00000000, 0x3c090800, 0x95291ba6, 0x3c020800, 0x944223e0, - 0x3c030800, 0x8c631bc0, 0x3c040800, 0x8c841bbc, 0x01221023, 0x0064182a, - 0xa7a9001e, 0x106000c8, 0xa7a20016, 0x24be0020, 0x97b6001e, 0x24b30018, - 0x24b70014, 0x8fc20000, 0x14400008, 0x00000000, 0x8fc2fff8, 0x97a30016, - 0x8fc4fff4, 0x00431021, 0x0082202a, 0x148000ba, 0x00000000, 0x97d50818, - 0x32a2ffff, 0x104000ad, 0x00009021, 0x0040a021, 0x00008821, 0x0e00062d, - 0x00000000, 0x00403021, 0x14c00007, 0x00000000, 0x3c020800, 0x8c4223ec, - 0x24420001, 0x3c010800, 0x0a00059e, 0xac2223ec, 0x3c100800, 0x02118021, - 0x8e101bd8, 0x9608000a, 0x31020040, 0x10400004, 0x2407180c, 0x8e02000c, - 0x2407188c, 0xacc20018, 0x31021000, 0x10400004, 0x34e32000, 0x00081040, - 0x3042c000, 0x00623825, 0x31020080, 0x54400001, 0x34e70010, 0x3c020800, - 0x00511021, 0x8c421be0, 0x3c030800, 0x00711821, 0x8c631be4, 0x00021500, - 0x00031c00, 0x00431025, 0xacc20014, 0x96040008, 0x3242ffff, 0x00821021, - 0x0282102a, 0x14400002, 0x02b22823, 0x00802821, 0x8e020000, 0x02459021, - 0xacc20000, 0x8e020004, 0x00c02021, 0x26310010, 0xac820004, 0x30e2ffff, - 0xac800008, 0xa485000e, 0xac820010, 0x24020305, 0x0e0005aa, 0xa482000c, - 0x3242ffff, 0x0054102b, 0x1440ffc0, 0x3242ffff, 0x0a000596, 0x00000000, - 0x8e620000, 0x8e63fffc, 0x0043102a, 0x1040006c, 0x00000000, 0x8e62fff0, - 0x00028900, 0x3c100800, 0x02118021, 0x0e00062d, 0x8e101bd8, 0x00403021, - 0x14c00005, 0x00000000, 0x8e62082c, 0x24420001, 0x0a00059e, 0xae62082c, - 0x9608000a, 0x31020040, 0x10400004, 0x2407180c, 0x8e02000c, 0x2407188c, - 0xacc20018, 0x31021000, 0x10400004, 0x34e32000, 0x00081040, 0x3042c000, - 0x00623825, 0x3c020800, 0x00511021, 0x8c421be0, 0x3c030800, 0x00711821, - 0x8c631be4, 0x00021500, 0x00031c00, 0x00431025, 0xacc20014, 0x8e63fff4, - 0x96020008, 0x00432023, 0x3242ffff, 0x3083ffff, 0x00431021, 0x02c2102a, - 0x10400003, 0x00802821, 0x97a9001e, 0x01322823, 0x8e620000, 0x30a4ffff, - 0x00441021, 0xae620000, 0xa4c5000e, 0x8e020000, 0xacc20000, 0x8e020004, - 0x8e63fff4, 0x00431021, 0xacc20004, 0x8e63fff4, 0x96020008, 0x00641821, - 0x0062102a, 0x14400006, 0x02459021, 0x8e62fff0, 0xae60fff4, 0x24420001, - 0x0a000579, 0xae62fff0, 0xae63fff4, 0xacc00008, 0x3242ffff, 0x10560003, - 0x31020004, 0x10400006, 0x24020305, 0x31020080, 0x54400001, 0x34e70010, - 0x34e70020, 0x24020905, 0xa4c2000c, 0x8ee30000, 0x8ee20004, 0x14620007, - 0x3c02b49a, 0x8ee20860, 0x54400001, 0x34e70400, 0x3c024b65, 0x0a000590, - 0x34427654, 0x344289ab, 0xacc2001c, 0x30e2ffff, 0xacc20010, 0x0e0005aa, - 0x00c02021, 0x3242ffff, 0x0056102b, 0x1440ff96, 0x00000000, 0x8e620000, - 0x8e63fffc, 0x0043102a, 0x1440ff3e, 0x00000000, 0x8fbf0044, 0x8fbe0040, - 0x8fb7003c, 0x8fb60038, 0x8fb50034, 0x8fb40030, 0x8fb3002c, 0x8fb20028, - 0x8fb10024, 0x8fb00020, 0x03e00008, 0x27bd0048, 0x27bdffe8, 0xafbf0014, - 0xafb00010, 0x8f624450, 0x8f634410, 0x0a0005b9, 0x00808021, 0x8f626820, - 0x30422000, 0x10400003, 0x00000000, 0x0e0001e3, 0x00002021, 0x8f624450, - 0x8f634410, 0x3042ffff, 0x0043102b, 0x1440fff5, 0x00000000, 0x8f630c14, - 0x3063000f, 0x2c620002, 0x1440000b, 0x00000000, 0x8f630c14, 0x3c020800, - 0x8c421b50, 0x3063000f, 0x24420001, 0x3c010800, 0xac221b50, 0x2c620002, - 0x1040fff7, 0x00000000, 0xaf705c18, 0x8f625c10, 0x30420002, 0x10400009, - 0x00000000, 0x8f626820, 0x30422000, 0x1040fff8, 0x00000000, 0x0e0001e3, - 0x00002021, 0x0a0005cc, 0x00000000, 0x8fbf0014, 0x8fb00010, 0x03e00008, - 0x27bd0018, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe8, 0x3c1bc000, - 0xafbf0014, 0xafb00010, 0xaf60680c, 0x8f626804, 0x34420082, 0xaf626804, - 0x8f634000, 0x24020b50, 0x3c010800, 0xac221b64, 0x24020b78, 0x3c010800, - 0xac221b74, 0x34630002, 0xaf634000, 0x0e00060d, 0x00808021, 0x3c010800, - 0xa0221b78, 0x304200ff, 0x24030002, 0x14430005, 0x00000000, 0x3c020800, - 0x8c421b64, 0x0a000600, 0xac5000c0, 0x3c020800, 0x8c421b64, 0xac5000bc, - 0x8f624434, 0x8f634438, 0x8f644410, 0x3c010800, 0xac221b6c, 0x3c010800, - 0xac231b7c, 0x3c010800, 0xac241b68, 0x8fbf0014, 0x8fb00010, 0x03e00008, - 0x27bd0018, 0x3c040800, 0x8c870000, 0x3c03aa55, 0x3463aa55, 0x3c06c003, - 0xac830000, 0x8cc20000, 0x14430007, 0x24050002, 0x3c0355aa, 0x346355aa, - 0xac830000, 0x8cc20000, 0x50430001, 0x24050001, 0x3c020800, 0xac470000, - 0x03e00008, 0x00a01021, 0x27bdfff8, 0x18800009, 0x00002821, 0x8f63680c, - 0x8f62680c, 0x1043fffe, 0x00000000, 0x24a50001, 0x00a4102a, 0x1440fff9, - 0x00000000, 0x03e00008, 0x27bd0008, 0x8f634450, 0x3c020800, 0x8c421b6c, - 0x00031c02, 0x0043102b, 0x14400008, 0x3c038000, 0x3c040800, 0x8c841b7c, - 0x8f624450, 0x00021c02, 0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444, - 0x8f624444, 0x00431024, 0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008, - 0x3042ffff, 0x3082ffff, 0x2442e000, 0x2c422001, 0x14400003, 0x3c024000, - 0x0a000650, 0x2402ffff, 0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002, - 0x1440fffc, 0x00001021, 0x03e00008, 0x00000000, 0x8f624450, 0x3c030800, - 0x8c631b68, 0x0a000659, 0x3042ffff, 0x8f624450, 0x3042ffff, 0x0043102b, - 0x1440fffc, 0x00000000, 0x03e00008, 0x00000000, 0x27bdffe0, 0x00802821, - 0x3c040800, 0x24841b10, 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, - 0x0e000684, 0xafa00014, 0x0a000668, 0x00000000, 0x8fbf0018, 0x03e00008, - 0x27bd0020, 0x00000000, 0x00000000, 0x00000000, 0x3c020800, 0x34423000, - 0x3c030800, 0x34633000, 0x3c040800, 0x348437ff, 0x3c010800, 0xac221b84, - 0x24020040, 0x3c010800, 0xac221b88, 0x3c010800, 0xac201b80, 0xac600000, - 0x24630004, 0x0083102b, 0x5040fffd, 0xac600000, 0x03e00008, 0x00000000, - 0x00804821, 0x8faa0010, 0x3c020800, 0x8c421b80, 0x3c040800, 0x8c841b88, - 0x8fab0014, 0x24430001, 0x0044102b, 0x3c010800, 0xac231b80, 0x14400003, - 0x00004021, 0x3c010800, 0xac201b80, 0x3c020800, 0x8c421b80, 0x3c030800, - 0x8c631b84, 0x91240000, 0x00021140, 0x00431021, 0x00481021, 0x25080001, - 0xa0440000, 0x29020008, 0x1440fff4, 0x25290001, 0x3c020800, 0x8c421b80, - 0x3c030800, 0x8c631b84, 0x8f64680c, 0x00021140, 0x00431021, 0xac440008, - 0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, - 0x00000000, 0x00000000, -}; - -u32 tg3TsoFwRodata[] = { - 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, - 0x00000000, 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, - 0x496e0000, 0x73746b6f, 0x66662a2a, 0x00000000, 0x53774576, - 0x656e7430, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x66617461, 0x6c457272, 0x00000000, 0x00000000, 0x00000000 -}; - -#if 0 /* All zeros, don't eat up space with it. */ -u32 tg3TsoFwData[] = { - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000 -}; -#endif - -/* 5705 needs a special version of the TSO firmware. */ -#define TG3_TSO5_FW_RELEASE_MAJOR 0x1 -#define TG3_TSO5_FW_RELASE_MINOR 0x1 -#define TG3_TSO5_FW_RELEASE_FIX 0x0 -#define TG3_TSO5_FW_START_ADDR 0x00010000 -#define TG3_TSO5_FW_TEXT_ADDR 0x00010000 -#define TG3_TSO5_FW_TEXT_LEN 0xeb0 -#define TG3_TSO5_FW_RODATA_ADDR 0x00010eb0 -#define TG3_TSO5_FW_RODATA_LEN 0x50 -#define TG3_TSO5_FW_DATA_ADDR 0x00010f20 -#define TG3_TSO5_FW_DATA_LEN 0x20 -#define TG3_TSO5_FW_SBSS_ADDR 0x00010f40 -#define TG3_TSO5_FW_SBSS_LEN 0x28 -#define TG3_TSO5_FW_BSS_ADDR 0x00010f70 -#define TG3_TSO5_FW_BSS_LEN 0x88 - -static u32 tg3Tso5FwText[] = { - 0x0c004003, 0x00000000, 0x00010f30, 0x00000000, 0x10000003, 0x00000000, - 0x0000000d, 0x0000000d, 0x3c1d0001, 0x37bde000, 0x03a0f021, 0x3c100001, - 0x26100000, 0x0c004010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe, - 0xafbf0018, 0x0c0042f0, 0x34840002, 0x0c00436c, 0x00000000, 0x3c030001, - 0x90630f54, 0x24020002, 0x3c040001, 0x24840ebc, 0x14620003, 0x24050001, - 0x3c040001, 0x24840eb0, 0x24060001, 0x00003821, 0xafa00010, 0x0c004380, - 0xafa00014, 0x0c00402c, 0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020, - 0x00000000, 0x00000000, 0x27bdffe0, 0xafbf001c, 0xafb20018, 0xafb10014, - 0x0c0042d3, 0xafb00010, 0x3c128000, 0x24110001, 0x8f706810, 0x32020400, - 0x10400007, 0x00000000, 0x8f641008, 0x00921024, 0x14400003, 0x00000000, - 0x0c004064, 0x00000000, 0x3c020001, 0x90420f76, 0x10510003, 0x32020200, - 0x1040fff1, 0x00000000, 0x0c0041b4, 0x00000000, 0x08004034, 0x00000000, - 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, - 0x27bdffe0, 0x3c040001, 0x24840ed0, 0x00002821, 0x00003021, 0x00003821, - 0xafbf0018, 0xafa00010, 0x0c004380, 0xafa00014, 0x0000d021, 0x24020130, - 0xaf625000, 0x3c010001, 0xa4200f70, 0x3c010001, 0xa0200f77, 0x8fbf0018, - 0x03e00008, 0x27bd0020, 0x00000000, 0x00000000, 0x3c030001, 0x24630f80, - 0x90620000, 0x27bdfff0, 0x14400003, 0x0080c021, 0x08004073, 0x00004821, - 0x3c022000, 0x03021024, 0x10400003, 0x24090002, 0x08004073, 0xa0600000, - 0x24090001, 0x00181040, 0x30431f80, 0x346f8008, 0x1520004b, 0x25eb0028, - 0x3c040001, 0x00832021, 0x8c848010, 0x3c050001, 0x24a50f9a, 0x00041402, - 0xa0a20000, 0x3c010001, 0xa0240f9b, 0x3c020001, 0x00431021, 0x94428014, - 0x3c010001, 0xa0220f9c, 0x3c0c0001, 0x01836021, 0x8d8c8018, 0x304200ff, - 0x24420008, 0x000220c3, 0x24020001, 0x3c010001, 0xa0220f80, 0x0124102b, - 0x1040000c, 0x00003821, 0x24a6000e, 0x01602821, 0x8ca20000, 0x8ca30004, - 0x24a50008, 0x24e70001, 0xacc20000, 0xacc30004, 0x00e4102b, 0x1440fff8, - 0x24c60008, 0x00003821, 0x3c080001, 0x25080f9b, 0x91060000, 0x3c020001, - 0x90420f9c, 0x2503000d, 0x00c32821, 0x00461023, 0x00021fc2, 0x00431021, - 0x00021043, 0x1840000c, 0x00002021, 0x91020001, 0x00461023, 0x00021fc2, - 0x00431021, 0x00021843, 0x94a20000, 0x24e70001, 0x00822021, 0x00e3102a, - 0x1440fffb, 0x24a50002, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402, - 0x00822021, 0x3c02ffff, 0x01821024, 0x3083ffff, 0x00431025, 0x3c010001, - 0x080040fa, 0xac220fa0, 0x3c050001, 0x24a50f9c, 0x90a20000, 0x3c0c0001, - 0x01836021, 0x8d8c8018, 0x000220c2, 0x1080000e, 0x00003821, 0x01603021, - 0x24a5000c, 0x8ca20000, 0x8ca30004, 0x24a50008, 0x24e70001, 0xacc20000, - 0xacc30004, 0x00e4102b, 0x1440fff8, 0x24c60008, 0x3c050001, 0x24a50f9c, - 0x90a20000, 0x30430007, 0x24020004, 0x10620011, 0x28620005, 0x10400005, - 0x24020002, 0x10620008, 0x000710c0, 0x080040fa, 0x00000000, 0x24020006, - 0x1062000e, 0x000710c0, 0x080040fa, 0x00000000, 0x00a21821, 0x9463000c, - 0x004b1021, 0x080040fa, 0xa4430000, 0x000710c0, 0x00a21821, 0x8c63000c, - 0x004b1021, 0x080040fa, 0xac430000, 0x00a21821, 0x8c63000c, 0x004b2021, - 0x00a21021, 0xac830000, 0x94420010, 0xa4820004, 0x95e70006, 0x3c020001, - 0x90420f9c, 0x3c030001, 0x90630f9a, 0x00e2c823, 0x3c020001, 0x90420f9b, - 0x24630028, 0x01e34021, 0x24420028, 0x15200012, 0x01e23021, 0x94c2000c, - 0x3c010001, 0xa4220f98, 0x94c20004, 0x94c30006, 0x3c010001, 0xa4200f96, - 0x3c010001, 0xa4200f92, 0x00021400, 0x00431025, 0x3c010001, 0xac220f8c, - 0x95020004, 0x3c010001, 0x08004124, 0xa4220f90, 0x3c020001, 0x94420f90, - 0x3c030001, 0x94630f92, 0x00431021, 0xa5020004, 0x3c020001, 0x94420f8c, - 0xa4c20004, 0x3c020001, 0x8c420f8c, 0xa4c20006, 0x3c040001, 0x94840f92, - 0x3c020001, 0x94420f90, 0x3c0a0001, 0x954a0f96, 0x00441821, 0x3063ffff, - 0x0062182a, 0x24020002, 0x1122000b, 0x00832023, 0x3c030001, 0x94630f98, - 0x30620009, 0x10400006, 0x3062fff6, 0xa4c2000c, 0x3c020001, 0x94420f98, - 0x30420009, 0x01425023, 0x24020001, 0x1122001b, 0x29220002, 0x50400005, - 0x24020002, 0x11200007, 0x31a2ffff, 0x08004197, 0x00000000, 0x1122001d, - 0x24020016, 0x08004197, 0x31a2ffff, 0x3c0e0001, 0x95ce0fa0, 0x10800005, - 0x01806821, 0x01c42021, 0x00041c02, 0x3082ffff, 0x00627021, 0x000e1027, - 0xa502000a, 0x3c030001, 0x90630f9b, 0x31a2ffff, 0x00e21021, 0x0800418d, - 0x00432023, 0x3c020001, 0x94420fa0, 0x00442021, 0x00041c02, 0x3082ffff, - 0x00622021, 0x00807021, 0x00041027, 0x08004185, 0xa502000a, 0x3c050001, - 0x24a50f9a, 0x90a30000, 0x14620002, 0x24e2fff2, 0xa5e20034, 0x90a20000, - 0x00e21023, 0xa5020002, 0x3c030001, 0x94630fa0, 0x3c020001, 0x94420f7a, - 0x30e5ffff, 0x00641821, 0x00451023, 0x00622023, 0x00041c02, 0x3082ffff, - 0x00622021, 0x00041027, 0xa502000a, 0x3c030001, 0x90630f9c, 0x24620001, - 0x14a20005, 0x00807021, 0x01631021, 0x90420000, 0x08004185, 0x00026200, - 0x24620002, 0x14a20003, 0x306200fe, 0x004b1021, 0x944c0000, 0x3c020001, - 0x94420fa2, 0x3183ffff, 0x3c040001, 0x90840f9b, 0x00431021, 0x00e21021, - 0x00442023, 0x008a2021, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402, - 0x00822021, 0x00806821, 0x00041027, 0xa4c20010, 0x31a2ffff, 0x000e1c00, - 0x00431025, 0x3c040001, 0x24840f92, 0xade20010, 0x94820000, 0x3c050001, - 0x94a50f96, 0x3c030001, 0x8c630f8c, 0x24420001, 0x00b92821, 0xa4820000, - 0x3322ffff, 0x00622021, 0x0083182b, 0x3c010001, 0xa4250f96, 0x10600003, - 0x24a2ffff, 0x3c010001, 0xa4220f96, 0x3c024000, 0x03021025, 0x3c010001, - 0xac240f8c, 0xaf621008, 0x03e00008, 0x27bd0010, 0x3c030001, 0x90630f76, - 0x27bdffe8, 0x24020001, 0xafbf0014, 0x10620026, 0xafb00010, 0x8f620cf4, - 0x2442ffff, 0x3042007f, 0x00021100, 0x8c434000, 0x3c010001, 0xac230f84, - 0x8c434008, 0x24444000, 0x8c5c4004, 0x30620040, 0x14400002, 0x24020088, - 0x24020008, 0x3c010001, 0xa4220f88, 0x30620004, 0x10400005, 0x24020001, - 0x3c010001, 0xa0220f77, 0x080041d5, 0x00031402, 0x3c010001, 0xa0200f77, - 0x00031402, 0x3c010001, 0xa4220f74, 0x9483000c, 0x24020001, 0x3c010001, - 0xa4200f70, 0x3c010001, 0xa0220f76, 0x3c010001, 0xa4230f82, 0x24020001, - 0x1342001e, 0x00000000, 0x13400005, 0x24020003, 0x13420067, 0x00000000, - 0x080042cf, 0x00000000, 0x3c020001, 0x94420f82, 0x241a0001, 0x3c010001, - 0xa4200f7e, 0x3c010001, 0xa4200f72, 0x304407ff, 0x00021bc2, 0x00031823, - 0x3063003e, 0x34630036, 0x00021242, 0x3042003c, 0x00621821, 0x3c010001, - 0xa4240f78, 0x00832021, 0x24630030, 0x3c010001, 0xa4240f7a, 0x3c010001, - 0xa4230f7c, 0x3c060001, 0x24c60f72, 0x94c50000, 0x94c30002, 0x3c040001, - 0x94840f7a, 0x00651021, 0x0044102a, 0x10400013, 0x3c108000, 0x00a31021, - 0xa4c20000, 0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f76, 0x8f641008, - 0x00901024, 0x14400003, 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4, - 0x00501024, 0x104000b7, 0x00000000, 0x0800420f, 0x00000000, 0x3c030001, - 0x94630f70, 0x00851023, 0xa4c40000, 0x00621821, 0x3042ffff, 0x3c010001, - 0xa4230f70, 0xaf620ce8, 0x3c020001, 0x94420f88, 0x34420024, 0xaf620cec, - 0x94c30002, 0x3c020001, 0x94420f70, 0x14620012, 0x3c028000, 0x3c108000, - 0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f76, 0x8f641008, 0x00901024, - 0x14400003, 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4, 0x00501024, - 0x1440fff7, 0x00000000, 0x080042cf, 0x241a0003, 0xaf620cf4, 0x3c108000, - 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064, 0x00000000, - 0x8f620cf4, 0x00501024, 0x1440fff7, 0x00000000, 0x080042cf, 0x241a0003, - 0x3c070001, 0x24e70f70, 0x94e20000, 0x03821021, 0xaf620ce0, 0x3c020001, - 0x8c420f84, 0xaf620ce4, 0x3c050001, 0x94a50f74, 0x94e30000, 0x3c040001, - 0x94840f78, 0x3c020001, 0x94420f7e, 0x00a32823, 0x00822023, 0x30a6ffff, - 0x3083ffff, 0x00c3102b, 0x14400043, 0x00000000, 0x3c020001, 0x94420f7c, - 0x00021400, 0x00621025, 0xaf620ce8, 0x94e20000, 0x3c030001, 0x94630f74, - 0x00441021, 0xa4e20000, 0x3042ffff, 0x14430021, 0x3c020008, 0x3c020001, - 0x90420f77, 0x10400006, 0x3c03000c, 0x3c020001, 0x94420f88, 0x34630624, - 0x0800427c, 0x0000d021, 0x3c020001, 0x94420f88, 0x3c030008, 0x34630624, - 0x00431025, 0xaf620cec, 0x3c108000, 0x3c02a000, 0xaf620cf4, 0x3c010001, - 0xa0200f76, 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064, - 0x00000000, 0x8f620cf4, 0x00501024, 0x10400015, 0x00000000, 0x08004283, - 0x00000000, 0x3c030001, 0x94630f88, 0x34420624, 0x3c108000, 0x00621825, - 0x3c028000, 0xaf630cec, 0xaf620cf4, 0x8f641008, 0x00901024, 0x14400003, - 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4, 0x00501024, 0x1440fff7, - 0x00000000, 0x3c010001, 0x080042cf, 0xa4200f7e, 0x3c020001, 0x94420f7c, - 0x00021400, 0x00c21025, 0xaf620ce8, 0x3c020001, 0x90420f77, 0x10400009, - 0x3c03000c, 0x3c020001, 0x94420f88, 0x34630624, 0x0000d021, 0x00431025, - 0xaf620cec, 0x080042c1, 0x3c108000, 0x3c020001, 0x94420f88, 0x3c030008, - 0x34630604, 0x00431025, 0xaf620cec, 0x3c020001, 0x94420f7e, 0x00451021, - 0x3c010001, 0xa4220f7e, 0x3c108000, 0x3c02a000, 0xaf620cf4, 0x3c010001, - 0xa0200f76, 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064, - 0x00000000, 0x8f620cf4, 0x00501024, 0x1440fff7, 0x00000000, 0x8fbf0014, - 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffe0, 0x3c040001, 0x24840ee0, - 0x00002821, 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, 0x0c004380, - 0xafa00014, 0x0000d021, 0x24020130, 0xaf625000, 0x3c010001, 0xa4200f70, - 0x3c010001, 0xa0200f77, 0x8f636804, 0x3c020001, 0x3442e000, 0x00621824, - 0x3c020001, 0x14620003, 0x00000000, 0x080042eb, 0x00000000, 0x8fbf0018, - 0x03e00008, 0x27bd0020, 0x27bdffe8, 0x3c1bc000, 0xafbf0014, 0xafb00010, - 0xaf60680c, 0x8f626804, 0x34420082, 0xaf626804, 0x8f634000, 0x24020b50, - 0x3c010001, 0xac220f40, 0x24020b78, 0x3c010001, 0xac220f50, 0x34630002, - 0xaf634000, 0x0c00431d, 0x00808021, 0x3c010001, 0xa0220f54, 0x304200ff, - 0x24030002, 0x14430005, 0x00000000, 0x3c020001, 0x8c420f40, 0x08004310, - 0xac5000c0, 0x3c020001, 0x8c420f40, 0xac5000bc, 0x8f624434, 0x8f634438, - 0x8f644410, 0x3c010001, 0xac220f48, 0x3c010001, 0xac230f58, 0x3c010001, - 0xac240f44, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x03e00008, - 0x24020001, 0x27bdfff8, 0x18800009, 0x00002821, 0x8f63680c, 0x8f62680c, - 0x1043fffe, 0x00000000, 0x24a50001, 0x00a4102a, 0x1440fff9, 0x00000000, - 0x03e00008, 0x27bd0008, 0x8f634450, 0x3c020001, 0x8c420f48, 0x00031c02, - 0x0043102b, 0x14400008, 0x3c038000, 0x3c040001, 0x8c840f58, 0x8f624450, - 0x00021c02, 0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, - 0x00431024, 0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff, - 0x3082ffff, 0x2442e000, 0x2c422001, 0x14400003, 0x3c024000, 0x0800434f, - 0x2402ffff, 0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, - 0x00001021, 0x03e00008, 0x00000000, 0x8f624450, 0x3c030001, 0x8c630f44, - 0x08004358, 0x3042ffff, 0x8f624450, 0x3042ffff, 0x0043102b, 0x1440fffc, - 0x00000000, 0x03e00008, 0x00000000, 0x27bdffe0, 0x00802821, 0x3c040001, - 0x24840ef0, 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, 0x0c004380, - 0xafa00014, 0x08004367, 0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020, - 0x3c020001, 0x3442d600, 0x3c030001, 0x3463d600, 0x3c040001, 0x3484ddff, - 0x3c010001, 0xac220f60, 0x24020040, 0x3c010001, 0xac220f64, 0x3c010001, - 0xac200f5c, 0xac600000, 0x24630004, 0x0083102b, 0x5040fffd, 0xac600000, - 0x03e00008, 0x00000000, 0x00804821, 0x8faa0010, 0x3c020001, 0x8c420f5c, - 0x3c040001, 0x8c840f64, 0x8fab0014, 0x24430001, 0x0044102b, 0x3c010001, - 0xac230f5c, 0x14400003, 0x00004021, 0x3c010001, 0xac200f5c, 0x3c020001, - 0x8c420f5c, 0x3c030001, 0x8c630f60, 0x91240000, 0x00021140, 0x00431021, - 0x00481021, 0x25080001, 0xa0440000, 0x29020008, 0x1440fff4, 0x25290001, - 0x3c020001, 0x8c420f5c, 0x3c030001, 0x8c630f60, 0x8f64680c, 0x00021140, - 0x00431021, 0xac440008, 0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, - 0x03e00008, 0xac4b001c, 0x00000000, 0x00000000, -}; - -u32 tg3Tso5FwRodata[] = { - 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000, - 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, - 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x66617461, 0x6c457272, - 0x00000000, 0x00000000, 0x00000000 -}; - -u32 tg3Tso5FwData[] = { - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x73746b6f, - 0x66666c64, 0x5f76312e, 0x312e3000, 0x00000000 -}; - -/* tp->lock is held. */ -static int tg3_load_tso_firmware(struct tg3 *tp) -{ - struct fw_info info; - unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size; - int err, i; - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { - info.text_base = TG3_TSO5_FW_TEXT_ADDR; - info.text_len = TG3_TSO5_FW_TEXT_LEN; - info.text_data = &tg3Tso5FwText[0]; - info.rodata_base = TG3_TSO5_FW_RODATA_ADDR; - info.rodata_len = TG3_TSO5_FW_RODATA_LEN; - info.rodata_data = &tg3Tso5FwRodata[0]; - info.data_base = TG3_TSO5_FW_DATA_ADDR; - info.data_len = TG3_TSO5_FW_DATA_LEN; - info.data_data = &tg3Tso5FwData[0]; - cpu_base = RX_CPU_BASE; - cpu_scratch_base = NIC_SRAM_MBUF_POOL_BASE5705; - cpu_scratch_size = (info.text_len + - info.rodata_len + - info.data_len + - TG3_TSO5_FW_SBSS_LEN + - TG3_TSO5_FW_BSS_LEN); - } else { - info.text_base = TG3_TSO_FW_TEXT_ADDR; - info.text_len = TG3_TSO_FW_TEXT_LEN; - info.text_data = &tg3TsoFwText[0]; - info.rodata_base = TG3_TSO_FW_RODATA_ADDR; - info.rodata_len = TG3_TSO_FW_RODATA_LEN; - info.rodata_data = &tg3TsoFwRodata[0]; - info.data_base = TG3_TSO_FW_DATA_ADDR; - info.data_len = TG3_TSO_FW_DATA_LEN; - info.data_data = NULL; - cpu_base = TX_CPU_BASE; - cpu_scratch_base = TX_CPU_SCRATCH_BASE; - cpu_scratch_size = TX_CPU_SCRATCH_SIZE; - } - - err = tg3_load_firmware_cpu(tp, cpu_base, - cpu_scratch_base, cpu_scratch_size, - &info); - if (err) - return err; - - /* Now startup the cpu. */ - tw32(cpu_base + CPU_STATE, 0xffffffff); - tw32(cpu_base + CPU_PC, info.text_base); - - /* Flush posted writes. */ - tr32(cpu_base + CPU_PC); - for (i = 0; i < 5; i++) { - if (tr32(cpu_base + CPU_PC) == info.text_base) - break; - tw32(cpu_base + CPU_STATE, 0xffffffff); - tw32(cpu_base + CPU_MODE, CPU_MODE_HALT); - tw32(cpu_base + CPU_PC, info.text_base); - - /* Flush posted writes. */ - tr32(cpu_base + CPU_PC); - - udelay(1000); - } - if (i >= 5) { - printk(KERN_ERR PFX "tg3_load_tso_firmware fails for %s " - "to set CPU PC, is %08x should be %08x\n", - tp->dev->name, tr32(cpu_base + CPU_PC), - info.text_base); - return -ENODEV; - } - tw32(cpu_base + CPU_STATE, 0xffffffff); - tw32(cpu_base + CPU_MODE, 0x00000000); - - /* Flush posted writes. */ - tr32(cpu_base + CPU_MODE); - - return 0; -} - -#endif /* TG3_TSO_SUPPORT != 0 */ - -/* tp->lock is held. */ -static void __tg3_set_mac_addr(struct tg3 *tp) -{ - u32 addr_high, addr_low; - int i; - - addr_high = ((tp->dev->dev_addr[0] << 8) | - tp->dev->dev_addr[1]); - addr_low = ((tp->dev->dev_addr[2] << 24) | - (tp->dev->dev_addr[3] << 16) | - (tp->dev->dev_addr[4] << 8) | - (tp->dev->dev_addr[5] << 0)); - for (i = 0; i < 4; i++) { - tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high); - tw32(MAC_ADDR_0_LOW + (i * 8), addr_low); - } - - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { - for (i = 0; i < 12; i++) { - tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high); - tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low); - } - } - - addr_high = (tp->dev->dev_addr[0] + - tp->dev->dev_addr[1] + - tp->dev->dev_addr[2] + - tp->dev->dev_addr[3] + - tp->dev->dev_addr[4] + - tp->dev->dev_addr[5]) & - TX_BACKOFF_SEED_MASK; - tw32(MAC_TX_BACKOFF_SEED, addr_high); -} - -static int tg3_set_mac_addr(struct net_device *dev, void *p) -{ - struct tg3 *tp = dev->priv; - struct sockaddr *addr = p; - - if (netif_running(dev)) - return -EBUSY; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - spin_lock_irq(&tp->lock); - __tg3_set_mac_addr(tp); - spin_unlock_irq(&tp->lock); - - return 0; -} - -/* tp->lock is held. */ -static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr, - dma_addr_t mapping, u32 maxlen_flags, - u32 nic_addr) -{ - tg3_write_mem(tp, - (bdinfo_addr + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH), - ((u64) mapping >> 32)); - tg3_write_mem(tp, - (bdinfo_addr + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW), - ((u64) mapping & 0xffffffff)); - tg3_write_mem(tp, - (bdinfo_addr + TG3_BDINFO_MAXLEN_FLAGS), - maxlen_flags); - - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) - tg3_write_mem(tp, - (bdinfo_addr + TG3_BDINFO_NIC_ADDR), - nic_addr); -} - -static void __tg3_set_rx_mode(struct net_device *); - -/* tp->lock is held. */ -static int tg3_reset_hw(struct tg3 *tp) -{ - u32 val, rdmac_mode; - int i, err, limit; - - tg3_disable_ints(tp); - - tg3_stop_fw(tp); - - if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) { - err = tg3_abort_hw(tp); - if (err) - return err; - } - - tg3_chip_reset(tp); - - tw32(GRC_MODE, tp->grc_mode); - tg3_write_mem(tp, - NIC_SRAM_FIRMWARE_MBOX, - NIC_SRAM_FIRMWARE_MBOX_MAGIC1); - if (tp->phy_id == PHY_ID_SERDES) { - tp->mac_mode = MAC_MODE_PORT_MODE_TBI; - tw32(MAC_MODE, tp->mac_mode); - } else - tw32(MAC_MODE, 0); - tr32(MAC_MODE); - udelay(40); - - /* Wait for firmware initialization to complete. */ - for (i = 0; i < 100000; i++) { - tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val); - if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1) - break; - udelay(10); - } - if (i >= 100000 && - !(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) { - printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, " - "firmware will not restart magic=%08x\n", - tp->dev->name, val); - return -ENODEV; - } - - if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) - tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX, - DRV_STATE_START); - else - tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX, - DRV_STATE_SUSPEND); - - /* This works around an issue with Athlon chipsets on - * B3 tigon3 silicon. This bit has no effect on any - * other revision. - */ - tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT; - tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); - tr32(TG3PCI_CLOCK_CTRL); - - if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && - (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) { - val = tr32(TG3PCI_PCISTATE); - val |= PCISTATE_RETRY_SAME_DMA; - tw32(TG3PCI_PCISTATE, val); - } - - /* Descriptor ring init may make accesses to the - * NIC SRAM area to setup the TX descriptors, so we - * can only do this after the hardware has been - * successfully reset. - */ - tg3_init_rings(tp); - - /* Clear statistics/status block in chip, and status block in ram. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { - for (i = NIC_SRAM_STATS_BLK; - i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE; - i += sizeof(u32)) { - tg3_write_mem(tp, i, 0); - udelay(40); - } - } - memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); - - /* This value is determined during the probe time DMA - * engine test, tg3_test_dma. - */ - tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl); - - tp->grc_mode &= ~(GRC_MODE_HOST_SENDBDS | - GRC_MODE_4X_NIC_SEND_RINGS | - GRC_MODE_NO_TX_PHDR_CSUM | - GRC_MODE_NO_RX_PHDR_CSUM); - if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) - tp->grc_mode |= GRC_MODE_HOST_SENDBDS; - else - tp->grc_mode |= GRC_MODE_4X_NIC_SEND_RINGS; - if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM) - tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM; - if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM) - tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM; - - tw32(GRC_MODE, - tp->grc_mode | - (GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP)); - - /* Setup the timer prescalar register. Clock is always 66Mhz. */ - tw32(GRC_MISC_CFG, - (65 << GRC_MISC_CFG_PRESCALAR_SHIFT)); - - /* Initialize MBUF/DESC pool. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { - tw32(BUFMGR_MB_POOL_ADDR, NIC_SRAM_MBUF_POOL_BASE); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) - tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE64); - else - tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE96); - tw32(BUFMGR_DMA_DESC_POOL_ADDR, NIC_SRAM_DMA_DESC_POOL_BASE); - tw32(BUFMGR_DMA_DESC_POOL_SIZE, NIC_SRAM_DMA_DESC_POOL_SIZE); - } -#if TG3_TSO_SUPPORT != 0 - else if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { - int fw_len; - - fw_len = (TG3_TSO5_FW_TEXT_LEN + - TG3_TSO5_FW_RODATA_LEN + - TG3_TSO5_FW_DATA_LEN + - TG3_TSO5_FW_SBSS_LEN + - TG3_TSO5_FW_BSS_LEN); - fw_len = (fw_len + (0x80 - 1)) & ~(0x80 - 1); - tw32(BUFMGR_MB_POOL_ADDR, - NIC_SRAM_MBUF_POOL_BASE5705 + fw_len); - tw32(BUFMGR_MB_POOL_SIZE, - NIC_SRAM_MBUF_POOL_SIZE5705 - fw_len - 0xa00); - } -#endif - - if (!(tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE)) { - tw32(BUFMGR_MB_RDMA_LOW_WATER, - tp->bufmgr_config.mbuf_read_dma_low_water); - tw32(BUFMGR_MB_MACRX_LOW_WATER, - tp->bufmgr_config.mbuf_mac_rx_low_water); - tw32(BUFMGR_MB_HIGH_WATER, - tp->bufmgr_config.mbuf_high_water); - } else { - tw32(BUFMGR_MB_RDMA_LOW_WATER, - tp->bufmgr_config.mbuf_read_dma_low_water_jumbo); - tw32(BUFMGR_MB_MACRX_LOW_WATER, - tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo); - tw32(BUFMGR_MB_HIGH_WATER, - tp->bufmgr_config.mbuf_high_water_jumbo); - } - tw32(BUFMGR_DMA_LOW_WATER, - tp->bufmgr_config.dma_low_water); - tw32(BUFMGR_DMA_HIGH_WATER, - tp->bufmgr_config.dma_high_water); - - tw32(BUFMGR_MODE, BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE); - for (i = 0; i < 2000; i++) { - if (tr32(BUFMGR_MODE) & BUFMGR_MODE_ENABLE) - break; - udelay(10); - } - if (i >= 2000) { - printk(KERN_ERR PFX "tg3_reset_hw cannot enable BUFMGR for %s.\n", - tp->dev->name); - return -ENODEV; - } - - tw32(FTQ_RESET, 0xffffffff); - tw32(FTQ_RESET, 0x00000000); - for (i = 0; i < 2000; i++) { - if (tr32(FTQ_RESET) == 0x00000000) - break; - udelay(10); - } - if (i >= 2000) { - printk(KERN_ERR PFX "tg3_reset_hw cannot reset FTQ for %s.\n", - tp->dev->name); - return -ENODEV; - } - - /* Setup replenish threshold. */ - tw32(RCVBDI_STD_THRESH, tp->rx_pending / 8); - - /* Initialize TG3_BDINFO's at: - * RCVDBDI_STD_BD: standard eth size rx ring - * RCVDBDI_JUMBO_BD: jumbo frame rx ring - * RCVDBDI_MINI_BD: small frame rx ring (??? does not work) - * - * like so: - * TG3_BDINFO_HOST_ADDR: high/low parts of DMA address of ring - * TG3_BDINFO_MAXLEN_FLAGS: (rx max buffer size << 16) | - * ring attribute flags - * TG3_BDINFO_NIC_ADDR: location of descriptors in nic SRAM - * - * Standard receive ring @ NIC_SRAM_RX_BUFFER_DESC, 512 entries. - * Jumbo receive ring @ NIC_SRAM_RX_JUMBO_BUFFER_DESC, 256 entries. - * - * The size of each ring is fixed in the firmware, but the location is - * configurable. - */ - tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH, - ((u64) tp->rx_std_mapping >> 32)); - tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, - ((u64) tp->rx_std_mapping & 0xffffffff)); - tw32(RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR, - NIC_SRAM_RX_BUFFER_DESC); - - /* Don't even try to program the JUMBO/MINI buffer descriptor - * configs on 5705. - */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { - tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, - RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT); - } else { - tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, - RX_STD_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT); - - tw32(RCVDBDI_MINI_BD + TG3_BDINFO_MAXLEN_FLAGS, - BDINFO_FLAGS_DISABLED); - - /* Setup replenish threshold. */ - tw32(RCVBDI_JUMBO_THRESH, tp->rx_jumbo_pending / 8); - - if (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) { - tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH, - ((u64) tp->rx_jumbo_mapping >> 32)); - tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, - ((u64) tp->rx_jumbo_mapping & 0xffffffff)); - tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, - RX_JUMBO_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT); - tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_NIC_ADDR, - NIC_SRAM_RX_JUMBO_BUFFER_DESC); - } else { - tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, - BDINFO_FLAGS_DISABLED); - } - - } - - /* There is only one send ring on 5705, no need to explicitly - * disable the others. - */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { - /* Clear out send RCB ring in SRAM. */ - for (i = NIC_SRAM_SEND_RCB; i < NIC_SRAM_RCV_RET_RCB; i += TG3_BDINFO_SIZE) - tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS, - BDINFO_FLAGS_DISABLED); - } - - tp->tx_prod = 0; - tp->tx_cons = 0; - tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0); - tw32_mailbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW); - - if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { - tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB, - tp->tx_desc_mapping, - (TG3_TX_RING_SIZE << - BDINFO_FLAGS_MAXLEN_SHIFT), - NIC_SRAM_TX_BUFFER_DESC); - } else { - tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB, - 0, - BDINFO_FLAGS_DISABLED, - NIC_SRAM_TX_BUFFER_DESC); - } - - /* There is only one receive return ring on 5705, no need to explicitly - * disable the others. - */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { - for (i = NIC_SRAM_RCV_RET_RCB; i < NIC_SRAM_STATS_BLK; - i += TG3_BDINFO_SIZE) { - tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS, - BDINFO_FLAGS_DISABLED); - } - } - - tp->rx_rcb_ptr = 0; - tw32_mailbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, 0); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW); - - tg3_set_bdinfo(tp, NIC_SRAM_RCV_RET_RCB, - tp->rx_rcb_mapping, - (TG3_RX_RCB_RING_SIZE(tp) << - BDINFO_FLAGS_MAXLEN_SHIFT), - 0); - - tp->rx_std_ptr = tp->rx_pending; - tw32_mailbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW, - tp->rx_std_ptr); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW); - - if (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) - tp->rx_jumbo_ptr = tp->rx_jumbo_pending; - else - tp->rx_jumbo_ptr = 0; - tw32_mailbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW, - tp->rx_jumbo_ptr); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW); - - /* Initialize MAC address and backoff seed. */ - __tg3_set_mac_addr(tp); - - /* MTU + ethernet header + FCS + optional VLAN tag */ - tw32(MAC_RX_MTU_SIZE, tp->dev->mtu + ETH_HLEN + 8); - - /* The slot time is changed by tg3_setup_phy if we - * run at gigabit with half duplex. - */ - tw32(MAC_TX_LENGTHS, - (2 << TX_LENGTHS_IPG_CRS_SHIFT) | - (6 << TX_LENGTHS_IPG_SHIFT) | - (32 << TX_LENGTHS_SLOT_TIME_SHIFT)); - - /* Receive rules. */ - tw32(MAC_RCV_RULE_CFG, RCV_RULE_CFG_DEFAULT_CLASS); - tw32(RCVLPC_CONFIG, 0x0181); - - /* Calculate RDMAC_MODE setting early, we need it to determine - * the RCVLPC_STATE_ENABLE mask. - */ - rdmac_mode = (RDMAC_MODE_ENABLE | RDMAC_MODE_TGTABORT_ENAB | - RDMAC_MODE_MSTABORT_ENAB | RDMAC_MODE_PARITYERR_ENAB | - RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB | - RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB | - RDMAC_MODE_LNGREAD_ENAB); - if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) - rdmac_mode |= RDMAC_MODE_SPLIT_ENABLE; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { - if (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) { - if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { - rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128; - } else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) && - !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) { - rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST; - } - } - } - - /* Receive/send statistics. */ - if ((rdmac_mode & RDMAC_MODE_FIFO_SIZE_128) && - (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) { - val = tr32(RCVLPC_STATS_ENABLE); - val &= ~RCVLPC_STATSENAB_LNGBRST_RFIX; - tw32(RCVLPC_STATS_ENABLE, val); - } else { - tw32(RCVLPC_STATS_ENABLE, 0xffffff); - } - tw32(RCVLPC_STATSCTRL, RCVLPC_STATSCTRL_ENABLE); - tw32(SNDDATAI_STATSENAB, 0xffffff); - tw32(SNDDATAI_STATSCTRL, - (SNDDATAI_SCTRL_ENABLE | - SNDDATAI_SCTRL_FASTUPD)); - - /* Setup host coalescing engine. */ - tw32(HOSTCC_MODE, 0); - for (i = 0; i < 2000; i++) { - if (!(tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE)) - break; - udelay(10); - } - -#ifdef NAPI - tw32(HOSTCC_RXCOL_TICKS, 0); - tw32(HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS); - tw32(HOSTCC_RXMAX_FRAMES, 1); - tw32(HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES); - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) - tw32(HOSTCC_RXCOAL_TICK_INT, 0); - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) - tw32(HOSTCC_TXCOAL_TICK_INT, 0); - tw32(HOSTCC_RXCOAL_MAXF_INT, 1); - tw32(HOSTCC_TXCOAL_MAXF_INT, 0); -#else - tw32(HOSTCC_RXCOL_TICKS, DEFAULT_RXCOL_TICKS); - tw32(HOSTCC_TXCOL_TICKS, DEFAULT_TXCOL_TICKS); - tw32(HOSTCC_RXMAX_FRAMES, DEFAULT_RXMAX_FRAMES); - tw32(HOSTCC_TXMAX_FRAMES, DEFAULT_TXMAX_FRAMES); - tw32(HOSTCC_RXCOAL_TICK_INT, DEFAULT_RXCOAL_TICK_INT); - tw32(HOSTCC_TXCOAL_TICK_INT, DEFAULT_TXCOAL_TICK_INT); - tw32(HOSTCC_RXCOAL_MAXF_INT, DEFAULT_RXCOAL_MAXF_INT); - tw32(HOSTCC_TXCOAL_MAXF_INT, DEFAULT_TXCOAL_MAXF_INT); -#endif - - /* set status block DMA address */ - tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, - ((u64) tp->status_mapping >> 32)); - tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW, - ((u64) tp->status_mapping & 0xffffffff)); - - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { - /* Status/statistics block address. See tg3_timer, - * the tg3_periodic_fetch_stats call there, and - * tg3_get_stats to see how this works for 5705 chips. - */ - tw32(HOSTCC_STAT_COAL_TICKS, - DEFAULT_STAT_COAL_TICKS); - tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, - ((u64) tp->stats_mapping >> 32)); - tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW, - ((u64) tp->stats_mapping & 0xffffffff)); - tw32(HOSTCC_STATS_BLK_NIC_ADDR, NIC_SRAM_STATS_BLK); - tw32(HOSTCC_STATUS_BLK_NIC_ADDR, NIC_SRAM_STATUS_BLK); - } - - tw32(HOSTCC_MODE, HOSTCC_MODE_ENABLE | tp->coalesce_mode); - - tw32(RCVCC_MODE, RCVCC_MODE_ENABLE | RCVCC_MODE_ATTN_ENABLE); - tw32(RCVLPC_MODE, RCVLPC_MODE_ENABLE); - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) - tw32(RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE); - - tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | - MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE; - tw32(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR); - tr32(MAC_MODE); - udelay(40); - - tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) - tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OUTPUT1); - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl); - tr32(GRC_LOCAL_CTRL); - udelay(100); - - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0); - tr32(MAILBOX_INTERRUPT_0); - - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { - tw32(DMAC_MODE, DMAC_MODE_ENABLE); - tr32(DMAC_MODE); - udelay(40); - } - - val = (WDMAC_MODE_ENABLE | WDMAC_MODE_TGTABORT_ENAB | - WDMAC_MODE_MSTABORT_ENAB | WDMAC_MODE_PARITYERR_ENAB | - WDMAC_MODE_ADDROFLOW_ENAB | WDMAC_MODE_FIFOOFLOW_ENAB | - WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB | - WDMAC_MODE_LNGREAD_ENAB); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && - (tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) != 0 && - !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) - val |= WDMAC_MODE_RX_ACCEL; - tw32(WDMAC_MODE, val); - tr32(WDMAC_MODE); - udelay(40); - - if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) { - val = tr32(TG3PCI_X_CAPS); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) { - val &= ~PCIX_CAPS_BURST_MASK; - val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT); - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { - val &= ~(PCIX_CAPS_SPLIT_MASK | PCIX_CAPS_BURST_MASK); - val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT); - if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) - val |= (tp->split_mode_max_reqs << - PCIX_CAPS_SPLIT_SHIFT); - } - tw32(TG3PCI_X_CAPS, val); - } - - tw32(RDMAC_MODE, rdmac_mode); - tr32(RDMAC_MODE); - udelay(40); - - tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE); - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) - tw32(MBFREE_MODE, MBFREE_MODE_ENABLE); - tw32(SNDDATAC_MODE, SNDDATAC_MODE_ENABLE); - tw32(SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE); - tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB); - tw32(RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ); - tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE); - tw32(SNDBDI_MODE, SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE); - tw32(SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE); - - if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) { - err = tg3_load_5701_a0_firmware_fix(tp); - if (err) - return err; - } - -#if TG3_TSO_SUPPORT != 0 - if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { - err = tg3_load_tso_firmware(tp); - if (err) - return err; - } -#endif - - tp->tx_mode = TX_MODE_ENABLE; - tw32(MAC_TX_MODE, tp->tx_mode); - tr32(MAC_TX_MODE); - udelay(100); - - tp->rx_mode = RX_MODE_ENABLE; - tw32(MAC_RX_MODE, tp->rx_mode); - tr32(MAC_RX_MODE); - udelay(10); - - if (tp->link_config.phy_is_low_power) { - tp->link_config.phy_is_low_power = 0; - tp->link_config.speed = tp->link_config.orig_speed; - tp->link_config.duplex = tp->link_config.orig_duplex; - tp->link_config.autoneg = tp->link_config.orig_autoneg; - } - - tp->mi_mode = MAC_MI_MODE_BASE; - tw32(MAC_MI_MODE, tp->mi_mode); - tr32(MAC_MI_MODE); - udelay(40); - - tw32(MAC_LED_CTRL, 0); - tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB); - if (tp->phy_id == PHY_ID_SERDES) { - tw32(MAC_RX_MODE, RX_MODE_RESET); - tr32(MAC_RX_MODE); - udelay(10); - } - tw32(MAC_RX_MODE, tp->rx_mode); - tr32(MAC_RX_MODE); - udelay(10); - - if (tp->pci_chip_rev_id == CHIPREV_ID_5703_A1) - tw32(MAC_SERDES_CFG, 0x616000); - - /* Prevent chip from dropping frames when flow control - * is enabled. - */ - tw32(MAC_LOW_WMARK_MAX_RX_FRAME, 2); - tr32(MAC_LOW_WMARK_MAX_RX_FRAME); - - err = tg3_setup_phy(tp); - if (err) - return err; - - if (tp->phy_id != PHY_ID_SERDES) { - u32 tmp; - - /* Clear CRC stats. */ - tg3_readphy(tp, 0x1e, &tmp); - tg3_writephy(tp, 0x1e, tmp | 0x8000); - tg3_readphy(tp, 0x14, &tmp); - } - - __tg3_set_rx_mode(tp->dev); - - /* Initialize receive rules. */ - tw32(MAC_RCV_RULE_0, 0xc2000000 & RCV_RULE_DISABLE_MASK); - tw32(MAC_RCV_VALUE_0, 0xffffffff & RCV_RULE_DISABLE_MASK); - tw32(MAC_RCV_RULE_1, 0x86000004 & RCV_RULE_DISABLE_MASK); - tw32(MAC_RCV_VALUE_1, 0xffffffff & RCV_RULE_DISABLE_MASK); - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) - limit = 8; - else - limit = 16; - if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) - limit -= 4; - switch (limit) { - case 16: - tw32(MAC_RCV_RULE_15, 0); tw32(MAC_RCV_VALUE_15, 0); - case 15: - tw32(MAC_RCV_RULE_14, 0); tw32(MAC_RCV_VALUE_14, 0); - case 14: - tw32(MAC_RCV_RULE_13, 0); tw32(MAC_RCV_VALUE_13, 0); - case 13: - tw32(MAC_RCV_RULE_12, 0); tw32(MAC_RCV_VALUE_12, 0); - case 12: - tw32(MAC_RCV_RULE_11, 0); tw32(MAC_RCV_VALUE_11, 0); - case 11: - tw32(MAC_RCV_RULE_10, 0); tw32(MAC_RCV_VALUE_10, 0); - case 10: - tw32(MAC_RCV_RULE_9, 0); tw32(MAC_RCV_VALUE_9, 0); - case 9: - tw32(MAC_RCV_RULE_8, 0); tw32(MAC_RCV_VALUE_8, 0); - case 8: - tw32(MAC_RCV_RULE_7, 0); tw32(MAC_RCV_VALUE_7, 0); - case 7: - tw32(MAC_RCV_RULE_6, 0); tw32(MAC_RCV_VALUE_6, 0); - case 6: - tw32(MAC_RCV_RULE_5, 0); tw32(MAC_RCV_VALUE_5, 0); - case 5: - tw32(MAC_RCV_RULE_4, 0); tw32(MAC_RCV_VALUE_4, 0); - case 4: - /* tw32(MAC_RCV_RULE_3, 0); tw32(MAC_RCV_VALUE_3, 0); */ - case 3: - /* tw32(MAC_RCV_RULE_2, 0); tw32(MAC_RCV_VALUE_2, 0); */ - case 2: - case 1: - - default: - break; - }; - - if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) - tg3_enable_ints(tp); - - return 0; -} - -/* Called at device open time to get the chip ready for - * packet processing. Invoked with tp->lock held. - */ -static int tg3_init_hw(struct tg3 *tp) -{ - int err; - - /* Force the chip into D0. */ - err = tg3_set_power_state(tp, 0); - if (err) - goto out; - - tg3_switch_clocks(tp); - - tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0); - - err = tg3_reset_hw(tp); - -out: - return err; -} - -#define TG3_STAT_ADD32(PSTAT, REG) \ -do { u32 __val = tr32(REG); \ - (PSTAT)->low += __val; \ - if ((PSTAT)->low < __val) \ - (PSTAT)->high += 1; \ -} while (0) - -static void tg3_periodic_fetch_stats(struct tg3 *tp) -{ - struct tg3_hw_stats *sp = tp->hw_stats; - - if (!netif_carrier_ok(tp->dev)) - return; - - TG3_STAT_ADD32(&sp->tx_octets, MAC_TX_STATS_OCTETS); - TG3_STAT_ADD32(&sp->tx_collisions, MAC_TX_STATS_COLLISIONS); - TG3_STAT_ADD32(&sp->tx_xon_sent, MAC_TX_STATS_XON_SENT); - TG3_STAT_ADD32(&sp->tx_xoff_sent, MAC_TX_STATS_XOFF_SENT); - TG3_STAT_ADD32(&sp->tx_mac_errors, MAC_TX_STATS_MAC_ERRORS); - TG3_STAT_ADD32(&sp->tx_single_collisions, MAC_TX_STATS_SINGLE_COLLISIONS); - TG3_STAT_ADD32(&sp->tx_mult_collisions, MAC_TX_STATS_MULT_COLLISIONS); - TG3_STAT_ADD32(&sp->tx_deferred, MAC_TX_STATS_DEFERRED); - TG3_STAT_ADD32(&sp->tx_excessive_collisions, MAC_TX_STATS_EXCESSIVE_COL); - TG3_STAT_ADD32(&sp->tx_late_collisions, MAC_TX_STATS_LATE_COL); - TG3_STAT_ADD32(&sp->tx_ucast_packets, MAC_TX_STATS_UCAST); - TG3_STAT_ADD32(&sp->tx_mcast_packets, MAC_TX_STATS_MCAST); - TG3_STAT_ADD32(&sp->tx_bcast_packets, MAC_TX_STATS_BCAST); - - TG3_STAT_ADD32(&sp->rx_octets, MAC_RX_STATS_OCTETS); - TG3_STAT_ADD32(&sp->rx_fragments, MAC_RX_STATS_FRAGMENTS); - TG3_STAT_ADD32(&sp->rx_ucast_packets, MAC_RX_STATS_UCAST); - TG3_STAT_ADD32(&sp->rx_mcast_packets, MAC_RX_STATS_MCAST); - TG3_STAT_ADD32(&sp->rx_bcast_packets, MAC_RX_STATS_BCAST); - TG3_STAT_ADD32(&sp->rx_fcs_errors, MAC_RX_STATS_FCS_ERRORS); - TG3_STAT_ADD32(&sp->rx_align_errors, MAC_RX_STATS_ALIGN_ERRORS); - TG3_STAT_ADD32(&sp->rx_xon_pause_rcvd, MAC_RX_STATS_XON_PAUSE_RECVD); - TG3_STAT_ADD32(&sp->rx_xoff_pause_rcvd, MAC_RX_STATS_XOFF_PAUSE_RECVD); - TG3_STAT_ADD32(&sp->rx_mac_ctrl_rcvd, MAC_RX_STATS_MAC_CTRL_RECVD); - TG3_STAT_ADD32(&sp->rx_xoff_entered, MAC_RX_STATS_XOFF_ENTERED); - TG3_STAT_ADD32(&sp->rx_frame_too_long_errors, MAC_RX_STATS_FRAME_TOO_LONG); - TG3_STAT_ADD32(&sp->rx_jabbers, MAC_RX_STATS_JABBERS); - TG3_STAT_ADD32(&sp->rx_undersize_packets, MAC_RX_STATS_UNDERSIZE); -} - -static void tg3_timer(unsigned long __opaque) -{ - struct tg3 *tp = (struct tg3 *) __opaque; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - spin_lock(&tp->tx_lock); - - /* All of this garbage is because when using non-tagged - * IRQ status the mailbox/status_block protocol the chip - * uses with the cpu is race prone. - */ - if (tp->hw_status->status & SD_STATUS_UPDATED) { - tw32(GRC_LOCAL_CTRL, - tp->grc_local_ctrl | GRC_LCLCTRL_SETINT); - } else { - tw32(HOSTCC_MODE, tp->coalesce_mode | - (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW)); - } - - if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { - tp->tg3_flags2 |= TG3_FLG2_RESTART_TIMER; - spin_unlock(&tp->tx_lock); - spin_unlock_irqrestore(&tp->lock, flags); - //schedule_task(&tp->reset_task); - tg3_reset_task(tp); - return; - } - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) - tg3_periodic_fetch_stats(tp); - - /* This part only runs once per second. */ - if (!--tp->timer_counter) { - if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) { - u32 mac_stat; - int phy_event; - - mac_stat = tr32(MAC_STATUS); - - phy_event = 0; - if (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) { - if (mac_stat & MAC_STATUS_MI_INTERRUPT) - phy_event = 1; - } else if (mac_stat & MAC_STATUS_LNKSTATE_CHANGED) - phy_event = 1; - - if (phy_event) - tg3_setup_phy(tp); - } else if (tp->tg3_flags & TG3_FLAG_POLL_SERDES) { - u32 mac_stat = tr32(MAC_STATUS); - int need_setup = 0; - - if (netif_carrier_ok(tp->dev) && - (mac_stat & MAC_STATUS_LNKSTATE_CHANGED)) { - need_setup = 1; - } - if (! netif_carrier_ok(tp->dev) && - (mac_stat & MAC_STATUS_PCS_SYNCED)) { - need_setup = 1; - } - if (need_setup) { - tw32(MAC_MODE, - (tp->mac_mode & - ~MAC_MODE_PORT_MODE_MASK)); - tr32(MAC_MODE); - udelay(40); - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); - udelay(40); - tg3_setup_phy(tp); - } - } - - tp->timer_counter = tp->timer_multiplier; - } - - /* Heartbeat is only sent once every 120 seconds. */ - if (!--tp->asf_counter) { - if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { - u32 val; - - tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_ALIVE); - tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); - tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 3); - val = tr32(GRC_RX_CPU_EVENT); - val |= (1 << 14); - tw32(GRC_RX_CPU_EVENT, val); - } - tp->asf_counter = tp->asf_multiplier; - } - - spin_unlock(&tp->tx_lock); - spin_unlock_irqrestore(&tp->lock, flags); - - tp->timer.expires = jiffies + tp->timer_offset; - add_timer(&tp->timer); -} - -static int tg3_open(struct net_device *dev) -{ - struct tg3 *tp = dev->priv; - int err; - - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - - tg3_disable_ints(tp); - tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; - - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - - /* If you move this call, make sure TG3_FLAG_HOST_TXDS in - * tp->tg3_flags is accurate at that new place. - */ - err = tg3_alloc_consistent(tp); - if (err) - return err; - - err = request_irq(dev->irq, tg3_interrupt, - SA_SHIRQ, dev->name, dev); - - if (err) { - tg3_free_consistent(tp); - return err; - } - - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - - err = tg3_init_hw(tp); - if (err) { - tg3_halt(tp); - tg3_free_rings(tp); - } else { - tp->timer_offset = HZ / 10; - tp->timer_counter = tp->timer_multiplier = 10; - tp->asf_counter = tp->asf_multiplier = (10 * 120); - - init_timer(&tp->timer); - tp->timer.expires = jiffies + tp->timer_offset; - tp->timer.data = (unsigned long) tp; - tp->timer.function = tg3_timer; - add_timer(&tp->timer); - - tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; - } - - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - - if (err) { - free_irq(dev->irq, dev); - tg3_free_consistent(tp); - return err; - } - - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - - tg3_enable_ints(tp); - - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - - netif_start_queue(dev); - - return 0; -} - -#if 0 -/*static*/ void tg3_dump_state(struct tg3 *tp) -{ - u32 val32, val32_2, val32_3, val32_4, val32_5; - u16 val16; - int i; - - pci_read_config_word(tp->pdev, PCI_STATUS, &val16); - pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, &val32); - printk("DEBUG: PCI status [%04x] TG3PCI state[%08x]\n", - val16, val32); - - /* MAC block */ - printk("DEBUG: MAC_MODE[%08x] MAC_STATUS[%08x]\n", - tr32(MAC_MODE), tr32(MAC_STATUS)); - printk(" MAC_EVENT[%08x] MAC_LED_CTRL[%08x]\n", - tr32(MAC_EVENT), tr32(MAC_LED_CTRL)); - printk("DEBUG: MAC_TX_MODE[%08x] MAC_TX_STATUS[%08x]\n", - tr32(MAC_TX_MODE), tr32(MAC_TX_STATUS)); - printk(" MAC_RX_MODE[%08x] MAC_RX_STATUS[%08x]\n", - tr32(MAC_RX_MODE), tr32(MAC_RX_STATUS)); - - /* Send data initiator control block */ - printk("DEBUG: SNDDATAI_MODE[%08x] SNDDATAI_STATUS[%08x]\n", - tr32(SNDDATAI_MODE), tr32(SNDDATAI_STATUS)); - printk(" SNDDATAI_STATSCTRL[%08x]\n", - tr32(SNDDATAI_STATSCTRL)); - - /* Send data completion control block */ - printk("DEBUG: SNDDATAC_MODE[%08x]\n", tr32(SNDDATAC_MODE)); - - /* Send BD ring selector block */ - printk("DEBUG: SNDBDS_MODE[%08x] SNDBDS_STATUS[%08x]\n", - tr32(SNDBDS_MODE), tr32(SNDBDS_STATUS)); - - /* Send BD initiator control block */ - printk("DEBUG: SNDBDI_MODE[%08x] SNDBDI_STATUS[%08x]\n", - tr32(SNDBDI_MODE), tr32(SNDBDI_STATUS)); - - /* Send BD completion control block */ - printk("DEBUG: SNDBDC_MODE[%08x]\n", tr32(SNDBDC_MODE)); - - /* Receive list placement control block */ - printk("DEBUG: RCVLPC_MODE[%08x] RCVLPC_STATUS[%08x]\n", - tr32(RCVLPC_MODE), tr32(RCVLPC_STATUS)); - printk(" RCVLPC_STATSCTRL[%08x]\n", - tr32(RCVLPC_STATSCTRL)); - - /* Receive data and receive BD initiator control block */ - printk("DEBUG: RCVDBDI_MODE[%08x] RCVDBDI_STATUS[%08x]\n", - tr32(RCVDBDI_MODE), tr32(RCVDBDI_STATUS)); - - /* Receive data completion control block */ - printk("DEBUG: RCVDCC_MODE[%08x]\n", - tr32(RCVDCC_MODE)); - - /* Receive BD initiator control block */ - printk("DEBUG: RCVBDI_MODE[%08x] RCVBDI_STATUS[%08x]\n", - tr32(RCVBDI_MODE), tr32(RCVBDI_STATUS)); - - /* Receive BD completion control block */ - printk("DEBUG: RCVCC_MODE[%08x] RCVCC_STATUS[%08x]\n", - tr32(RCVCC_MODE), tr32(RCVCC_STATUS)); - - /* Receive list selector control block */ - printk("DEBUG: RCVLSC_MODE[%08x] RCVLSC_STATUS[%08x]\n", - tr32(RCVLSC_MODE), tr32(RCVLSC_STATUS)); - - /* Mbuf cluster free block */ - printk("DEBUG: MBFREE_MODE[%08x] MBFREE_STATUS[%08x]\n", - tr32(MBFREE_MODE), tr32(MBFREE_STATUS)); - - /* Host coalescing control block */ - printk("DEBUG: HOSTCC_MODE[%08x] HOSTCC_STATUS[%08x]\n", - tr32(HOSTCC_MODE), tr32(HOSTCC_STATUS)); - printk("DEBUG: HOSTCC_STATS_BLK_HOST_ADDR[%08x%08x]\n", - tr32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH), - tr32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW)); - printk("DEBUG: HOSTCC_STATUS_BLK_HOST_ADDR[%08x%08x]\n", - tr32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH), - tr32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW)); - printk("DEBUG: HOSTCC_STATS_BLK_NIC_ADDR[%08x]\n", - tr32(HOSTCC_STATS_BLK_NIC_ADDR)); - printk("DEBUG: HOSTCC_STATUS_BLK_NIC_ADDR[%08x]\n", - tr32(HOSTCC_STATUS_BLK_NIC_ADDR)); - - /* Memory arbiter control block */ - printk("DEBUG: MEMARB_MODE[%08x] MEMARB_STATUS[%08x]\n", - tr32(MEMARB_MODE), tr32(MEMARB_STATUS)); - - /* Buffer manager control block */ - printk("DEBUG: BUFMGR_MODE[%08x] BUFMGR_STATUS[%08x]\n", - tr32(BUFMGR_MODE), tr32(BUFMGR_STATUS)); - printk("DEBUG: BUFMGR_MB_POOL_ADDR[%08x] BUFMGR_MB_POOL_SIZE[%08x]\n", - tr32(BUFMGR_MB_POOL_ADDR), tr32(BUFMGR_MB_POOL_SIZE)); - printk("DEBUG: BUFMGR_DMA_DESC_POOL_ADDR[%08x] " - "BUFMGR_DMA_DESC_POOL_SIZE[%08x]\n", - tr32(BUFMGR_DMA_DESC_POOL_ADDR), - tr32(BUFMGR_DMA_DESC_POOL_SIZE)); - - /* Read DMA control block */ - printk("DEBUG: RDMAC_MODE[%08x] RDMAC_STATUS[%08x]\n", - tr32(RDMAC_MODE), tr32(RDMAC_STATUS)); - - /* Write DMA control block */ - printk("DEBUG: WDMAC_MODE[%08x] WDMAC_STATUS[%08x]\n", - tr32(WDMAC_MODE), tr32(WDMAC_STATUS)); - - /* DMA completion block */ - printk("DEBUG: DMAC_MODE[%08x]\n", - tr32(DMAC_MODE)); - - /* GRC block */ - printk("DEBUG: GRC_MODE[%08x] GRC_MISC_CFG[%08x]\n", - tr32(GRC_MODE), tr32(GRC_MISC_CFG)); - printk("DEBUG: GRC_LOCAL_CTRL[%08x]\n", - tr32(GRC_LOCAL_CTRL)); - - /* TG3_BDINFOs */ - printk("DEBUG: RCVDBDI_JUMBO_BD[%08x%08x:%08x:%08x]\n", - tr32(RCVDBDI_JUMBO_BD + 0x0), - tr32(RCVDBDI_JUMBO_BD + 0x4), - tr32(RCVDBDI_JUMBO_BD + 0x8), - tr32(RCVDBDI_JUMBO_BD + 0xc)); - printk("DEBUG: RCVDBDI_STD_BD[%08x%08x:%08x:%08x]\n", - tr32(RCVDBDI_STD_BD + 0x0), - tr32(RCVDBDI_STD_BD + 0x4), - tr32(RCVDBDI_STD_BD + 0x8), - tr32(RCVDBDI_STD_BD + 0xc)); - printk("DEBUG: RCVDBDI_MINI_BD[%08x%08x:%08x:%08x]\n", - tr32(RCVDBDI_MINI_BD + 0x0), - tr32(RCVDBDI_MINI_BD + 0x4), - tr32(RCVDBDI_MINI_BD + 0x8), - tr32(RCVDBDI_MINI_BD + 0xc)); - - tg3_read_mem(tp, NIC_SRAM_SEND_RCB + 0x0, &val32); - tg3_read_mem(tp, NIC_SRAM_SEND_RCB + 0x4, &val32_2); - tg3_read_mem(tp, NIC_SRAM_SEND_RCB + 0x8, &val32_3); - tg3_read_mem(tp, NIC_SRAM_SEND_RCB + 0xc, &val32_4); - printk("DEBUG: SRAM_SEND_RCB_0[%08x%08x:%08x:%08x]\n", - val32, val32_2, val32_3, val32_4); - - tg3_read_mem(tp, NIC_SRAM_RCV_RET_RCB + 0x0, &val32); - tg3_read_mem(tp, NIC_SRAM_RCV_RET_RCB + 0x4, &val32_2); - tg3_read_mem(tp, NIC_SRAM_RCV_RET_RCB + 0x8, &val32_3); - tg3_read_mem(tp, NIC_SRAM_RCV_RET_RCB + 0xc, &val32_4); - printk("DEBUG: SRAM_RCV_RET_RCB_0[%08x%08x:%08x:%08x]\n", - val32, val32_2, val32_3, val32_4); - - tg3_read_mem(tp, NIC_SRAM_STATUS_BLK + 0x0, &val32); - tg3_read_mem(tp, NIC_SRAM_STATUS_BLK + 0x4, &val32_2); - tg3_read_mem(tp, NIC_SRAM_STATUS_BLK + 0x8, &val32_3); - tg3_read_mem(tp, NIC_SRAM_STATUS_BLK + 0xc, &val32_4); - tg3_read_mem(tp, NIC_SRAM_STATUS_BLK + 0x10, &val32_5); - printk("DEBUG: SRAM_STATUS_BLK[%08x:%08x:%08x:%08x:%08x]\n", - val32, val32_2, val32_3, val32_4, val32_5); - - /* SW status block */ - printk("DEBUG: Host status block [%08x:%08x:(%04x:%04x:%04x):(%04x:%04x)]\n", - tp->hw_status->status, - tp->hw_status->status_tag, - tp->hw_status->rx_jumbo_consumer, - tp->hw_status->rx_consumer, - tp->hw_status->rx_mini_consumer, - tp->hw_status->idx[0].rx_producer, - tp->hw_status->idx[0].tx_consumer); - - /* SW statistics block */ - printk("DEBUG: Host statistics block [%08x:%08x:%08x:%08x]\n", - ((u32 *)tp->hw_stats)[0], - ((u32 *)tp->hw_stats)[1], - ((u32 *)tp->hw_stats)[2], - ((u32 *)tp->hw_stats)[3]); - - /* Mailboxes */ - printk("DEBUG: SNDHOST_PROD[%08x%08x] SNDNIC_PROD[%08x%08x]\n", - tr32(MAILBOX_SNDHOST_PROD_IDX_0 + 0x0), - tr32(MAILBOX_SNDHOST_PROD_IDX_0 + 0x4), - tr32(MAILBOX_SNDNIC_PROD_IDX_0 + 0x0), - tr32(MAILBOX_SNDNIC_PROD_IDX_0 + 0x4)); - - /* NIC side send descriptors. */ - for (i = 0; i < 6; i++) { - unsigned long txd; - - txd = tp->regs + NIC_SRAM_WIN_BASE + NIC_SRAM_TX_BUFFER_DESC - + (i * sizeof(struct tg3_tx_buffer_desc)); - printk("DEBUG: NIC TXD(%d)[%08x:%08x:%08x:%08x]\n", - i, - readl(txd + 0x0), readl(txd + 0x4), - readl(txd + 0x8), readl(txd + 0xc)); - } - - /* NIC side RX descriptors. */ - for (i = 0; i < 6; i++) { - unsigned long rxd; - - rxd = tp->regs + NIC_SRAM_WIN_BASE + NIC_SRAM_RX_BUFFER_DESC - + (i * sizeof(struct tg3_rx_buffer_desc)); - printk("DEBUG: NIC RXD_STD(%d)[0][%08x:%08x:%08x:%08x]\n", - i, - readl(rxd + 0x0), readl(rxd + 0x4), - readl(rxd + 0x8), readl(rxd + 0xc)); - rxd += (4 * sizeof(u32)); - printk("DEBUG: NIC RXD_STD(%d)[1][%08x:%08x:%08x:%08x]\n", - i, - readl(rxd + 0x0), readl(rxd + 0x4), - readl(rxd + 0x8), readl(rxd + 0xc)); - } - - for (i = 0; i < 6; i++) { - unsigned long rxd; - - rxd = tp->regs + NIC_SRAM_WIN_BASE + NIC_SRAM_RX_JUMBO_BUFFER_DESC - + (i * sizeof(struct tg3_rx_buffer_desc)); - printk("DEBUG: NIC RXD_JUMBO(%d)[0][%08x:%08x:%08x:%08x]\n", - i, - readl(rxd + 0x0), readl(rxd + 0x4), - readl(rxd + 0x8), readl(rxd + 0xc)); - rxd += (4 * sizeof(u32)); - printk("DEBUG: NIC RXD_JUMBO(%d)[1][%08x:%08x:%08x:%08x]\n", - i, - readl(rxd + 0x0), readl(rxd + 0x4), - readl(rxd + 0x8), readl(rxd + 0xc)); - } -} -#endif - -static struct net_device_stats *tg3_get_stats(struct net_device *); - -static int tg3_close(struct net_device *dev) -{ - struct tg3 *tp = dev->priv; - - netif_stop_queue(dev); - - del_timer_sync(&tp->timer); - - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); -#if 0 - tg3_dump_state(tp); -#endif - - tg3_disable_ints(tp); - - tg3_halt(tp); - tg3_free_rings(tp); - tp->tg3_flags &= - ~(TG3_FLAG_INIT_COMPLETE | - TG3_FLAG_GOT_SERDES_FLOWCTL); - netif_carrier_off(tp->dev); - - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - - free_irq(dev->irq, dev); - - memcpy(&tp->net_stats_prev, tg3_get_stats(tp->dev), - sizeof(tp->net_stats_prev)); - - tg3_free_consistent(tp); - - return 0; -} - -static inline unsigned long get_stat64(tg3_stat64_t *val) -{ - unsigned long ret; - -#if (BITS_PER_LONG == 32) - ret = val->low; -#else - ret = ((u64)val->high << 32) | ((u64)val->low); -#endif - return ret; -} - -static unsigned long calc_crc_errors(struct tg3 *tp) -{ - struct tg3_hw_stats *hw_stats = tp->hw_stats; - - if (tp->phy_id != PHY_ID_SERDES && - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) { - unsigned long flags; - u32 val; - - spin_lock_irqsave(&tp->lock, flags); - tg3_readphy(tp, 0x1e, &val); - tg3_writephy(tp, 0x1e, val | 0x8000); - tg3_readphy(tp, 0x14, &val); - spin_unlock_irqrestore(&tp->lock, flags); - - tp->phy_crc_errors += val; - - return tp->phy_crc_errors; - } - - return get_stat64(&hw_stats->rx_fcs_errors); -} - -static struct net_device_stats *tg3_get_stats(struct net_device *dev) -{ - struct tg3 *tp = dev->priv; - struct net_device_stats *stats = &tp->net_stats; - struct net_device_stats *old_stats = &tp->net_stats_prev; - struct tg3_hw_stats *hw_stats = tp->hw_stats; - - if (!hw_stats) - return old_stats; - - stats->rx_packets = old_stats->rx_packets + - get_stat64(&hw_stats->rx_ucast_packets) + - get_stat64(&hw_stats->rx_mcast_packets) + - get_stat64(&hw_stats->rx_bcast_packets); - - stats->tx_packets = old_stats->tx_packets + - get_stat64(&hw_stats->tx_ucast_packets) + - get_stat64(&hw_stats->tx_mcast_packets) + - get_stat64(&hw_stats->tx_bcast_packets); - - stats->rx_bytes = old_stats->rx_bytes + - get_stat64(&hw_stats->rx_octets); - stats->tx_bytes = old_stats->tx_bytes + - get_stat64(&hw_stats->tx_octets); - - stats->rx_errors = old_stats->rx_errors + - get_stat64(&hw_stats->rx_errors); - stats->tx_errors = old_stats->tx_errors + - get_stat64(&hw_stats->tx_errors) + - get_stat64(&hw_stats->tx_mac_errors) + - get_stat64(&hw_stats->tx_carrier_sense_errors) + - get_stat64(&hw_stats->tx_discards); - - stats->multicast = old_stats->multicast + - get_stat64(&hw_stats->rx_mcast_packets); - stats->collisions = old_stats->collisions + - get_stat64(&hw_stats->tx_collisions); - - stats->rx_length_errors = old_stats->rx_length_errors + - get_stat64(&hw_stats->rx_frame_too_long_errors) + - get_stat64(&hw_stats->rx_undersize_packets); - - stats->rx_over_errors = old_stats->rx_over_errors + - get_stat64(&hw_stats->rxbds_empty); - stats->rx_frame_errors = old_stats->rx_frame_errors + - get_stat64(&hw_stats->rx_align_errors); - stats->tx_aborted_errors = old_stats->tx_aborted_errors + - get_stat64(&hw_stats->tx_discards); - stats->tx_carrier_errors = old_stats->tx_carrier_errors + - get_stat64(&hw_stats->tx_carrier_sense_errors); - - stats->rx_crc_errors = old_stats->rx_crc_errors + - calc_crc_errors(tp); - - return stats; -} - -static inline u32 calc_crc(unsigned char *buf, int len) -{ - u32 reg; - u32 tmp; - int j, k; - - reg = 0xffffffff; - - for (j = 0; j < len; j++) { - reg ^= buf[j]; - - for (k = 0; k < 8; k++) { - tmp = reg & 0x01; - - reg >>= 1; - - if (tmp) { - reg ^= 0xedb88320; - } - } - } - - return ~reg; -} - -static void tg3_set_multi(struct tg3 *tp, unsigned int accept_all) -{ - /* accept or reject all multicast frames */ - tw32(MAC_HASH_REG_0, accept_all ? 0xffffffff : 0); - tw32(MAC_HASH_REG_1, accept_all ? 0xffffffff : 0); - tw32(MAC_HASH_REG_2, accept_all ? 0xffffffff : 0); - tw32(MAC_HASH_REG_3, accept_all ? 0xffffffff : 0); -} - -static void __tg3_set_rx_mode(struct net_device *dev) -{ - struct tg3 *tp = dev->priv; - u32 rx_mode; - - rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC | - RX_MODE_KEEP_VLAN_TAG); -#if TG3_VLAN_TAG_USED - if (!tp->vlgrp) - rx_mode |= RX_MODE_KEEP_VLAN_TAG; -#else - /* By definition, VLAN is disabled always in this - * case. - */ - rx_mode |= RX_MODE_KEEP_VLAN_TAG; -#endif - - if (dev->flags & IFF_PROMISC) { - /* Promiscuous mode. */ - rx_mode |= RX_MODE_PROMISC; - } else if (dev->flags & IFF_ALLMULTI) { - /* Accept all multicast. */ - tg3_set_multi (tp, 1); - } else if (dev->mc_count < 1) { - /* Reject all multicast. */ - tg3_set_multi (tp, 0); - } else { - /* Accept one or more multicast(s). */ - struct dev_mc_list *mclist; - unsigned int i; - u32 mc_filter[4] = { 0, }; - u32 regidx; - u32 bit; - u32 crc; - - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - - crc = calc_crc (mclist->dmi_addr, ETH_ALEN); - bit = ~crc & 0x7f; - regidx = (bit & 0x60) >> 5; - bit &= 0x1f; - mc_filter[regidx] |= (1 << bit); - } - - tw32(MAC_HASH_REG_0, mc_filter[0]); - tw32(MAC_HASH_REG_1, mc_filter[1]); - tw32(MAC_HASH_REG_2, mc_filter[2]); - tw32(MAC_HASH_REG_3, mc_filter[3]); - } - - if (rx_mode != tp->rx_mode) { - tp->rx_mode = rx_mode; - tw32(MAC_RX_MODE, rx_mode); - tr32(MAC_RX_MODE); - udelay(10); - } -} - -static void tg3_set_rx_mode(struct net_device *dev) -{ - struct tg3 *tp = dev->priv; - - spin_lock_irq(&tp->lock); - __tg3_set_rx_mode(dev); - spin_unlock_irq(&tp->lock); -} - -#ifdef ETHTOOL - -#define TG3_REGDUMP_LEN (32 * 1024) - -static int tg3_get_regs_len(struct net_device *dev) -{ - return TG3_REGDUMP_LEN; -} - -static void tg3_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) -{ - struct tg3 *tp = dev->priv; - u8 *orig_p = p; - int i; - - regs->version = 0; - - memset(p, 0, TG3_REGDUMP_LEN); - - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - -#define __GET_REG32(reg) (*((u32 *)(p))++ = tr32(reg)) -#define GET_REG32_LOOP(base,len) \ -do { p = orig_p + (base); \ - for (i = 0; i < len; i += 4) \ - __GET_REG32((base) + i); \ -} while (0) -#define GET_REG32_1(reg) \ -do { p = orig_p + (reg); \ - __GET_REG32((reg)); \ -} while (0) - - GET_REG32_LOOP(TG3PCI_VENDOR, 0xb0); - GET_REG32_LOOP(MAILBOX_INTERRUPT_0, 0x200); - GET_REG32_LOOP(MAC_MODE, 0x4f0); - GET_REG32_LOOP(SNDDATAI_MODE, 0xe0); - GET_REG32_1(SNDDATAC_MODE); - GET_REG32_LOOP(SNDBDS_MODE, 0x80); - GET_REG32_LOOP(SNDBDI_MODE, 0x48); - GET_REG32_1(SNDBDC_MODE); - GET_REG32_LOOP(RCVLPC_MODE, 0x20); - GET_REG32_LOOP(RCVLPC_SELLST_BASE, 0x15c); - GET_REG32_LOOP(RCVDBDI_MODE, 0x0c); - GET_REG32_LOOP(RCVDBDI_JUMBO_BD, 0x3c); - GET_REG32_LOOP(RCVDBDI_BD_PROD_IDX_0, 0x44); - GET_REG32_1(RCVDCC_MODE); - GET_REG32_LOOP(RCVBDI_MODE, 0x20); - GET_REG32_LOOP(RCVCC_MODE, 0x14); - GET_REG32_LOOP(RCVLSC_MODE, 0x08); - GET_REG32_1(MBFREE_MODE); - GET_REG32_LOOP(HOSTCC_MODE, 0x100); - GET_REG32_LOOP(MEMARB_MODE, 0x10); - GET_REG32_LOOP(BUFMGR_MODE, 0x58); - GET_REG32_LOOP(RDMAC_MODE, 0x08); - GET_REG32_LOOP(WDMAC_MODE, 0x08); - GET_REG32_LOOP(RX_CPU_BASE, 0x280); - GET_REG32_LOOP(TX_CPU_BASE, 0x280); - GET_REG32_LOOP(GRCMBOX_INTERRUPT_0, 0x110); - GET_REG32_LOOP(FTQ_RESET, 0x120); - GET_REG32_LOOP(MSGINT_MODE, 0x0c); - GET_REG32_1(DMAC_MODE); - GET_REG32_LOOP(GRC_MODE, 0x4c); - GET_REG32_LOOP(NVRAM_CMD, 0x24); - -#undef __GET_REG32 -#undef GET_REG32_LOOP -#undef GET_REG32_1 - - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); -} - -#endif /* ETHTOOL */ - -#if 0 -static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct tg3 *tp = dev->priv; - - if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) || - tp->link_config.phy_is_low_power) - return -EAGAIN; - - cmd->supported = (SUPPORTED_Autoneg); - - if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) - cmd->supported |= (SUPPORTED_1000baseT_Half | - SUPPORTED_1000baseT_Full); - - if (tp->phy_id != PHY_ID_SERDES) - cmd->supported |= (SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_MII); - else - cmd->supported |= SUPPORTED_FIBRE; - - cmd->advertising = tp->link_config.advertising; - cmd->speed = tp->link_config.active_speed; - cmd->duplex = tp->link_config.active_duplex; - cmd->port = 0; - cmd->phy_address = PHY_ADDR; - cmd->transceiver = 0; - cmd->autoneg = tp->link_config.autoneg; - cmd->maxtxpkt = 0; - cmd->maxrxpkt = 0; - return 0; -} - -static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct tg3 *tp = dev->priv; - - if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) || - tp->link_config.phy_is_low_power) - return -EAGAIN; - - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - - tp->link_config.autoneg = cmd->autoneg; - if (cmd->autoneg == AUTONEG_ENABLE) { - tp->link_config.advertising = cmd->advertising; - tp->link_config.speed = SPEED_INVALID; - tp->link_config.duplex = DUPLEX_INVALID; - } else { - tp->link_config.speed = cmd->speed; - tp->link_config.duplex = cmd->duplex; - } - - tg3_setup_phy(tp); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void tg3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct tg3 *tp = dev->priv; - - strcpy(info->driver, DRV_MODULE_NAME); - strcpy(info->version, DRV_MODULE_VERSION); - strcpy(info->bus_info, pci_name(tp->pdev)); -} - -static void tg3_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct tg3 *tp = dev->priv; - - wol->supported = WAKE_MAGIC; - wol->wolopts = 0; - if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) - wol->wolopts = WAKE_MAGIC; - memset(&wol->sopass, 0, sizeof(wol->sopass)); -} - -static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct tg3 *tp = dev->priv; - - if (wol->wolopts & ~WAKE_MAGIC) - return -EINVAL; - if ((wol->wolopts & WAKE_MAGIC) && - tp->phy_id == PHY_ID_SERDES && - !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP)) - return -EINVAL; - - spin_lock_irq(&tp->lock); - if (wol->wolopts & WAKE_MAGIC) - tp->tg3_flags |= TG3_FLAG_WOL_ENABLE; - else - tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE; - spin_unlock_irq(&tp->lock); - - return 0; -} - -static u32 tg3_get_msglevel(struct net_device *dev) -{ - struct tg3 *tp = dev->priv; - return tp->msg_enable; -} - -static void tg3_set_msglevel(struct net_device *dev, u32 value) -{ - struct tg3 *tp = dev->priv; - tp->msg_enable = value; -} - -#if TG3_TSO_SUPPORT != 0 -static int tg3_set_tso(struct net_device *dev, u32 value) -{ - struct tg3 *tp = dev->priv; - - if (!(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) { - if (value) - return -EINVAL; - return 0; - } - return ethtool_op_set_tso(dev, value); -} -#endif - -static int tg3_nway_reset(struct net_device *dev) -{ - struct tg3 *tp = dev->priv; - u32 bmcr; - int r; - - spin_lock_irq(&tp->lock); - tg3_readphy(tp, MII_BMCR, &bmcr); - tg3_readphy(tp, MII_BMCR, &bmcr); - r = -EINVAL; - if (bmcr & BMCR_ANENABLE) { - tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART); - r = 0; - } - spin_unlock_irq(&tp->lock); - - return r; -} -#endif /* 0 */ - -#ifdef ETHTOOL - -static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) -{ - struct tg3 *tp = dev->priv; - - ering->rx_max_pending = TG3_RX_RING_SIZE - 1; - ering->rx_mini_max_pending = 0; - ering->rx_jumbo_max_pending = TG3_RX_JUMBO_RING_SIZE - 1; - - ering->rx_pending = tp->rx_pending; - ering->rx_mini_pending = 0; - ering->rx_jumbo_pending = tp->rx_jumbo_pending; - ering->tx_pending = tp->tx_pending; -} - -static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) -{ - struct tg3 *tp = dev->priv; - - if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) || - (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) || - (ering->tx_pending > TG3_TX_RING_SIZE - 1)) - return -EINVAL; - - tg3_netif_stop(tp); - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - - tp->rx_pending = ering->rx_pending; - - if ((tp->tg3_flags2 & TG3_FLG2_MAX_RXPEND_64) && - tp->rx_pending > 63) - tp->rx_pending = 63; - tp->rx_jumbo_pending = ering->rx_jumbo_pending; - tp->tx_pending = ering->tx_pending; - - tg3_halt(tp); - tg3_init_hw(tp); - netif_wake_queue(tp->dev); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - tg3_netif_start(tp); - - return 0; -} - -static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) -{ - struct tg3 *tp = dev->priv; - - epause->autoneg = (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0; - epause->rx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_RX) != 0; - epause->tx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_TX) != 0; -} - -static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) -{ - struct tg3 *tp = dev->priv; - - tg3_netif_stop(tp); - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - if (epause->autoneg) - tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; - else - tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG; - if (epause->rx_pause) - tp->tg3_flags |= TG3_FLAG_PAUSE_RX; - else - tp->tg3_flags &= ~TG3_FLAG_PAUSE_RX; - if (epause->tx_pause) - tp->tg3_flags |= TG3_FLAG_PAUSE_TX; - else - tp->tg3_flags &= ~TG3_FLAG_PAUSE_TX; - tg3_halt(tp); - tg3_init_hw(tp); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - tg3_netif_start(tp); - - return 0; -} - -#endif /* ETHTOOL */ - -#if 0 -static u32 tg3_get_rx_csum(struct net_device *dev) -{ - struct tg3 *tp = dev->priv; - return (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0; -} - -static int tg3_set_rx_csum(struct net_device *dev, u32 data) -{ - struct tg3 *tp = dev->priv; - - if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) { - if (data != 0) - return -EINVAL; - return 0; - } - - spin_lock_irq(&tp->lock); - if (data) - tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS; - else - tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS; - spin_unlock_irq(&tp->lock); - - return 0; -} - -static int tg3_set_tx_csum(struct net_device *dev, u32 data) -{ - struct tg3 *tp = dev->priv; - - if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) { - if (data != 0) - return -EINVAL; - return 0; - } - - if (data) - dev->features |= NETIF_F_IP_CSUM; - else - dev->features &= ~NETIF_F_IP_CSUM; - - return 0; -} -#endif /* 0 */ - -static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data; - struct tg3 *tp = dev->priv; - int err; - - switch(cmd) { - case SIOCGMIIPHY: - data->phy_id = PHY_ADDR; - - /* fallthru */ - case SIOCGMIIREG: { - u32 mii_regval; - - spin_lock_irq(&tp->lock); - err = tg3_readphy(tp, data->reg_num & 0x1f, &mii_regval); - spin_unlock_irq(&tp->lock); - - data->val_out = mii_regval; - - return err; - } - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irq(&tp->lock); - err = tg3_writephy(tp, data->reg_num & 0x1f, data->val_in); - spin_unlock_irq(&tp->lock); - - return err; - - default: - /* do nothing */ - break; - } - return -EOPNOTSUPP; -} - -#if TG3_VLAN_TAG_USED -static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) -{ - struct tg3 *tp = dev->priv; - - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - - tp->vlgrp = grp; - - /* Update RX_MODE_KEEP_VLAN_TAG bit in RX_MODE register. */ - __tg3_set_rx_mode(dev); - - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); -} - -static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) -{ - struct tg3 *tp = dev->priv; - - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - if (tp->vlgrp) - tp->vlgrp->vlan_devices[vid] = NULL; - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); -} -#endif - -#ifdef ETHTOOL -static struct ethtool_ops tg3_ethtool_ops = { - .get_settings = tg3_get_settings, - .set_settings = tg3_set_settings, - .get_drvinfo = tg3_get_drvinfo, - .get_regs_len = tg3_get_regs_len, - .get_regs = tg3_get_regs, - .get_wol = tg3_get_wol, - .set_wol = tg3_set_wol, - .get_msglevel = tg3_get_msglevel, - .set_msglevel = tg3_set_msglevel, - .nway_reset = tg3_nway_reset, - .get_link = ethtool_op_get_link, - .get_ringparam = tg3_get_ringparam, - .set_ringparam = tg3_set_ringparam, - .get_pauseparam = tg3_get_pauseparam, - .set_pauseparam = tg3_set_pauseparam, - .get_rx_csum = tg3_get_rx_csum, - .set_rx_csum = tg3_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = tg3_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, -#if TG3_TSO_SUPPORT != 0 - .get_tso = ethtool_op_get_tso, - .set_tso = tg3_set_tso, -#endif -}; -#endif - -/* Chips other than 5700/5701 use the NVRAM for fetching info. */ -static void __devinit tg3_nvram_init(struct tg3 *tp) -{ - int j; - - if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) - return; - - tw32(GRC_EEPROM_ADDR, - (EEPROM_ADDR_FSM_RESET | - (EEPROM_DEFAULT_CLOCK_PERIOD << - EEPROM_ADDR_CLKPERD_SHIFT))); - - /* XXX schedule_timeout() ... */ - for (j = 0; j < 100; j++) - udelay(10); - - /* Enable seeprom accesses. */ - tw32(GRC_LOCAL_CTRL, - tr32(GRC_LOCAL_CTRL) | GRC_LCLCTRL_AUTO_SEEPROM); - tr32(GRC_LOCAL_CTRL); - udelay(100); - - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) { - u32 nvcfg1 = tr32(NVRAM_CFG1); - - tp->tg3_flags |= TG3_FLAG_NVRAM; - if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) { - if (nvcfg1 & NVRAM_CFG1_BUFFERED_MODE) - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - } else { - nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; - tw32(NVRAM_CFG1, nvcfg1); - } - - } else { - tp->tg3_flags &= ~(TG3_FLAG_NVRAM | TG3_FLAG_NVRAM_BUFFERED); - } -} - -static int __devinit tg3_nvram_read_using_eeprom(struct tg3 *tp, - u32 offset, u32 *val) -{ - u32 tmp; - int i; - - if (offset > EEPROM_ADDR_ADDR_MASK || - (offset % 4) != 0) - return -EINVAL; - - tmp = tr32(GRC_EEPROM_ADDR) & ~(EEPROM_ADDR_ADDR_MASK | - EEPROM_ADDR_DEVID_MASK | - EEPROM_ADDR_READ); - tw32(GRC_EEPROM_ADDR, - tmp | - (0 << EEPROM_ADDR_DEVID_SHIFT) | - ((offset << EEPROM_ADDR_ADDR_SHIFT) & - EEPROM_ADDR_ADDR_MASK) | - EEPROM_ADDR_READ | EEPROM_ADDR_START); - - for (i = 0; i < 10000; i++) { - tmp = tr32(GRC_EEPROM_ADDR); - - if (tmp & EEPROM_ADDR_COMPLETE) - break; - udelay(100); - } - if (!(tmp & EEPROM_ADDR_COMPLETE)) - return -EBUSY; - - *val = tr32(GRC_EEPROM_DATA); - return 0; -} - -static int __devinit tg3_nvram_read(struct tg3 *tp, - u32 offset, u32 *val) -{ - int i, saw_done_clear; - - if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) { - printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 5704\n"); - return -EINVAL; - } - - if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) - return tg3_nvram_read_using_eeprom(tp, offset, val); - - if (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) - offset = ((offset / NVRAM_BUFFERED_PAGE_SIZE) << - NVRAM_BUFFERED_PAGE_POS) + - (offset % NVRAM_BUFFERED_PAGE_SIZE); - - if (offset > NVRAM_ADDR_MSK) - return -EINVAL; - - tw32(NVRAM_SWARB, SWARB_REQ_SET1); - for (i = 0; i < 1000; i++) { - if (tr32(NVRAM_SWARB) & SWARB_GNT1) - break; - udelay(20); - } - - tw32(NVRAM_ADDR, offset); - tw32(NVRAM_CMD, - NVRAM_CMD_RD | NVRAM_CMD_GO | - NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE); - - /* Wait for done bit to clear then set again. */ - saw_done_clear = 0; - for (i = 0; i < 1000; i++) { - udelay(10); - if (!saw_done_clear && - !(tr32(NVRAM_CMD) & NVRAM_CMD_DONE)) - saw_done_clear = 1; - else if (saw_done_clear && - (tr32(NVRAM_CMD) & NVRAM_CMD_DONE)) - break; - } - if (i >= 1000) { - tw32(NVRAM_SWARB, SWARB_REQ_CLR1); - return -EBUSY; - } - - *val = swab32(tr32(NVRAM_RDDATA)); - tw32(NVRAM_SWARB, 0x20); - - return 0; -} - -struct subsys_tbl_ent { - u16 subsys_vendor, subsys_devid; - u32 phy_id; -}; - -static struct subsys_tbl_ent subsys_id_to_phy_id[] = { - /* Broadcom boards. */ - { 0x14e4, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */ - { 0x14e4, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */ - { 0x14e4, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */ - { 0x14e4, 0x0003, PHY_ID_SERDES }, /* BCM95700A9 */ - { 0x14e4, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */ - { 0x14e4, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */ - { 0x14e4, 0x0007, PHY_ID_SERDES }, /* BCM95701A7 */ - { 0x14e4, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */ - { 0x14e4, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */ - { 0x14e4, 0x0009, PHY_ID_BCM5701 }, /* BCM95703Ax1 */ - { 0x14e4, 0x8009, PHY_ID_BCM5701 }, /* BCM95703Ax2 */ - - /* 3com boards. */ - { PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */ - { PCI_VENDOR_ID_3COM, 0x1006, PHY_ID_BCM5701 }, /* 3C996BT */ - /* { PCI_VENDOR_ID_3COM, 0x1002, PHY_ID_XXX }, 3C996CT */ - /* { PCI_VENDOR_ID_3COM, 0x1003, PHY_ID_XXX }, 3C997T */ - { PCI_VENDOR_ID_3COM, 0x1004, PHY_ID_SERDES }, /* 3C996SX */ - /* { PCI_VENDOR_ID_3COM, 0x1005, PHY_ID_XXX }, 3C997SZ */ - { PCI_VENDOR_ID_3COM, 0x1007, PHY_ID_BCM5701 }, /* 3C1000T */ - { PCI_VENDOR_ID_3COM, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */ - - /* DELL boards. */ - { PCI_VENDOR_ID_DELL, 0x00d1, PHY_ID_BCM5401 }, /* VIPER */ - { PCI_VENDOR_ID_DELL, 0x0106, PHY_ID_BCM5401 }, /* JAGUAR */ - { PCI_VENDOR_ID_DELL, 0x0109, PHY_ID_BCM5411 }, /* MERLOT */ - { PCI_VENDOR_ID_DELL, 0x010a, PHY_ID_BCM5411 }, /* SLIM_MERLOT */ - - /* Compaq boards. */ - { PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */ - { PCI_VENDOR_ID_COMPAQ, 0x009a, PHY_ID_BCM5701 }, /* BANSHEE_2 */ - { PCI_VENDOR_ID_COMPAQ, 0x007d, PHY_ID_SERDES }, /* CHANGELING */ - { PCI_VENDOR_ID_COMPAQ, 0x0085, PHY_ID_BCM5701 }, /* NC7780 */ - { PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 } /* NC7780_2 */ -}; - -static int __devinit tg3_phy_probe(struct tg3 *tp) -{ - u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2; - u32 hw_phy_id, hw_phy_id_masked; - enum phy_led_mode eeprom_led_mode; - u32 val; - int i, eeprom_signature_found, err; - - tp->phy_id = PHY_ID_INVALID; - for (i = 0; i < ARRAY_SIZE(subsys_id_to_phy_id); i++) { - if ((subsys_id_to_phy_id[i].subsys_vendor == - tp->pdev->subsystem_vendor) && - (subsys_id_to_phy_id[i].subsys_devid == - tp->pdev->subsystem_device)) { - tp->phy_id = subsys_id_to_phy_id[i].phy_id; - break; - } - } - - eeprom_phy_id = PHY_ID_INVALID; - eeprom_led_mode = led_mode_auto; - eeprom_signature_found = 0; - tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); - if (val == NIC_SRAM_DATA_SIG_MAGIC) { - u32 nic_cfg; - - tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg); - tp->nic_sram_data_cfg = nic_cfg; - - eeprom_signature_found = 1; - - if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) == - NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) { - eeprom_phy_id = PHY_ID_SERDES; - } else { - u32 nic_phy_id; - - tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id); - if (nic_phy_id != 0) { - u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK; - u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK; - - eeprom_phy_id = (id1 >> 16) << 10; - eeprom_phy_id |= (id2 & 0xfc00) << 16; - eeprom_phy_id |= (id2 & 0x03ff) << 0; - } - } - - switch (nic_cfg & NIC_SRAM_DATA_CFG_LED_MODE_MASK) { - case NIC_SRAM_DATA_CFG_LED_TRIPLE_SPD: - eeprom_led_mode = led_mode_three_link; - break; - - case NIC_SRAM_DATA_CFG_LED_LINK_SPD: - eeprom_led_mode = led_mode_link10; - break; - - default: - eeprom_led_mode = led_mode_auto; - break; - }; - - if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) && - (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)) - tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; - - if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) - tp->tg3_flags |= TG3_FLAG_ENABLE_ASF; - if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL) - tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP; - } - - /* Now read the physical PHY_ID from the chip and verify - * that it is sane. If it doesn't look good, we fall back - * to either the hard-coded table based PHY_ID and failing - * that the value found in the eeprom area. - */ - err = tg3_readphy(tp, MII_PHYSID1, &hw_phy_id_1); - err |= tg3_readphy(tp, MII_PHYSID2, &hw_phy_id_2); - - hw_phy_id = (hw_phy_id_1 & 0xffff) << 10; - hw_phy_id |= (hw_phy_id_2 & 0xfc00) << 16; - hw_phy_id |= (hw_phy_id_2 & 0x03ff) << 0; - - hw_phy_id_masked = hw_phy_id & PHY_ID_MASK; - - if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) { - tp->phy_id = hw_phy_id; - } else { - /* phy_id currently holds the value found in the - * subsys_id_to_phy_id[] table or PHY_ID_INVALID - * if a match was not found there. - */ - if (tp->phy_id == PHY_ID_INVALID) { - if (!eeprom_signature_found || - !KNOWN_PHY_ID(eeprom_phy_id & PHY_ID_MASK)) - return -ENODEV; - tp->phy_id = eeprom_phy_id; - } - } - - err = tg3_phy_reset(tp, 1); - if (err) - return err; - - if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) { - u32 mii_tg3_ctrl; - - /* These chips, when reset, only advertise 10Mb - * capabilities. Fix that. - */ - err = tg3_writephy(tp, MII_ADVERTISE, - (ADVERTISE_CSMA | - ADVERTISE_PAUSE_CAP | - ADVERTISE_10HALF | - ADVERTISE_10FULL | - ADVERTISE_100HALF | - ADVERTISE_100FULL)); - mii_tg3_ctrl = (MII_TG3_CTRL_ADV_1000_HALF | - MII_TG3_CTRL_ADV_1000_FULL | - MII_TG3_CTRL_AS_MASTER | - MII_TG3_CTRL_ENABLE_AS_MASTER); - if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) - mii_tg3_ctrl = 0; - - err |= tg3_writephy(tp, MII_TG3_CTRL, mii_tg3_ctrl); - err |= tg3_writephy(tp, MII_BMCR, - (BMCR_ANRESTART | BMCR_ANENABLE)); - } - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) { - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f); - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x2aaa); - } - - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) && - (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)) { - tg3_writephy(tp, 0x1c, 0x8d68); - tg3_writephy(tp, 0x1c, 0x8d68); - } - - /* Enable Ethernet@WireSpeed */ - tg3_phy_set_wirespeed(tp); - - if (!err && ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)) { - err = tg3_init_5401phy_dsp(tp); - } - - /* Determine the PHY led mode. */ - if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) { - tp->led_mode = led_mode_link10; - } else { - tp->led_mode = led_mode_three_link; - if (eeprom_signature_found && - eeprom_led_mode != led_mode_auto) - tp->led_mode = eeprom_led_mode; - } - - if (tp->phy_id == PHY_ID_SERDES) - tp->link_config.advertising = - (ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full | - ADVERTISED_Autoneg | - ADVERTISED_FIBRE); - if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) - tp->link_config.advertising &= - ~(ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full); - - return err; -} - -static void __devinit tg3_read_partno(struct tg3 *tp) -{ - unsigned char vpd_data[256]; - int i; - - if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) { - /* Sun decided not to put the necessary bits in the - * NVRAM of their onboard tg3 parts :( - */ - strcpy(tp->board_part_number, "Sun 5704"); - return; - } - - for (i = 0; i < 256; i += 4) { - u32 tmp; - - if (tg3_nvram_read(tp, 0x100 + i, &tmp)) - goto out_not_found; - - vpd_data[i + 0] = ((tmp >> 0) & 0xff); - vpd_data[i + 1] = ((tmp >> 8) & 0xff); - vpd_data[i + 2] = ((tmp >> 16) & 0xff); - vpd_data[i + 3] = ((tmp >> 24) & 0xff); - } - - /* Now parse and find the part number. */ - for (i = 0; i < 256; ) { - unsigned char val = vpd_data[i]; - int block_end; - - if (val == 0x82 || val == 0x91) { - i = (i + 3 + - (vpd_data[i + 1] + - (vpd_data[i + 2] << 8))); - continue; - } - - if (val != 0x90) - goto out_not_found; - - block_end = (i + 3 + - (vpd_data[i + 1] + - (vpd_data[i + 2] << 8))); - i += 3; - while (i < block_end) { - if (vpd_data[i + 0] == 'P' && - vpd_data[i + 1] == 'N') { - int partno_len = vpd_data[i + 2]; - - if (partno_len > 24) - goto out_not_found; - - memcpy(tp->board_part_number, - &vpd_data[i + 3], - partno_len); - - /* Success. */ - return; - } - } - - /* Part number not found. */ - goto out_not_found; - } - -out_not_found: - strcpy(tp->board_part_number, "none"); -} - -#ifdef CONFIG_SPARC64 -static int __devinit tg3_is_sun_5704(struct tg3 *tp) -{ - struct pci_dev *pdev = tp->pdev; - struct pcidev_cookie *pcp = pdev->sysdata; - - if (pcp != NULL) { - int node = pcp->prom_node; - u32 venid, devid; - int err; - - err = prom_getproperty(node, "subsystem-vendor-id", - (char *) &venid, sizeof(venid)); - if (err == 0 || err == -1) - return 0; - err = prom_getproperty(node, "subsystem-id", - (char *) &devid, sizeof(devid)); - if (err == 0 || err == -1) - return 0; - - if (venid == PCI_VENDOR_ID_SUN && - devid == PCI_DEVICE_ID_TIGON3_5704) - return 1; - } - return 0; -} -#endif - -static int __devinit tg3_get_invariants(struct tg3 *tp) -{ - u32 misc_ctrl_reg; - u32 cacheline_sz_reg; - u32 pci_state_reg, grc_misc_cfg; - u16 pci_cmd; - int err; - -#ifdef CONFIG_SPARC64 - if (tg3_is_sun_5704(tp)) - tp->tg3_flags2 |= TG3_FLG2_SUN_5704; -#endif - - /* If we have an AMD 762 or Intel ICH/ICH0/ICH2 chipset, write - * reordering to the mailbox registers done by the host - * controller can cause major troubles. We read back from - * every mailbox register write to force the writes to be - * posted to the chip in order. - */ - if (pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82801AA_8, NULL) || - pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82801AB_8, NULL) || - pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82801BA_11, NULL) || - pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82801BA_6, NULL) || - pci_find_device(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_FE_GATE_700C, NULL)) - tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER; - - /* Force memory write invalidate off. If we leave it on, - * then on 5700_BX chips we have to enable a workaround. - * The workaround is to set the TG3PCI_DMA_RW_CTRL boundary - * to match the cacheline size. The Broadcom driver have this - * workaround but turns MWI off all the times so never uses - * it. This seems to suggest that the workaround is insufficient. - */ - pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd); - pci_cmd &= ~PCI_COMMAND_INVALIDATE; - pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd); - - /* It is absolutely critical that TG3PCI_MISC_HOST_CTRL - * has the register indirect write enable bit set before - * we try to access any of the MMIO registers. It is also - * critical that the PCI-X hw workaround situation is decided - * before that as well. - */ - pci_read_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, - &misc_ctrl_reg); - - tp->pci_chip_rev_id = (misc_ctrl_reg >> - MISC_HOST_CTRL_CHIPREV_SHIFT); - - /* Initialize misc host control in PCI block. */ - tp->misc_host_ctrl |= (misc_ctrl_reg & - MISC_HOST_CTRL_CHIPREV); - pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, - tp->misc_host_ctrl); - - pci_read_config_dword(tp->pdev, TG3PCI_CACHELINESZ, - &cacheline_sz_reg); - - tp->pci_cacheline_sz = (cacheline_sz_reg >> 0) & 0xff; - tp->pci_lat_timer = (cacheline_sz_reg >> 8) & 0xff; - tp->pci_hdr_type = (cacheline_sz_reg >> 16) & 0xff; - tp->pci_bist = (cacheline_sz_reg >> 24) & 0xff; - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 && - tp->pci_lat_timer < 64) { - tp->pci_lat_timer = 64; - - cacheline_sz_reg = ((tp->pci_cacheline_sz & 0xff) << 0); - cacheline_sz_reg |= ((tp->pci_lat_timer & 0xff) << 8); - cacheline_sz_reg |= ((tp->pci_hdr_type & 0xff) << 16); - cacheline_sz_reg |= ((tp->pci_bist & 0xff) << 24); - - pci_write_config_dword(tp->pdev, TG3PCI_CACHELINESZ, - cacheline_sz_reg); - } - - pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, - &pci_state_reg); - - if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0) { - tp->tg3_flags |= TG3_FLAG_PCIX_MODE; - - /* If this is a 5700 BX chipset, and we are in PCI-X - * mode, enable register write workaround. - * - * The workaround is to use indirect register accesses - * for all chip writes not to mailbox registers. - */ - if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) { - u32 pm_reg; - u16 pci_cmd; - - tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG; - - /* The chip can have it's power management PCI config - * space registers clobbered due to this bug. - * So explicitly force the chip into D0 here. - */ - pci_read_config_dword(tp->pdev, TG3PCI_PM_CTRL_STAT, - &pm_reg); - pm_reg &= ~PCI_PM_CTRL_STATE_MASK; - pm_reg |= PCI_PM_CTRL_PME_ENABLE | 0 /* D0 */; - pci_write_config_dword(tp->pdev, TG3PCI_PM_CTRL_STAT, - pm_reg); - - /* Also, force SERR#/PERR# in PCI command. */ - pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd); - pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; - pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd); - } - } - - /* Back to back register writes can cause problems on this chip, - * the workaround is to read back all reg writes except those to - * mailbox regs. See tg3_write_indirect_reg32(). - */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) - tp->tg3_flags |= TG3_FLAG_5701_REG_WRITE_BUG; - - if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0) - tp->tg3_flags |= TG3_FLAG_PCI_HIGH_SPEED; - if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0) - tp->tg3_flags |= TG3_FLAG_PCI_32BIT; - - /* Chip-specific fixup from Broadcom driver */ - if ((tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) && - (!(pci_state_reg & PCISTATE_RETRY_SAME_DMA))) { - pci_state_reg |= PCISTATE_RETRY_SAME_DMA; - pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, pci_state_reg); - } - - /* Force the chip into D0. */ - err = tg3_set_power_state(tp, 0); - if (err) { - printk(KERN_ERR PFX "(%s) transition to D0 failed\n", - tp->pdev->slot_name); - return err; - } - - /* 5700 B0 chips do not support checksumming correctly due - * to hardware bugs. - */ - if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0) - tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS; - - /* Pseudo-header checksum is done by hardware logic and not - * the offload processers, so make the chip do the pseudo- - * header checksums on receive. For transmit it is more - * convenient to do the pseudo-header checksum in software - * as Linux does that on transmit for us in all cases. - */ - tp->tg3_flags |= TG3_FLAG_NO_TX_PSEUDO_CSUM; - tp->tg3_flags &= ~TG3_FLAG_NO_RX_PSEUDO_CSUM; - - /* Derive initial jumbo mode from MTU assigned in - * ether_setup() via the alloc_etherdev() call - */ - if (tp->dev->mtu > ETH_DATA_LEN) - tp->tg3_flags |= TG3_FLAG_JUMBO_ENABLE; - - /* Determine WakeOnLan speed to use. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5701_B0 || - tp->pci_chip_rev_id == CHIPREV_ID_5701_B2) { - tp->tg3_flags &= ~(TG3_FLAG_WOL_SPEED_100MB); - } else { - tp->tg3_flags |= TG3_FLAG_WOL_SPEED_100MB; - } - - /* A few boards don't want Ethernet@WireSpeed phy feature */ - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) || - ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) && - (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) && - (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1))) - tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED; - - /* Only 5701 and later support tagged irq status mode. - * Also, 5788 chips cannot use tagged irq status. - * - * However, since we are using NAPI avoid tagged irq status - * because the interrupt condition is more difficult to - * fully clear in that mode. - */ - tp->coalesce_mode = 0; - - if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX && - GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX) - tp->coalesce_mode |= HOSTCC_MODE_32BYTE; - - /* Initialize MAC MI mode, polling disabled. */ - tw32(MAC_MI_MODE, tp->mi_mode); - tr32(MAC_MI_MODE); - udelay(40); - - /* Initialize data/descriptor byte/word swapping. */ - tw32(GRC_MODE, tp->grc_mode); - - tg3_switch_clocks(tp); - - /* Clear this out for sanity. */ - tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0); - - pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, - &pci_state_reg); - if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0 && - (tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) == 0) { - u32 chiprevid = GET_CHIP_REV_ID(tp->misc_host_ctrl); - - if (chiprevid == CHIPREV_ID_5701_A0 || - chiprevid == CHIPREV_ID_5701_B0 || - chiprevid == CHIPREV_ID_5701_B2 || - chiprevid == CHIPREV_ID_5701_B5) { - unsigned long sram_base; - - /* Write some dummy words into the SRAM status block - * area, see if it reads back correctly. If the return - * value is bad, force enable the PCIX workaround. - */ - sram_base = tp->regs + NIC_SRAM_WIN_BASE + NIC_SRAM_STATS_BLK; - - writel(0x00000000, sram_base); - writel(0x00000000, sram_base + 4); - writel(0xffffffff, sram_base + 4); - if (readl(sram_base) != 0x00000000) - tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG; - } - } - - udelay(50); - tg3_nvram_init(tp); - - /* Determine if TX descriptors will reside in - * main memory or in the chip SRAM. - */ - if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) - tp->tg3_flags |= TG3_FLAG_HOST_TXDS; - - grc_misc_cfg = tr32(GRC_MISC_CFG); - grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK; - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && - grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) { - tp->tg3_flags |= TG3_FLAG_SPLIT_MODE; - tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ; - } - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && - (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 || - grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M)) - tp->tg3_flags2 |= TG3_FLG2_IS_5788; - - /* these are limited to 10/100 only */ - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 && - (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && - tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM && - (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901 || - tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2))) - tp->tg3_flags |= TG3_FLAG_10_100_ONLY; - - err = tg3_phy_probe(tp); - if (err) { - printk(KERN_ERR PFX "(%s) phy probe failed, err %d\n", - tp->pdev->slot_name, err); - /* ... but do not return immediately ... */ - } - - tg3_read_partno(tp); - - if (tp->phy_id == PHY_ID_SERDES) { - tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT; - - /* And override led_mode in case Dell ever makes - * a fibre board. - */ - tp->led_mode = led_mode_three_link; - } else { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) - tp->tg3_flags |= TG3_FLAG_USE_MI_INTERRUPT; - else - tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT; - } - - /* 5700 {AX,BX} chips have a broken status block link - * change bit implementation, so we must use the - * status register in those cases. - */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) - tp->tg3_flags |= TG3_FLAG_USE_LINKCHG_REG; - else - tp->tg3_flags &= ~TG3_FLAG_USE_LINKCHG_REG; - - /* The led_mode is set during tg3_phy_probe, here we might - * have to force the link status polling mechanism based - * upon subsystem IDs. - */ - if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL && - tp->phy_id != PHY_ID_SERDES) { - tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT | - TG3_FLAG_USE_LINKCHG_REG); - } - - /* For all SERDES we poll the MAC status register. */ - if (tp->phy_id == PHY_ID_SERDES) - tp->tg3_flags |= TG3_FLAG_POLL_SERDES; - else - tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES; - - /* 5700 BX chips need to have their TX producer index mailboxes - * written twice to workaround a bug. - */ - if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) - tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG; - else - tp->tg3_flags &= ~TG3_FLAG_TXD_MBOX_HWBUG; - - /* 5700 chips can get confused if TX buffers straddle the - * 4GB address boundary in some cases. - */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) - tp->dev->hard_start_xmit = tg3_start_xmit_4gbug; - else - tp->dev->hard_start_xmit = tg3_start_xmit; - - tp->rx_offset = 2; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 && - (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) - tp->rx_offset = 0; - - /* By default, disable wake-on-lan. User can change this - * using ETHTOOL_SWOL. - */ - tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE; - - return err; -} - -#ifdef CONFIG_SPARC64 -static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp) -{ - struct net_device *dev = tp->dev; - struct pci_dev *pdev = tp->pdev; - struct pcidev_cookie *pcp = pdev->sysdata; - - if (pcp != NULL) { - int node = pcp->prom_node; - - if (prom_getproplen(node, "local-mac-address") == 6) { - prom_getproperty(node, "local-mac-address", - dev->dev_addr, 6); - return 0; - } - } - return -ENODEV; -} - -static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp) -{ - struct net_device *dev = tp->dev; - - memcpy(dev->dev_addr, idprom->id_ethaddr, 6); - return 0; -} -#endif - -static int __devinit tg3_get_device_address(struct tg3 *tp) -{ - struct net_device *dev = tp->dev; - u32 hi, lo, mac_offset; - -#ifdef CONFIG_SPARC64 - if (!tg3_get_macaddr_sparc(tp)) - return 0; -#endif - - if (PCI_FUNC(tp->pdev->devfn) == 0) - mac_offset = 0x7c; - else - mac_offset = 0xcc; - - /* First try to get it from MAC address mailbox. */ - tg3_read_mem(tp, NIC_SRAM_MAC_ADDR_HIGH_MBOX, &hi); - if ((hi >> 16) == 0x484b) { - dev->dev_addr[0] = (hi >> 8) & 0xff; - dev->dev_addr[1] = (hi >> 0) & 0xff; - - tg3_read_mem(tp, NIC_SRAM_MAC_ADDR_LOW_MBOX, &lo); - dev->dev_addr[2] = (lo >> 24) & 0xff; - dev->dev_addr[3] = (lo >> 16) & 0xff; - dev->dev_addr[4] = (lo >> 8) & 0xff; - dev->dev_addr[5] = (lo >> 0) & 0xff; - } - /* Next, try NVRAM. */ - else if (!(tp->tg3_flags & TG3_FLG2_SUN_5704) && - !tg3_nvram_read(tp, mac_offset + 0, &hi) && - !tg3_nvram_read(tp, mac_offset + 4, &lo)) { - dev->dev_addr[0] = ((hi >> 16) & 0xff); - dev->dev_addr[1] = ((hi >> 24) & 0xff); - dev->dev_addr[2] = ((lo >> 0) & 0xff); - dev->dev_addr[3] = ((lo >> 8) & 0xff); - dev->dev_addr[4] = ((lo >> 16) & 0xff); - dev->dev_addr[5] = ((lo >> 24) & 0xff); - } - /* Finally just fetch it out of the MAC control regs. */ - else { - hi = tr32(MAC_ADDR_0_HIGH); - lo = tr32(MAC_ADDR_0_LOW); - - dev->dev_addr[5] = lo & 0xff; - dev->dev_addr[4] = (lo >> 8) & 0xff; - dev->dev_addr[3] = (lo >> 16) & 0xff; - dev->dev_addr[2] = (lo >> 24) & 0xff; - dev->dev_addr[1] = hi & 0xff; - dev->dev_addr[0] = (hi >> 8) & 0xff; - } - - if (!is_valid_ether_addr(&dev->dev_addr[0])) { -#ifdef CONFIG_SPARC64 - if (!tg3_get_default_macaddr_sparc(tp)) - return 0; -#endif - return -EINVAL; - } - return 0; -} - -static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma, int size, int to_device) -{ - struct tg3_internal_buffer_desc test_desc; - u32 sram_dma_descs; - int i, ret; - - sram_dma_descs = NIC_SRAM_DMA_DESC_POOL_BASE; - - tw32(FTQ_RCVBD_COMP_FIFO_ENQDEQ, 0); - tw32(FTQ_RCVDATA_COMP_FIFO_ENQDEQ, 0); - tw32(RDMAC_STATUS, 0); - tw32(WDMAC_STATUS, 0); - - tw32(BUFMGR_MODE, 0); - tw32(FTQ_RESET, 0); - - /* pci_alloc_consistent gives only non-DAC addresses */ - test_desc.addr_hi = 0; - test_desc.addr_lo = buf_dma & 0xffffffff; - test_desc.nic_mbuf = 0x00002100; - test_desc.len = size; - if (to_device) { - test_desc.cqid_sqid = (13 << 8) | 2; - tw32(RDMAC_MODE, RDMAC_MODE_RESET); - tr32(RDMAC_MODE); - udelay(40); - - tw32(RDMAC_MODE, RDMAC_MODE_ENABLE); - tr32(RDMAC_MODE); - udelay(40); - } else { - test_desc.cqid_sqid = (16 << 8) | 7; - tw32(WDMAC_MODE, WDMAC_MODE_RESET); - tr32(WDMAC_MODE); - udelay(40); - - tw32(WDMAC_MODE, WDMAC_MODE_ENABLE); - tr32(WDMAC_MODE); - udelay(40); - } - test_desc.flags = 0x00000004; - - for (i = 0; i < (sizeof(test_desc) / sizeof(u32)); i++) { - u32 val; - - val = *(((u32 *)&test_desc) + i); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, - sram_dma_descs + (i * sizeof(u32))); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); - } - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); - - if (to_device) { - tw32(FTQ_DMA_HIGH_READ_FIFO_ENQDEQ, sram_dma_descs); - } else { - tw32(FTQ_DMA_HIGH_WRITE_FIFO_ENQDEQ, sram_dma_descs); - } - - ret = -ENODEV; - for (i = 0; i < 40; i++) { - u32 val; - - if (to_device) - val = tr32(FTQ_RCVBD_COMP_FIFO_ENQDEQ); - else - val = tr32(FTQ_RCVDATA_COMP_FIFO_ENQDEQ); - if ((val & 0xffff) == sram_dma_descs) { - ret = 0; - break; - } - - udelay(100); - } - - return ret; -} - -#define TEST_BUFFER_SIZE 0x400 - -static int __devinit tg3_test_dma(struct tg3 *tp) -{ - dma_addr_t buf_dma; - u32 *buf; - int ret; - - buf = pci_alloc_consistent(tp->pdev, TEST_BUFFER_SIZE, &buf_dma); - if (!buf) { - ret = -ENOMEM; - goto out_nofree; - } - - if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) == 0) { - tp->dma_rwctrl = - (0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) | - (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) | - (0x7 << DMA_RWCTRL_WRITE_WATER_SHIFT) | - (0x7 << DMA_RWCTRL_READ_WATER_SHIFT) | - (0x0f << DMA_RWCTRL_MIN_DMA_SHIFT); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) - tp->dma_rwctrl &= ~(DMA_RWCTRL_MIN_DMA - << DMA_RWCTRL_MIN_DMA_SHIFT); - } else { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) - tp->dma_rwctrl = - (0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) | - (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) | - (0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) | - (0x7 << DMA_RWCTRL_READ_WATER_SHIFT) | - (0x00 << DMA_RWCTRL_MIN_DMA_SHIFT); - else - tp->dma_rwctrl = - (0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) | - (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) | - (0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) | - (0x3 << DMA_RWCTRL_READ_WATER_SHIFT) | - (0x0f << DMA_RWCTRL_MIN_DMA_SHIFT); - - /* Wheee, some more chip bugs... */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { - u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f); - - if (ccval == 0x6 || ccval == 0x7) - tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA; - } - } - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) - tp->dma_rwctrl &= ~(DMA_RWCTRL_MIN_DMA - << DMA_RWCTRL_MIN_DMA_SHIFT); - - /* We don't do this on x86 because it seems to hurt performace. - * It does help things on other platforms though. - */ -#ifndef CONFIG_X86 - { - u8 byte; - int cacheline_size; - pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, &byte); - - if (byte == 0) - cacheline_size = 1024; - else - cacheline_size = (int) byte * 4; - - tp->dma_rwctrl &= ~(DMA_RWCTRL_READ_BNDRY_MASK | - DMA_RWCTRL_WRITE_BNDRY_MASK); - - switch (cacheline_size) { - case 16: - tp->dma_rwctrl |= - (DMA_RWCTRL_READ_BNDRY_16 | - DMA_RWCTRL_WRITE_BNDRY_16); - break; - - case 32: - tp->dma_rwctrl |= - (DMA_RWCTRL_READ_BNDRY_32 | - DMA_RWCTRL_WRITE_BNDRY_32); - break; - - case 64: - tp->dma_rwctrl |= - (DMA_RWCTRL_READ_BNDRY_64 | - DMA_RWCTRL_WRITE_BNDRY_64); - break; - - case 128: - tp->dma_rwctrl |= - (DMA_RWCTRL_READ_BNDRY_128 | - DMA_RWCTRL_WRITE_BNDRY_128); - break; - - case 256: - tp->dma_rwctrl |= - (DMA_RWCTRL_READ_BNDRY_256 | - DMA_RWCTRL_WRITE_BNDRY_256); - break; - - case 512: - tp->dma_rwctrl |= - (DMA_RWCTRL_READ_BNDRY_512 | - DMA_RWCTRL_WRITE_BNDRY_512); - break; - - case 1024: - tp->dma_rwctrl |= - (DMA_RWCTRL_READ_BNDRY_1024 | - DMA_RWCTRL_WRITE_BNDRY_1024); - break; - }; - } -#endif - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { - /* Remove this if it causes problems for some boards. */ - tp->dma_rwctrl |= DMA_RWCTRL_USE_MEM_READ_MULT; - } - - tp->dma_rwctrl |= DMA_RWCTRL_ASSERT_ALL_BE; - - tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl); - -#if 0 - /* Unneeded, already done by tg3_get_invariants. */ - tg3_switch_clocks(tp); -#endif - - ret = 0; - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) - goto out; - - while (1) { - u32 *p, i; - - p = buf; - for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) - p[i] = i; - - /* Send the buffer to the chip. */ - ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 1); - if (ret) - break; - - p = buf; - for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) - p[i] = 0; - - /* Now read it back. */ - ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 0); - if (ret) - break; - - /* Verify it. */ - p = buf; - for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) { - if (p[i] == i) - continue; - - if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) == - DMA_RWCTRL_WRITE_BNDRY_DISAB) { - tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16; - tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl); - break; - } else { - ret = -ENODEV; - goto out; - } - } - - if (i == (TEST_BUFFER_SIZE / sizeof(u32))) { - /* Success. */ - ret = 0; - break; - } - } - -out: - pci_free_consistent(tp->pdev, TEST_BUFFER_SIZE, buf, buf_dma); -out_nofree: - return ret; -} - -static void __devinit tg3_init_link_config(struct tg3 *tp) -{ - tp->link_config.advertising = - (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | - ADVERTISED_Autoneg | ADVERTISED_MII); - tp->link_config.speed = SPEED_INVALID; - tp->link_config.duplex = DUPLEX_INVALID; - tp->link_config.autoneg = AUTONEG_ENABLE; - netif_carrier_off(tp->dev); - tp->link_config.active_speed = SPEED_INVALID; - tp->link_config.active_duplex = DUPLEX_INVALID; - tp->link_config.phy_is_low_power = 0; - tp->link_config.orig_speed = SPEED_INVALID; - tp->link_config.orig_duplex = DUPLEX_INVALID; - tp->link_config.orig_autoneg = AUTONEG_INVALID; -} - -static void __devinit tg3_init_bufmgr_config(struct tg3 *tp) -{ - tp->bufmgr_config.mbuf_read_dma_low_water = - DEFAULT_MB_RDMA_LOW_WATER; - tp->bufmgr_config.mbuf_mac_rx_low_water = - DEFAULT_MB_MACRX_LOW_WATER; - tp->bufmgr_config.mbuf_high_water = - DEFAULT_MB_HIGH_WATER; - - tp->bufmgr_config.mbuf_read_dma_low_water_jumbo = - DEFAULT_MB_RDMA_LOW_WATER_JUMBO; - tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo = - DEFAULT_MB_MACRX_LOW_WATER_JUMBO; - tp->bufmgr_config.mbuf_high_water_jumbo = - DEFAULT_MB_HIGH_WATER_JUMBO; - - tp->bufmgr_config.dma_low_water = DEFAULT_DMA_LOW_WATER; - tp->bufmgr_config.dma_high_water = DEFAULT_DMA_HIGH_WATER; -} - -static char * __devinit tg3_phy_string(struct tg3 *tp) -{ - switch (tp->phy_id & PHY_ID_MASK) { - case PHY_ID_BCM5400: return "5400"; - case PHY_ID_BCM5401: return "5401"; - case PHY_ID_BCM5411: return "5411"; - case PHY_ID_BCM5701: return "5701"; - case PHY_ID_BCM5703: return "5703"; - case PHY_ID_BCM5704: return "5704"; - case PHY_ID_BCM5705: return "5705"; - case PHY_ID_BCM8002: return "8002"; - case PHY_ID_SERDES: return "serdes"; - default: return "unknown"; - }; -} - -static struct pci_dev * __devinit tg3_find_5704_peer(struct tg3 *tp) -{ - struct pci_dev *peer = NULL; - unsigned int func; - - for (func = 0; func < 7; func++) { - unsigned int devfn = tp->pdev->devfn; - - devfn &= ~7; - devfn |= func; - - if (devfn == tp->pdev->devfn) - continue; - peer = pci_find_slot(tp->pdev->bus->number, devfn); - if (peer) - break; - } - if (!peer || peer == tp->pdev) - BUG(); - return peer; -} - -static int __devinit tg3_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - static int tg3_version_printed = 0; - unsigned long tg3reg_base, tg3reg_len; - struct net_device *dev; - struct tg3 *tp; - int i, err, pci_using_dac, pm_cap; - - if (tg3_version_printed++ == 0) - printk(KERN_INFO "%s", version); - - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR PFX "Cannot enable PCI device, " - "aborting.\n"); - return err; - } - - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - printk(KERN_ERR PFX "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - err = pci_request_regions(pdev, DRV_MODULE_NAME); - if (err) { - printk(KERN_ERR PFX "Cannot obtain PCI resources, " - "aborting.\n"); - goto err_out_disable_pdev; - } - - pci_set_master(pdev); - - /* Find power-management capability. */ - pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pm_cap == 0) { - printk(KERN_ERR PFX "Cannot find PowerManagement capability, " - "aborting.\n"); - goto err_out_free_res; - } - - /* Configure DMA attributes. */ - if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) { - pci_using_dac = 1; - } else { - err = pci_set_dma_mask(pdev, 0xffffffffULL); - if (err) { - printk(KERN_ERR PFX "No usable DMA configuration, " - "aborting.\n"); - goto err_out_free_res; - } - pci_using_dac = 0; - } - - tg3reg_base = pci_resource_start(pdev, 0); - tg3reg_len = pci_resource_len(pdev, 0); - - dev = alloc_etherdev(sizeof(*tp)); - if (!dev) { - printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - SET_MODULE_OWNER(dev); - - if (pci_using_dac) - dev->features |= NETIF_F_HIGHDMA; -#if TG3_VLAN_TAG_USED - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->vlan_rx_register = tg3_vlan_rx_register; - dev->vlan_rx_kill_vid = tg3_vlan_rx_kill_vid; -#endif - - tp = dev->priv; - tp->pdev = pdev; - tp->dev = dev; - tp->pm_cap = pm_cap; - tp->mac_mode = TG3_DEF_MAC_MODE; - tp->rx_mode = TG3_DEF_RX_MODE; - tp->tx_mode = TG3_DEF_TX_MODE; - tp->mi_mode = MAC_MI_MODE_BASE; - if (tg3_debug > 0) - tp->msg_enable = tg3_debug; - else - tp->msg_enable = TG3_DEF_MSG_ENABLE; - - /* The word/byte swap controls here control register access byte - * swapping. DMA data byte swapping is controlled in the GRC_MODE - * setting below. - */ - tp->misc_host_ctrl = - MISC_HOST_CTRL_MASK_PCI_INT | - MISC_HOST_CTRL_WORD_SWAP | - MISC_HOST_CTRL_INDIR_ACCESS | - MISC_HOST_CTRL_PCISTATE_RW; - - /* The NONFRM (non-frame) byte/word swap controls take effect - * on descriptor entries, anything which isn't packet data. - * - * The StrongARM chips on the board (one for tx, one for rx) - * are running in big-endian mode. - */ - tp->grc_mode = (GRC_MODE_WSWAP_DATA | GRC_MODE_BSWAP_DATA | - GRC_MODE_WSWAP_NONFRM_DATA); -#ifdef __BIG_ENDIAN - tp->grc_mode |= GRC_MODE_BSWAP_NONFRM_DATA; -#endif - spin_lock_init(&tp->lock); - spin_lock_init(&tp->tx_lock); - spin_lock_init(&tp->indirect_lock); - INIT_TQUEUE(&tp->reset_task, tg3_reset_task, tp); - - tp->regs = (unsigned long) ioremap(tg3reg_base, tg3reg_len); - if (tp->regs == 0UL) { - printk(KERN_ERR PFX "Cannot map device registers, " - "aborting.\n"); - err = -ENOMEM; - goto err_out_free_dev; - } - - tg3_init_link_config(tp); - - tg3_init_bufmgr_config(tp); - - tp->rx_pending = TG3_DEF_RX_RING_PENDING; - tp->rx_jumbo_pending = TG3_DEF_RX_JUMBO_RING_PENDING; - tp->tx_pending = TG3_DEF_TX_RING_PENDING; - - dev->open = tg3_open; - dev->stop = tg3_close; - dev->get_stats = tg3_get_stats; - dev->set_multicast_list = tg3_set_rx_mode; - dev->set_mac_address = tg3_set_mac_addr; - dev->do_ioctl = tg3_ioctl; - dev->tx_timeout = tg3_tx_timeout; -#ifdef NAPI - dev->poll = tg3_poll; -#endif -#ifdef ETHTOOL - dev->ethtool_ops = &tg3_ethtool_ops; -#endif -#ifdef NAPI - dev->weight = 64; -#endif - dev->watchdog_timeo = TG3_TX_TIMEOUT; - dev->change_mtu = tg3_change_mtu; - dev->irq = pdev->irq; - - err = tg3_get_invariants(tp); - if (err) { - printk(KERN_ERR PFX "Problem fetching invariants of chip, " - "aborting.\n"); - goto err_out_iounmap; - } - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { - tp->bufmgr_config.mbuf_read_dma_low_water = - DEFAULT_MB_RDMA_LOW_WATER_5705; - tp->bufmgr_config.mbuf_mac_rx_low_water = - DEFAULT_MB_MACRX_LOW_WATER_5705; - tp->bufmgr_config.mbuf_high_water = - DEFAULT_MB_HIGH_WATER_5705; - } - -#if TG3_TSO_SUPPORT != 0 - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 || - tp->pci_chip_rev_id == CHIPREV_ID_5705_A0 || - (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0 || - (tp->tg3_flags2 & TG3_FLG2_IS_5788)) { - tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; - } else { - tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; - } - - /* TSO is off by default, user can enable using ethtool. */ -#if 0 - if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) - dev->features |= NETIF_F_TSO; -#endif - -#endif - - if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 && - !(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) && - !(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH)) { - tp->tg3_flags2 |= TG3_FLG2_MAX_RXPEND_64; - tp->rx_pending = 63; - } - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) - tp->pdev_peer = tg3_find_5704_peer(tp); - - err = tg3_get_device_address(tp); - if (err) { - printk(KERN_ERR PFX "Could not obtain valid ethernet address, " - "aborting.\n"); - goto err_out_iounmap; - } - - err = tg3_test_dma(tp); - if (err) { - printk(KERN_ERR PFX "DMA engine test failed, aborting.\n"); - goto err_out_iounmap; - } - - /* Tigon3 can do ipv4 only... and some chips have buggy - * checksumming. - */ - if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) { - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS; - } else - tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS; - - if (tp->tg3_flags2 & TG3_FLG2_IS_5788) - dev->features &= ~NETIF_F_HIGHDMA; - - err = register_netdev(dev); - if (err) { - printk(KERN_ERR PFX "Cannot register net device, " - "aborting.\n"); - goto err_out_iounmap; - } - - pci_set_drvdata(pdev, dev); - - /* Now that we have fully setup the chip, save away a snapshot - * of the PCI config space. We need to restore this after - * GRC_MISC_CFG core clock resets and some resume events. - */ - pci_save_state(tp->pdev, tp->pci_cfg_state); - - printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT Ethernet ", - dev->name, - tp->board_part_number, - tp->pci_chip_rev_id, - tg3_phy_string(tp), - ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "X" : ""), - ((tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED) ? - ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "133MHz" : "66MHz") : - ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "100MHz" : "33MHz")), - ((tp->tg3_flags & TG3_FLAG_PCI_32BIT) ? "32-bit" : "64-bit"), - (tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100" : "10/100/1000"); - - for (i = 0; i < 6; i++) - printk("%2.2x%c", dev->dev_addr[i], - i == 5 ? '\n' : ':'); - - return 0; - -err_out_iounmap: - iounmap((void *) tp->regs); - -err_out_free_dev: - kfree(dev); - -err_out_free_res: - pci_release_regions(pdev); - -err_out_disable_pdev: - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - return err; -} - -static void __devexit tg3_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - - if (dev) { - unregister_netdev(dev); - iounmap((void *) ((struct tg3 *)(dev->priv))->regs); - kfree(dev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -static int tg3_suspend(struct pci_dev *pdev, u32 state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct tg3 *tp = dev->priv; - int err; - - if (!netif_running(dev)) - return 0; - - tg3_netif_stop(tp); - - del_timer_sync(&tp->timer); - - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - tg3_disable_ints(tp); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - - netif_device_detach(dev); - - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - tg3_halt(tp); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - - err = tg3_set_power_state(tp, state); - if (err) { - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - - tg3_init_hw(tp); - - tp->timer.expires = jiffies + tp->timer_offset; - add_timer(&tp->timer); - - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - - netif_device_attach(dev); - tg3_netif_start(tp); - } - - return err; -} - -static int tg3_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct tg3 *tp = dev->priv; - int err; - - if (!netif_running(dev)) - return 0; - - err = tg3_set_power_state(tp, 0); - if (err) - return err; - - netif_device_attach(dev); - - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - - tg3_init_hw(tp); - - tp->timer.expires = jiffies + tp->timer_offset; - add_timer(&tp->timer); - - tg3_enable_ints(tp); - - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - - tg3_netif_start(tp); - - return 0; -} - -static struct pci_driver tg3_driver = { - .name = DRV_MODULE_NAME, - .id_table = tg3_pci_tbl, - .probe = tg3_init_one, - .remove = __devexit_p(tg3_remove_one), - .suspend = tg3_suspend, - .resume = tg3_resume -}; - -static int __init tg3_init(void) -{ - return pci_module_init(&tg3_driver); -} - -static void __exit tg3_cleanup(void) -{ - pci_unregister_driver(&tg3_driver); -} - -module_init(tg3_init); -module_exit(tg3_cleanup); diff --git a/xen/drivers/net/tg3.h b/xen/drivers/net/tg3.h deleted file mode 100644 index 438d064e9b..0000000000 --- a/xen/drivers/net/tg3.h +++ /dev/null @@ -1,1999 +0,0 @@ -/* $Id: tg3.h,v 1.37.2.32 2002/03/11 12:18:18 davem Exp $ - * tg3.h: Definitions for Broadcom Tigon3 ethernet driver. - * - * Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com) - * Copyright (C) 2001 Jeff Garzik (jgarzik@pobox.com) - */ - -#ifndef _T3_H -#define _T3_H - -#define TG3_64BIT_REG_HIGH 0x00UL -#define TG3_64BIT_REG_LOW 0x04UL - -/* Descriptor block info. */ -#define TG3_BDINFO_HOST_ADDR 0x0UL /* 64-bit */ -#define TG3_BDINFO_MAXLEN_FLAGS 0x8UL /* 32-bit */ -#define BDINFO_FLAGS_USE_EXT_RECV 0x00000001 /* ext rx_buffer_desc */ -#define BDINFO_FLAGS_DISABLED 0x00000002 -#define BDINFO_FLAGS_MAXLEN_MASK 0xffff0000 -#define BDINFO_FLAGS_MAXLEN_SHIFT 16 -#define TG3_BDINFO_NIC_ADDR 0xcUL /* 32-bit */ -#define TG3_BDINFO_SIZE 0x10UL - -#define RX_COPY_THRESHOLD 0 /* No CopyBreak for Xen */ - -#define RX_STD_MAX_SIZE 1536 -#define RX_STD_MAX_SIZE_5705 512 -#define RX_JUMBO_MAX_SIZE 0xdeadbeef /* XXX */ - -/* First 256 bytes are a mirror of PCI config space. */ -#define TG3PCI_VENDOR 0x00000000 -#define TG3PCI_VENDOR_BROADCOM 0x14e4 -#define TG3PCI_DEVICE 0x00000002 -#define TG3PCI_DEVICE_TIGON3_1 0x1644 /* BCM5700 */ -#define TG3PCI_DEVICE_TIGON3_2 0x1645 /* BCM5701 */ -#define TG3PCI_DEVICE_TIGON3_3 0x1646 /* BCM5702 */ -#define TG3PCI_DEVICE_TIGON3_4 0x1647 /* BCM5703 */ -#define TG3PCI_COMMAND 0x00000004 -#define TG3PCI_STATUS 0x00000006 -#define TG3PCI_CCREVID 0x00000008 -#define TG3PCI_CACHELINESZ 0x0000000c -#define TG3PCI_LATTIMER 0x0000000d -#define TG3PCI_HEADERTYPE 0x0000000e -#define TG3PCI_BIST 0x0000000f -#define TG3PCI_BASE0_LOW 0x00000010 -#define TG3PCI_BASE0_HIGH 0x00000014 -/* 0x18 --> 0x2c unused */ -#define TG3PCI_SUBSYSVENID 0x0000002c -#define TG3PCI_SUBSYSID 0x0000002e -#define TG3PCI_ROMADDR 0x00000030 -#define TG3PCI_CAPLIST 0x00000034 -/* 0x35 --> 0x3c unused */ -#define TG3PCI_IRQ_LINE 0x0000003c -#define TG3PCI_IRQ_PIN 0x0000003d -#define TG3PCI_MIN_GNT 0x0000003e -#define TG3PCI_MAX_LAT 0x0000003f -#define TG3PCI_X_CAPS 0x00000040 -#define PCIX_CAPS_RELAXED_ORDERING 0x00020000 -#define PCIX_CAPS_SPLIT_MASK 0x00700000 -#define PCIX_CAPS_SPLIT_SHIFT 20 -#define PCIX_CAPS_BURST_MASK 0x000c0000 -#define PCIX_CAPS_BURST_SHIFT 18 -#define PCIX_CAPS_MAX_BURST_CPIOB 2 -#define TG3PCI_PM_CAP_PTR 0x00000041 -#define TG3PCI_X_COMMAND 0x00000042 -#define TG3PCI_X_STATUS 0x00000044 -#define TG3PCI_PM_CAP_ID 0x00000048 -#define TG3PCI_VPD_CAP_PTR 0x00000049 -#define TG3PCI_PM_CAPS 0x0000004a -#define TG3PCI_PM_CTRL_STAT 0x0000004c -#define TG3PCI_BR_SUPP_EXT 0x0000004e -#define TG3PCI_PM_DATA 0x0000004f -#define TG3PCI_VPD_CAP_ID 0x00000050 -#define TG3PCI_MSI_CAP_PTR 0x00000051 -#define TG3PCI_VPD_ADDR_FLAG 0x00000052 -#define VPD_ADDR_FLAG_WRITE 0x00008000 -#define TG3PCI_VPD_DATA 0x00000054 -#define TG3PCI_MSI_CAP_ID 0x00000058 -#define TG3PCI_NXT_CAP_PTR 0x00000059 -#define TG3PCI_MSI_CTRL 0x0000005a -#define TG3PCI_MSI_ADDR_LOW 0x0000005c -#define TG3PCI_MSI_ADDR_HIGH 0x00000060 -#define TG3PCI_MSI_DATA 0x00000064 -/* 0x66 --> 0x68 unused */ -#define TG3PCI_MISC_HOST_CTRL 0x00000068 -#define MISC_HOST_CTRL_CLEAR_INT 0x00000001 -#define MISC_HOST_CTRL_MASK_PCI_INT 0x00000002 -#define MISC_HOST_CTRL_BYTE_SWAP 0x00000004 -#define MISC_HOST_CTRL_WORD_SWAP 0x00000008 -#define MISC_HOST_CTRL_PCISTATE_RW 0x00000010 -#define MISC_HOST_CTRL_CLKREG_RW 0x00000020 -#define MISC_HOST_CTRL_REGWORD_SWAP 0x00000040 -#define MISC_HOST_CTRL_INDIR_ACCESS 0x00000080 -#define MISC_HOST_CTRL_IRQ_MASK_MODE 0x00000100 -#define MISC_HOST_CTRL_TAGGED_STATUS 0x00000200 -#define MISC_HOST_CTRL_CHIPREV 0xffff0000 -#define MISC_HOST_CTRL_CHIPREV_SHIFT 16 -#define GET_CHIP_REV_ID(MISC_HOST_CTRL) \ - (((MISC_HOST_CTRL) & MISC_HOST_CTRL_CHIPREV) >> \ - MISC_HOST_CTRL_CHIPREV_SHIFT) -#define CHIPREV_ID_5700_A0 0x7000 -#define CHIPREV_ID_5700_A1 0x7001 -#define CHIPREV_ID_5700_B0 0x7100 -#define CHIPREV_ID_5700_B1 0x7101 -#define CHIPREV_ID_5700_B3 0x7102 -#define CHIPREV_ID_5700_ALTIMA 0x7104 -#define CHIPREV_ID_5700_C0 0x7200 -#define CHIPREV_ID_5701_A0 0x0000 -#define CHIPREV_ID_5701_B0 0x0100 -#define CHIPREV_ID_5701_B2 0x0102 -#define CHIPREV_ID_5701_B5 0x0105 -#define CHIPREV_ID_5703_A0 0x1000 -#define CHIPREV_ID_5703_A1 0x1001 -#define CHIPREV_ID_5703_A2 0x1002 -#define CHIPREV_ID_5703_A3 0x1003 -#define CHIPREV_ID_5704_A0 0x2000 -#define CHIPREV_ID_5704_A1 0x2001 -#define CHIPREV_ID_5704_A2 0x2002 -#define CHIPREV_ID_5705_A0 0x3000 -#define CHIPREV_ID_5705_A1 0x3001 -#define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12) -#define ASIC_REV_5700 0x07 -#define ASIC_REV_5701 0x00 -#define ASIC_REV_5703 0x01 -#define ASIC_REV_5704 0x02 -#define ASIC_REV_5705 0x03 -#define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) -#define CHIPREV_5700_AX 0x70 -#define CHIPREV_5700_BX 0x71 -#define CHIPREV_5700_CX 0x72 -#define CHIPREV_5701_AX 0x00 -#define GET_METAL_REV(CHIP_REV_ID) ((CHIP_REV_ID) & 0xff) -#define METAL_REV_A0 0x00 -#define METAL_REV_A1 0x01 -#define METAL_REV_B0 0x00 -#define METAL_REV_B1 0x01 -#define METAL_REV_B2 0x02 -#define TG3PCI_DMA_RW_CTRL 0x0000006c -#define DMA_RWCTRL_MIN_DMA 0x000000ff -#define DMA_RWCTRL_MIN_DMA_SHIFT 0 -#define DMA_RWCTRL_READ_BNDRY_MASK 0x00000700 -#define DMA_RWCTRL_READ_BNDRY_DISAB 0x00000000 -#define DMA_RWCTRL_READ_BNDRY_16 0x00000100 -#define DMA_RWCTRL_READ_BNDRY_32 0x00000200 -#define DMA_RWCTRL_READ_BNDRY_64 0x00000300 -#define DMA_RWCTRL_READ_BNDRY_128 0x00000400 -#define DMA_RWCTRL_READ_BNDRY_256 0x00000500 -#define DMA_RWCTRL_READ_BNDRY_512 0x00000600 -#define DMA_RWCTRL_READ_BNDRY_1024 0x00000700 -#define DMA_RWCTRL_WRITE_BNDRY_MASK 0x00003800 -#define DMA_RWCTRL_WRITE_BNDRY_DISAB 0x00000000 -#define DMA_RWCTRL_WRITE_BNDRY_16 0x00000800 -#define DMA_RWCTRL_WRITE_BNDRY_32 0x00001000 -#define DMA_RWCTRL_WRITE_BNDRY_64 0x00001800 -#define DMA_RWCTRL_WRITE_BNDRY_128 0x00002000 -#define DMA_RWCTRL_WRITE_BNDRY_256 0x00002800 -#define DMA_RWCTRL_WRITE_BNDRY_512 0x00003000 -#define DMA_RWCTRL_WRITE_BNDRY_1024 0x00003800 -#define DMA_RWCTRL_ONE_DMA 0x00004000 -#define DMA_RWCTRL_READ_WATER 0x00070000 -#define DMA_RWCTRL_READ_WATER_SHIFT 16 -#define DMA_RWCTRL_WRITE_WATER 0x00380000 -#define DMA_RWCTRL_WRITE_WATER_SHIFT 19 -#define DMA_RWCTRL_USE_MEM_READ_MULT 0x00400000 -#define DMA_RWCTRL_ASSERT_ALL_BE 0x00800000 -#define DMA_RWCTRL_PCI_READ_CMD 0x0f000000 -#define DMA_RWCTRL_PCI_READ_CMD_SHIFT 24 -#define DMA_RWCTRL_PCI_WRITE_CMD 0xf0000000 -#define DMA_RWCTRL_PCI_WRITE_CMD_SHIFT 28 -#define TG3PCI_PCISTATE 0x00000070 -#define PCISTATE_FORCE_RESET 0x00000001 -#define PCISTATE_INT_NOT_ACTIVE 0x00000002 -#define PCISTATE_CONV_PCI_MODE 0x00000004 -#define PCISTATE_BUS_SPEED_HIGH 0x00000008 -#define PCISTATE_BUS_32BIT 0x00000010 -#define PCISTATE_ROM_ENABLE 0x00000020 -#define PCISTATE_ROM_RETRY_ENABLE 0x00000040 -#define PCISTATE_FLAT_VIEW 0x00000100 -#define PCISTATE_RETRY_SAME_DMA 0x00002000 -#define TG3PCI_CLOCK_CTRL 0x00000074 -#define CLOCK_CTRL_CORECLK_DISABLE 0x00000200 -#define CLOCK_CTRL_RXCLK_DISABLE 0x00000400 -#define CLOCK_CTRL_TXCLK_DISABLE 0x00000800 -#define CLOCK_CTRL_ALTCLK 0x00001000 -#define CLOCK_CTRL_PWRDOWN_PLL133 0x00008000 -#define CLOCK_CTRL_44MHZ_CORE 0x00040000 -#define CLOCK_CTRL_625_CORE 0x00100000 -#define CLOCK_CTRL_FORCE_CLKRUN 0x00200000 -#define CLOCK_CTRL_CLKRUN_OENABLE 0x00400000 -#define CLOCK_CTRL_DELAY_PCI_GRANT 0x80000000 -#define TG3PCI_REG_BASE_ADDR 0x00000078 -#define TG3PCI_MEM_WIN_BASE_ADDR 0x0000007c -#define TG3PCI_REG_DATA 0x00000080 -#define TG3PCI_MEM_WIN_DATA 0x00000084 -#define TG3PCI_MODE_CTRL 0x00000088 -#define TG3PCI_MISC_CFG 0x0000008c -#define TG3PCI_MISC_LOCAL_CTRL 0x00000090 -/* 0x94 --> 0x98 unused */ -#define TG3PCI_STD_RING_PROD_IDX 0x00000098 /* 64-bit */ -#define TG3PCI_RCV_RET_RING_CON_IDX 0x000000a0 /* 64-bit */ -#define TG3PCI_SND_PROD_IDX 0x000000a8 /* 64-bit */ -/* 0xb0 --> 0x100 unused */ - -/* 0x100 --> 0x200 unused */ - -/* Mailbox registers */ -#define MAILBOX_INTERRUPT_0 0x00000200 /* 64-bit */ -#define MAILBOX_INTERRUPT_1 0x00000208 /* 64-bit */ -#define MAILBOX_INTERRUPT_2 0x00000210 /* 64-bit */ -#define MAILBOX_INTERRUPT_3 0x00000218 /* 64-bit */ -#define MAILBOX_GENERAL_0 0x00000220 /* 64-bit */ -#define MAILBOX_GENERAL_1 0x00000228 /* 64-bit */ -#define MAILBOX_GENERAL_2 0x00000230 /* 64-bit */ -#define MAILBOX_GENERAL_3 0x00000238 /* 64-bit */ -#define MAILBOX_GENERAL_4 0x00000240 /* 64-bit */ -#define MAILBOX_GENERAL_5 0x00000248 /* 64-bit */ -#define MAILBOX_GENERAL_6 0x00000250 /* 64-bit */ -#define MAILBOX_GENERAL_7 0x00000258 /* 64-bit */ -#define MAILBOX_RELOAD_STAT 0x00000260 /* 64-bit */ -#define MAILBOX_RCV_STD_PROD_IDX 0x00000268 /* 64-bit */ -#define MAILBOX_RCV_JUMBO_PROD_IDX 0x00000270 /* 64-bit */ -#define MAILBOX_RCV_MINI_PROD_IDX 0x00000278 /* 64-bit */ -#define MAILBOX_RCVRET_CON_IDX_0 0x00000280 /* 64-bit */ -#define MAILBOX_RCVRET_CON_IDX_1 0x00000288 /* 64-bit */ -#define MAILBOX_RCVRET_CON_IDX_2 0x00000290 /* 64-bit */ -#define MAILBOX_RCVRET_CON_IDX_3 0x00000298 /* 64-bit */ -#define MAILBOX_RCVRET_CON_IDX_4 0x000002a0 /* 64-bit */ -#define MAILBOX_RCVRET_CON_IDX_5 0x000002a8 /* 64-bit */ -#define MAILBOX_RCVRET_CON_IDX_6 0x000002b0 /* 64-bit */ -#define MAILBOX_RCVRET_CON_IDX_7 0x000002b8 /* 64-bit */ -#define MAILBOX_RCVRET_CON_IDX_8 0x000002c0 /* 64-bit */ -#define MAILBOX_RCVRET_CON_IDX_9 0x000002c8 /* 64-bit */ -#define MAILBOX_RCVRET_CON_IDX_10 0x000002d0 /* 64-bit */ -#define MAILBOX_RCVRET_CON_IDX_11 0x000002d8 /* 64-bit */ -#define MAILBOX_RCVRET_CON_IDX_12 0x000002e0 /* 64-bit */ -#define MAILBOX_RCVRET_CON_IDX_13 0x000002e8 /* 64-bit */ -#define MAILBOX_RCVRET_CON_IDX_14 0x000002f0 /* 64-bit */ -#define MAILBOX_RCVRET_CON_IDX_15 0x000002f8 /* 64-bit */ -#define MAILBOX_SNDHOST_PROD_IDX_0 0x00000300 /* 64-bit */ -#define MAILBOX_SNDHOST_PROD_IDX_1 0x00000308 /* 64-bit */ -#define MAILBOX_SNDHOST_PROD_IDX_2 0x00000310 /* 64-bit */ -#define MAILBOX_SNDHOST_PROD_IDX_3 0x00000318 /* 64-bit */ -#define MAILBOX_SNDHOST_PROD_IDX_4 0x00000320 /* 64-bit */ -#define MAILBOX_SNDHOST_PROD_IDX_5 0x00000328 /* 64-bit */ -#define MAILBOX_SNDHOST_PROD_IDX_6 0x00000330 /* 64-bit */ -#define MAILBOX_SNDHOST_PROD_IDX_7 0x00000338 /* 64-bit */ -#define MAILBOX_SNDHOST_PROD_IDX_8 0x00000340 /* 64-bit */ -#define MAILBOX_SNDHOST_PROD_IDX_9 0x00000348 /* 64-bit */ -#define MAILBOX_SNDHOST_PROD_IDX_10 0x00000350 /* 64-bit */ -#define MAILBOX_SNDHOST_PROD_IDX_11 0x00000358 /* 64-bit */ -#define MAILBOX_SNDHOST_PROD_IDX_12 0x00000360 /* 64-bit */ -#define MAILBOX_SNDHOST_PROD_IDX_13 0x00000368 /* 64-bit */ -#define MAILBOX_SNDHOST_PROD_IDX_14 0x00000370 /* 64-bit */ -#define MAILBOX_SNDHOST_PROD_IDX_15 0x00000378 /* 64-bit */ -#define MAILBOX_SNDNIC_PROD_IDX_0 0x00000380 /* 64-bit */ -#define MAILBOX_SNDNIC_PROD_IDX_1 0x00000388 /* 64-bit */ -#define MAILBOX_SNDNIC_PROD_IDX_2 0x00000390 /* 64-bit */ -#define MAILBOX_SNDNIC_PROD_IDX_3 0x00000398 /* 64-bit */ -#define MAILBOX_SNDNIC_PROD_IDX_4 0x000003a0 /* 64-bit */ -#define MAILBOX_SNDNIC_PROD_IDX_5 0x000003a8 /* 64-bit */ -#define MAILBOX_SNDNIC_PROD_IDX_6 0x000003b0 /* 64-bit */ -#define MAILBOX_SNDNIC_PROD_IDX_7 0x000003b8 /* 64-bit */ -#define MAILBOX_SNDNIC_PROD_IDX_8 0x000003c0 /* 64-bit */ -#define MAILBOX_SNDNIC_PROD_IDX_9 0x000003c8 /* 64-bit */ -#define MAILBOX_SNDNIC_PROD_IDX_10 0x000003d0 /* 64-bit */ -#define MAILBOX_SNDNIC_PROD_IDX_11 0x000003d8 /* 64-bit */ -#define MAILBOX_SNDNIC_PROD_IDX_12 0x000003e0 /* 64-bit */ -#define MAILBOX_SNDNIC_PROD_IDX_13 0x000003e8 /* 64-bit */ -#define MAILBOX_SNDNIC_PROD_IDX_14 0x000003f0 /* 64-bit */ -#define MAILBOX_SNDNIC_PROD_IDX_15 0x000003f8 /* 64-bit */ - -/* MAC control registers */ -#define MAC_MODE 0x00000400 -#define MAC_MODE_RESET 0x00000001 -#define MAC_MODE_HALF_DUPLEX 0x00000002 -#define MAC_MODE_PORT_MODE_MASK 0x0000000c -#define MAC_MODE_PORT_MODE_TBI 0x0000000c -#define MAC_MODE_PORT_MODE_GMII 0x00000008 -#define MAC_MODE_PORT_MODE_MII 0x00000004 -#define MAC_MODE_PORT_MODE_NONE 0x00000000 -#define MAC_MODE_PORT_INT_LPBACK 0x00000010 -#define MAC_MODE_TAGGED_MAC_CTRL 0x00000080 -#define MAC_MODE_TX_BURSTING 0x00000100 -#define MAC_MODE_MAX_DEFER 0x00000200 -#define MAC_MODE_LINK_POLARITY 0x00000400 -#define MAC_MODE_RXSTAT_ENABLE 0x00000800 -#define MAC_MODE_RXSTAT_CLEAR 0x00001000 -#define MAC_MODE_RXSTAT_FLUSH 0x00002000 -#define MAC_MODE_TXSTAT_ENABLE 0x00004000 -#define MAC_MODE_TXSTAT_CLEAR 0x00008000 -#define MAC_MODE_TXSTAT_FLUSH 0x00010000 -#define MAC_MODE_SEND_CONFIGS 0x00020000 -#define MAC_MODE_MAGIC_PKT_ENABLE 0x00040000 -#define MAC_MODE_ACPI_ENABLE 0x00080000 -#define MAC_MODE_MIP_ENABLE 0x00100000 -#define MAC_MODE_TDE_ENABLE 0x00200000 -#define MAC_MODE_RDE_ENABLE 0x00400000 -#define MAC_MODE_FHDE_ENABLE 0x00800000 -#define MAC_STATUS 0x00000404 -#define MAC_STATUS_PCS_SYNCED 0x00000001 -#define MAC_STATUS_SIGNAL_DET 0x00000002 -#define MAC_STATUS_RCVD_CFG 0x00000004 -#define MAC_STATUS_CFG_CHANGED 0x00000008 -#define MAC_STATUS_SYNC_CHANGED 0x00000010 -#define MAC_STATUS_PORT_DEC_ERR 0x00000400 -#define MAC_STATUS_LNKSTATE_CHANGED 0x00001000 -#define MAC_STATUS_MI_COMPLETION 0x00400000 -#define MAC_STATUS_MI_INTERRUPT 0x00800000 -#define MAC_STATUS_AP_ERROR 0x01000000 -#define MAC_STATUS_ODI_ERROR 0x02000000 -#define MAC_STATUS_RXSTAT_OVERRUN 0x04000000 -#define MAC_STATUS_TXSTAT_OVERRUN 0x08000000 -#define MAC_EVENT 0x00000408 -#define MAC_EVENT_PORT_DECODE_ERR 0x00000400 -#define MAC_EVENT_LNKSTATE_CHANGED 0x00001000 -#define MAC_EVENT_MI_COMPLETION 0x00400000 -#define MAC_EVENT_MI_INTERRUPT 0x00800000 -#define MAC_EVENT_AP_ERROR 0x01000000 -#define MAC_EVENT_ODI_ERROR 0x02000000 -#define MAC_EVENT_RXSTAT_OVERRUN 0x04000000 -#define MAC_EVENT_TXSTAT_OVERRUN 0x08000000 -#define MAC_LED_CTRL 0x0000040c -#define LED_CTRL_LNKLED_OVERRIDE 0x00000001 -#define LED_CTRL_1000MBPS_ON 0x00000002 -#define LED_CTRL_100MBPS_ON 0x00000004 -#define LED_CTRL_10MBPS_ON 0x00000008 -#define LED_CTRL_TRAFFIC_OVERRIDE 0x00000010 -#define LED_CTRL_TRAFFIC_BLINK 0x00000020 -#define LED_CTRL_TRAFFIC_LED 0x00000040 -#define LED_CTRL_1000MBPS_STATUS 0x00000080 -#define LED_CTRL_100MBPS_STATUS 0x00000100 -#define LED_CTRL_10MBPS_STATUS 0x00000200 -#define LED_CTRL_TRAFFIC_STATUS 0x00000400 -#define LED_CTRL_MAC_MODE 0x00000000 -#define LED_CTRL_PHY_MODE_1 0x00000800 -#define LED_CTRL_PHY_MODE_2 0x00001000 -#define LED_CTRL_BLINK_RATE_MASK 0x7ff80000 -#define LED_CTRL_BLINK_RATE_SHIFT 19 -#define LED_CTRL_BLINK_PER_OVERRIDE 0x00080000 -#define LED_CTRL_BLINK_RATE_OVERRIDE 0x80000000 -#define MAC_ADDR_0_HIGH 0x00000410 /* upper 2 bytes */ -#define MAC_ADDR_0_LOW 0x00000414 /* lower 4 bytes */ -#define MAC_ADDR_1_HIGH 0x00000418 /* upper 2 bytes */ -#define MAC_ADDR_1_LOW 0x0000041c /* lower 4 bytes */ -#define MAC_ADDR_2_HIGH 0x00000420 /* upper 2 bytes */ -#define MAC_ADDR_2_LOW 0x00000424 /* lower 4 bytes */ -#define MAC_ADDR_3_HIGH 0x00000428 /* upper 2 bytes */ -#define MAC_ADDR_3_LOW 0x0000042c /* lower 4 bytes */ -#define MAC_ACPI_MBUF_PTR 0x00000430 -#define MAC_ACPI_LEN_OFFSET 0x00000434 -#define ACPI_LENOFF_LEN_MASK 0x0000ffff -#define ACPI_LENOFF_LEN_SHIFT 0 -#define ACPI_LENOFF_OFF_MASK 0x0fff0000 -#define ACPI_LENOFF_OFF_SHIFT 16 -#define MAC_TX_BACKOFF_SEED 0x00000438 -#define TX_BACKOFF_SEED_MASK 0x000003ff -#define MAC_RX_MTU_SIZE 0x0000043c -#define RX_MTU_SIZE_MASK 0x0000ffff -#define MAC_PCS_TEST 0x00000440 -#define PCS_TEST_PATTERN_MASK 0x000fffff -#define PCS_TEST_PATTERN_SHIFT 0 -#define PCS_TEST_ENABLE 0x00100000 -#define MAC_TX_AUTO_NEG 0x00000444 -#define TX_AUTO_NEG_MASK 0x0000ffff -#define TX_AUTO_NEG_SHIFT 0 -#define MAC_RX_AUTO_NEG 0x00000448 -#define RX_AUTO_NEG_MASK 0x0000ffff -#define RX_AUTO_NEG_SHIFT 0 -#define MAC_MI_COM 0x0000044c -#define MI_COM_CMD_MASK 0x0c000000 -#define MI_COM_CMD_WRITE 0x04000000 -#define MI_COM_CMD_READ 0x08000000 -#define MI_COM_READ_FAILED 0x10000000 -#define MI_COM_START 0x20000000 -#define MI_COM_BUSY 0x20000000 -#define MI_COM_PHY_ADDR_MASK 0x03e00000 -#define MI_COM_PHY_ADDR_SHIFT 21 -#define MI_COM_REG_ADDR_MASK 0x001f0000 -#define MI_COM_REG_ADDR_SHIFT 16 -#define MI_COM_DATA_MASK 0x0000ffff -#define MAC_MI_STAT 0x00000450 -#define MAC_MI_STAT_LNKSTAT_ATTN_ENAB 0x00000001 -#define MAC_MI_MODE 0x00000454 -#define MAC_MI_MODE_CLK_10MHZ 0x00000001 -#define MAC_MI_MODE_SHORT_PREAMBLE 0x00000002 -#define MAC_MI_MODE_AUTO_POLL 0x00000010 -#define MAC_MI_MODE_CORE_CLK_62MHZ 0x00008000 -#define MAC_MI_MODE_BASE 0x000c0000 /* XXX magic values XXX */ -#define MAC_AUTO_POLL_STATUS 0x00000458 -#define MAC_AUTO_POLL_ERROR 0x00000001 -#define MAC_TX_MODE 0x0000045c -#define TX_MODE_RESET 0x00000001 -#define TX_MODE_ENABLE 0x00000002 -#define TX_MODE_FLOW_CTRL_ENABLE 0x00000010 -#define TX_MODE_BIG_BCKOFF_ENABLE 0x00000020 -#define TX_MODE_LONG_PAUSE_ENABLE 0x00000040 -#define MAC_TX_STATUS 0x00000460 -#define TX_STATUS_XOFFED 0x00000001 -#define TX_STATUS_SENT_XOFF 0x00000002 -#define TX_STATUS_SENT_XON 0x00000004 -#define TX_STATUS_LINK_UP 0x00000008 -#define TX_STATUS_ODI_UNDERRUN 0x00000010 -#define TX_STATUS_ODI_OVERRUN 0x00000020 -#define MAC_TX_LENGTHS 0x00000464 -#define TX_LENGTHS_SLOT_TIME_MASK 0x000000ff -#define TX_LENGTHS_SLOT_TIME_SHIFT 0 -#define TX_LENGTHS_IPG_MASK 0x00000f00 -#define TX_LENGTHS_IPG_SHIFT 8 -#define TX_LENGTHS_IPG_CRS_MASK 0x00003000 -#define TX_LENGTHS_IPG_CRS_SHIFT 12 -#define MAC_RX_MODE 0x00000468 -#define RX_MODE_RESET 0x00000001 -#define RX_MODE_ENABLE 0x00000002 -#define RX_MODE_FLOW_CTRL_ENABLE 0x00000004 -#define RX_MODE_KEEP_MAC_CTRL 0x00000008 -#define RX_MODE_KEEP_PAUSE 0x00000010 -#define RX_MODE_ACCEPT_OVERSIZED 0x00000020 -#define RX_MODE_ACCEPT_RUNTS 0x00000040 -#define RX_MODE_LEN_CHECK 0x00000080 -#define RX_MODE_PROMISC 0x00000100 -#define RX_MODE_NO_CRC_CHECK 0x00000200 -#define RX_MODE_KEEP_VLAN_TAG 0x00000400 -#define MAC_RX_STATUS 0x0000046c -#define RX_STATUS_REMOTE_TX_XOFFED 0x00000001 -#define RX_STATUS_XOFF_RCVD 0x00000002 -#define RX_STATUS_XON_RCVD 0x00000004 -#define MAC_HASH_REG_0 0x00000470 -#define MAC_HASH_REG_1 0x00000474 -#define MAC_HASH_REG_2 0x00000478 -#define MAC_HASH_REG_3 0x0000047c -#define MAC_RCV_RULE_0 0x00000480 -#define MAC_RCV_VALUE_0 0x00000484 -#define MAC_RCV_RULE_1 0x00000488 -#define MAC_RCV_VALUE_1 0x0000048c -#define MAC_RCV_RULE_2 0x00000490 -#define MAC_RCV_VALUE_2 0x00000494 -#define MAC_RCV_RULE_3 0x00000498 -#define MAC_RCV_VALUE_3 0x0000049c -#define MAC_RCV_RULE_4 0x000004a0 -#define MAC_RCV_VALUE_4 0x000004a4 -#define MAC_RCV_RULE_5 0x000004a8 -#define MAC_RCV_VALUE_5 0x000004ac -#define MAC_RCV_RULE_6 0x000004b0 -#define MAC_RCV_VALUE_6 0x000004b4 -#define MAC_RCV_RULE_7 0x000004b8 -#define MAC_RCV_VALUE_7 0x000004bc -#define MAC_RCV_RULE_8 0x000004c0 -#define MAC_RCV_VALUE_8 0x000004c4 -#define MAC_RCV_RULE_9 0x000004c8 -#define MAC_RCV_VALUE_9 0x000004cc -#define MAC_RCV_RULE_10 0x000004d0 -#define MAC_RCV_VALUE_10 0x000004d4 -#define MAC_RCV_RULE_11 0x000004d8 -#define MAC_RCV_VALUE_11 0x000004dc -#define MAC_RCV_RULE_12 0x000004e0 -#define MAC_RCV_VALUE_12 0x000004e4 -#define MAC_RCV_RULE_13 0x000004e8 -#define MAC_RCV_VALUE_13 0x000004ec -#define MAC_RCV_RULE_14 0x000004f0 -#define MAC_RCV_VALUE_14 0x000004f4 -#define MAC_RCV_RULE_15 0x000004f8 -#define MAC_RCV_VALUE_15 0x000004fc -#define RCV_RULE_DISABLE_MASK 0x7fffffff -#define MAC_RCV_RULE_CFG 0x00000500 -#define RCV_RULE_CFG_DEFAULT_CLASS 0x00000008 -#define MAC_LOW_WMARK_MAX_RX_FRAME 0x00000504 -/* 0x508 --> 0x520 unused */ -#define MAC_HASHREGU_0 0x00000520 -#define MAC_HASHREGU_1 0x00000524 -#define MAC_HASHREGU_2 0x00000528 -#define MAC_HASHREGU_3 0x0000052c -#define MAC_EXTADDR_0_HIGH 0x00000530 -#define MAC_EXTADDR_0_LOW 0x00000534 -#define MAC_EXTADDR_1_HIGH 0x00000538 -#define MAC_EXTADDR_1_LOW 0x0000053c -#define MAC_EXTADDR_2_HIGH 0x00000540 -#define MAC_EXTADDR_2_LOW 0x00000544 -#define MAC_EXTADDR_3_HIGH 0x00000548 -#define MAC_EXTADDR_3_LOW 0x0000054c -#define MAC_EXTADDR_4_HIGH 0x00000550 -#define MAC_EXTADDR_4_LOW 0x00000554 -#define MAC_EXTADDR_5_HIGH 0x00000558 -#define MAC_EXTADDR_5_LOW 0x0000055c -#define MAC_EXTADDR_6_HIGH 0x00000560 -#define MAC_EXTADDR_6_LOW 0x00000564 -#define MAC_EXTADDR_7_HIGH 0x00000568 -#define MAC_EXTADDR_7_LOW 0x0000056c -#define MAC_EXTADDR_8_HIGH 0x00000570 -#define MAC_EXTADDR_8_LOW 0x00000574 -#define MAC_EXTADDR_9_HIGH 0x00000578 -#define MAC_EXTADDR_9_LOW 0x0000057c -#define MAC_EXTADDR_10_HIGH 0x00000580 -#define MAC_EXTADDR_10_LOW 0x00000584 -#define MAC_EXTADDR_11_HIGH 0x00000588 -#define MAC_EXTADDR_11_LOW 0x0000058c -#define MAC_SERDES_CFG 0x00000590 -#define MAC_SERDES_STAT 0x00000594 -/* 0x598 --> 0x600 unused */ -#define MAC_TX_MAC_STATE_BASE 0x00000600 /* 16 bytes */ -#define MAC_RX_MAC_STATE_BASE 0x00000610 /* 20 bytes */ -/* 0x624 --> 0x800 unused */ -#define MAC_TX_STATS_OCTETS 0x00000800 -#define MAC_TX_STATS_RESV1 0x00000804 -#define MAC_TX_STATS_COLLISIONS 0x00000808 -#define MAC_TX_STATS_XON_SENT 0x0000080c -#define MAC_TX_STATS_XOFF_SENT 0x00000810 -#define MAC_TX_STATS_RESV2 0x00000814 -#define MAC_TX_STATS_MAC_ERRORS 0x00000818 -#define MAC_TX_STATS_SINGLE_COLLISIONS 0x0000081c -#define MAC_TX_STATS_MULT_COLLISIONS 0x00000820 -#define MAC_TX_STATS_DEFERRED 0x00000824 -#define MAC_TX_STATS_RESV3 0x00000828 -#define MAC_TX_STATS_EXCESSIVE_COL 0x0000082c -#define MAC_TX_STATS_LATE_COL 0x00000830 -#define MAC_TX_STATS_RESV4_1 0x00000834 -#define MAC_TX_STATS_RESV4_2 0x00000838 -#define MAC_TX_STATS_RESV4_3 0x0000083c -#define MAC_TX_STATS_RESV4_4 0x00000840 -#define MAC_TX_STATS_RESV4_5 0x00000844 -#define MAC_TX_STATS_RESV4_6 0x00000848 -#define MAC_TX_STATS_RESV4_7 0x0000084c -#define MAC_TX_STATS_RESV4_8 0x00000850 -#define MAC_TX_STATS_RESV4_9 0x00000854 -#define MAC_TX_STATS_RESV4_10 0x00000858 -#define MAC_TX_STATS_RESV4_11 0x0000085c -#define MAC_TX_STATS_RESV4_12 0x00000860 -#define MAC_TX_STATS_RESV4_13 0x00000864 -#define MAC_TX_STATS_RESV4_14 0x00000868 -#define MAC_TX_STATS_UCAST 0x0000086c -#define MAC_TX_STATS_MCAST 0x00000870 -#define MAC_TX_STATS_BCAST 0x00000874 -#define MAC_TX_STATS_RESV5_1 0x00000878 -#define MAC_TX_STATS_RESV5_2 0x0000087c -#define MAC_RX_STATS_OCTETS 0x00000880 -#define MAC_RX_STATS_RESV1 0x00000884 -#define MAC_RX_STATS_FRAGMENTS 0x00000888 -#define MAC_RX_STATS_UCAST 0x0000088c -#define MAC_RX_STATS_MCAST 0x00000890 -#define MAC_RX_STATS_BCAST 0x00000894 -#define MAC_RX_STATS_FCS_ERRORS 0x00000898 -#define MAC_RX_STATS_ALIGN_ERRORS 0x0000089c -#define MAC_RX_STATS_XON_PAUSE_RECVD 0x000008a0 -#define MAC_RX_STATS_XOFF_PAUSE_RECVD 0x000008a4 -#define MAC_RX_STATS_MAC_CTRL_RECVD 0x000008a8 -#define MAC_RX_STATS_XOFF_ENTERED 0x000008ac -#define MAC_RX_STATS_FRAME_TOO_LONG 0x000008b0 -#define MAC_RX_STATS_JABBERS 0x000008b4 -#define MAC_RX_STATS_UNDERSIZE 0x000008b8 -/* 0x8bc --> 0xc00 unused */ - -/* Send data initiator control registers */ -#define SNDDATAI_MODE 0x00000c00 -#define SNDDATAI_MODE_RESET 0x00000001 -#define SNDDATAI_MODE_ENABLE 0x00000002 -#define SNDDATAI_MODE_STAT_OFLOW_ENAB 0x00000004 -#define SNDDATAI_STATUS 0x00000c04 -#define SNDDATAI_STATUS_STAT_OFLOW 0x00000004 -#define SNDDATAI_STATSCTRL 0x00000c08 -#define SNDDATAI_SCTRL_ENABLE 0x00000001 -#define SNDDATAI_SCTRL_FASTUPD 0x00000002 -#define SNDDATAI_SCTRL_CLEAR 0x00000004 -#define SNDDATAI_SCTRL_FLUSH 0x00000008 -#define SNDDATAI_SCTRL_FORCE_ZERO 0x00000010 -#define SNDDATAI_STATSENAB 0x00000c0c -#define SNDDATAI_STATSINCMASK 0x00000c10 -/* 0xc14 --> 0xc80 unused */ -#define SNDDATAI_COS_CNT_0 0x00000c80 -#define SNDDATAI_COS_CNT_1 0x00000c84 -#define SNDDATAI_COS_CNT_2 0x00000c88 -#define SNDDATAI_COS_CNT_3 0x00000c8c -#define SNDDATAI_COS_CNT_4 0x00000c90 -#define SNDDATAI_COS_CNT_5 0x00000c94 -#define SNDDATAI_COS_CNT_6 0x00000c98 -#define SNDDATAI_COS_CNT_7 0x00000c9c -#define SNDDATAI_COS_CNT_8 0x00000ca0 -#define SNDDATAI_COS_CNT_9 0x00000ca4 -#define SNDDATAI_COS_CNT_10 0x00000ca8 -#define SNDDATAI_COS_CNT_11 0x00000cac -#define SNDDATAI_COS_CNT_12 0x00000cb0 -#define SNDDATAI_COS_CNT_13 0x00000cb4 -#define SNDDATAI_COS_CNT_14 0x00000cb8 -#define SNDDATAI_COS_CNT_15 0x00000cbc -#define SNDDATAI_DMA_RDQ_FULL_CNT 0x00000cc0 -#define SNDDATAI_DMA_PRIO_RDQ_FULL_CNT 0x00000cc4 -#define SNDDATAI_SDCQ_FULL_CNT 0x00000cc8 -#define SNDDATAI_NICRNG_SSND_PIDX_CNT 0x00000ccc -#define SNDDATAI_STATS_UPDATED_CNT 0x00000cd0 -#define SNDDATAI_INTERRUPTS_CNT 0x00000cd4 -#define SNDDATAI_AVOID_INTERRUPTS_CNT 0x00000cd8 -#define SNDDATAI_SND_THRESH_HIT_CNT 0x00000cdc -/* 0xce0 --> 0x1000 unused */ - -/* Send data completion control registers */ -#define SNDDATAC_MODE 0x00001000 -#define SNDDATAC_MODE_RESET 0x00000001 -#define SNDDATAC_MODE_ENABLE 0x00000002 -/* 0x1004 --> 0x1400 unused */ - -/* Send BD ring selector */ -#define SNDBDS_MODE 0x00001400 -#define SNDBDS_MODE_RESET 0x00000001 -#define SNDBDS_MODE_ENABLE 0x00000002 -#define SNDBDS_MODE_ATTN_ENABLE 0x00000004 -#define SNDBDS_STATUS 0x00001404 -#define SNDBDS_STATUS_ERROR_ATTN 0x00000004 -#define SNDBDS_HWDIAG 0x00001408 -/* 0x140c --> 0x1440 */ -#define SNDBDS_SEL_CON_IDX_0 0x00001440 -#define SNDBDS_SEL_CON_IDX_1 0x00001444 -#define SNDBDS_SEL_CON_IDX_2 0x00001448 -#define SNDBDS_SEL_CON_IDX_3 0x0000144c -#define SNDBDS_SEL_CON_IDX_4 0x00001450 -#define SNDBDS_SEL_CON_IDX_5 0x00001454 -#define SNDBDS_SEL_CON_IDX_6 0x00001458 -#define SNDBDS_SEL_CON_IDX_7 0x0000145c -#define SNDBDS_SEL_CON_IDX_8 0x00001460 -#define SNDBDS_SEL_CON_IDX_9 0x00001464 -#define SNDBDS_SEL_CON_IDX_10 0x00001468 -#define SNDBDS_SEL_CON_IDX_11 0x0000146c -#define SNDBDS_SEL_CON_IDX_12 0x00001470 -#define SNDBDS_SEL_CON_IDX_13 0x00001474 -#define SNDBDS_SEL_CON_IDX_14 0x00001478 -#define SNDBDS_SEL_CON_IDX_15 0x0000147c -/* 0x1480 --> 0x1800 unused */ - -/* Send BD initiator control registers */ -#define SNDBDI_MODE 0x00001800 -#define SNDBDI_MODE_RESET 0x00000001 -#define SNDBDI_MODE_ENABLE 0x00000002 -#define SNDBDI_MODE_ATTN_ENABLE 0x00000004 -#define SNDBDI_STATUS 0x00001804 -#define SNDBDI_STATUS_ERROR_ATTN 0x00000004 -#define SNDBDI_IN_PROD_IDX_0 0x00001808 -#define SNDBDI_IN_PROD_IDX_1 0x0000180c -#define SNDBDI_IN_PROD_IDX_2 0x00001810 -#define SNDBDI_IN_PROD_IDX_3 0x00001814 -#define SNDBDI_IN_PROD_IDX_4 0x00001818 -#define SNDBDI_IN_PROD_IDX_5 0x0000181c -#define SNDBDI_IN_PROD_IDX_6 0x00001820 -#define SNDBDI_IN_PROD_IDX_7 0x00001824 -#define SNDBDI_IN_PROD_IDX_8 0x00001828 -#define SNDBDI_IN_PROD_IDX_9 0x0000182c -#define SNDBDI_IN_PROD_IDX_10 0x00001830 -#define SNDBDI_IN_PROD_IDX_11 0x00001834 -#define SNDBDI_IN_PROD_IDX_12 0x00001838 -#define SNDBDI_IN_PROD_IDX_13 0x0000183c -#define SNDBDI_IN_PROD_IDX_14 0x00001840 -#define SNDBDI_IN_PROD_IDX_15 0x00001844 -/* 0x1848 --> 0x1c00 unused */ - -/* Send BD completion control registers */ -#define SNDBDC_MODE 0x00001c00 -#define SNDBDC_MODE_RESET 0x00000001 -#define SNDBDC_MODE_ENABLE 0x00000002 -#define SNDBDC_MODE_ATTN_ENABLE 0x00000004 -/* 0x1c04 --> 0x2000 unused */ - -/* Receive list placement control registers */ -#define RCVLPC_MODE 0x00002000 -#define RCVLPC_MODE_RESET 0x00000001 -#define RCVLPC_MODE_ENABLE 0x00000002 -#define RCVLPC_MODE_CLASS0_ATTN_ENAB 0x00000004 -#define RCVLPC_MODE_MAPOOR_AATTN_ENAB 0x00000008 -#define RCVLPC_MODE_STAT_OFLOW_ENAB 0x00000010 -#define RCVLPC_STATUS 0x00002004 -#define RCVLPC_STATUS_CLASS0 0x00000004 -#define RCVLPC_STATUS_MAPOOR 0x00000008 -#define RCVLPC_STATUS_STAT_OFLOW 0x00000010 -#define RCVLPC_LOCK 0x00002008 -#define RCVLPC_LOCK_REQ_MASK 0x0000ffff -#define RCVLPC_LOCK_REQ_SHIFT 0 -#define RCVLPC_LOCK_GRANT_MASK 0xffff0000 -#define RCVLPC_LOCK_GRANT_SHIFT 16 -#define RCVLPC_NON_EMPTY_BITS 0x0000200c -#define RCVLPC_NON_EMPTY_BITS_MASK 0x0000ffff -#define RCVLPC_CONFIG 0x00002010 -#define RCVLPC_STATSCTRL 0x00002014 -#define RCVLPC_STATSCTRL_ENABLE 0x00000001 -#define RCVLPC_STATSCTRL_FASTUPD 0x00000002 -#define RCVLPC_STATS_ENABLE 0x00002018 -#define RCVLPC_STATSENAB_LNGBRST_RFIX 0x00400000 -#define RCVLPC_STATS_INCMASK 0x0000201c -/* 0x2020 --> 0x2100 unused */ -#define RCVLPC_SELLST_BASE 0x00002100 /* 16 16-byte entries */ -#define SELLST_TAIL 0x00000004 -#define SELLST_CONT 0x00000008 -#define SELLST_UNUSED 0x0000000c -#define RCVLPC_COS_CNTL_BASE 0x00002200 /* 16 4-byte entries */ -#define RCVLPC_DROP_FILTER_CNT 0x00002240 -#define RCVLPC_DMA_WQ_FULL_CNT 0x00002244 -#define RCVLPC_DMA_HIPRIO_WQ_FULL_CNT 0x00002248 -#define RCVLPC_NO_RCV_BD_CNT 0x0000224c -#define RCVLPC_IN_DISCARDS_CNT 0x00002250 -#define RCVLPC_IN_ERRORS_CNT 0x00002254 -#define RCVLPC_RCV_THRESH_HIT_CNT 0x00002258 -/* 0x225c --> 0x2400 unused */ - -/* Receive Data and Receive BD Initiator Control */ -#define RCVDBDI_MODE 0x00002400 -#define RCVDBDI_MODE_RESET 0x00000001 -#define RCVDBDI_MODE_ENABLE 0x00000002 -#define RCVDBDI_MODE_JUMBOBD_NEEDED 0x00000004 -#define RCVDBDI_MODE_FRM_TOO_BIG 0x00000008 -#define RCVDBDI_MODE_INV_RING_SZ 0x00000010 -#define RCVDBDI_STATUS 0x00002404 -#define RCVDBDI_STATUS_JUMBOBD_NEEDED 0x00000004 -#define RCVDBDI_STATUS_FRM_TOO_BIG 0x00000008 -#define RCVDBDI_STATUS_INV_RING_SZ 0x00000010 -#define RCVDBDI_SPLIT_FRAME_MINSZ 0x00002408 -/* 0x240c --> 0x2440 unused */ -#define RCVDBDI_JUMBO_BD 0x00002440 /* TG3_BDINFO_... */ -#define RCVDBDI_STD_BD 0x00002450 /* TG3_BDINFO_... */ -#define RCVDBDI_MINI_BD 0x00002460 /* TG3_BDINFO_... */ -#define RCVDBDI_JUMBO_CON_IDX 0x00002470 -#define RCVDBDI_STD_CON_IDX 0x00002474 -#define RCVDBDI_MINI_CON_IDX 0x00002478 -/* 0x247c --> 0x2480 unused */ -#define RCVDBDI_BD_PROD_IDX_0 0x00002480 -#define RCVDBDI_BD_PROD_IDX_1 0x00002484 -#define RCVDBDI_BD_PROD_IDX_2 0x00002488 -#define RCVDBDI_BD_PROD_IDX_3 0x0000248c -#define RCVDBDI_BD_PROD_IDX_4 0x00002490 -#define RCVDBDI_BD_PROD_IDX_5 0x00002494 -#define RCVDBDI_BD_PROD_IDX_6 0x00002498 -#define RCVDBDI_BD_PROD_IDX_7 0x0000249c -#define RCVDBDI_BD_PROD_IDX_8 0x000024a0 -#define RCVDBDI_BD_PROD_IDX_9 0x000024a4 -#define RCVDBDI_BD_PROD_IDX_10 0x000024a8 -#define RCVDBDI_BD_PROD_IDX_11 0x000024ac -#define RCVDBDI_BD_PROD_IDX_12 0x000024b0 -#define RCVDBDI_BD_PROD_IDX_13 0x000024b4 -#define RCVDBDI_BD_PROD_IDX_14 0x000024b8 -#define RCVDBDI_BD_PROD_IDX_15 0x000024bc -#define RCVDBDI_HWDIAG 0x000024c0 -/* 0x24c4 --> 0x2800 unused */ - -/* Receive Data Completion Control */ -#define RCVDCC_MODE 0x00002800 -#define RCVDCC_MODE_RESET 0x00000001 -#define RCVDCC_MODE_ENABLE 0x00000002 -#define RCVDCC_MODE_ATTN_ENABLE 0x00000004 -/* 0x2804 --> 0x2c00 unused */ - -/* Receive BD Initiator Control Registers */ -#define RCVBDI_MODE 0x00002c00 -#define RCVBDI_MODE_RESET 0x00000001 -#define RCVBDI_MODE_ENABLE 0x00000002 -#define RCVBDI_MODE_RCB_ATTN_ENAB 0x00000004 -#define RCVBDI_STATUS 0x00002c04 -#define RCVBDI_STATUS_RCB_ATTN 0x00000004 -#define RCVBDI_JUMBO_PROD_IDX 0x00002c08 -#define RCVBDI_STD_PROD_IDX 0x00002c0c -#define RCVBDI_MINI_PROD_IDX 0x00002c10 -#define RCVBDI_MINI_THRESH 0x00002c14 -#define RCVBDI_STD_THRESH 0x00002c18 -#define RCVBDI_JUMBO_THRESH 0x00002c1c -/* 0x2c20 --> 0x3000 unused */ - -/* Receive BD Completion Control Registers */ -#define RCVCC_MODE 0x00003000 -#define RCVCC_MODE_RESET 0x00000001 -#define RCVCC_MODE_ENABLE 0x00000002 -#define RCVCC_MODE_ATTN_ENABLE 0x00000004 -#define RCVCC_STATUS 0x00003004 -#define RCVCC_STATUS_ERROR_ATTN 0x00000004 -#define RCVCC_JUMP_PROD_IDX 0x00003008 -#define RCVCC_STD_PROD_IDX 0x0000300c -#define RCVCC_MINI_PROD_IDX 0x00003010 -/* 0x3014 --> 0x3400 unused */ - -/* Receive list selector control registers */ -#define RCVLSC_MODE 0x00003400 -#define RCVLSC_MODE_RESET 0x00000001 -#define RCVLSC_MODE_ENABLE 0x00000002 -#define RCVLSC_MODE_ATTN_ENABLE 0x00000004 -#define RCVLSC_STATUS 0x00003404 -#define RCVLSC_STATUS_ERROR_ATTN 0x00000004 -/* 0x3408 --> 0x3800 unused */ - -/* Mbuf cluster free registers */ -#define MBFREE_MODE 0x00003800 -#define MBFREE_MODE_RESET 0x00000001 -#define MBFREE_MODE_ENABLE 0x00000002 -#define MBFREE_STATUS 0x00003804 -/* 0x3808 --> 0x3c00 unused */ - -/* Host coalescing control registers */ -#define HOSTCC_MODE 0x00003c00 -#define HOSTCC_MODE_RESET 0x00000001 -#define HOSTCC_MODE_ENABLE 0x00000002 -#define HOSTCC_MODE_ATTN 0x00000004 -#define HOSTCC_MODE_NOW 0x00000008 -#define HOSTCC_MODE_FULL_STATUS 0x00000000 -#define HOSTCC_MODE_64BYTE 0x00000080 -#define HOSTCC_MODE_32BYTE 0x00000100 -#define HOSTCC_MODE_CLRTICK_RXBD 0x00000200 -#define HOSTCC_MODE_CLRTICK_TXBD 0x00000400 -#define HOSTCC_MODE_NOINT_ON_NOW 0x00000800 -#define HOSTCC_MODE_NOINT_ON_FORCE 0x00001000 -#define HOSTCC_STATUS 0x00003c04 -#define HOSTCC_STATUS_ERROR_ATTN 0x00000004 -#define HOSTCC_RXCOL_TICKS 0x00003c08 -#define LOW_RXCOL_TICKS 0x00000032 -#define DEFAULT_RXCOL_TICKS 0x00000048 -#define HIGH_RXCOL_TICKS 0x00000096 -#define HOSTCC_TXCOL_TICKS 0x00003c0c -#define LOW_TXCOL_TICKS 0x00000096 -#define DEFAULT_TXCOL_TICKS 0x0000012c -#define HIGH_TXCOL_TICKS 0x00000145 -#define HOSTCC_RXMAX_FRAMES 0x00003c10 -#define LOW_RXMAX_FRAMES 0x00000005 -#define DEFAULT_RXMAX_FRAMES 0x00000008 -#define HIGH_RXMAX_FRAMES 0x00000012 -#define HOSTCC_TXMAX_FRAMES 0x00003c14 -#define LOW_TXMAX_FRAMES 0x00000035 -#define DEFAULT_TXMAX_FRAMES 0x0000004b -#define HIGH_TXMAX_FRAMES 0x00000052 -#define HOSTCC_RXCOAL_TICK_INT 0x00003c18 -#define DEFAULT_RXCOAL_TICK_INT 0x00000019 -#define HOSTCC_TXCOAL_TICK_INT 0x00003c1c -#define DEFAULT_TXCOAL_TICK_INT 0x00000019 -#define HOSTCC_RXCOAL_MAXF_INT 0x00003c20 -#define DEFAULT_RXCOAL_MAXF_INT 0x00000005 -#define HOSTCC_TXCOAL_MAXF_INT 0x00003c24 -#define DEFAULT_TXCOAL_MAXF_INT 0x00000005 -#define HOSTCC_STAT_COAL_TICKS 0x00003c28 -#define DEFAULT_STAT_COAL_TICKS 0x000f4240 -/* 0x3c2c --> 0x3c30 unused */ -#define HOSTCC_STATS_BLK_HOST_ADDR 0x00003c30 /* 64-bit */ -#define HOSTCC_STATUS_BLK_HOST_ADDR 0x00003c38 /* 64-bit */ -#define HOSTCC_STATS_BLK_NIC_ADDR 0x00003c40 -#define HOSTCC_STATUS_BLK_NIC_ADDR 0x00003c44 -#define HOSTCC_FLOW_ATTN 0x00003c48 -/* 0x3c4c --> 0x3c50 unused */ -#define HOSTCC_JUMBO_CON_IDX 0x00003c50 -#define HOSTCC_STD_CON_IDX 0x00003c54 -#define HOSTCC_MINI_CON_IDX 0x00003c58 -/* 0x3c5c --> 0x3c80 unused */ -#define HOSTCC_RET_PROD_IDX_0 0x00003c80 -#define HOSTCC_RET_PROD_IDX_1 0x00003c84 -#define HOSTCC_RET_PROD_IDX_2 0x00003c88 -#define HOSTCC_RET_PROD_IDX_3 0x00003c8c -#define HOSTCC_RET_PROD_IDX_4 0x00003c90 -#define HOSTCC_RET_PROD_IDX_5 0x00003c94 -#define HOSTCC_RET_PROD_IDX_6 0x00003c98 -#define HOSTCC_RET_PROD_IDX_7 0x00003c9c -#define HOSTCC_RET_PROD_IDX_8 0x00003ca0 -#define HOSTCC_RET_PROD_IDX_9 0x00003ca4 -#define HOSTCC_RET_PROD_IDX_10 0x00003ca8 -#define HOSTCC_RET_PROD_IDX_11 0x00003cac -#define HOSTCC_RET_PROD_IDX_12 0x00003cb0 -#define HOSTCC_RET_PROD_IDX_13 0x00003cb4 -#define HOSTCC_RET_PROD_IDX_14 0x00003cb8 -#define HOSTCC_RET_PROD_IDX_15 0x00003cbc -#define HOSTCC_SND_CON_IDX_0 0x00003cc0 -#define HOSTCC_SND_CON_IDX_1 0x00003cc4 -#define HOSTCC_SND_CON_IDX_2 0x00003cc8 -#define HOSTCC_SND_CON_IDX_3 0x00003ccc -#define HOSTCC_SND_CON_IDX_4 0x00003cd0 -#define HOSTCC_SND_CON_IDX_5 0x00003cd4 -#define HOSTCC_SND_CON_IDX_6 0x00003cd8 -#define HOSTCC_SND_CON_IDX_7 0x00003cdc -#define HOSTCC_SND_CON_IDX_8 0x00003ce0 -#define HOSTCC_SND_CON_IDX_9 0x00003ce4 -#define HOSTCC_SND_CON_IDX_10 0x00003ce8 -#define HOSTCC_SND_CON_IDX_11 0x00003cec -#define HOSTCC_SND_CON_IDX_12 0x00003cf0 -#define HOSTCC_SND_CON_IDX_13 0x00003cf4 -#define HOSTCC_SND_CON_IDX_14 0x00003cf8 -#define HOSTCC_SND_CON_IDX_15 0x00003cfc -/* 0x3d00 --> 0x4000 unused */ - -/* Memory arbiter control registers */ -#define MEMARB_MODE 0x00004000 -#define MEMARB_MODE_RESET 0x00000001 -#define MEMARB_MODE_ENABLE 0x00000002 -#define MEMARB_STATUS 0x00004004 -#define MEMARB_TRAP_ADDR_LOW 0x00004008 -#define MEMARB_TRAP_ADDR_HIGH 0x0000400c -/* 0x4010 --> 0x4400 unused */ - -/* Buffer manager control registers */ -#define BUFMGR_MODE 0x00004400 -#define BUFMGR_MODE_RESET 0x00000001 -#define BUFMGR_MODE_ENABLE 0x00000002 -#define BUFMGR_MODE_ATTN_ENABLE 0x00000004 -#define BUFMGR_MODE_BM_TEST 0x00000008 -#define BUFMGR_MODE_MBLOW_ATTN_ENAB 0x00000010 -#define BUFMGR_STATUS 0x00004404 -#define BUFMGR_STATUS_ERROR 0x00000004 -#define BUFMGR_STATUS_MBLOW 0x00000010 -#define BUFMGR_MB_POOL_ADDR 0x00004408 -#define BUFMGR_MB_POOL_SIZE 0x0000440c -#define BUFMGR_MB_RDMA_LOW_WATER 0x00004410 -#define DEFAULT_MB_RDMA_LOW_WATER 0x00000050 -#define DEFAULT_MB_RDMA_LOW_WATER_5705 0x00000000 -#define DEFAULT_MB_RDMA_LOW_WATER_JUMBO 0x00000130 -#define BUFMGR_MB_MACRX_LOW_WATER 0x00004414 -#define DEFAULT_MB_MACRX_LOW_WATER 0x00000020 -#define DEFAULT_MB_MACRX_LOW_WATER_5705 0x00000010 -#define DEFAULT_MB_MACRX_LOW_WATER_JUMBO 0x00000098 -#define BUFMGR_MB_HIGH_WATER 0x00004418 -#define DEFAULT_MB_HIGH_WATER 0x00000060 -#define DEFAULT_MB_HIGH_WATER_5705 0x00000060 -#define DEFAULT_MB_HIGH_WATER_JUMBO 0x0000017c -#define BUFMGR_RX_MB_ALLOC_REQ 0x0000441c -#define BUFMGR_MB_ALLOC_BIT 0x10000000 -#define BUFMGR_RX_MB_ALLOC_RESP 0x00004420 -#define BUFMGR_TX_MB_ALLOC_REQ 0x00004424 -#define BUFMGR_TX_MB_ALLOC_RESP 0x00004428 -#define BUFMGR_DMA_DESC_POOL_ADDR 0x0000442c -#define BUFMGR_DMA_DESC_POOL_SIZE 0x00004430 -#define BUFMGR_DMA_LOW_WATER 0x00004434 -#define DEFAULT_DMA_LOW_WATER 0x00000005 -#define BUFMGR_DMA_HIGH_WATER 0x00004438 -#define DEFAULT_DMA_HIGH_WATER 0x0000000a -#define BUFMGR_RX_DMA_ALLOC_REQ 0x0000443c -#define BUFMGR_RX_DMA_ALLOC_RESP 0x00004440 -#define BUFMGR_TX_DMA_ALLOC_REQ 0x00004444 -#define BUFMGR_TX_DMA_ALLOC_RESP 0x00004448 -#define BUFMGR_HWDIAG_0 0x0000444c -#define BUFMGR_HWDIAG_1 0x00004450 -#define BUFMGR_HWDIAG_2 0x00004454 -/* 0x4458 --> 0x4800 unused */ - -/* Read DMA control registers */ -#define RDMAC_MODE 0x00004800 -#define RDMAC_MODE_RESET 0x00000001 -#define RDMAC_MODE_ENABLE 0x00000002 -#define RDMAC_MODE_TGTABORT_ENAB 0x00000004 -#define RDMAC_MODE_MSTABORT_ENAB 0x00000008 -#define RDMAC_MODE_PARITYERR_ENAB 0x00000010 -#define RDMAC_MODE_ADDROFLOW_ENAB 0x00000020 -#define RDMAC_MODE_FIFOOFLOW_ENAB 0x00000040 -#define RDMAC_MODE_FIFOURUN_ENAB 0x00000080 -#define RDMAC_MODE_FIFOOREAD_ENAB 0x00000100 -#define RDMAC_MODE_LNGREAD_ENAB 0x00000200 -#define RDMAC_MODE_SPLIT_ENABLE 0x00000800 -#define RDMAC_MODE_SPLIT_RESET 0x00001000 -#define RDMAC_MODE_FIFO_SIZE_128 0x00020000 -#define RDMAC_MODE_FIFO_LONG_BURST 0x00030000 -#define RDMAC_STATUS 0x00004804 -#define RDMAC_STATUS_TGTABORT 0x00000004 -#define RDMAC_STATUS_MSTABORT 0x00000008 -#define RDMAC_STATUS_PARITYERR 0x00000010 -#define RDMAC_STATUS_ADDROFLOW 0x00000020 -#define RDMAC_STATUS_FIFOOFLOW 0x00000040 -#define RDMAC_STATUS_FIFOURUN 0x00000080 -#define RDMAC_STATUS_FIFOOREAD 0x00000100 -#define RDMAC_STATUS_LNGREAD 0x00000200 -/* 0x4808 --> 0x4c00 unused */ - -/* Write DMA control registers */ -#define WDMAC_MODE 0x00004c00 -#define WDMAC_MODE_RESET 0x00000001 -#define WDMAC_MODE_ENABLE 0x00000002 -#define WDMAC_MODE_TGTABORT_ENAB 0x00000004 -#define WDMAC_MODE_MSTABORT_ENAB 0x00000008 -#define WDMAC_MODE_PARITYERR_ENAB 0x00000010 -#define WDMAC_MODE_ADDROFLOW_ENAB 0x00000020 -#define WDMAC_MODE_FIFOOFLOW_ENAB 0x00000040 -#define WDMAC_MODE_FIFOURUN_ENAB 0x00000080 -#define WDMAC_MODE_FIFOOREAD_ENAB 0x00000100 -#define WDMAC_MODE_LNGREAD_ENAB 0x00000200 -#define WDMAC_MODE_RX_ACCEL 0x00000400 -#define WDMAC_STATUS 0x00004c04 -#define WDMAC_STATUS_TGTABORT 0x00000004 -#define WDMAC_STATUS_MSTABORT 0x00000008 -#define WDMAC_STATUS_PARITYERR 0x00000010 -#define WDMAC_STATUS_ADDROFLOW 0x00000020 -#define WDMAC_STATUS_FIFOOFLOW 0x00000040 -#define WDMAC_STATUS_FIFOURUN 0x00000080 -#define WDMAC_STATUS_FIFOOREAD 0x00000100 -#define WDMAC_STATUS_LNGREAD 0x00000200 -/* 0x4c08 --> 0x5000 unused */ - -/* Per-cpu register offsets (arm9) */ -#define CPU_MODE 0x00000000 -#define CPU_MODE_RESET 0x00000001 -#define CPU_MODE_HALT 0x00000400 -#define CPU_STATE 0x00000004 -#define CPU_EVTMASK 0x00000008 -/* 0xc --> 0x1c reserved */ -#define CPU_PC 0x0000001c -#define CPU_INSN 0x00000020 -#define CPU_SPAD_UFLOW 0x00000024 -#define CPU_WDOG_CLEAR 0x00000028 -#define CPU_WDOG_VECTOR 0x0000002c -#define CPU_WDOG_PC 0x00000030 -#define CPU_HW_BP 0x00000034 -/* 0x38 --> 0x44 unused */ -#define CPU_WDOG_SAVED_STATE 0x00000044 -#define CPU_LAST_BRANCH_ADDR 0x00000048 -#define CPU_SPAD_UFLOW_SET 0x0000004c -/* 0x50 --> 0x200 unused */ -#define CPU_R0 0x00000200 -#define CPU_R1 0x00000204 -#define CPU_R2 0x00000208 -#define CPU_R3 0x0000020c -#define CPU_R4 0x00000210 -#define CPU_R5 0x00000214 -#define CPU_R6 0x00000218 -#define CPU_R7 0x0000021c -#define CPU_R8 0x00000220 -#define CPU_R9 0x00000224 -#define CPU_R10 0x00000228 -#define CPU_R11 0x0000022c -#define CPU_R12 0x00000230 -#define CPU_R13 0x00000234 -#define CPU_R14 0x00000238 -#define CPU_R15 0x0000023c -#define CPU_R16 0x00000240 -#define CPU_R17 0x00000244 -#define CPU_R18 0x00000248 -#define CPU_R19 0x0000024c -#define CPU_R20 0x00000250 -#define CPU_R21 0x00000254 -#define CPU_R22 0x00000258 -#define CPU_R23 0x0000025c -#define CPU_R24 0x00000260 -#define CPU_R25 0x00000264 -#define CPU_R26 0x00000268 -#define CPU_R27 0x0000026c -#define CPU_R28 0x00000270 -#define CPU_R29 0x00000274 -#define CPU_R30 0x00000278 -#define CPU_R31 0x0000027c -/* 0x280 --> 0x400 unused */ - -#define RX_CPU_BASE 0x00005000 -#define TX_CPU_BASE 0x00005400 - -/* Mailboxes */ -#define GRCMBOX_INTERRUPT_0 0x00005800 /* 64-bit */ -#define GRCMBOX_INTERRUPT_1 0x00005808 /* 64-bit */ -#define GRCMBOX_INTERRUPT_2 0x00005810 /* 64-bit */ -#define GRCMBOX_INTERRUPT_3 0x00005818 /* 64-bit */ -#define GRCMBOX_GENERAL_0 0x00005820 /* 64-bit */ -#define GRCMBOX_GENERAL_1 0x00005828 /* 64-bit */ -#define GRCMBOX_GENERAL_2 0x00005830 /* 64-bit */ -#define GRCMBOX_GENERAL_3 0x00005838 /* 64-bit */ -#define GRCMBOX_GENERAL_4 0x00005840 /* 64-bit */ -#define GRCMBOX_GENERAL_5 0x00005848 /* 64-bit */ -#define GRCMBOX_GENERAL_6 0x00005850 /* 64-bit */ -#define GRCMBOX_GENERAL_7 0x00005858 /* 64-bit */ -#define GRCMBOX_RELOAD_STAT 0x00005860 /* 64-bit */ -#define GRCMBOX_RCVSTD_PROD_IDX 0x00005868 /* 64-bit */ -#define GRCMBOX_RCVJUMBO_PROD_IDX 0x00005870 /* 64-bit */ -#define GRCMBOX_RCVMINI_PROD_IDX 0x00005878 /* 64-bit */ -#define GRCMBOX_RCVRET_CON_IDX_0 0x00005880 /* 64-bit */ -#define GRCMBOX_RCVRET_CON_IDX_1 0x00005888 /* 64-bit */ -#define GRCMBOX_RCVRET_CON_IDX_2 0x00005890 /* 64-bit */ -#define GRCMBOX_RCVRET_CON_IDX_3 0x00005898 /* 64-bit */ -#define GRCMBOX_RCVRET_CON_IDX_4 0x000058a0 /* 64-bit */ -#define GRCMBOX_RCVRET_CON_IDX_5 0x000058a8 /* 64-bit */ -#define GRCMBOX_RCVRET_CON_IDX_6 0x000058b0 /* 64-bit */ -#define GRCMBOX_RCVRET_CON_IDX_7 0x000058b8 /* 64-bit */ -#define GRCMBOX_RCVRET_CON_IDX_8 0x000058c0 /* 64-bit */ -#define GRCMBOX_RCVRET_CON_IDX_9 0x000058c8 /* 64-bit */ -#define GRCMBOX_RCVRET_CON_IDX_10 0x000058d0 /* 64-bit */ -#define GRCMBOX_RCVRET_CON_IDX_11 0x000058d8 /* 64-bit */ -#define GRCMBOX_RCVRET_CON_IDX_12 0x000058e0 /* 64-bit */ -#define GRCMBOX_RCVRET_CON_IDX_13 0x000058e8 /* 64-bit */ -#define GRCMBOX_RCVRET_CON_IDX_14 0x000058f0 /* 64-bit */ -#define GRCMBOX_RCVRET_CON_IDX_15 0x000058f8 /* 64-bit */ -#define GRCMBOX_SNDHOST_PROD_IDX_0 0x00005900 /* 64-bit */ -#define GRCMBOX_SNDHOST_PROD_IDX_1 0x00005908 /* 64-bit */ -#define GRCMBOX_SNDHOST_PROD_IDX_2 0x00005910 /* 64-bit */ -#define GRCMBOX_SNDHOST_PROD_IDX_3 0x00005918 /* 64-bit */ -#define GRCMBOX_SNDHOST_PROD_IDX_4 0x00005920 /* 64-bit */ -#define GRCMBOX_SNDHOST_PROD_IDX_5 0x00005928 /* 64-bit */ -#define GRCMBOX_SNDHOST_PROD_IDX_6 0x00005930 /* 64-bit */ -#define GRCMBOX_SNDHOST_PROD_IDX_7 0x00005938 /* 64-bit */ -#define GRCMBOX_SNDHOST_PROD_IDX_8 0x00005940 /* 64-bit */ -#define GRCMBOX_SNDHOST_PROD_IDX_9 0x00005948 /* 64-bit */ -#define GRCMBOX_SNDHOST_PROD_IDX_10 0x00005950 /* 64-bit */ -#define GRCMBOX_SNDHOST_PROD_IDX_11 0x00005958 /* 64-bit */ -#define GRCMBOX_SNDHOST_PROD_IDX_12 0x00005960 /* 64-bit */ -#define GRCMBOX_SNDHOST_PROD_IDX_13 0x00005968 /* 64-bit */ -#define GRCMBOX_SNDHOST_PROD_IDX_14 0x00005970 /* 64-bit */ -#define GRCMBOX_SNDHOST_PROD_IDX_15 0x00005978 /* 64-bit */ -#define GRCMBOX_SNDNIC_PROD_IDX_0 0x00005980 /* 64-bit */ -#define GRCMBOX_SNDNIC_PROD_IDX_1 0x00005988 /* 64-bit */ -#define GRCMBOX_SNDNIC_PROD_IDX_2 0x00005990 /* 64-bit */ -#define GRCMBOX_SNDNIC_PROD_IDX_3 0x00005998 /* 64-bit */ -#define GRCMBOX_SNDNIC_PROD_IDX_4 0x000059a0 /* 64-bit */ -#define GRCMBOX_SNDNIC_PROD_IDX_5 0x000059a8 /* 64-bit */ -#define GRCMBOX_SNDNIC_PROD_IDX_6 0x000059b0 /* 64-bit */ -#define GRCMBOX_SNDNIC_PROD_IDX_7 0x000059b8 /* 64-bit */ -#define GRCMBOX_SNDNIC_PROD_IDX_8 0x000059c0 /* 64-bit */ -#define GRCMBOX_SNDNIC_PROD_IDX_9 0x000059c8 /* 64-bit */ -#define GRCMBOX_SNDNIC_PROD_IDX_10 0x000059d0 /* 64-bit */ -#define GRCMBOX_SNDNIC_PROD_IDX_11 0x000059d8 /* 64-bit */ -#define GRCMBOX_SNDNIC_PROD_IDX_12 0x000059e0 /* 64-bit */ -#define GRCMBOX_SNDNIC_PROD_IDX_13 0x000059e8 /* 64-bit */ -#define GRCMBOX_SNDNIC_PROD_IDX_14 0x000059f0 /* 64-bit */ -#define GRCMBOX_SNDNIC_PROD_IDX_15 0x000059f8 /* 64-bit */ -#define GRCMBOX_HIGH_PRIO_EV_VECTOR 0x00005a00 -#define GRCMBOX_HIGH_PRIO_EV_MASK 0x00005a04 -#define GRCMBOX_LOW_PRIO_EV_VEC 0x00005a08 -#define GRCMBOX_LOW_PRIO_EV_MASK 0x00005a0c -/* 0x5a10 --> 0x5c00 */ - -/* Flow Through queues */ -#define FTQ_RESET 0x00005c00 -/* 0x5c04 --> 0x5c10 unused */ -#define FTQ_DMA_NORM_READ_CTL 0x00005c10 -#define FTQ_DMA_NORM_READ_FULL_CNT 0x00005c14 -#define FTQ_DMA_NORM_READ_FIFO_ENQDEQ 0x00005c18 -#define FTQ_DMA_NORM_READ_WRITE_PEEK 0x00005c1c -#define FTQ_DMA_HIGH_READ_CTL 0x00005c20 -#define FTQ_DMA_HIGH_READ_FULL_CNT 0x00005c24 -#define FTQ_DMA_HIGH_READ_FIFO_ENQDEQ 0x00005c28 -#define FTQ_DMA_HIGH_READ_WRITE_PEEK 0x00005c2c -#define FTQ_DMA_COMP_DISC_CTL 0x00005c30 -#define FTQ_DMA_COMP_DISC_FULL_CNT 0x00005c34 -#define FTQ_DMA_COMP_DISC_FIFO_ENQDEQ 0x00005c38 -#define FTQ_DMA_COMP_DISC_WRITE_PEEK 0x00005c3c -#define FTQ_SEND_BD_COMP_CTL 0x00005c40 -#define FTQ_SEND_BD_COMP_FULL_CNT 0x00005c44 -#define FTQ_SEND_BD_COMP_FIFO_ENQDEQ 0x00005c48 -#define FTQ_SEND_BD_COMP_WRITE_PEEK 0x00005c4c -#define FTQ_SEND_DATA_INIT_CTL 0x00005c50 -#define FTQ_SEND_DATA_INIT_FULL_CNT 0x00005c54 -#define FTQ_SEND_DATA_INIT_FIFO_ENQDEQ 0x00005c58 -#define FTQ_SEND_DATA_INIT_WRITE_PEEK 0x00005c5c -#define FTQ_DMA_NORM_WRITE_CTL 0x00005c60 -#define FTQ_DMA_NORM_WRITE_FULL_CNT 0x00005c64 -#define FTQ_DMA_NORM_WRITE_FIFO_ENQDEQ 0x00005c68 -#define FTQ_DMA_NORM_WRITE_WRITE_PEEK 0x00005c6c -#define FTQ_DMA_HIGH_WRITE_CTL 0x00005c70 -#define FTQ_DMA_HIGH_WRITE_FULL_CNT 0x00005c74 -#define FTQ_DMA_HIGH_WRITE_FIFO_ENQDEQ 0x00005c78 -#define FTQ_DMA_HIGH_WRITE_WRITE_PEEK 0x00005c7c -#define FTQ_SWTYPE1_CTL 0x00005c80 -#define FTQ_SWTYPE1_FULL_CNT 0x00005c84 -#define FTQ_SWTYPE1_FIFO_ENQDEQ 0x00005c88 -#define FTQ_SWTYPE1_WRITE_PEEK 0x00005c8c -#define FTQ_SEND_DATA_COMP_CTL 0x00005c90 -#define FTQ_SEND_DATA_COMP_FULL_CNT 0x00005c94 -#define FTQ_SEND_DATA_COMP_FIFO_ENQDEQ 0x00005c98 -#define FTQ_SEND_DATA_COMP_WRITE_PEEK 0x00005c9c -#define FTQ_HOST_COAL_CTL 0x00005ca0 -#define FTQ_HOST_COAL_FULL_CNT 0x00005ca4 -#define FTQ_HOST_COAL_FIFO_ENQDEQ 0x00005ca8 -#define FTQ_HOST_COAL_WRITE_PEEK 0x00005cac -#define FTQ_MAC_TX_CTL 0x00005cb0 -#define FTQ_MAC_TX_FULL_CNT 0x00005cb4 -#define FTQ_MAC_TX_FIFO_ENQDEQ 0x00005cb8 -#define FTQ_MAC_TX_WRITE_PEEK 0x00005cbc -#define FTQ_MB_FREE_CTL 0x00005cc0 -#define FTQ_MB_FREE_FULL_CNT 0x00005cc4 -#define FTQ_MB_FREE_FIFO_ENQDEQ 0x00005cc8 -#define FTQ_MB_FREE_WRITE_PEEK 0x00005ccc -#define FTQ_RCVBD_COMP_CTL 0x00005cd0 -#define FTQ_RCVBD_COMP_FULL_CNT 0x00005cd4 -#define FTQ_RCVBD_COMP_FIFO_ENQDEQ 0x00005cd8 -#define FTQ_RCVBD_COMP_WRITE_PEEK 0x00005cdc -#define FTQ_RCVLST_PLMT_CTL 0x00005ce0 -#define FTQ_RCVLST_PLMT_FULL_CNT 0x00005ce4 -#define FTQ_RCVLST_PLMT_FIFO_ENQDEQ 0x00005ce8 -#define FTQ_RCVLST_PLMT_WRITE_PEEK 0x00005cec -#define FTQ_RCVDATA_INI_CTL 0x00005cf0 -#define FTQ_RCVDATA_INI_FULL_CNT 0x00005cf4 -#define FTQ_RCVDATA_INI_FIFO_ENQDEQ 0x00005cf8 -#define FTQ_RCVDATA_INI_WRITE_PEEK 0x00005cfc -#define FTQ_RCVDATA_COMP_CTL 0x00005d00 -#define FTQ_RCVDATA_COMP_FULL_CNT 0x00005d04 -#define FTQ_RCVDATA_COMP_FIFO_ENQDEQ 0x00005d08 -#define FTQ_RCVDATA_COMP_WRITE_PEEK 0x00005d0c -#define FTQ_SWTYPE2_CTL 0x00005d10 -#define FTQ_SWTYPE2_FULL_CNT 0x00005d14 -#define FTQ_SWTYPE2_FIFO_ENQDEQ 0x00005d18 -#define FTQ_SWTYPE2_WRITE_PEEK 0x00005d1c -/* 0x5d20 --> 0x6000 unused */ - -/* Message signaled interrupt registers */ -#define MSGINT_MODE 0x00006000 -#define MSGINT_MODE_RESET 0x00000001 -#define MSGINT_MODE_ENABLE 0x00000002 -#define MSGINT_STATUS 0x00006004 -#define MSGINT_FIFO 0x00006008 -/* 0x600c --> 0x6400 unused */ - -/* DMA completion registers */ -#define DMAC_MODE 0x00006400 -#define DMAC_MODE_RESET 0x00000001 -#define DMAC_MODE_ENABLE 0x00000002 -/* 0x6404 --> 0x6800 unused */ - -/* GRC registers */ -#define GRC_MODE 0x00006800 -#define GRC_MODE_UPD_ON_COAL 0x00000001 -#define GRC_MODE_BSWAP_NONFRM_DATA 0x00000002 -#define GRC_MODE_WSWAP_NONFRM_DATA 0x00000004 -#define GRC_MODE_BSWAP_DATA 0x00000010 -#define GRC_MODE_WSWAP_DATA 0x00000020 -#define GRC_MODE_SPLITHDR 0x00000100 -#define GRC_MODE_NOFRM_CRACKING 0x00000200 -#define GRC_MODE_INCL_CRC 0x00000400 -#define GRC_MODE_ALLOW_BAD_FRMS 0x00000800 -#define GRC_MODE_NOIRQ_ON_SENDS 0x00002000 -#define GRC_MODE_NOIRQ_ON_RCV 0x00004000 -#define GRC_MODE_FORCE_PCI32BIT 0x00008000 -#define GRC_MODE_HOST_STACKUP 0x00010000 -#define GRC_MODE_HOST_SENDBDS 0x00020000 -#define GRC_MODE_NO_TX_PHDR_CSUM 0x00100000 -#define GRC_MODE_NO_RX_PHDR_CSUM 0x00800000 -#define GRC_MODE_IRQ_ON_TX_CPU_ATTN 0x01000000 -#define GRC_MODE_IRQ_ON_RX_CPU_ATTN 0x02000000 -#define GRC_MODE_IRQ_ON_MAC_ATTN 0x04000000 -#define GRC_MODE_IRQ_ON_DMA_ATTN 0x08000000 -#define GRC_MODE_IRQ_ON_FLOW_ATTN 0x10000000 -#define GRC_MODE_4X_NIC_SEND_RINGS 0x20000000 -#define GRC_MODE_MCAST_FRM_ENABLE 0x40000000 -#define GRC_MISC_CFG 0x00006804 -#define GRC_MISC_CFG_CORECLK_RESET 0x00000001 -#define GRC_MISC_CFG_PRESCALAR_MASK 0x000000fe -#define GRC_MISC_CFG_PRESCALAR_SHIFT 1 -#define GRC_MISC_CFG_BOARD_ID_MASK 0x0001e000 -#define GRC_MISC_CFG_BOARD_ID_5700 0x0001e000 -#define GRC_MISC_CFG_BOARD_ID_5701 0x00000000 -#define GRC_MISC_CFG_BOARD_ID_5702FE 0x00004000 -#define GRC_MISC_CFG_BOARD_ID_5703 0x00000000 -#define GRC_MISC_CFG_BOARD_ID_5703S 0x00002000 -#define GRC_MISC_CFG_BOARD_ID_5704 0x00000000 -#define GRC_MISC_CFG_BOARD_ID_5704CIOBE 0x00004000 -#define GRC_MISC_CFG_BOARD_ID_5704_A2 0x00008000 -#define GRC_MISC_CFG_BOARD_ID_5788 0x00010000 -#define GRC_MISC_CFG_BOARD_ID_5788M 0x00018000 -#define GRC_MISC_CFG_BOARD_ID_AC91002A1 0x00018000 -#define GRC_MISC_CFG_KEEP_GPHY_POWER 0x04000000 -#define GRC_LOCAL_CTRL 0x00006808 -#define GRC_LCLCTRL_INT_ACTIVE 0x00000001 -#define GRC_LCLCTRL_CLEARINT 0x00000002 -#define GRC_LCLCTRL_SETINT 0x00000004 -#define GRC_LCLCTRL_INT_ON_ATTN 0x00000008 -#define GRC_LCLCTRL_GPIO_INPUT0 0x00000100 -#define GRC_LCLCTRL_GPIO_INPUT1 0x00000200 -#define GRC_LCLCTRL_GPIO_INPUT2 0x00000400 -#define GRC_LCLCTRL_GPIO_OE0 0x00000800 -#define GRC_LCLCTRL_GPIO_OE1 0x00001000 -#define GRC_LCLCTRL_GPIO_OE2 0x00002000 -#define GRC_LCLCTRL_GPIO_OUTPUT0 0x00004000 -#define GRC_LCLCTRL_GPIO_OUTPUT1 0x00008000 -#define GRC_LCLCTRL_GPIO_OUTPUT2 0x00010000 -#define GRC_LCLCTRL_EXTMEM_ENABLE 0x00020000 -#define GRC_LCLCTRL_MEMSZ_MASK 0x001c0000 -#define GRC_LCLCTRL_MEMSZ_256K 0x00000000 -#define GRC_LCLCTRL_MEMSZ_512K 0x00040000 -#define GRC_LCLCTRL_MEMSZ_1M 0x00080000 -#define GRC_LCLCTRL_MEMSZ_2M 0x000c0000 -#define GRC_LCLCTRL_MEMSZ_4M 0x00100000 -#define GRC_LCLCTRL_MEMSZ_8M 0x00140000 -#define GRC_LCLCTRL_MEMSZ_16M 0x00180000 -#define GRC_LCLCTRL_BANK_SELECT 0x00200000 -#define GRC_LCLCTRL_SSRAM_TYPE 0x00400000 -#define GRC_LCLCTRL_AUTO_SEEPROM 0x01000000 -#define GRC_TIMER 0x0000680c -#define GRC_RX_CPU_EVENT 0x00006810 -#define GRC_RX_TIMER_REF 0x00006814 -#define GRC_RX_CPU_SEM 0x00006818 -#define GRC_REMOTE_RX_CPU_ATTN 0x0000681c -#define GRC_TX_CPU_EVENT 0x00006820 -#define GRC_TX_TIMER_REF 0x00006824 -#define GRC_TX_CPU_SEM 0x00006828 -#define GRC_REMOTE_TX_CPU_ATTN 0x0000682c -#define GRC_MEM_POWER_UP 0x00006830 /* 64-bit */ -#define GRC_EEPROM_ADDR 0x00006838 -#define EEPROM_ADDR_WRITE 0x00000000 -#define EEPROM_ADDR_READ 0x80000000 -#define EEPROM_ADDR_COMPLETE 0x40000000 -#define EEPROM_ADDR_FSM_RESET 0x20000000 -#define EEPROM_ADDR_DEVID_MASK 0x1c000000 -#define EEPROM_ADDR_DEVID_SHIFT 26 -#define EEPROM_ADDR_START 0x02000000 -#define EEPROM_ADDR_CLKPERD_SHIFT 16 -#define EEPROM_ADDR_ADDR_MASK 0x0000ffff -#define EEPROM_ADDR_ADDR_SHIFT 0 -#define EEPROM_DEFAULT_CLOCK_PERIOD 0x60 -#define EEPROM_CHIP_SIZE (64 * 1024) -#define GRC_EEPROM_DATA 0x0000683c -#define GRC_EEPROM_CTRL 0x00006840 -#define GRC_MDI_CTRL 0x00006844 -#define GRC_SEEPROM_DELAY 0x00006848 -/* 0x684c --> 0x6c00 unused */ - -/* 0x6c00 --> 0x7000 unused */ - -/* NVRAM Control registers */ -#define NVRAM_CMD 0x00007000 -#define NVRAM_CMD_RESET 0x00000001 -#define NVRAM_CMD_DONE 0x00000008 -#define NVRAM_CMD_GO 0x00000010 -#define NVRAM_CMD_WR 0x00000020 -#define NVRAM_CMD_RD 0x00000000 -#define NVRAM_CMD_ERASE 0x00000040 -#define NVRAM_CMD_FIRST 0x00000080 -#define NVRAM_CMD_LAST 0x00000100 -#define NVRAM_STAT 0x00007004 -#define NVRAM_WRDATA 0x00007008 -#define NVRAM_ADDR 0x0000700c -#define NVRAM_ADDR_MSK 0x00ffffff -#define NVRAM_RDDATA 0x00007010 -#define NVRAM_CFG1 0x00007014 -#define NVRAM_CFG1_FLASHIF_ENAB 0x00000001 -#define NVRAM_CFG1_BUFFERED_MODE 0x00000002 -#define NVRAM_CFG1_PASS_THRU 0x00000004 -#define NVRAM_CFG1_BIT_BANG 0x00000008 -#define NVRAM_CFG1_COMPAT_BYPASS 0x80000000 -#define NVRAM_CFG2 0x00007018 -#define NVRAM_CFG3 0x0000701c -#define NVRAM_SWARB 0x00007020 -#define SWARB_REQ_SET0 0x00000001 -#define SWARB_REQ_SET1 0x00000002 -#define SWARB_REQ_SET2 0x00000004 -#define SWARB_REQ_SET3 0x00000008 -#define SWARB_REQ_CLR0 0x00000010 -#define SWARB_REQ_CLR1 0x00000020 -#define SWARB_REQ_CLR2 0x00000040 -#define SWARB_REQ_CLR3 0x00000080 -#define SWARB_GNT0 0x00000100 -#define SWARB_GNT1 0x00000200 -#define SWARB_GNT2 0x00000400 -#define SWARB_GNT3 0x00000800 -#define SWARB_REQ0 0x00001000 -#define SWARB_REQ1 0x00002000 -#define SWARB_REQ2 0x00004000 -#define SWARB_REQ3 0x00008000 -#define NVRAM_BUFFERED_PAGE_SIZE 264 -#define NVRAM_BUFFERED_PAGE_POS 9 -/* 0x7024 --> 0x7400 unused */ - -/* 0x7400 --> 0x8000 unused */ - -/* 32K Window into NIC internal memory */ -#define NIC_SRAM_WIN_BASE 0x00008000 - -/* Offsets into first 32k of NIC internal memory. */ -#define NIC_SRAM_PAGE_ZERO 0x00000000 -#define NIC_SRAM_SEND_RCB 0x00000100 /* 16 * TG3_BDINFO_... */ -#define NIC_SRAM_RCV_RET_RCB 0x00000200 /* 16 * TG3_BDINFO_... */ -#define NIC_SRAM_STATS_BLK 0x00000300 -#define NIC_SRAM_STATUS_BLK 0x00000b00 - -#define NIC_SRAM_FIRMWARE_MBOX 0x00000b50 -#define NIC_SRAM_FIRMWARE_MBOX_MAGIC1 0x4B657654 -#define NIC_SRAM_FIRMWARE_MBOX_MAGIC2 0x4861764b /* !dma on linkchg */ - -#define NIC_SRAM_DATA_SIG 0x00000b54 -#define NIC_SRAM_DATA_SIG_MAGIC 0x4b657654 /* ascii for 'KevT' */ - -#define NIC_SRAM_DATA_CFG 0x00000b58 -#define NIC_SRAM_DATA_CFG_LED_MODE_MASK 0x0000000c -#define NIC_SRAM_DATA_CFG_LED_MODE_UNKNOWN 0x00000000 -#define NIC_SRAM_DATA_CFG_LED_TRIPLE_SPD 0x00000004 -#define NIC_SRAM_DATA_CFG_LED_OPEN_DRAIN 0x00000004 -#define NIC_SRAM_DATA_CFG_LED_LINK_SPD 0x00000008 -#define NIC_SRAM_DATA_CFG_LED_OUTPUT 0x00000008 -#define NIC_SRAM_DATA_CFG_PHY_TYPE_MASK 0x00000030 -#define NIC_SRAM_DATA_CFG_PHY_TYPE_UNKNOWN 0x00000000 -#define NIC_SRAM_DATA_CFG_PHY_TYPE_COPPER 0x00000010 -#define NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER 0x00000020 -#define NIC_SRAM_DATA_CFG_WOL_ENABLE 0x00000040 -#define NIC_SRAM_DATA_CFG_ASF_ENABLE 0x00000080 -#define NIC_SRAM_DATA_CFG_EEPROM_WP 0x00000100 -#define NIC_SRAM_DATA_CFG_MINI_PCI 0x00001000 -#define NIC_SRAM_DATA_CFG_FIBER_WOL 0x00004000 - -#define NIC_SRAM_DATA_PHY_ID 0x00000b74 -#define NIC_SRAM_DATA_PHY_ID1_MASK 0xffff0000 -#define NIC_SRAM_DATA_PHY_ID2_MASK 0x0000ffff - -#define NIC_SRAM_FW_CMD_MBOX 0x00000b78 -#define FWCMD_NICDRV_ALIVE 0x00000001 -#define FWCMD_NICDRV_PAUSE_FW 0x00000002 -#define FWCMD_NICDRV_IPV4ADDR_CHG 0x00000003 -#define FWCMD_NICDRV_IPV6ADDR_CHG 0x00000004 -#define FWCMD_NICDRV_FIX_DMAR 0x00000005 -#define FWCMD_NICDRV_FIX_DMAW 0x00000006 -#define NIC_SRAM_FW_CMD_LEN_MBOX 0x00000b7c -#define NIC_SRAM_FW_CMD_DATA_MBOX 0x00000b80 -#define NIC_SRAM_FW_ASF_STATUS_MBOX 0x00000c00 -#define NIC_SRAM_FW_DRV_STATE_MBOX 0x00000c04 -#define DRV_STATE_START 0x00000001 -#define DRV_STATE_UNLOAD 0x00000002 -#define DRV_STATE_WOL 0x00000003 -#define DRV_STATE_SUSPEND 0x00000004 - -#define NIC_SRAM_FW_RESET_TYPE_MBOX 0x00000c08 - -#define NIC_SRAM_MAC_ADDR_HIGH_MBOX 0x00000c14 -#define NIC_SRAM_MAC_ADDR_LOW_MBOX 0x00000c18 - -#define NIC_SRAM_RX_MINI_BUFFER_DESC 0x00001000 - -#define NIC_SRAM_DMA_DESC_POOL_BASE 0x00002000 -#define NIC_SRAM_DMA_DESC_POOL_SIZE 0x00002000 -#define NIC_SRAM_TX_BUFFER_DESC 0x00004000 /* 512 entries */ -#define NIC_SRAM_RX_BUFFER_DESC 0x00006000 /* 256 entries */ -#define NIC_SRAM_RX_JUMBO_BUFFER_DESC 0x00007000 /* 256 entries */ -#define NIC_SRAM_MBUF_POOL_BASE 0x00008000 -#define NIC_SRAM_MBUF_POOL_SIZE96 0x00018000 -#define NIC_SRAM_MBUF_POOL_SIZE64 0x00010000 -#define NIC_SRAM_MBUF_POOL_BASE5705 0x00010000 -#define NIC_SRAM_MBUF_POOL_SIZE5705 0x0000e000 - -/* Currently this is fixed. */ -#define PHY_ADDR 0x01 - -/* Tigon3 specific PHY MII registers. */ -#define TG3_BMCR_SPEED1000 0x0040 - -#define MII_TG3_CTRL 0x09 /* 1000-baseT control register */ -#define MII_TG3_CTRL_ADV_1000_HALF 0x0100 -#define MII_TG3_CTRL_ADV_1000_FULL 0x0200 -#define MII_TG3_CTRL_AS_MASTER 0x0800 -#define MII_TG3_CTRL_ENABLE_AS_MASTER 0x1000 - -#define MII_TG3_EXT_CTRL 0x10 /* Extended control register */ -#define MII_TG3_EXT_CTRL_LNK3_LED_MODE 0x0002 -#define MII_TG3_EXT_CTRL_TBI 0x8000 - -#define MII_TG3_EXT_STAT 0x11 /* Extended status register */ -#define MII_TG3_EXT_STAT_LPASS 0x0100 - -#define MII_TG3_DSP_RW_PORT 0x15 /* DSP coefficient read/write port */ - -#define MII_TG3_DSP_ADDRESS 0x17 /* DSP address register */ - -#define MII_TG3_AUX_CTRL 0x18 /* auxilliary control register */ - -#define MII_TG3_AUX_STAT 0x19 /* auxilliary status register */ -#define MII_TG3_AUX_STAT_LPASS 0x0004 -#define MII_TG3_AUX_STAT_SPDMASK 0x0700 -#define MII_TG3_AUX_STAT_10HALF 0x0100 -#define MII_TG3_AUX_STAT_10FULL 0x0200 -#define MII_TG3_AUX_STAT_100HALF 0x0300 -#define MII_TG3_AUX_STAT_100_4 0x0400 -#define MII_TG3_AUX_STAT_100FULL 0x0500 -#define MII_TG3_AUX_STAT_1000HALF 0x0600 -#define MII_TG3_AUX_STAT_1000FULL 0x0700 - -#define MII_TG3_ISTAT 0x1a /* IRQ status register */ -#define MII_TG3_IMASK 0x1b /* IRQ mask register */ - -/* ISTAT/IMASK event bits */ -#define MII_TG3_INT_LINKCHG 0x0002 -#define MII_TG3_INT_SPEEDCHG 0x0004 -#define MII_TG3_INT_DUPLEXCHG 0x0008 -#define MII_TG3_INT_ANEG_PAGE_RX 0x0400 - -/* XXX Add this to mii.h */ -#ifndef ADVERTISE_PAUSE -#define ADVERTISE_PAUSE_CAP 0x0400 -#endif -#ifndef ADVERTISE_PAUSE_ASYM -#define ADVERTISE_PAUSE_ASYM 0x0800 -#endif -#ifndef LPA_PAUSE -#define LPA_PAUSE_CAP 0x0400 -#endif -#ifndef LPA_PAUSE_ASYM -#define LPA_PAUSE_ASYM 0x0800 -#endif - -/* There are two ways to manage the TX descriptors on the tigon3. - * Either the descriptors are in host DMA'able memory, or they - * exist only in the cards on-chip SRAM. All 16 send bds are under - * the same mode, they may not be configured individually. - * - * The mode we use is controlled by TG3_FLAG_HOST_TXDS in tp->tg3_flags. - * - * To use host memory TX descriptors: - * 1) Set GRC_MODE_HOST_SENDBDS in GRC_MODE register. - * Make sure GRC_MODE_4X_NIC_SEND_RINGS is clear. - * 2) Allocate DMA'able memory. - * 3) In NIC_SRAM_SEND_RCB (of desired index) of on-chip SRAM: - * a) Set TG3_BDINFO_HOST_ADDR to DMA address of memory - * obtained in step 2 - * b) Set TG3_BDINFO_NIC_ADDR to NIC_SRAM_TX_BUFFER_DESC. - * c) Set len field of TG3_BDINFO_MAXLEN_FLAGS to number - * of TX descriptors. Leave flags field clear. - * 4) Access TX descriptors via host memory. The chip - * will refetch into local SRAM as needed when producer - * index mailboxes are updated. - * - * To use on-chip TX descriptors: - * 1) Set GRC_MODE_4X_NIC_SEND_RINGS in GRC_MODE register. - * Make sure GRC_MODE_HOST_SENDBDS is clear. - * 2) In NIC_SRAM_SEND_RCB (of desired index) of on-chip SRAM: - * a) Set TG3_BDINFO_HOST_ADDR to zero. - * b) Set TG3_BDINFO_NIC_ADDR to NIC_SRAM_TX_BUFFER_DESC - * c) TG3_BDINFO_MAXLEN_FLAGS is don't care. - * 3) Access TX descriptors directly in on-chip SRAM - * using normal {read,write}l(). (and not using - * pointer dereferencing of ioremap()'d memory like - * the broken Broadcom driver does) - * - * Note that BDINFO_FLAGS_DISABLED should be set in the flags field of - * TG3_BDINFO_MAXLEN_FLAGS of all unused SEND_RCB indices. - */ -struct tg3_tx_buffer_desc { - u32 addr_hi; - u32 addr_lo; - - u32 len_flags; -#define TXD_FLAG_TCPUDP_CSUM 0x0001 -#define TXD_FLAG_IP_CSUM 0x0002 -#define TXD_FLAG_END 0x0004 -#define TXD_FLAG_IP_FRAG 0x0008 -#define TXD_FLAG_IP_FRAG_END 0x0010 -#define TXD_FLAG_VLAN 0x0040 -#define TXD_FLAG_COAL_NOW 0x0080 -#define TXD_FLAG_CPU_PRE_DMA 0x0100 -#define TXD_FLAG_CPU_POST_DMA 0x0200 -#define TXD_FLAG_ADD_SRC_ADDR 0x1000 -#define TXD_FLAG_CHOOSE_SRC_ADDR 0x6000 -#define TXD_FLAG_NO_CRC 0x8000 -#define TXD_LEN_SHIFT 16 - - u32 vlan_tag; -#define TXD_VLAN_TAG_SHIFT 0 -#define TXD_MSS_SHIFT 16 -}; - -#define TXD_ADDR 0x00UL /* 64-bit */ -#define TXD_LEN_FLAGS 0x08UL /* 32-bit (upper 16-bits are len) */ -#define TXD_VLAN_TAG 0x0cUL /* 32-bit (upper 16-bits are tag) */ -#define TXD_SIZE 0x10UL - -struct tg3_rx_buffer_desc { - u32 addr_hi; - u32 addr_lo; - - u32 idx_len; -#define RXD_IDX_MASK 0xffff0000 -#define RXD_IDX_SHIFT 16 -#define RXD_LEN_MASK 0x0000ffff -#define RXD_LEN_SHIFT 0 - - u32 type_flags; -#define RXD_TYPE_SHIFT 16 -#define RXD_FLAGS_SHIFT 0 - -#define RXD_FLAG_END 0x0004 -#define RXD_FLAG_MINI 0x0800 -#define RXD_FLAG_JUMBO 0x0020 -#define RXD_FLAG_VLAN 0x0040 -#define RXD_FLAG_ERROR 0x0400 -#define RXD_FLAG_IP_CSUM 0x1000 -#define RXD_FLAG_TCPUDP_CSUM 0x2000 -#define RXD_FLAG_IS_TCP 0x4000 - - u32 ip_tcp_csum; -#define RXD_IPCSUM_MASK 0xffff0000 -#define RXD_IPCSUM_SHIFT 16 -#define RXD_TCPCSUM_MASK 0x0000ffff -#define RXD_TCPCSUM_SHIFT 0 - - u32 err_vlan; - -#define RXD_VLAN_MASK 0x0000ffff - -#define RXD_ERR_BAD_CRC 0x00010000 -#define RXD_ERR_COLLISION 0x00020000 -#define RXD_ERR_LINK_LOST 0x00040000 -#define RXD_ERR_PHY_DECODE 0x00080000 -#define RXD_ERR_ODD_NIBBLE_RCVD_MII 0x00100000 -#define RXD_ERR_MAC_ABRT 0x00200000 -#define RXD_ERR_TOO_SMALL 0x00400000 -#define RXD_ERR_NO_RESOURCES 0x00800000 -#define RXD_ERR_HUGE_FRAME 0x01000000 -#define RXD_ERR_MASK 0xffff0000 - - u32 reserved; - u32 opaque; -#define RXD_OPAQUE_INDEX_MASK 0x0000ffff -#define RXD_OPAQUE_INDEX_SHIFT 0 -#define RXD_OPAQUE_RING_STD 0x00010000 -#define RXD_OPAQUE_RING_JUMBO 0x00020000 -#define RXD_OPAQUE_RING_MINI 0x00040000 -#define RXD_OPAQUE_RING_MASK 0x00070000 -}; - -struct tg3_ext_rx_buffer_desc { - struct { - u32 addr_hi; - u32 addr_lo; - } addrlist[3]; - u32 len2_len1; - u32 resv_len3; - struct tg3_rx_buffer_desc std; -}; - -/* We only use this when testing out the DMA engine - * at probe time. This is the internal format of buffer - * descriptors used by the chip at NIC_SRAM_DMA_DESCS. - */ -struct tg3_internal_buffer_desc { - u32 addr_hi; - u32 addr_lo; - u32 nic_mbuf; - /* XXX FIX THIS */ -#ifdef __BIG_ENDIAN - u16 cqid_sqid; - u16 len; -#else - u16 len; - u16 cqid_sqid; -#endif - u32 flags; - u32 __cookie1; - u32 __cookie2; - u32 __cookie3; -}; - -#define TG3_HW_STATUS_SIZE 0x50 -struct tg3_hw_status { - u32 status; -#define SD_STATUS_UPDATED 0x00000001 -#define SD_STATUS_LINK_CHG 0x00000002 -#define SD_STATUS_ERROR 0x00000004 - - u32 status_tag; - -#ifdef __BIG_ENDIAN - u16 rx_consumer; - u16 rx_jumbo_consumer; -#else - u16 rx_jumbo_consumer; - u16 rx_consumer; -#endif - -#ifdef __BIG_ENDIAN - u16 reserved; - u16 rx_mini_consumer; -#else - u16 rx_mini_consumer; - u16 reserved; -#endif - struct { -#ifdef __BIG_ENDIAN - u16 tx_consumer; - u16 rx_producer; -#else - u16 rx_producer; - u16 tx_consumer; -#endif - } idx[16]; -}; - -typedef struct { - u32 high, low; -} tg3_stat64_t; - -struct tg3_hw_stats { - u8 __reserved0[0x400-0x300]; - - /* Statistics maintained by Receive MAC. */ - tg3_stat64_t rx_octets; - u64 __reserved1; - tg3_stat64_t rx_fragments; - tg3_stat64_t rx_ucast_packets; - tg3_stat64_t rx_mcast_packets; - tg3_stat64_t rx_bcast_packets; - tg3_stat64_t rx_fcs_errors; - tg3_stat64_t rx_align_errors; - tg3_stat64_t rx_xon_pause_rcvd; - tg3_stat64_t rx_xoff_pause_rcvd; - tg3_stat64_t rx_mac_ctrl_rcvd; - tg3_stat64_t rx_xoff_entered; - tg3_stat64_t rx_frame_too_long_errors; - tg3_stat64_t rx_jabbers; - tg3_stat64_t rx_undersize_packets; - tg3_stat64_t rx_in_length_errors; - tg3_stat64_t rx_out_length_errors; - tg3_stat64_t rx_64_or_less_octet_packets; - tg3_stat64_t rx_65_to_127_octet_packets; - tg3_stat64_t rx_128_to_255_octet_packets; - tg3_stat64_t rx_256_to_511_octet_packets; - tg3_stat64_t rx_512_to_1023_octet_packets; - tg3_stat64_t rx_1024_to_1522_octet_packets; - tg3_stat64_t rx_1523_to_2047_octet_packets; - tg3_stat64_t rx_2048_to_4095_octet_packets; - tg3_stat64_t rx_4096_to_8191_octet_packets; - tg3_stat64_t rx_8192_to_9022_octet_packets; - - u64 __unused0[37]; - - /* Statistics maintained by Transmit MAC. */ - tg3_stat64_t tx_octets; - u64 __reserved2; - tg3_stat64_t tx_collisions; - tg3_stat64_t tx_xon_sent; - tg3_stat64_t tx_xoff_sent; - tg3_stat64_t tx_flow_control; - tg3_stat64_t tx_mac_errors; - tg3_stat64_t tx_single_collisions; - tg3_stat64_t tx_mult_collisions; - tg3_stat64_t tx_deferred; - u64 __reserved3; - tg3_stat64_t tx_excessive_collisions; - tg3_stat64_t tx_late_collisions; - tg3_stat64_t tx_collide_2times; - tg3_stat64_t tx_collide_3times; - tg3_stat64_t tx_collide_4times; - tg3_stat64_t tx_collide_5times; - tg3_stat64_t tx_collide_6times; - tg3_stat64_t tx_collide_7times; - tg3_stat64_t tx_collide_8times; - tg3_stat64_t tx_collide_9times; - tg3_stat64_t tx_collide_10times; - tg3_stat64_t tx_collide_11times; - tg3_stat64_t tx_collide_12times; - tg3_stat64_t tx_collide_13times; - tg3_stat64_t tx_collide_14times; - tg3_stat64_t tx_collide_15times; - tg3_stat64_t tx_ucast_packets; - tg3_stat64_t tx_mcast_packets; - tg3_stat64_t tx_bcast_packets; - tg3_stat64_t tx_carrier_sense_errors; - tg3_stat64_t tx_discards; - tg3_stat64_t tx_errors; - - u64 __unused1[31]; - - /* Statistics maintained by Receive List Placement. */ - tg3_stat64_t COS_rx_packets[16]; - tg3_stat64_t COS_rx_filter_dropped; - tg3_stat64_t dma_writeq_full; - tg3_stat64_t dma_write_prioq_full; - tg3_stat64_t rxbds_empty; - tg3_stat64_t rx_discards; - tg3_stat64_t rx_errors; - tg3_stat64_t rx_threshold_hit; - - u64 __unused2[9]; - - /* Statistics maintained by Send Data Initiator. */ - tg3_stat64_t COS_out_packets[16]; - tg3_stat64_t dma_readq_full; - tg3_stat64_t dma_read_prioq_full; - tg3_stat64_t tx_comp_queue_full; - - /* Statistics maintained by Host Coalescing. */ - tg3_stat64_t ring_set_send_prod_index; - tg3_stat64_t ring_status_update; - tg3_stat64_t nic_irqs; - tg3_stat64_t nic_avoided_irqs; - tg3_stat64_t nic_tx_threshold_hit; - - u8 __reserved4[0xb00-0x9c0]; -}; - -enum phy_led_mode { - led_mode_auto, - led_mode_three_link, - led_mode_link10 -}; - -/* 'mapping' is superfluous as the chip does not write into - * the tx/rx post rings so we could just fetch it from there. - * But the cache behavior is better how we are doing it now. - */ -struct ring_info { - struct sk_buff *skb; - DECLARE_PCI_UNMAP_ADDR(mapping) -}; - -struct tx_ring_info { - struct sk_buff *skb; - DECLARE_PCI_UNMAP_ADDR(mapping) - u32 prev_vlan_tag; -}; - -struct tg3_config_info { - u32 flags; -}; - -struct tg3_link_config { - /* Describes what we're trying to get. */ - u32 advertising; - u16 speed; - u8 duplex; - u8 autoneg; - - /* Describes what we actually have. */ - u16 active_speed; - u8 active_duplex; -#define SPEED_INVALID 0xffff -#define DUPLEX_INVALID 0xff -#define AUTONEG_INVALID 0xff - - /* When we go in and out of low power mode we need - * to swap with this state. - */ - int phy_is_low_power; - u16 orig_speed; - u8 orig_duplex; - u8 orig_autoneg; -}; - -struct tg3_bufmgr_config { - u32 mbuf_read_dma_low_water; - u32 mbuf_mac_rx_low_water; - u32 mbuf_high_water; - - u32 mbuf_read_dma_low_water_jumbo; - u32 mbuf_mac_rx_low_water_jumbo; - u32 mbuf_high_water_jumbo; - - u32 dma_low_water; - u32 dma_high_water; -}; - -struct tg3 { - /* begin "general, frequently-used members" cacheline section */ - - /* SMP locking strategy: - * - * lock: Held during all operations except TX packet - * processing. - * - * tx_lock: Held during tg3_start_xmit{,_4gbug} and tg3_tx - * - * If you want to shut up all asynchronous processing you must - * acquire both locks, 'lock' taken before 'tx_lock'. IRQs must - * be disabled to take 'lock' but only softirq disabling is - * necessary for acquisition of 'tx_lock'. - */ - spinlock_t lock; - spinlock_t indirect_lock; - - unsigned long regs; - struct net_device *dev; - struct pci_dev *pdev; - - struct tg3_hw_status *hw_status; - dma_addr_t status_mapping; - - u32 msg_enable; - - /* begin "tx thread" cacheline section */ - u32 tx_prod; - u32 tx_cons; - u32 tx_pending; - - spinlock_t tx_lock; - - /* TX descs are only used if TG3_FLAG_HOST_TXDS is set. */ - struct tg3_tx_buffer_desc *tx_ring; - struct tx_ring_info *tx_buffers; - dma_addr_t tx_desc_mapping; - - /* begin "rx thread" cacheline section */ - u32 rx_rcb_ptr; - u32 rx_std_ptr; - u32 rx_jumbo_ptr; - u32 rx_pending; - u32 rx_jumbo_pending; -#if TG3_VLAN_TAG_USED - struct vlan_group *vlgrp; -#endif - - struct tg3_rx_buffer_desc *rx_std; - struct ring_info *rx_std_buffers; - dma_addr_t rx_std_mapping; - - struct tg3_rx_buffer_desc *rx_jumbo; - struct ring_info *rx_jumbo_buffers; - dma_addr_t rx_jumbo_mapping; - - struct tg3_rx_buffer_desc *rx_rcb; - dma_addr_t rx_rcb_mapping; - - /* begin "everything else" cacheline(s) section */ - struct net_device_stats net_stats; - struct net_device_stats net_stats_prev; - unsigned long phy_crc_errors; - - u32 rx_offset; - u32 tg3_flags; -#define TG3_FLAG_HOST_TXDS 0x00000001 -#define TG3_FLAG_TXD_MBOX_HWBUG 0x00000002 -#define TG3_FLAG_RX_CHECKSUMS 0x00000004 -#define TG3_FLAG_USE_LINKCHG_REG 0x00000008 -#define TG3_FLAG_USE_MI_INTERRUPT 0x00000010 -#define TG3_FLAG_ENABLE_ASF 0x00000020 -#define TG3_FLAG_5701_REG_WRITE_BUG 0x00000040 -#define TG3_FLAG_POLL_SERDES 0x00000080 -#define TG3_FLAG_MBOX_WRITE_REORDER 0x00000100 -#define TG3_FLAG_PCIX_TARGET_HWBUG 0x00000200 -#define TG3_FLAG_WOL_SPEED_100MB 0x00000400 -#define TG3_FLAG_WOL_ENABLE 0x00000800 -#define TG3_FLAG_EEPROM_WRITE_PROT 0x00001000 -#define TG3_FLAG_NVRAM 0x00002000 -#define TG3_FLAG_NVRAM_BUFFERED 0x00004000 -#define TG3_FLAG_RX_PAUSE 0x00008000 -#define TG3_FLAG_TX_PAUSE 0x00010000 -#define TG3_FLAG_PCIX_MODE 0x00020000 -#define TG3_FLAG_PCI_HIGH_SPEED 0x00040000 -#define TG3_FLAG_PCI_32BIT 0x00080000 -#define TG3_FLAG_NO_TX_PSEUDO_CSUM 0x00100000 -#define TG3_FLAG_NO_RX_PSEUDO_CSUM 0x00200000 -#define TG3_FLAG_SERDES_WOL_CAP 0x00400000 -#define TG3_FLAG_JUMBO_ENABLE 0x00800000 -#define TG3_FLAG_10_100_ONLY 0x01000000 -#define TG3_FLAG_PAUSE_AUTONEG 0x02000000 -#define TG3_FLAG_PAUSE_RX 0x04000000 -#define TG3_FLAG_PAUSE_TX 0x08000000 -#define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 -#define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000 -#define TG3_FLAG_SPLIT_MODE 0x40000000 -#define TG3_FLAG_INIT_COMPLETE 0x80000000 - u32 tg3_flags2; -#define TG3_FLG2_RESTART_TIMER 0x00000001 -#define TG3_FLG2_SUN_5704 0x00000002 -#define TG3_FLG2_NO_ETH_WIRE_SPEED 0x00000004 -#define TG3_FLG2_IS_5788 0x00000008 -#define TG3_FLG2_MAX_RXPEND_64 0x00000010 -#define TG3_FLG2_TSO_CAPABLE 0x00000020 - - u32 split_mode_max_reqs; -#define SPLIT_MODE_5704_MAX_REQ 3 - - struct timer_list timer; - u16 timer_counter; - u16 timer_multiplier; - u32 timer_offset; - u16 asf_counter; - u16 asf_multiplier; - - struct tg3_link_config link_config; - struct tg3_bufmgr_config bufmgr_config; - - /* cache h/w values, often passed straight to h/w */ - u32 rx_mode; - u32 tx_mode; - u32 mac_mode; - u32 mi_mode; - u32 misc_host_ctrl; - u32 grc_mode; - u32 grc_local_ctrl; - u32 dma_rwctrl; - u32 coalesce_mode; - - /* PCI block */ - u16 pci_chip_rev_id; - u8 pci_cacheline_sz; - u8 pci_lat_timer; - u8 pci_hdr_type; - u8 pci_bist; - u32 pci_cfg_state[64 / sizeof(u32)]; - - int pm_cap; - - /* PHY info */ - u32 phy_id; -#define PHY_ID_MASK 0xfffffff0 -#define PHY_ID_BCM5400 0x60008040 -#define PHY_ID_BCM5401 0x60008050 -#define PHY_ID_BCM5411 0x60008070 -#define PHY_ID_BCM5701 0x60008110 -#define PHY_ID_BCM5703 0x60008160 -#define PHY_ID_BCM5704 0x60008190 -#define PHY_ID_BCM5705 0x600081a0 -#define PHY_ID_BCM8002 0x60010140 -#define PHY_ID_SERDES 0xfeedbee0 -#define PHY_ID_INVALID 0xffffffff -#define PHY_ID_REV_MASK 0x0000000f -#define PHY_REV_BCM5401_B0 0x1 -#define PHY_REV_BCM5401_B2 0x3 -#define PHY_REV_BCM5401_C0 0x6 -#define PHY_REV_BCM5411_X0 0x1 /* Found on Netgear GA302T */ - - enum phy_led_mode led_mode; - - char board_part_number[24]; - u32 nic_sram_data_cfg; - u32 pci_clock_ctrl; - struct pci_dev *pdev_peer; - - /* This macro assumes the passed PHY ID is already masked - * with PHY_ID_MASK. - */ -#define KNOWN_PHY_ID(X) \ - ((X) == PHY_ID_BCM5400 || (X) == PHY_ID_BCM5401 || \ - (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \ - (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \ - (X) == PHY_ID_BCM5705 || \ - (X) == PHY_ID_BCM8002 || (X) == PHY_ID_SERDES) - - struct tg3_hw_stats *hw_stats; - dma_addr_t stats_mapping; - struct tq_struct reset_task; -}; - -#endif /* !(_T3_H) */ diff --git a/xen/drivers/net/tulip/21142.c b/xen/drivers/net/tulip/21142.c deleted file mode 100644 index e237590103..0000000000 --- a/xen/drivers/net/tulip/21142.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - drivers/net/tulip/21142.c - - Maintained by Jeff Garzik - Copyright 2000,2001 The Linux Kernel Team - Written/copyright 1994-2001 by Donald Becker. - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Please refer to Documentation/DocBook/tulip.{pdf,ps,html} - for more information on this driver, or visit the project - Web page at http://sourceforge.net/projects/tulip/ - -*/ - -#include "tulip.h" -#include -#include - - -static u16 t21142_csr13[] = { 0x0001, 0x0009, 0x0009, 0x0000, 0x0001, }; -u16 t21142_csr14[] = { 0xFFFF, 0x0705, 0x0705, 0x0000, 0x7F3D, }; -static u16 t21142_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; - - -/* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list - of available transceivers. */ -void t21142_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - int csr12 = inl(ioaddr + CSR12); - int next_tick = 60*HZ; - int new_csr6 = 0; - - if (tulip_debug > 2) - printk(KERN_INFO"%s: 21143 negotiation status %8.8x, %s.\n", - dev->name, csr12, medianame[dev->if_port]); - if (tulip_media_cap[dev->if_port] & MediaIsMII) { - tulip_check_duplex(dev); - next_tick = 60*HZ; - } else if (tp->nwayset) { - /* Don't screw up a negotiated session! */ - if (tulip_debug > 1) - printk(KERN_INFO"%s: Using NWay-set %s media, csr12 %8.8x.\n", - dev->name, medianame[dev->if_port], csr12); - } else if (tp->medialock) { - ; - } else if (dev->if_port == 3) { - if (csr12 & 2) { /* No 100mbps link beat, revert to 10mbps. */ - if (tulip_debug > 1) - printk(KERN_INFO"%s: No 21143 100baseTx link beat, %8.8x, " - "trying NWay.\n", dev->name, csr12); - t21142_start_nway(dev); - next_tick = 3*HZ; - } - } else if ((csr12 & 0x7000) != 0x5000) { - /* Negotiation failed. Search media types. */ - if (tulip_debug > 1) - printk(KERN_INFO"%s: 21143 negotiation failed, status %8.8x.\n", - dev->name, csr12); - if (!(csr12 & 4)) { /* 10mbps link beat good. */ - new_csr6 = 0x82420000; - dev->if_port = 0; - outl(0, ioaddr + CSR13); - outl(0x0003FFFF, ioaddr + CSR14); - outw(t21142_csr15[dev->if_port], ioaddr + CSR15); - outl(t21142_csr13[dev->if_port], ioaddr + CSR13); - } else { - /* Select 100mbps port to check for link beat. */ - new_csr6 = 0x83860000; - dev->if_port = 3; - outl(0, ioaddr + CSR13); - outl(0x0003FF7F, ioaddr + CSR14); - outw(8, ioaddr + CSR15); - outl(1, ioaddr + CSR13); - } - if (tulip_debug > 1) - printk(KERN_INFO"%s: Testing new 21143 media %s.\n", - dev->name, medianame[dev->if_port]); - if (new_csr6 != (tp->csr6 & ~0x00D5)) { - tp->csr6 &= 0x00D5; - tp->csr6 |= new_csr6; - outl(0x0301, ioaddr + CSR12); - tulip_restart_rxtx(tp); - } - next_tick = 3*HZ; - } - - /* mod_timer synchronizes us with potential add_timer calls - * from interrupts. - */ - mod_timer(&tp->timer, RUN_AT(next_tick)); -} - - -void t21142_start_nway(struct net_device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - int csr14 = ((tp->sym_advertise & 0x0780) << 9) | - ((tp->sym_advertise & 0x0020) << 1) | 0xffbf; - - dev->if_port = 0; - tp->nway = tp->mediasense = 1; - tp->nwayset = tp->lpar = 0; - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Restarting 21143 autonegotiation, csr14=%8.8x.\n", - dev->name, csr14); - outl(0x0001, ioaddr + CSR13); - udelay(100); - outl(csr14, ioaddr + CSR14); - tp->csr6 = 0x82420000 | (tp->sym_advertise & 0x0040 ? FullDuplex : 0); - outl(tp->csr6, ioaddr + CSR6); - if (tp->mtable && tp->mtable->csr15dir) { - outl(tp->mtable->csr15dir, ioaddr + CSR15); - outl(tp->mtable->csr15val, ioaddr + CSR15); - } else - outw(0x0008, ioaddr + CSR15); - outl(0x1301, ioaddr + CSR12); /* Trigger NWAY. */ -} - - - -void t21142_lnk_change(struct net_device *dev, int csr5) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - int csr12 = inl(ioaddr + CSR12); - - if (tulip_debug > 1) - printk(KERN_INFO"%s: 21143 link status interrupt %8.8x, CSR5 %x, " - "%8.8x.\n", dev->name, csr12, csr5, inl(ioaddr + CSR14)); - - /* If NWay finished and we have a negotiated partner capability. */ - if (tp->nway && !tp->nwayset && (csr12 & 0x7000) == 0x5000) { - int setup_done = 0; - int negotiated = tp->sym_advertise & (csr12 >> 16); - tp->lpar = csr12 >> 16; - tp->nwayset = 1; - if (negotiated & 0x0100) dev->if_port = 5; - else if (negotiated & 0x0080) dev->if_port = 3; - else if (negotiated & 0x0040) dev->if_port = 4; - else if (negotiated & 0x0020) dev->if_port = 0; - else { - tp->nwayset = 0; - if ((csr12 & 2) == 0 && (tp->sym_advertise & 0x0180)) - dev->if_port = 3; - } - tp->full_duplex = (tulip_media_cap[dev->if_port] & MediaAlwaysFD) ? 1:0; - - if (tulip_debug > 1) { - if (tp->nwayset) - printk(KERN_INFO "%s: Switching to %s based on link " - "negotiation %4.4x & %4.4x = %4.4x.\n", - dev->name, medianame[dev->if_port], tp->sym_advertise, - tp->lpar, negotiated); - else - printk(KERN_INFO "%s: Autonegotiation failed, using %s," - " link beat status %4.4x.\n", - dev->name, medianame[dev->if_port], csr12); - } - - if (tp->mtable) { - int i; - for (i = 0; i < tp->mtable->leafcount; i++) - if (tp->mtable->mleaf[i].media == dev->if_port) { - int startup = ! ((tp->chip_id == DC21143 && tp->revision == 65)); - tp->cur_index = i; - tulip_select_media(dev, startup); - setup_done = 1; - break; - } - } - if ( ! setup_done) { - tp->csr6 = (dev->if_port & 1 ? 0x838E0000 : 0x82420000) | (tp->csr6 & 0x20ff); - if (tp->full_duplex) - tp->csr6 |= 0x0200; - outl(1, ioaddr + CSR13); - } -#if 0 /* Restart shouldn't be needed. */ - outl(tp->csr6 | RxOn, ioaddr + CSR6); - if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Restarting Tx and Rx, CSR5 is %8.8x.\n", - dev->name, inl(ioaddr + CSR5)); -#endif - tulip_start_rxtx(tp); - if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Setting CSR6 %8.8x/%x CSR12 %8.8x.\n", - dev->name, tp->csr6, inl(ioaddr + CSR6), - inl(ioaddr + CSR12)); - } else if ((tp->nwayset && (csr5 & 0x08000000) - && (dev->if_port == 3 || dev->if_port == 5) - && (csr12 & 2) == 2) || - (tp->nway && (csr5 & (TPLnkFail)))) { - /* Link blew? Maybe restart NWay. */ - del_timer_sync(&tp->timer); - t21142_start_nway(dev); - tp->timer.expires = RUN_AT(3*HZ); - add_timer(&tp->timer); - } else if (dev->if_port == 3 || dev->if_port == 5) { - if (tulip_debug > 1) - printk(KERN_INFO"%s: 21143 %s link beat %s.\n", - dev->name, medianame[dev->if_port], - (csr12 & 2) ? "failed" : "good"); - if ((csr12 & 2) && ! tp->medialock) { - del_timer_sync(&tp->timer); - t21142_start_nway(dev); - tp->timer.expires = RUN_AT(3*HZ); - add_timer(&tp->timer); - } else if (dev->if_port == 5) - outl(inl(ioaddr + CSR14) & ~0x080, ioaddr + CSR14); - } else if (dev->if_port == 0 || dev->if_port == 4) { - if ((csr12 & 4) == 0) - printk(KERN_INFO"%s: 21143 10baseT link beat good.\n", - dev->name); - } else if (!(csr12 & 4)) { /* 10mbps link beat good. */ - if (tulip_debug) - printk(KERN_INFO"%s: 21143 10mbps sensed media.\n", - dev->name); - dev->if_port = 0; - } else if (tp->nwayset) { - if (tulip_debug) - printk(KERN_INFO"%s: 21143 using NWay-set %s, csr6 %8.8x.\n", - dev->name, medianame[dev->if_port], tp->csr6); - } else { /* 100mbps link beat good. */ - if (tulip_debug) - printk(KERN_INFO"%s: 21143 100baseTx sensed media.\n", - dev->name); - dev->if_port = 3; - tp->csr6 = 0x838E0000 | (tp->csr6 & 0x20ff); - outl(0x0003FF7F, ioaddr + CSR14); - outl(0x0301, ioaddr + CSR12); - tulip_restart_rxtx(tp); - } -} - - diff --git a/xen/drivers/net/tulip/ChangeLog b/xen/drivers/net/tulip/ChangeLog deleted file mode 100644 index a235306b6e..0000000000 --- a/xen/drivers/net/tulip/ChangeLog +++ /dev/null @@ -1,563 +0,0 @@ -2002-09-18 Ryan Bradetich - - tulip hppa support: - * eeprom.c (tulip_build_fake_mediatable): new function - (tulip_parse_eeprom): call it, when no media table - * interrupt.c (phy_interrupt): new function - (tulip_interrupt): call it, before checking for no-irq-work - * tulip.c: add HAS_PHY_IRQ chip feature flag. - add csr12_shadow to tulip_private struct, only for hppa currently. - * tulip_core (tulip_init_one): support hppa wonky eeproms - -2002-05-11 Juan Quintela - - * 21142.c (t21142_lnk_change): Revert earlier patch - to always reset phy; only conditionally do so now. - -2002-05-03 Jeff Garzik - - * tulip_core (tulip_pci_tbl): Add new "comet" - pci id. Contributed by Ohta Kyuma. - -2002-03-07 Jeff Garzik - - * tulip_core (tulip_mwi_config): Use new PCI API functions - for enabling and disabled Memory-Write-Invalidate - PCI transaction. - Fix bugs in tulip MWI config also. - -2002-02-07 Uwe Bonnes - - * tulip_core (tulip_pci_tbl[]): - Add PCI id for comet tulip clone. - -2001-12-19 John Zielinski - - * tulip_core.c (tulip_up, tulip_init_one): - More places to revert PHY autoconfiguration bit removal. - -2001-12-16 Andrew Lambeth - - * tulip_core.c (tulip_start_xmit): Use the more-portable - spin_lock_irqsave. - -2001-11-13 David S. Miller - - * tulip_core.c (tulip_mwi_config): Kill unused label early_out. - -2001-11-06 Richard Mortimer - - * tulip_core.c: Correct set of values to mask out of csr0, - for DM9102A chips. Limit burst/alignment of DM9102A chips - on Sparcs. - -2001-11-06 Jun Sun - - * tulip_core.c: Support finding MAC address on - two MIPS boards, DDB5476 and DDB5477. - -2001-11-06 Kevin B. Hendricks - - * Makefile, tulip.h, tulip_core.c, pnic2.c, 21142.c: - Fixes for PNIC II support. - -2001-11-06 David S. Miller - - * tulip_core.c: Support reading MAC address from - Sparc OBP property local-mac-address. - -2001-07-17 Erik A. Hendriks - - * 21142.c: Merge fix from tulip.c 0.92w which prevents the - overwriting of csr6 bits we want to preserve. - -2001-07-10 Jeff Golds - - * tulip_core.c: Fix two comments - -2001-07-06 Stephen Degler - - * media.c: - The media selection process at the end of NWAY is busted - because for the case of MII/SYM it needs to be: - - csr13 <- 0 - csr14 <- 0 - csr6 <- the value calculated is okay. - - In the other media cases csr14 is computed by - t21142_csr14val[dev->if_port], which seems ok. The value of - zero as opposed to 3FFFFF comes straight from appendix D of the - 21143 data book, and it makes logical sense because you're - bypassing all the SIA interface when you usa MII or SYM (see - figure 1-1 in the data book if your're visually oriented) - -2001-07-03 Jeff Golds - - * tulip_core.c (tulip_clean_tx_ring): - Clear status for in-progress Tx's, and count - Tx errors for all packets being released. - -2001-06-16 Jeff Garzik - - * tulip.h, tulip_core.c: - Integrate MMIO support from devel branch, but default - it to off for stable kernel and driver series. - -2001-06-16 Jeff Garzik - - * tulip_core.c (tulip_init_one): - Free descriptor rings on error. - -2001-06-16 Jeff Garzik - - * tulip_core.c (tulip_mwi_config, tulip_init_one): - Large update to csr0 bus configuration code. This is not stable - yet, so it is only conditionally enabled, via CONFIG_TULIP_MWI. - -2001-06-16 Jeff Garzik - - * tulip_core.c: - Initialize timer in tulip_init_one and tulip_down, - not in tulip_up. - -2001-06-14 Jeff Garzik - - * tulip_core.c: - - Update tulip_suspend, tulip_resume for new PCI PM API. - - Surround suspend/resume code with CONFIG_PM. - -2001-06-12 Jeff Golds - - * tulip_core.c: - - Reset sw ring ptrs in tulip_up. Fixes PM resume case. - - Clean rx and tx rings on device down. - -2001-06-05 David Miller - - * tulip_core (set_rx_mode): Do not use set_bit - on an integer variable. Also fix endianness issue. - -2001-06-04 Jeff Garzik - - * interrupt.c: - Simplify rx processing when CONFIG_NET_HW_FLOWCONTROL is - active, and in the process fix a bug where flow control - and low load caused rx not to be acknowledged properly. - -2001-06-01 Jeff Garzik - - * tulip.h: - - Remove tulip_outl_csr helper, redundant. - - Add tulip_start_rxtx inline helper. - - tulip_stop_rxtx helper: Add synchronization. Always use current - csr6 value, instead of tp->csr6 value or value passed as arg. - - tulip_restart_rxtx helper: Add synchronization. Always - use tp->csr6 for desired mode, not value passed as arg. - - New RxOn, TxOn, RxTx constants for csr6 modes. - - Remove now-redundant constants csr6_st, csr6_sr. - - * 21142.c, interrupt.c, media.c, pnic.c, tulip_core.c: - Update for above rxtx helper changes. - - * interrupt.c: - - whitespace cleanup around #ifdef CONFIG_NET_HW_FLOWCONTROL, - convert tabs to spaces. - - Move tp->stats.rx_missed_errors update outside the ifdef. - -2001-05-18 Jeff Garzik - - * tulip_core.c: Added ethtool support. - ETHTOOL_GDRVINFO ioctl only, for now. - -2001-05-14 Robert Olsson - - * Restored HW_FLOWCONTROL from Linux 2.1 series tulip (ANK) - plus Jamal's NETIF_RX_* feedback control. - -2001-05-14 Robert Olsson - - * Added support for 21143's Interrupt Mitigation. - Jamal original instigator. - -2001-05-14 Robert Olsson - - * tulip_refill_rx prototype added to tulip.h - -2001-05-13 Jeff Garzik - - * tulip_core.c: Remove HAS_PCI_MWI flag from Comet, untested. - -2001-05-12 Jeff Garzik - - * tulip_core.c, tulip.h: Remove Conexant PCI id, no chip - docs are available to fix problems with support. - -2001-05-12 Jeff Garzik - - * tulip_core.c (tulip_init_one): Do not call - unregister_netdev in error cleanup. Remnant of old - usage of init_etherdev. - -2001-05-12 Jeff Garzik - - * media.c (tulip_find_mii): Simple write the updated BMCR - twice, as it seems the best thing to do for both broken and - sane chips. - If the mii_advert value, as read from MII_ADVERTISE, is zero, - then generate a value we should advertise from the capability - bits in BMSR. - Fill in tp->advertising for all cases. - Just to be safe, clear all unwanted bits. - -2001-05-12 Jeff Garzik - - * tulip_core.c (private_ioctl): Fill in tp->advertising - when advertising value is changed by the user. - -2001-05-12 Jeff Garzik - - * tulip_core.c: Mark Comet chips as needed the updated MWI - csr0 configuration. - -2001-05-12 Jeff Garzik - - * media.c, tulip_core.c: Move MII scan into - from inlined inside tulip_init_one to new function - tulip_find_mii in media.c. - -2001-05-12 Jeff Garzik - - * media.c (tulip_check_duplex): - Only restart Rx/Tx engines if they are active - (and csr6 changes) - -2001-05-12 Jeff Garzik - - * tulip_core.c (tulip_mwi_config): - Clamp values read from PCI cache line size register to - values acceptable to tulip chip. Done for safety and - -almost- certainly unneeded. - -2001-05-11 Jeff Garzik - - * tulip_core.c (tulip_init_one): - Instead of unconditionally enabling autonegotiation, disable - autonegotiation if not using the default port. Further, - flip the nway bit immediately, and then update the - speed/duplex in a separate MII transaction. We do this - because some boards require that nway be disabled separately, - before media selection is forced. - - TODO: Investigate if we can simply write the same value - to BMCR twice, to avoid setting unnecessarily changing - phy settings. - -2001-05-11 Jeff Garzik - - * tulip.h, tulip_core.c: If HAS_PCI_MWI is set for a - given chip, adjust the csr0 values not according to - provided values but according to system cache line size. - Currently cache alignment is matched as closely to cache - line size as possible. Currently programmable burst limit - is set (ie. never unlimited), and always equal to cache - alignment and system cache size. Currently MWI bit is set - only if the MWI bit is present in the PCI command register. - -2001-05-11 Jeff Garzik - - * media.c (tulip_select_media): - For media types 1 and 3, only use the provided eeprom - advertising value if it is non-zero. - (tulip_check_duplex): - Do not exit ASAP if full_duplex_lock is set. This - ensures that the csr6 value is written if an update - is needed. - -2001-05-10 Jeff Garzik - - Merge PNIC-II-specific stuff from Becker's tulip.c: - - * tulip.h, 21142.c (pnic2_lnk_change): new function - * tulip_core.c (tulip_init_one): use it - - * tulip_core.c (tulip_tx_timeout): Add specific - debugging for PNIC2. - -2001-05-10 Jeff Garzik - - * tulip_core.c (tulip_init_one): Print out - tulip%d instead of PCI device number, for - consistency. - -2001-05-10 Jeff Garzik - - * Merge changes from Becker's tulip.c: - Fix bugs in ioctl. - Fix several bugs by distinguishing between MII - and SYM advertising values. - Set CSR14 autonegotiation bit for media types 2 and 4, - where the SIA CSR setup values are not provided. - -2001-05-10 Jeff Garzik - - * media.c (tulip_select_media): Only update MII - advertising value if startup arg < 2. - - * tulip.h: Do not enable CSR13/14/15 autoconfiguration - for 21041. - - * tulip_core.c: - 21041: add specific code for reset, and do not set CAC bit - When resetting media, for media table type 11 media, pass - value 2 as 'startup' arg to select_media, to avoid updating - MII advertising value. - -2001-05-10 Jeff Garzik - - * pnic.c (pnic_check_duplex): remove - pnic.c (pnic_lnk_change, pnic_timer): use - tulip_check_duplex not pnic_check_duplex. - - * media.c (tulip_check_duplex): - Clean up to use symbolic names instead of numeric constants. - Set TxThreshold mode as necessary as well as clearing it. - Update csr6 if csr6 changes, not simply if duplex changes. - - (found by Manfred Spraul) - -2001-05-10 Jeff Garzik - - * 21142.c, eeprom.c, tulip.h, tulip_core.c: - Remove DPRINTK as another, better method of - debug message printing is available. - -2001-05-09 Jeff Garzik - - * 21142.c (t21142_lnk_change): Pass arg startup==1 - to tulip_select_media, in order to force csr13 to be - zeroed out prior to going to full duplex mode. Fixes - autonegotiation on a quad-port Znyx card. - (from Stephen Dengler) - -2001-05-09 Russell King - - * interrupt.c: Better PCI bus error reporting. - -2001-04-03 Jeff Garzik - - * tulip_core.c: Now that dev->name is only available late - in the probe, insert a hack to replace a not-evaluated - "eth%d" string with an evaluated "tulip%d" string. - Also, remove obvious comment and an indentation cleanup. - -2001-04-03 Jeff Garzik - - * tulip_core.c: If we are a module, always print out the - version string. If we are built into the kernel, only print - the version string if at least one tulip is detected. - -2001-04-03 Jeff Garzik - - Merged from Becker's tulip.c 0.92t: - - * tulip_core.c: Add support for Conexant LANfinity. - -2001-04-03 Jeff Garzik - - * tulip_core.c: Only suspend/resume if the interface - is up and running. Use alloc_etherdev and pci_request_regions. - Spelling fix. - -2001-04-03 Jeff Garzik - - * tulip_core.c: Remove code that existed when one or more of - the following defines existed. These defines were never used - by normal users in practice: TULIP_FULL_DUPLEX, - TULIP_DEFAULT_MEDIA, and TULIP_NO_MEDIA_SWITCH. - - * tulip.h, eeprom.c: Move EE_* constants from tulip.h to eeprom.c. - * tulip.h, media.c: Move MDIO_* constants from tulip.h to media.c. - - * media.c: Add barrier() to mdio_read/write's PNIC status check - loops. - -2001-04-03 Jeff Garzik - - Merged from Becker's tulip.c 0.92t: - - * tulip.h: Add MEDIA_MASK constant for bounding medianame[] - array lookups. - * eeprom.c, media.c, timer.c, tulip_core.c: Use it. - - * media.c, tulip_core.c: mdio_{read,write} cleanup. Since this - is called [pretty much] directly from ioctl, we mask - read/write arguments to limit the values passed. - Added mii_lock. Added comet_miireg2offset and better - Comet-specific mdio_read/write code. Pay closer attention - to the bits we set in ioctl. Remove spinlocks from ioctl, - they are in mdio_read/write now. Use mask to limit - phy number in tulip_init_one's MII scan. - -2001-04-03 Jeff Garzik - - Merged from Becker's tulip.c 0.92t: - - * 21142.c, tulip_core.c: PNIC2 MAC address and NWay fixes. - * tulip.h: Add FullDuplex constant, used in above change. - -2001-04-03 Jeff Garzik - - * timer.c: Do not call netif_carrier_{on,off}, it is not used in - the main tree. Leave code in, disabled, as markers for future - carrier notification. - -2001-04-03 Jeff Garzik - - Merged from Becker's tulip.c 0.92t, except for the tulip.h - whitespace cleanup: - - * interrupt.c: If Rx stops, make sure to update the - multicast filter before restarting. - * tulip.h: Add COMET_MAC_ADDR feature flag, clean up flags. - Add Accept* Rx mode bit constants. - Add mc_filter[] to driver private struct. - * tulip_core.c: Add new Comet PCI id 0x1113:0x9511. - Add COMET_MAC_ADDR feature flag to comet entry in board info array. - Prefer to test COMET_MAC_ADDR flag to testing chip_id for COMET, - when dealing with the Comet's MAC address. - Enable Tx underrun recovery for Comet chips. - Use new Accept* constants in set_rx_mode. - Prefer COMET_MAC_ADDR flag test to chip_id test in set_rx_mode. - Store built mc_filter for later use in intr handler by Comets. - -2001-04-03 Jeff Garzik - - * tulip_core.c: Use tp->cur_tx when building the - setup frame, instead of assuming that the setup - frame is always built in slot zero. This case is - hit during PM resume. - -2001-04-03 Jeff Garzik - - * *.c: Update file headers (copyright, urls, etc.) - * Makefile: re-order to that chip-specific modules on own line - * eeprom.c: BSS/zero-init cleanup (Andrey Panin) - * tulip_core.c: merge medianame[] update from tulip.c. - Additional arch-specific rx_copybreak, csr0 values. (various) - -2001-02-20 Jeff Garzik - - * media.c (tulip_select_media): No need to initialize - new_csr6, all cases initialize it properly. - -2001-02-18 Manfred Spraul - - * interrupt.c (tulip_refill_rx): Make public. - If PNIC chip stops due to lack of Rx buffers, restart it. - (tulip_interrupt): PNIC doesn't have a h/w timer, emulate - with software timers. - * pnic.c (pnic_check_duplex): New function, PNIC-specific - version of tulip_check_duplex. - (pnic_lnk_change): Call pnic_check_duplex. If we use an - external MII, then we mustn't use the internal negotiation. - (pnic_timer): Support Rx refilling on work overflow in - interrupt handler, as PNIC doesn't support a h/w timer. - * tulip_core.c (tulip_tbl[]): Modify default csr6 - -2001-02-11 Jeff Garzik - - * tulip_core.c (tulip_init_one): Call pci_enable_device - to ensure wakeup/resource assignment before checking those - values. - (tulip_init_one): Replace PCI ids with constants from pci_id.h. - (tulip_suspend, tulip_resume, tulip_remove_one): Call - pci_power_on/off (commented out for now). - -2001-02-10 Jeff Garzik - - * tulip.h: Add CFDD_xxx bits for Tulip power management - * tulip_core.c (tulip_set_power_state): New function, - manipulating Tulip chip power state where supported. - (tulip_up, tulip_down, tulip_init_one): Use it. - -2001-02-10 Jeff Garzik - - * tulip_core.c (tulip_tx_timeout): Call netif_wake_queue - to ensure the next Tx is always sent to us. - -2001-01-27 Jeff Garzik - - * tulip_core.c (tulip_remove_one): Fix mem leak by freeing - tp->media_tbl. Add check for !dev, reformat code appropriately. - -2001-01-27 Jeff Garzik - - * tulip_tbl[]: Comment all entries to make order and chip_id - relationship more clear. - * tulip_pci_tbl[]: Add new Accton PCI id (COMET chipset). - -2001-01-16 Jeff Garzik - - * tulip_core.c: static vars no longer explicitly - initialized to zero. - * eeprom.c (tulip_read_eeprom): Make sure to delay between - EE_ENB and EE_ENB|EE_SHIFT_CLK. Merged from becker tulip.c. - -2001-01-05 Peter De Schrijver - - * eeprom.c (tulip_parse_eeprom): Interpret a bit more of 21142 - extended format type 3 info blocks in a tulip SROM. - -2001-01-03 Matti Aarnio - - * media.c (tulip_select_media): Support media types 5 and 6 - -2001-??-?? ?? - - * tulip_core.c: Add comment about LanMedia needing - a different driver. - Enable workarounds for early PCI chipsets. - Add IA64 csr0 support, update HPPA csr0 support. - -2000-12-17 Alan Cox - - * eeprom.c, timer.c, tulip.h, tulip_core.c: Merge support - for the Davicom's quirks into the main tulip. - Patch by Tobias Ringstrom - -2000-11-08 Jim Studt - - * eeprom.c (tulip_parse_eeprom): Check array bounds for - medianame[] and block_name[] arrays to avoid oops due - to bad values returned from hardware. - -2000-11-02 Jeff Garzik - - * tulip_core.c (set_rx_mode): This is synchronized via - dev->xmit_lock, so only the queueing of the setup frame needs to - be locked, against tulip_interrupt. - -2000-11-02 Alexey Kuznetov - - * timer.c (tulip_timer): Call netif_carrier_{on,off} to report - link state to the rest of the kernel, and userspace. - * interrupt.c (tulip_interrupt): Remove tx_full. - * tulip.h: Likewise. - * tulip_core.c (tulip_init_ring, tulip_start_xmit, set_rx_mode): - Likewise. - -2000-10-18 Jeff Garzik - - * tulip_core.c: (tulip_init_one) Print out ethernet interface - on error. Print out a message when pci_enable_device fails. - Handle DMA alloc failure. - -2000-10-18 Jeff Garzik - - * Makefile: New file. - * tulip_core.c (tulip_init_one): Correct error messages - on PIO/MMIO region reserve failure. - (tulip_init_one) Add new check to ensure that PIO region is - sufficient for our needs. - diff --git a/xen/drivers/net/tulip/Makefile b/xen/drivers/net/tulip/Makefile deleted file mode 100644 index a96b5b9835..0000000000 --- a/xen/drivers/net/tulip/Makefile +++ /dev/null @@ -1,8 +0,0 @@ - -include $(BASEDIR)/Rules.mk - -default: $(OBJS) - $(LD) -r -o tulip.o $(OBJS) - -clean: - rm -f *.o *~ core diff --git a/xen/drivers/net/tulip/eeprom.c b/xen/drivers/net/tulip/eeprom.c deleted file mode 100644 index e7f39a7a14..0000000000 --- a/xen/drivers/net/tulip/eeprom.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - drivers/net/tulip/eeprom.c - - Maintained by Jeff Garzik - Copyright 2000,2001 The Linux Kernel Team - Written/copyright 1994-2001 by Donald Becker. - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Please refer to Documentation/DocBook/tulip.{pdf,ps,html} - for more information on this driver, or visit the project - Web page at http://sourceforge.net/projects/tulip/ - -*/ - -#include "tulip.h" -#include -#include - - - -/* Serial EEPROM section. */ -/* The main routine to parse the very complicated SROM structure. - Search www.digital.com for "21X4 SROM" to get details. - This code is very complex, and will require changes to support - additional cards, so I'll be verbose about what is going on. - */ - -/* Known cards that have old-style EEPROMs. */ -static struct eeprom_fixup eeprom_fixups[] __devinitdata = { - {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c, - 0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }}, - {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f, - 0x0000, 0x009E, /* 10baseT */ - 0x0004, 0x009E, /* 10baseT-FD */ - 0x0903, 0x006D, /* 100baseTx */ - 0x0905, 0x006D, /* 100baseTx-FD */ }}, - {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x063f, - 0x0107, 0x8021, /* 100baseFx */ - 0x0108, 0x8021, /* 100baseFx-FD */ - 0x0100, 0x009E, /* 10baseT */ - 0x0104, 0x009E, /* 10baseT-FD */ - 0x0103, 0x006D, /* 100baseTx */ - 0x0105, 0x006D, /* 100baseTx-FD */ }}, - {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0513, - 0x1001, 0x009E, /* 10base2, CSR12 0x10*/ - 0x0000, 0x009E, /* 10baseT */ - 0x0004, 0x009E, /* 10baseT-FD */ - 0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */ - 0x0305, 0x006D, /* 100baseTx-FD CSR12 0x03 */}}, - {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x051F, - 0x1B01, 0x0000, /* 10base2, CSR12 0x1B */ - 0x0B00, 0x009E, /* 10baseT, CSR12 0x0B */ - 0x0B04, 0x009E, /* 10baseT-FD,CSR12 0x0B */ - 0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */ - 0x1B05, 0x006D, /* 100baseTx-FD CSR12 0x1B */ - }}, - {"NetWinder", 0x00, 0x10, 0x57, - /* Default media = MII - * MII block, reset sequence (3) = 0x0821 0x0000 0x0001, capabilities 0x01e1 - */ - { 0x1e00, 0x0000, 0x000b, 0x8f01, 0x0103, 0x0300, 0x0821, 0x000, 0x0001, 0x0000, 0x01e1 } - }, - {0, 0, 0, 0, {}}}; - - -static const char *block_name[] __devinitdata = { - "21140 non-MII", - "21140 MII PHY", - "21142 Serial PHY", - "21142 MII PHY", - "21143 SYM PHY", - "21143 reset method" -}; - - -/** - * tulip_build_fake_mediatable - Build a fake mediatable entry. - * @tp: Ptr to the tulip private data. - * - * Some cards like the 3x5 HSC cards (J3514A) do not have a standard - * srom and can not be handled under the fixup routine. These cards - * still need a valid mediatable entry for correct csr12 setup and - * mii handling. - * - * Since this is currently a parisc-linux specific function, the - * #ifdef __hppa__ should completely optimize this function away for - * non-parisc hardware. - */ -static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp) -{ -#ifdef __hppa__ - unsigned char *ee_data = tp->eeprom; - - if (ee_data[0] == 0x3c && ee_data[1] == 0x10 && - (ee_data[2] == 0x63 || ee_data[2] == 0x61) && ee_data[3] == 0x10) { - - static unsigned char leafdata[] = - { 0x01, /* phy number */ - 0x02, /* gpr setup sequence length */ - 0x02, 0x00, /* gpr setup sequence */ - 0x02, /* phy reset sequence length */ - 0x01, 0x00, /* phy reset sequence */ - 0x00, 0x78, /* media capabilities */ - 0x00, 0xe0, /* nway advertisment */ - 0x00, 0x05, /* fdx bit map */ - 0x00, 0x06 /* ttm bit map */ - }; - - tp->mtable = (struct mediatable *) - kmalloc(sizeof(struct mediatable) + sizeof(struct medialeaf), GFP_KERNEL); - - if (tp->mtable == NULL) - return; /* Horrible, impossible failure. */ - - tp->mtable->defaultmedia = 0x800; - tp->mtable->leafcount = 1; - tp->mtable->csr12dir = 0x3f; /* inputs on bit7 for hsc-pci, bit6 for pci-fx */ - tp->mtable->has_nonmii = 0; - tp->mtable->has_reset = 0; - tp->mtable->has_mii = 1; - tp->mtable->csr15dir = tp->mtable->csr15val = 0; - tp->mtable->mleaf[0].type = 1; - tp->mtable->mleaf[0].media = 11; - tp->mtable->mleaf[0].leafdata = &leafdata[0]; - tp->flags |= HAS_PHY_IRQ; - tp->csr12_shadow = -1; - } -#endif -} - -void __devinit tulip_parse_eeprom(struct net_device *dev) -{ - /* The last media info list parsed, for multiport boards. */ - static struct mediatable *last_mediatable; - static unsigned char *last_ee_data; - static int controller_index; - struct tulip_private *tp = (struct tulip_private *)dev->priv; - unsigned char *ee_data = tp->eeprom; - int i; - - tp->mtable = 0; - /* Detect an old-style (SA only) EEPROM layout: - memcmp(eedata, eedata+16, 8). */ - for (i = 0; i < 8; i ++) - if (ee_data[i] != ee_data[16+i]) - break; - if (i >= 8) { - if (ee_data[0] == 0xff) { - if (last_mediatable) { - controller_index++; - printk(KERN_INFO "%s: Controller %d of multiport board.\n", - dev->name, controller_index); - tp->mtable = last_mediatable; - ee_data = last_ee_data; - goto subsequent_board; - } else - printk(KERN_INFO "%s: Missing EEPROM, this interface may " - "not work correctly!\n", - dev->name); - return; - } - /* Do a fix-up based on the vendor half of the station address prefix. */ - for (i = 0; eeprom_fixups[i].name; i++) { - if (dev->dev_addr[0] == eeprom_fixups[i].addr0 - && dev->dev_addr[1] == eeprom_fixups[i].addr1 - && dev->dev_addr[2] == eeprom_fixups[i].addr2) { - if (dev->dev_addr[2] == 0xE8 && ee_data[0x1a] == 0x55) - i++; /* An Accton EN1207, not an outlaw Maxtech. */ - memcpy(ee_data + 26, eeprom_fixups[i].newtable, - sizeof(eeprom_fixups[i].newtable)); - printk(KERN_INFO "%s: Old format EEPROM on '%s' board. Using" - " substitute media control info.\n", - dev->name, eeprom_fixups[i].name); - break; - } - } - if (eeprom_fixups[i].name == NULL) { /* No fixup found. */ - printk(KERN_INFO "%s: Old style EEPROM with no media selection " - "information.\n", - dev->name); - return; - } - } - - controller_index = 0; - if (ee_data[19] > 1) { /* Multiport board. */ - last_ee_data = ee_data; - } -subsequent_board: - - if (ee_data[27] == 0) { /* No valid media table. */ - tulip_build_fake_mediatable(tp); - } else if (tp->chip_id == DC21041) { - unsigned char *p = (void *)ee_data + ee_data[27 + controller_index*3]; - int media = get_u16(p); - int count = p[2]; - p += 3; - - printk(KERN_INFO "%s: 21041 Media table, default media %4.4x (%s).\n", - dev->name, media, - media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]); - for (i = 0; i < count; i++) { - unsigned char media_block = *p++; - int media_code = media_block & MEDIA_MASK; - if (media_block & 0x40) - p += 6; - printk(KERN_INFO "%s: 21041 media #%d, %s.\n", - dev->name, media_code, medianame[media_code]); - } - } else { - unsigned char *p = (void *)ee_data + ee_data[27]; - unsigned char csr12dir = 0; - int count, new_advertise = 0; - struct mediatable *mtable; - u16 media = get_u16(p); - - p += 2; - if (tp->flags & CSR12_IN_SROM) - csr12dir = *p++; - count = *p++; - - /* there is no phy information, don't even try to build mtable */ - if (count == 0) { - if (tulip_debug > 0) - printk(KERN_WARNING "%s: no phy info, aborting mtable build\n", dev->name); - return; - } - - mtable = (struct mediatable *) - kmalloc(sizeof(struct mediatable) + count*sizeof(struct medialeaf), - GFP_KERNEL); - if (mtable == NULL) - return; /* Horrible, impossible failure. */ - last_mediatable = tp->mtable = mtable; - mtable->defaultmedia = media; - mtable->leafcount = count; - mtable->csr12dir = csr12dir; - mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0; - mtable->csr15dir = mtable->csr15val = 0; - - printk(KERN_INFO "%s: EEPROM default media type %s.\n", dev->name, - media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]); - for (i = 0; i < count; i++) { - struct medialeaf *leaf = &mtable->mleaf[i]; - - if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */ - leaf->type = 0; - leaf->media = p[0] & 0x3f; - leaf->leafdata = p; - if ((p[2] & 0x61) == 0x01) /* Bogus, but Znyx boards do it. */ - mtable->has_mii = 1; - p += 4; - } else { - leaf->type = p[1]; - if (p[1] == 0x05) { - mtable->has_reset = i; - leaf->media = p[2] & 0x0f; - } else if (tp->chip_id == DM910X && p[1] == 0x80) { - /* Hack to ignore Davicom delay period block */ - mtable->leafcount--; - count--; - i--; - leaf->leafdata = p + 2; - p += (p[0] & 0x3f) + 1; - continue; - } else if (p[1] & 1) { - int gpr_len, reset_len; - - mtable->has_mii = 1; - leaf->media = 11; - gpr_len=p[3]*2; - reset_len=p[4+gpr_len]*2; - new_advertise |= get_u16(&p[7+gpr_len+reset_len]); - } else { - mtable->has_nonmii = 1; - leaf->media = p[2] & MEDIA_MASK; - /* Davicom's media number for 100BaseTX is strange */ - if (tp->chip_id == DM910X && leaf->media == 1) - leaf->media = 3; - switch (leaf->media) { - case 0: new_advertise |= 0x0020; break; - case 4: new_advertise |= 0x0040; break; - case 3: new_advertise |= 0x0080; break; - case 5: new_advertise |= 0x0100; break; - case 6: new_advertise |= 0x0200; break; - } - if (p[1] == 2 && leaf->media == 0) { - if (p[2] & 0x40) { - u32 base15 = get_unaligned((u16*)&p[7]); - mtable->csr15dir = - (get_unaligned((u16*)&p[9])<<16) + base15; - mtable->csr15val = - (get_unaligned((u16*)&p[11])<<16) + base15; - } else { - mtable->csr15dir = get_unaligned((u16*)&p[3])<<16; - mtable->csr15val = get_unaligned((u16*)&p[5])<<16; - } - } - } - leaf->leafdata = p + 2; - p += (p[0] & 0x3f) + 1; - } - if (tulip_debug > 1 && leaf->media == 11) { - unsigned char *bp = leaf->leafdata; - printk(KERN_INFO "%s: MII interface PHY %d, setup/reset " - "sequences %d/%d long, capabilities %2.2x %2.2x.\n", - dev->name, bp[0], bp[1], bp[2 + bp[1]*2], - bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]); - } - printk(KERN_INFO "%s: Index #%d - Media %s (#%d) described " - "by a %s (%d) block.\n", - dev->name, i, medianame[leaf->media & 15], leaf->media, - leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "", - leaf->type); - } - if (new_advertise) - tp->sym_advertise = new_advertise; - } -} -/* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */ -#define EE_CS 0x01 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x04 /* Data from the Tulip to EEPROM. */ -#define EE_WRITE_0 0x01 -#define EE_WRITE_1 0x05 -#define EE_DATA_READ 0x08 /* Data from the EEPROM chip. */ -#define EE_ENB (0x4800 | EE_CS) - -/* Delay between EEPROM clock transitions. - Even at 33Mhz current PCI implementations don't overrun the EEPROM clock. - We add a bus turn-around to insure that this remains true. */ -#define eeprom_delay() inl(ee_addr) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_READ_CMD (6) - -/* Note: this routine returns extra data bits for size detection. */ -int __devinit tulip_read_eeprom(long ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - long ee_addr = ioaddr + CSR9; - int read_cmd = location | (EE_READ_CMD << addr_len); - - outl(EE_ENB & ~EE_CS, ee_addr); - outl(EE_ENB, ee_addr); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - outl(EE_ENB | dataval, ee_addr); - eeprom_delay(); - outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); - eeprom_delay(); - retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0); - } - outl(EE_ENB, ee_addr); - eeprom_delay(); - - for (i = 16; i > 0; i--) { - outl(EE_ENB | EE_SHIFT_CLK, ee_addr); - eeprom_delay(); - retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0); - outl(EE_ENB, ee_addr); - eeprom_delay(); - } - - /* Terminate the EEPROM access. */ - outl(EE_ENB & ~EE_CS, ee_addr); - return retval; -} - diff --git a/xen/drivers/net/tulip/interrupt.c b/xen/drivers/net/tulip/interrupt.c deleted file mode 100644 index 330b06cb98..0000000000 --- a/xen/drivers/net/tulip/interrupt.c +++ /dev/null @@ -1,585 +0,0 @@ -/* - drivers/net/tulip/interrupt.c - - Maintained by Jeff Garzik - Copyright 2000,2001 The Linux Kernel Team - Written/copyright 1994-2001 by Donald Becker. - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Please refer to Documentation/DocBook/tulip.{pdf,ps,html} - for more information on this driver, or visit the project - Web page at http://sourceforge.net/projects/tulip/ - -*/ - -#include "tulip.h" -#include -#include -#include - - -int tulip_rx_copybreak; -unsigned int tulip_max_interrupt_work; - -#ifdef CONFIG_NET_HW_FLOWCONTROL - -#define MIT_SIZE 15 -unsigned int mit_table[MIT_SIZE+1] = -{ - /* CRS11 21143 hardware Mitigation Control Interrupt - We use only RX mitigation we other techniques for - TX intr. mitigation. - - 31 Cycle Size (timer control) - 30:27 TX timer in 16 * Cycle size - 26:24 TX No pkts before Int. - 23:20 RX timer in Cycle size - 19:17 RX No pkts before Int. - 16 Continues Mode (CM) - */ - - 0x0, /* IM disabled */ - 0x80150000, /* RX time = 1, RX pkts = 2, CM = 1 */ - 0x80150000, - 0x80270000, - 0x80370000, - 0x80490000, - 0x80590000, - 0x80690000, - 0x807B0000, - 0x808B0000, - 0x809D0000, - 0x80AD0000, - 0x80BD0000, - 0x80CF0000, - 0x80DF0000, -// 0x80FF0000 /* RX time = 16, RX pkts = 7, CM = 1 */ - 0x80F10000 /* RX time = 16, RX pkts = 0, CM = 1 */ -}; -#endif - - -int tulip_refill_rx(struct net_device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - int entry; - int refilled = 0; - - /* Refill the Rx ring buffers. */ - for (; tp->cur_rx - tp->dirty_rx > 0; tp->dirty_rx++) { - entry = tp->dirty_rx % RX_RING_SIZE; - if (tp->rx_buffers[entry].skb == NULL) { - struct sk_buff *skb; - dma_addr_t mapping; - - skb = tp->rx_buffers[entry].skb = dev_alloc_skb(PKT_BUF_SZ); - if (skb == NULL) - break; - - mapping = pci_map_single(tp->pdev, skb->tail, PKT_BUF_SZ, - PCI_DMA_FROMDEVICE); - tp->rx_buffers[entry].mapping = mapping; - - skb->dev = dev; /* Mark as being used by this device. */ - tp->rx_ring[entry].buffer1 = cpu_to_le32(mapping); - refilled++; - } - tp->rx_ring[entry].status = cpu_to_le32(DescOwned); - } - if(tp->chip_id == LC82C168) { - if(((inl(dev->base_addr + CSR5)>>17)&0x07) == 4) { - /* Rx stopped due to out of buffers, - * restart it - */ - outl(0x01, dev->base_addr + CSR2); - } - } - return refilled; -} - - -static int tulip_rx(struct net_device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - int entry = tp->cur_rx % RX_RING_SIZE; - int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx; - int received = 0; - -#ifdef CONFIG_NET_HW_FLOWCONTROL - int drop = 0, mit_sel = 0; - -/* that one buffer is needed for mit activation; or might be a - bug in the ring buffer code; check later -- JHS*/ - - if (rx_work_limit >=RX_RING_SIZE) rx_work_limit--; -#endif - - if (tulip_debug > 4) - printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry, - tp->rx_ring[entry].status); - /* If we own the next entry, it is a new packet. Send it up. */ - while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { - s32 status = le32_to_cpu(tp->rx_ring[entry].status); - - if (tulip_debug > 5) - printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n", - dev->name, entry, status); - if (--rx_work_limit < 0) - break; - if ((status & 0x38008300) != 0x0300) { - if ((status & 0x38000300) != 0x0300) { - /* Ingore earlier buffers. */ - if ((status & 0xffff) != 0x7fff) { - if (tulip_debug > 1) - printk(KERN_WARNING "%s: Oversized Ethernet frame " - "spanned multiple buffers, status %8.8x!\n", - dev->name, status); - tp->stats.rx_length_errors++; - } - } else if (status & RxDescFatalErr) { - /* There was a fatal error. */ - if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", - dev->name, status); - tp->stats.rx_errors++; /* end of a packet.*/ - if (status & 0x0890) tp->stats.rx_length_errors++; - if (status & 0x0004) tp->stats.rx_frame_errors++; - if (status & 0x0002) tp->stats.rx_crc_errors++; - if (status & 0x0001) tp->stats.rx_fifo_errors++; - } - } else { - /* Omit the four octet CRC from the length. */ - short pkt_len = ((status >> 16) & 0x7ff) - 4; - struct sk_buff *skb; - -#ifndef final_version - if (pkt_len > 1518) { - printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n", - dev->name, pkt_len, pkt_len); - pkt_len = 1518; - tp->stats.rx_length_errors++; - } -#endif - -#ifdef CONFIG_NET_HW_FLOWCONTROL - drop = atomic_read(&netdev_dropping); - if (drop) - goto throttle; -#endif -#ifdef COPYBREAK - /* Check if the packet is long enough to accept without copying - to a minimally-sized skbuff. */ - if (pkt_len < tulip_rx_copybreak - && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { - skb->dev = dev; - skb_reserve(skb, 2); /* 16 byte align the IP header */ - pci_dma_sync_single(tp->pdev, - tp->rx_buffers[entry].mapping, - pkt_len, PCI_DMA_FROMDEVICE); -#if ! defined(__alpha__) - eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->tail, - pkt_len, 0); - skb_put(skb, pkt_len); -#else - memcpy(skb_put(skb, pkt_len), - tp->rx_buffers[entry].skb->tail, - pkt_len); -#endif - } else { /* Pass up the skb already on the Rx ring. */ -#else - { -#endif /* COPYBREAK */ - char *temp = skb_put(skb = tp->rx_buffers[entry].skb, - pkt_len); - -#ifndef final_version - if (tp->rx_buffers[entry].mapping != - le32_to_cpu(tp->rx_ring[entry].buffer1)) { - printk(KERN_ERR "%s: Internal fault: The skbuff addresses " - "do not match in tulip_rx: %08x vs. %08x %p / %p.\n", - dev->name, - le32_to_cpu(tp->rx_ring[entry].buffer1), - tp->rx_buffers[entry].mapping, - skb->head, temp); - } -#endif - - pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping, - PKT_BUF_SZ, PCI_DMA_FROMDEVICE); - - tp->rx_buffers[entry].skb = NULL; - tp->rx_buffers[entry].mapping = 0; - } - skb->protocol = eth_type_trans(skb, dev); -#ifdef CONFIG_NET_HW_FLOWCONTROL - mit_sel = -#endif - netif_rx(skb); - -#ifdef CONFIG_NET_HW_FLOWCONTROL - switch (mit_sel) { - case NET_RX_SUCCESS: - case NET_RX_CN_LOW: - case NET_RX_CN_MOD: - break; - - case NET_RX_CN_HIGH: - rx_work_limit -= NET_RX_CN_HIGH; /* additional*/ - break; - case NET_RX_DROP: - rx_work_limit = -1; - break; - default: - printk("unknown feedback return code %d\n", mit_sel); - break; - } - - drop = atomic_read(&netdev_dropping); - if (drop) { -throttle: - rx_work_limit = -1; - mit_sel = NET_RX_DROP; - - if (tp->fc_bit) { - long ioaddr = dev->base_addr; - - /* disable Rx & RxNoBuf ints. */ - outl(tulip_tbl[tp->chip_id].valid_intrs&RX_A_NBF_STOP, ioaddr + CSR7); - set_bit(tp->fc_bit, &netdev_fc_xoff); - } - } -#endif - dev->last_rx = jiffies; - tp->stats.rx_packets++; - tp->stats.rx_bytes += pkt_len; - } - received++; - entry = (++tp->cur_rx) % RX_RING_SIZE; - } -#ifdef CONFIG_NET_HW_FLOWCONTROL - - /* We use this simplistic scheme for IM. It's proven by - real life installations. We can have IM enabled - continuesly but this would cause unnecessary latency. - Unfortunely we can't use all the NET_RX_* feedback here. - This would turn on IM for devices that is not contributing - to backlog congestion with unnecessary latency. - - We monitor the device RX-ring and have: - - HW Interrupt Mitigation either ON or OFF. - - ON: More then 1 pkt received (per intr.) OR we are dropping - OFF: Only 1 pkt received - - Note. We only use min and max (0, 15) settings from mit_table */ - - - if( tp->flags & HAS_INTR_MITIGATION) { - if((received > 1 || mit_sel == NET_RX_DROP) - && tp->mit_sel != 15 ) { - tp->mit_sel = 15; - tp->mit_change = 1; /* Force IM change */ - } - if((received <= 1 && mit_sel != NET_RX_DROP) && tp->mit_sel != 0 ) { - tp->mit_sel = 0; - tp->mit_change = 1; /* Force IM change */ - } - } - - return RX_RING_SIZE+1; /* maxrx+1 */ -#else - return received; -#endif -} - -static inline void phy_interrupt (struct net_device *dev) -{ -#ifdef __hppa__ - int csr12 = inl(dev->base_addr + CSR12) & 0xff; - struct tulip_private *tp = (struct tulip_private *)dev->priv; - - if (csr12 != tp->csr12_shadow) { - /* ack interrupt */ - outl(csr12 | 0x02, dev->base_addr + CSR12); - tp->csr12_shadow = csr12; - /* do link change stuff */ - spin_lock(&tp->lock); - tulip_check_duplex(dev); - spin_unlock(&tp->lock); - /* clear irq ack bit */ - outl(csr12 & ~0x02, dev->base_addr + CSR12); - } -#endif -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *)dev_instance; - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - int csr5; - int entry; - int missed; - int rx = 0; - int tx = 0; - int oi = 0; - int maxrx = RX_RING_SIZE; - int maxtx = TX_RING_SIZE; - int maxoi = TX_RING_SIZE; - unsigned int work_count = tulip_max_interrupt_work; - - /* Let's see whether the interrupt really is for us */ - csr5 = inl(ioaddr + CSR5); - - if (tp->flags & HAS_PHY_IRQ) - phy_interrupt (dev); - - if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) - return; - - tp->nir++; - - do { - /* Acknowledge all of the current interrupt sources ASAP. */ - outl(csr5 & 0x0001ffff, ioaddr + CSR5); - - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", - dev->name, csr5, inl(dev->base_addr + CSR5)); - - if (csr5 & (RxIntr | RxNoBuf)) { -#ifdef CONFIG_NET_HW_FLOWCONTROL - if ((!tp->fc_bit) || - (!test_bit(tp->fc_bit, &netdev_fc_xoff))) -#endif - rx += tulip_rx(dev); - tulip_refill_rx(dev); - } - - if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { - unsigned int dirty_tx; - - spin_lock(&tp->lock); - - for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; - dirty_tx++) { - int entry = dirty_tx % TX_RING_SIZE; - int status = le32_to_cpu(tp->tx_ring[entry].status); - - if (status < 0) - break; /* It still has not been Txed */ - - /* Check for Rx filter setup frames. */ - if (tp->tx_buffers[entry].skb == NULL) { - /* test because dummy frames not mapped */ - if (tp->tx_buffers[entry].mapping) - pci_unmap_single(tp->pdev, - tp->tx_buffers[entry].mapping, - sizeof(tp->setup_frame), - PCI_DMA_TODEVICE); - continue; - } - - if (status & 0x8000) { - /* There was an major error, log it. */ -#ifndef final_version - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, status); -#endif - tp->stats.tx_errors++; - if (status & 0x4104) tp->stats.tx_aborted_errors++; - if (status & 0x0C00) tp->stats.tx_carrier_errors++; - if (status & 0x0200) tp->stats.tx_window_errors++; - if (status & 0x0002) tp->stats.tx_fifo_errors++; - if ((status & 0x0080) && tp->full_duplex == 0) - tp->stats.tx_heartbeat_errors++; - } else { - tp->stats.tx_bytes += - tp->tx_buffers[entry].skb->len; - tp->stats.collisions += (status >> 3) & 15; - tp->stats.tx_packets++; - } - - pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping, - tp->tx_buffers[entry].skb->len, - PCI_DMA_TODEVICE); - - /* Free the original skb. */ - dev_kfree_skb_irq(tp->tx_buffers[entry].skb); - tp->tx_buffers[entry].skb = NULL; - tp->tx_buffers[entry].mapping = 0; - tx++; - } - -#ifndef final_version - if (tp->cur_tx - dirty_tx > TX_RING_SIZE) { - printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += TX_RING_SIZE; - } -#endif - - if (tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) - netif_wake_queue(dev); - - tp->dirty_tx = dirty_tx; - if (csr5 & TxDied) { - if (tulip_debug > 2) - printk(KERN_WARNING "%s: The transmitter stopped." - " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", - dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); - tulip_restart_rxtx(tp); - } - spin_unlock(&tp->lock); - } - - /* Log errors. */ - if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */ - if (csr5 == 0xffffffff) - break; - if (csr5 & TxJabber) tp->stats.tx_errors++; - if (csr5 & TxFIFOUnderflow) { - if ((tp->csr6 & 0xC000) != 0xC000) - tp->csr6 += 0x4000; /* Bump up the Tx threshold */ - else - tp->csr6 |= 0x00200000; /* Store-n-forward. */ - /* Restart the transmit process. */ - tulip_restart_rxtx(tp); - outl(0, ioaddr + CSR1); - } - if (csr5 & (RxDied | RxNoBuf)) { - if (tp->flags & COMET_MAC_ADDR) { - outl(tp->mc_filter[0], ioaddr + 0xAC); - outl(tp->mc_filter[1], ioaddr + 0xB0); - } - } - if (csr5 & RxDied) { /* Missed a Rx frame. */ - tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; -#ifdef CONFIG_NET_HW_FLOWCONTROL - if (tp->fc_bit && !test_bit(tp->fc_bit, &netdev_fc_xoff)) { - tp->stats.rx_errors++; - tulip_start_rxtx(tp); - } -#else - tp->stats.rx_errors++; - tulip_start_rxtx(tp); -#endif - } - /* - * NB: t21142_lnk_change() does a del_timer_sync(), so be careful if this - * call is ever done under the spinlock - */ - if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) { - if (tp->link_change) - (tp->link_change)(dev, csr5); - } - if (csr5 & SytemError) { - int error = (csr5 >> 23) & 7; - /* oops, we hit a PCI error. The code produced corresponds - * to the reason: - * 0 - parity error - * 1 - master abort - * 2 - target abort - * Note that on parity error, we should do a software reset - * of the chip to get it back into a sane state (according - * to the 21142/3 docs that is). - * -- rmk - */ - printk(KERN_ERR "%s: (%lu) System Error occured (%d)\n", - dev->name, tp->nir, error); - } - /* Clear all error sources, included undocumented ones! */ - outl(0x0800f7ba, ioaddr + CSR5); - oi++; - } - if (csr5 & TimerInt) { - - if (tulip_debug > 2) - printk(KERN_ERR "%s: Re-enabling interrupts, %8.8x.\n", - dev->name, csr5); -#ifdef CONFIG_NET_HW_FLOWCONTROL - if (tp->fc_bit && (test_bit(tp->fc_bit, &netdev_fc_xoff))) - if (net_ratelimit()) printk("BUG!! enabling interupt when FC off (timerintr.) \n"); -#endif - outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); - tp->ttimer = 0; - oi++; - } - if (tx > maxtx || rx > maxrx || oi > maxoi) { - if (tulip_debug > 1) - printk(KERN_WARNING "%s: Too much work during an interrupt, " - "csr5=0x%8.8x. (%lu) (%d,%d,%d)\n", dev->name, csr5, tp->nir, tx, rx, oi); - - /* Acknowledge all interrupt sources. */ - outl(0x8001ffff, ioaddr + CSR5); - if (tp->flags & HAS_INTR_MITIGATION) { -#ifdef CONFIG_NET_HW_FLOWCONTROL - if(tp->mit_change) { - outl(mit_table[tp->mit_sel], ioaddr + CSR11); - tp->mit_change = 0; - } -#else - /* Josip Loncaric at ICASE did extensive experimentation - to develop a good interrupt mitigation setting.*/ - outl(0x8b240000, ioaddr + CSR11); -#endif - } else if (tp->chip_id == LC82C168) { - /* the LC82C168 doesn't have a hw timer.*/ - outl(0x00, ioaddr + CSR7); - mod_timer(&tp->timer, RUN_AT(HZ/50)); - } else { - /* Mask all interrupting sources, set timer to - re-enable. */ -#ifndef CONFIG_NET_HW_FLOWCONTROL - outl(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt, ioaddr + CSR7); - outl(0x0012, ioaddr + CSR11); -#endif - } - break; - } - - work_count--; - if (work_count == 0) - break; - - csr5 = inl(ioaddr + CSR5); - } while ((csr5 & (NormalIntr|AbnormalIntr)) != 0); - - tulip_refill_rx(dev); - - /* check if the card is in suspend mode */ - entry = tp->dirty_rx % RX_RING_SIZE; - if (tp->rx_buffers[entry].skb == NULL) { - if (tulip_debug > 1) - printk(KERN_WARNING "%s: in rx suspend mode: (%lu) (tp->cur_rx = %u, ttimer = %d, rx = %d) go/stay in suspend mode\n", dev->name, tp->nir, tp->cur_rx, tp->ttimer, rx); - if (tp->chip_id == LC82C168) { - outl(0x00, ioaddr + CSR7); - mod_timer(&tp->timer, RUN_AT(HZ/50)); - } else { - if (tp->ttimer == 0 || (inl(ioaddr + CSR11) & 0xffff) == 0) { - if (tulip_debug > 1) - printk(KERN_WARNING "%s: in rx suspend mode: (%lu) set timer\n", dev->name, tp->nir); - outl(tulip_tbl[tp->chip_id].valid_intrs | TimerInt, - ioaddr + CSR7); - outl(TimerInt, ioaddr + CSR5); - outl(12, ioaddr + CSR11); - tp->ttimer = 1; - } - } - } - - if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) { - tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed; - } - - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n", - dev->name, inl(ioaddr + CSR5)); - -} diff --git a/xen/drivers/net/tulip/media.c b/xen/drivers/net/tulip/media.c deleted file mode 100644 index e9bf8b2bfc..0000000000 --- a/xen/drivers/net/tulip/media.c +++ /dev/null @@ -1,563 +0,0 @@ -/* - drivers/net/tulip/media.c - - Maintained by Jeff Garzik - Copyright 2000,2001 The Linux Kernel Team - Written/copyright 1994-2001 by Donald Becker. - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Please refer to Documentation/DocBook/tulip.{pdf,ps,html} - for more information on this driver, or visit the project - Web page at http://sourceforge.net/projects/tulip/ - -*/ - -#include -#include -#include -#include -#include "tulip.h" - - -/* This is a mysterious value that can be written to CSR11 in the 21040 (only) - to support a pre-NWay full-duplex signaling mechanism using short frames. - No one knows what it should be, but if left at its default value some - 10base2(!) packets trigger a full-duplex-request interrupt. */ -#define FULL_DUPLEX_MAGIC 0x6969 - -/* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues or future 66Mhz PCI. */ -#define mdio_delay() inl(mdio_addr) - -/* Read and write the MII registers using software-generated serial - MDIO protocol. It is just different enough from the EEPROM protocol - to not share code. The maxium data clock rate is 2.5 Mhz. */ -#define MDIO_SHIFT_CLK 0x10000 -#define MDIO_DATA_WRITE0 0x00000 -#define MDIO_DATA_WRITE1 0x20000 -#define MDIO_ENB 0x00000 /* Ignore the 0x02000 databook setting. */ -#define MDIO_ENB_IN 0x40000 -#define MDIO_DATA_READ 0x80000 - -static const unsigned char comet_miireg2offset[32] = { - 0xB4, 0xB8, 0xBC, 0xC0, 0xC4, 0xC8, 0xCC, 0, 0,0,0,0, 0,0,0,0, - 0,0xD0,0,0, 0,0,0,0, 0,0,0,0, 0, 0xD4, 0xD8, 0xDC, }; - - -/* MII transceiver control section. - Read and write the MII registers using software-generated serial - MDIO protocol. See the MII specifications or DP83840A data sheet - for details. */ - -int tulip_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - int i; - int read_cmd = (0xf6 << 10) | ((phy_id & 0x1f) << 5) | location; - int retval = 0; - long ioaddr = dev->base_addr; - long mdio_addr = ioaddr + CSR9; - unsigned long flags; - - if (location & ~0x1f) - return 0xffff; - - if (tp->chip_id == COMET && phy_id == 30) { - if (comet_miireg2offset[location]) - return inl(ioaddr + comet_miireg2offset[location]); - return 0xffff; - } - - spin_lock_irqsave(&tp->mii_lock, flags); - if (tp->chip_id == LC82C168) { - int i = 1000; - outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0); - inl(ioaddr + 0xA0); - inl(ioaddr + 0xA0); - while (--i > 0) { - barrier(); - if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000)) - break; - } - spin_unlock_irqrestore(&tp->mii_lock, flags); - return retval & 0xffff; - } - - /* Establish sync by sending at least 32 logic ones. */ - for (i = 32; i >= 0; i--) { - outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); - mdio_delay(); - outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); - mdio_delay(); - } - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; - - outl(MDIO_ENB | dataval, mdio_addr); - mdio_delay(); - outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr); - mdio_delay(); - } - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - outl(MDIO_ENB_IN, mdio_addr); - mdio_delay(); - retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0); - outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); - mdio_delay(); - } - - spin_unlock_irqrestore(&tp->mii_lock, flags); - return (retval>>1) & 0xffff; -} - -void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - int i; - int cmd = (0x5002 << 16) | ((phy_id & 0x1f) << 23) | (location<<18) | (val & 0xffff); - long ioaddr = dev->base_addr; - long mdio_addr = ioaddr + CSR9; - unsigned long flags; - - if (location & ~0x1f) - return; - - if (tp->chip_id == COMET && phy_id == 30) { - if (comet_miireg2offset[location]) - outl(val, ioaddr + comet_miireg2offset[location]); - return; - } - - spin_lock_irqsave(&tp->mii_lock, flags); - if (tp->chip_id == LC82C168) { - int i = 1000; - outl(cmd, ioaddr + 0xA0); - do { - barrier(); - if ( ! (inl(ioaddr + 0xA0) & 0x80000000)) - break; - } while (--i > 0); - spin_unlock_irqrestore(&tp->mii_lock, flags); - return; - } - - /* Establish sync by sending 32 logic ones. */ - for (i = 32; i >= 0; i--) { - outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); - mdio_delay(); - outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); - mdio_delay(); - } - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; - outl(MDIO_ENB | dataval, mdio_addr); - mdio_delay(); - outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr); - mdio_delay(); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - outl(MDIO_ENB_IN, mdio_addr); - mdio_delay(); - outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); - mdio_delay(); - } - - spin_unlock_irqrestore(&tp->mii_lock, flags); -} - - -/* Set up the transceiver control registers for the selected media type. */ -void tulip_select_media(struct net_device *dev, int startup) -{ - long ioaddr = dev->base_addr; - struct tulip_private *tp = (struct tulip_private *)dev->priv; - struct mediatable *mtable = tp->mtable; - u32 new_csr6; - int i; - - if (mtable) { - struct medialeaf *mleaf = &mtable->mleaf[tp->cur_index]; - unsigned char *p = mleaf->leafdata; - switch (mleaf->type) { - case 0: /* 21140 non-MII xcvr. */ - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Using a 21140 non-MII transceiver" - " with control setting %2.2x.\n", - dev->name, p[1]); - dev->if_port = p[0]; - if (startup) - outl(mtable->csr12dir | 0x100, ioaddr + CSR12); - outl(p[1], ioaddr + CSR12); - new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18); - break; - case 2: case 4: { - u16 setup[5]; - u32 csr13val, csr14val, csr15dir, csr15val; - for (i = 0; i < 5; i++) - setup[i] = get_u16(&p[i*2 + 1]); - - dev->if_port = p[0] & MEDIA_MASK; - if (tulip_media_cap[dev->if_port] & MediaAlwaysFD) - tp->full_duplex = 1; - - if (startup && mtable->has_reset) { - struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset]; - unsigned char *rst = rleaf->leafdata; - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Resetting the transceiver.\n", - dev->name); - for (i = 0; i < rst[0]; i++) - outl(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15); - } - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: 21143 non-MII %s transceiver control " - "%4.4x/%4.4x.\n", - dev->name, medianame[dev->if_port], setup[0], setup[1]); - if (p[0] & 0x40) { /* SIA (CSR13-15) setup values are provided. */ - csr13val = setup[0]; - csr14val = setup[1]; - csr15dir = (setup[3]<<16) | setup[2]; - csr15val = (setup[4]<<16) | setup[2]; - outl(0, ioaddr + CSR13); - outl(csr14val, ioaddr + CSR14); - outl(csr15dir, ioaddr + CSR15); /* Direction */ - outl(csr15val, ioaddr + CSR15); /* Data */ - outl(csr13val, ioaddr + CSR13); - } else { - csr13val = 1; - csr14val = 0; - csr15dir = (setup[0]<<16) | 0x0008; - csr15val = (setup[1]<<16) | 0x0008; - if (dev->if_port <= 4) - csr14val = t21142_csr14[dev->if_port]; - if (startup) { - outl(0, ioaddr + CSR13); - outl(csr14val, ioaddr + CSR14); - } - outl(csr15dir, ioaddr + CSR15); /* Direction */ - outl(csr15val, ioaddr + CSR15); /* Data */ - if (startup) outl(csr13val, ioaddr + CSR13); - } - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Setting CSR15 to %8.8x/%8.8x.\n", - dev->name, csr15dir, csr15val); - if (mleaf->type == 4) - new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18); - else - new_csr6 = 0x82420000; - break; - } - case 1: case 3: { - int phy_num = p[0]; - int init_length = p[1]; - u16 *misc_info, tmp_info; - - dev->if_port = 11; - new_csr6 = 0x020E0000; - if (mleaf->type == 3) { /* 21142 */ - u16 *init_sequence = (u16*)(p+2); - u16 *reset_sequence = &((u16*)(p+3))[init_length]; - int reset_length = p[2 + init_length*2]; - misc_info = reset_sequence + reset_length; - if (startup) - for (i = 0; i < reset_length; i++) - outl(get_u16(&reset_sequence[i]) << 16, ioaddr + CSR15); - for (i = 0; i < init_length; i++) - outl(get_u16(&init_sequence[i]) << 16, ioaddr + CSR15); - } else { - u8 *init_sequence = p + 2; - u8 *reset_sequence = p + 3 + init_length; - int reset_length = p[2 + init_length]; - misc_info = (u16*)(reset_sequence + reset_length); - if (startup) { - outl(mtable->csr12dir | 0x100, ioaddr + CSR12); - for (i = 0; i < reset_length; i++) - outl(reset_sequence[i], ioaddr + CSR12); - } - for (i = 0; i < init_length; i++) - outl(init_sequence[i], ioaddr + CSR12); - } - tmp_info = get_u16(&misc_info[1]); - if (tmp_info) - tp->advertising[phy_num] = tmp_info | 1; - if (tmp_info && startup < 2) { - if (tp->mii_advertise == 0) - tp->mii_advertise = tp->advertising[phy_num]; - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Advertising %4.4x on MII %d.\n", - dev->name, tp->mii_advertise, tp->phys[phy_num]); - tulip_mdio_write(dev, tp->phys[phy_num], 4, tp->mii_advertise); - } - break; - } - case 5: case 6: { - u16 setup[5]; - - new_csr6 = 0; /* FIXME */ - - for (i = 0; i < 5; i++) - setup[i] = get_u16(&p[i*2 + 1]); - - if (startup && mtable->has_reset) { - struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset]; - unsigned char *rst = rleaf->leafdata; - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Resetting the transceiver.\n", - dev->name); - for (i = 0; i < rst[0]; i++) - outl(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15); - } - - break; - } - default: - printk(KERN_DEBUG "%s: Invalid media table selection %d.\n", - dev->name, mleaf->type); - new_csr6 = 0x020E0000; - } - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Using media type %s, CSR12 is %2.2x.\n", - dev->name, medianame[dev->if_port], - inl(ioaddr + CSR12) & 0xff); - } else if (tp->chip_id == DC21041) { - int port = dev->if_port <= 4 ? dev->if_port : 0; - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: 21041 using media %s, CSR12 is %4.4x.\n", - dev->name, medianame[port == 3 ? 12: port], - inl(ioaddr + CSR12)); - outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */ - outl(t21041_csr14[port], ioaddr + CSR14); - outl(t21041_csr15[port], ioaddr + CSR15); - outl(t21041_csr13[port], ioaddr + CSR13); - new_csr6 = 0x80020000; - } else if (tp->chip_id == LC82C168) { - if (startup && ! tp->medialock) - dev->if_port = tp->mii_cnt ? 11 : 0; - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: PNIC PHY status is %3.3x, media %s.\n", - dev->name, inl(ioaddr + 0xB8), medianame[dev->if_port]); - if (tp->mii_cnt) { - new_csr6 = 0x810C0000; - outl(0x0001, ioaddr + CSR15); - outl(0x0201B07A, ioaddr + 0xB8); - } else if (startup) { - /* Start with 10mbps to do autonegotiation. */ - outl(0x32, ioaddr + CSR12); - new_csr6 = 0x00420000; - outl(0x0001B078, ioaddr + 0xB8); - outl(0x0201B078, ioaddr + 0xB8); - } else if (dev->if_port == 3 || dev->if_port == 5) { - outl(0x33, ioaddr + CSR12); - new_csr6 = 0x01860000; - /* Trigger autonegotiation. */ - outl(startup ? 0x0201F868 : 0x0001F868, ioaddr + 0xB8); - } else { - outl(0x32, ioaddr + CSR12); - new_csr6 = 0x00420000; - outl(0x1F078, ioaddr + 0xB8); - } - } else if (tp->chip_id == DC21040) { /* 21040 */ - /* Turn on the xcvr interface. */ - int csr12 = inl(ioaddr + CSR12); - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: 21040 media type is %s, CSR12 is %2.2x.\n", - dev->name, medianame[dev->if_port], csr12); - if (tulip_media_cap[dev->if_port] & MediaAlwaysFD) - tp->full_duplex = 1; - new_csr6 = 0x20000; - /* Set the full duplux match frame. */ - outl(FULL_DUPLEX_MAGIC, ioaddr + CSR11); - outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */ - if (t21040_csr13[dev->if_port] & 8) { - outl(0x0705, ioaddr + CSR14); - outl(0x0006, ioaddr + CSR15); - } else { - outl(0xffff, ioaddr + CSR14); - outl(0x0000, ioaddr + CSR15); - } - outl(0x8f01 | t21040_csr13[dev->if_port], ioaddr + CSR13); - } else { /* Unknown chip type with no media table. */ - if (tp->default_port == 0) - dev->if_port = tp->mii_cnt ? 11 : 3; - if (tulip_media_cap[dev->if_port] & MediaIsMII) { - new_csr6 = 0x020E0000; - } else if (tulip_media_cap[dev->if_port] & MediaIsFx) { - new_csr6 = 0x02860000; - } else - new_csr6 = 0x03860000; - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: No media description table, assuming " - "%s transceiver, CSR12 %2.2x.\n", - dev->name, medianame[dev->if_port], - inl(ioaddr + CSR12)); - } - - tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0); - return; -} - -/* - Check the MII negotiated duplex and change the CSR6 setting if - required. - Return 0 if everything is OK. - Return < 0 if the transceiver is missing or has no link beat. - */ -int tulip_check_duplex(struct net_device *dev) -{ - struct tulip_private *tp = dev->priv; - unsigned int bmsr, lpa, negotiated, new_csr6; - - bmsr = tulip_mdio_read(dev, tp->phys[0], MII_BMSR); - lpa = tulip_mdio_read(dev, tp->phys[0], MII_LPA); - if (tulip_debug > 1) - printk(KERN_INFO "%s: MII status %4.4x, Link partner report " - "%4.4x.\n", dev->name, bmsr, lpa); - if (bmsr == 0xffff) - return -2; - if ((bmsr & BMSR_LSTATUS) == 0) { - int new_bmsr = tulip_mdio_read(dev, tp->phys[0], MII_BMSR); - if ((new_bmsr & BMSR_LSTATUS) == 0) { - if (tulip_debug > 1) - printk(KERN_INFO "%s: No link beat on the MII interface," - " status %4.4x.\n", dev->name, new_bmsr); - return -1; - } - } - negotiated = lpa & tp->advertising[0]; - tp->full_duplex = mii_duplex(tp->full_duplex_lock, negotiated); - - new_csr6 = tp->csr6; - - if (negotiated & LPA_100) new_csr6 &= ~TxThreshold; - else new_csr6 |= TxThreshold; - if (tp->full_duplex) new_csr6 |= FullDuplex; - else new_csr6 &= ~FullDuplex; - - if (new_csr6 != tp->csr6) { - tp->csr6 = new_csr6; - tulip_restart_rxtx(tp); - - if (tulip_debug > 0) - printk(KERN_INFO "%s: Setting %s-duplex based on MII" - "#%d link partner capability of %4.4x.\n", - dev->name, tp->full_duplex ? "full" : "half", - tp->phys[0], lpa); - return 1; - } - - return 0; -} - -void __devinit tulip_find_mii (struct net_device *dev, int board_idx) -{ - struct tulip_private *tp = dev->priv; - int phyn, phy_idx = 0; - int mii_reg0; - int mii_advert; - unsigned int to_advert, new_bmcr, ane_switch; - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, - but takes much time. */ - for (phyn = 1; phyn <= 32 && phy_idx < sizeof (tp->phys); phyn++) { - int phy = phyn & 0x1f; - int mii_status = tulip_mdio_read (dev, phy, MII_BMSR); - if ((mii_status & 0x8301) == 0x8001 || - ((mii_status & BMSR_100BASE4) == 0 - && (mii_status & 0x7800) != 0)) { - /* preserve Becker logic, gain indentation level */ - } else { - continue; - } - - mii_reg0 = tulip_mdio_read (dev, phy, MII_BMCR); - mii_advert = tulip_mdio_read (dev, phy, MII_ADVERTISE); - ane_switch = 0; - - /* if not advertising at all, gen an - * advertising value from the capability - * bits in BMSR - */ - if ((mii_advert & ADVERTISE_ALL) == 0) { - unsigned int tmpadv = tulip_mdio_read (dev, phy, MII_BMSR); - mii_advert = ((tmpadv >> 6) & 0x3e0) | 1; - } - - if (tp->mii_advertise) { - tp->advertising[phy_idx] = - to_advert = tp->mii_advertise; - } else if (tp->advertising[phy_idx]) { - to_advert = tp->advertising[phy_idx]; - } else { - tp->advertising[phy_idx] = - tp->mii_advertise = - to_advert = mii_advert; - } - - tp->phys[phy_idx++] = phy; - - printk (KERN_INFO "tulip%d: MII transceiver #%d " - "config %4.4x status %4.4x advertising %4.4x.\n", - board_idx, phy, mii_reg0, mii_status, mii_advert); - - /* Fixup for DLink with miswired PHY. */ - if (mii_advert != to_advert) { - printk (KERN_DEBUG "tulip%d: Advertising %4.4x on PHY %d," - " previously advertising %4.4x.\n", - board_idx, to_advert, phy, mii_advert); - tulip_mdio_write (dev, phy, 4, to_advert); - } - - /* Enable autonegotiation: some boards default to off. */ - if (tp->default_port == 0) { - new_bmcr = mii_reg0 | BMCR_ANENABLE; - if (new_bmcr != mii_reg0) { - new_bmcr |= BMCR_ANRESTART; - ane_switch = 1; - } - } - /* ...or disable nway, if forcing media */ - else { - new_bmcr = mii_reg0 & ~BMCR_ANENABLE; - if (new_bmcr != mii_reg0) - ane_switch = 1; - } - - /* clear out bits we never want at this point */ - new_bmcr &= ~(BMCR_CTST | BMCR_FULLDPLX | BMCR_ISOLATE | - BMCR_PDOWN | BMCR_SPEED100 | BMCR_LOOPBACK | - BMCR_RESET); - - if (tp->full_duplex) - new_bmcr |= BMCR_FULLDPLX; - if (tulip_media_cap[tp->default_port] & MediaIs100) - new_bmcr |= BMCR_SPEED100; - - if (new_bmcr != mii_reg0) { - /* some phys need the ANE switch to - * happen before forced media settings - * will "take." However, we write the - * same value twice in order not to - * confuse the sane phys. - */ - if (ane_switch) { - tulip_mdio_write (dev, phy, MII_BMCR, new_bmcr); - udelay (10); - } - tulip_mdio_write (dev, phy, MII_BMCR, new_bmcr); - } - } - tp->mii_cnt = phy_idx; - if (tp->mtable && tp->mtable->has_mii && phy_idx == 0) { - printk (KERN_INFO "tulip%d: ***WARNING***: No MII transceiver found!\n", - board_idx); - tp->phys[0] = 1; - } -} diff --git a/xen/drivers/net/tulip/pnic.c b/xen/drivers/net/tulip/pnic.c deleted file mode 100644 index 271c223dd0..0000000000 --- a/xen/drivers/net/tulip/pnic.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - drivers/net/tulip/pnic.c - - Maintained by Jeff Garzik - Copyright 2000,2001 The Linux Kernel Team - Written/copyright 1994-2001 by Donald Becker. - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Please refer to Documentation/DocBook/tulip.{pdf,ps,html} - for more information on this driver, or visit the project - Web page at http://sourceforge.net/projects/tulip/ - -*/ - -#include -#include "tulip.h" - - -void pnic_do_nway(struct net_device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - u32 phy_reg = inl(ioaddr + 0xB8); - u32 new_csr6 = tp->csr6 & ~0x40C40200; - - if (phy_reg & 0x78000000) { /* Ignore baseT4 */ - if (phy_reg & 0x20000000) dev->if_port = 5; - else if (phy_reg & 0x40000000) dev->if_port = 3; - else if (phy_reg & 0x10000000) dev->if_port = 4; - else if (phy_reg & 0x08000000) dev->if_port = 0; - tp->nwayset = 1; - new_csr6 = (dev->if_port & 1) ? 0x01860000 : 0x00420000; - outl(0x32 | (dev->if_port & 1), ioaddr + CSR12); - if (dev->if_port & 1) - outl(0x1F868, ioaddr + 0xB8); - if (phy_reg & 0x30000000) { - tp->full_duplex = 1; - new_csr6 |= 0x00000200; - } - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: PNIC autonegotiated status %8.8x, %s.\n", - dev->name, phy_reg, medianame[dev->if_port]); - if (tp->csr6 != new_csr6) { - tp->csr6 = new_csr6; - /* Restart Tx */ - tulip_restart_rxtx(tp); - dev->trans_start = jiffies; - } - } -} - -void pnic_lnk_change(struct net_device *dev, int csr5) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - int phy_reg = inl(ioaddr + 0xB8); - - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: PNIC link changed state %8.8x, CSR5 %8.8x.\n", - dev->name, phy_reg, csr5); - if (inl(ioaddr + CSR5) & TPLnkFail) { - outl((inl(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7); - /* If we use an external MII, then we mustn't use the - * internal negotiation. - */ - if (tulip_media_cap[dev->if_port] & MediaIsMII) - return; - if (! tp->nwayset || jiffies - dev->trans_start > 1*HZ) { - tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff); - outl(tp->csr6, ioaddr + CSR6); - outl(0x30, ioaddr + CSR12); - outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */ - dev->trans_start = jiffies; - } - } else if (inl(ioaddr + CSR5) & TPLnkPass) { - if (tulip_media_cap[dev->if_port] & MediaIsMII) { - spin_lock(&tp->lock); - tulip_check_duplex(dev); - spin_unlock(&tp->lock); - } else { - pnic_do_nway(dev); - } - outl((inl(ioaddr + CSR7) & ~TPLnkPass) | TPLnkFail, ioaddr + CSR7); - } -} - -void pnic_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - int next_tick = 60*HZ; - - if(!inl(ioaddr + CSR7)) { - /* the timer was called due to a work overflow - * in the interrupt handler. Skip the connection - * checks, the nic is definitively speaking with - * his link partner. - */ - goto too_good_connection; - } - - if (tulip_media_cap[dev->if_port] & MediaIsMII) { - spin_lock_irq(&tp->lock); - if (tulip_check_duplex(dev) > 0) - next_tick = 3*HZ; - spin_unlock_irq(&tp->lock); - } else { - int csr12 = inl(ioaddr + CSR12); - int new_csr6 = tp->csr6 & ~0x40C40200; - int phy_reg = inl(ioaddr + 0xB8); - int csr5 = inl(ioaddr + CSR5); - - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: PNIC timer PHY status %8.8x, %s " - "CSR5 %8.8x.\n", - dev->name, phy_reg, medianame[dev->if_port], csr5); - if (phy_reg & 0x04000000) { /* Remote link fault */ - outl(0x0201F078, ioaddr + 0xB8); - next_tick = 1*HZ; - tp->nwayset = 0; - } else if (phy_reg & 0x78000000) { /* Ignore baseT4 */ - pnic_do_nway(dev); - next_tick = 60*HZ; - } else if (csr5 & TPLnkFail) { /* 100baseTx link beat */ - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: %s link beat failed, CSR12 %4.4x, " - "CSR5 %8.8x, PHY %3.3x.\n", - dev->name, medianame[dev->if_port], csr12, - inl(ioaddr + CSR5), inl(ioaddr + 0xB8)); - next_tick = 3*HZ; - if (tp->medialock) { - } else if (tp->nwayset && (dev->if_port & 1)) { - next_tick = 1*HZ; - } else if (dev->if_port == 0) { - dev->if_port = 3; - outl(0x33, ioaddr + CSR12); - new_csr6 = 0x01860000; - outl(0x1F868, ioaddr + 0xB8); - } else { - dev->if_port = 0; - outl(0x32, ioaddr + CSR12); - new_csr6 = 0x00420000; - outl(0x1F078, ioaddr + 0xB8); - } - if (tp->csr6 != new_csr6) { - tp->csr6 = new_csr6; - /* Restart Tx */ - tulip_restart_rxtx(tp); - dev->trans_start = jiffies; - if (tulip_debug > 1) - printk(KERN_INFO "%s: Changing PNIC configuration to %s " - "%s-duplex, CSR6 %8.8x.\n", - dev->name, medianame[dev->if_port], - tp->full_duplex ? "full" : "half", new_csr6); - } - } - } -too_good_connection: - mod_timer(&tp->timer, RUN_AT(next_tick)); - if(!inl(ioaddr + CSR7)) { - if (tulip_debug > 1) - printk(KERN_INFO "%s: sw timer wakeup.\n", dev->name); - disable_irq(dev->irq); - tulip_refill_rx(dev); - enable_irq(dev->irq); - outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); - } -} diff --git a/xen/drivers/net/tulip/pnic2.c b/xen/drivers/net/tulip/pnic2.c deleted file mode 100644 index 140c919caa..0000000000 --- a/xen/drivers/net/tulip/pnic2.c +++ /dev/null @@ -1,407 +0,0 @@ -/* - drivers/net/tulip/pnic2.c - - Maintained by Jeff Garzik - Copyright 2000,2001 The Linux Kernel Team - Written/copyright 1994-2001 by Donald Becker. - Modified to hep support PNIC_II by Kevin B. Hendricks - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Please refer to Documentation/DocBook/tulip.{pdf,ps,html} - for more information on this driver, or visit the project - Web page at http://sourceforge.net/projects/tulip/ - -*/ - - -/* Understanding the PNIC_II - everything is this file is based - * on the PNIC_II_PDF datasheet which is sorely lacking in detail - * - * As I understand things, here are the registers and bits that - * explain the masks and constants used in this file that are - * either different from the 21142/3 or important for basic operation. - * - * - * CSR 6 (mask = 0xfe3bd1fd of bits not to change) - * ----- - * Bit 24 - SCR - * Bit 23 - PCS - * Bit 22 - TTM (Trasmit Threshold Mode) - * Bit 18 - Port Select - * Bit 13 - Start - 1, Stop - 0 Transmissions - * Bit 11:10 - Loop Back Operation Mode - * Bit 9 - Full Duplex mode (Advertise 10BaseT-FD is CSR14<7> is set) - * Bit 1 - Start - 1, Stop - 0 Receive - * - * - * CSR 14 (mask = 0xfff0ee39 of bits not to change) - * ------ - * Bit 19 - PAUSE-Pause - * Bit 18 - Advertise T4 - * Bit 17 - Advertise 100baseTx-FD - * Bit 16 - Advertise 100baseTx-HD - * Bit 12 - LTE - Link Test Enable - * Bit 7 - ANE - Auto Negotiate Enable - * Bit 6 - HDE - Advertise 10baseT-HD - * Bit 2 - Reset to Power down - kept as 1 for normal operation - * Bit 1 - Loop Back enable for 10baseT MCC - * - * - * CSR 12 - * ------ - * Bit 25 - Partner can do T4 - * Bit 24 - Partner can do 100baseTx-FD - * Bit 23 - Partner can do 100baseTx-HD - * Bit 22 - Partner can do 10baseT-FD - * Bit 21 - Partner can do 10baseT-HD - * Bit 15 - LPN is 1 if all above bits are valid other wise 0 - * Bit 14:12 - autonegotiation state (write 001 to start autonegotiate) - * Bit 3 - Autopolarity state - * Bit 2 - LS10B - link state of 10baseT 0 - good, 1 - failed - * Bit 1 - LS100B - link state of 100baseT 0 - good, 1- faild - * - * - * Data Port Selection Info - *------------------------- - * - * CSR14<7> CSR6<18> CSR6<22> CSR6<23> CSR6<24> MODE/PORT - * 1 0 0 (X) 0 (X) 1 NWAY - * 0 0 1 0 (X) 0 10baseT - * 0 1 0 1 1 (X) 100baseT - * - * - */ - - - -#include "tulip.h" -#include -#include - - -void pnic2_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - int next_tick = 60*HZ; - - if (tulip_debug > 3) - printk(KERN_INFO"%s: PNIC2 negotiation status %8.8x.\n", - dev->name,inl(ioaddr + CSR12)); - - if (next_tick) { - mod_timer(&tp->timer, RUN_AT(next_tick)); - } -} - - -void pnic2_start_nway(struct net_device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - int csr14; - int csr12; - - /* set up what to advertise during the negotiation */ - - /* load in csr14 and mask off bits not to touch - * comment at top of file explains mask value - */ - csr14 = (inl(ioaddr + CSR14) & 0xfff0ee39); - - /* bit 17 - advetise 100baseTx-FD */ - if (tp->sym_advertise & 0x0100) csr14 |= 0x00020000; - - /* bit 16 - advertise 100baseTx-HD */ - if (tp->sym_advertise & 0x0080) csr14 |= 0x00010000; - - /* bit 6 - advertise 10baseT-HD */ - if (tp->sym_advertise & 0x0020) csr14 |= 0x00000040; - - /* Now set bit 12 Link Test Enable, Bit 7 Autonegotiation Enable - * and bit 0 Don't PowerDown 10baseT - */ - csr14 |= 0x00001184; - - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Restarting PNIC2 autonegotiation, " - "csr14=%8.8x.\n", dev->name, csr14); - - /* tell pnic2_lnk_change we are doing an nway negotiation */ - dev->if_port = 0; - tp->nway = tp->mediasense = 1; - tp->nwayset = tp->lpar = 0; - - /* now we have to set up csr6 for NWAY state */ - - tp->csr6 = inl(ioaddr + CSR6); - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: On Entry to Nway, " - "csr6=%8.8x.\n", dev->name, tp->csr6); - - /* mask off any bits not to touch - * comment at top of file explains mask value - */ - tp->csr6 = tp->csr6 & 0xfe3bd1fd; - - /* don't forget that bit 9 is also used for advertising */ - /* advertise 10baseT-FD for the negotiation (bit 9) */ - if (tp->sym_advertise & 0x0040) tp->csr6 |= 0x00000200; - - /* set bit 24 for nway negotiation mode ... - * see Data Port Selection comment at top of file - * and "Stop" - reset both Transmit (bit 13) and Receive (bit 1) - */ - tp->csr6 |= 0x01000000; - outl(csr14, ioaddr + CSR14); - outl(tp->csr6, ioaddr + CSR6); - udelay(100); - - /* all set up so now force the negotiation to begin */ - - /* read in current values and mask off all but the - * Autonegotiation bits 14:12. Writing a 001 to those bits - * should start the autonegotiation - */ - csr12 = (inl(ioaddr + CSR12) & 0xffff8fff); - csr12 |= 0x1000; - outl(csr12, ioaddr + CSR12); -} - - - -void pnic2_lnk_change(struct net_device *dev, int csr5) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - int csr14; - - /* read the staus register to find out what is up */ - int csr12 = inl(ioaddr + CSR12); - - if (tulip_debug > 1) - printk(KERN_INFO"%s: PNIC2 link status interrupt %8.8x, " - " CSR5 %x, %8.8x.\n", dev->name, csr12, - csr5, inl(ioaddr + CSR14)); - - /* If NWay finished and we have a negotiated partner capability. - * check bits 14:12 for bit pattern 101 - all is good - */ - if (tp->nway && !tp->nwayset) { - - /* we did an auto negotiation */ - - if ((csr12 & 0x7000) == 0x5000) { - - /* negotiation ended successfully */ - - /* get the link partners reply and mask out all but - * bits 24-21 which show the partners capabilites - * and match those to what we advertised - * - * then begin to interpret the results of the negotiation. - * Always go in this order : (we are ignoring T4 for now) - * 100baseTx-FD, 100baseTx-HD, 10baseT-FD, 10baseT-HD - */ - - int negotiated = ((csr12 >> 16) & 0x01E0) & tp->sym_advertise; - tp->lpar = (csr12 >> 16); - tp->nwayset = 1; - - if (negotiated & 0x0100) dev->if_port = 5; - else if (negotiated & 0x0080) dev->if_port = 3; - else if (negotiated & 0x0040) dev->if_port = 4; - else if (negotiated & 0x0020) dev->if_port = 0; - else { - if (tulip_debug > 1) - printk(KERN_INFO "%s: funny autonegotiate result " - "csr12 %8.8x advertising %4.4x\n", - dev->name, csr12, tp->sym_advertise); - tp->nwayset = 0; - /* so check if 100baseTx link state is okay */ - if ((csr12 & 2) == 0 && (tp->sym_advertise & 0x0180)) - dev->if_port = 3; - } - - /* now record the duplex that was negotiated */ - tp->full_duplex = 0; - if ((dev->if_port == 4) || (dev->if_port == 5)) - tp->full_duplex = 1; - - if (tulip_debug > 1) { - if (tp->nwayset) - printk(KERN_INFO "%s: Switching to %s based on link " - "negotiation %4.4x & %4.4x = %4.4x.\n", - dev->name, medianame[dev->if_port], - tp->sym_advertise, tp->lpar, negotiated); - } - - /* remember to turn off bit 7 - autonegotiate - * enable so we can properly end nway mode and - * set duplex (ie. use csr6<9> again) - */ - csr14 = (inl(ioaddr + CSR14) & 0xffffff7f); - outl(csr14,ioaddr + CSR14); - - - /* now set the data port and operating mode - * (see the Data Port Selection comments at - * the top of the file - */ - - /* get current csr6 and mask off bits not to touch */ - /* see comment at top of file */ - - tp->csr6 = (inl(ioaddr + CSR6) & 0xfe3bd1fd); - - /* so if using if_port 3 or 5 then select the 100baseT - * port else select the 10baseT port. - * See the Data Port Selection table at the top - * of the file which was taken from the PNIC_II.PDF - * datasheet - */ - if (dev->if_port & 1) tp->csr6 |= 0x01840000; - else tp->csr6 |= 0x00400000; - - /* now set the full duplex bit appropriately */ - if (tp->full_duplex) tp->csr6 |= 0x00000200; - - outl(1, ioaddr + CSR13); - - if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Setting CSR6 %8.8x/%x CSR12 " - "%8.8x.\n", dev->name, tp->csr6, - inl(ioaddr + CSR6), inl(ioaddr + CSR12)); - - /* now the following actually writes out the - * new csr6 values - */ - tulip_start_rxtx(tp); - - return; - - } else { - printk(KERN_INFO "%s: Autonegotiation failed, " - "using %s, link beat status %4.4x.\n", - dev->name, medianame[dev->if_port], csr12); - - /* remember to turn off bit 7 - autonegotiate - * enable so we don't forget - */ - csr14 = (inl(ioaddr + CSR14) & 0xffffff7f); - outl(csr14,ioaddr + CSR14); - - /* what should we do when autonegotiate fails? - * should we try again or default to baseline - * case. I just don't know. - * - * for now default to some baseline case - */ - - dev->if_port = 0; - tp->nway = 0; - tp->nwayset = 1; - - /* set to 10baseTx-HD - see Data Port Selection - * comment given at the top of the file - */ - tp->csr6 = (inl(ioaddr + CSR6) & 0xfe3bd1fd); - tp->csr6 |= 0x00400000; - - tulip_restart_rxtx(tp); - - return; - - } - } - - if ((tp->nwayset && (csr5 & 0x08000000) - && (dev->if_port == 3 || dev->if_port == 5) - && (csr12 & 2) == 2) || (tp->nway && (csr5 & (TPLnkFail)))) { - - /* Link blew? Maybe restart NWay. */ - - if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Ugh! Link blew?\n", dev->name); - - del_timer_sync(&tp->timer); - pnic2_start_nway(dev); - tp->timer.expires = RUN_AT(3*HZ); - add_timer(&tp->timer); - - return; - } - - - if (dev->if_port == 3 || dev->if_port == 5) { - - /* we are at 100mb and a potential link change occurred */ - - if (tulip_debug > 1) - printk(KERN_INFO"%s: PNIC2 %s link beat %s.\n", - dev->name, medianame[dev->if_port], - (csr12 & 2) ? "failed" : "good"); - - /* check 100 link beat */ - - tp->nway = 0; - tp->nwayset = 1; - - /* if failed then try doing an nway to get in sync */ - if ((csr12 & 2) && ! tp->medialock) { - del_timer_sync(&tp->timer); - pnic2_start_nway(dev); - tp->timer.expires = RUN_AT(3*HZ); - add_timer(&tp->timer); - } - - return; - } - - if (dev->if_port == 0 || dev->if_port == 4) { - - /* we are at 10mb and a potential link change occurred */ - - if (tulip_debug > 1) - printk(KERN_INFO"%s: PNIC2 %s link beat %s.\n", - dev->name, medianame[dev->if_port], - (csr12 & 4) ? "failed" : "good"); - - - tp->nway = 0; - tp->nwayset = 1; - - /* if failed, try doing an nway to get in sync */ - if ((csr12 & 4) && ! tp->medialock) { - del_timer_sync(&tp->timer); - pnic2_start_nway(dev); - tp->timer.expires = RUN_AT(3*HZ); - add_timer(&tp->timer); - } - - return; - } - - - if (tulip_debug > 1) - printk(KERN_INFO"%s: PNIC2 Link Change Default?\n",dev->name); - - /* if all else fails default to trying 10baseT-HD */ - dev->if_port = 0; - - /* make sure autonegotiate enable is off */ - csr14 = (inl(ioaddr + CSR14) & 0xffffff7f); - outl(csr14,ioaddr + CSR14); - - /* set to 10baseTx-HD - see Data Port Selection - * comment given at the top of the file - */ - tp->csr6 = (inl(ioaddr + CSR6) & 0xfe3bd1fd); - tp->csr6 |= 0x00400000; - - tulip_restart_rxtx(tp); -} - diff --git a/xen/drivers/net/tulip/timer.c b/xen/drivers/net/tulip/timer.c deleted file mode 100644 index 4f6fabeaa7..0000000000 --- a/xen/drivers/net/tulip/timer.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - drivers/net/tulip/timer.c - - Maintained by Jeff Garzik - Copyright 2000,2001 The Linux Kernel Team - Written/copyright 1994-2001 by Donald Becker. - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Please refer to Documentation/DocBook/tulip.{pdf,ps,html} - for more information on this driver, or visit the project - Web page at http://sourceforge.net/projects/tulip/ - -*/ - -#include "tulip.h" - - -void tulip_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - u32 csr12 = inl(ioaddr + CSR12); - int next_tick = 2*HZ; - - if (tulip_debug > 2) { - printk(KERN_DEBUG "%s: Media selection tick, %s, status %8.8x mode" - " %8.8x SIA %8.8x %8.8x %8.8x %8.8x.\n", - dev->name, medianame[dev->if_port], inl(ioaddr + CSR5), - inl(ioaddr + CSR6), csr12, inl(ioaddr + CSR13), - inl(ioaddr + CSR14), inl(ioaddr + CSR15)); - } - switch (tp->chip_id) { - case DC21040: - if (!tp->medialock && csr12 & 0x0002) { /* Network error */ - printk(KERN_INFO "%s: No link beat found.\n", - dev->name); - dev->if_port = (dev->if_port == 2 ? 0 : 2); - tulip_select_media(dev, 0); - dev->trans_start = jiffies; - } - break; - case DC21041: - if (tulip_debug > 2) - printk(KERN_DEBUG "%s: 21041 media tick CSR12 %8.8x.\n", - dev->name, csr12); - if (tp->medialock) break; - switch (dev->if_port) { - case 0: case 3: case 4: - if (csr12 & 0x0004) { /*LnkFail */ - /* 10baseT is dead. Check for activity on alternate port. */ - tp->mediasense = 1; - if (csr12 & 0x0200) - dev->if_port = 2; - else - dev->if_port = 1; - printk(KERN_INFO "%s: No 21041 10baseT link beat, Media switched to %s.\n", - dev->name, medianame[dev->if_port]); - outl(0, ioaddr + CSR13); /* Reset */ - outl(t21041_csr14[dev->if_port], ioaddr + CSR14); - outl(t21041_csr15[dev->if_port], ioaddr + CSR15); - outl(t21041_csr13[dev->if_port], ioaddr + CSR13); - next_tick = 10*HZ; /* 2.4 sec. */ - } else - next_tick = 30*HZ; - break; - case 1: /* 10base2 */ - case 2: /* AUI */ - if (csr12 & 0x0100) { - next_tick = (30*HZ); /* 30 sec. */ - tp->mediasense = 0; - } else if ((csr12 & 0x0004) == 0) { - printk(KERN_INFO "%s: 21041 media switched to 10baseT.\n", - dev->name); - dev->if_port = 0; - tulip_select_media(dev, 0); - next_tick = (24*HZ)/10; /* 2.4 sec. */ - } else if (tp->mediasense || (csr12 & 0x0002)) { - dev->if_port = 3 - dev->if_port; /* Swap ports. */ - tulip_select_media(dev, 0); - next_tick = 20*HZ; - } else { - next_tick = 20*HZ; - } - break; - } - break; - case DC21140: - case DC21142: - case MX98713: - case COMPEX9881: - case DM910X: - default: { - struct medialeaf *mleaf; - unsigned char *p; - if (tp->mtable == NULL) { /* No EEPROM info, use generic code. */ - /* Not much that can be done. - Assume this a generic MII or SYM transceiver. */ - next_tick = 60*HZ; - if (tulip_debug > 2) - printk(KERN_DEBUG "%s: network media monitor CSR6 %8.8x " - "CSR12 0x%2.2x.\n", - dev->name, inl(ioaddr + CSR6), csr12 & 0xff); - break; - } - mleaf = &tp->mtable->mleaf[tp->cur_index]; - p = mleaf->leafdata; - switch (mleaf->type) { - case 0: case 4: { - /* Type 0 serial or 4 SYM transceiver. Check the link beat bit. */ - int offset = mleaf->type == 4 ? 5 : 2; - s8 bitnum = p[offset]; - if (p[offset+1] & 0x80) { - if (tulip_debug > 1) - printk(KERN_DEBUG"%s: Transceiver monitor tick " - "CSR12=%#2.2x, no media sense.\n", - dev->name, csr12); - if (mleaf->type == 4) { - if (mleaf->media == 3 && (csr12 & 0x02)) - goto select_next_media; - } - break; - } - if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Transceiver monitor tick: CSR12=%#2.2x" - " bit %d is %d, expecting %d.\n", - dev->name, csr12, (bitnum >> 1) & 7, - (csr12 & (1 << ((bitnum >> 1) & 7))) != 0, - (bitnum >= 0)); - /* Check that the specified bit has the proper value. */ - if ((bitnum < 0) != - ((csr12 & (1 << ((bitnum >> 1) & 7))) != 0)) { - if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Link beat detected for %s.\n", dev->name, - medianame[mleaf->media & MEDIA_MASK]); - if ((p[2] & 0x61) == 0x01) /* Bogus Znyx board. */ - goto actually_mii; - /* netif_carrier_on(dev); */ - break; - } - /* netif_carrier_off(dev); */ - if (tp->medialock) - break; - select_next_media: - if (--tp->cur_index < 0) { - /* We start again, but should instead look for default. */ - tp->cur_index = tp->mtable->leafcount - 1; - } - dev->if_port = tp->mtable->mleaf[tp->cur_index].media; - if (tulip_media_cap[dev->if_port] & MediaIsFD) - goto select_next_media; /* Skip FD entries. */ - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: No link beat on media %s," - " trying transceiver type %s.\n", - dev->name, medianame[mleaf->media & MEDIA_MASK], - medianame[tp->mtable->mleaf[tp->cur_index].media]); - tulip_select_media(dev, 0); - /* Restart the transmit process. */ - tulip_restart_rxtx(tp); - next_tick = (24*HZ)/10; - break; - } - case 1: case 3: /* 21140, 21142 MII */ - actually_mii: - if (tulip_check_duplex(dev) < 0) - { /* netif_carrier_off(dev); */ } - else - { /* netif_carrier_on(dev); */ } - next_tick = 60*HZ; - break; - case 2: /* 21142 serial block has no link beat. */ - default: - break; - } - } - break; - } - /* mod_timer synchronizes us with potential add_timer calls - * from interrupts. - */ - mod_timer(&tp->timer, RUN_AT(next_tick)); -} - - -void mxic_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - int next_tick = 60*HZ; - - if (tulip_debug > 3) { - printk(KERN_INFO"%s: MXIC negotiation status %8.8x.\n", dev->name, - inl(ioaddr + CSR12)); - } - if (next_tick) { - mod_timer(&tp->timer, RUN_AT(next_tick)); - } -} - - -void comet_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - int next_tick = 60*HZ; - - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Comet link status %4.4x partner capability " - "%4.4x.\n", - dev->name, inl(ioaddr + 0xB8), inl(ioaddr + 0xC8)); - /* mod_timer synchronizes us with potential add_timer calls - * from interrupts. - */ - mod_timer(&tp->timer, RUN_AT(next_tick)); -} - diff --git a/xen/drivers/net/tulip/tulip.h b/xen/drivers/net/tulip/tulip.h deleted file mode 100644 index 79a3788532..0000000000 --- a/xen/drivers/net/tulip/tulip.h +++ /dev/null @@ -1,501 +0,0 @@ -/* - drivers/net/tulip/tulip.h - - Copyright 2000,2001 The Linux Kernel Team - Written/copyright 1994-2001 by Donald Becker. - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Please refer to Documentation/DocBook/tulip.{pdf,ps,html} - for more information on this driver, or visit the project - Web page at http://sourceforge.net/projects/tulip/ - -*/ - -#ifndef __NET_TULIP_H__ -#define __NET_TULIP_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - -/* undefine, or define to various debugging levels (>4 == obscene levels) */ -#define TULIP_DEBUG 1 - -/* undefine USE_IO_OPS for MMIO, define for PIO */ -#ifdef CONFIG_TULIP_MMIO -# undef USE_IO_OPS -#else -# define USE_IO_OPS 1 -#endif - - - -struct tulip_chip_table { - char *chip_name; - int io_size; - int valid_intrs; /* CSR7 interrupt enable settings */ - int flags; - void (*media_timer) (unsigned long data); -}; - - -enum tbl_flag { - HAS_MII = 0x0001, - HAS_MEDIA_TABLE = 0x0002, - CSR12_IN_SROM = 0x0004, - ALWAYS_CHECK_MII = 0x0008, - HAS_ACPI = 0x0010, - MC_HASH_ONLY = 0x0020, /* Hash-only multicast filter. */ - HAS_PNICNWAY = 0x0080, - HAS_NWAY = 0x0040, /* Uses internal NWay xcvr. */ - HAS_INTR_MITIGATION = 0x0100, - IS_ASIX = 0x0200, - HAS_8023X = 0x0400, - COMET_MAC_ADDR = 0x0800, - HAS_PCI_MWI = 0x1000, - HAS_PHY_IRQ = 0x2000, -}; - - -/* chip types. careful! order is VERY IMPORTANT here, as these - * are used throughout the driver as indices into arrays */ -/* Note 21142 == 21143. */ -enum chips { - DC21040 = 0, - DC21041 = 1, - DC21140 = 2, - DC21142 = 3, DC21143 = 3, - LC82C168, - MX98713, - MX98715, - MX98725, - AX88140, - PNIC2, - COMET, - COMPEX9881, - I21145, - DM910X, - CONEXANT, -}; - - -enum MediaIs { - MediaIsFD = 1, - MediaAlwaysFD = 2, - MediaIsMII = 4, - MediaIsFx = 8, - MediaIs100 = 16 -}; - - -/* Offsets to the Command and Status Registers, "CSRs". All accesses - must be longword instructions and quadword aligned. */ -enum tulip_offsets { - CSR0 = 0, - CSR1 = 0x08, - CSR2 = 0x10, - CSR3 = 0x18, - CSR4 = 0x20, - CSR5 = 0x28, - CSR6 = 0x30, - CSR7 = 0x38, - CSR8 = 0x40, - CSR9 = 0x48, - CSR10 = 0x50, - CSR11 = 0x58, - CSR12 = 0x60, - CSR13 = 0x68, - CSR14 = 0x70, - CSR15 = 0x78, -}; - -/* register offset and bits for CFDD PCI config reg */ -enum pci_cfg_driver_reg { - CFDD = 0x40, - CFDD_Sleep = (1 << 31), - CFDD_Snooze = (1 << 30), -}; - - -/* The bits in the CSR5 status registers, mostly interrupt sources. */ -enum status_bits { - TimerInt = 0x800, - SytemError = 0x2000, - TPLnkFail = 0x1000, - TPLnkPass = 0x10, - NormalIntr = 0x10000, - AbnormalIntr = 0x8000, - RxJabber = 0x200, - RxDied = 0x100, - RxNoBuf = 0x80, - RxIntr = 0x40, - TxFIFOUnderflow = 0x20, - TxJabber = 0x08, - TxNoBuf = 0x04, - TxDied = 0x02, - TxIntr = 0x01, -}; - - -enum tulip_mode_bits { - TxThreshold = (1 << 22), - FullDuplex = (1 << 9), - TxOn = 0x2000, - AcceptBroadcast = 0x0100, - AcceptAllMulticast = 0x0080, - AcceptAllPhys = 0x0040, - AcceptRunt = 0x0008, - RxOn = 0x0002, - RxTx = (TxOn | RxOn), -}; - - -enum tulip_busconfig_bits { - MWI = (1 << 24), - MRL = (1 << 23), - MRM = (1 << 21), - CALShift = 14, - BurstLenShift = 8, -}; - - -/* The Tulip Rx and Tx buffer descriptors. */ -struct tulip_rx_desc { - s32 status; - s32 length; - u32 buffer1; - u32 buffer2; -}; - - -struct tulip_tx_desc { - s32 status; - s32 length; - u32 buffer1; - u32 buffer2; /* We use only buffer 1. */ -}; - - -enum desc_status_bits { - DescOwned = 0x80000000, - RxDescFatalErr = 0x8000, - RxWholePkt = 0x0300, -}; - - -enum t21041_csr13_bits { - csr13_eng = (0xEF0<<4), /* for eng. purposes only, hardcode at EF0h */ - csr13_aui = (1<<3), /* clear to force 10bT, set to force AUI/BNC */ - csr13_cac = (1<<2), /* CSR13/14/15 autoconfiguration */ - csr13_srl = (1<<0), /* When reset, resets all SIA functions, machines */ - - csr13_mask_auibnc = (csr13_eng | csr13_aui | csr13_srl), - csr13_mask_10bt = (csr13_eng | csr13_srl), -}; - -enum t21143_csr6_bits { - csr6_sc = (1<<31), - csr6_ra = (1<<30), - csr6_ign_dest_msb = (1<<26), - csr6_mbo = (1<<25), - csr6_scr = (1<<24), /* scramble mode flag: can't be set */ - csr6_pcs = (1<<23), /* Enables PCS functions (symbol mode requires csr6_ps be set) default is set */ - csr6_ttm = (1<<22), /* Transmit Threshold Mode, set for 10baseT, 0 for 100BaseTX */ - csr6_sf = (1<<21), /* Store and forward. If set ignores TR bits */ - csr6_hbd = (1<<19), /* Heart beat disable. Disables SQE function in 10baseT */ - csr6_ps = (1<<18), /* Port Select. 0 (defualt) = 10baseT, 1 = 100baseTX: can't be set */ - csr6_ca = (1<<17), /* Collision Offset Enable. If set uses special algorithm in low collision situations */ - csr6_trh = (1<<15), /* Transmit Threshold high bit */ - csr6_trl = (1<<14), /* Transmit Threshold low bit */ - - /*************************************************************** - * This table shows transmit threshold values based on media * - * and these two registers (from PNIC1 & 2 docs) Note: this is * - * all meaningless if sf is set. * - ***************************************************************/ - - /*********************************** - * (trh,trl) * 100BaseTX * 10BaseT * - *********************************** - * (0,0) * 128 * 72 * - * (0,1) * 256 * 96 * - * (1,0) * 512 * 128 * - * (1,1) * 1024 * 160 * - ***********************************/ - - csr6_fc = (1<<12), /* Forces a collision in next transmission (for testing in loopback mode) */ - csr6_om_int_loop = (1<<10), /* internal (FIFO) loopback flag */ - csr6_om_ext_loop = (1<<11), /* external (PMD) loopback flag */ - /* set both and you get (PHY) loopback */ - csr6_fd = (1<<9), /* Full duplex mode, disables hearbeat, no loopback */ - csr6_pm = (1<<7), /* Pass All Multicast */ - csr6_pr = (1<<6), /* Promiscuous mode */ - csr6_sb = (1<<5), /* Start(1)/Stop(0) backoff counter */ - csr6_if = (1<<4), /* Inverse Filtering, rejects only addresses in address table: can't be set */ - csr6_pb = (1<<3), /* Pass Bad Frames, (1) causes even bad frames to be passed on */ - csr6_ho = (1<<2), /* Hash-only filtering mode: can't be set */ - csr6_hp = (1<<0), /* Hash/Perfect Receive Filtering Mode: can't be set */ - - csr6_mask_capture = (csr6_sc | csr6_ca), - csr6_mask_defstate = (csr6_mask_capture | csr6_mbo), - csr6_mask_hdcap = (csr6_mask_defstate | csr6_hbd | csr6_ps), - csr6_mask_hdcaptt = (csr6_mask_hdcap | csr6_trh | csr6_trl), - csr6_mask_fullcap = (csr6_mask_hdcaptt | csr6_fd), - csr6_mask_fullpromisc = (csr6_pr | csr6_pm), - csr6_mask_filters = (csr6_hp | csr6_ho | csr6_if), - csr6_mask_100bt = (csr6_scr | csr6_pcs | csr6_hbd), -}; - - -/* Keep the ring sizes a power of two for efficiency. - Making the Tx ring too large decreases the effectiveness of channel - bonding and packet priority. - There are no ill effects from too-large receive rings. */ -#undef TX_RING_SIZE -#undef RX_RING_SIZE -#define TX_RING_SIZE 16 -#define RX_RING_SIZE 32 - -#define MEDIA_MASK 31 - -#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */ - -#define TULIP_MIN_CACHE_LINE 8 /* in units of 32-bit words */ - -#if defined(__sparc__) || defined(__hppa__) -/* The UltraSparc PCI controllers will disconnect at every 64-byte - * crossing anyways so it makes no sense to tell Tulip to burst - * any more than that. - */ -#define TULIP_MAX_CACHE_LINE 16 /* in units of 32-bit words */ -#else -#define TULIP_MAX_CACHE_LINE 32 /* in units of 32-bit words */ -#endif - - -/* Ring-wrap flag in length field, use for last ring entry. - 0x01000000 means chain on buffer2 address, - 0x02000000 means use the ring start address in CSR2/3. - Note: Some work-alike chips do not function correctly in chained mode. - The ASIX chip works only in chained mode. - Thus we indicates ring mode, but always write the 'next' field for - chained mode as well. -*/ -#define DESC_RING_WRAP 0x02000000 - - -#define EEPROM_SIZE 128 /* 2 << EEPROM_ADDRLEN */ - - -#define RUN_AT(x) (jiffies + (x)) - -#if defined(__i386__) /* AKA get_unaligned() */ -#define get_u16(ptr) (*(u16 *)(ptr)) -#else -#define get_u16(ptr) (((u8*)(ptr))[0] + (((u8*)(ptr))[1]<<8)) -#endif - -struct medialeaf { - u8 type; - u8 media; - unsigned char *leafdata; -}; - - -struct mediatable { - u16 defaultmedia; - u8 leafcount; - u8 csr12dir; /* General purpose pin directions. */ - unsigned has_mii:1; - unsigned has_nonmii:1; - unsigned has_reset:6; - u32 csr15dir; - u32 csr15val; /* 21143 NWay setting. */ - struct medialeaf mleaf[0]; -}; - - -struct mediainfo { - struct mediainfo *next; - int info_type; - int index; - unsigned char *info; -}; - -struct ring_info { - struct sk_buff *skb; - dma_addr_t mapping; -}; - - -struct tulip_private { - const char *product_name; - struct net_device *next_module; - struct tulip_rx_desc *rx_ring; - struct tulip_tx_desc *tx_ring; - dma_addr_t rx_ring_dma; - dma_addr_t tx_ring_dma; - /* The saved address of a sent-in-place packet/buffer, for skfree(). */ - struct ring_info tx_buffers[TX_RING_SIZE]; - /* The addresses of receive-in-place skbuffs. */ - struct ring_info rx_buffers[RX_RING_SIZE]; - u16 setup_frame[96]; /* Pseudo-Tx frame to init address table. */ - int chip_id; - int revision; - int flags; - struct net_device_stats stats; - struct timer_list timer; /* Media selection timer. */ - u32 mc_filter[2]; - spinlock_t lock; - spinlock_t mii_lock; - unsigned int cur_rx, cur_tx; /* The next free ring entry */ - unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ - -#ifdef CONFIG_NET_HW_FLOWCONTROL -#define RX_A_NBF_STOP 0xffffff3f /* To disable RX and RX-NOBUF ints. */ - int fc_bit; - int mit_sel; - int mit_change; /* Signal for Interrupt Mitigtion */ -#endif - unsigned int full_duplex:1; /* Full-duplex operation requested. */ - unsigned int full_duplex_lock:1; - unsigned int fake_addr:1; /* Multiport board faked address. */ - unsigned int default_port:4; /* Last dev->if_port value. */ - unsigned int media2:4; /* Secondary monitored media port. */ - unsigned int medialock:1; /* Don't sense media type. */ - unsigned int mediasense:1; /* Media sensing in progress. */ - unsigned int nway:1, nwayset:1; /* 21143 internal NWay. */ - unsigned int csr0; /* CSR0 setting. */ - unsigned int csr6; /* Current CSR6 control settings. */ - unsigned char eeprom[EEPROM_SIZE]; /* Serial EEPROM contents. */ - void (*link_change) (struct net_device * dev, int csr5); - u16 sym_advertise, mii_advertise; /* NWay capabilities advertised. */ - u16 lpar; /* 21143 Link partner ability. */ - u16 advertising[4]; - signed char phys[4], mii_cnt; /* MII device addresses. */ - struct mediatable *mtable; - int cur_index; /* Current media index. */ - int saved_if_port; - struct pci_dev *pdev; - int ttimer; - int susp_rx; - unsigned long nir; - unsigned long base_addr; - int csr12_shadow; - int pad0; /* Used for 8-byte alignment */ -}; - - -struct eeprom_fixup { - char *name; - unsigned char addr0; - unsigned char addr1; - unsigned char addr2; - u16 newtable[32]; /* Max length below. */ -}; - - -/* 21142.c */ -extern u16 t21142_csr14[]; -void t21142_timer(unsigned long data); -void t21142_start_nway(struct net_device *dev); -void t21142_lnk_change(struct net_device *dev, int csr5); - - -/* PNIC2.c */ -void pnic2_lnk_change(struct net_device *dev, int csr5); -void pnic2_timer(unsigned long data); -void pnic2_start_nway(struct net_device *dev); - -/* eeprom.c */ -void tulip_parse_eeprom(struct net_device *dev); -int tulip_read_eeprom(long ioaddr, int location, int addr_len); - -/* interrupt.c */ -extern unsigned int tulip_max_interrupt_work; -extern int tulip_rx_copybreak; -void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -int tulip_refill_rx(struct net_device *dev); - -/* media.c */ -int tulip_mdio_read(struct net_device *dev, int phy_id, int location); -void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int value); -void tulip_select_media(struct net_device *dev, int startup); -int tulip_check_duplex(struct net_device *dev); -void tulip_find_mii (struct net_device *dev, int board_idx); - -/* pnic.c */ -void pnic_do_nway(struct net_device *dev); -void pnic_lnk_change(struct net_device *dev, int csr5); -void pnic_timer(unsigned long data); - -/* timer.c */ -void tulip_timer(unsigned long data); -void mxic_timer(unsigned long data); -void comet_timer(unsigned long data); - -/* tulip_core.c */ -extern int tulip_debug; -extern const char * const medianame[]; -extern const char tulip_media_cap[]; -extern struct tulip_chip_table tulip_tbl[]; -extern u8 t21040_csr13[]; -extern u16 t21041_csr13[]; -extern u16 t21041_csr14[]; -extern u16 t21041_csr15[]; - -#ifndef USE_IO_OPS -#undef inb -#undef inw -#undef inl -#undef outb -#undef outw -#undef outl -#define inb(addr) readb((void*)(addr)) -#define inw(addr) readw((void*)(addr)) -#define inl(addr) readl((void*)(addr)) -#define outb(val,addr) writeb((val), (void*)(addr)) -#define outw(val,addr) writew((val), (void*)(addr)) -#define outl(val,addr) writel((val), (void*)(addr)) -#endif /* !USE_IO_OPS */ - - - -static inline void tulip_start_rxtx(struct tulip_private *tp) -{ - long ioaddr = tp->base_addr; - outl(tp->csr6 | RxTx, ioaddr + CSR6); - barrier(); - (void) inl(ioaddr + CSR6); /* mmio sync */ -} - -static inline void tulip_stop_rxtx(struct tulip_private *tp) -{ - long ioaddr = tp->base_addr; - u32 csr6 = inl(ioaddr + CSR6); - - if (csr6 & RxTx) { - outl(csr6 & ~RxTx, ioaddr + CSR6); - barrier(); - (void) inl(ioaddr + CSR6); /* mmio sync */ - } -} - -static inline void tulip_restart_rxtx(struct tulip_private *tp) -{ - tulip_stop_rxtx(tp); - udelay(5); - tulip_start_rxtx(tp); -} - -#endif /* __NET_TULIP_H__ */ diff --git a/xen/drivers/net/tulip/tulip_core.c b/xen/drivers/net/tulip/tulip_core.c deleted file mode 100644 index 0c46cf191b..0000000000 --- a/xen/drivers/net/tulip/tulip_core.c +++ /dev/null @@ -1,1938 +0,0 @@ -/* tulip_core.c: A DEC 21x4x-family ethernet driver for Linux. */ - -/* - Maintained by Jeff Garzik - Copyright 2000-2002 The Linux Kernel Team - Written/copyright 1994-2001 by Donald Becker. - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Please refer to Documentation/DocBook/tulip.{pdf,ps,html} - for more information on this driver, or visit the project - Web page at http://sourceforge.net/projects/tulip/ - -*/ - -#define DRV_NAME "tulip" -#define DRV_VERSION "0.9.15-pre12" -#define DRV_RELDATE "Aug 9, 2002" - -#include -#include -#include "tulip.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __sparc__ -#include -#endif - -static char version[] __devinitdata = - "Linux Tulip driver version " DRV_VERSION " (" DRV_RELDATE ")\n"; - - -/* A few user-configurable values. */ - -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static unsigned int max_interrupt_work = 25; - -#define MAX_UNITS 8 -/* Used to pass the full-duplex flag, etc. */ -static int full_duplex[MAX_UNITS]; -static int options[MAX_UNITS]; -static int mtu[MAX_UNITS]; /* Jumbo MTU for interfaces. */ - -/* The possible media types that can be set in options[] are: */ -const char * const medianame[32] = { - "10baseT", "10base2", "AUI", "100baseTx", - "10baseT-FDX", "100baseTx-FDX", "100baseT4", "100baseFx", - "100baseFx-FDX", "MII 10baseT", "MII 10baseT-FDX", "MII", - "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FDX", "MII 100baseT4", - "MII 100baseFx-HDX", "MII 100baseFx-FDX", "Home-PNA 1Mbps", "Invalid-19", - "","","","", "","","","", "","","","Transceiver reset", -}; - -/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */ -#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \ - || defined(__sparc_) || defined(__ia64__) \ - || defined(__sh__) || defined(__mips__) -static int rx_copybreak = 1518; -#else -static int rx_copybreak = 100; -#endif - -/* - Set the bus performance register. - Typical: Set 16 longword cache alignment, no burst limit. - Cache alignment bits 15:14 Burst length 13:8 - 0000 No alignment 0x00000000 unlimited 0800 8 longwords - 4000 8 longwords 0100 1 longword 1000 16 longwords - 8000 16 longwords 0200 2 longwords 2000 32 longwords - C000 32 longwords 0400 4 longwords - Warning: many older 486 systems are broken and require setting 0x00A04800 - 8 longword cache alignment, 8 longword burst. - ToDo: Non-Intel setting could be better. -*/ - -#if defined(__alpha__) || defined(__ia64__) || defined(__x86_64__) -static int csr0 = 0x01A00000 | 0xE000; -#elif defined(__i386__) || defined(__powerpc__) -static int csr0 = 0x01A00000 | 0x8000; -#elif defined(__sparc__) || defined(__hppa__) -/* The UltraSparc PCI controllers will disconnect at every 64-byte - * crossing anyways so it makes no sense to tell Tulip to burst - * any more than that. - */ -static int csr0 = 0x01A00000 | 0x9000; -#elif defined(__arm__) || defined(__sh__) -static int csr0 = 0x01A00000 | 0x4800; -#elif defined(__mips__) -static int csr0 = 0x00200000 | 0x4000; -#else -#warning Processor architecture undefined! -static int csr0 = 0x00A00000 | 0x4800; -#endif - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (4*HZ) - - -MODULE_AUTHOR("The Linux Kernel Team"); -MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_PARM(tulip_debug, "i"); -MODULE_PARM(max_interrupt_work, "i"); -MODULE_PARM(rx_copybreak, "i"); -MODULE_PARM(csr0, "i"); -MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); - -#define PFX DRV_NAME ": " - -#ifdef TULIP_DEBUG -int tulip_debug = TULIP_DEBUG; -#else -int tulip_debug = 1; -#endif - - - -/* - * This table use during operation for capabilities and media timer. - * - * It is indexed via the values in 'enum chips' - */ - -struct tulip_chip_table tulip_tbl[] = { - /* DC21040 */ - { "Digital DC21040 Tulip", 128, 0x0001ebef, 0, tulip_timer }, - - /* DC21041 */ - { "Digital DC21041 Tulip", 128, 0x0001ebef, - HAS_MEDIA_TABLE | HAS_NWAY, tulip_timer }, - - /* DC21140 */ - { "Digital DS21140 Tulip", 128, 0x0001ebef, - HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_PCI_MWI, tulip_timer }, - - /* DC21142, DC21143 */ - { "Digital DS21143 Tulip", 128, 0x0801fbff, - HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY - | HAS_INTR_MITIGATION | HAS_PCI_MWI, t21142_timer }, - - /* LC82C168 */ - { "Lite-On 82c168 PNIC", 256, 0x0001fbef, - HAS_MII | HAS_PNICNWAY, pnic_timer }, - - /* MX98713 */ - { "Macronix 98713 PMAC", 128, 0x0001ebef, - HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer }, - - /* MX98715 */ - { "Macronix 98715 PMAC", 256, 0x0001ebef, - HAS_MEDIA_TABLE, mxic_timer }, - - /* MX98725 */ - { "Macronix 98725 PMAC", 256, 0x0001ebef, - HAS_MEDIA_TABLE, mxic_timer }, - - /* AX88140 */ - { "ASIX AX88140", 128, 0x0001fbff, - HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY - | IS_ASIX, tulip_timer }, - - /* PNIC2 */ - { "Lite-On PNIC-II", 256, 0x0801fbff, - HAS_MII | HAS_NWAY | HAS_8023X | HAS_PCI_MWI, pnic2_timer }, - - /* COMET */ - { "ADMtek Comet", 256, 0x0001abef, - MC_HASH_ONLY | COMET_MAC_ADDR, comet_timer }, - - /* COMPEX9881 */ - { "Compex 9881 PMAC", 128, 0x0001ebef, - HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer }, - - /* I21145 */ - { "Intel DS21145 Tulip", 128, 0x0801fbff, - HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI - | HAS_NWAY | HAS_PCI_MWI, t21142_timer }, - - /* DM910X */ - { "Davicom DM9102/DM9102A", 128, 0x0001ebef, - HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI, - tulip_timer }, - - /* CONEXANT */ - { "Conexant LANfinity", 256, 0x0001ebef, - HAS_MII, tulip_timer }, -}; - - -static struct pci_device_id tulip_pci_tbl[] __devinitdata = { - { 0x1011, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21040 }, - { 0x1011, 0x0014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21041 }, - { 0x1011, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21140 }, - { 0x1011, 0x0019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21143 }, - { 0x11AD, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, LC82C168 }, - { 0x10d9, 0x0512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98713 }, - { 0x10d9, 0x0531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 }, -/* { 0x10d9, 0x0531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98725 },*/ - { 0x125B, 0x1400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AX88140 }, - { 0x11AD, 0xc115, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PNIC2 }, - { 0x1317, 0x0981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, - { 0x1317, 0x0985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, - { 0x1317, 0x1985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, - { 0x1317, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, - { 0x13D1, 0xAB02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, - { 0x13D1, 0xAB03, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, - { 0x13D1, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, - { 0x104A, 0x0981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, - { 0x104A, 0x2774, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, - { 0x1259, 0xa120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, - { 0x11F6, 0x9881, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMPEX9881 }, - { 0x8086, 0x0039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, I21145 }, - { 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X }, - { 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X }, - { 0x1113, 0x1216, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, - { 0x1113, 0x1217, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 }, - { 0x1113, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, - { 0x1186, 0x1561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, - { 0x1626, 0x8410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, - { 0x1737, 0xAB09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, - { 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, - { 0x14f1, 0x1803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CONEXANT }, - { } /* terminate list */ -}; -MODULE_DEVICE_TABLE(pci, tulip_pci_tbl); - - -/* A full-duplex map for media types. */ -const char tulip_media_cap[32] = -{0,0,0,16, 3,19,16,24, 27,4,7,5, 0,20,23,20, 28,31,0,0, }; -u8 t21040_csr13[] = {2,0x0C,8,4, 4,0,0,0, 0,0,0,0, 4,0,0,0}; - -/* 21041 transceiver register settings: 10-T, 10-2, AUI, 10-T, 10T-FD*/ -u16 t21041_csr13[] = { - csr13_mask_10bt, /* 10-T */ - csr13_mask_auibnc, /* 10-2 */ - csr13_mask_auibnc, /* AUI */ - csr13_mask_10bt, /* 10-T */ - csr13_mask_10bt, /* 10T-FD */ -}; -u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, }; -u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; - - -static void tulip_tx_timeout(struct net_device *dev); -static void tulip_init_ring(struct net_device *dev); -static int tulip_start_xmit(struct sk_buff *skb, struct net_device *dev); -static int tulip_open(struct net_device *dev); -static int tulip_close(struct net_device *dev); -static void tulip_up(struct net_device *dev); -static void tulip_down(struct net_device *dev); -static struct net_device_stats *tulip_get_stats(struct net_device *dev); -static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static void set_rx_mode(struct net_device *dev); - - - -static void tulip_set_power_state (struct tulip_private *tp, - int sleep, int snooze) -{ - if (tp->flags & HAS_ACPI) { - u32 tmp, newtmp; - pci_read_config_dword (tp->pdev, CFDD, &tmp); - newtmp = tmp & ~(CFDD_Sleep | CFDD_Snooze); - if (sleep) - newtmp |= CFDD_Sleep; - else if (snooze) - newtmp |= CFDD_Snooze; - if (tmp != newtmp) - pci_write_config_dword (tp->pdev, CFDD, newtmp); - } - -} - - -static void tulip_up(struct net_device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - int next_tick = 3*HZ; - int i; - - /* Wake the chip from sleep/snooze mode. */ - tulip_set_power_state (tp, 0, 0); - - /* On some chip revs we must set the MII/SYM port before the reset!? */ - if (tp->mii_cnt || (tp->mtable && tp->mtable->has_mii)) - outl(0x00040000, ioaddr + CSR6); - - /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */ - outl(0x00000001, ioaddr + CSR0); - udelay(100); - - /* Deassert reset. - Wait the specified 50 PCI cycles after a reset by initializing - Tx and Rx queues and the address filter list. */ - outl(tp->csr0, ioaddr + CSR0); - udelay(100); - - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: tulip_up(), irq==%d.\n", dev->name, dev->irq); - - outl(tp->rx_ring_dma, ioaddr + CSR3); - outl(tp->tx_ring_dma, ioaddr + CSR4); - tp->cur_rx = tp->cur_tx = 0; - tp->dirty_rx = tp->dirty_tx = 0; - - if (tp->flags & MC_HASH_ONLY) { - u32 addr_low = cpu_to_le32(get_unaligned((u32 *)dev->dev_addr)); - u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(dev->dev_addr+4))); - if (tp->chip_id == AX88140) { - outl(0, ioaddr + CSR13); - outl(addr_low, ioaddr + CSR14); - outl(1, ioaddr + CSR13); - outl(addr_high, ioaddr + CSR14); - } else if (tp->flags & COMET_MAC_ADDR) { - outl(addr_low, ioaddr + 0xA4); - outl(addr_high, ioaddr + 0xA8); - outl(0, ioaddr + 0xAC); - outl(0, ioaddr + 0xB0); - } - } else { - /* This is set_rx_mode(), but without starting the transmitter. */ - u16 *eaddrs = (u16 *)dev->dev_addr; - u16 *setup_frm = &tp->setup_frame[15*6]; - dma_addr_t mapping; - - /* 21140 bug: you must add the broadcast address. */ - memset(tp->setup_frame, 0xff, sizeof(tp->setup_frame)); - /* Fill the final entry of the table with our physical address. */ - *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; - *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; - *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; - - mapping = pci_map_single(tp->pdev, tp->setup_frame, - sizeof(tp->setup_frame), - PCI_DMA_TODEVICE); - tp->tx_buffers[tp->cur_tx].skb = NULL; - tp->tx_buffers[tp->cur_tx].mapping = mapping; - - /* Put the setup frame on the Tx list. */ - tp->tx_ring[tp->cur_tx].length = cpu_to_le32(0x08000000 | 192); - tp->tx_ring[tp->cur_tx].buffer1 = cpu_to_le32(mapping); - tp->tx_ring[tp->cur_tx].status = cpu_to_le32(DescOwned); - - tp->cur_tx++; - } - - tp->saved_if_port = dev->if_port; - if (dev->if_port == 0) - dev->if_port = tp->default_port; - - /* Allow selecting a default media. */ - i = 0; - if (tp->mtable == NULL) - goto media_picked; - if (dev->if_port) { - int looking_for = tulip_media_cap[dev->if_port] & MediaIsMII ? 11 : - (dev->if_port == 12 ? 0 : dev->if_port); - for (i = 0; i < tp->mtable->leafcount; i++) - if (tp->mtable->mleaf[i].media == looking_for) { - printk(KERN_INFO "%s: Using user-specified media %s.\n", - dev->name, medianame[dev->if_port]); - goto media_picked; - } - } - if ((tp->mtable->defaultmedia & 0x0800) == 0) { - int looking_for = tp->mtable->defaultmedia & MEDIA_MASK; - for (i = 0; i < tp->mtable->leafcount; i++) - if (tp->mtable->mleaf[i].media == looking_for) { - printk(KERN_INFO "%s: Using EEPROM-set media %s.\n", - dev->name, medianame[looking_for]); - goto media_picked; - } - } - /* Start sensing first non-full-duplex media. */ - for (i = tp->mtable->leafcount - 1; - (tulip_media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--) - ; -media_picked: - - tp->csr6 = 0; - tp->cur_index = i; - tp->nwayset = 0; - - if (dev->if_port) { - if (tp->chip_id == DC21143 && - (tulip_media_cap[dev->if_port] & MediaIsMII)) { - /* We must reset the media CSRs when we force-select MII mode. */ - outl(0x0000, ioaddr + CSR13); - outl(0x0000, ioaddr + CSR14); - outl(0x0008, ioaddr + CSR15); - } - tulip_select_media(dev, 1); - } else if (tp->chip_id == DC21041) { - dev->if_port = 0; - tp->nway = tp->mediasense = 1; - tp->nwayset = tp->lpar = 0; - outl(0x00000000, ioaddr + CSR13); - outl(0xFFFFFFFF, ioaddr + CSR14); - outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */ - tp->csr6 = 0x80020000; - if (tp->sym_advertise & 0x0040) - tp->csr6 |= FullDuplex; - outl(tp->csr6, ioaddr + CSR6); - outl(0x0000EF01, ioaddr + CSR13); - - } else if (tp->chip_id == DC21142) { - if (tp->mii_cnt) { - tulip_select_media(dev, 1); - if (tulip_debug > 1) - printk(KERN_INFO "%s: Using MII transceiver %d, status " - "%4.4x.\n", - dev->name, tp->phys[0], tulip_mdio_read(dev, tp->phys[0], 1)); - outl(csr6_mask_defstate, ioaddr + CSR6); - tp->csr6 = csr6_mask_hdcap; - dev->if_port = 11; - outl(0x0000, ioaddr + CSR13); - outl(0x0000, ioaddr + CSR14); - } else - t21142_start_nway(dev); - } else if (tp->chip_id == PNIC2) { - /* for initial startup advertise 10/100 Full and Half */ - tp->sym_advertise = 0x01E0; - /* enable autonegotiate end interrupt */ - outl(inl(ioaddr+CSR5)| 0x00008010, ioaddr + CSR5); - outl(inl(ioaddr+CSR7)| 0x00008010, ioaddr + CSR7); - pnic2_start_nway(dev); - } else if (tp->chip_id == LC82C168 && ! tp->medialock) { - if (tp->mii_cnt) { - dev->if_port = 11; - tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0); - outl(0x0001, ioaddr + CSR15); - } else if (inl(ioaddr + CSR5) & TPLnkPass) - pnic_do_nway(dev); - else { - /* Start with 10mbps to do autonegotiation. */ - outl(0x32, ioaddr + CSR12); - tp->csr6 = 0x00420000; - outl(0x0001B078, ioaddr + 0xB8); - outl(0x0201B078, ioaddr + 0xB8); - next_tick = 1*HZ; - } - } else if ((tp->chip_id == MX98713 || tp->chip_id == COMPEX9881) - && ! tp->medialock) { - dev->if_port = 0; - tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0); - outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80); - } else if (tp->chip_id == MX98715 || tp->chip_id == MX98725) { - /* Provided by BOLO, Macronix - 12/10/1998. */ - dev->if_port = 0; - tp->csr6 = 0x01a80200; - outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80); - outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0); - } else if (tp->chip_id == COMET || tp->chip_id == CONEXANT) { - /* Enable automatic Tx underrun recovery. */ - outl(inl(ioaddr + 0x88) | 1, ioaddr + 0x88); - dev->if_port = tp->mii_cnt ? 11 : 0; - tp->csr6 = 0x00040000; - } else if (tp->chip_id == AX88140) { - tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100; - } else - tulip_select_media(dev, 1); - - /* Start the chip's Tx to process setup frame. */ - tulip_stop_rxtx(tp); - barrier(); - udelay(5); - outl(tp->csr6 | TxOn, ioaddr + CSR6); - - /* Enable interrupts by setting the interrupt mask. */ - outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5); - outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); - tulip_start_rxtx(tp); - outl(0, ioaddr + CSR2); /* Rx poll demand */ - - if (tulip_debug > 2) { - printk(KERN_DEBUG "%s: Done tulip_up(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n", - dev->name, inl(ioaddr + CSR0), inl(ioaddr + CSR5), - inl(ioaddr + CSR6)); - } - - /* Set the timer to switch to check for link beat and perhaps switch - to an alternate media type. */ - tp->timer.expires = RUN_AT(next_tick); - add_timer(&tp->timer); -} - -#ifdef CONFIG_NET_HW_FLOWCONTROL -/* Enable receiver */ -void tulip_xon(struct net_device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - - clear_bit(tp->fc_bit, &netdev_fc_xoff); - if (netif_running(dev)){ - - tulip_refill_rx(dev); - outl(tulip_tbl[tp->chip_id].valid_intrs, dev->base_addr+CSR7); - } -} -#endif - -static int -tulip_open(struct net_device *dev) -{ -#ifdef CONFIG_NET_HW_FLOWCONTROL - struct tulip_private *tp = (struct tulip_private *)dev->priv; -#endif - int retval; - MOD_INC_USE_COUNT; - - if ((retval = request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev))) { - MOD_DEC_USE_COUNT; - return retval; - } - - tulip_init_ring (dev); - - tulip_up (dev); - -#ifdef CONFIG_NET_HW_FLOWCONTROL - tp->fc_bit = netdev_register_fc(dev, tulip_xon); -#endif - - netif_start_queue (dev); - - return 0; -} - - -static void tulip_tx_timeout(struct net_device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - unsigned long flags; - - spin_lock_irqsave (&tp->lock, flags); - - if (tulip_media_cap[dev->if_port] & MediaIsMII) { - /* Do nothing -- the media monitor should handle this. */ - if (tulip_debug > 1) - printk(KERN_WARNING "%s: Transmit timeout using MII device.\n", - dev->name); - } else if (tp->chip_id == DC21040) { - if ( !tp->medialock && inl(ioaddr + CSR12) & 0x0002) { - dev->if_port = (dev->if_port == 2 ? 0 : 2); - printk(KERN_INFO "%s: 21040 transmit timed out, switching to " - "%s.\n", - dev->name, medianame[dev->if_port]); - tulip_select_media(dev, 0); - } - goto out; - } else if (tp->chip_id == DC21041) { - int csr12 = inl(ioaddr + CSR12); - - printk(KERN_WARNING "%s: 21041 transmit timed out, status %8.8x, " - "CSR12 %8.8x, CSR13 %8.8x, CSR14 %8.8x, resetting...\n", - dev->name, inl(ioaddr + CSR5), csr12, - inl(ioaddr + CSR13), inl(ioaddr + CSR14)); - tp->mediasense = 1; - if ( ! tp->medialock) { - if (dev->if_port == 1 || dev->if_port == 2) - if (csr12 & 0x0004) { - dev->if_port = 2 - dev->if_port; - } else - dev->if_port = 0; - else - dev->if_port = 1; - tulip_select_media(dev, 0); - } - } else if (tp->chip_id == DC21140 || tp->chip_id == DC21142 - || tp->chip_id == MX98713 || tp->chip_id == COMPEX9881 - || tp->chip_id == DM910X) { - printk(KERN_WARNING "%s: 21140 transmit timed out, status %8.8x, " - "SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n", - dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12), - inl(ioaddr + CSR13), inl(ioaddr + CSR14), inl(ioaddr + CSR15)); - if ( ! tp->medialock && tp->mtable) { - do - --tp->cur_index; - while (tp->cur_index >= 0 - && (tulip_media_cap[tp->mtable->mleaf[tp->cur_index].media] - & MediaIsFD)); - if (--tp->cur_index < 0) { - /* We start again, but should instead look for default. */ - tp->cur_index = tp->mtable->leafcount - 1; - } - tulip_select_media(dev, 0); - printk(KERN_WARNING "%s: transmit timed out, switching to %s " - "media.\n", dev->name, medianame[dev->if_port]); - } - } else if (tp->chip_id == PNIC2) { - printk(KERN_WARNING "%s: PNIC2 transmit timed out, status %8.8x, " - "CSR6/7 %8.8x / %8.8x CSR12 %8.8x, resetting...\n", - dev->name, (int)inl(ioaddr + CSR5), (int)inl(ioaddr + CSR6), - (int)inl(ioaddr + CSR7), (int)inl(ioaddr + CSR12)); - } else { - printk(KERN_WARNING "%s: Transmit timed out, status %8.8x, CSR12 " - "%8.8x, resetting...\n", - dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12)); - dev->if_port = 0; - } - -#if defined(way_too_many_messages) - if (tulip_debug > 3) { - int i; - for (i = 0; i < RX_RING_SIZE; i++) { - u8 *buf = (u8 *)(tp->rx_ring[i].buffer1); - int j; - printk(KERN_DEBUG "%2d: %8.8x %8.8x %8.8x %8.8x " - "%2.2x %2.2x %2.2x.\n", - i, (unsigned int)tp->rx_ring[i].status, - (unsigned int)tp->rx_ring[i].length, - (unsigned int)tp->rx_ring[i].buffer1, - (unsigned int)tp->rx_ring[i].buffer2, - buf[0], buf[1], buf[2]); - for (j = 0; buf[j] != 0xee && j < 1600; j++) - if (j < 100) printk(" %2.2x", buf[j]); - printk(" j=%d.\n", j); - } - printk(KERN_DEBUG " Rx ring %8.8x: ", (int)tp->rx_ring); - for (i = 0; i < RX_RING_SIZE; i++) - printk(" %8.8x", (unsigned int)tp->rx_ring[i].status); - printk("\n" KERN_DEBUG " Tx ring %8.8x: ", (int)tp->tx_ring); - for (i = 0; i < TX_RING_SIZE; i++) - printk(" %8.8x", (unsigned int)tp->tx_ring[i].status); - printk("\n"); - } -#endif - - /* Stop and restart the chip's Tx processes . */ -#ifdef CONFIG_NET_HW_FLOWCONTROL - if (tp->fc_bit && test_bit(tp->fc_bit,&netdev_fc_xoff)) - printk("BUG tx_timeout restarting rx when fc on\n"); -#endif - tulip_restart_rxtx(tp); - /* Trigger an immediate transmit demand. */ - outl(0, ioaddr + CSR1); - - tp->stats.tx_errors++; - -out: - spin_unlock_irqrestore (&tp->lock, flags); - dev->trans_start = jiffies; - netif_wake_queue (dev); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void tulip_init_ring(struct net_device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - int i; - - tp->susp_rx = 0; - tp->ttimer = 0; - tp->nir = 0; - - for (i = 0; i < RX_RING_SIZE; i++) { - tp->rx_ring[i].status = 0x00000000; - tp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ); - tp->rx_ring[i].buffer2 = cpu_to_le32(tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * (i + 1)); - tp->rx_buffers[i].skb = NULL; - tp->rx_buffers[i].mapping = 0; - } - /* Mark the last entry as wrapping the ring. */ - tp->rx_ring[i-1].length = cpu_to_le32(PKT_BUF_SZ | DESC_RING_WRAP); - tp->rx_ring[i-1].buffer2 = cpu_to_le32(tp->rx_ring_dma); - - for (i = 0; i < RX_RING_SIZE; i++) { - dma_addr_t mapping; - - /* Note the receive buffer must be longword aligned. - dev_alloc_skb() provides 16 byte alignment. But do *not* - use skb_reserve() to align the IP header! */ - struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ); - tp->rx_buffers[i].skb = skb; - if (skb == NULL) - break; - mapping = pci_map_single(tp->pdev, skb->tail, - PKT_BUF_SZ, PCI_DMA_FROMDEVICE); - tp->rx_buffers[i].mapping = mapping; - skb->dev = dev; /* Mark as being used by this device. */ - tp->rx_ring[i].status = cpu_to_le32(DescOwned); /* Owned by Tulip chip */ - tp->rx_ring[i].buffer1 = cpu_to_le32(mapping); - } - tp->dirty_rx = (unsigned int)(i - RX_RING_SIZE); - - /* The Tx buffer descriptor is filled in as needed, but we - do need to clear the ownership bit. */ - for (i = 0; i < TX_RING_SIZE; i++) { - tp->tx_buffers[i].skb = NULL; - tp->tx_buffers[i].mapping = 0; - tp->tx_ring[i].status = 0x00000000; - tp->tx_ring[i].buffer2 = cpu_to_le32(tp->tx_ring_dma + sizeof(struct tulip_tx_desc) * (i + 1)); - } - tp->tx_ring[i-1].buffer2 = cpu_to_le32(tp->tx_ring_dma); -} - -static int -tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - int entry; - u32 flag; - dma_addr_t mapping; - unsigned long eflags; - - if (skb_shinfo(skb)->nr_frags != 0) - BUG(); - - spin_lock_irqsave(&tp->lock, eflags); - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % TX_RING_SIZE; - - tp->tx_buffers[entry].skb = skb; - mapping = pci_map_single(tp->pdev, skb->data, - skb->len, PCI_DMA_TODEVICE); - tp->tx_buffers[entry].mapping = mapping; - tp->tx_ring[entry].buffer1 = cpu_to_le32(mapping); - - if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */ - flag = 0x60000000; /* No interrupt */ - } else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) { - flag = 0xe0000000; /* Tx-done intr. */ - } else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) { - flag = 0x60000000; /* No Tx-done intr. */ - } else { /* Leave room for set_rx_mode() to fill entries. */ - flag = 0xe0000000; /* Tx-done intr. */ - netif_stop_queue(dev); - } - if (entry == TX_RING_SIZE-1) - flag = 0xe0000000 | DESC_RING_WRAP; - - tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); - /* if we were using Transmit Automatic Polling, we would need a - * wmb() here. */ - tp->tx_ring[entry].status = cpu_to_le32(DescOwned); - wmb(); - - tp->cur_tx++; - - /* Trigger an immediate transmit demand. */ - outl(0, dev->base_addr + CSR1); - - spin_unlock_irqrestore(&tp->lock, eflags); - - dev->trans_start = jiffies; - - return 0; -} - -static void tulip_clean_tx_ring(struct tulip_private *tp) -{ - unsigned int dirty_tx; - - for (dirty_tx = tp->dirty_tx ; tp->cur_tx - dirty_tx > 0; - dirty_tx++) { - int entry = dirty_tx % TX_RING_SIZE; - int status = le32_to_cpu(tp->tx_ring[entry].status); - - if (status < 0) { - tp->stats.tx_errors++; /* It wasn't Txed */ - tp->tx_ring[entry].status = 0; - } - - /* Check for Tx filter setup frames. */ - if (tp->tx_buffers[entry].skb == NULL) { - /* test because dummy frames not mapped */ - if (tp->tx_buffers[entry].mapping) - pci_unmap_single(tp->pdev, - tp->tx_buffers[entry].mapping, - sizeof(tp->setup_frame), - PCI_DMA_TODEVICE); - continue; - } - - pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping, - tp->tx_buffers[entry].skb->len, - PCI_DMA_TODEVICE); - - /* Free the original skb. */ - dev_kfree_skb_irq(tp->tx_buffers[entry].skb); - tp->tx_buffers[entry].skb = NULL; - tp->tx_buffers[entry].mapping = 0; - } -} - -static void tulip_down (struct net_device *dev) -{ - long ioaddr = dev->base_addr; - struct tulip_private *tp = (struct tulip_private *) dev->priv; - unsigned long flags; - - del_timer_sync (&tp->timer); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts by clearing the interrupt mask. */ - outl (0x00000000, ioaddr + CSR7); - - /* Stop the Tx and Rx processes. */ - tulip_stop_rxtx(tp); - - /* prepare receive buffers */ - tulip_refill_rx(dev); - - /* release any unconsumed transmit buffers */ - tulip_clean_tx_ring(tp); - - /* 21040 -- Leave the card in 10baseT state. */ - if (tp->chip_id == DC21040) - outl (0x00000004, ioaddr + CSR13); - - if (inl (ioaddr + CSR6) != 0xffffffff) - tp->stats.rx_missed_errors += inl (ioaddr + CSR8) & 0xffff; - - spin_unlock_irqrestore (&tp->lock, flags); - - init_timer(&tp->timer); - tp->timer.data = (unsigned long)dev; - tp->timer.function = tulip_tbl[tp->chip_id].media_timer; - - dev->if_port = tp->saved_if_port; - - /* Leave the driver in snooze, not sleep, mode. */ - tulip_set_power_state (tp, 0, 1); -} - - -static int tulip_close (struct net_device *dev) -{ - long ioaddr = dev->base_addr; - struct tulip_private *tp = (struct tulip_private *) dev->priv; - int i; - - netif_stop_queue (dev); - -#ifdef CONFIG_NET_HW_FLOWCONTROL - if (tp->fc_bit) { - int bit = tp->fc_bit; - tp->fc_bit = 0; - netdev_unregister_fc(bit); - } -#endif - tulip_down (dev); - - if (tulip_debug > 1) - printk (KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, inl (ioaddr + CSR5)); - - free_irq (dev->irq, dev); - - /* Free all the skbuffs in the Rx queue. */ - for (i = 0; i < RX_RING_SIZE; i++) { - struct sk_buff *skb = tp->rx_buffers[i].skb; - dma_addr_t mapping = tp->rx_buffers[i].mapping; - - tp->rx_buffers[i].skb = NULL; - tp->rx_buffers[i].mapping = 0; - - tp->rx_ring[i].status = 0; /* Not owned by Tulip chip. */ - tp->rx_ring[i].length = 0; - tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */ - if (skb) { - pci_unmap_single(tp->pdev, mapping, PKT_BUF_SZ, - PCI_DMA_FROMDEVICE); - dev_kfree_skb (skb); - } - } - for (i = 0; i < TX_RING_SIZE; i++) { - struct sk_buff *skb = tp->tx_buffers[i].skb; - - if (skb != NULL) { - pci_unmap_single(tp->pdev, tp->tx_buffers[i].mapping, - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb (skb); - } - tp->tx_buffers[i].skb = NULL; - tp->tx_buffers[i].mapping = 0; - } - - MOD_DEC_USE_COUNT; - - return 0; -} - -static struct net_device_stats *tulip_get_stats(struct net_device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - - if (netif_running(dev)) { - unsigned long flags; - - spin_lock_irqsave (&tp->lock, flags); - - tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; - - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &tp->stats; -} - - -static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr) -{ - struct tulip_private *np = dev->priv; - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - strcpy(info.bus_info, np->pdev->slot_name); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - - } - - return -EOPNOTSUPP; -} - -/* Provide ioctl() calls to examine the MII xcvr state. */ -static int private_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct tulip_private *tp = dev->priv; - long ioaddr = dev->base_addr; - struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data; - const unsigned int phy_idx = 0; - int phy = tp->phys[phy_idx] & 0x1f; - unsigned int regnum = data->reg_num; - - switch (cmd) { - case SIOCETHTOOL: - return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); - - case SIOCGMIIPHY: /* Get address of MII PHY in use. */ - case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ - if (tp->mii_cnt) - data->phy_id = phy; - else if (tp->flags & HAS_NWAY) - data->phy_id = 32; - else if (tp->chip_id == COMET) - data->phy_id = 1; - else - return -ENODEV; - - case SIOCGMIIREG: /* Read MII PHY register. */ - case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ - if (data->phy_id == 32 && (tp->flags & HAS_NWAY)) { - int csr12 = inl (ioaddr + CSR12); - int csr14 = inl (ioaddr + CSR14); - switch (regnum) { - case 0: - if (((csr14<<5) & 0x1000) || - (dev->if_port == 5 && tp->nwayset)) - data->val_out = 0x1000; - else - data->val_out = (tulip_media_cap[dev->if_port]&MediaIs100 ? 0x2000 : 0) - | (tulip_media_cap[dev->if_port]&MediaIsFD ? 0x0100 : 0); - break; - case 1: - data->val_out = - 0x1848 + - ((csr12&0x7000) == 0x5000 ? 0x20 : 0) + - ((csr12&0x06) == 6 ? 0 : 4); - if (tp->chip_id != DC21041) - data->val_out |= 0x6048; - break; - case 4: - /* Advertised value, bogus 10baseTx-FD value from CSR6. */ - data->val_out = - ((inl(ioaddr + CSR6) >> 3) & 0x0040) + - ((csr14 >> 1) & 0x20) + 1; - if (tp->chip_id != DC21041) - data->val_out |= ((csr14 >> 9) & 0x03C0); - break; - case 5: data->val_out = tp->lpar; break; - default: data->val_out = 0; break; - } - } else { - data->val_out = tulip_mdio_read (dev, data->phy_id & 0x1f, regnum); - } - return 0; - - case SIOCSMIIREG: /* Write MII PHY register. */ - case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ - if (!capable (CAP_NET_ADMIN)) - return -EPERM; - if (regnum & ~0x1f) - return -EINVAL; - if (data->phy_id == phy) { - u16 value = data->val_in; - switch (regnum) { - case 0: /* Check for autonegotiation on or reset. */ - tp->full_duplex_lock = (value & 0x9000) ? 0 : 1; - if (tp->full_duplex_lock) - tp->full_duplex = (value & 0x0100) ? 1 : 0; - break; - case 4: - tp->advertising[phy_idx] = - tp->mii_advertise = data->val_in; - break; - } - } - if (data->phy_id == 32 && (tp->flags & HAS_NWAY)) { - u16 value = data->val_in; - if (regnum == 0) { - if ((value & 0x1200) == 0x1200) { - if (tp->chip_id == PNIC2) { - pnic2_start_nway (dev); - } else { - t21142_start_nway (dev); - } - } - } else if (regnum == 4) - tp->sym_advertise = value; - } else { - tulip_mdio_write (dev, data->phy_id & 0x1f, regnum, data->val_in); - } - return 0; - default: - return -EOPNOTSUPP; - } - - return -EOPNOTSUPP; -} - - -/* Set or clear the multicast filter for this adaptor. - Note that we only use exclusion around actually queueing the - new frame, not around filling tp->setup_frame. This is non-deterministic - when re-entered but still correct. */ - -#undef set_bit_le -#define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0) - -static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - u16 hash_table[32]; - struct dev_mc_list *mclist; - int i; - u16 *eaddrs; - - memset(hash_table, 0, sizeof(hash_table)); - set_bit_le(255, hash_table); /* Broadcast entry */ - /* This should work on big-endian machines as well. */ - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int index = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff; - - set_bit_le(index, hash_table); - - for (i = 0; i < 32; i++) { - *setup_frm++ = hash_table[i]; - *setup_frm++ = hash_table[i]; - } - setup_frm = &tp->setup_frame[13*6]; - } - - /* Fill the final entry with our physical address. */ - eaddrs = (u16 *)dev->dev_addr; - *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; - *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; - *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; -} - -static void build_setup_frame_perfect(u16 *setup_frm, struct net_device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - struct dev_mc_list *mclist; - int i; - u16 *eaddrs; - - /* We have <= 14 addresses so we can use the wonderful - 16 address perfect filtering of the Tulip. */ - for (i = 0, mclist = dev->mc_list; i < dev->mc_count; - i++, mclist = mclist->next) { - eaddrs = (u16 *)mclist->dmi_addr; - *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; - *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; - *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; - } - /* Fill the unused entries with the broadcast address. */ - memset(setup_frm, 0xff, (15-i)*12); - setup_frm = &tp->setup_frame[15*6]; - - /* Fill the final entry with our physical address. */ - eaddrs = (u16 *)dev->dev_addr; - *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; - *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; - *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; -} - - -static void set_rx_mode(struct net_device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - int csr6; - - csr6 = inl(ioaddr + CSR6) & ~0x00D5; - - tp->csr6 &= ~0x00D5; - if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ - tp->csr6 |= AcceptAllMulticast | AcceptAllPhys; - csr6 |= AcceptAllMulticast | AcceptAllPhys; - /* Unconditionally log net taps. */ - printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name); - } else if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter well -- accept all multicasts. */ - tp->csr6 |= AcceptAllMulticast; - csr6 |= AcceptAllMulticast; - } else if (tp->flags & MC_HASH_ONLY) { - /* Some work-alikes have only a 64-entry hash filter table. */ - /* Should verify correctness on big-endian/__powerpc__ */ - struct dev_mc_list *mclist; - int i; - if (dev->mc_count > 64) { /* Arbitrary non-effective limit. */ - tp->csr6 |= AcceptAllMulticast; - csr6 |= AcceptAllMulticast; - } else { - u32 mc_filter[2] = {0, 0}; /* Multicast hash filter */ - int filterbit; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - if (tp->flags & COMET_MAC_ADDR) - filterbit = ether_crc_le(ETH_ALEN, mclist->dmi_addr); - else - filterbit = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - filterbit &= 0x3f; - mc_filter[filterbit >> 5] |= cpu_to_le32(1 << (filterbit & 31)); - if (tulip_debug > 2) { - printk(KERN_INFO "%s: Added filter for %2.2x:%2.2x:%2.2x:" - "%2.2x:%2.2x:%2.2x %8.8x bit %d.\n", dev->name, - mclist->dmi_addr[0], mclist->dmi_addr[1], - mclist->dmi_addr[2], mclist->dmi_addr[3], - mclist->dmi_addr[4], mclist->dmi_addr[5], - ether_crc(ETH_ALEN, mclist->dmi_addr), filterbit); - } - } - if (mc_filter[0] == tp->mc_filter[0] && - mc_filter[1] == tp->mc_filter[1]) - ; /* No change. */ - else if (tp->flags & IS_ASIX) { - outl(2, ioaddr + CSR13); - outl(mc_filter[0], ioaddr + CSR14); - outl(3, ioaddr + CSR13); - outl(mc_filter[1], ioaddr + CSR14); - } else if (tp->flags & COMET_MAC_ADDR) { - outl(mc_filter[0], ioaddr + 0xAC); - outl(mc_filter[1], ioaddr + 0xB0); - } - tp->mc_filter[0] = mc_filter[0]; - tp->mc_filter[1] = mc_filter[1]; - } - } else { - unsigned long flags; - - /* Note that only the low-address shortword of setup_frame is valid! - The values are doubled for big-endian architectures. */ - if (dev->mc_count > 14) { /* Must use a multicast hash table. */ - build_setup_frame_hash(tp->setup_frame, dev); - } else { - build_setup_frame_perfect(tp->setup_frame, dev); - } - - spin_lock_irqsave(&tp->lock, flags); - - if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) { - /* Same setup recently queued, we need not add it. */ - } else { - u32 tx_flags = 0x08000000 | 192; - unsigned int entry; - int dummy = -1; - - /* Now add this frame to the Tx list. */ - - entry = tp->cur_tx++ % TX_RING_SIZE; - - if (entry != 0) { - /* Avoid a chip errata by prefixing a dummy entry. */ - tp->tx_buffers[entry].skb = NULL; - tp->tx_buffers[entry].mapping = 0; - tp->tx_ring[entry].length = - (entry == TX_RING_SIZE-1) ? cpu_to_le32(DESC_RING_WRAP) : 0; - tp->tx_ring[entry].buffer1 = 0; - /* Must set DescOwned later to avoid race with chip */ - dummy = entry; - entry = tp->cur_tx++ % TX_RING_SIZE; - } - - tp->tx_buffers[entry].skb = NULL; - tp->tx_buffers[entry].mapping = - pci_map_single(tp->pdev, tp->setup_frame, - sizeof(tp->setup_frame), - PCI_DMA_TODEVICE); - /* Put the setup frame on the Tx list. */ - if (entry == TX_RING_SIZE-1) - tx_flags |= DESC_RING_WRAP; /* Wrap ring. */ - tp->tx_ring[entry].length = cpu_to_le32(tx_flags); - tp->tx_ring[entry].buffer1 = - cpu_to_le32(tp->tx_buffers[entry].mapping); - tp->tx_ring[entry].status = cpu_to_le32(DescOwned); - if (dummy >= 0) - tp->tx_ring[dummy].status = cpu_to_le32(DescOwned); - if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) - netif_stop_queue(dev); - - /* Trigger an immediate transmit demand. */ - outl(0, ioaddr + CSR1); - } - - spin_unlock_irqrestore(&tp->lock, flags); - } - - outl(csr6, ioaddr + CSR6); -} - -#ifdef CONFIG_TULIP_MWI -static void __devinit tulip_mwi_config (struct pci_dev *pdev, - struct net_device *dev) -{ - struct tulip_private *tp = dev->priv; - u8 cache; - u16 pci_command; - u32 csr0; - - if (tulip_debug > 3) - printk(KERN_DEBUG "%s: tulip_mwi_config()\n", pdev->slot_name); - - tp->csr0 = csr0 = 0; - - /* if we have any cache line size at all, we can do MRM */ - csr0 |= MRM; - - /* ...and barring hardware bugs, MWI */ - if (!(tp->chip_id == DC21143 && tp->revision == 65)) - csr0 |= MWI; - - /* set or disable MWI in the standard PCI command bit. - * Check for the case where mwi is desired but not available - */ - if (csr0 & MWI) pci_set_mwi(pdev); - else pci_clear_mwi(pdev); - - /* read result from hardware (in case bit refused to enable) */ - pci_read_config_word(pdev, PCI_COMMAND, &pci_command); - if ((csr0 & MWI) && (!(pci_command & PCI_COMMAND_INVALIDATE))) - csr0 &= ~MWI; - - /* if cache line size hardwired to zero, no MWI */ - pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache); - if ((csr0 & MWI) && (cache == 0)) { - csr0 &= ~MWI; - pci_clear_mwi(pdev); - } - - /* assign per-cacheline-size cache alignment and - * burst length values - */ - switch (cache) { - case 8: - csr0 |= MRL | (1 << CALShift) | (16 << BurstLenShift); - break; - case 16: - csr0 |= MRL | (2 << CALShift) | (16 << BurstLenShift); - break; - case 32: - csr0 |= MRL | (3 << CALShift) | (32 << BurstLenShift); - break; - default: - cache = 0; - break; - } - - /* if we have a good cache line size, we by now have a good - * csr0, so save it and exit - */ - if (cache) - goto out; - - /* we don't have a good csr0 or cache line size, disable MWI */ - if (csr0 & MWI) { - pci_clear_mwi(pdev); - csr0 &= ~MWI; - } - - /* sane defaults for burst length and cache alignment - * originally from de4x5 driver - */ - csr0 |= (8 << BurstLenShift) | (1 << CALShift); - -out: - tp->csr0 = csr0; - if (tulip_debug > 2) - printk(KERN_DEBUG "%s: MWI config cacheline=%d, csr0=%08x\n", - pdev->slot_name, cache, csr0); -} -#endif - -static int __devinit tulip_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct tulip_private *tp; - /* See note below on the multiport cards. */ - static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'}; - static int last_irq; - static int multiport_cnt; /* For four-port boards w/one EEPROM */ - u8 chip_rev; - int i, irq; - unsigned short sum; - u8 ee_data[EEPROM_SIZE]; - struct net_device *dev; - long ioaddr; - static int board_idx = -1; - int chip_idx = ent->driver_data; - unsigned int t2104x_mode = 0; - unsigned int eeprom_missing = 0; - unsigned int force_csr0 = 0; - -#ifndef MODULE - static int did_version; /* Already printed version info. */ - if (tulip_debug > 0 && did_version++ == 0) - printk (KERN_INFO "%s", version); -#endif - - board_idx++; - - /* - * Lan media wire a tulip chip to a wan interface. Needs a very - * different driver (lmc driver) - */ - - if (pdev->subsystem_vendor == PCI_VENDOR_ID_LMC) { - printk (KERN_ERR PFX "skipping LMC card.\n"); - return -ENODEV; - } - - /* - * Early DM9100's need software CRC and the DMFE driver - */ - - if (pdev->vendor == 0x1282 && pdev->device == 0x9100) - { - u32 dev_rev; - /* Read Chip revision */ - pci_read_config_dword(pdev, PCI_REVISION_ID, &dev_rev); - if(dev_rev < 0x02000030) - { - printk(KERN_ERR PFX "skipping early DM9100 with Crc bug (use dmfe)\n"); - return -ENODEV; - } - } - - /* - * Looks for early PCI chipsets where people report hangs - * without the workarounds being on. - */ - - /* Intel Saturn. Switch to 8 long words burst, 8 long word cache aligned - Aries might need this too. The Saturn errata are not pretty reading but - thankfully its an old 486 chipset. - */ - - if (pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424, NULL)) { - csr0 = MRL | MRM | (8 << BurstLenShift) | (1 << CALShift); - force_csr0 = 1; - } - /* The dreaded SiS496 486 chipset. Same workaround as above. */ - if (pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, NULL)) { - csr0 = MRL | MRM | (8 << BurstLenShift) | (1 << CALShift); - force_csr0 = 1; - } - - /* bugfix: the ASIX must have a burst limit or horrible things happen. */ - if (chip_idx == AX88140) { - if ((csr0 & 0x3f00) == 0) - csr0 |= 0x2000; - } - - /* PNIC doesn't have MWI/MRL/MRM... */ - if (chip_idx == LC82C168) - csr0 &= ~0xfff10000; /* zero reserved bits 31:20, 16 */ - - /* DM9102A has troubles with MRM & clear reserved bits 24:22, 20, 16, 7:1 */ - if (pdev->vendor == 0x1282 && pdev->device == 0x9102) - csr0 &= ~0x01f100ff; - -#if defined(__sparc__) - /* DM9102A needs 32-dword alignment/burst length on sparc - chip bug? */ - if (pdev->vendor == 0x1282 && pdev->device == 0x9102) - csr0 = (csr0 & ~0xff00) | 0xe000; -#endif - - /* - * And back to business - */ - - i = pci_enable_device(pdev); - if (i) { - printk (KERN_ERR PFX - "Cannot enable tulip board #%d, aborting\n", - board_idx); - return i; - } - - ioaddr = pci_resource_start (pdev, 0); - irq = pdev->irq; - - /* alloc_etherdev ensures aligned and zeroed private structures */ - dev = alloc_etherdev (sizeof (*tp)); - if (!dev) { - printk (KERN_ERR PFX "ether device alloc failed, aborting\n"); - return -ENOMEM; - } - - if (pci_resource_len (pdev, 0) < tulip_tbl[chip_idx].io_size) { - printk (KERN_ERR PFX "%s: I/O region (0x%lx@0x%lx) too small, " - "aborting\n", pdev->slot_name, - pci_resource_len (pdev, 0), - pci_resource_start (pdev, 0)); - goto err_out_free_netdev; - } - - /* grab all resources from both PIO and MMIO regions, as we - * don't want anyone else messing around with our hardware */ - if (pci_request_regions (pdev, "tulip")) - goto err_out_free_netdev; - -#ifndef USE_IO_OPS - ioaddr = (unsigned long) ioremap (pci_resource_start (pdev, 1), - tulip_tbl[chip_idx].io_size); - if (!ioaddr) - goto err_out_free_res; -#endif - - pci_read_config_byte (pdev, PCI_REVISION_ID, &chip_rev); - - /* - * initialize private data structure 'tp' - * it is zeroed and aligned in alloc_etherdev - */ - tp = dev->priv; - - tp->rx_ring = pci_alloc_consistent(pdev, - sizeof(struct tulip_rx_desc) * RX_RING_SIZE + - sizeof(struct tulip_tx_desc) * TX_RING_SIZE, - &tp->rx_ring_dma); - if (!tp->rx_ring) - goto err_out_mtable; - tp->tx_ring = (struct tulip_tx_desc *)(tp->rx_ring + RX_RING_SIZE); - tp->tx_ring_dma = tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * RX_RING_SIZE; - - tp->chip_id = chip_idx; - tp->flags = tulip_tbl[chip_idx].flags; - tp->pdev = pdev; - tp->base_addr = ioaddr; - tp->revision = chip_rev; - tp->csr0 = csr0; - spin_lock_init(&tp->lock); - spin_lock_init(&tp->mii_lock); - init_timer(&tp->timer); - tp->timer.data = (unsigned long)dev; - tp->timer.function = tulip_tbl[tp->chip_id].media_timer; - - dev->base_addr = ioaddr; - -#ifdef CONFIG_TULIP_MWI - if (!force_csr0 && (tp->flags & HAS_PCI_MWI)) - tulip_mwi_config (pdev, dev); -#else - /* MWI is broken for DC21143 rev 65... */ - if (chip_idx == DC21143 && chip_rev == 65) - tp->csr0 &= ~MWI; -#endif - - /* Stop the chip's Tx and Rx processes. */ - tulip_stop_rxtx(tp); - - pci_set_master(pdev); - - /* Clear the missed-packet counter. */ - inl(ioaddr + CSR8); - - if (chip_idx == DC21041) { - if (inl(ioaddr + CSR9) & 0x8000) { - chip_idx = DC21040; - t2104x_mode = 1; - } else { - t2104x_mode = 2; - } - } - - /* The station address ROM is read byte serially. The register must - be polled, waiting for the value to be read bit serially from the - EEPROM. - */ - sum = 0; - if (chip_idx == DC21040) { - outl(0, ioaddr + CSR9); /* Reset the pointer with a dummy write. */ - for (i = 0; i < 6; i++) { - int value, boguscnt = 100000; - do - value = inl(ioaddr + CSR9); - while (value < 0 && --boguscnt > 0); - dev->dev_addr[i] = value; - sum += value & 0xff; - } - } else if (chip_idx == LC82C168) { - for (i = 0; i < 3; i++) { - int value, boguscnt = 100000; - outl(0x600 | i, ioaddr + 0x98); - do - value = inl(ioaddr + CSR9); - while (value < 0 && --boguscnt > 0); - put_unaligned(le16_to_cpu(value), ((u16*)dev->dev_addr) + i); - sum += value & 0xffff; - } - } else if (chip_idx == COMET) { - /* No need to read the EEPROM. */ - put_unaligned(inl(ioaddr + 0xA4), (u32 *)dev->dev_addr); - put_unaligned(inl(ioaddr + 0xA8), (u16 *)(dev->dev_addr + 4)); - for (i = 0; i < 6; i ++) - sum += dev->dev_addr[i]; - } else { - /* A serial EEPROM interface, we read now and sort it out later. */ - int sa_offset = 0; - int ee_addr_size = tulip_read_eeprom(ioaddr, 0xff, 8) & 0x40000 ? 8 : 6; - - for (i = 0; i < sizeof(ee_data)/2; i++) - ((u16 *)ee_data)[i] = - le16_to_cpu(tulip_read_eeprom(ioaddr, i, ee_addr_size)); - - /* DEC now has a specification (see Notes) but early board makers - just put the address in the first EEPROM locations. */ - /* This does memcmp(eedata, eedata+16, 8) */ - for (i = 0; i < 8; i ++) - if (ee_data[i] != ee_data[16+i]) - sa_offset = 20; - if (chip_idx == CONEXANT) { - /* Check that the tuple type and length is correct. */ - if (ee_data[0x198] == 0x04 && ee_data[0x199] == 6) - sa_offset = 0x19A; - } - if (ee_data[0] == 0xff && ee_data[1] == 0xff && - ee_data[2] == 0) { - sa_offset = 2; /* Grrr, damn Matrox boards. */ - multiport_cnt = 4; - } -#ifdef CONFIG_DDB5476 - if ((pdev->bus->number == 0) && (PCI_SLOT(pdev->devfn) == 6)) { - /* DDB5476 MAC address in first EEPROM locations. */ - sa_offset = 0; - /* No media table either */ - tp->flags &= ~HAS_MEDIA_TABLE; - } -#endif -#ifdef CONFIG_DDB5477 - if ((pdev->bus->number == 0) && (PCI_SLOT(pdev->devfn) == 4)) { - /* DDB5477 MAC address in first EEPROM locations. */ - sa_offset = 0; - /* No media table either */ - tp->flags &= ~HAS_MEDIA_TABLE; - } -#endif -#ifdef CONFIG_MIPS_COBALT - if ((pdev->bus->number == 0) && - ((PCI_SLOT(pdev->devfn) == 7) || - (PCI_SLOT(pdev->devfn) == 12))) { - /* Cobalt MAC address in first EEPROM locations. */ - sa_offset = 0; - /* No media table either */ - tp->flags &= ~HAS_MEDIA_TABLE; - } -#endif -#ifdef __hppa__ - /* 3x5 HSC (J3514A) has a broken srom */ - if(ee_data[0] == 0x61 && ee_data[1] == 0x10) { - /* pci_vendor_id and subsystem_id are swapped */ - ee_data[0] = ee_data[2]; - ee_data[1] = ee_data[3]; - ee_data[2] = 0x61; - ee_data[3] = 0x10; - - /* srom need to be byte-swaped and shifted up 1 word. - * This shift needs to happen at the end of the MAC - * first because of the 2 byte overlap. - */ - for(i = 4; i >= 0; i -= 2) { - ee_data[17 + i + 3] = ee_data[17 + i]; - ee_data[16 + i + 5] = ee_data[16 + i]; - } - } -#endif - for (i = 0; i < 6; i ++) { - dev->dev_addr[i] = ee_data[i + sa_offset]; - sum += ee_data[i + sa_offset]; - } - } - /* Lite-On boards have the address byte-swapped. */ - if ((dev->dev_addr[0] == 0xA0 || dev->dev_addr[0] == 0xC0) - && dev->dev_addr[1] == 0x00) - for (i = 0; i < 6; i+=2) { - char tmp = dev->dev_addr[i]; - dev->dev_addr[i] = dev->dev_addr[i+1]; - dev->dev_addr[i+1] = tmp; - } - /* On the Zynx 315 Etherarray and other multiport boards only the - first Tulip has an EEPROM. - On Sparc systems the mac address is held in the OBP property - "local-mac-address". - The addresses of the subsequent ports are derived from the first. - Many PCI BIOSes also incorrectly report the IRQ line, so we correct - that here as well. */ - if (sum == 0 || sum == 6*0xff) { -#if defined(__sparc__) - struct pcidev_cookie *pcp = pdev->sysdata; -#endif - eeprom_missing = 1; - for (i = 0; i < 5; i++) - dev->dev_addr[i] = last_phys_addr[i]; - dev->dev_addr[i] = last_phys_addr[i] + 1; -#if defined(__sparc__) - if ((pcp != NULL) && prom_getproplen(pcp->prom_node, - "local-mac-address") == 6) { - prom_getproperty(pcp->prom_node, "local-mac-address", - dev->dev_addr, 6); - } -#endif -#if defined(__i386__) /* Patch up x86 BIOS bug. */ - if (last_irq) - irq = last_irq; -#endif - } - - for (i = 0; i < 6; i++) - last_phys_addr[i] = dev->dev_addr[i]; - last_irq = irq; - dev->irq = irq; - - /* The lower four bits are the media type. */ - if (board_idx >= 0 && board_idx < MAX_UNITS) { - if (options[board_idx] & MEDIA_MASK) - tp->default_port = options[board_idx] & MEDIA_MASK; - if ((options[board_idx] & FullDuplex) || full_duplex[board_idx] > 0) - tp->full_duplex = 1; - if (mtu[board_idx] > 0) - dev->mtu = mtu[board_idx]; - } - if (dev->mem_start & MEDIA_MASK) - tp->default_port = dev->mem_start & MEDIA_MASK; - if (tp->default_port) { - printk(KERN_INFO "tulip%d: Transceiver selection forced to %s.\n", - board_idx, medianame[tp->default_port & MEDIA_MASK]); - tp->medialock = 1; - if (tulip_media_cap[tp->default_port] & MediaAlwaysFD) - tp->full_duplex = 1; - } - if (tp->full_duplex) - tp->full_duplex_lock = 1; - - if (tulip_media_cap[tp->default_port] & MediaIsMII) { - u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 }; - tp->mii_advertise = media2advert[tp->default_port - 9]; - tp->mii_advertise |= (tp->flags & HAS_8023X); /* Matching bits! */ - } - - if (tp->flags & HAS_MEDIA_TABLE) { - memcpy(tp->eeprom, ee_data, sizeof(tp->eeprom)); - - sprintf(dev->name, "tulip%d", board_idx); /* hack */ - tulip_parse_eeprom(dev); - strcpy(dev->name, "eth%d"); /* un-hack */ - } - - if ((tp->flags & ALWAYS_CHECK_MII) || - (tp->mtable && tp->mtable->has_mii) || - ( ! tp->mtable && (tp->flags & HAS_MII))) { - if (tp->mtable && tp->mtable->has_mii) { - for (i = 0; i < tp->mtable->leafcount; i++) - if (tp->mtable->mleaf[i].media == 11) { - tp->cur_index = i; - tp->saved_if_port = dev->if_port; - tulip_select_media(dev, 2); - dev->if_port = tp->saved_if_port; - break; - } - } - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs - later, but takes much time. */ - tulip_find_mii (dev, board_idx); - } - - /* The Tulip-specific entries in the device structure. */ - dev->open = tulip_open; - dev->hard_start_xmit = tulip_start_xmit; - dev->tx_timeout = tulip_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; - dev->stop = tulip_close; - dev->get_stats = tulip_get_stats; - dev->do_ioctl = private_ioctl; - dev->set_multicast_list = set_rx_mode; - - if (register_netdev(dev)) - goto err_out_free_ring; - - printk(KERN_INFO "%s: %s rev %d at %#3lx,", - dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr); - pci_set_drvdata(pdev, dev); - - if (t2104x_mode == 1) - printk(" 21040 compatible mode,"); - else if (t2104x_mode == 2) - printk(" 21041 mode,"); - if (eeprom_missing) - printk(" EEPROM not present,"); - for (i = 0; i < 6; i++) - printk("%c%2.2X", i ? ':' : ' ', dev->dev_addr[i]); - printk(", IRQ %d.\n", irq); - - if (tp->chip_id == PNIC2) - tp->link_change = pnic2_lnk_change; - else if ((tp->flags & HAS_NWAY) || tp->chip_id == DC21041) - tp->link_change = t21142_lnk_change; - else if (tp->flags & HAS_PNICNWAY) - tp->link_change = pnic_lnk_change; - - /* Reset the xcvr interface and turn on heartbeat. */ - switch (chip_idx) { - case DC21041: - if (tp->sym_advertise == 0) - tp->sym_advertise = 0x0061; - outl(0x00000000, ioaddr + CSR13); - outl(0xFFFFFFFF, ioaddr + CSR14); - outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */ - outl(inl(ioaddr + CSR6) | csr6_fd, ioaddr + CSR6); - outl(0x0000EF01, ioaddr + CSR13); - break; - case DC21040: - outl(0x00000000, ioaddr + CSR13); - outl(0x00000004, ioaddr + CSR13); - break; - case DC21140: - case DM910X: - default: - if (tp->mtable) - outl(tp->mtable->csr12dir | 0x100, ioaddr + CSR12); - break; - case DC21142: - if (tp->mii_cnt || tulip_media_cap[dev->if_port] & MediaIsMII) { - outl(csr6_mask_defstate, ioaddr + CSR6); - outl(0x0000, ioaddr + CSR13); - outl(0x0000, ioaddr + CSR14); - outl(csr6_mask_hdcap, ioaddr + CSR6); - } else - t21142_start_nway(dev); - break; - case PNIC2: - /* just do a reset for sanity sake */ - outl(0x0000, ioaddr + CSR13); - outl(0x0000, ioaddr + CSR14); - break; - case LC82C168: - if ( ! tp->mii_cnt) { - tp->nway = 1; - tp->nwayset = 0; - outl(csr6_ttm | csr6_ca, ioaddr + CSR6); - outl(0x30, ioaddr + CSR12); - outl(0x0001F078, ioaddr + CSR6); - outl(0x0201F078, ioaddr + CSR6); /* Turn on autonegotiation. */ - } - break; - case MX98713: - case COMPEX9881: - outl(0x00000000, ioaddr + CSR6); - outl(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */ - outl(0x00000001, ioaddr + CSR13); - break; - case MX98715: - case MX98725: - outl(0x01a80000, ioaddr + CSR6); - outl(0xFFFFFFFF, ioaddr + CSR14); - outl(0x00001000, ioaddr + CSR12); - break; - case COMET: - /* No initialization necessary. */ - break; - } - - /* put the chip in snooze mode until opened */ - tulip_set_power_state (tp, 0, 1); - - alert_slow_netdevice(dev, tulip_tbl[chip_idx].chip_name); - - return 0; - -err_out_free_ring: - pci_free_consistent (pdev, - sizeof (struct tulip_rx_desc) * RX_RING_SIZE + - sizeof (struct tulip_tx_desc) * TX_RING_SIZE, - tp->rx_ring, tp->rx_ring_dma); - -err_out_mtable: - if (tp->mtable) - kfree (tp->mtable); -#ifndef USE_IO_OPS - iounmap((void *)ioaddr); - -err_out_free_res: -#endif - pci_release_regions (pdev); - -err_out_free_netdev: - kfree (dev); - return -ENODEV; -} - - -#ifdef CONFIG_PM - -static int tulip_suspend (struct pci_dev *pdev, u32 state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - - if (dev && netif_running (dev) && netif_device_present (dev)) { - netif_device_detach (dev); - tulip_down (dev); - /* pci_power_off(pdev, -1); */ - } - return 0; -} - - -static int tulip_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - - if (dev && netif_running (dev) && !netif_device_present (dev)) { -#if 1 - pci_enable_device (pdev); -#endif - /* pci_power_on(pdev); */ - tulip_up (dev); - netif_device_attach (dev); - } - return 0; -} - -#endif /* CONFIG_PM */ - - -static void __devexit tulip_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct tulip_private *tp; - - if (!dev) - return; - - tp = dev->priv; - pci_free_consistent (pdev, - sizeof (struct tulip_rx_desc) * RX_RING_SIZE + - sizeof (struct tulip_tx_desc) * TX_RING_SIZE, - tp->rx_ring, tp->rx_ring_dma); - unregister_netdev (dev); - if (tp->mtable) - kfree (tp->mtable); -#ifndef USE_IO_OPS - iounmap((void *)dev->base_addr); -#endif - kfree (dev); - pci_release_regions (pdev); - pci_set_drvdata (pdev, NULL); - - /* pci_power_off (pdev, -1); */ -} - - -static struct pci_driver tulip_driver = { - name: DRV_NAME, - id_table: tulip_pci_tbl, - probe: tulip_init_one, - remove: __devexit_p(tulip_remove_one), -#ifdef CONFIG_PM - suspend: tulip_suspend, - resume: tulip_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init tulip_init (void) -{ -#ifdef MODULE - printk (KERN_INFO "%s", version); -#endif - - /* copy module parms into globals */ - tulip_rx_copybreak = rx_copybreak; - tulip_max_interrupt_work = max_interrupt_work; - - /* probe for and init boards */ - return pci_module_init (&tulip_driver); -} - - -static void __exit tulip_cleanup (void) -{ - pci_unregister_driver (&tulip_driver); -} - - -module_init(tulip_init); -module_exit(tulip_cleanup); diff --git a/xen/drivers/pci/pci.c b/xen/drivers/pci/pci.c index f8c33bad06..846e5f01dc 100644 --- a/xen/drivers/pci/pci.c +++ b/xen/drivers/pci/pci.c @@ -619,86 +619,11 @@ pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) return NULL; } -#ifdef OLD_DRIVERS -static int -pci_announce_device(struct pci_driver *drv, struct pci_dev *dev) -{ - const struct pci_device_id *id; - int ret = 0; - - if (drv->id_table) { - id = pci_match_device(drv->id_table, dev); - if (!id) { - ret = 0; - goto out; - } - } else - id = NULL; - - dev_probe_lock(); - if (drv->probe(dev, id) >= 0) { - dev->driver = drv; - ret = 1; - } - dev_probe_unlock(); -out: - return ret; -} -#endif /* OLD_DRIVERS */ - -/** - * pci_register_driver - register a new pci driver - * @drv: the driver structure to register - * - * Adds the driver structure to the list of registered drivers - * Returns the number of pci devices which were claimed by the driver - * during registration. The driver remains registered even if the - * return value is zero. - */ -int -pci_register_driver(struct pci_driver *drv) -{ -#ifdef OLD_DRIVERS - struct pci_dev *dev; - int count = 0; - - list_add_tail(&drv->node, &pci_drivers); - pci_for_each_dev(dev) { - if (!pci_dev_driver(dev)) - count += pci_announce_device(drv, dev); - } - return count; -#else - return 0; +#if 0 /* NOT IN XEN */ +static int pci_announce_device(struct pci_driver *drv, struct pci_dev *dev) +int pci_register_driver(struct pci_driver *drv) +void pci_unregister_driver(struct pci_driver *drv) #endif -} - -/** - * pci_unregister_driver - unregister a pci driver - * @drv: the driver structure to unregister - * - * Deletes the driver structure from the list of registered PCI drivers, - * gives it a chance to clean up by calling its remove() function for - * each device it was responsible for, and marks those devices as - * driverless. - */ - -void -pci_unregister_driver(struct pci_driver *drv) -{ -#ifdef OLD_DRIVERS - struct pci_dev *dev; - - list_del(&drv->node); - pci_for_each_dev(dev) { - if (dev->driver == drv) { - if (drv->remove) - drv->remove(dev); - dev->driver = NULL; - } - } -#endif -} #ifdef CONFIG_HOTPLUG diff --git a/xen/drivers/scsi/BusLogic.c b/xen/drivers/scsi/BusLogic.c deleted file mode 100644 index 8fba3d19d7..0000000000 --- a/xen/drivers/scsi/BusLogic.c +++ /dev/null @@ -1,5010 +0,0 @@ -/* - - Linux Driver for BusLogic MultiMaster and FlashPoint SCSI Host Adapters - - Copyright 1995-1998 by Leonard N. Zubkoff - - This program is free software; you may redistribute and/or modify it under - the terms of the GNU General Public License Version 2 as published by the - Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for complete details. - - The author respectfully requests that any modifications to this software be - sent directly to him for evaluation and testing. - - Special thanks to Wayne Yen, Jin-Lon Hon, and Alex Win of BusLogic, whose - advice has been invaluable, to David Gentzel, for writing the original Linux - BusLogic driver, and to Paul Gortmaker, for being such a dedicated test site. - - Finally, special thanks to Mylex/BusLogic for making the FlashPoint SCCB - Manager available as freely redistributable source code. - -*/ - - -#define BusLogic_DriverVersion "2.1.15" -#define BusLogic_DriverDate "17 August 1998" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/*#include */ -#include -#include -#include -#include -#include -#include "scsi.h" -#include "hosts.h" -#include "sd.h" -#include "BusLogic.h" -#include "FlashPoint.c.inc" - - -/* - BusLogic_DriverOptionsCount is a count of the number of BusLogic Driver - Options specifications provided via the Linux Kernel Command Line or via - the Loadable Kernel Module Installation Facility. -*/ - -static int - BusLogic_DriverOptionsCount; - - -/* - BusLogic_DriverOptions is an array of Driver Options structures representing - BusLogic Driver Options specifications provided via the Linux Kernel Command - Line or via the Loadable Kernel Module Installation Facility. -*/ - -static BusLogic_DriverOptions_T - BusLogic_DriverOptions[BusLogic_MaxHostAdapters]; - - -/* - BusLogic can be assigned a string by insmod. -*/ - -#ifdef MODULE -static char *BusLogic; -MODULE_PARM(BusLogic, "s"); -#endif - - -/* - BusLogic_ProbeOptions is a set of Probe Options to be applied across - all BusLogic Host Adapters. -*/ - -static BusLogic_ProbeOptions_T - BusLogic_ProbeOptions; - - -/* - BusLogic_GlobalOptions is a set of Global Options to be applied across - all BusLogic Host Adapters. -*/ - -static BusLogic_GlobalOptions_T - BusLogic_GlobalOptions; - - -/* - BusLogic_FirstRegisteredHostAdapter and BusLogic_LastRegisteredHostAdapter - are pointers to the first and last registered BusLogic Host Adapters. -*/ - -static BusLogic_HostAdapter_T - *BusLogic_FirstRegisteredHostAdapter, - *BusLogic_LastRegisteredHostAdapter; - - -/* - BusLogic_ProbeInfoCount is the number of entries in BusLogic_ProbeInfoList. -*/ - -static int - BusLogic_ProbeInfoCount; - - -/* - BusLogic_ProbeInfoList is the list of I/O Addresses and Bus Probe Information - to be checked for potential BusLogic Host Adapters. It is initialized by - interrogating the PCI Configuration Space on PCI machines as well as from the - list of standard BusLogic I/O Addresses. -*/ - -static BusLogic_ProbeInfo_T - *BusLogic_ProbeInfoList; - - -/* - BusLogic_CommandFailureReason holds a string identifying the reason why a - call to BusLogic_Command failed. It is only non-NULL when BusLogic_Command - returns a failure code. -*/ - -static char - *BusLogic_CommandFailureReason; - -/* - BusLogic_AnnounceDriver announces the Driver Version and Date, Author's - Name, Copyright Notice, and Electronic Mail Address. -*/ - -static void BusLogic_AnnounceDriver(BusLogic_HostAdapter_T *HostAdapter) -{ - BusLogic_Announce("***** BusLogic SCSI Driver Version " - BusLogic_DriverVersion " of " - BusLogic_DriverDate " *****\n", HostAdapter); - BusLogic_Announce("Copyright 1995-1998 by Leonard N. Zubkoff " - "\n", HostAdapter); -} - - -/* - BusLogic_DriverInfo returns the Host Adapter Name to identify this SCSI - Driver and Host Adapter. -*/ - -const char *BusLogic_DriverInfo(SCSI_Host_T *Host) -{ - BusLogic_HostAdapter_T *HostAdapter = - (BusLogic_HostAdapter_T *) Host->hostdata; - return HostAdapter->FullModelName; -} - - -/* - BusLogic_RegisterHostAdapter adds Host Adapter to the list of registered - BusLogic Host Adapters. -*/ - -static void BusLogic_RegisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter) -{ - HostAdapter->Next = NULL; - if (BusLogic_FirstRegisteredHostAdapter == NULL) - { - BusLogic_FirstRegisteredHostAdapter = HostAdapter; - BusLogic_LastRegisteredHostAdapter = HostAdapter; - } - else - { - BusLogic_LastRegisteredHostAdapter->Next = HostAdapter; - BusLogic_LastRegisteredHostAdapter = HostAdapter; - } -} - - -/* - BusLogic_UnregisterHostAdapter removes Host Adapter from the list of - registered BusLogic Host Adapters. -*/ - -static void BusLogic_UnregisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter) -{ - if (HostAdapter == BusLogic_FirstRegisteredHostAdapter) - { - BusLogic_FirstRegisteredHostAdapter = - BusLogic_FirstRegisteredHostAdapter->Next; - if (HostAdapter == BusLogic_LastRegisteredHostAdapter) - BusLogic_LastRegisteredHostAdapter = NULL; - } - else - { - BusLogic_HostAdapter_T *PreviousHostAdapter = - BusLogic_FirstRegisteredHostAdapter; - while (PreviousHostAdapter != NULL && - PreviousHostAdapter->Next != HostAdapter) - PreviousHostAdapter = PreviousHostAdapter->Next; - if (PreviousHostAdapter != NULL) - PreviousHostAdapter->Next = HostAdapter->Next; - } - HostAdapter->Next = NULL; -} - - -/* - BusLogic_InitializeCCBs initializes a group of Command Control Blocks (CCBs) - for Host Adapter from the BlockSize bytes located at BlockPointer. The newly - created CCBs are added to Host Adapter's free list. -*/ - -static void BusLogic_InitializeCCBs(BusLogic_HostAdapter_T *HostAdapter, - void *BlockPointer, int BlockSize) -{ - BusLogic_CCB_T *CCB = (BusLogic_CCB_T *) BlockPointer; - memset(BlockPointer, 0, BlockSize); - CCB->AllocationGroupHead = true; - while ((BlockSize -= sizeof(BusLogic_CCB_T)) >= 0) - { - CCB->Status = BusLogic_CCB_Free; - CCB->HostAdapter = HostAdapter; - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) - { - CCB->CallbackFunction = BusLogic_QueueCompletedCCB; - CCB->BaseAddress = HostAdapter->FlashPointInfo.BaseAddress; - } - CCB->Next = HostAdapter->Free_CCBs; - CCB->NextAll = HostAdapter->All_CCBs; - HostAdapter->Free_CCBs = CCB; - HostAdapter->All_CCBs = CCB; - HostAdapter->AllocatedCCBs++; - CCB++; - } -} - - -/* - BusLogic_CreateInitialCCBs allocates the initial CCBs for Host Adapter. -*/ - -static boolean BusLogic_CreateInitialCCBs(BusLogic_HostAdapter_T *HostAdapter) -{ - int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(BusLogic_CCB_T); - while (HostAdapter->AllocatedCCBs < HostAdapter->InitialCCBs) - { - void *BlockPointer = kmalloc(BlockSize, - (HostAdapter->BounceBuffersRequired - ? GFP_ATOMIC | GFP_DMA - : GFP_ATOMIC)); - if (BlockPointer == NULL) - { - BusLogic_Error("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n", - HostAdapter); - return false; - } - BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize); - } - return true; -} - - -/* - BusLogic_DestroyCCBs deallocates the CCBs for Host Adapter. -*/ - -static void BusLogic_DestroyCCBs(BusLogic_HostAdapter_T *HostAdapter) -{ - BusLogic_CCB_T *NextCCB = HostAdapter->All_CCBs, *CCB; - HostAdapter->All_CCBs = NULL; - HostAdapter->Free_CCBs = NULL; - while ((CCB = NextCCB) != NULL) - { - NextCCB = CCB->NextAll; - if (CCB->AllocationGroupHead) - kfree(CCB); - } -} - - -/* - BusLogic_CreateAdditionalCCBs allocates Additional CCBs for Host Adapter. If - allocation fails and there are no remaining CCBs available, the Driver Queue - Depth is decreased to a known safe value to avoid potential deadlocks when - multiple host adapters share the same IRQ Channel. -*/ - -static void BusLogic_CreateAdditionalCCBs(BusLogic_HostAdapter_T *HostAdapter, - int AdditionalCCBs, - boolean SuccessMessageP) -{ - int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(BusLogic_CCB_T); - int PreviouslyAllocated = HostAdapter->AllocatedCCBs; - if (AdditionalCCBs <= 0) return; - while (HostAdapter->AllocatedCCBs - PreviouslyAllocated < AdditionalCCBs) - { - void *BlockPointer = kmalloc(BlockSize, - (HostAdapter->BounceBuffersRequired - ? GFP_ATOMIC | GFP_DMA - : GFP_ATOMIC)); - if (BlockPointer == NULL) break; - BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize); - } - if (HostAdapter->AllocatedCCBs > PreviouslyAllocated) - { - if (SuccessMessageP) - BusLogic_Notice("Allocated %d additional CCBs (total now %d)\n", - HostAdapter, - HostAdapter->AllocatedCCBs - PreviouslyAllocated, - HostAdapter->AllocatedCCBs); - return; - } - BusLogic_Notice("Failed to allocate additional CCBs\n", HostAdapter); - if (HostAdapter->DriverQueueDepth > - HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount) - { - HostAdapter->DriverQueueDepth = - HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount; - HostAdapter->SCSI_Host->can_queue = HostAdapter->DriverQueueDepth; - } -} - - -/* - BusLogic_AllocateCCB allocates a CCB from Host Adapter's free list, - allocating more memory from the Kernel if necessary. The Host Adapter's - Lock should already have been acquired by the caller. -*/ - -static BusLogic_CCB_T *BusLogic_AllocateCCB(BusLogic_HostAdapter_T - *HostAdapter) -{ - static unsigned long SerialNumber = 0; - BusLogic_CCB_T *CCB; - CCB = HostAdapter->Free_CCBs; - if (CCB != NULL) - { - CCB->SerialNumber = ++SerialNumber; - HostAdapter->Free_CCBs = CCB->Next; - CCB->Next = NULL; - if (HostAdapter->Free_CCBs == NULL) - BusLogic_CreateAdditionalCCBs(HostAdapter, - HostAdapter->IncrementalCCBs, - true); - return CCB; - } - BusLogic_CreateAdditionalCCBs(HostAdapter, - HostAdapter->IncrementalCCBs, - true); - CCB = HostAdapter->Free_CCBs; - if (CCB == NULL) return NULL; - CCB->SerialNumber = ++SerialNumber; - HostAdapter->Free_CCBs = CCB->Next; - CCB->Next = NULL; - return CCB; -} - - -/* - BusLogic_DeallocateCCB deallocates a CCB, returning it to the Host Adapter's - free list. The Host Adapter's Lock should already have been acquired by the - caller. -*/ - -static void BusLogic_DeallocateCCB(BusLogic_CCB_T *CCB) -{ - BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter; - CCB->Command = NULL; - CCB->Status = BusLogic_CCB_Free; - CCB->Next = HostAdapter->Free_CCBs; - HostAdapter->Free_CCBs = CCB; -} - - -/* - BusLogic_Command sends the command OperationCode to HostAdapter, optionally - providing ParameterLength bytes of ParameterData and receiving at most - ReplyLength bytes of ReplyData; any excess reply data is received but - discarded. - - On success, this function returns the number of reply bytes read from - the Host Adapter (including any discarded data); on failure, it returns - -1 if the command was invalid, or -2 if a timeout occurred. - - BusLogic_Command is called exclusively during host adapter detection and - initialization, so performance and latency are not critical, and exclusive - access to the Host Adapter hardware is assumed. Once the host adapter and - driver are initialized, the only Host Adapter command that is issued is the - single byte Execute Mailbox Command operation code, which does not require - waiting for the Host Adapter Ready bit to be set in the Status Register. -*/ - -static int BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter, - BusLogic_OperationCode_T OperationCode, - void *ParameterData, - int ParameterLength, - void *ReplyData, - int ReplyLength) -{ - unsigned char *ParameterPointer = (unsigned char *) ParameterData; - unsigned char *ReplyPointer = (unsigned char *) ReplyData; - BusLogic_StatusRegister_T StatusRegister; - BusLogic_InterruptRegister_T InterruptRegister; - ProcessorFlags_T ProcessorFlags = 0; - int ReplyBytes = 0, Result; - long TimeoutCounter; - /* - Clear out the Reply Data if provided. - */ - if (ReplyLength > 0) - memset(ReplyData, 0, ReplyLength); - /* - If the IRQ Channel has not yet been acquired, then interrupts must be - disabled while issuing host adapter commands since a Command Complete - interrupt could occur if the IRQ Channel was previously enabled by another - BusLogic Host Adapter or another driver sharing the same IRQ Channel. - */ - if (!HostAdapter->IRQ_ChannelAcquired) - { - save_flags(ProcessorFlags); - cli(); - } - /* - Wait for the Host Adapter Ready bit to be set and the Command/Parameter - Register Busy bit to be reset in the Status Register. - */ - TimeoutCounter = 10000; - while (--TimeoutCounter >= 0) - { - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister.Bits.HostAdapterReady && - !StatusRegister.Bits.CommandParameterRegisterBusy) - break; - udelay(100); - } - if (TimeoutCounter < 0) - { - BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready"; - Result = -2; - goto Done; - } - /* - Write the OperationCode to the Command/Parameter Register. - */ - HostAdapter->HostAdapterCommandCompleted = false; - BusLogic_WriteCommandParameterRegister(HostAdapter, OperationCode); - /* - Write any additional Parameter Bytes. - */ - TimeoutCounter = 10000; - while (ParameterLength > 0 && --TimeoutCounter >= 0) - { - /* - Wait 100 microseconds to give the Host Adapter enough time to determine - whether the last value written to the Command/Parameter Register was - valid or not. If the Command Complete bit is set in the Interrupt - Register, then the Command Invalid bit in the Status Register will be - reset if the Operation Code or Parameter was valid and the command - has completed, or set if the Operation Code or Parameter was invalid. - If the Data In Register Ready bit is set in the Status Register, then - the Operation Code was valid, and data is waiting to be read back - from the Host Adapter. Otherwise, wait for the Command/Parameter - Register Busy bit in the Status Register to be reset. - */ - udelay(100); - InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (InterruptRegister.Bits.CommandComplete) break; - if (HostAdapter->HostAdapterCommandCompleted) break; - if (StatusRegister.Bits.DataInRegisterReady) break; - if (StatusRegister.Bits.CommandParameterRegisterBusy) continue; - BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++); - ParameterLength--; - } - if (TimeoutCounter < 0) - { - BusLogic_CommandFailureReason = - "Timeout waiting for Parameter Acceptance"; - Result = -2; - goto Done; - } - /* - The Modify I/O Address command does not cause a Command Complete Interrupt. - */ - if (OperationCode == BusLogic_ModifyIOAddress) - { - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister.Bits.CommandInvalid) - { - BusLogic_CommandFailureReason = "Modify I/O Address Invalid"; - Result = -1; - goto Done; - } - if (BusLogic_GlobalOptions.TraceConfiguration) - BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: " - "(Modify I/O Address)\n", HostAdapter, - OperationCode, StatusRegister.All); - Result = 0; - goto Done; - } - /* - Select an appropriate timeout value for awaiting command completion. - */ - switch (OperationCode) - { - case BusLogic_InquireInstalledDevicesID0to7: - case BusLogic_InquireInstalledDevicesID8to15: - case BusLogic_InquireTargetDevices: - /* Approximately 60 seconds. */ - TimeoutCounter = 60*10000; - break; - default: - /* Approximately 1 second. */ - TimeoutCounter = 10000; - break; - } - /* - Receive any Reply Bytes, waiting for either the Command Complete bit to - be set in the Interrupt Register, or for the Interrupt Handler to set the - Host Adapter Command Completed bit in the Host Adapter structure. - */ - while (--TimeoutCounter >= 0) - { - InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (InterruptRegister.Bits.CommandComplete) break; - if (HostAdapter->HostAdapterCommandCompleted) break; - if (StatusRegister.Bits.DataInRegisterReady) - { - if (++ReplyBytes <= ReplyLength) - *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter); - else BusLogic_ReadDataInRegister(HostAdapter); - } - if (OperationCode == BusLogic_FetchHostAdapterLocalRAM && - StatusRegister.Bits.HostAdapterReady) break; - udelay(100); - } - if (TimeoutCounter < 0) - { - BusLogic_CommandFailureReason = "Timeout waiting for Command Complete"; - Result = -2; - goto Done; - } - /* - Clear any pending Command Complete Interrupt. - */ - BusLogic_InterruptReset(HostAdapter); - /* - Provide tracing information if requested. - */ - if (BusLogic_GlobalOptions.TraceConfiguration) - { - int i; - BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:", - HostAdapter, OperationCode, - StatusRegister.All, ReplyLength, ReplyBytes); - if (ReplyLength > ReplyBytes) ReplyLength = ReplyBytes; - for (i = 0; i < ReplyLength; i++) - BusLogic_Notice(" %02X", HostAdapter, - ((unsigned char *) ReplyData)[i]); - BusLogic_Notice("\n", HostAdapter); - } - /* - Process Command Invalid conditions. - */ - if (StatusRegister.Bits.CommandInvalid) - { - /* - Some early BusLogic Host Adapters may not recover properly from - a Command Invalid condition, so if this appears to be the case, - a Soft Reset is issued to the Host Adapter. Potentially invalid - commands are never attempted after Mailbox Initialization is - performed, so there should be no Host Adapter state lost by a - Soft Reset in response to a Command Invalid condition. - */ - udelay(1000); - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister.Bits.CommandInvalid || - StatusRegister.Bits.Reserved || - StatusRegister.Bits.DataInRegisterReady || - StatusRegister.Bits.CommandParameterRegisterBusy || - !StatusRegister.Bits.HostAdapterReady || - !StatusRegister.Bits.InitializationRequired || - StatusRegister.Bits.DiagnosticActive || - StatusRegister.Bits.DiagnosticFailure) - { - BusLogic_SoftReset(HostAdapter); - udelay(1000); - } - BusLogic_CommandFailureReason = "Command Invalid"; - Result = -1; - goto Done; - } - /* - Handle Excess Parameters Supplied conditions. - */ - if (ParameterLength > 0) - { - BusLogic_CommandFailureReason = "Excess Parameters Supplied"; - Result = -1; - goto Done; - } - /* - Indicate the command completed successfully. - */ - BusLogic_CommandFailureReason = NULL; - Result = ReplyBytes; - /* - Restore the interrupt status if necessary and return. - */ -Done: - if (!HostAdapter->IRQ_ChannelAcquired) - restore_flags(ProcessorFlags); - return Result; -} - - -/* - BusLogic_AppendProbeAddressISA appends a single ISA I/O Address to the list - of I/O Address and Bus Probe Information to be checked for potential BusLogic - Host Adapters. -*/ - -static void BusLogic_AppendProbeAddressISA(BusLogic_IO_Address_T IO_Address) -{ - BusLogic_ProbeInfo_T *ProbeInfo; - if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) return; - ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; - ProbeInfo->HostAdapterType = BusLogic_MultiMaster; - ProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus; - ProbeInfo->IO_Address = IO_Address; -} - - -/* - BusLogic_InitializeProbeInfoListISA initializes the list of I/O Address and - Bus Probe Information to be checked for potential BusLogic SCSI Host Adapters - only from the list of standard BusLogic MultiMaster ISA I/O Addresses. -*/ - -static void BusLogic_InitializeProbeInfoListISA(BusLogic_HostAdapter_T - *PrototypeHostAdapter) -{ - /* - If BusLogic Driver Options specifications requested that ISA Bus Probes - be inhibited, do not proceed further. - */ - if (BusLogic_ProbeOptions.NoProbeISA) return; - /* - Append the list of standard BusLogic MultiMaster ISA I/O Addresses. - */ - if (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe330 - : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0) - BusLogic_AppendProbeAddressISA(0x330); - if (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe334 - : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0) - BusLogic_AppendProbeAddressISA(0x334); - if (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe230 - : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0) - BusLogic_AppendProbeAddressISA(0x230); - if (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe234 - : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0) - BusLogic_AppendProbeAddressISA(0x234); - if (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe130 - : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0) - BusLogic_AppendProbeAddressISA(0x130); - if (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe134 - : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0) - BusLogic_AppendProbeAddressISA(0x134); -} - - -#ifdef CONFIG_PCI - - -/* - BusLogic_SortProbeInfo sorts a section of BusLogic_ProbeInfoList in order - of increasing PCI Bus and Device Number. -*/ - -static void BusLogic_SortProbeInfo(BusLogic_ProbeInfo_T *ProbeInfoList, - int ProbeInfoCount) -{ - int LastInterchange = ProbeInfoCount-1, Bound, j; - while (LastInterchange > 0) - { - Bound = LastInterchange; - LastInterchange = 0; - for (j = 0; j < Bound; j++) - { - BusLogic_ProbeInfo_T *ProbeInfo1 = &ProbeInfoList[j]; - BusLogic_ProbeInfo_T *ProbeInfo2 = &ProbeInfoList[j+1]; - if (ProbeInfo1->Bus > ProbeInfo2->Bus || - (ProbeInfo1->Bus == ProbeInfo2->Bus && - (ProbeInfo1->Device > ProbeInfo2->Device))) - { - BusLogic_ProbeInfo_T TempProbeInfo; - memcpy(&TempProbeInfo, ProbeInfo1, sizeof(BusLogic_ProbeInfo_T)); - memcpy(ProbeInfo1, ProbeInfo2, sizeof(BusLogic_ProbeInfo_T)); - memcpy(ProbeInfo2, &TempProbeInfo, sizeof(BusLogic_ProbeInfo_T)); - LastInterchange = j; - } - } - } -} - - -/* - BusLogic_InitializeMultiMasterProbeInfo initializes the list of I/O Address - and Bus Probe Information to be checked for potential BusLogic MultiMaster - SCSI Host Adapters by interrogating the PCI Configuration Space on PCI - machines as well as from the list of standard BusLogic MultiMaster ISA - I/O Addresses. It returns the number of PCI MultiMaster Host Adapters found. -*/ - -static int BusLogic_InitializeMultiMasterProbeInfo(BusLogic_HostAdapter_T - *PrototypeHostAdapter) -{ - BusLogic_ProbeInfo_T *PrimaryProbeInfo = - &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount]; - int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1; - int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0; - boolean ForceBusDeviceScanningOrder = false; - boolean ForceBusDeviceScanningOrderChecked = false; - boolean StandardAddressSeen[6]; - PCI_Device_T *PCI_Device = NULL; - int i; - if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) return 0; - BusLogic_ProbeInfoCount++; - for (i = 0; i < 6; i++) - StandardAddressSeen[i] = false; - /* - Iterate over the MultiMaster PCI Host Adapters. For each enumerated host - adapter, determine whether its ISA Compatible I/O Port is enabled and if - so, whether it is assigned the Primary I/O Address. A host adapter that is - assigned the Primary I/O Address will always be the preferred boot device. - The MultiMaster BIOS will first recognize a host adapter at the Primary I/O - Address, then any other PCI host adapters, and finally any host adapters - located at the remaining standard ISA I/O Addresses. When a PCI host - adapter is found with its ISA Compatible I/O Port enabled, a command is - issued to disable the ISA Compatible I/O Port, and it is noted that the - particular standard ISA I/O Address need not be probed. - */ - PrimaryProbeInfo->IO_Address = 0; - while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC, - PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER, - PCI_Device)) != NULL) - { - BusLogic_HostAdapter_T *HostAdapter = PrototypeHostAdapter; - BusLogic_PCIHostAdapterInformation_T PCIHostAdapterInformation; - BusLogic_ModifyIOAddressRequest_T ModifyIOAddressRequest; - unsigned char Bus = PCI_Device->bus->number; - unsigned char Device = PCI_Device->devfn >> 3; - unsigned int IRQ_Channel; - unsigned long BaseAddress0; - unsigned long BaseAddress1; - BusLogic_IO_Address_T IO_Address; - BusLogic_PCI_Address_T PCI_Address; - - if (pci_enable_device(PCI_Device)) - continue; - - IRQ_Channel = PCI_Device->irq; - IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0); - PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1); - - if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) - { - BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " - "MultiMaster Host Adapter\n", NULL, BaseAddress0); - BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", - NULL, Bus, Device, IO_Address); - continue; - } - if (pci_resource_flags(PCI_Device,1) & IORESOURCE_IO) - { - BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " - "MultiMaster Host Adapter\n", NULL, BaseAddress1); - BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", - NULL, Bus, Device, PCI_Address); - continue; - } - if (IRQ_Channel == 0) - { - BusLogic_Error("BusLogic: IRQ Channel %d illegal for " - "MultiMaster Host Adapter\n", NULL, IRQ_Channel); - BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", - NULL, Bus, Device, IO_Address); - continue; - } - if (BusLogic_GlobalOptions.TraceProbe) - { - BusLogic_Notice("BusLogic: PCI MultiMaster Host Adapter " - "detected at\n", NULL); - BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " - "0x%X PCI Address 0x%X\n", NULL, - Bus, Device, IO_Address, PCI_Address); - } - /* - Issue the Inquire PCI Host Adapter Information command to determine - the ISA Compatible I/O Port. If the ISA Compatible I/O Port is - known and enabled, note that the particular Standard ISA I/O - Address should not be probed. - */ - HostAdapter->IO_Address = IO_Address; - BusLogic_InterruptReset(HostAdapter); - if (BusLogic_Command(HostAdapter, - BusLogic_InquirePCIHostAdapterInformation, - NULL, 0, &PCIHostAdapterInformation, - sizeof(PCIHostAdapterInformation)) - == sizeof(PCIHostAdapterInformation)) - { - if (PCIHostAdapterInformation.ISACompatibleIOPort < 6) - StandardAddressSeen[PCIHostAdapterInformation - .ISACompatibleIOPort] = true; - } - else PCIHostAdapterInformation.ISACompatibleIOPort = - BusLogic_IO_Disable; - /* - Issue the Modify I/O Address command to disable the ISA Compatible - I/O Port. - */ - ModifyIOAddressRequest = BusLogic_IO_Disable; - BusLogic_Command(HostAdapter, BusLogic_ModifyIOAddress, - &ModifyIOAddressRequest, - sizeof(ModifyIOAddressRequest), NULL, 0); - /* - For the first MultiMaster Host Adapter enumerated, issue the Fetch - Host Adapter Local RAM command to read byte 45 of the AutoSCSI area, - for the setting of the "Use Bus And Device # For PCI Scanning Seq." - option. Issue the Inquire Board ID command since this option is - only valid for the BT-948/958/958D. - */ - if (!ForceBusDeviceScanningOrderChecked) - { - BusLogic_FetchHostAdapterLocalRAMRequest_T - FetchHostAdapterLocalRAMRequest; - BusLogic_AutoSCSIByte45_T AutoSCSIByte45; - BusLogic_BoardID_T BoardID; - FetchHostAdapterLocalRAMRequest.ByteOffset = - BusLogic_AutoSCSI_BaseOffset + 45; - FetchHostAdapterLocalRAMRequest.ByteCount = - sizeof(AutoSCSIByte45); - BusLogic_Command(HostAdapter, - BusLogic_FetchHostAdapterLocalRAM, - &FetchHostAdapterLocalRAMRequest, - sizeof(FetchHostAdapterLocalRAMRequest), - &AutoSCSIByte45, sizeof(AutoSCSIByte45)); - BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, - NULL, 0, &BoardID, sizeof(BoardID)); - if (BoardID.FirmwareVersion1stDigit == '5') - ForceBusDeviceScanningOrder = - AutoSCSIByte45.ForceBusDeviceScanningOrder; - ForceBusDeviceScanningOrderChecked = true; - } - /* - Determine whether this MultiMaster Host Adapter has its ISA - Compatible I/O Port enabled and is assigned the Primary I/O Address. - If it does, then it is the Primary MultiMaster Host Adapter and must - be recognized first. If it does not, then it is added to the list - for probing after any Primary MultiMaster Host Adapter is probed. - */ - if (PCIHostAdapterInformation.ISACompatibleIOPort == BusLogic_IO_330) - { - PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster; - PrimaryProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; - PrimaryProbeInfo->IO_Address = IO_Address; - PrimaryProbeInfo->PCI_Address = PCI_Address; - PrimaryProbeInfo->Bus = Bus; - PrimaryProbeInfo->Device = Device; - PrimaryProbeInfo->IRQ_Channel = IRQ_Channel; - PCIMultiMasterCount++; - } - else if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) - { - BusLogic_ProbeInfo_T *ProbeInfo = - &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; - ProbeInfo->HostAdapterType = BusLogic_MultiMaster; - ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; - ProbeInfo->IO_Address = IO_Address; - ProbeInfo->PCI_Address = PCI_Address; - ProbeInfo->Bus = Bus; - ProbeInfo->Device = Device; - ProbeInfo->IRQ_Channel = IRQ_Channel; - NonPrimaryPCIMultiMasterCount++; - PCIMultiMasterCount++; - } - else BusLogic_Warning("BusLogic: Too many Host Adapters " - "detected\n", NULL); - } - /* - If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option is ON - for the first enumerated MultiMaster Host Adapter, and if that host adapter - is a BT-948/958/958D, then the MultiMaster BIOS will recognize MultiMaster - Host Adapters in the order of increasing PCI Bus and Device Number. In - that case, sort the probe information into the same order the BIOS uses. - If this option is OFF, then the MultiMaster BIOS will recognize MultiMaster - Host Adapters in the order they are enumerated by the PCI BIOS, and hence - no sorting is necessary. - */ - if (ForceBusDeviceScanningOrder) - BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[ - NonPrimaryPCIMultiMasterIndex], - NonPrimaryPCIMultiMasterCount); - /* - If no PCI MultiMaster Host Adapter is assigned the Primary I/O Address, - then the Primary I/O Address must be probed explicitly before any PCI - host adapters are probed. - */ - if (!BusLogic_ProbeOptions.NoProbeISA) - if (PrimaryProbeInfo->IO_Address == 0 && - (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe330 - : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)) - { - PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster; - PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus; - PrimaryProbeInfo->IO_Address = 0x330; - } - /* - Append the list of standard BusLogic MultiMaster ISA I/O Addresses, - omitting the Primary I/O Address which has already been handled. - */ - if (!BusLogic_ProbeOptions.NoProbeISA) - { - if (!StandardAddressSeen[1] && - (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe334 - : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0)) - BusLogic_AppendProbeAddressISA(0x334); - if (!StandardAddressSeen[2] && - (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe230 - : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0)) - BusLogic_AppendProbeAddressISA(0x230); - if (!StandardAddressSeen[3] && - (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe234 - : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0)) - BusLogic_AppendProbeAddressISA(0x234); - if (!StandardAddressSeen[4] && - (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe130 - : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0)) - BusLogic_AppendProbeAddressISA(0x130); - if (!StandardAddressSeen[5] && - (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe134 - : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0)) - BusLogic_AppendProbeAddressISA(0x134); - } - /* - Iterate over the older non-compliant MultiMaster PCI Host Adapters, - noting the PCI bus location and assigned IRQ Channel. - */ - PCI_Device = NULL; - while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC, - PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC, - PCI_Device)) != NULL) - { - unsigned char Bus = PCI_Device->bus->number; - unsigned char Device = PCI_Device->devfn >> 3; - unsigned int IRQ_Channel = PCI_Device->irq; - BusLogic_IO_Address_T IO_Address = pci_resource_start(PCI_Device, 0); - - if (pci_enable_device(PCI_Device)) - continue; - - if (IO_Address == 0 || IRQ_Channel == 0) continue; - for (i = 0; i < BusLogic_ProbeInfoCount; i++) - { - BusLogic_ProbeInfo_T *ProbeInfo = &BusLogic_ProbeInfoList[i]; - if (ProbeInfo->IO_Address == IO_Address && - ProbeInfo->HostAdapterType == BusLogic_MultiMaster) - { - ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; - ProbeInfo->PCI_Address = 0; - ProbeInfo->Bus = Bus; - ProbeInfo->Device = Device; - ProbeInfo->IRQ_Channel = IRQ_Channel; - break; - } - } - } - return PCIMultiMasterCount; -} - - -/* - BusLogic_InitializeFlashPointProbeInfo initializes the list of I/O Address - and Bus Probe Information to be checked for potential BusLogic FlashPoint - Host Adapters by interrogating the PCI Configuration Space. It returns the - number of FlashPoint Host Adapters found. -*/ - -static int BusLogic_InitializeFlashPointProbeInfo(BusLogic_HostAdapter_T - *PrototypeHostAdapter) -{ - int FlashPointIndex = BusLogic_ProbeInfoCount, FlashPointCount = 0; - PCI_Device_T *PCI_Device = NULL; - /* - Interrogate PCI Configuration Space for any FlashPoint Host Adapters. - */ - while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC, - PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT, - PCI_Device)) != NULL) - { - unsigned char Bus = PCI_Device->bus->number; - unsigned char Device = PCI_Device->devfn >> 3; - unsigned int IRQ_Channel = PCI_Device->irq; - unsigned long BaseAddress0 = pci_resource_start(PCI_Device, 0); - unsigned long BaseAddress1 = pci_resource_start(PCI_Device, 1); - BusLogic_IO_Address_T IO_Address = BaseAddress0; - BusLogic_PCI_Address_T PCI_Address = BaseAddress1; - - if (pci_enable_device(PCI_Device)) - continue; - -#ifndef CONFIG_SCSI_OMIT_FLASHPOINT - if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) - { - BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " - "FlashPoint Host Adapter\n", NULL, BaseAddress0); - BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", - NULL, Bus, Device, IO_Address); - continue; - } - if (pci_resource_flags(PCI_Device, 1) & IORESOURCE_IO) - { - BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " - "FlashPoint Host Adapter\n", NULL, BaseAddress1); - BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", - NULL, Bus, Device, PCI_Address); - continue; - } - if (IRQ_Channel == 0) - { - BusLogic_Error("BusLogic: IRQ Channel %d illegal for " - "FlashPoint Host Adapter\n", NULL, IRQ_Channel); - BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", - NULL, Bus, Device, IO_Address); - continue; - } - if (BusLogic_GlobalOptions.TraceProbe) - { - BusLogic_Notice("BusLogic: FlashPoint Host Adapter " - "detected at\n", NULL); - BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " - "0x%X PCI Address 0x%X\n", NULL, - Bus, Device, IO_Address, PCI_Address); - } - if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) - { - BusLogic_ProbeInfo_T *ProbeInfo = - &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; - ProbeInfo->HostAdapterType = BusLogic_FlashPoint; - ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; - ProbeInfo->IO_Address = IO_Address; - ProbeInfo->PCI_Address = PCI_Address; - ProbeInfo->Bus = Bus; - ProbeInfo->Device = Device; - ProbeInfo->IRQ_Channel = IRQ_Channel; - FlashPointCount++; - } - else BusLogic_Warning("BusLogic: Too many Host Adapters " - "detected\n", NULL); -#else - BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " - "PCI Bus %d Device %d\n", NULL, Bus, Device); - BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, irq %d, " - "but FlashPoint\n", NULL, IO_Address, PCI_Address, IRQ_Channel); - BusLogic_Error("BusLogic: support was omitted in this kernel " - "configuration.\n", NULL); -#endif - } - /* - The FlashPoint BIOS will scan for FlashPoint Host Adapters in the order of - increasing PCI Bus and Device Number, so sort the probe information into - the same order the BIOS uses. - */ - BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[FlashPointIndex], - FlashPointCount); - return FlashPointCount; -} - - -/* - BusLogic_InitializeProbeInfoList initializes the list of I/O Address and Bus - Probe Information to be checked for potential BusLogic SCSI Host Adapters by - interrogating the PCI Configuration Space on PCI machines as well as from the - list of standard BusLogic MultiMaster ISA I/O Addresses. By default, if both - FlashPoint and PCI MultiMaster Host Adapters are present, this driver will - probe for FlashPoint Host Adapters first unless the BIOS primary disk is - controlled by the first PCI MultiMaster Host Adapter, in which case - MultiMaster Host Adapters will be probed first. The BusLogic Driver Options - specifications "MultiMasterFirst" and "FlashPointFirst" can be used to force - a particular probe order. -*/ - -static void BusLogic_InitializeProbeInfoList(BusLogic_HostAdapter_T - *PrototypeHostAdapter) -{ - /* - If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint - Host Adapters; otherwise, default to the standard ISA MultiMaster probe. - */ - if (!BusLogic_ProbeOptions.NoProbePCI && pci_present()) - { - if (BusLogic_ProbeOptions.MultiMasterFirst) - { - BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter); - BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter); - } - else if (BusLogic_ProbeOptions.FlashPointFirst) - { - BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter); - BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter); - } - else - { - int FlashPointCount = - BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter); - int PCIMultiMasterCount = - BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter); - if (FlashPointCount > 0 && PCIMultiMasterCount > 0) - { - BusLogic_ProbeInfo_T *ProbeInfo = - &BusLogic_ProbeInfoList[FlashPointCount]; - BusLogic_HostAdapter_T *HostAdapter = PrototypeHostAdapter; - BusLogic_FetchHostAdapterLocalRAMRequest_T - FetchHostAdapterLocalRAMRequest; - BusLogic_BIOSDriveMapByte_T Drive0MapByte; - while (ProbeInfo->HostAdapterBusType != BusLogic_PCI_Bus) - ProbeInfo++; - HostAdapter->IO_Address = ProbeInfo->IO_Address; - FetchHostAdapterLocalRAMRequest.ByteOffset = - BusLogic_BIOS_BaseOffset + BusLogic_BIOS_DriveMapOffset + 0; - FetchHostAdapterLocalRAMRequest.ByteCount = - sizeof(Drive0MapByte); - BusLogic_Command(HostAdapter, - BusLogic_FetchHostAdapterLocalRAM, - &FetchHostAdapterLocalRAMRequest, - sizeof(FetchHostAdapterLocalRAMRequest), - &Drive0MapByte, sizeof(Drive0MapByte)); - /* - If the Map Byte for BIOS Drive 0 indicates that BIOS Drive 0 - is controlled by this PCI MultiMaster Host Adapter, then - reverse the probe order so that MultiMaster Host Adapters are - probed before FlashPoint Host Adapters. - */ - if (Drive0MapByte.DiskGeometry != - BusLogic_BIOS_Disk_Not_Installed) - { - BusLogic_ProbeInfo_T - SavedProbeInfo[BusLogic_MaxHostAdapters]; - int MultiMasterCount = - BusLogic_ProbeInfoCount - FlashPointCount; - memcpy(SavedProbeInfo, - BusLogic_ProbeInfoList, - BusLogic_ProbeInfoCount - * sizeof(BusLogic_ProbeInfo_T)); - memcpy(&BusLogic_ProbeInfoList[0], - &SavedProbeInfo[FlashPointCount], - MultiMasterCount * sizeof(BusLogic_ProbeInfo_T)); - memcpy(&BusLogic_ProbeInfoList[MultiMasterCount], - &SavedProbeInfo[0], - FlashPointCount * sizeof(BusLogic_ProbeInfo_T)); - } - } - } - } - else BusLogic_InitializeProbeInfoListISA(PrototypeHostAdapter); -} - - -#endif /* CONFIG_PCI */ - - -/* - BusLogic_Failure prints a standardized error message, and then returns false. -*/ - -static boolean BusLogic_Failure(BusLogic_HostAdapter_T *HostAdapter, - char *ErrorMessage) -{ - BusLogic_AnnounceDriver(HostAdapter); - if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus) - { - BusLogic_Error("While configuring BusLogic PCI Host Adapter at\n", - HostAdapter); - BusLogic_Error("Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n", - HostAdapter, HostAdapter->Bus, HostAdapter->Device, - HostAdapter->IO_Address, HostAdapter->PCI_Address); - } - else BusLogic_Error("While configuring BusLogic Host Adapter at " - "I/O Address 0x%X:\n", HostAdapter, - HostAdapter->IO_Address); - BusLogic_Error("%s FAILED - DETACHING\n", HostAdapter, ErrorMessage); - if (BusLogic_CommandFailureReason != NULL) - BusLogic_Error("ADDITIONAL FAILURE INFO - %s\n", HostAdapter, - BusLogic_CommandFailureReason); - return false; -} - - -/* - BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter. -*/ - -static boolean BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *HostAdapter) -{ - BusLogic_StatusRegister_T StatusRegister; - BusLogic_InterruptRegister_T InterruptRegister; - BusLogic_GeometryRegister_T GeometryRegister; - /* - FlashPoint Host Adapters are Probed by the FlashPoint SCCB Manager. - */ - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) - { - FlashPoint_Info_T *FlashPointInfo = &HostAdapter->FlashPointInfo; - FlashPointInfo->BaseAddress = - (BusLogic_Base_Address_T) HostAdapter->IO_Address; - FlashPointInfo->IRQ_Channel = HostAdapter->IRQ_Channel; - FlashPointInfo->Present = false; - if (!(FlashPoint_ProbeHostAdapter(FlashPointInfo) == 0 && - FlashPointInfo->Present)) - { - BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " - "PCI Bus %d Device %d\n", HostAdapter, - HostAdapter->Bus, HostAdapter->Device); - BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, " - "but FlashPoint\n", HostAdapter, - HostAdapter->IO_Address, HostAdapter->PCI_Address); - BusLogic_Error("BusLogic: Probe Function failed to validate it.\n", - HostAdapter); - return false; - } - if (BusLogic_GlobalOptions.TraceProbe) - BusLogic_Notice("BusLogic_Probe(0x%X): FlashPoint Found\n", - HostAdapter, HostAdapter->IO_Address); - /* - Indicate the Host Adapter Probe completed successfully. - */ - return true; - } - /* - Read the Status, Interrupt, and Geometry Registers to test if there are I/O - ports that respond, and to check the values to determine if they are from a - BusLogic Host Adapter. A nonexistent I/O port will return 0xFF, in which - case there is definitely no BusLogic Host Adapter at this base I/O Address. - The test here is a subset of that used by the BusLogic Host Adapter BIOS. - */ - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); - GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter); - if (BusLogic_GlobalOptions.TraceProbe) - BusLogic_Notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, " - "Geometry 0x%02X\n", HostAdapter, - HostAdapter->IO_Address, StatusRegister.All, - InterruptRegister.All, GeometryRegister.All); - if (StatusRegister.All == 0 || - StatusRegister.Bits.DiagnosticActive || - StatusRegister.Bits.CommandParameterRegisterBusy || - StatusRegister.Bits.Reserved || - StatusRegister.Bits.CommandInvalid || - InterruptRegister.Bits.Reserved != 0) - return false; - /* - Check the undocumented Geometry Register to test if there is an I/O port - that responded. Adaptec Host Adapters do not implement the Geometry - Register, so this test helps serve to avoid incorrectly recognizing an - Adaptec 1542A or 1542B as a BusLogic. Unfortunately, the Adaptec 1542C - series does respond to the Geometry Register I/O port, but it will be - rejected later when the Inquire Extended Setup Information command is - issued in BusLogic_CheckHostAdapter. The AMI FastDisk Host Adapter is a - BusLogic clone that implements the same interface as earlier BusLogic - Host Adapters, including the undocumented commands, and is therefore - supported by this driver. However, the AMI FastDisk always returns 0x00 - upon reading the Geometry Register, so the extended translation option - should always be left disabled on the AMI FastDisk. - */ - if (GeometryRegister.All == 0xFF) return false; - /* - Indicate the Host Adapter Probe completed successfully. - */ - return true; -} - - -/* - BusLogic_HardwareResetHostAdapter issues a Hardware Reset to the Host Adapter - and waits for Host Adapter Diagnostics to complete. If HardReset is true, a - Hard Reset is performed which also initiates a SCSI Bus Reset. Otherwise, a - Soft Reset is performed which only resets the Host Adapter without forcing a - SCSI Bus Reset. -*/ - -static boolean BusLogic_HardwareResetHostAdapter(BusLogic_HostAdapter_T - *HostAdapter, - boolean HardReset) -{ - BusLogic_StatusRegister_T StatusRegister; - int TimeoutCounter; - /* - FlashPoint Host Adapters are Hard Reset by the FlashPoint SCCB Manager. - */ - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) - { - FlashPoint_Info_T *FlashPointInfo = &HostAdapter->FlashPointInfo; - FlashPointInfo->HostSoftReset = !HardReset; - FlashPointInfo->ReportDataUnderrun = true; - HostAdapter->CardHandle = - FlashPoint_HardwareResetHostAdapter(FlashPointInfo); - if (HostAdapter->CardHandle == FlashPoint_BadCardHandle) return false; - /* - Indicate the Host Adapter Hard Reset completed successfully. - */ - return true; - } - /* - Issue a Hard Reset or Soft Reset Command to the Host Adapter. The Host - Adapter should respond by setting Diagnostic Active in the Status Register. - */ - if (HardReset) - BusLogic_HardReset(HostAdapter); - else BusLogic_SoftReset(HostAdapter); - /* - Wait until Diagnostic Active is set in the Status Register. - */ - TimeoutCounter = 5*10000; - while (--TimeoutCounter >= 0) - { - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister.Bits.DiagnosticActive) break; - udelay(100); - } - if (BusLogic_GlobalOptions.TraceHardwareReset) - BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Active, " - "Status 0x%02X\n", HostAdapter, - HostAdapter->IO_Address, StatusRegister.All); - if (TimeoutCounter < 0) return false; - /* - Wait 100 microseconds to allow completion of any initial diagnostic - activity which might leave the contents of the Status Register - unpredictable. - */ - udelay(100); - /* - Wait until Diagnostic Active is reset in the Status Register. - */ - TimeoutCounter = 10*10000; - while (--TimeoutCounter >= 0) - { - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (!StatusRegister.Bits.DiagnosticActive) break; - udelay(100); - } - if (BusLogic_GlobalOptions.TraceHardwareReset) - BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Completed, " - "Status 0x%02X\n", HostAdapter, - HostAdapter->IO_Address, StatusRegister.All); - if (TimeoutCounter < 0) return false; - /* - Wait until at least one of the Diagnostic Failure, Host Adapter Ready, - or Data In Register Ready bits is set in the Status Register. - */ - TimeoutCounter = 10000; - while (--TimeoutCounter >= 0) - { - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister.Bits.DiagnosticFailure || - StatusRegister.Bits.HostAdapterReady || - StatusRegister.Bits.DataInRegisterReady) - break; - udelay(100); - } - if (BusLogic_GlobalOptions.TraceHardwareReset) - BusLogic_Notice("BusLogic_HardwareReset(0x%X): Host Adapter Ready, " - "Status 0x%02X\n", HostAdapter, - HostAdapter->IO_Address, StatusRegister.All); - if (TimeoutCounter < 0) return false; - /* - If Diagnostic Failure is set or Host Adapter Ready is reset, then an - error occurred during the Host Adapter diagnostics. If Data In Register - Ready is set, then there is an Error Code available. - */ - if (StatusRegister.Bits.DiagnosticFailure || - !StatusRegister.Bits.HostAdapterReady) - { - BusLogic_CommandFailureReason = NULL; - BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS"); - BusLogic_Error("HOST ADAPTER STATUS REGISTER = %02X\n", - HostAdapter, StatusRegister.All); - if (StatusRegister.Bits.DataInRegisterReady) - { - unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter); - BusLogic_Error("HOST ADAPTER ERROR CODE = %d\n", - HostAdapter, ErrorCode); - } - return false; - } - /* - Indicate the Host Adapter Hard Reset completed successfully. - */ - return true; -} - - -/* - BusLogic_CheckHostAdapter checks to be sure this really is a BusLogic - Host Adapter. -*/ - -static boolean BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter) -{ - BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation; - BusLogic_RequestedReplyLength_T RequestedReplyLength; - boolean Result = true; - /* - FlashPoint Host Adapters do not require this protection. - */ - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true; - /* - Issue the Inquire Extended Setup Information command. Only genuine - BusLogic Host Adapters and true clones support this command. Adaptec 1542C - series Host Adapters that respond to the Geometry Register I/O port will - fail this command. - */ - RequestedReplyLength = sizeof(ExtendedSetupInformation); - if (BusLogic_Command(HostAdapter, - BusLogic_InquireExtendedSetupInformation, - &RequestedReplyLength, - sizeof(RequestedReplyLength), - &ExtendedSetupInformation, - sizeof(ExtendedSetupInformation)) - != sizeof(ExtendedSetupInformation)) - Result = false; - /* - Provide tracing information if requested and return. - */ - if (BusLogic_GlobalOptions.TraceProbe) - BusLogic_Notice("BusLogic_Check(0x%X): MultiMaster %s\n", HostAdapter, - HostAdapter->IO_Address, (Result ? "Found" : "Not Found")); - return Result; -} - - -/* - BusLogic_ReadHostAdapterConfiguration reads the Configuration Information - from Host Adapter and initializes the Host Adapter structure. -*/ - -static boolean BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T - *HostAdapter) -{ - BusLogic_BoardID_T BoardID; - BusLogic_Configuration_T Configuration; - BusLogic_SetupInformation_T SetupInformation; - BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation; - BusLogic_HostAdapterModelNumber_T HostAdapterModelNumber; - BusLogic_FirmwareVersion3rdDigit_T FirmwareVersion3rdDigit; - BusLogic_FirmwareVersionLetter_T FirmwareVersionLetter; - BusLogic_PCIHostAdapterInformation_T PCIHostAdapterInformation; - BusLogic_FetchHostAdapterLocalRAMRequest_T FetchHostAdapterLocalRAMRequest; - BusLogic_AutoSCSIData_T AutoSCSIData; - BusLogic_GeometryRegister_T GeometryRegister; - BusLogic_RequestedReplyLength_T RequestedReplyLength; - unsigned char *TargetPointer, Character; - int TargetID, i; - /* - Configuration Information for FlashPoint Host Adapters is provided in the - FlashPoint_Info structure by the FlashPoint SCCB Manager's Probe Function. - Initialize fields in the Host Adapter structure from the FlashPoint_Info - structure. - */ - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) - { - FlashPoint_Info_T *FlashPointInfo = &HostAdapter->FlashPointInfo; - TargetPointer = HostAdapter->ModelName; - *TargetPointer++ = 'B'; - *TargetPointer++ = 'T'; - *TargetPointer++ = '-'; - for (i = 0; i < sizeof(FlashPointInfo->ModelNumber); i++) - *TargetPointer++ = FlashPointInfo->ModelNumber[i]; - *TargetPointer++ = '\0'; - strcpy(HostAdapter->FirmwareVersion, FlashPoint_FirmwareVersion); - HostAdapter->SCSI_ID = FlashPointInfo->SCSI_ID; - HostAdapter->ExtendedTranslationEnabled = - FlashPointInfo->ExtendedTranslationEnabled; - HostAdapter->ParityCheckingEnabled = - FlashPointInfo->ParityCheckingEnabled; - HostAdapter->BusResetEnabled = !FlashPointInfo->HostSoftReset; - HostAdapter->LevelSensitiveInterrupt = true; - HostAdapter->HostWideSCSI = FlashPointInfo->HostWideSCSI; - HostAdapter->HostDifferentialSCSI = false; - HostAdapter->HostSupportsSCAM = true; - HostAdapter->HostUltraSCSI = true; - HostAdapter->ExtendedLUNSupport = true; - HostAdapter->TerminationInfoValid = true; - HostAdapter->LowByteTerminated = FlashPointInfo->LowByteTerminated; - HostAdapter->HighByteTerminated = FlashPointInfo->HighByteTerminated; - HostAdapter->SCAM_Enabled = FlashPointInfo->SCAM_Enabled; - HostAdapter->SCAM_Level2 = FlashPointInfo->SCAM_Level2; - HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit; - HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8); - HostAdapter->MaxLogicalUnits = 32; - HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize; - HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize; - HostAdapter->DriverQueueDepth = 255; - HostAdapter->HostAdapterQueueDepth = HostAdapter->DriverQueueDepth; - HostAdapter->SynchronousPermitted = FlashPointInfo->SynchronousPermitted; - HostAdapter->FastPermitted = FlashPointInfo->FastPermitted; - HostAdapter->UltraPermitted = FlashPointInfo->UltraPermitted; - HostAdapter->WidePermitted = FlashPointInfo->WidePermitted; - HostAdapter->DisconnectPermitted = FlashPointInfo->DisconnectPermitted; - HostAdapter->TaggedQueuingPermitted = 0xFFFF; - goto Common; - } - /* - Issue the Inquire Board ID command. - */ - if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0, - &BoardID, sizeof(BoardID)) != sizeof(BoardID)) - return BusLogic_Failure(HostAdapter, "INQUIRE BOARD ID"); - /* - Issue the Inquire Configuration command. - */ - if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration, NULL, 0, - &Configuration, sizeof(Configuration)) - != sizeof(Configuration)) - return BusLogic_Failure(HostAdapter, "INQUIRE CONFIGURATION"); - /* - Issue the Inquire Setup Information command. - */ - RequestedReplyLength = sizeof(SetupInformation); - if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, - &RequestedReplyLength, sizeof(RequestedReplyLength), - &SetupInformation, sizeof(SetupInformation)) - != sizeof(SetupInformation)) - return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION"); - /* - Issue the Inquire Extended Setup Information command. - */ - RequestedReplyLength = sizeof(ExtendedSetupInformation); - if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation, - &RequestedReplyLength, sizeof(RequestedReplyLength), - &ExtendedSetupInformation, - sizeof(ExtendedSetupInformation)) - != sizeof(ExtendedSetupInformation)) - return BusLogic_Failure(HostAdapter, "INQUIRE EXTENDED SETUP INFORMATION"); - /* - Issue the Inquire Firmware Version 3rd Digit command. - */ - FirmwareVersion3rdDigit = '\0'; - if (BoardID.FirmwareVersion1stDigit > '0') - if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit, - NULL, 0, &FirmwareVersion3rdDigit, - sizeof(FirmwareVersion3rdDigit)) - != sizeof(FirmwareVersion3rdDigit)) - return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT"); - /* - Issue the Inquire Host Adapter Model Number command. - */ - if (ExtendedSetupInformation.BusType == 'A' && - BoardID.FirmwareVersion1stDigit == '2') - /* BusLogic BT-542B ISA 2.xx */ - strcpy(HostAdapterModelNumber, "542B"); - else if (ExtendedSetupInformation.BusType == 'E' && - BoardID.FirmwareVersion1stDigit == '2' && - (BoardID.FirmwareVersion2ndDigit <= '1' || - (BoardID.FirmwareVersion2ndDigit == '2' && - FirmwareVersion3rdDigit == '0'))) - /* BusLogic BT-742A EISA 2.1x or 2.20 */ - strcpy(HostAdapterModelNumber, "742A"); - else if (ExtendedSetupInformation.BusType == 'E' && - BoardID.FirmwareVersion1stDigit == '0') - /* AMI FastDisk EISA Series 441 0.x */ - strcpy(HostAdapterModelNumber, "747A"); - else - { - RequestedReplyLength = sizeof(HostAdapterModelNumber); - if (BusLogic_Command(HostAdapter, BusLogic_InquireHostAdapterModelNumber, - &RequestedReplyLength, sizeof(RequestedReplyLength), - &HostAdapterModelNumber, - sizeof(HostAdapterModelNumber)) - != sizeof(HostAdapterModelNumber)) - return BusLogic_Failure(HostAdapter, - "INQUIRE HOST ADAPTER MODEL NUMBER"); - } - /* - BusLogic MultiMaster Host Adapters can be identified by their model number - and the major version number of their firmware as follows: - - 5.xx BusLogic "W" Series Host Adapters: - BT-948/958/958D - 4.xx BusLogic "C" Series Host Adapters: - BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF - 3.xx BusLogic "S" Series Host Adapters: - BT-747S/747D/757S/757D/445S/545S/542D - BT-542B/742A (revision H) - 2.xx BusLogic "A" Series Host Adapters: - BT-542B/742A (revision G and below) - 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter - */ - /* - Save the Model Name and Host Adapter Name in the Host Adapter structure. - */ - TargetPointer = HostAdapter->ModelName; - *TargetPointer++ = 'B'; - *TargetPointer++ = 'T'; - *TargetPointer++ = '-'; - for (i = 0; i < sizeof(HostAdapterModelNumber); i++) - { - Character = HostAdapterModelNumber[i]; - if (Character == ' ' || Character == '\0') break; - *TargetPointer++ = Character; - } - *TargetPointer++ = '\0'; - /* - Save the Firmware Version in the Host Adapter structure. - */ - TargetPointer = HostAdapter->FirmwareVersion; - *TargetPointer++ = BoardID.FirmwareVersion1stDigit; - *TargetPointer++ = '.'; - *TargetPointer++ = BoardID.FirmwareVersion2ndDigit; - if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0') - *TargetPointer++ = FirmwareVersion3rdDigit; - *TargetPointer = '\0'; - /* - Issue the Inquire Firmware Version Letter command. - */ - if (strcmp(HostAdapter->FirmwareVersion, "3.3") >= 0) - { - if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersionLetter, - NULL, 0, &FirmwareVersionLetter, - sizeof(FirmwareVersionLetter)) - != sizeof(FirmwareVersionLetter)) - return BusLogic_Failure(HostAdapter, - "INQUIRE FIRMWARE VERSION LETTER"); - if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0') - *TargetPointer++ = FirmwareVersionLetter; - *TargetPointer = '\0'; - } - /* - Save the Host Adapter SCSI ID in the Host Adapter structure. - */ - HostAdapter->SCSI_ID = Configuration.HostAdapterID; - /* - Determine the Bus Type and save it in the Host Adapter structure, determine - and save the IRQ Channel if necessary, and determine and save the DMA - Channel for ISA Host Adapters. - */ - HostAdapter->HostAdapterBusType = - BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4']; - if (HostAdapter->IRQ_Channel == 0) - { - if (Configuration.IRQ_Channel9) - HostAdapter->IRQ_Channel = 9; - else if (Configuration.IRQ_Channel10) - HostAdapter->IRQ_Channel = 10; - else if (Configuration.IRQ_Channel11) - HostAdapter->IRQ_Channel = 11; - else if (Configuration.IRQ_Channel12) - HostAdapter->IRQ_Channel = 12; - else if (Configuration.IRQ_Channel14) - HostAdapter->IRQ_Channel = 14; - else if (Configuration.IRQ_Channel15) - HostAdapter->IRQ_Channel = 15; - } - if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus) - { - if (Configuration.DMA_Channel5) - HostAdapter->DMA_Channel = 5; - else if (Configuration.DMA_Channel6) - HostAdapter->DMA_Channel = 6; - else if (Configuration.DMA_Channel7) - HostAdapter->DMA_Channel = 7; - } - /* - Determine whether Extended Translation is enabled and save it in - the Host Adapter structure. - */ - GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter); - HostAdapter->ExtendedTranslationEnabled = - GeometryRegister.Bits.ExtendedTranslationEnabled; - /* - Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide - SCSI flag, Differential SCSI flag, SCAM Supported flag, and - Ultra SCSI flag in the Host Adapter structure. - */ - HostAdapter->HostAdapterScatterGatherLimit = - ExtendedSetupInformation.ScatterGatherLimit; - HostAdapter->DriverScatterGatherLimit = - HostAdapter->HostAdapterScatterGatherLimit; - if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit) - HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit; - if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt) - HostAdapter->LevelSensitiveInterrupt = true; - HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI; - HostAdapter->HostDifferentialSCSI = - ExtendedSetupInformation.HostDifferentialSCSI; - HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM; - HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI; - /* - Determine whether Extended LUN Format CCBs are supported and save the - information in the Host Adapter structure. - */ - if (HostAdapter->FirmwareVersion[0] == '5' || - (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI)) - HostAdapter->ExtendedLUNSupport = true; - /* - Issue the Inquire PCI Host Adapter Information command to read the - Termination Information from "W" series MultiMaster Host Adapters. - */ - if (HostAdapter->FirmwareVersion[0] == '5') - { - if (BusLogic_Command(HostAdapter, - BusLogic_InquirePCIHostAdapterInformation, - NULL, 0, &PCIHostAdapterInformation, - sizeof(PCIHostAdapterInformation)) - != sizeof(PCIHostAdapterInformation)) - return BusLogic_Failure(HostAdapter, - "INQUIRE PCI HOST ADAPTER INFORMATION"); - /* - Save the Termination Information in the Host Adapter structure. - */ - if (PCIHostAdapterInformation.GenericInfoValid) - { - HostAdapter->TerminationInfoValid = true; - HostAdapter->LowByteTerminated = - PCIHostAdapterInformation.LowByteTerminated; - HostAdapter->HighByteTerminated = - PCIHostAdapterInformation.HighByteTerminated; - } - } - /* - Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data - from "W" and "C" series MultiMaster Host Adapters. - */ - if (HostAdapter->FirmwareVersion[0] >= '4') - { - FetchHostAdapterLocalRAMRequest.ByteOffset = - BusLogic_AutoSCSI_BaseOffset; - FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData); - if (BusLogic_Command(HostAdapter, - BusLogic_FetchHostAdapterLocalRAM, - &FetchHostAdapterLocalRAMRequest, - sizeof(FetchHostAdapterLocalRAMRequest), - &AutoSCSIData, sizeof(AutoSCSIData)) - != sizeof(AutoSCSIData)) - return BusLogic_Failure(HostAdapter, "FETCH HOST ADAPTER LOCAL RAM"); - /* - Save the Parity Checking Enabled, Bus Reset Enabled, and Termination - Information in the Host Adapter structure. - */ - HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled; - HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled; - if (HostAdapter->FirmwareVersion[0] == '4') - { - HostAdapter->TerminationInfoValid = true; - HostAdapter->LowByteTerminated = AutoSCSIData.LowByteTerminated; - HostAdapter->HighByteTerminated = AutoSCSIData.HighByteTerminated; - } - /* - Save the Wide Permitted, Fast Permitted, Synchronous Permitted, - Disconnect Permitted, Ultra Permitted, and SCAM Information in the - Host Adapter structure. - */ - HostAdapter->WidePermitted = AutoSCSIData.WidePermitted; - HostAdapter->FastPermitted = AutoSCSIData.FastPermitted; - HostAdapter->SynchronousPermitted = - AutoSCSIData.SynchronousPermitted; - HostAdapter->DisconnectPermitted = - AutoSCSIData.DisconnectPermitted; - if (HostAdapter->HostUltraSCSI) - HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted; - if (HostAdapter->HostSupportsSCAM) - { - HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled; - HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2; - } - } - /* - Initialize fields in the Host Adapter structure for "S" and "A" series - MultiMaster Host Adapters. - */ - if (HostAdapter->FirmwareVersion[0] < '4') - { - if (SetupInformation.SynchronousInitiationEnabled) - { - HostAdapter->SynchronousPermitted = 0xFF; - if (HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus) - { - if (ExtendedSetupInformation.Misc.FastOnEISA) - HostAdapter->FastPermitted = 0xFF; - if (strcmp(HostAdapter->ModelName, "BT-757") == 0) - HostAdapter->WidePermitted = 0xFF; - } - } - HostAdapter->DisconnectPermitted = 0xFF; - HostAdapter->ParityCheckingEnabled = - SetupInformation.ParityCheckingEnabled; - HostAdapter->BusResetEnabled = true; - } - /* - Determine the maximum number of Target IDs and Logical Units supported by - this driver for Wide and Narrow Host Adapters. - */ - HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8); - HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8); - /* - Select appropriate values for the Mailbox Count, Driver Queue Depth, - Initial CCBs, and Incremental CCBs variables based on whether or not Strict - Round Robin Mode is supported. If Strict Round Robin Mode is supported, - then there is no performance degradation in using the maximum possible - number of Outgoing and Incoming Mailboxes and allowing the Tagged and - Untagged Queue Depths to determine the actual utilization. If Strict Round - Robin Mode is not supported, then the Host Adapter must scan all the - Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can - cause a substantial performance penalty. The host adapters actually have - room to store the following number of CCBs internally; that is, they can - internally queue and manage this many active commands on the SCSI bus - simultaneously. Performance measurements demonstrate that the Driver Queue - Depth should be set to the Mailbox Count, rather than the Host Adapter - Queue Depth (internal CCB capacity), as it is more efficient to have the - queued commands waiting in Outgoing Mailboxes if necessary than to block - the process in the higher levels of the SCSI Subsystem. - - 192 BT-948/958/958D - 100 BT-946C/956C/956CD/747C/757C/757CD/445C - 50 BT-545C/540CF - 30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A - */ - if (HostAdapter->FirmwareVersion[0] == '5') - HostAdapter->HostAdapterQueueDepth = 192; - else if (HostAdapter->FirmwareVersion[0] == '4') - HostAdapter->HostAdapterQueueDepth = - (HostAdapter->HostAdapterBusType != BusLogic_ISA_Bus ? 100 : 50); - else HostAdapter->HostAdapterQueueDepth = 30; - if (strcmp(HostAdapter->FirmwareVersion, "3.31") >= 0) - { - HostAdapter->StrictRoundRobinModeSupport = true; - HostAdapter->MailboxCount = BusLogic_MaxMailboxes; - } - else - { - HostAdapter->StrictRoundRobinModeSupport = false; - HostAdapter->MailboxCount = 32; - } - HostAdapter->DriverQueueDepth = HostAdapter->MailboxCount; - HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize; - HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize; - /* - Tagged Queuing support is available and operates properly on all "W" series - MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with - firmware version 4.22 and above, and on "S" series MultiMaster Host - Adapters with firmware version 3.35 and above. - */ - HostAdapter->TaggedQueuingPermitted = 0; - switch (HostAdapter->FirmwareVersion[0]) - { - case '5': - HostAdapter->TaggedQueuingPermitted = 0xFFFF; - break; - case '4': - if (strcmp(HostAdapter->FirmwareVersion, "4.22") >= 0) - HostAdapter->TaggedQueuingPermitted = 0xFFFF; - break; - case '3': - if (strcmp(HostAdapter->FirmwareVersion, "3.35") >= 0) - HostAdapter->TaggedQueuingPermitted = 0xFFFF; - break; - } - /* - Determine the Host Adapter BIOS Address if the BIOS is enabled and - save it in the Host Adapter structure. The BIOS is disabled if the - BIOS_Address is 0. - */ - HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12; - /* - ISA Host Adapters require Bounce Buffers if there is more than 16MB memory. - */ - if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus && - /*(void *) high_memory > (void *) MAX_DMA_ADDRESS*/ 1) - HostAdapter->BounceBuffersRequired = true; - /* - BusLogic BT-445S Host Adapters prior to board revision E have a hardware - bug whereby when the BIOS is enabled, transfers to/from the same address - range the BIOS occupies modulo 16MB are handled incorrectly. Only properly - functioning BT-445S Host Adapters have firmware version 3.37, so require - that ISA Bounce Buffers be used for the buggy BT-445S models if there is - more than 16MB memory. - */ - if (HostAdapter->BIOS_Address > 0 && - strcmp(HostAdapter->ModelName, "BT-445S") == 0 && - strcmp(HostAdapter->FirmwareVersion, "3.37") < 0 && - /*(void *) high_memory > (void *) MAX_DMA_ADDRESS*/ 1) - HostAdapter->BounceBuffersRequired = true; - /* - Initialize parameters common to MultiMaster and FlashPoint Host Adapters. - */ -Common: - /* - Initialize the Host Adapter Full Model Name from the Model Name. - */ - strcpy(HostAdapter->FullModelName, "BusLogic "); - strcat(HostAdapter->FullModelName, HostAdapter->ModelName); - /* - Select an appropriate value for the Tagged Queue Depth either from a - BusLogic Driver Options specification, or based on whether this Host - Adapter requires that ISA Bounce Buffers be used. The Tagged Queue Depth - is left at 0 for automatic determination in BusLogic_SelectQueueDepths. - Initialize the Untagged Queue Depth. - */ - for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) - { - unsigned char QueueDepth = 0; - if (HostAdapter->DriverOptions != NULL && - HostAdapter->DriverOptions->QueueDepth[TargetID] > 0) - QueueDepth = HostAdapter->DriverOptions->QueueDepth[TargetID]; - else if (HostAdapter->BounceBuffersRequired) - QueueDepth = BusLogic_TaggedQueueDepthBB; - HostAdapter->QueueDepth[TargetID] = QueueDepth; - } - if (HostAdapter->BounceBuffersRequired) - HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepthBB; - else HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepth; - if (HostAdapter->DriverOptions != NULL) - HostAdapter->CommonQueueDepth = - HostAdapter->DriverOptions->CommonQueueDepth; - if (HostAdapter->CommonQueueDepth > 0 && - HostAdapter->CommonQueueDepth < HostAdapter->UntaggedQueueDepth) - HostAdapter->UntaggedQueueDepth = HostAdapter->CommonQueueDepth; - /* - Tagged Queuing is only allowed if Disconnect/Reconnect is permitted. - Therefore, mask the Tagged Queuing Permitted Default bits with the - Disconnect/Reconnect Permitted bits. - */ - HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted; - /* - Combine the default Tagged Queuing Permitted bits with any BusLogic Driver - Options Tagged Queuing specification. - */ - if (HostAdapter->DriverOptions != NULL) - HostAdapter->TaggedQueuingPermitted = - (HostAdapter->DriverOptions->TaggedQueuingPermitted & - HostAdapter->DriverOptions->TaggedQueuingPermittedMask) | - (HostAdapter->TaggedQueuingPermitted & - ~HostAdapter->DriverOptions->TaggedQueuingPermittedMask); - /* - Select appropriate values for the Error Recovery Strategy array - either from a BusLogic Driver Options specification, or using - BusLogic_ErrorRecovery_Default. - */ - for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) - if (HostAdapter->DriverOptions != NULL) - HostAdapter->ErrorRecoveryStrategy[TargetID] = - HostAdapter->DriverOptions->ErrorRecoveryStrategy[TargetID]; - else HostAdapter->ErrorRecoveryStrategy[TargetID] = - BusLogic_ErrorRecovery_Default; - /* - Select an appropriate value for Bus Settle Time either from a BusLogic - Driver Options specification, or from BusLogic_DefaultBusSettleTime. - */ - if (HostAdapter->DriverOptions != NULL && - HostAdapter->DriverOptions->BusSettleTime > 0) - HostAdapter->BusSettleTime = HostAdapter->DriverOptions->BusSettleTime; - else HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime; - /* - Indicate reading the Host Adapter Configuration completed successfully. - */ - return true; -} - - -/* - BusLogic_ReportHostAdapterConfiguration reports the configuration of - Host Adapter. -*/ - -static boolean BusLogic_ReportHostAdapterConfiguration(BusLogic_HostAdapter_T - *HostAdapter) -{ - unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1; - unsigned short SynchronousPermitted, FastPermitted; - unsigned short UltraPermitted, WidePermitted; - unsigned short DisconnectPermitted, TaggedQueuingPermitted; - boolean CommonSynchronousNegotiation, CommonTaggedQueueDepth; - boolean CommonErrorRecovery; - char SynchronousString[BusLogic_MaxTargetDevices+1]; - char WideString[BusLogic_MaxTargetDevices+1]; - char DisconnectString[BusLogic_MaxTargetDevices+1]; - char TaggedQueuingString[BusLogic_MaxTargetDevices+1]; - char ErrorRecoveryString[BusLogic_MaxTargetDevices+1]; - char *SynchronousMessage = SynchronousString; - char *WideMessage = WideString; - char *DisconnectMessage = DisconnectString; - char *TaggedQueuingMessage = TaggedQueuingString; - char *ErrorRecoveryMessage = ErrorRecoveryString; - int TargetID; - BusLogic_Info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n", - HostAdapter, HostAdapter->ModelName, - BusLogic_HostAdapterBusNames[HostAdapter->HostAdapterBusType], - (HostAdapter->HostWideSCSI ? " Wide" : ""), - (HostAdapter->HostDifferentialSCSI ? " Differential" : ""), - (HostAdapter->HostUltraSCSI ? " Ultra" : "")); - BusLogic_Info(" Firmware Version: %s, I/O Address: 0x%X, " - "IRQ Channel: %d/%s\n", HostAdapter, - HostAdapter->FirmwareVersion, - HostAdapter->IO_Address, HostAdapter->IRQ_Channel, - (HostAdapter->LevelSensitiveInterrupt ? "Level" : "Edge")); - if (HostAdapter->HostAdapterBusType != BusLogic_PCI_Bus) - { - BusLogic_Info(" DMA Channel: ", HostAdapter); - if (HostAdapter->DMA_Channel > 0) - BusLogic_Info("%d, ", HostAdapter, HostAdapter->DMA_Channel); - else BusLogic_Info("None, ", HostAdapter); - if (HostAdapter->BIOS_Address > 0) - BusLogic_Info("BIOS Address: 0x%X, ", HostAdapter, - HostAdapter->BIOS_Address); - else BusLogic_Info("BIOS Address: None, ", HostAdapter); - } - else - { - BusLogic_Info(" PCI Bus: %d, Device: %d, Address: ", - HostAdapter, HostAdapter->Bus, HostAdapter->Device); - if (HostAdapter->PCI_Address > 0) - BusLogic_Info("0x%X, ", HostAdapter, HostAdapter->PCI_Address); - else BusLogic_Info("Unassigned, ", HostAdapter); - } - BusLogic_Info("Host Adapter SCSI ID: %d\n", HostAdapter, - HostAdapter->SCSI_ID); - BusLogic_Info(" Parity Checking: %s, Extended Translation: %s\n", - HostAdapter, - (HostAdapter->ParityCheckingEnabled - ? "Enabled" : "Disabled"), - (HostAdapter->ExtendedTranslationEnabled - ? "Enabled" : "Disabled")); - AllTargetsMask &= ~(1 << HostAdapter->SCSI_ID); - SynchronousPermitted = HostAdapter->SynchronousPermitted & AllTargetsMask; - FastPermitted = HostAdapter->FastPermitted & AllTargetsMask; - UltraPermitted = HostAdapter->UltraPermitted & AllTargetsMask; - if ((BusLogic_MultiMasterHostAdapterP(HostAdapter) && - (HostAdapter->FirmwareVersion[0] >= '4' || - HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)) || - BusLogic_FlashPointHostAdapterP(HostAdapter)) - { - CommonSynchronousNegotiation = false; - if (SynchronousPermitted == 0) - { - SynchronousMessage = "Disabled"; - CommonSynchronousNegotiation = true; - } - else if (SynchronousPermitted == AllTargetsMask) - { - if (FastPermitted == 0) - { - SynchronousMessage = "Slow"; - CommonSynchronousNegotiation = true; - } - else if (FastPermitted == AllTargetsMask) - { - if (UltraPermitted == 0) - { - SynchronousMessage = "Fast"; - CommonSynchronousNegotiation = true; - } - else if (UltraPermitted == AllTargetsMask) - { - SynchronousMessage = "Ultra"; - CommonSynchronousNegotiation = true; - } - } - } - if (!CommonSynchronousNegotiation) - { - for (TargetID = 0; - TargetID < HostAdapter->MaxTargetDevices; - TargetID++) - SynchronousString[TargetID] = - ((!(SynchronousPermitted & (1 << TargetID))) ? 'N' : - (!(FastPermitted & (1 << TargetID)) ? 'S' : - (!(UltraPermitted & (1 << TargetID)) ? 'F' : 'U'))); - SynchronousString[HostAdapter->SCSI_ID] = '#'; - SynchronousString[HostAdapter->MaxTargetDevices] = '\0'; - } - } - else SynchronousMessage = - (SynchronousPermitted == 0 ? "Disabled" : "Enabled"); - WidePermitted = HostAdapter->WidePermitted & AllTargetsMask; - if (WidePermitted == 0) - WideMessage = "Disabled"; - else if (WidePermitted == AllTargetsMask) - WideMessage = "Enabled"; - else - { - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - WideString[TargetID] = - ((WidePermitted & (1 << TargetID)) ? 'Y' : 'N'); - WideString[HostAdapter->SCSI_ID] = '#'; - WideString[HostAdapter->MaxTargetDevices] = '\0'; - } - DisconnectPermitted = HostAdapter->DisconnectPermitted & AllTargetsMask; - if (DisconnectPermitted == 0) - DisconnectMessage = "Disabled"; - else if (DisconnectPermitted == AllTargetsMask) - DisconnectMessage = "Enabled"; - else - { - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - DisconnectString[TargetID] = - ((DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N'); - DisconnectString[HostAdapter->SCSI_ID] = '#'; - DisconnectString[HostAdapter->MaxTargetDevices] = '\0'; - } - TaggedQueuingPermitted = - HostAdapter->TaggedQueuingPermitted & AllTargetsMask; - if (TaggedQueuingPermitted == 0) - TaggedQueuingMessage = "Disabled"; - else if (TaggedQueuingPermitted == AllTargetsMask) - TaggedQueuingMessage = "Enabled"; - else - { - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - TaggedQueuingString[TargetID] = - ((TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N'); - TaggedQueuingString[HostAdapter->SCSI_ID] = '#'; - TaggedQueuingString[HostAdapter->MaxTargetDevices] = '\0'; - } - BusLogic_Info(" Synchronous Negotiation: %s, Wide Negotiation: %s\n", - HostAdapter, SynchronousMessage, WideMessage); - BusLogic_Info(" Disconnect/Reconnect: %s, Tagged Queuing: %s\n", - HostAdapter, DisconnectMessage, TaggedQueuingMessage); - if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) - { - BusLogic_Info(" Scatter/Gather Limit: %d of %d segments, " - "Mailboxes: %d\n", HostAdapter, - HostAdapter->DriverScatterGatherLimit, - HostAdapter->HostAdapterScatterGatherLimit, - HostAdapter->MailboxCount); - BusLogic_Info(" Driver Queue Depth: %d, " - "Host Adapter Queue Depth: %d\n", - HostAdapter, HostAdapter->DriverQueueDepth, - HostAdapter->HostAdapterQueueDepth); - } - else BusLogic_Info(" Driver Queue Depth: %d, " - "Scatter/Gather Limit: %d segments\n", - HostAdapter, HostAdapter->DriverQueueDepth, - HostAdapter->DriverScatterGatherLimit); - BusLogic_Info(" Tagged Queue Depth: ", HostAdapter); - CommonTaggedQueueDepth = true; - for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - if (HostAdapter->QueueDepth[TargetID] != HostAdapter->QueueDepth[0]) - { - CommonTaggedQueueDepth = false; - break; - } - if (CommonTaggedQueueDepth) - { - if (HostAdapter->QueueDepth[0] > 0) - BusLogic_Info("%d", HostAdapter, HostAdapter->QueueDepth[0]); - else BusLogic_Info("Automatic", HostAdapter); - } - else BusLogic_Info("Individual", HostAdapter); - BusLogic_Info(", Untagged Queue Depth: %d\n", HostAdapter, - HostAdapter->UntaggedQueueDepth); - CommonErrorRecovery = true; - for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - if (HostAdapter->ErrorRecoveryStrategy[TargetID] != - HostAdapter->ErrorRecoveryStrategy[0]) - { - CommonErrorRecovery = false; - break; - } - if (CommonErrorRecovery) - ErrorRecoveryMessage = - BusLogic_ErrorRecoveryStrategyNames[ - HostAdapter->ErrorRecoveryStrategy[0]]; - else - { - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - ErrorRecoveryString[TargetID] = - BusLogic_ErrorRecoveryStrategyLetters[ - HostAdapter->ErrorRecoveryStrategy[TargetID]]; - ErrorRecoveryString[HostAdapter->SCSI_ID] = '#'; - ErrorRecoveryString[HostAdapter->MaxTargetDevices] = '\0'; - } - BusLogic_Info(" Error Recovery Strategy: %s, SCSI Bus Reset: %s\n", - HostAdapter, ErrorRecoveryMessage, - (HostAdapter->BusResetEnabled ? "Enabled" : "Disabled")); - if (HostAdapter->TerminationInfoValid) - { - if (HostAdapter->HostWideSCSI) - BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter, - (HostAdapter->LowByteTerminated - ? (HostAdapter->HighByteTerminated - ? "Both Enabled" : "Low Enabled") - : (HostAdapter->HighByteTerminated - ? "High Enabled" : "Both Disabled"))); - else BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter, - (HostAdapter->LowByteTerminated ? - "Enabled" : "Disabled")); - if (HostAdapter->HostSupportsSCAM) - BusLogic_Info(", SCAM: %s", HostAdapter, - (HostAdapter->SCAM_Enabled - ? (HostAdapter->SCAM_Level2 - ? "Enabled, Level 2" : "Enabled, Level 1") - : "Disabled")); - BusLogic_Info("\n", HostAdapter); - } - /* - Indicate reporting the Host Adapter configuration completed successfully. - */ - return true; -} - - -/* - BusLogic_AcquireResources acquires the system resources necessary to use - Host Adapter. -*/ - -static boolean BusLogic_AcquireResources(BusLogic_HostAdapter_T *HostAdapter) -{ - if (HostAdapter->IRQ_Channel == 0) - { - BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n", - HostAdapter); - return false; - } - /* - Acquire shared access to the IRQ Channel. - */ - if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler, - SA_SHIRQ, HostAdapter->FullModelName, HostAdapter) < 0) - { - BusLogic_Error("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n", - HostAdapter, HostAdapter->IRQ_Channel); - return false; - } - HostAdapter->IRQ_ChannelAcquired = true; - /* - Acquire exclusive access to the DMA Channel. - */ - if (HostAdapter->DMA_Channel > 0) - { -#if 0 /* XEN */ - if (request_dma(HostAdapter->DMA_Channel, - HostAdapter->FullModelName) < 0) - { - BusLogic_Error("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n", - HostAdapter, HostAdapter->DMA_Channel); - return false; - } -#endif - set_dma_mode(HostAdapter->DMA_Channel, DMA_MODE_CASCADE); - enable_dma(HostAdapter->DMA_Channel); - HostAdapter->DMA_ChannelAcquired = true; - } - /* - Indicate the System Resource Acquisition completed successfully, - */ - return true; -} - - -/* - BusLogic_ReleaseResources releases any system resources previously acquired - by BusLogic_AcquireResources. -*/ - -static void BusLogic_ReleaseResources(BusLogic_HostAdapter_T *HostAdapter) -{ - /* - Release shared access to the IRQ Channel. - */ - if (HostAdapter->IRQ_ChannelAcquired) - free_irq(HostAdapter->IRQ_Channel, HostAdapter); -#if 0 /* XEN */ - /* - Release exclusive access to the DMA Channel. - */ - if (HostAdapter->DMA_ChannelAcquired) - free_dma(HostAdapter->DMA_Channel); -#endif -} - - -/* - BusLogic_InitializeHostAdapter initializes Host Adapter. This is the only - function called during SCSI Host Adapter detection which modifies the state - of the Host Adapter from its initial power on or hard reset state. -*/ - -static boolean BusLogic_InitializeHostAdapter(BusLogic_HostAdapter_T - *HostAdapter) -{ - BusLogic_ExtendedMailboxRequest_T ExtendedMailboxRequest; - BusLogic_RoundRobinModeRequest_T RoundRobinModeRequest; - BusLogic_SetCCBFormatRequest_T SetCCBFormatRequest; - int TargetID; - /* - Initialize the pointers to the first and last CCBs that are queued for - completion processing. - */ - HostAdapter->FirstCompletedCCB = NULL; - HostAdapter->LastCompletedCCB = NULL; - /* - Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active, - Command Successful Flag, Active Commands, and Commands Since Reset - for each Target Device. - */ - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - { - HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL; - HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false; - HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false; - HostAdapter->ActiveCommands[TargetID] = 0; - HostAdapter->CommandsSinceReset[TargetID] = 0; - } - /* - FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes. - */ - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) goto Done; - /* - Initialize the Outgoing and Incoming Mailbox pointers. - */ - HostAdapter->FirstOutgoingMailbox = - (BusLogic_OutgoingMailbox_T *) HostAdapter->MailboxSpace; - HostAdapter->LastOutgoingMailbox = - HostAdapter->FirstOutgoingMailbox + HostAdapter->MailboxCount - 1; - HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox; - HostAdapter->FirstIncomingMailbox = - (BusLogic_IncomingMailbox_T *) (HostAdapter->LastOutgoingMailbox + 1); - HostAdapter->LastIncomingMailbox = - HostAdapter->FirstIncomingMailbox + HostAdapter->MailboxCount - 1; - HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox; - /* - Initialize the Outgoing and Incoming Mailbox structures. - */ - memset(HostAdapter->FirstOutgoingMailbox, 0, - HostAdapter->MailboxCount * sizeof(BusLogic_OutgoingMailbox_T)); - memset(HostAdapter->FirstIncomingMailbox, 0, - HostAdapter->MailboxCount * sizeof(BusLogic_IncomingMailbox_T)); - /* - Initialize the Host Adapter's Pointer to the Outgoing/Incoming Mailboxes. - */ - ExtendedMailboxRequest.MailboxCount = HostAdapter->MailboxCount; - ExtendedMailboxRequest.BaseMailboxAddress = - Virtual_to_Bus(HostAdapter->FirstOutgoingMailbox); - if (BusLogic_Command(HostAdapter, BusLogic_InitializeExtendedMailbox, - &ExtendedMailboxRequest, - sizeof(ExtendedMailboxRequest), NULL, 0) < 0) - return BusLogic_Failure(HostAdapter, "MAILBOX INITIALIZATION"); - /* - Enable Strict Round Robin Mode if supported by the Host Adapter. In - Strict Round Robin Mode, the Host Adapter only looks at the next Outgoing - Mailbox for each new command, rather than scanning through all the - Outgoing Mailboxes to find any that have new commands in them. Strict - Round Robin Mode is significantly more efficient. - */ - if (HostAdapter->StrictRoundRobinModeSupport) - { - RoundRobinModeRequest = BusLogic_StrictRoundRobinMode; - if (BusLogic_Command(HostAdapter, BusLogic_EnableStrictRoundRobinMode, - &RoundRobinModeRequest, - sizeof(RoundRobinModeRequest), NULL, 0) < 0) - return BusLogic_Failure(HostAdapter, "ENABLE STRICT ROUND ROBIN MODE"); - } - /* - For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB - Format command to allow 32 Logical Units per Target Device. - */ - if (HostAdapter->ExtendedLUNSupport) - { - SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB; - if (BusLogic_Command(HostAdapter, BusLogic_SetCCBFormat, - &SetCCBFormatRequest, sizeof(SetCCBFormatRequest), - NULL, 0) < 0) - return BusLogic_Failure(HostAdapter, "SET CCB FORMAT"); - } - /* - Announce Successful Initialization. - */ -Done: - if (!HostAdapter->HostAdapterInitialized) - { - BusLogic_Info("*** %s Initialized Successfully ***\n", - HostAdapter, HostAdapter->FullModelName); - BusLogic_Info("\n", HostAdapter); - } - else BusLogic_Warning("*** %s Initialized Successfully ***\n", - HostAdapter, HostAdapter->FullModelName); - HostAdapter->HostAdapterInitialized = true; - /* - Indicate the Host Adapter Initialization completed successfully. - */ - return true; -} - - -/* - BusLogic_TargetDeviceInquiry inquires about the Target Devices accessible - through Host Adapter. -*/ - -static boolean BusLogic_TargetDeviceInquiry(BusLogic_HostAdapter_T - *HostAdapter) -{ - BusLogic_InstalledDevices_T InstalledDevices; - BusLogic_InstalledDevices8_T InstalledDevicesID0to7; - BusLogic_SetupInformation_T SetupInformation; - BusLogic_SynchronousPeriod_T SynchronousPeriod; - BusLogic_RequestedReplyLength_T RequestedReplyLength; - int TargetID; - /* - Wait a few seconds between the Host Adapter Hard Reset which initiates - a SCSI Bus Reset and issuing any SCSI Commands. Some SCSI devices get - confused if they receive SCSI Commands too soon after a SCSI Bus Reset. - */ - BusLogic_Delay(HostAdapter->BusSettleTime); - /* - FlashPoint Host Adapters do not provide for Target Device Inquiry. - */ - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true; - /* - Inhibit the Target Device Inquiry if requested. - */ - if (HostAdapter->DriverOptions != NULL && - HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry) - return true; - /* - Issue the Inquire Target Devices command for host adapters with firmware - version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command - for older host adapters. This is necessary to force Synchronous Transfer - Negotiation so that the Inquire Setup Information and Inquire Synchronous - Period commands will return valid data. The Inquire Target Devices command - is preferable to Inquire Installed Devices ID 0 to 7 since it only probes - Logical Unit 0 of each Target Device. - */ - if (strcmp(HostAdapter->FirmwareVersion, "4.25") >= 0) - { - if (BusLogic_Command(HostAdapter, BusLogic_InquireTargetDevices, NULL, 0, - &InstalledDevices, sizeof(InstalledDevices)) - != sizeof(InstalledDevices)) - return BusLogic_Failure(HostAdapter, "INQUIRE TARGET DEVICES"); - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - HostAdapter->TargetFlags[TargetID].TargetExists = - (InstalledDevices & (1 << TargetID) ? true : false); - } - else - { - if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID0to7, - NULL, 0, &InstalledDevicesID0to7, - sizeof(InstalledDevicesID0to7)) - != sizeof(InstalledDevicesID0to7)) - return BusLogic_Failure(HostAdapter, - "INQUIRE INSTALLED DEVICES ID 0 TO 7"); - for (TargetID = 0; TargetID < 8; TargetID++) - HostAdapter->TargetFlags[TargetID].TargetExists = - (InstalledDevicesID0to7[TargetID] != 0 ? true : false); - } - /* - Issue the Inquire Setup Information command. - */ - RequestedReplyLength = sizeof(SetupInformation); - if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, - &RequestedReplyLength, sizeof(RequestedReplyLength), - &SetupInformation, sizeof(SetupInformation)) - != sizeof(SetupInformation)) - return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION"); - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - HostAdapter->SynchronousOffset[TargetID] = - (TargetID < 8 - ? SetupInformation.SynchronousValuesID0to7[TargetID].Offset - : SetupInformation.SynchronousValuesID8to15[TargetID-8].Offset); - if (strcmp(HostAdapter->FirmwareVersion, "5.06L") >= 0) - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - HostAdapter->TargetFlags[TargetID].WideTransfersActive = - (TargetID < 8 - ? (SetupInformation.WideTransfersActiveID0to7 & (1 << TargetID) - ? true : false) - : (SetupInformation.WideTransfersActiveID8to15 & (1 << (TargetID-8)) - ? true : false)); - /* - Issue the Inquire Synchronous Period command. - */ - if (HostAdapter->FirmwareVersion[0] >= '3') - { - RequestedReplyLength = sizeof(SynchronousPeriod); - if (BusLogic_Command(HostAdapter, BusLogic_InquireSynchronousPeriod, - &RequestedReplyLength, sizeof(RequestedReplyLength), - &SynchronousPeriod, sizeof(SynchronousPeriod)) - != sizeof(SynchronousPeriod)) - return BusLogic_Failure(HostAdapter, "INQUIRE SYNCHRONOUS PERIOD"); - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID]; - } - else - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - if (SetupInformation.SynchronousValuesID0to7[TargetID].Offset > 0) - HostAdapter->SynchronousPeriod[TargetID] = - 20 + 5 * SetupInformation.SynchronousValuesID0to7[TargetID] - .TransferPeriod; - /* - Indicate the Target Device Inquiry completed successfully. - */ - return true; -} - - -/* - BusLogic_ReportTargetDeviceInfo reports about the Target Devices accessible - through Host Adapter. -*/ - -static void BusLogic_ReportTargetDeviceInfo(BusLogic_HostAdapter_T - *HostAdapter) -{ - int TargetID; - /* - Inhibit the Target Device Inquiry and Reporting if requested. - */ - if (BusLogic_MultiMasterHostAdapterP(HostAdapter) && - HostAdapter->DriverOptions != NULL && - HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry) - return; - /* - Report on the Target Devices found. - */ - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - { - BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID]; - if (TargetFlags->TargetExists && !TargetFlags->TargetInfoReported) - { - int SynchronousTransferRate = 0; - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) - { - unsigned char WideTransfersActive; - FlashPoint_InquireTargetInfo( - HostAdapter->CardHandle, TargetID, - &HostAdapter->SynchronousPeriod[TargetID], - &HostAdapter->SynchronousOffset[TargetID], - &WideTransfersActive); - TargetFlags->WideTransfersActive = WideTransfersActive; - } - else if (TargetFlags->WideTransfersSupported && - (HostAdapter->WidePermitted & (1 << TargetID)) && - strcmp(HostAdapter->FirmwareVersion, "5.06L") < 0) - TargetFlags->WideTransfersActive = true; - if (HostAdapter->SynchronousPeriod[TargetID] > 0) - SynchronousTransferRate = - 100000 / HostAdapter->SynchronousPeriod[TargetID]; - if (TargetFlags->WideTransfersActive) - SynchronousTransferRate <<= 1; - if (SynchronousTransferRate >= 9950) - { - SynchronousTransferRate = (SynchronousTransferRate + 50) / 100; - BusLogic_Info("Target %d: Queue Depth %d, %sSynchronous at " - "%d.%01d MB/sec, offset %d\n", - HostAdapter, TargetID, - HostAdapter->QueueDepth[TargetID], - (TargetFlags->WideTransfersActive ? "Wide " : ""), - SynchronousTransferRate / 10, - SynchronousTransferRate % 10, - HostAdapter->SynchronousOffset[TargetID]); - } - else if (SynchronousTransferRate > 0) - { - SynchronousTransferRate = (SynchronousTransferRate + 5) / 10; - BusLogic_Info("Target %d: Queue Depth %d, %sSynchronous at " - "%d.%02d MB/sec, offset %d\n", - HostAdapter, TargetID, - HostAdapter->QueueDepth[TargetID], - (TargetFlags->WideTransfersActive ? "Wide " : ""), - SynchronousTransferRate / 100, - SynchronousTransferRate % 100, - HostAdapter->SynchronousOffset[TargetID]); - } - else BusLogic_Info("Target %d: Queue Depth %d, Asynchronous\n", - HostAdapter, TargetID, - HostAdapter->QueueDepth[TargetID]); - TargetFlags->TargetInfoReported = true; - } - } -} - - -/* - BusLogic_InitializeHostStructure initializes the fields in the SCSI Host - structure. The base, io_port, n_io_ports, irq, and dma_channel fields in the - SCSI Host structure are intentionally left uninitialized, as this driver - handles acquisition and release of these resources explicitly, as well as - ensuring exclusive access to the Host Adapter hardware and data structures - through explicit acquisition and release of the Host Adapter's Lock. -*/ - -static void BusLogic_InitializeHostStructure(BusLogic_HostAdapter_T - *HostAdapter, - SCSI_Host_T *Host) -{ - Host->max_id = HostAdapter->MaxTargetDevices; - Host->max_lun = HostAdapter->MaxLogicalUnits; - Host->max_channel = 0; - Host->unique_id = HostAdapter->IO_Address; - Host->this_id = HostAdapter->SCSI_ID; - Host->can_queue = HostAdapter->DriverQueueDepth; - Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit; - Host->unchecked_isa_dma = HostAdapter->BounceBuffersRequired; - Host->cmd_per_lun = HostAdapter->UntaggedQueueDepth; -} - - -/* - BusLogic_SelectQueueDepths selects Queue Depths for each Target Device based - on the Host Adapter's Total Queue Depth and the number, type, speed, and - capabilities of the Target Devices. When called for the last Host Adapter, - it reports on the Target Device Information for all BusLogic Host Adapters - since all the Target Devices have now been probed. -*/ - -static void BusLogic_SelectQueueDepths(SCSI_Host_T *Host, - SCSI_Device_T *DeviceList) -{ - BusLogic_HostAdapter_T *HostAdapter = - (BusLogic_HostAdapter_T *) Host->hostdata; - int TaggedDeviceCount = 0, AutomaticTaggedDeviceCount = 0; - int UntaggedDeviceCount = 0, AutomaticTaggedQueueDepth = 0; - int AllocatedQueueDepth = 0; - SCSI_Device_T *Device; - int TargetID; - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - if (HostAdapter->TargetFlags[TargetID].TargetExists) - { - int QueueDepth = HostAdapter->QueueDepth[TargetID]; - if (HostAdapter->TargetFlags[TargetID].TaggedQueuingSupported && - (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) - { - TaggedDeviceCount++; - if (QueueDepth == 0) AutomaticTaggedDeviceCount++; - } - else - { - UntaggedDeviceCount++; - if (QueueDepth == 0 || - QueueDepth > HostAdapter->UntaggedQueueDepth) - { - QueueDepth = HostAdapter->UntaggedQueueDepth; - HostAdapter->QueueDepth[TargetID] = QueueDepth; - } - } - AllocatedQueueDepth += QueueDepth; - if (QueueDepth == 1) - HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID); - } - HostAdapter->TargetDeviceCount = TaggedDeviceCount + UntaggedDeviceCount; - if (AutomaticTaggedDeviceCount > 0) - { - AutomaticTaggedQueueDepth = - (HostAdapter->HostAdapterQueueDepth - AllocatedQueueDepth) - / AutomaticTaggedDeviceCount; - if (AutomaticTaggedQueueDepth > BusLogic_MaxAutomaticTaggedQueueDepth) - AutomaticTaggedQueueDepth = BusLogic_MaxAutomaticTaggedQueueDepth; - if (AutomaticTaggedQueueDepth < BusLogic_MinAutomaticTaggedQueueDepth) - AutomaticTaggedQueueDepth = BusLogic_MinAutomaticTaggedQueueDepth; - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - if (HostAdapter->TargetFlags[TargetID].TargetExists && - HostAdapter->QueueDepth[TargetID] == 0) - { - AllocatedQueueDepth += AutomaticTaggedQueueDepth; - HostAdapter->QueueDepth[TargetID] = AutomaticTaggedQueueDepth; - } - } - for (Device = DeviceList; Device != NULL; Device = Device->next) - if (Device->host == Host) - Device->queue_depth = HostAdapter->QueueDepth[Device->id]; - /* Allocate an extra CCB for each Target Device for a Bus Device Reset. */ - AllocatedQueueDepth += HostAdapter->TargetDeviceCount; - if (AllocatedQueueDepth > HostAdapter->DriverQueueDepth) - AllocatedQueueDepth = HostAdapter->DriverQueueDepth; - BusLogic_CreateAdditionalCCBs(HostAdapter, - AllocatedQueueDepth - - HostAdapter->AllocatedCCBs, - false); - if (HostAdapter == BusLogic_LastRegisteredHostAdapter) - for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; - HostAdapter != NULL; - HostAdapter = HostAdapter->Next) - BusLogic_ReportTargetDeviceInfo(HostAdapter); -} - - -/* - BusLogic_DetectHostAdapter probes for BusLogic Host Adapters at the standard - I/O Addresses where they may be located, initializing, registering, and - reporting the configuration of each BusLogic Host Adapter it finds. It - returns the number of BusLogic Host Adapters successfully initialized and - registered. -*/ - -int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *HostTemplate) -{ - int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex; - BusLogic_HostAdapter_T *PrototypeHostAdapter; - if (BusLogic_ProbeOptions.NoProbe) return 0; - BusLogic_ProbeInfoList = (BusLogic_ProbeInfo_T *) - kmalloc(BusLogic_MaxHostAdapters * sizeof(BusLogic_ProbeInfo_T), - GFP_ATOMIC); - if (BusLogic_ProbeInfoList == NULL) - { - BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL); - return 0; - } - memset(BusLogic_ProbeInfoList, 0, - BusLogic_MaxHostAdapters * sizeof(BusLogic_ProbeInfo_T)); - PrototypeHostAdapter = (BusLogic_HostAdapter_T *) - kmalloc(sizeof(BusLogic_HostAdapter_T), GFP_ATOMIC); - if (PrototypeHostAdapter == NULL) - { - kfree(BusLogic_ProbeInfoList); - BusLogic_Error("BusLogic: Unable to allocate Prototype " - "Host Adapter\n", NULL); - return 0; - } - memset(PrototypeHostAdapter, 0, sizeof(BusLogic_HostAdapter_T)); -#ifdef MODULE - if (BusLogic != NULL) - BusLogic_Setup(BusLogic); -#endif - BusLogic_InitializeProbeInfoList(PrototypeHostAdapter); - for (ProbeIndex = 0; ProbeIndex < BusLogic_ProbeInfoCount; ProbeIndex++) - { - BusLogic_ProbeInfo_T *ProbeInfo = &BusLogic_ProbeInfoList[ProbeIndex]; - BusLogic_HostAdapter_T *HostAdapter = PrototypeHostAdapter; - SCSI_Host_T *Host; - if (ProbeInfo->IO_Address == 0) continue; - memset(HostAdapter, 0, sizeof(BusLogic_HostAdapter_T)); - HostAdapter->HostAdapterType = ProbeInfo->HostAdapterType; - HostAdapter->HostAdapterBusType = ProbeInfo->HostAdapterBusType; - HostAdapter->IO_Address = ProbeInfo->IO_Address; - HostAdapter->PCI_Address = ProbeInfo->PCI_Address; - HostAdapter->Bus = ProbeInfo->Bus; - HostAdapter->Device = ProbeInfo->Device; - HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel; - HostAdapter->AddressCount = - BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType]; - /* - Probe the Host Adapter. If unsuccessful, abort further initialization. - */ - if (!BusLogic_ProbeHostAdapter(HostAdapter)) continue; - /* - Hard Reset the Host Adapter. If unsuccessful, abort further - initialization. - */ - if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true)) continue; - /* - Check the Host Adapter. If unsuccessful, abort further initialization. - */ - if (!BusLogic_CheckHostAdapter(HostAdapter)) continue; - /* - Initialize the Driver Options field if provided. - */ - if (DriverOptionsIndex < BusLogic_DriverOptionsCount) - HostAdapter->DriverOptions = - &BusLogic_DriverOptions[DriverOptionsIndex++]; - /* - Announce the Driver Version and Date, Author's Name, Copyright Notice, - and Electronic Mail Address. - */ - BusLogic_AnnounceDriver(HostAdapter); - /* - Register usage of the I/O Address range. From this point onward, any - failure will be assumed to be due to a problem with the Host Adapter, - rather than due to having mistakenly identified this port as belonging - to a BusLogic Host Adapter. The I/O Address range will not be - released, thereby preventing it from being incorrectly identified as - any other type of Host Adapter. - */ - request_region(HostAdapter->IO_Address, HostAdapter->AddressCount, - "BusLogic"); - /* - Register the SCSI Host structure. - */ - Host = scsi_register(HostTemplate, sizeof(BusLogic_HostAdapter_T)); - if(Host==NULL) - { - release_region(HostAdapter->IO_Address, HostAdapter->AddressCount); - continue; - } - HostAdapter = (BusLogic_HostAdapter_T *) Host->hostdata; - memcpy(HostAdapter, PrototypeHostAdapter, sizeof(BusLogic_HostAdapter_T)); - HostAdapter->SCSI_Host = Host; - HostAdapter->HostNumber = Host->host_no; - Host->select_queue_depths = BusLogic_SelectQueueDepths; - /* - Add Host Adapter to the end of the list of registered BusLogic - Host Adapters. - */ - BusLogic_RegisterHostAdapter(HostAdapter); - /* - Read the Host Adapter Configuration, Configure the Host Adapter, - Acquire the System Resources necessary to use the Host Adapter, then - Create the Initial CCBs, Initialize the Host Adapter, and finally - perform Target Device Inquiry. - */ - if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) && - BusLogic_ReportHostAdapterConfiguration(HostAdapter) && - BusLogic_AcquireResources(HostAdapter) && - BusLogic_CreateInitialCCBs(HostAdapter) && - BusLogic_InitializeHostAdapter(HostAdapter) && - BusLogic_TargetDeviceInquiry(HostAdapter)) - { - /* - Initialization has been completed successfully. Release and - re-register usage of the I/O Address range so that the Model - Name of the Host Adapter will appear, and initialize the SCSI - Host structure. - */ - release_region(HostAdapter->IO_Address, - HostAdapter->AddressCount); - request_region(HostAdapter->IO_Address, - HostAdapter->AddressCount, - HostAdapter->FullModelName); - BusLogic_InitializeHostStructure(HostAdapter, Host); - BusLogicHostAdapterCount++; - } - else - { - /* - An error occurred during Host Adapter Configuration Querying, Host - Adapter Configuration, Resource Acquisition, CCB Creation, Host - Adapter Initialization, or Target Device Inquiry, so remove Host - Adapter from the list of registered BusLogic Host Adapters, destroy - the CCBs, Release the System Resources, and Unregister the SCSI - Host. - */ - BusLogic_DestroyCCBs(HostAdapter); - BusLogic_ReleaseResources(HostAdapter); - BusLogic_UnregisterHostAdapter(HostAdapter); - scsi_unregister(Host); - } - } - kfree(PrototypeHostAdapter); - kfree(BusLogic_ProbeInfoList); - BusLogic_ProbeInfoList = NULL; - return BusLogicHostAdapterCount; -} - - -/* - BusLogic_ReleaseHostAdapter releases all resources previously acquired to - support a specific Host Adapter, including the I/O Address range, and - unregisters the BusLogic Host Adapter. -*/ - -int BusLogic_ReleaseHostAdapter(SCSI_Host_T *Host) -{ - BusLogic_HostAdapter_T *HostAdapter = - (BusLogic_HostAdapter_T *) Host->hostdata; - /* - FlashPoint Host Adapters must first be released by the FlashPoint - SCCB Manager. - */ - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) - FlashPoint_ReleaseHostAdapter(HostAdapter->CardHandle); - /* - Destroy the CCBs and release any system resources acquired to - support Host Adapter. - */ - BusLogic_DestroyCCBs(HostAdapter); - BusLogic_ReleaseResources(HostAdapter); - /* - Release usage of the I/O Address range. - */ - release_region(HostAdapter->IO_Address, HostAdapter->AddressCount); - /* - Remove Host Adapter from the list of registered BusLogic Host Adapters. - */ - BusLogic_UnregisterHostAdapter(HostAdapter); - return 0; -} - - -/* - BusLogic_QueueCompletedCCB queues CCB for completion processing. -*/ - -static void BusLogic_QueueCompletedCCB(BusLogic_CCB_T *CCB) -{ - BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter; - CCB->Status = BusLogic_CCB_Completed; - CCB->Next = NULL; - if (HostAdapter->FirstCompletedCCB == NULL) - { - HostAdapter->FirstCompletedCCB = CCB; - HostAdapter->LastCompletedCCB = CCB; - } - else - { - HostAdapter->LastCompletedCCB->Next = CCB; - HostAdapter->LastCompletedCCB = CCB; - } - HostAdapter->ActiveCommands[CCB->TargetID]--; -} - - -/* - BusLogic_ComputeResultCode computes a SCSI Subsystem Result Code from - the Host Adapter Status and Target Device Status. -*/ - -static int BusLogic_ComputeResultCode(BusLogic_HostAdapter_T *HostAdapter, - BusLogic_HostAdapterStatus_T - HostAdapterStatus, - BusLogic_TargetDeviceStatus_T - TargetDeviceStatus) -{ - int HostStatus; - switch (HostAdapterStatus) - { - case BusLogic_CommandCompletedNormally: - case BusLogic_LinkedCommandCompleted: - case BusLogic_LinkedCommandCompletedWithFlag: - HostStatus = DID_OK; - break; - case BusLogic_SCSISelectionTimeout: - HostStatus = DID_TIME_OUT; - break; - case BusLogic_InvalidOutgoingMailboxActionCode: - case BusLogic_InvalidCommandOperationCode: - case BusLogic_InvalidCommandParameter: - BusLogic_Warning("BusLogic Driver Protocol Error 0x%02X\n", - HostAdapter, HostAdapterStatus); - case BusLogic_DataUnderRun: - case BusLogic_DataOverRun: - case BusLogic_UnexpectedBusFree: - case BusLogic_LinkedCCBhasInvalidLUN: - case BusLogic_AutoRequestSenseFailed: - case BusLogic_TaggedQueuingMessageRejected: - case BusLogic_UnsupportedMessageReceived: - case BusLogic_HostAdapterHardwareFailed: - case BusLogic_TargetDeviceReconnectedImproperly: - case BusLogic_AbortQueueGenerated: - case BusLogic_HostAdapterSoftwareError: - case BusLogic_HostAdapterHardwareTimeoutError: - case BusLogic_SCSIParityErrorDetected: - HostStatus = DID_ERROR; - break; - case BusLogic_InvalidBusPhaseRequested: - case BusLogic_TargetFailedResponseToATN: - case BusLogic_HostAdapterAssertedRST: - case BusLogic_OtherDeviceAssertedRST: - case BusLogic_HostAdapterAssertedBusDeviceReset: - HostStatus = DID_RESET; - break; - default: - BusLogic_Warning("Unknown Host Adapter Status 0x%02X\n", - HostAdapter, HostAdapterStatus); - HostStatus = DID_ERROR; - break; - } - return (HostStatus << 16) | TargetDeviceStatus; -} - - -/* - BusLogic_ScanIncomingMailboxes scans the Incoming Mailboxes saving any - Incoming Mailbox entries for completion processing. -*/ - -static void BusLogic_ScanIncomingMailboxes(BusLogic_HostAdapter_T *HostAdapter) -{ - /* - Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving - any completed CCBs for further processing. It is essential that for each - CCB and SCSI Command issued, command completion processing is performed - exactly once. Therefore, only Incoming Mailboxes with completion code - Command Completed Without Error, Command Completed With Error, or Command - Aborted At Host Request are saved for completion processing. When an - Incoming Mailbox has a completion code of Aborted Command Not Found, the - CCB had already completed or been aborted before the current Abort request - was processed, and so completion processing has already occurred and no - further action should be taken. - */ - BusLogic_IncomingMailbox_T *NextIncomingMailbox = - HostAdapter->NextIncomingMailbox; - BusLogic_CompletionCode_T CompletionCode; - while ((CompletionCode = NextIncomingMailbox->CompletionCode) != - BusLogic_IncomingMailboxFree) - { - BusLogic_CCB_T *CCB = (BusLogic_CCB_T *) - Bus_to_Virtual(NextIncomingMailbox->CCB); - if (CompletionCode != BusLogic_AbortedCommandNotFound) - { - if (CCB->Status == BusLogic_CCB_Active || - CCB->Status == BusLogic_CCB_Reset) - { - /* - Save the Completion Code for this CCB and queue the CCB - for completion processing. - */ - CCB->CompletionCode = CompletionCode; - BusLogic_QueueCompletedCCB(CCB); - } - else - { - /* - If a CCB ever appears in an Incoming Mailbox and is not marked - as status Active or Reset, then there is most likely a bug in - the Host Adapter firmware. - */ - BusLogic_Warning("Illegal CCB #%ld status %d in " - "Incoming Mailbox\n", HostAdapter, - CCB->SerialNumber, CCB->Status); - } - } - NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree; - if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox) - NextIncomingMailbox = HostAdapter->FirstIncomingMailbox; - } - HostAdapter->NextIncomingMailbox = NextIncomingMailbox; -} - - -/* - BusLogic_ProcessCompletedCCBs iterates over the completed CCBs for Host - Adapter setting the SCSI Command Result Codes, deallocating the CCBs, and - calling the SCSI Subsystem Completion Routines. The Host Adapter's Lock - should already have been acquired by the caller. -*/ - -static void BusLogic_ProcessCompletedCCBs(BusLogic_HostAdapter_T *HostAdapter) -{ - if (HostAdapter->ProcessCompletedCCBsActive) return; - HostAdapter->ProcessCompletedCCBsActive = true; - while (HostAdapter->FirstCompletedCCB != NULL) - { - BusLogic_CCB_T *CCB = HostAdapter->FirstCompletedCCB; - SCSI_Command_T *Command = CCB->Command; - HostAdapter->FirstCompletedCCB = CCB->Next; - if (HostAdapter->FirstCompletedCCB == NULL) - HostAdapter->LastCompletedCCB = NULL; - /* - Process the Completed CCB. - */ - if (CCB->Opcode == BusLogic_BusDeviceReset) - { - int TargetID = CCB->TargetID; - BusLogic_Warning("Bus Device Reset CCB #%ld to Target " - "%d Completed\n", HostAdapter, - CCB->SerialNumber, TargetID); - BusLogic_IncrementErrorCounter( - &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted); - HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false; - HostAdapter->CommandsSinceReset[TargetID] = 0; - HostAdapter->LastResetCompleted[TargetID] = jiffies; - /* - Place CCB back on the Host Adapter's free list. - */ - BusLogic_DeallocateCCB(CCB); - /* - Bus Device Reset CCBs have the Command field non-NULL only when a - Bus Device Reset was requested for a Command that did not have a - currently active CCB in the Host Adapter (i.e., a Synchronous - Bus Device Reset), and hence would not have its Completion Routine - called otherwise. - */ - while (Command != NULL) - { - SCSI_Command_T *NextCommand = Command->reset_chain; - Command->reset_chain = NULL; - Command->result = DID_RESET << 16; - Command->scsi_done(Command); - Command = NextCommand; - } - /* - Iterate over the CCBs for this Host Adapter performing completion - processing for any CCBs marked as Reset for this Target. - */ - for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) - if (CCB->Status == BusLogic_CCB_Reset && CCB->TargetID == TargetID) - { - Command = CCB->Command; - BusLogic_DeallocateCCB(CCB); - HostAdapter->ActiveCommands[TargetID]--; - Command->result = DID_RESET << 16; - Command->scsi_done(Command); - } - HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL; - } - else - { - /* - Translate the Completion Code, Host Adapter Status, and Target - Device Status into a SCSI Subsystem Result Code. - */ - switch (CCB->CompletionCode) - { - case BusLogic_IncomingMailboxFree: - case BusLogic_AbortedCommandNotFound: - case BusLogic_InvalidCCB: - BusLogic_Warning("CCB #%ld to Target %d Impossible State\n", - HostAdapter, CCB->SerialNumber, CCB->TargetID); - break; - case BusLogic_CommandCompletedWithoutError: - HostAdapter->TargetStatistics[CCB->TargetID] - .CommandsCompleted++; - HostAdapter->TargetFlags[CCB->TargetID] - .CommandSuccessfulFlag = true; - Command->result = DID_OK << 16; - break; - case BusLogic_CommandAbortedAtHostRequest: - BusLogic_Warning("CCB #%ld to Target %d Aborted\n", - HostAdapter, CCB->SerialNumber, CCB->TargetID); - BusLogic_IncrementErrorCounter( - &HostAdapter->TargetStatistics[CCB->TargetID] - .CommandAbortsCompleted); - Command->result = DID_ABORT << 16; - break; - case BusLogic_CommandCompletedWithError: - Command->result = - BusLogic_ComputeResultCode(HostAdapter, - CCB->HostAdapterStatus, - CCB->TargetDeviceStatus); - if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout) - { - HostAdapter->TargetStatistics[CCB->TargetID] - .CommandsCompleted++; - if (BusLogic_GlobalOptions.TraceErrors) - { - int i; - BusLogic_Notice("CCB #%ld Target %d: Result %X Host " - "Adapter Status %02X " - "Target Status %02X\n", - HostAdapter, CCB->SerialNumber, - CCB->TargetID, Command->result, - CCB->HostAdapterStatus, - CCB->TargetDeviceStatus); - BusLogic_Notice("CDB ", HostAdapter); - for (i = 0; i < CCB->CDB_Length; i++) - BusLogic_Notice(" %02X", HostAdapter, CCB->CDB[i]); - BusLogic_Notice("\n", HostAdapter); - BusLogic_Notice("Sense ", HostAdapter); - for (i = 0; i < CCB->SenseDataLength; i++) - BusLogic_Notice(" %02X", HostAdapter, - Command->sense_buffer[i]); - BusLogic_Notice("\n", HostAdapter); - } - } - break; - } - /* - When an INQUIRY command completes normally, save the - CmdQue (Tagged Queuing Supported) and WBus16 (16 Bit - Wide Data Transfers Supported) bits. - */ - if (CCB->CDB[0] == INQUIRY && CCB->CDB[1] == 0 && - CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally) - { - BusLogic_TargetFlags_T *TargetFlags = - &HostAdapter->TargetFlags[CCB->TargetID]; - SCSI_Inquiry_T *InquiryResult = - (SCSI_Inquiry_T *) Command->request_buffer; - TargetFlags->TargetExists = true; - TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue; - TargetFlags->WideTransfersSupported = InquiryResult->WBus16; - } - /* - Place CCB back on the Host Adapter's free list. - */ - BusLogic_DeallocateCCB(CCB); - /* - Call the SCSI Command Completion Routine. - */ - Command->scsi_done(Command); - } - } - HostAdapter->ProcessCompletedCCBsActive = false; -} - - -/* - BusLogic_InterruptHandler handles hardware interrupts from BusLogic Host - Adapters. -*/ - -static void BusLogic_InterruptHandler(int IRQ_Channel, - void *DeviceIdentifier, - Registers_T *InterruptRegisters) -{ - BusLogic_HostAdapter_T *HostAdapter = - (BusLogic_HostAdapter_T *) DeviceIdentifier; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Host Adapter. - */ - BusLogic_AcquireHostAdapterLockIH(HostAdapter, &ProcessorFlags); - /* - Handle Interrupts appropriately for each Host Adapter type. - */ - if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) - { - BusLogic_InterruptRegister_T InterruptRegister; - /* - Read the Host Adapter Interrupt Register. - */ - InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); - if (InterruptRegister.Bits.InterruptValid) - { - /* - Acknowledge the interrupt and reset the Host Adapter - Interrupt Register. - */ - BusLogic_InterruptReset(HostAdapter); - /* - Process valid External SCSI Bus Reset and Incoming Mailbox - Loaded Interrupts. Command Complete Interrupts are noted, - and Outgoing Mailbox Available Interrupts are ignored, as - they are never enabled. - */ - if (InterruptRegister.Bits.ExternalBusReset) - HostAdapter->HostAdapterExternalReset = true; - else if (InterruptRegister.Bits.IncomingMailboxLoaded) - BusLogic_ScanIncomingMailboxes(HostAdapter); - else if (InterruptRegister.Bits.CommandComplete) - HostAdapter->HostAdapterCommandCompleted = true; - } - } - else - { - /* - Check if there is a pending interrupt for this Host Adapter. - */ - if (FlashPoint_InterruptPending(HostAdapter->CardHandle)) - switch (FlashPoint_HandleInterrupt(HostAdapter->CardHandle)) - { - case FlashPoint_NormalInterrupt: - break; - case FlashPoint_ExternalBusReset: - HostAdapter->HostAdapterExternalReset = true; - break; - case FlashPoint_InternalError: - BusLogic_Warning("Internal FlashPoint Error detected" - " - Resetting Host Adapter\n", HostAdapter); - HostAdapter->HostAdapterInternalError = true; - break; - } - } - /* - Process any completed CCBs. - */ - if (HostAdapter->FirstCompletedCCB != NULL) - BusLogic_ProcessCompletedCCBs(HostAdapter); - /* - Reset the Host Adapter if requested. - */ - if (HostAdapter->HostAdapterExternalReset || - HostAdapter->HostAdapterInternalError) - { - BusLogic_ResetHostAdapter(HostAdapter, NULL, 0); - HostAdapter->HostAdapterExternalReset = false; - HostAdapter->HostAdapterInternalError = false; -#if 0 /* XEN */ - scsi_mark_host_reset(HostAdapter->SCSI_Host); -#endif - } - /* - Release exclusive access to Host Adapter. - */ - BusLogic_ReleaseHostAdapterLockIH(HostAdapter, &ProcessorFlags); -} - - -/* - BusLogic_WriteOutgoingMailbox places CCB and Action Code into an Outgoing - Mailbox for execution by Host Adapter. The Host Adapter's Lock should - already have been acquired by the caller. -*/ - -static boolean BusLogic_WriteOutgoingMailbox(BusLogic_HostAdapter_T - *HostAdapter, - BusLogic_ActionCode_T ActionCode, - BusLogic_CCB_T *CCB) -{ - BusLogic_OutgoingMailbox_T *NextOutgoingMailbox; - NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox; - if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree) - { - CCB->Status = BusLogic_CCB_Active; - /* - The CCB field must be written before the Action Code field since - the Host Adapter is operating asynchronously and the locking code - does not protect against simultaneous access by the Host Adapter. - */ - NextOutgoingMailbox->CCB = Virtual_to_Bus(CCB); - NextOutgoingMailbox->ActionCode = ActionCode; - BusLogic_StartMailboxCommand(HostAdapter); - if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox) - NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox; - HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox; - if (ActionCode == BusLogic_MailboxStartCommand) - { - HostAdapter->ActiveCommands[CCB->TargetID]++; - if (CCB->Opcode != BusLogic_BusDeviceReset) - HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++; - } - return true; - } - return false; -} - - -/* - BusLogic_QueueCommand creates a CCB for Command and places it into an - Outgoing Mailbox for execution by the associated Host Adapter. -*/ - -int BusLogic_QueueCommand(SCSI_Command_T *Command, - void (*CompletionRoutine)(SCSI_Command_T *)) -{ - BusLogic_HostAdapter_T *HostAdapter = - (BusLogic_HostAdapter_T *) Command->host->hostdata; - BusLogic_TargetFlags_T *TargetFlags = - &HostAdapter->TargetFlags[Command->target]; - BusLogic_TargetStatistics_T *TargetStatistics = - HostAdapter->TargetStatistics; - unsigned char *CDB = Command->cmnd; - int CDB_Length = Command->cmd_len; - int TargetID = Command->target; - int LogicalUnit = Command->lun; - void *BufferPointer = Command->request_buffer; - int BufferLength = Command->request_bufflen; - int SegmentCount = Command->use_sg; - ProcessorFlags_T ProcessorFlags; - BusLogic_CCB_T *CCB; - /* - SCSI REQUEST_SENSE commands will be executed automatically by the Host - Adapter for any errors, so they should not be executed explicitly unless - the Sense Data is zero indicating that no error occurred. - */ - if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0) - { - Command->result = DID_OK << 16; - CompletionRoutine(Command); - return 0; - } - /* - Acquire exclusive access to Host Adapter. - */ - BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags); - /* - Allocate a CCB from the Host Adapter's free list. In the unlikely event - that there are none available and memory allocation fails, wait 1 second - and try again. If that fails, the Host Adapter is probably hung so signal - an error as a Host Adapter Hard Reset should be initiated soon. - */ - CCB = BusLogic_AllocateCCB(HostAdapter); - if (CCB == NULL) - { - BusLogic_Delay(1); - CCB = BusLogic_AllocateCCB(HostAdapter); - if (CCB == NULL) - { - Command->result = DID_ERROR << 16; - CompletionRoutine(Command); - goto Done; - } - } - /* - Initialize the fields in the BusLogic Command Control Block (CCB). - */ - if (SegmentCount == 0) - { - CCB->Opcode = BusLogic_InitiatorCCB; - CCB->DataLength = BufferLength; - CCB->DataPointer = Virtual_to_Bus(BufferPointer); - } - else - { - SCSI_ScatterList_T *ScatterList = (SCSI_ScatterList_T *) BufferPointer; - int Segment; - CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather; - CCB->DataLength = SegmentCount * sizeof(BusLogic_ScatterGatherSegment_T); - if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) - CCB->DataPointer = Virtual_to_Bus(CCB->ScatterGatherList); - else CCB->DataPointer = Virtual_to_32Bit_Virtual(CCB->ScatterGatherList); - for (Segment = 0; Segment < SegmentCount; Segment++) - { - CCB->ScatterGatherList[Segment].SegmentByteCount = - ScatterList[Segment].length; - CCB->ScatterGatherList[Segment].SegmentDataPointer = - Virtual_to_Bus(ScatterList[Segment].address); - } - } - switch (CDB[0]) - { - case READ_6: - case READ_10: - CCB->DataDirection = BusLogic_DataInLengthChecked; - TargetStatistics[TargetID].ReadCommands++; - BusLogic_IncrementByteCounter( - &TargetStatistics[TargetID].TotalBytesRead, BufferLength); - BusLogic_IncrementSizeBucket( - TargetStatistics[TargetID].ReadCommandSizeBuckets, BufferLength); - break; - case WRITE_6: - case WRITE_10: - CCB->DataDirection = BusLogic_DataOutLengthChecked; - TargetStatistics[TargetID].WriteCommands++; - BusLogic_IncrementByteCounter( - &TargetStatistics[TargetID].TotalBytesWritten, BufferLength); - BusLogic_IncrementSizeBucket( - TargetStatistics[TargetID].WriteCommandSizeBuckets, BufferLength); - break; - default: - CCB->DataDirection = BusLogic_UncheckedDataTransfer; - break; - } - CCB->CDB_Length = CDB_Length; - CCB->SenseDataLength = sizeof(Command->sense_buffer); - CCB->HostAdapterStatus = 0; - CCB->TargetDeviceStatus = 0; - CCB->TargetID = TargetID; - CCB->LogicalUnit = LogicalUnit; - CCB->TagEnable = false; - CCB->LegacyTagEnable = false; - /* - BusLogic recommends that after a Reset the first couple of commands that - are sent to a Target Device be sent in a non Tagged Queue fashion so that - the Host Adapter and Target Device can establish Synchronous and Wide - Transfer before Queue Tag messages can interfere with the Synchronous and - Wide Negotiation messages. By waiting to enable Tagged Queuing until after - the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is - assured that after a Reset any pending commands are requeued before Tagged - Queuing is enabled and that the Tagged Queuing message will not occur while - the partition table is being printed. In addition, some devices do not - properly handle the transition from non-tagged to tagged commands, so it is - necessary to wait until there are no pending commands for a target device - before queuing tagged commands. - */ - if (HostAdapter->CommandsSinceReset[TargetID]++ >= - BusLogic_MaxTaggedQueueDepth && - !TargetFlags->TaggedQueuingActive && - HostAdapter->ActiveCommands[TargetID] == 0 && - TargetFlags->TaggedQueuingSupported && - (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) - { - TargetFlags->TaggedQueuingActive = true; - BusLogic_Notice("Tagged Queuing now active for Target %d\n", - HostAdapter, TargetID); - } - if (TargetFlags->TaggedQueuingActive) - { - BusLogic_QueueTag_T QueueTag = BusLogic_SimpleQueueTag; - /* - When using Tagged Queuing with Simple Queue Tags, it appears that disk - drive controllers do not guarantee that a queued command will not - remain in a disconnected state indefinitely if commands that read or - write nearer the head position continue to arrive without interruption. - Therefore, for each Target Device this driver keeps track of the last - time either the queue was empty or an Ordered Queue Tag was issued. If - more than 4 seconds (one fifth of the 20 second disk timeout) have - elapsed since this last sequence point, this command will be issued - with an Ordered Queue Tag rather than a Simple Queue Tag, which forces - the Target Device to complete all previously queued commands before - this command may be executed. - */ - if (HostAdapter->ActiveCommands[TargetID] == 0) - HostAdapter->LastSequencePoint[TargetID] = jiffies; - else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4*HZ) - { - HostAdapter->LastSequencePoint[TargetID] = jiffies; - QueueTag = BusLogic_OrderedQueueTag; - } - if (HostAdapter->ExtendedLUNSupport) - { - CCB->TagEnable = true; - CCB->QueueTag = QueueTag; - } - else - { - CCB->LegacyTagEnable = true; - CCB->LegacyQueueTag = QueueTag; - } - } - memcpy(CCB->CDB, CDB, CDB_Length); - CCB->SenseDataPointer = Virtual_to_Bus(&Command->sense_buffer); - CCB->Command = Command; - Command->scsi_done = CompletionRoutine; - if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) - { - /* - Place the CCB in an Outgoing Mailbox. The higher levels of the SCSI - Subsystem should not attempt to queue more commands than can be placed - in Outgoing Mailboxes, so there should always be one free. In the - unlikely event that there are none available, wait 1 second and try - again. If that fails, the Host Adapter is probably hung so signal an - error as a Host Adapter Hard Reset should be initiated soon. - */ - if (!BusLogic_WriteOutgoingMailbox( - HostAdapter, BusLogic_MailboxStartCommand, CCB)) - { - BusLogic_Warning("Unable to write Outgoing Mailbox - " - "Pausing for 1 second\n", HostAdapter); - BusLogic_Delay(1); - if (!BusLogic_WriteOutgoingMailbox( - HostAdapter, BusLogic_MailboxStartCommand, CCB)) - { - BusLogic_Warning("Still unable to write Outgoing Mailbox - " - "Host Adapter Dead?\n", HostAdapter); - BusLogic_DeallocateCCB(CCB); - Command->result = DID_ERROR << 16; - Command->scsi_done(Command); - } - } - } - else - { - /* - Call the FlashPoint SCCB Manager to start execution of the CCB. - */ - CCB->Status = BusLogic_CCB_Active; - HostAdapter->ActiveCommands[TargetID]++; - TargetStatistics[TargetID].CommandsAttempted++; - FlashPoint_StartCCB(HostAdapter->CardHandle, CCB); - /* - The Command may have already completed and BusLogic_QueueCompletedCCB - been called, or it may still be pending. - */ - if (CCB->Status == BusLogic_CCB_Completed) - BusLogic_ProcessCompletedCCBs(HostAdapter); - } - /* - Release exclusive access to Host Adapter. - */ -Done: - BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags); - return 0; -} - - -/* - BusLogic_AbortCommand aborts Command if possible. -*/ - -int BusLogic_AbortCommand(SCSI_Command_T *Command) -{ - BusLogic_HostAdapter_T *HostAdapter = - (BusLogic_HostAdapter_T *) Command->host->hostdata; - int TargetID = Command->target; - ProcessorFlags_T ProcessorFlags; - BusLogic_CCB_T *CCB; - int Result; - BusLogic_IncrementErrorCounter( - &HostAdapter->TargetStatistics[TargetID].CommandAbortsRequested); - /* - Acquire exclusive access to Host Adapter. - */ - BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags); - /* - If this Command has already completed, then no Abort is necessary. - */ - if (Command->serial_number != Command->serial_number_at_timeout) - { - BusLogic_Warning("Unable to Abort Command to Target %d - " - "Already Completed\n", HostAdapter, TargetID); - Result = SCSI_ABORT_NOT_RUNNING; - goto Done; - } - /* - Attempt to find an Active CCB for this Command. If no Active CCB for this - Command is found, then no Abort is necessary. - */ - for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) - if (CCB->Command == Command) break; - if (CCB == NULL) - { - BusLogic_Warning("Unable to Abort Command to Target %d - " - "No CCB Found\n", HostAdapter, TargetID); - Result = SCSI_ABORT_NOT_RUNNING; - goto Done; - } - else if (CCB->Status == BusLogic_CCB_Completed) - { - BusLogic_Warning("Unable to Abort Command to Target %d - " - "CCB Completed\n", HostAdapter, TargetID); - Result = SCSI_ABORT_NOT_RUNNING; - goto Done; - } - else if (CCB->Status == BusLogic_CCB_Reset) - { - BusLogic_Warning("Unable to Abort Command to Target %d - " - "CCB Reset\n", HostAdapter, TargetID); - Result = SCSI_ABORT_PENDING; - goto Done; - } - if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) - { - /* - Attempt to Abort this CCB. MultiMaster Firmware versions prior to 5.xx - do not generate Abort Tag messages, but only generate the non-tagged - Abort message. Since non-tagged commands are not sent by the Host - Adapter until the queue of outstanding tagged commands has completed, - and the Abort message is treated as a non-tagged command, it is - effectively impossible to abort commands when Tagged Queuing is active. - Firmware version 5.xx does generate Abort Tag messages, so it is - possible to abort commands when Tagged Queuing is active. - */ - if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive && - HostAdapter->FirmwareVersion[0] < '5') - { - BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " - "Abort Tag Not Supported\n", - HostAdapter, CCB->SerialNumber, TargetID); - Result = SCSI_ABORT_SNOOZE; - } - else if (BusLogic_WriteOutgoingMailbox( - HostAdapter, BusLogic_MailboxAbortCommand, CCB)) - { - BusLogic_Warning("Aborting CCB #%ld to Target %d\n", - HostAdapter, CCB->SerialNumber, TargetID); - BusLogic_IncrementErrorCounter( - &HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted); - Result = SCSI_ABORT_PENDING; - } - else - { - BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " - "No Outgoing Mailboxes\n", - HostAdapter, CCB->SerialNumber, TargetID); - Result = SCSI_ABORT_BUSY; - } - } - else - { - /* - Call the FlashPoint SCCB Manager to abort execution of the CCB. - */ - BusLogic_Warning("Aborting CCB #%ld to Target %d\n", - HostAdapter, CCB->SerialNumber, TargetID); - BusLogic_IncrementErrorCounter( - &HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted); - FlashPoint_AbortCCB(HostAdapter->CardHandle, CCB); - /* - The Abort may have already been completed and - BusLogic_QueueCompletedCCB been called, or it - may still be pending. - */ - Result = SCSI_ABORT_PENDING; - if (CCB->Status == BusLogic_CCB_Completed) - { - BusLogic_ProcessCompletedCCBs(HostAdapter); - Result = SCSI_ABORT_SUCCESS; - } - } - /* - Release exclusive access to Host Adapter. - */ -Done: - BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags); - return Result; -} - - -/* - BusLogic_ResetHostAdapter resets Host Adapter if possible, marking all - currently executing SCSI Commands as having been Reset. -*/ - -static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter, - SCSI_Command_T *Command, - unsigned int ResetFlags) -{ - ProcessorFlags_T ProcessorFlags; - BusLogic_CCB_T *CCB; - int TargetID, Result; - boolean HardReset; - if (HostAdapter->HostAdapterExternalReset) - { - BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets); - HardReset = false; - } - else if (HostAdapter->HostAdapterInternalError) - { - BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors); - HardReset = true; - } - else - { - BusLogic_IncrementErrorCounter( - &HostAdapter->TargetStatistics[Command->target] - .HostAdapterResetsRequested); - HardReset = true; - } - /* - Acquire exclusive access to Host Adapter. - */ - BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags); - /* - If this is an Asynchronous Reset and this Command has already completed, - then no Reset is necessary. - */ - if (ResetFlags & SCSI_RESET_ASYNCHRONOUS) - { - TargetID = Command->target; - if (Command->serial_number != Command->serial_number_at_timeout) - { - BusLogic_Warning("Unable to Reset Command to Target %d - " - "Already Completed or Reset\n", - HostAdapter, TargetID); - Result = SCSI_RESET_NOT_RUNNING; - goto Done; - } - for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) - if (CCB->Command == Command) break; - if (CCB == NULL) - { - BusLogic_Warning("Unable to Reset Command to Target %d - " - "No CCB Found\n", HostAdapter, TargetID); - Result = SCSI_RESET_NOT_RUNNING; - goto Done; - } - else if (CCB->Status == BusLogic_CCB_Completed) - { - BusLogic_Warning("Unable to Reset Command to Target %d - " - "CCB Completed\n", HostAdapter, TargetID); - Result = SCSI_RESET_NOT_RUNNING; - goto Done; - } - else if (CCB->Status == BusLogic_CCB_Reset && - HostAdapter->BusDeviceResetPendingCCB[TargetID] == NULL) - { - BusLogic_Warning("Unable to Reset Command to Target %d - " - "Reset Pending\n", HostAdapter, TargetID); - Result = SCSI_RESET_PENDING; - goto Done; - } - } - if (Command == NULL) - { - if (HostAdapter->HostAdapterInternalError) - BusLogic_Warning("Resetting %s due to Host Adapter Internal Error\n", - HostAdapter, HostAdapter->FullModelName); - else BusLogic_Warning("Resetting %s due to External SCSI Bus Reset\n", - HostAdapter, HostAdapter->FullModelName); - } - else - { - BusLogic_Warning("Resetting %s due to Target %d\n", HostAdapter, - HostAdapter->FullModelName, Command->target); - BusLogic_IncrementErrorCounter( - &HostAdapter->TargetStatistics[Command->target] - .HostAdapterResetsAttempted); - } - /* - Attempt to Reset and Reinitialize the Host Adapter. - */ - if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) && - BusLogic_InitializeHostAdapter(HostAdapter))) - { - BusLogic_Error("Resetting %s Failed\n", HostAdapter, - HostAdapter->FullModelName); - Result = SCSI_RESET_ERROR; - goto Done; - } - if (Command != NULL) - BusLogic_IncrementErrorCounter( - &HostAdapter->TargetStatistics[Command->target] - .HostAdapterResetsCompleted); - /* - Mark all currently executing CCBs as having been Reset. - */ - for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) - if (CCB->Status == BusLogic_CCB_Active) - CCB->Status = BusLogic_CCB_Reset; - /* - Wait a few seconds between the Host Adapter Hard Reset which initiates - a SCSI Bus Reset and issuing any SCSI Commands. Some SCSI devices get - confused if they receive SCSI Commands too soon after a SCSI Bus Reset. - Note that a timer interrupt may occur here, but all active CCBs have - already been marked Reset and so a reentrant call will return Pending. - */ - if (HardReset) - BusLogic_Delay(HostAdapter->BusSettleTime); - /* - If this is a Synchronous Reset, perform completion processing for - the Command being Reset. - */ - if (ResetFlags & SCSI_RESET_SYNCHRONOUS) - { - Command->result = DID_RESET << 16; - Command->scsi_done(Command); - } - /* - Perform completion processing for all CCBs marked as Reset. - */ - for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) - if (CCB->Status == BusLogic_CCB_Reset) - { - Command = CCB->Command; - BusLogic_DeallocateCCB(CCB); - while (Command != NULL) - { - SCSI_Command_T *NextCommand = Command->reset_chain; - Command->reset_chain = NULL; - Command->result = DID_RESET << 16; - Command->scsi_done(Command); - Command = NextCommand; - } - } - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - { - HostAdapter->LastResetAttempted[TargetID] = jiffies; - HostAdapter->LastResetCompleted[TargetID] = jiffies; - } - Result = SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET; - /* - Release exclusive access to Host Adapter. - */ -Done: - BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags); - return Result; -} - - -/* - BusLogic_SendBusDeviceReset sends a Bus Device Reset to the Target - Device associated with Command. -*/ - -static int BusLogic_SendBusDeviceReset(BusLogic_HostAdapter_T *HostAdapter, - SCSI_Command_T *Command, - unsigned int ResetFlags) -{ - int TargetID = Command->target; - BusLogic_CCB_T *CCB, *XCCB; - ProcessorFlags_T ProcessorFlags; - int Result = -1; - BusLogic_IncrementErrorCounter( - &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsRequested); - /* - Acquire exclusive access to Host Adapter. - */ - BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags); - /* - If this is an Asynchronous Reset and this Command has already completed, - then no Reset is necessary. - */ - if (ResetFlags & SCSI_RESET_ASYNCHRONOUS) - { - if (Command->serial_number != Command->serial_number_at_timeout) - { - BusLogic_Warning("Unable to Reset Command to Target %d - " - "Already Completed\n", HostAdapter, TargetID); - Result = SCSI_RESET_NOT_RUNNING; - goto Done; - } - for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) - if (CCB->Command == Command) break; - if (CCB == NULL) - { - BusLogic_Warning("Unable to Reset Command to Target %d - " - "No CCB Found\n", HostAdapter, TargetID); - Result = SCSI_RESET_NOT_RUNNING; - goto Done; - } - else if (CCB->Status == BusLogic_CCB_Completed) - { - BusLogic_Warning("Unable to Reset Command to Target %d - " - "CCB Completed\n", HostAdapter, TargetID); - Result = SCSI_RESET_NOT_RUNNING; - goto Done; - } - else if (CCB->Status == BusLogic_CCB_Reset) - { - BusLogic_Warning("Unable to Reset Command to Target %d - " - "Reset Pending\n", HostAdapter, TargetID); - Result = SCSI_RESET_PENDING; - goto Done; - } - else if (HostAdapter->BusDeviceResetPendingCCB[TargetID] != NULL) - { - BusLogic_Warning("Bus Device Reset already pending to Target %d\n", - HostAdapter, TargetID); - goto Done; - } - } - /* - If this is a Synchronous Reset and a Bus Device Reset is already pending - for this Target Device, do not send a second one. Add this Command to - the list of Commands for which completion processing must be performed - when the Bus Device Reset CCB completes. - */ - if (ResetFlags & SCSI_RESET_SYNCHRONOUS) - if ((CCB = HostAdapter->BusDeviceResetPendingCCB[TargetID]) != NULL) - { - Command->reset_chain = CCB->Command; - CCB->Command = Command; - BusLogic_Warning("Unable to Reset Command to Target %d - " - "Reset Pending\n", HostAdapter, TargetID); - Result = SCSI_RESET_PENDING; - goto Done; - } - if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) - { - /* - MultiMaster Firmware versions prior to 5.xx treat a Bus Device Reset as - a non-tagged command. Since non-tagged commands are not sent by the - Host Adapter until the queue of outstanding tagged commands has - completed, it is effectively impossible to send a Bus Device Reset - while there are tagged commands outstanding. Therefore, in that case a - full Host Adapter Hard Reset and SCSI Bus Reset must be done. - */ - if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive && - HostAdapter->ActiveCommands[TargetID] > 0 && - HostAdapter->FirmwareVersion[0] < '5') - goto Done; - } - /* - Allocate a CCB from the Host Adapter's free list. In the unlikely event - that there are none available and memory allocation fails, attempt a full - Host Adapter Hard Reset and SCSI Bus Reset. - */ - CCB = BusLogic_AllocateCCB(HostAdapter); - if (CCB == NULL) goto Done; - BusLogic_Warning("Sending Bus Device Reset CCB #%ld to Target %d\n", - HostAdapter, CCB->SerialNumber, TargetID); - CCB->Opcode = BusLogic_BusDeviceReset; - CCB->TargetID = TargetID; - /* - For Synchronous Resets, arrange for the interrupt handler to perform - completion processing for the Command being Reset. - */ - if (ResetFlags & SCSI_RESET_SYNCHRONOUS) - { - Command->reset_chain = NULL; - CCB->Command = Command; - } - if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) - { - /* - Attempt to write an Outgoing Mailbox with the Bus Device Reset CCB. - If sending a Bus Device Reset is impossible, attempt a full Host - Adapter Hard Reset and SCSI Bus Reset. - */ - if (!(BusLogic_WriteOutgoingMailbox( - HostAdapter, BusLogic_MailboxStartCommand, CCB))) - { - BusLogic_Warning("Unable to write Outgoing Mailbox for " - "Bus Device Reset\n", HostAdapter); - BusLogic_DeallocateCCB(CCB); - goto Done; - } - } - else - { - /* - Call the FlashPoint SCCB Manager to start execution of the CCB. - */ - CCB->Status = BusLogic_CCB_Active; - HostAdapter->ActiveCommands[TargetID]++; - FlashPoint_StartCCB(HostAdapter->CardHandle, CCB); - } - /* - If there is a currently executing CCB in the Host Adapter for this Command - (i.e. this is an Asynchronous Reset), then an Incoming Mailbox entry may be - made with a completion code of BusLogic_HostAdapterAssertedBusDeviceReset. - If there is no active CCB for this Command (i.e. this is a Synchronous - Reset), then the Bus Device Reset CCB's Command field will have been set - to the Command so that the interrupt for the completion of the Bus Device - Reset can call the Completion Routine for the Command. On successful - execution of a Bus Device Reset, older firmware versions did return the - pending CCBs with the appropriate completion code, but more recent firmware - versions only return the Bus Device Reset CCB itself. This driver handles - both cases by marking all the currently executing CCBs to this Target - Device as Reset. When the Bus Device Reset CCB is processed by the - interrupt handler, any remaining CCBs marked as Reset will have completion - processing performed. - */ - BusLogic_IncrementErrorCounter( - &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsAttempted); - HostAdapter->BusDeviceResetPendingCCB[TargetID] = CCB; - HostAdapter->LastResetAttempted[TargetID] = jiffies; - for (XCCB = HostAdapter->All_CCBs; XCCB != NULL; XCCB = XCCB->NextAll) - if (XCCB->Status == BusLogic_CCB_Active && XCCB->TargetID == TargetID) - XCCB->Status = BusLogic_CCB_Reset; - /* - FlashPoint Host Adapters may have already completed the Bus Device - Reset and BusLogic_QueueCompletedCCB been called, or it may still be - pending. - */ - Result = SCSI_RESET_PENDING; - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) - if (CCB->Status == BusLogic_CCB_Completed) - { - BusLogic_ProcessCompletedCCBs(HostAdapter); - Result = SCSI_RESET_SUCCESS; - } - /* - If a Bus Device Reset was not possible for some reason, force a full - Host Adapter Hard Reset and SCSI Bus Reset. - */ -Done: - if (Result < 0) - Result = BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags); - /* - Release exclusive access to Host Adapter. - */ - BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags); - return Result; -} - - -/* - BusLogic_ResetCommand takes appropriate action to reset Command. -*/ - -int BusLogic_ResetCommand(SCSI_Command_T *Command, unsigned int ResetFlags) -{ - BusLogic_HostAdapter_T *HostAdapter = - (BusLogic_HostAdapter_T *) Command->host->hostdata; - int TargetID = Command->target; - BusLogic_ErrorRecoveryStrategy_T - ErrorRecoveryStrategy = HostAdapter->ErrorRecoveryStrategy[TargetID]; - /* - Disable Tagged Queuing if it is active for this Target Device and if - it has been less than 10 minutes since the last reset occurred, or since - the system was initialized if no prior resets have occurred. - */ - if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive && - jiffies - HostAdapter->LastResetCompleted[TargetID] < 10*60*HZ) - { - HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID); - HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false; - BusLogic_Warning("Tagged Queuing now disabled for Target %d\n", - HostAdapter, TargetID); - } - switch (ErrorRecoveryStrategy) - { - case BusLogic_ErrorRecovery_Default: - if (ResetFlags & SCSI_RESET_SUGGEST_HOST_RESET) - return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags); - else if (ResetFlags & SCSI_RESET_SUGGEST_BUS_RESET) - return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags); - /* Fall through to Bus Device Reset case. */ - case BusLogic_ErrorRecovery_BusDeviceReset: - /* - The Bus Device Reset Error Recovery Strategy only graduates to a Hard - Reset when no commands have completed successfully since the last Bus - Device Reset and it has been at least 100 milliseconds. This prevents - a sequence of commands that all timeout together from immediately - forcing a Hard Reset before the Bus Device Reset has had a chance to - clear the error condition. - */ - if (HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag || - jiffies - HostAdapter->LastResetAttempted[TargetID] < HZ/10) - { - HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false; - return BusLogic_SendBusDeviceReset(HostAdapter, Command, ResetFlags); - } - /* Fall through to Hard Reset case. */ - case BusLogic_ErrorRecovery_HardReset: - return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags); - case BusLogic_ErrorRecovery_None: - BusLogic_Warning("Error Recovery for Target %d Suppressed\n", - HostAdapter, TargetID); - break; - } - return SCSI_RESET_PUNT; -} - - -#if 0 /* XEN */ -/* - BusLogic_BIOSDiskParameters returns the Heads/Sectors/Cylinders BIOS Disk - Parameters for Disk. The default disk geometry is 64 heads, 32 sectors, and - the appropriate number of cylinders so as not to exceed drive capacity. In - order for disks equal to or larger than 1 GB to be addressable by the BIOS - without exceeding the BIOS limitation of 1024 cylinders, Extended Translation - may be enabled in AutoSCSI on FlashPoint Host Adapters and on "W" and "C" - series MultiMaster Host Adapters, or by a dip switch setting on "S" and "A" - series MultiMaster Host Adapters. With Extended Translation enabled, drives - between 1 GB inclusive and 2 GB exclusive are given a disk geometry of 128 - heads and 32 sectors, and drives above 2 GB inclusive are given a disk - geometry of 255 heads and 63 sectors. However, if the BIOS detects that the - Extended Translation setting does not match the geometry in the partition - table, then the translation inferred from the partition table will be used by - the BIOS, and a warning may be displayed. -*/ - -int BusLogic_BIOSDiskParameters(SCSI_Disk_T *Disk, KernelDevice_T Device, - int *Parameters) -{ - BusLogic_HostAdapter_T *HostAdapter = - (BusLogic_HostAdapter_T *) Disk->device->host->hostdata; - BIOS_DiskParameters_T *DiskParameters = (BIOS_DiskParameters_T *) Parameters; - struct buffer_head *BufferHead; - if (HostAdapter->ExtendedTranslationEnabled && - Disk->capacity >= 2*1024*1024 /* 1 GB in 512 byte sectors */) - { - if (Disk->capacity >= 4*1024*1024 /* 2 GB in 512 byte sectors */) - { - DiskParameters->Heads = 255; - DiskParameters->Sectors = 63; - } - else - { - DiskParameters->Heads = 128; - DiskParameters->Sectors = 32; - } - } - else - { - DiskParameters->Heads = 64; - DiskParameters->Sectors = 32; - } - DiskParameters->Cylinders = - Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors); - /* - Attempt to read the first 1024 bytes from the disk device. - */ - BufferHead = bread(MKDEV(MAJOR(Device), MINOR(Device) & ~0x0F), 0, block_size(Device)); - if (BufferHead == NULL) return 0; - /* - If the boot sector partition table flag is valid, search for a partition - table entry whose end_head matches one of the standard BusLogic geometry - translations (64/32, 128/32, or 255/63). - */ - if (*(unsigned short *) (BufferHead->b_data + 0x1FE) == 0xAA55) - { - PartitionTable_T *FirstPartitionEntry = - (PartitionTable_T *) (BufferHead->b_data + 0x1BE); - PartitionTable_T *PartitionEntry = FirstPartitionEntry; - int SavedCylinders = DiskParameters->Cylinders, PartitionNumber; - unsigned char PartitionEntryEndHead, PartitionEntryEndSector; - for (PartitionNumber = 0; PartitionNumber < 4; PartitionNumber++) - { - PartitionEntryEndHead = PartitionEntry->end_head; - PartitionEntryEndSector = PartitionEntry->end_sector & 0x3F; - if (PartitionEntryEndHead == 64-1) - { - DiskParameters->Heads = 64; - DiskParameters->Sectors = 32; - break; - } - else if (PartitionEntryEndHead == 128-1) - { - DiskParameters->Heads = 128; - DiskParameters->Sectors = 32; - break; - } - else if (PartitionEntryEndHead == 255-1) - { - DiskParameters->Heads = 255; - DiskParameters->Sectors = 63; - break; - } - PartitionEntry++; - } - if (PartitionNumber == 4) - { - PartitionEntryEndHead = FirstPartitionEntry->end_head; - PartitionEntryEndSector = FirstPartitionEntry->end_sector & 0x3F; - } - DiskParameters->Cylinders = - Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors); - if (PartitionNumber < 4 && - PartitionEntryEndSector == DiskParameters->Sectors) - { - if (DiskParameters->Cylinders != SavedCylinders) - BusLogic_Warning("Adopting Geometry %d/%d from Partition Table\n", - HostAdapter, - DiskParameters->Heads, DiskParameters->Sectors); - } - else if (PartitionEntryEndHead > 0 || PartitionEntryEndSector > 0) - { - BusLogic_Warning("Warning: Partition Table appears to " - "have Geometry %d/%d which is\n", HostAdapter, - PartitionEntryEndHead + 1, - PartitionEntryEndSector); - BusLogic_Warning("not compatible with current BusLogic " - "Host Adapter Geometry %d/%d\n", HostAdapter, - DiskParameters->Heads, DiskParameters->Sectors); - } - } - brelse(BufferHead); - return 0; -} - - -/* - BugLogic_ProcDirectoryInfo implements /proc/scsi/BusLogic/. -*/ - -int BusLogic_ProcDirectoryInfo(char *ProcBuffer, char **StartPointer, - off_t Offset, int BytesAvailable, - int HostNumber, int WriteFlag) -{ - BusLogic_HostAdapter_T *HostAdapter; - BusLogic_TargetStatistics_T *TargetStatistics; - int TargetID, Length; - char *Buffer; - for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; - HostAdapter != NULL; - HostAdapter = HostAdapter->Next) - if (HostAdapter->HostNumber == HostNumber) break; - if (HostAdapter == NULL) - { - BusLogic_Error("Cannot find Host Adapter for SCSI Host %d\n", - NULL, HostNumber); - return 0; - } - TargetStatistics = HostAdapter->TargetStatistics; - if (WriteFlag) - { - HostAdapter->ExternalHostAdapterResets = 0; - HostAdapter->HostAdapterInternalErrors = 0; - memset(TargetStatistics, 0, - BusLogic_MaxTargetDevices * sizeof(BusLogic_TargetStatistics_T)); - return 0; - } - Buffer = HostAdapter->MessageBuffer; - Length = HostAdapter->MessageBufferLength; - Length += sprintf(&Buffer[Length], "\n\ -Current Driver Queue Depth: %d\n\ -Currently Allocated CCBs: %d\n", - HostAdapter->DriverQueueDepth, - HostAdapter->AllocatedCCBs); - Length += sprintf(&Buffer[Length], "\n\n\ - DATA TRANSFER STATISTICS\n\ -\n\ -Target Tagged Queuing Queue Depth Active Attempted Completed\n\ -====== ============== =========== ====== ========= =========\n"); - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - { - BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID]; - if (!TargetFlags->TargetExists) continue; - Length += - sprintf(&Buffer[Length], " %2d %s", TargetID, - (TargetFlags->TaggedQueuingSupported - ? (TargetFlags->TaggedQueuingActive - ? " Active" - : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID) - ? " Permitted" : " Disabled")) - : "Not Supported")); - Length += sprintf(&Buffer[Length], - " %3d %3u %9u %9u\n", - HostAdapter->QueueDepth[TargetID], - HostAdapter->ActiveCommands[TargetID], - TargetStatistics[TargetID].CommandsAttempted, - TargetStatistics[TargetID].CommandsCompleted); - } - Length += sprintf(&Buffer[Length], "\n\ -Target Read Commands Write Commands Total Bytes Read Total Bytes Written\n\ -====== ============= ============== =================== ===================\n"); - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - { - BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID]; - if (!TargetFlags->TargetExists) continue; - Length += - sprintf(&Buffer[Length], " %2d %9u %9u", TargetID, - TargetStatistics[TargetID].ReadCommands, - TargetStatistics[TargetID].WriteCommands); - if (TargetStatistics[TargetID].TotalBytesRead.Billions > 0) - Length += - sprintf(&Buffer[Length], " %9u%09u", - TargetStatistics[TargetID].TotalBytesRead.Billions, - TargetStatistics[TargetID].TotalBytesRead.Units); - else - Length += - sprintf(&Buffer[Length], " %9u", - TargetStatistics[TargetID].TotalBytesRead.Units); - if (TargetStatistics[TargetID].TotalBytesWritten.Billions > 0) - Length += - sprintf(&Buffer[Length], " %9u%09u\n", - TargetStatistics[TargetID].TotalBytesWritten.Billions, - TargetStatistics[TargetID].TotalBytesWritten.Units); - else - Length += - sprintf(&Buffer[Length], " %9u\n", - TargetStatistics[TargetID].TotalBytesWritten.Units); - } - Length += sprintf(&Buffer[Length], "\n\ -Target Command 0-1KB 1-2KB 2-4KB 4-8KB 8-16KB\n\ -====== ======= ========= ========= ========= ========= =========\n"); - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - { - BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID]; - if (!TargetFlags->TargetExists) continue; - Length += - sprintf(&Buffer[Length], - " %2d Read %9u %9u %9u %9u %9u\n", TargetID, - TargetStatistics[TargetID].ReadCommandSizeBuckets[0], - TargetStatistics[TargetID].ReadCommandSizeBuckets[1], - TargetStatistics[TargetID].ReadCommandSizeBuckets[2], - TargetStatistics[TargetID].ReadCommandSizeBuckets[3], - TargetStatistics[TargetID].ReadCommandSizeBuckets[4]); - Length += - sprintf(&Buffer[Length], - " %2d Write %9u %9u %9u %9u %9u\n", TargetID, - TargetStatistics[TargetID].WriteCommandSizeBuckets[0], - TargetStatistics[TargetID].WriteCommandSizeBuckets[1], - TargetStatistics[TargetID].WriteCommandSizeBuckets[2], - TargetStatistics[TargetID].WriteCommandSizeBuckets[3], - TargetStatistics[TargetID].WriteCommandSizeBuckets[4]); - } - Length += sprintf(&Buffer[Length], "\n\ -Target Command 16-32KB 32-64KB 64-128KB 128-256KB 256KB+\n\ -====== ======= ========= ========= ========= ========= =========\n"); - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - { - BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID]; - if (!TargetFlags->TargetExists) continue; - Length += - sprintf(&Buffer[Length], - " %2d Read %9u %9u %9u %9u %9u\n", TargetID, - TargetStatistics[TargetID].ReadCommandSizeBuckets[5], - TargetStatistics[TargetID].ReadCommandSizeBuckets[6], - TargetStatistics[TargetID].ReadCommandSizeBuckets[7], - TargetStatistics[TargetID].ReadCommandSizeBuckets[8], - TargetStatistics[TargetID].ReadCommandSizeBuckets[9]); - Length += - sprintf(&Buffer[Length], - " %2d Write %9u %9u %9u %9u %9u\n", TargetID, - TargetStatistics[TargetID].WriteCommandSizeBuckets[5], - TargetStatistics[TargetID].WriteCommandSizeBuckets[6], - TargetStatistics[TargetID].WriteCommandSizeBuckets[7], - TargetStatistics[TargetID].WriteCommandSizeBuckets[8], - TargetStatistics[TargetID].WriteCommandSizeBuckets[9]); - } - Length += sprintf(&Buffer[Length], "\n\n\ - ERROR RECOVERY STATISTICS\n\ -\n\ - Command Aborts Bus Device Resets Host Adapter Resets\n\ -Target Requested Completed Requested Completed Requested Completed\n\ - ID \\\\\\\\ Attempted //// \\\\\\\\ Attempted //// \\\\\\\\ Attempted ////\n\ -====== ===== ===== ===== ===== ===== ===== ===== ===== =====\n"); - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - { - BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID]; - if (!TargetFlags->TargetExists) continue; - Length += - sprintf(&Buffer[Length], "\ - %2d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n", TargetID, - TargetStatistics[TargetID].CommandAbortsRequested, - TargetStatistics[TargetID].CommandAbortsAttempted, - TargetStatistics[TargetID].CommandAbortsCompleted, - TargetStatistics[TargetID].BusDeviceResetsRequested, - TargetStatistics[TargetID].BusDeviceResetsAttempted, - TargetStatistics[TargetID].BusDeviceResetsCompleted, - TargetStatistics[TargetID].HostAdapterResetsRequested, - TargetStatistics[TargetID].HostAdapterResetsAttempted, - TargetStatistics[TargetID].HostAdapterResetsCompleted); - } - Length += sprintf(&Buffer[Length], "\nExternal Host Adapter Resets: %d\n", - HostAdapter->ExternalHostAdapterResets); - Length += sprintf(&Buffer[Length], "Host Adapter Internal Errors: %d\n", - HostAdapter->HostAdapterInternalErrors); - if (Length >= BusLogic_MessageBufferSize) - BusLogic_Error("Message Buffer length %d exceeds size %d\n", - HostAdapter, Length, BusLogic_MessageBufferSize); - if ((Length -= Offset) <= 0) return 0; - if (Length >= BytesAvailable) Length = BytesAvailable; - memcpy(ProcBuffer, HostAdapter->MessageBuffer + Offset, Length); - *StartPointer = ProcBuffer; - return Length; -} - -#endif /* !XEN */ - -/* - BusLogic_Message prints Driver Messages. -*/ - -static void BusLogic_Message(BusLogic_MessageLevel_T MessageLevel, - char *Format, - BusLogic_HostAdapter_T *HostAdapter, - ...) -{ - static char Buffer[BusLogic_LineBufferSize]; - static boolean BeginningOfLine = true; - va_list Arguments; - int Length = 0; - va_start(Arguments, HostAdapter); - Length = vsprintf(Buffer, Format, Arguments); - va_end(Arguments); - if (MessageLevel == BusLogic_AnnounceLevel) - { - static int AnnouncementLines = 0; - strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], - Buffer); - HostAdapter->MessageBufferLength += Length; - if (++AnnouncementLines <= 2) - printk("%sscsi: %s", BusLogic_MessageLevelMap[MessageLevel], Buffer); - } - else if (MessageLevel == BusLogic_InfoLevel) - { - strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], - Buffer); - HostAdapter->MessageBufferLength += Length; - if (BeginningOfLine) - { - if (Buffer[0] != '\n' || Length > 1) - printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], - HostAdapter->HostNumber, Buffer); - } - else printk("%s", Buffer); - } - else - { - if (BeginningOfLine) - { - if (HostAdapter != NULL && HostAdapter->HostAdapterInitialized) - printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], - HostAdapter->HostNumber, Buffer); - else printk("%s%s", BusLogic_MessageLevelMap[MessageLevel], Buffer); - } - else printk("%s", Buffer); - } - BeginningOfLine = (Buffer[Length-1] == '\n'); -} - - -#if 0 /* XEN */ -/* - BusLogic_ParseKeyword parses an individual option keyword. It returns true - and updates the pointer if the keyword is recognized and false otherwise. -*/ - -static boolean BusLogic_ParseKeyword(char **StringPointer, char *Keyword) -{ - char *Pointer = *StringPointer; - while (*Keyword != '\0') - { - char StringChar = *Pointer++; - char KeywordChar = *Keyword++; - if (StringChar >= 'A' && StringChar <= 'Z') - StringChar += 'a' - 'Z'; - if (KeywordChar >= 'A' && KeywordChar <= 'Z') - KeywordChar += 'a' - 'Z'; - if (StringChar != KeywordChar) return false; - } - *StringPointer = Pointer; - return true; -} - -/* - BusLogic_ParseDriverOptions handles processing of BusLogic Driver Options - specifications. - - BusLogic Driver Options may be specified either via the Linux Kernel Command - Line or via the Loadable Kernel Module Installation Facility. Driver Options - for multiple host adapters may be specified either by separating the option - strings by a semicolon, or by specifying multiple "BusLogic=" strings on the - command line. Individual option specifications for a single host adapter are - separated by commas. The Probing and Debugging Options apply to all host - adapters whereas the remaining options apply individually only to the - selected host adapter. - - The BusLogic Driver Probing Options comprise the following: - - IO: - - The "IO:" option specifies an ISA I/O Address to be probed for a non-PCI - MultiMaster Host Adapter. If neither "IO:" nor "NoProbeISA" options are - specified, then the standard list of BusLogic MultiMaster ISA I/O Addresses - will be probed (0x330, 0x334, 0x230, 0x234, 0x130, and 0x134). Multiple - "IO:" options may be specified to precisely determine the I/O Addresses to - be probed, but the probe order will always follow the standard list. - - NoProbe - - The "NoProbe" option disables all probing and therefore no BusLogic Host - Adapters will be detected. - - NoProbeISA - - The "NoProbeISA" option disables probing of the standard BusLogic ISA I/O - Addresses and therefore only PCI MultiMaster and FlashPoint Host Adapters - will be detected. - - NoProbePCI - - The "NoProbePCI" options disables the interrogation of PCI Configuration - Space and therefore only ISA Multimaster Host Adapters will be detected, as - well as PCI Multimaster Host Adapters that have their ISA Compatible I/O - Port set to "Primary" or "Alternate". - - NoSortPCI - - The "NoSortPCI" option forces PCI MultiMaster Host Adapters to be - enumerated in the order provided by the PCI BIOS, ignoring any setting of - the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option. - - MultiMasterFirst - - The "MultiMasterFirst" option forces MultiMaster Host Adapters to be probed - before FlashPoint Host Adapters. By default, if both FlashPoint and PCI - MultiMaster Host Adapters are present, this driver will probe for - FlashPoint Host Adapters first unless the BIOS primary disk is controlled - by the first PCI MultiMaster Host Adapter, in which case MultiMaster Host - Adapters will be probed first. - - FlashPointFirst - - The "FlashPointFirst" option forces FlashPoint Host Adapters to be probed - before MultiMaster Host Adapters. - - The BusLogic Driver Tagged Queuing Options allow for explicitly specifying - the Queue Depth and whether Tagged Queuing is permitted for each Target - Device (assuming that the Target Device supports Tagged Queuing). The Queue - Depth is the number of SCSI Commands that are allowed to be concurrently - presented for execution (either to the Host Adapter or Target Device). Note - that explicitly enabling Tagged Queuing may lead to problems; the option to - enable or disable Tagged Queuing is provided primarily to allow disabling - Tagged Queuing on Target Devices that do not implement it correctly. The - following options are available: - - QueueDepth: - - The "QueueDepth:" or QD:" option specifies the Queue Depth to use for all - Target Devices that support Tagged Queuing, as well as the maximum Queue - Depth for devices that do not support Tagged Queuing. If no Queue Depth - option is provided, the Queue Depth will be determined automatically based - on the Host Adapter's Total Queue Depth and the number, type, speed, and - capabilities of the detected Target Devices. For Host Adapters that - require ISA Bounce Buffers, the Queue Depth is automatically set by default - to BusLogic_TaggedQueueDepthBB or BusLogic_UntaggedQueueDepthBB to avoid - excessive preallocation of DMA Bounce Buffer memory. Target Devices that - do not support Tagged Queuing always have their Queue Depth set to - BusLogic_UntaggedQueueDepth or BusLogic_UntaggedQueueDepthBB, unless a - lower Queue Depth option is provided. A Queue Depth of 1 automatically - disables Tagged Queuing. - - QueueDepth:[,...] - - The "QueueDepth:[...]" or "QD:[...]" option specifies the Queue Depth - individually for each Target Device. If an is omitted, the - associated Target Device will have its Queue Depth selected automatically. - - TaggedQueuing:Default - - The "TaggedQueuing:Default" or "TQ:Default" option permits Tagged Queuing - based on the firmware version of the BusLogic Host Adapter and based on - whether the Queue Depth allows queuing multiple commands. - - TaggedQueuing:Enable - - The "TaggedQueuing:Enable" or "TQ:Enable" option enables Tagged Queuing for - all Target Devices on this Host Adapter, overriding any limitation that - would otherwise be imposed based on the Host Adapter firmware version. - - TaggedQueuing:Disable - - The "TaggedQueuing:Disable" or "TQ:Disable" option disables Tagged Queuing - for all Target Devices on this Host Adapter. - - TaggedQueuing: - - The "TaggedQueuing:" or "TQ:" option controls - Tagged Queuing individually for each Target Device. is a - sequence of "Y", "N", and "X" characters. "Y" enables Tagged Queuing, "N" - disables Tagged Queuing, and "X" accepts the default based on the firmware - version. The first character refers to Target Device 0, the second to - Target Device 1, and so on; if the sequence of "Y", "N", and "X" characters - does not cover all the Target Devices, unspecified characters are assumed - to be "X". - - The BusLogic Driver Error Recovery Option allows for explicitly specifying - the Error Recovery action to be performed when BusLogic_ResetCommand is - called due to a SCSI Command failing to complete successfully. The following - options are available: - - ErrorRecovery:Default - - The "ErrorRecovery:Default" or "ER:Default" option selects between the Hard - Reset and Bus Device Reset options based on the recommendation of the SCSI - Subsystem. - - ErrorRecovery:HardReset - - The "ErrorRecovery:HardReset" or "ER:HardReset" option will initiate a Host - Adapter Hard Reset which also causes a SCSI Bus Reset. - - ErrorRecovery:BusDeviceReset - - The "ErrorRecovery:BusDeviceReset" or "ER:BusDeviceReset" option will send - a Bus Device Reset message to the individual Target Device causing the - error. If Error Recovery is again initiated for this Target Device and no - SCSI Command to this Target Device has completed successfully since the Bus - Device Reset message was sent, then a Hard Reset will be attempted. - - ErrorRecovery:None - - The "ErrorRecovery:None" or "ER:None" option suppresses Error Recovery. - This option should only be selected if a SCSI Bus Reset or Bus Device Reset - will cause the Target Device or a critical operation to suffer a complete - and unrecoverable failure. - - ErrorRecovery: - - The "ErrorRecovery:" or "ER:" option controls - Error Recovery individually for each Target Device. is a - sequence of "D", "H", "B", and "N" characters. "D" selects Default, "H" - selects Hard Reset, "B" selects Bus Device Reset, and "N" selects None. - The first character refers to Target Device 0, the second to Target Device - 1, and so on; if the sequence of "D", "H", "B", and "N" characters does not - cover all the possible Target Devices, unspecified characters are assumed - to be "D". - - The BusLogic Driver Miscellaneous Options comprise the following: - - BusSettleTime: - - The "BusSettleTime:" or "BST:" option specifies the Bus Settle Time in - seconds. The Bus Settle Time is the amount of time to wait between a Host - Adapter Hard Reset which initiates a SCSI Bus Reset and issuing any SCSI - Commands. If unspecified, it defaults to BusLogic_DefaultBusSettleTime. - - InhibitTargetInquiry - - The "InhibitTargetInquiry" option inhibits the execution of an Inquire - Target Devices or Inquire Installed Devices command on MultiMaster Host - Adapters. This may be necessary with some older Target Devices that do not - respond correctly when Logical Units above 0 are addressed. - - The BusLogic Driver Debugging Options comprise the following: - - TraceProbe - - The "TraceProbe" option enables tracing of Host Adapter Probing. - - TraceHardwareReset - - The "TraceHardwareReset" option enables tracing of Host Adapter Hardware - Reset. - - TraceConfiguration - - The "TraceConfiguration" option enables tracing of Host Adapter - Configuration. - - TraceErrors - - The "TraceErrors" option enables tracing of SCSI Commands that return an - error from the Target Device. The CDB and Sense Data will be printed for - each SCSI Command that fails. - - Debug - - The "Debug" option enables all debugging options. - - The following examples demonstrate setting the Queue Depth for Target Devices - 1 and 2 on the first host adapter to 7 and 15, the Queue Depth for all Target - Devices on the second host adapter to 31, and the Bus Settle Time on the - second host adapter to 30 seconds. - - Linux Kernel Command Line: - - linux BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30 - - LILO Linux Boot Loader (in /etc/lilo.conf): - - append = "BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30" - - INSMOD Loadable Kernel Module Installation Facility: - - insmod BusLogic.o \ - 'BusLogic="QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"' - - NOTE: Module Utilities 2.1.71 or later is required for correct parsing - of driver options containing commas. - -*/ - -static int __init BusLogic_ParseDriverOptions(char *OptionsString) -{ - while (true) - { - BusLogic_DriverOptions_T *DriverOptions = - &BusLogic_DriverOptions[BusLogic_DriverOptionsCount++]; - int TargetID; - memset(DriverOptions, 0, sizeof(BusLogic_DriverOptions_T)); - for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) - DriverOptions->ErrorRecoveryStrategy[TargetID] = - BusLogic_ErrorRecovery_Default; - while (*OptionsString != '\0' && *OptionsString != ';') - { - /* Probing Options. */ - if (BusLogic_ParseKeyword(&OptionsString, "IO:")) - { - BusLogic_IO_Address_T IO_Address = - simple_strtoul(OptionsString, &OptionsString, 0); - BusLogic_ProbeOptions.LimitedProbeISA = true; - switch (IO_Address) - { - case 0x330: - BusLogic_ProbeOptions.Probe330 = true; - break; - case 0x334: - BusLogic_ProbeOptions.Probe334 = true; - break; - case 0x230: - BusLogic_ProbeOptions.Probe230 = true; - break; - case 0x234: - BusLogic_ProbeOptions.Probe234 = true; - break; - case 0x130: - BusLogic_ProbeOptions.Probe130 = true; - break; - case 0x134: - BusLogic_ProbeOptions.Probe134 = true; - break; - default: - BusLogic_Error("BusLogic: Invalid Driver Options " - "(illegal I/O Address 0x%X)\n", - NULL, IO_Address); - return 0; - } - } - else if (BusLogic_ParseKeyword(&OptionsString, "NoProbeISA")) - BusLogic_ProbeOptions.NoProbeISA = true; - else if (BusLogic_ParseKeyword(&OptionsString, "NoProbePCI")) - BusLogic_ProbeOptions.NoProbePCI = true; - else if (BusLogic_ParseKeyword(&OptionsString, "NoProbe")) - BusLogic_ProbeOptions.NoProbe = true; - else if (BusLogic_ParseKeyword(&OptionsString, "NoSortPCI")) - BusLogic_ProbeOptions.NoSortPCI = true; - else if (BusLogic_ParseKeyword(&OptionsString, "MultiMasterFirst")) - BusLogic_ProbeOptions.MultiMasterFirst = true; - else if (BusLogic_ParseKeyword(&OptionsString, "FlashPointFirst")) - BusLogic_ProbeOptions.FlashPointFirst = true; - /* Tagged Queuing Options. */ - else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:[") || - BusLogic_ParseKeyword(&OptionsString, "QD:[")) - { - for (TargetID = 0; - TargetID < BusLogic_MaxTargetDevices; - TargetID++) - { - unsigned short QueueDepth = - simple_strtoul(OptionsString, &OptionsString, 0); - if (QueueDepth > BusLogic_MaxTaggedQueueDepth) - { - BusLogic_Error("BusLogic: Invalid Driver Options " - "(illegal Queue Depth %d)\n", - NULL, QueueDepth); - return 0; - } - DriverOptions->QueueDepth[TargetID] = QueueDepth; - if (*OptionsString == ',') - OptionsString++; - else if (*OptionsString == ']') - break; - else - { - BusLogic_Error("BusLogic: Invalid Driver Options " - "(',' or ']' expected at '%s')\n", - NULL, OptionsString); - return 0; - } - } - if (*OptionsString != ']') - { - BusLogic_Error("BusLogic: Invalid Driver Options " - "(']' expected at '%s')\n", - NULL, OptionsString); - return 0; - } - else OptionsString++; - } - else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:") || - BusLogic_ParseKeyword(&OptionsString, "QD:")) - { - unsigned short QueueDepth = - simple_strtoul(OptionsString, &OptionsString, 0); - if (QueueDepth == 0 || QueueDepth > BusLogic_MaxTaggedQueueDepth) - { - BusLogic_Error("BusLogic: Invalid Driver Options " - "(illegal Queue Depth %d)\n", - NULL, QueueDepth); - return 0; - } - DriverOptions->CommonQueueDepth = QueueDepth; - for (TargetID = 0; - TargetID < BusLogic_MaxTargetDevices; - TargetID++) - DriverOptions->QueueDepth[TargetID] = QueueDepth; - } - else if (BusLogic_ParseKeyword(&OptionsString, "TaggedQueuing:") || - BusLogic_ParseKeyword(&OptionsString, "TQ:")) - { - if (BusLogic_ParseKeyword(&OptionsString, "Default")) - { - DriverOptions->TaggedQueuingPermitted = 0x0000; - DriverOptions->TaggedQueuingPermittedMask = 0x0000; - } - else if (BusLogic_ParseKeyword(&OptionsString, "Enable")) - { - DriverOptions->TaggedQueuingPermitted = 0xFFFF; - DriverOptions->TaggedQueuingPermittedMask = 0xFFFF; - } - else if (BusLogic_ParseKeyword(&OptionsString, "Disable")) - { - DriverOptions->TaggedQueuingPermitted = 0x0000; - DriverOptions->TaggedQueuingPermittedMask = 0xFFFF; - } - else - { - unsigned short TargetBit; - for (TargetID = 0, TargetBit = 1; - TargetID < BusLogic_MaxTargetDevices; - TargetID++, TargetBit <<= 1) - switch (*OptionsString++) - { - case 'Y': - DriverOptions->TaggedQueuingPermitted |= TargetBit; - DriverOptions->TaggedQueuingPermittedMask |= TargetBit; - break; - case 'N': - DriverOptions->TaggedQueuingPermitted &= ~TargetBit; - DriverOptions->TaggedQueuingPermittedMask |= TargetBit; - break; - case 'X': - break; - default: - OptionsString--; - TargetID = BusLogic_MaxTargetDevices; - break; - } - } - } - /* Error Recovery Option. */ - else if (BusLogic_ParseKeyword(&OptionsString, "ErrorRecovery:") || - BusLogic_ParseKeyword(&OptionsString, "ER:")) - { - if (BusLogic_ParseKeyword(&OptionsString, "Default")) - for (TargetID = 0; - TargetID < BusLogic_MaxTargetDevices; - TargetID++) - DriverOptions->ErrorRecoveryStrategy[TargetID] = - BusLogic_ErrorRecovery_Default; - else if (BusLogic_ParseKeyword(&OptionsString, "HardReset")) - for (TargetID = 0; - TargetID < BusLogic_MaxTargetDevices; - TargetID++) - DriverOptions->ErrorRecoveryStrategy[TargetID] = - BusLogic_ErrorRecovery_HardReset; - else if (BusLogic_ParseKeyword(&OptionsString, "BusDeviceReset")) - for (TargetID = 0; - TargetID < BusLogic_MaxTargetDevices; - TargetID++) - DriverOptions->ErrorRecoveryStrategy[TargetID] = - BusLogic_ErrorRecovery_BusDeviceReset; - else if (BusLogic_ParseKeyword(&OptionsString, "None")) - for (TargetID = 0; - TargetID < BusLogic_MaxTargetDevices; - TargetID++) - DriverOptions->ErrorRecoveryStrategy[TargetID] = - BusLogic_ErrorRecovery_None; - else - for (TargetID = 0; - TargetID < BusLogic_MaxTargetDevices; - TargetID++) - switch (*OptionsString++) - { - case 'D': - DriverOptions->ErrorRecoveryStrategy[TargetID] = - BusLogic_ErrorRecovery_Default; - break; - case 'H': - DriverOptions->ErrorRecoveryStrategy[TargetID] = - BusLogic_ErrorRecovery_HardReset; - break; - case 'B': - DriverOptions->ErrorRecoveryStrategy[TargetID] = - BusLogic_ErrorRecovery_BusDeviceReset; - break; - case 'N': - DriverOptions->ErrorRecoveryStrategy[TargetID] = - BusLogic_ErrorRecovery_None; - break; - default: - OptionsString--; - TargetID = BusLogic_MaxTargetDevices; - break; - } - } - /* Miscellaneous Options. */ - else if (BusLogic_ParseKeyword(&OptionsString, "BusSettleTime:") || - BusLogic_ParseKeyword(&OptionsString, "BST:")) - { - unsigned short BusSettleTime = - simple_strtoul(OptionsString, &OptionsString, 0); - if (BusSettleTime > 5 * 60) - { - BusLogic_Error("BusLogic: Invalid Driver Options " - "(illegal Bus Settle Time %d)\n", - NULL, BusSettleTime); - return 0; - } - DriverOptions->BusSettleTime = BusSettleTime; - } - else if (BusLogic_ParseKeyword(&OptionsString, - "InhibitTargetInquiry")) - DriverOptions->LocalOptions.InhibitTargetInquiry = true; - /* Debugging Options. */ - else if (BusLogic_ParseKeyword(&OptionsString, "TraceProbe")) - BusLogic_GlobalOptions.TraceProbe = true; - else if (BusLogic_ParseKeyword(&OptionsString, "TraceHardwareReset")) - BusLogic_GlobalOptions.TraceHardwareReset = true; - else if (BusLogic_ParseKeyword(&OptionsString, "TraceConfiguration")) - BusLogic_GlobalOptions.TraceConfiguration = true; - else if (BusLogic_ParseKeyword(&OptionsString, "TraceErrors")) - BusLogic_GlobalOptions.TraceErrors = true; - else if (BusLogic_ParseKeyword(&OptionsString, "Debug")) - { - BusLogic_GlobalOptions.TraceProbe = true; - BusLogic_GlobalOptions.TraceHardwareReset = true; - BusLogic_GlobalOptions.TraceConfiguration = true; - BusLogic_GlobalOptions.TraceErrors = true; - } - if (*OptionsString == ',') - OptionsString++; - else if (*OptionsString != ';' && *OptionsString != '\0') - { - BusLogic_Error("BusLogic: Unexpected Driver Option '%s' " - "ignored\n", NULL, OptionsString); - *OptionsString = '\0'; - } - } - if (!(BusLogic_DriverOptionsCount == 0 || - BusLogic_ProbeInfoCount == 0 || - BusLogic_DriverOptionsCount == BusLogic_ProbeInfoCount)) - { - BusLogic_Error("BusLogic: Invalid Driver Options " - "(all or no I/O Addresses must be specified)\n", NULL); - return 0; - } - /* - Tagged Queuing is disabled when the Queue Depth is 1 since queuing - multiple commands is not possible. - */ - for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) - if (DriverOptions->QueueDepth[TargetID] == 1) - { - unsigned short TargetBit = 1 << TargetID; - DriverOptions->TaggedQueuingPermitted &= ~TargetBit; - DriverOptions->TaggedQueuingPermittedMask |= TargetBit; - } - if (*OptionsString == ';') OptionsString++; - if (*OptionsString == '\0') return 0; - } - return 1; -} - - -/* - BusLogic_Setup handles processing of Kernel Command Line Arguments. -*/ - -static int __init -BusLogic_Setup(char *str) -{ - int ints[3]; - - (void)get_options(str, ARRAY_SIZE(ints), ints); - - if (ints[0] != 0) { - BusLogic_Error("BusLogic: Obsolete Command Line Entry " - "Format Ignored\n", NULL); - return 0; - } - if (str == NULL || *str == '\0') - return 0; - return BusLogic_ParseDriverOptions(str); -} - -__setup("BusLogic=", BusLogic_Setup); - -#endif /* !XEN */ - -/* - Get it all started -*/ -MODULE_LICENSE("GPL"); - -static SCSI_Host_Template_T driver_template = BUSLOGIC; - -#include "scsi_module.c.inc" diff --git a/xen/drivers/scsi/BusLogic.h b/xen/drivers/scsi/BusLogic.h deleted file mode 100644 index 506ac80473..0000000000 --- a/xen/drivers/scsi/BusLogic.h +++ /dev/null @@ -1,1811 +0,0 @@ -/* - - Linux Driver for BusLogic MultiMaster and FlashPoint SCSI Host Adapters - - Copyright 1995-1998 by Leonard N. Zubkoff - - This program is free software; you may redistribute and/or modify it under - the terms of the GNU General Public License Version 2 as published by the - Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for complete details. - - The author respectfully requests that any modifications to this software be - sent directly to him for evaluation and testing. - - Special thanks to Wayne Yen, Jin-Lon Hon, and Alex Win of BusLogic, whose - advice has been invaluable, to David Gentzel, for writing the original Linux - BusLogic driver, and to Paul Gortmaker, for being such a dedicated test site. - - Finally, special thanks to Mylex/BusLogic for making the FlashPoint SCCB - Manager available as freely redistributable source code. - -*/ - - -#include - - -/* - Define types for some of the structures that interface with the rest - of the Linux Kernel and SCSI Subsystem. -*/ - -typedef kdev_t KernelDevice_T; -typedef unsigned long ProcessorFlags_T; -typedef struct pt_regs Registers_T; -typedef struct partition PartitionTable_T; -typedef struct pci_dev PCI_Device_T; -typedef Scsi_Host_Template SCSI_Host_Template_T; -typedef struct Scsi_Host SCSI_Host_T; -typedef struct scsi_device SCSI_Device_T; -typedef struct scsi_disk SCSI_Disk_T; -typedef struct scsi_cmnd SCSI_Command_T; -typedef struct scatterlist SCSI_ScatterList_T; - - -/* - Define prototypes for the BusLogic Driver Interface Functions. -*/ - -extern const char *BusLogic_DriverInfo(SCSI_Host_T *); -extern int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *); -extern int BusLogic_ReleaseHostAdapter(SCSI_Host_T *); -extern int BusLogic_QueueCommand(SCSI_Command_T *, - void (*CompletionRoutine)(SCSI_Command_T *)); -extern int BusLogic_AbortCommand(SCSI_Command_T *); -extern int BusLogic_ResetCommand(SCSI_Command_T *, unsigned int); -extern int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *); -#if 0 /* XEN */ -extern int BusLogic_ProcDirectoryInfo(char *, char **, off_t, int, int, int); -#endif - - -/* - Define the BusLogic SCSI Host Template structure. -*/ - -#define BUSLOGIC \ - { /*proc_name: "BusLogic",*/ /* ProcFS Directory Entry */ \ - /*proc_info: BusLogic_ProcDirectoryInfo,*/ /* ProcFS Info Function */ \ - name: "BusLogic", /* Driver Name */ \ - detect: BusLogic_DetectHostAdapter, /* Detect Host Adapter */ \ - release: BusLogic_ReleaseHostAdapter, /* Release Host Adapter */ \ - info: BusLogic_DriverInfo, /* Driver Info Function */ \ - queuecommand: BusLogic_QueueCommand, /* Queue Command Function */ \ - abort: BusLogic_AbortCommand, /* Abort Command Function */ \ - reset: BusLogic_ResetCommand, /* Reset Command Function */ \ - /*bios_param: BusLogic_BIOSDiskParameters,*/ /* BIOS Disk Parameters */ \ - unchecked_isa_dma: 1, /* Default Initial Value */ \ - max_sectors: 128, /* I/O queue len limit */ \ - use_clustering: ENABLE_CLUSTERING } /* Enable Clustering */ - - -/* - BusLogic_DriverVersion protects the private portion of this file. -*/ - -#ifdef BusLogic_DriverVersion - - -/* - FlashPoint support is only available for the Intel x86 Architecture with - CONFIG_PCI set. -*/ - -#ifndef __i386__ -#undef CONFIG_SCSI_OMIT_FLASHPOINT -#define CONFIG_SCSI_OMIT_FLASHPOINT -#endif - -#ifndef CONFIG_PCI -#undef CONFIG_SCSI_OMIT_FLASHPOINT -#define CONFIG_SCSI_OMIT_FLASHPOINT -#define BusLogic_InitializeProbeInfoListISA \ - BusLogic_InitializeProbeInfoList -#endif - - -/* - Define the maximum number of BusLogic Host Adapters supported by this driver. -*/ - -#define BusLogic_MaxHostAdapters 16 - - -/* - Define the maximum number of Target Devices supported by this driver. -*/ - -#define BusLogic_MaxTargetDevices 16 - - -/* - Define the maximum number of Scatter/Gather Segments used by this driver. - For optimal performance, it is important that this limit be at least as - large as the largest single request generated by the I/O Subsystem. -*/ - -#define BusLogic_ScatterGatherLimit 128 - - -/* - Define the maximum, maximum automatic, minimum automatic, and default Queue - Depth to allow for Target Devices depending on whether or not they support - Tagged Queuing and whether or not ISA Bounce Buffers are required. -*/ - -#define BusLogic_MaxTaggedQueueDepth 64 -#define BusLogic_MaxAutomaticTaggedQueueDepth 28 -#define BusLogic_MinAutomaticTaggedQueueDepth 7 -#define BusLogic_TaggedQueueDepthBB 3 -#define BusLogic_UntaggedQueueDepth 3 -#define BusLogic_UntaggedQueueDepthBB 2 - - -/* - Define the default amount of time in seconds to wait between a Host Adapter - Hard Reset which initiates a SCSI Bus Reset and issuing any SCSI commands. - Some SCSI devices get confused if they receive SCSI commands too soon after - a SCSI Bus Reset. -*/ - -#define BusLogic_DefaultBusSettleTime 2 - - -/* - Define the maximum number of Mailboxes that should be used for MultiMaster - Host Adapters. This number is chosen to be larger than the maximum Host - Adapter Queue Depth and small enough so that the Host Adapter structure - does not cross an allocation block size boundary. -*/ - -#define BusLogic_MaxMailboxes 211 - - -/* - Define the number of CCBs that should be allocated as a group to optimize - Kernel memory allocation. -*/ - -#define BusLogic_CCB_AllocationGroupSize 7 - - -/* - Define the Host Adapter Line and Message Buffer Sizes. -*/ - -#define BusLogic_LineBufferSize 100 -#define BusLogic_MessageBufferSize 9700 - - -/* - Define the Driver Message Levels. -*/ - -typedef enum BusLogic_MessageLevel -{ - BusLogic_AnnounceLevel = 0, - BusLogic_InfoLevel = 1, - BusLogic_NoticeLevel = 2, - BusLogic_WarningLevel = 3, - BusLogic_ErrorLevel = 4 -} -BusLogic_MessageLevel_T; - -static char - *BusLogic_MessageLevelMap[] = - { KERN_NOTICE, KERN_NOTICE, KERN_NOTICE, KERN_WARNING, KERN_ERR }; - - -/* - Define Driver Message macros. -*/ - -#define BusLogic_Announce(Format, Arguments...) \ - BusLogic_Message(BusLogic_AnnounceLevel, Format, ##Arguments) - -#define BusLogic_Info(Format, Arguments...) \ - BusLogic_Message(BusLogic_InfoLevel, Format, ##Arguments) - -#define BusLogic_Notice(Format, Arguments...) \ - BusLogic_Message(BusLogic_NoticeLevel, Format, ##Arguments) - -#define BusLogic_Warning(Format, Arguments...) \ - BusLogic_Message(BusLogic_WarningLevel, Format, ##Arguments) - -#define BusLogic_Error(Format, Arguments...) \ - BusLogic_Message(BusLogic_ErrorLevel, Format, ##Arguments) - - -/* - Define the types of BusLogic Host Adapters that are supported and the number - of I/O Addresses required by each type. -*/ - -typedef enum -{ - BusLogic_MultiMaster = 1, - BusLogic_FlashPoint = 2 -} -__attribute__ ((packed)) -BusLogic_HostAdapterType_T; - -#define BusLogic_MultiMasterAddressCount 4 -#define BusLogic_FlashPointAddressCount 256 - -static int - BusLogic_HostAdapterAddressCount[3] = - { 0, BusLogic_MultiMasterAddressCount, BusLogic_FlashPointAddressCount }; - - -/* - Define macros for testing the Host Adapter Type. -*/ - -#ifndef CONFIG_SCSI_OMIT_FLASHPOINT - -#define BusLogic_MultiMasterHostAdapterP(HostAdapter) \ - (HostAdapter->HostAdapterType == BusLogic_MultiMaster) - -#define BusLogic_FlashPointHostAdapterP(HostAdapter) \ - (HostAdapter->HostAdapterType == BusLogic_FlashPoint) - -#else - -#define BusLogic_MultiMasterHostAdapterP(HostAdapter) \ - (true) - -#define BusLogic_FlashPointHostAdapterP(HostAdapter) \ - (false) - -#endif - - -/* - Define the possible Host Adapter Bus Types. -*/ - -typedef enum -{ - BusLogic_Unknown_Bus = 0, - BusLogic_ISA_Bus = 1, - BusLogic_EISA_Bus = 2, - BusLogic_PCI_Bus = 3, - BusLogic_VESA_Bus = 4, - BusLogic_MCA_Bus = 5 -} -__attribute__ ((packed)) -BusLogic_HostAdapterBusType_T; - -static char - *BusLogic_HostAdapterBusNames[] = - { "Unknown", "ISA", "EISA", "PCI", "VESA", "MCA" }; - -static BusLogic_HostAdapterBusType_T - BusLogic_HostAdapterBusTypes[] = - { BusLogic_VESA_Bus, /* BT-4xx */ - BusLogic_ISA_Bus, /* BT-5xx */ - BusLogic_MCA_Bus, /* BT-6xx */ - BusLogic_EISA_Bus, /* BT-7xx */ - BusLogic_Unknown_Bus, /* BT-8xx */ - BusLogic_PCI_Bus }; /* BT-9xx */ - - -/* - Define the possible Host Adapter BIOS Disk Geometry Translations. -*/ - -typedef enum BusLogic_BIOS_DiskGeometryTranslation -{ - BusLogic_BIOS_Disk_Not_Installed = 0, - BusLogic_BIOS_Disk_Installed_64x32 = 1, - BusLogic_BIOS_Disk_Installed_128x32 = 2, - BusLogic_BIOS_Disk_Installed_255x63 = 3 -} -__attribute__ ((packed)) -BusLogic_BIOS_DiskGeometryTranslation_T; - - -/* - Define a Boolean data type. -*/ - -typedef enum { false, true } __attribute__ ((packed)) boolean; - - -/* - Define a 32 bit I/O Address data type. -*/ - -typedef unsigned int BusLogic_IO_Address_T; - - -/* - Define a 32 bit PCI Bus Address data type. -*/ - -typedef unsigned int BusLogic_PCI_Address_T; - - -/* - Define a 32 bit Base Address data type. -*/ - -typedef unsigned int BusLogic_Base_Address_T; - - -/* - Define a 32 bit Bus Address data type. -*/ - -typedef unsigned int BusLogic_BusAddress_T; - - -/* - Define a 32 bit Byte Count data type. -*/ - -typedef unsigned int BusLogic_ByteCount_T; - - -/* - Define a 10^18 Statistics Byte Counter data type. -*/ - -typedef struct BusLogic_ByteCounter -{ - unsigned int Units; - unsigned int Billions; -} -BusLogic_ByteCounter_T; - - -/* - Define the structure for I/O Address and Bus Probing Information. -*/ - -typedef struct BusLogic_ProbeInfo -{ - BusLogic_HostAdapterType_T HostAdapterType; - BusLogic_HostAdapterBusType_T HostAdapterBusType; - BusLogic_IO_Address_T IO_Address; - BusLogic_PCI_Address_T PCI_Address; - unsigned char Bus; - unsigned char Device; - unsigned char IRQ_Channel; -} -BusLogic_ProbeInfo_T; - - -/* - Define the Probe Options. -*/ - -typedef struct BusLogic_ProbeOptions -{ - boolean NoProbe:1; /* Bit 0 */ - boolean NoProbeISA:1; /* Bit 1 */ - boolean NoProbePCI:1; /* Bit 2 */ - boolean NoSortPCI:1; /* Bit 3 */ - boolean MultiMasterFirst:1; /* Bit 4 */ - boolean FlashPointFirst:1; /* Bit 5 */ - boolean LimitedProbeISA:1; /* Bit 6 */ - boolean Probe330:1; /* Bit 7 */ - boolean Probe334:1; /* Bit 8 */ - boolean Probe230:1; /* Bit 9 */ - boolean Probe234:1; /* Bit 10 */ - boolean Probe130:1; /* Bit 11 */ - boolean Probe134:1; /* Bit 12 */ -} -BusLogic_ProbeOptions_T; - - -/* - Define the Global Options. -*/ - -typedef struct BusLogic_GlobalOptions -{ - boolean TraceProbe:1; /* Bit 0 */ - boolean TraceHardwareReset:1; /* Bit 1 */ - boolean TraceConfiguration:1; /* Bit 2 */ - boolean TraceErrors:1; /* Bit 3 */ -} -BusLogic_GlobalOptions_T; - - -/* - Define the Local Options. -*/ - -typedef struct BusLogic_LocalOptions -{ - boolean InhibitTargetInquiry:1; /* Bit 0 */ -} -BusLogic_LocalOptions_T; - - -/* - Define the Error Recovery Strategy Options. -*/ - -typedef enum -{ - BusLogic_ErrorRecovery_Default = 0, - BusLogic_ErrorRecovery_BusDeviceReset = 1, - BusLogic_ErrorRecovery_HardReset = 2, - BusLogic_ErrorRecovery_None = 3 -} -__attribute__ ((packed)) -BusLogic_ErrorRecoveryStrategy_T; - -static char - *BusLogic_ErrorRecoveryStrategyNames[] = - { "Default", "Bus Device Reset", "Hard Reset", "None" }, - BusLogic_ErrorRecoveryStrategyLetters[] = - { 'D', 'B', 'H', 'N' }; - - -/* - Define the BusLogic SCSI Host Adapter I/O Register Offsets. -*/ - -#define BusLogic_ControlRegisterOffset 0 /* WO register */ -#define BusLogic_StatusRegisterOffset 0 /* RO register */ -#define BusLogic_CommandParameterRegisterOffset 1 /* WO register */ -#define BusLogic_DataInRegisterOffset 1 /* RO register */ -#define BusLogic_InterruptRegisterOffset 2 /* RO register */ -#define BusLogic_GeometryRegisterOffset 3 /* RO register */ - - -/* - Define the structure of the write-only Control Register. -*/ - -typedef union BusLogic_ControlRegister -{ - unsigned char All; - struct { - unsigned char :4; /* Bits 0-3 */ - boolean SCSIBusReset:1; /* Bit 4 */ - boolean InterruptReset:1; /* Bit 5 */ - boolean SoftReset:1; /* Bit 6 */ - boolean HardReset:1; /* Bit 7 */ - } Bits; -} -BusLogic_ControlRegister_T; - - -/* - Define the structure of the read-only Status Register. -*/ - -typedef union BusLogic_StatusRegister -{ - unsigned char All; - struct { - boolean CommandInvalid:1; /* Bit 0 */ - boolean Reserved:1; /* Bit 1 */ - boolean DataInRegisterReady:1; /* Bit 2 */ - boolean CommandParameterRegisterBusy:1; /* Bit 3 */ - boolean HostAdapterReady:1; /* Bit 4 */ - boolean InitializationRequired:1; /* Bit 5 */ - boolean DiagnosticFailure:1; /* Bit 6 */ - boolean DiagnosticActive:1; /* Bit 7 */ - } Bits; -} -BusLogic_StatusRegister_T; - - -/* - Define the structure of the read-only Interrupt Register. -*/ - -typedef union BusLogic_InterruptRegister -{ - unsigned char All; - struct { - boolean IncomingMailboxLoaded:1; /* Bit 0 */ - boolean OutgoingMailboxAvailable:1; /* Bit 1 */ - boolean CommandComplete:1; /* Bit 2 */ - boolean ExternalBusReset:1; /* Bit 3 */ - unsigned char Reserved:3; /* Bits 4-6 */ - boolean InterruptValid:1; /* Bit 7 */ - } Bits; -} -BusLogic_InterruptRegister_T; - - -/* - Define the structure of the read-only Geometry Register. -*/ - -typedef union BusLogic_GeometryRegister -{ - unsigned char All; - struct { - BusLogic_BIOS_DiskGeometryTranslation_T Drive0Geometry:2; /* Bits 0-1 */ - BusLogic_BIOS_DiskGeometryTranslation_T Drive1Geometry:2; /* Bits 2-3 */ - unsigned char :3; /* Bits 4-6 */ - boolean ExtendedTranslationEnabled:1; /* Bit 7 */ - } Bits; -} -BusLogic_GeometryRegister_T; - - -/* - Define the BusLogic SCSI Host Adapter Command Register Operation Codes. -*/ - -typedef enum -{ - BusLogic_TestCommandCompleteInterrupt = 0x00, - BusLogic_InitializeMailbox = 0x01, - BusLogic_ExecuteMailboxCommand = 0x02, - BusLogic_ExecuteBIOSCommand = 0x03, - BusLogic_InquireBoardID = 0x04, - BusLogic_EnableOutgoingMailboxAvailableInt = 0x05, - BusLogic_SetSCSISelectionTimeout = 0x06, - BusLogic_SetPreemptTimeOnBus = 0x07, - BusLogic_SetTimeOffBus = 0x08, - BusLogic_SetBusTransferRate = 0x09, - BusLogic_InquireInstalledDevicesID0to7 = 0x0A, - BusLogic_InquireConfiguration = 0x0B, - BusLogic_EnableTargetMode = 0x0C, - BusLogic_InquireSetupInformation = 0x0D, - BusLogic_WriteAdapterLocalRAM = 0x1A, - BusLogic_ReadAdapterLocalRAM = 0x1B, - BusLogic_WriteBusMasterChipFIFO = 0x1C, - BusLogic_ReadBusMasterChipFIFO = 0x1D, - BusLogic_EchoCommandData = 0x1F, - BusLogic_HostAdapterDiagnostic = 0x20, - BusLogic_SetAdapterOptions = 0x21, - BusLogic_InquireInstalledDevicesID8to15 = 0x23, - BusLogic_InquireTargetDevices = 0x24, - BusLogic_DisableHostAdapterInterrupt = 0x25, - BusLogic_InitializeExtendedMailbox = 0x81, - BusLogic_ExecuteSCSICommand = 0x83, - BusLogic_InquireFirmwareVersion3rdDigit = 0x84, - BusLogic_InquireFirmwareVersionLetter = 0x85, - BusLogic_InquirePCIHostAdapterInformation = 0x86, - BusLogic_InquireHostAdapterModelNumber = 0x8B, - BusLogic_InquireSynchronousPeriod = 0x8C, - BusLogic_InquireExtendedSetupInformation = 0x8D, - BusLogic_EnableStrictRoundRobinMode = 0x8F, - BusLogic_StoreHostAdapterLocalRAM = 0x90, - BusLogic_FetchHostAdapterLocalRAM = 0x91, - BusLogic_StoreLocalDataInEEPROM = 0x92, - BusLogic_UploadAutoSCSICode = 0x94, - BusLogic_ModifyIOAddress = 0x95, - BusLogic_SetCCBFormat = 0x96, - BusLogic_WriteInquiryBuffer = 0x9A, - BusLogic_ReadInquiryBuffer = 0x9B, - BusLogic_FlashROMUploadDownload = 0xA7, - BusLogic_ReadSCAMData = 0xA8, - BusLogic_WriteSCAMData = 0xA9 -} -BusLogic_OperationCode_T; - - -/* - Define the Inquire Board ID reply structure. -*/ - -typedef struct BusLogic_BoardID -{ - unsigned char BoardType; /* Byte 0 */ - unsigned char CustomFeatures; /* Byte 1 */ - unsigned char FirmwareVersion1stDigit; /* Byte 2 */ - unsigned char FirmwareVersion2ndDigit; /* Byte 3 */ -} -BusLogic_BoardID_T; - - -/* - Define the Inquire Installed Devices ID 0 to 7 and Inquire Installed - Devices ID 8 to 15 reply type. For each Target Device, a byte is returned - where bit 0 set indicates that Logical Unit 0 exists, bit 1 set indicates - that Logical Unit 1 exists, and so on. -*/ - -typedef unsigned char BusLogic_InstalledDevices8_T[8]; - - -/* - Define the Inquire Target Devices reply type. Inquire Target Devices only - tests Logical Unit 0 of each Target Device unlike the Inquire Installed - Devices commands which test Logical Units 0 - 7. Two bytes are returned, - where byte 0 bit 0 set indicates that Target Device 0 exists, and so on. -*/ - -typedef unsigned short BusLogic_InstalledDevices_T; - - -/* - Define the Inquire Configuration reply structure. -*/ - -typedef struct BusLogic_Configuration -{ - unsigned char :5; /* Byte 0 Bits 0-4 */ - boolean DMA_Channel5:1; /* Byte 0 Bit 5 */ - boolean DMA_Channel6:1; /* Byte 0 Bit 6 */ - boolean DMA_Channel7:1; /* Byte 0 Bit 7 */ - boolean IRQ_Channel9:1; /* Byte 1 Bit 0 */ - boolean IRQ_Channel10:1; /* Byte 1 Bit 1 */ - boolean IRQ_Channel11:1; /* Byte 1 Bit 2 */ - boolean IRQ_Channel12:1; /* Byte 1 Bit 3 */ - unsigned char :1; /* Byte 1 Bit 4 */ - boolean IRQ_Channel14:1; /* Byte 1 Bit 5 */ - boolean IRQ_Channel15:1; /* Byte 1 Bit 6 */ - unsigned char :1; /* Byte 1 Bit 7 */ - unsigned char HostAdapterID:4; /* Byte 2 Bits 0-3 */ - unsigned char :4; /* Byte 2 Bits 4-7 */ -} -BusLogic_Configuration_T; - - -/* - Define the Inquire Setup Information reply structure. -*/ - -typedef struct BusLogic_SynchronousValue -{ - unsigned char Offset:4; /* Bits 0-3 */ - unsigned char TransferPeriod:3; /* Bits 4-6 */ - boolean Synchronous:1; /* Bit 7 */ -} -BusLogic_SynchronousValue_T; - -typedef BusLogic_SynchronousValue_T - BusLogic_SynchronousValues8_T[8]; - -typedef BusLogic_SynchronousValue_T - BusLogic_SynchronousValues_T[BusLogic_MaxTargetDevices]; - -typedef struct BusLogic_SetupInformation -{ - boolean SynchronousInitiationEnabled:1; /* Byte 0 Bit 0 */ - boolean ParityCheckingEnabled:1; /* Byte 0 Bit 1 */ - unsigned char :6; /* Byte 0 Bits 2-7 */ - unsigned char BusTransferRate; /* Byte 1 */ - unsigned char PreemptTimeOnBus; /* Byte 2 */ - unsigned char TimeOffBus; /* Byte 3 */ - unsigned char MailboxCount; /* Byte 4 */ - unsigned char MailboxAddress[3]; /* Bytes 5-7 */ - BusLogic_SynchronousValues8_T SynchronousValuesID0to7; /* Bytes 8-15 */ - unsigned char DisconnectPermittedID0to7; /* Byte 16 */ - unsigned char Signature; /* Byte 17 */ - unsigned char CharacterD; /* Byte 18 */ - unsigned char HostBusType; /* Byte 19 */ - unsigned char WideTransfersPermittedID0to7; /* Byte 20 */ - unsigned char WideTransfersActiveID0to7; /* Byte 21 */ - BusLogic_SynchronousValues8_T SynchronousValuesID8to15; /* Bytes 22-29 */ - unsigned char DisconnectPermittedID8to15; /* Byte 30 */ - unsigned char :8; /* Byte 31 */ - unsigned char WideTransfersPermittedID8to15; /* Byte 32 */ - unsigned char WideTransfersActiveID8to15; /* Byte 33 */ -} -BusLogic_SetupInformation_T; - - -/* - Define the Initialize Extended Mailbox request structure. -*/ - -typedef struct BusLogic_ExtendedMailboxRequest -{ - unsigned char MailboxCount; /* Byte 0 */ - BusLogic_BusAddress_T BaseMailboxAddress; /* Bytes 1-4 */ -} -__attribute__ ((packed)) -BusLogic_ExtendedMailboxRequest_T; - - -/* - Define the Inquire Firmware Version 3rd Digit reply type. -*/ - -typedef unsigned char BusLogic_FirmwareVersion3rdDigit_T; - - -/* - Define the Inquire Firmware Version Letter reply type. -*/ - -typedef unsigned char BusLogic_FirmwareVersionLetter_T; - - -/* - Define the Inquire PCI Host Adapter Information reply type. The ISA - Compatible I/O Port values are defined here and are also used with - the Modify I/O Address command. -*/ - -typedef enum BusLogic_ISACompatibleIOPort -{ - BusLogic_IO_330 = 0, - BusLogic_IO_334 = 1, - BusLogic_IO_230 = 2, - BusLogic_IO_234 = 3, - BusLogic_IO_130 = 4, - BusLogic_IO_134 = 5, - BusLogic_IO_Disable = 6, - BusLogic_IO_Disable2 = 7 -} -__attribute__ ((packed)) -BusLogic_ISACompatibleIOPort_T; - -typedef struct BusLogic_PCIHostAdapterInformation -{ - BusLogic_ISACompatibleIOPort_T ISACompatibleIOPort; /* Byte 0 */ - unsigned char PCIAssignedIRQChannel; /* Byte 1 */ - boolean LowByteTerminated:1; /* Byte 2 Bit 0 */ - boolean HighByteTerminated:1; /* Byte 2 Bit 1 */ - unsigned char :2; /* Byte 2 Bits 2-3 */ - boolean JP1:1; /* Byte 2 Bit 4 */ - boolean JP2:1; /* Byte 2 Bit 5 */ - boolean JP3:1; /* Byte 2 Bit 6 */ - boolean GenericInfoValid:1; /* Byte 2 Bit 7 */ - unsigned char :8; /* Byte 3 */ -} -BusLogic_PCIHostAdapterInformation_T; - - -/* - Define the Inquire Host Adapter Model Number reply type. -*/ - -typedef unsigned char BusLogic_HostAdapterModelNumber_T[5]; - - -/* - Define the Inquire Synchronous Period reply type. For each Target Device, - a byte is returned which represents the Synchronous Transfer Period in units - of 10 nanoseconds. -*/ - -typedef unsigned char BusLogic_SynchronousPeriod_T[BusLogic_MaxTargetDevices]; - - -/* - Define the Inquire Extended Setup Information reply structure. -*/ - -typedef struct BusLogic_ExtendedSetupInformation -{ - unsigned char BusType; /* Byte 0 */ - unsigned char BIOS_Address; /* Byte 1 */ - unsigned short ScatterGatherLimit; /* Bytes 2-3 */ - unsigned char MailboxCount; /* Byte 4 */ - BusLogic_BusAddress_T BaseMailboxAddress; /* Bytes 5-8 */ - struct { unsigned char :2; /* Byte 9 Bits 0-1 */ - boolean FastOnEISA:1; /* Byte 9 Bit 2 */ - unsigned char :3; /* Byte 9 Bits 3-5 */ - boolean LevelSensitiveInterrupt:1; /* Byte 9 Bit 6 */ - unsigned char :1; } Misc; /* Byte 9 Bit 7 */ - unsigned char FirmwareRevision[3]; /* Bytes 10-12 */ - boolean HostWideSCSI:1; /* Byte 13 Bit 0 */ - boolean HostDifferentialSCSI:1; /* Byte 13 Bit 1 */ - boolean HostSupportsSCAM:1; /* Byte 13 Bit 2 */ - boolean HostUltraSCSI:1; /* Byte 13 Bit 3 */ - boolean HostSmartTermination:1; /* Byte 13 Bit 4 */ - unsigned char :3; /* Byte 13 Bits 5-7 */ -} -__attribute__ ((packed)) -BusLogic_ExtendedSetupInformation_T; - - -/* - Define the Enable Strict Round Robin Mode request type. -*/ - -typedef enum BusLogic_RoundRobinModeRequest -{ - BusLogic_AggressiveRoundRobinMode = 0, - BusLogic_StrictRoundRobinMode = 1 -} -__attribute__ ((packed)) -BusLogic_RoundRobinModeRequest_T; - - -/* - Define the Fetch Host Adapter Local RAM request type. -*/ - -#define BusLogic_BIOS_BaseOffset 0 -#define BusLogic_AutoSCSI_BaseOffset 64 - -typedef struct BusLogic_FetchHostAdapterLocalRAMRequest -{ - unsigned char ByteOffset; /* Byte 0 */ - unsigned char ByteCount; /* Byte 1 */ -} -BusLogic_FetchHostAdapterLocalRAMRequest_T; - - -/* - Define the Host Adapter Local RAM AutoSCSI structure. -*/ - -typedef struct BusLogic_AutoSCSIData -{ - unsigned char InternalFactorySignature[2]; /* Bytes 0-1 */ - unsigned char InformationByteCount; /* Byte 2 */ - unsigned char HostAdapterType[6]; /* Bytes 3-8 */ - unsigned char :8; /* Byte 9 */ - boolean FloppyEnabled:1; /* Byte 10 Bit 0 */ - boolean FloppySecondary:1; /* Byte 10 Bit 1 */ - boolean LevelSensitiveInterrupt:1; /* Byte 10 Bit 2 */ - unsigned char :2; /* Byte 10 Bits 3-4 */ - unsigned char SystemRAMAreaForBIOS:3; /* Byte 10 Bits 5-7 */ - unsigned char DMA_Channel:7; /* Byte 11 Bits 0-6 */ - boolean DMA_AutoConfiguration:1; /* Byte 11 Bit 7 */ - unsigned char IRQ_Channel:7; /* Byte 12 Bits 0-6 */ - boolean IRQ_AutoConfiguration:1; /* Byte 12 Bit 7 */ - unsigned char DMA_TransferRate; /* Byte 13 */ - unsigned char SCSI_ID; /* Byte 14 */ - boolean LowByteTerminated:1; /* Byte 15 Bit 0 */ - boolean ParityCheckingEnabled:1; /* Byte 15 Bit 1 */ - boolean HighByteTerminated:1; /* Byte 15 Bit 2 */ - boolean NoisyCablingEnvironment:1; /* Byte 15 Bit 3 */ - boolean FastSynchronousNegotiation:1; /* Byte 15 Bit 4 */ - boolean BusResetEnabled:1; /* Byte 15 Bit 5 */ - boolean :1; /* Byte 15 Bit 6 */ - boolean ActiveNegationEnabled:1; /* Byte 15 Bit 7 */ - unsigned char BusOnDelay; /* Byte 16 */ - unsigned char BusOffDelay; /* Byte 17 */ - boolean HostAdapterBIOSEnabled:1; /* Byte 18 Bit 0 */ - boolean BIOSRedirectionOfINT19Enabled:1; /* Byte 18 Bit 1 */ - boolean ExtendedTranslationEnabled:1; /* Byte 18 Bit 2 */ - boolean MapRemovableAsFixedEnabled:1; /* Byte 18 Bit 3 */ - boolean :1; /* Byte 18 Bit 4 */ - boolean BIOSSupportsMoreThan2DrivesEnabled:1; /* Byte 18 Bit 5 */ - boolean BIOSInterruptModeEnabled:1; /* Byte 18 Bit 6 */ - boolean FlopticalSupportEnabled:1; /* Byte 19 Bit 7 */ - unsigned short DeviceEnabled; /* Bytes 19-20 */ - unsigned short WidePermitted; /* Bytes 21-22 */ - unsigned short FastPermitted; /* Bytes 23-24 */ - unsigned short SynchronousPermitted; /* Bytes 25-26 */ - unsigned short DisconnectPermitted; /* Bytes 27-28 */ - unsigned short SendStartUnitCommand; /* Bytes 29-30 */ - unsigned short IgnoreInBIOSScan; /* Bytes 31-32 */ - unsigned char PCIInterruptPin:2; /* Byte 33 Bits 0-1 */ - unsigned char HostAdapterIOPortAddress:2; /* Byte 33 Bits 2-3 */ - boolean StrictRoundRobinModeEnabled:1; /* Byte 33 Bit 4 */ - boolean VESABusSpeedGreaterThan33MHz:1; /* Byte 33 Bit 5 */ - boolean VESABurstWriteEnabled:1; /* Byte 33 Bit 6 */ - boolean VESABurstReadEnabled:1; /* Byte 33 Bit 7 */ - unsigned short UltraPermitted; /* Bytes 34-35 */ - unsigned int :32; /* Bytes 36-39 */ - unsigned char :8; /* Byte 40 */ - unsigned char AutoSCSIMaximumLUN; /* Byte 41 */ - boolean :1; /* Byte 42 Bit 0 */ - boolean SCAM_Dominant:1; /* Byte 42 Bit 1 */ - boolean SCAM_Enabled:1; /* Byte 42 Bit 2 */ - boolean SCAM_Level2:1; /* Byte 42 Bit 3 */ - unsigned char :4; /* Byte 42 Bits 4-7 */ - boolean INT13ExtensionEnabled:1; /* Byte 43 Bit 0 */ - boolean :1; /* Byte 43 Bit 1 */ - boolean CDROMBootEnabled:1; /* Byte 43 Bit 2 */ - unsigned char :5; /* Byte 43 Bits 3-7 */ - unsigned char BootTargetID:4; /* Byte 44 Bits 0-3 */ - unsigned char BootChannel:4; /* Byte 44 Bits 4-7 */ - unsigned char ForceBusDeviceScanningOrder:1; /* Byte 45 Bit 0 */ - unsigned char :7; /* Byte 45 Bits 1-7 */ - unsigned short NonTaggedToAlternateLUNPermitted; /* Bytes 46-47 */ - unsigned short RenegotiateSyncAfterCheckCondition; /* Bytes 48-49 */ - unsigned char Reserved[10]; /* Bytes 50-59 */ - unsigned char ManufacturingDiagnostic[2]; /* Bytes 60-61 */ - unsigned short Checksum; /* Bytes 62-63 */ -} -__attribute__ ((packed)) -BusLogic_AutoSCSIData_T; - - -/* - Define the Host Adapter Local RAM Auto SCSI Byte 45 structure. -*/ - -typedef struct BusLogic_AutoSCSIByte45 -{ - unsigned char ForceBusDeviceScanningOrder:1; /* Bit 0 */ - unsigned char :7; /* Bits 1-7 */ -} -BusLogic_AutoSCSIByte45_T; - - -/* - Define the Host Adapter Local RAM BIOS Drive Map Byte structure. -*/ - -#define BusLogic_BIOS_DriveMapOffset 17 - -typedef struct BusLogic_BIOSDriveMapByte -{ - unsigned char TargetIDBit3:1; /* Bit 0 */ - unsigned char :2; /* Bits 1-2 */ - BusLogic_BIOS_DiskGeometryTranslation_T DiskGeometry:2; /* Bits 3-4 */ - unsigned char TargetID:3; /* Bits 5-7 */ -} -BusLogic_BIOSDriveMapByte_T; - - -/* - Define the Modify I/O Address request type. On PCI Host Adapters, the - Modify I/O Address command allows modification of the ISA compatible I/O - Address that the Host Adapter responds to; it does not affect the PCI - compliant I/O Address assigned at system initialization. -*/ - -typedef BusLogic_ISACompatibleIOPort_T BusLogic_ModifyIOAddressRequest_T; - - -/* - Define the Set CCB Format request type. Extended LUN Format CCBs are - necessary to support more than 8 Logical Units per Target Device. -*/ - -typedef enum BusLogic_SetCCBFormatRequest -{ - BusLogic_LegacyLUNFormatCCB = 0, - BusLogic_ExtendedLUNFormatCCB = 1 -} -__attribute__ ((packed)) -BusLogic_SetCCBFormatRequest_T; - - -/* - Define the Requested Reply Length type used by the Inquire Setup Information, - Inquire Host Adapter Model Number, Inquire Synchronous Period, and Inquire - Extended Setup Information commands. -*/ - -typedef unsigned char BusLogic_RequestedReplyLength_T; - - -/* - Define the Outgoing Mailbox Action Codes. -*/ - -typedef enum -{ - BusLogic_OutgoingMailboxFree = 0x00, - BusLogic_MailboxStartCommand = 0x01, - BusLogic_MailboxAbortCommand = 0x02 -} -__attribute__ ((packed)) -BusLogic_ActionCode_T; - - -/* - Define the Incoming Mailbox Completion Codes. The MultiMaster Firmware - only uses codes 0 - 4. The FlashPoint SCCB Manager has no mailboxes, so - completion codes are stored in the CCB; it only uses codes 1, 2, 4, and 5. -*/ - -typedef enum -{ - BusLogic_IncomingMailboxFree = 0x00, - BusLogic_CommandCompletedWithoutError = 0x01, - BusLogic_CommandAbortedAtHostRequest = 0x02, - BusLogic_AbortedCommandNotFound = 0x03, - BusLogic_CommandCompletedWithError = 0x04, - BusLogic_InvalidCCB = 0x05 -} -__attribute__ ((packed)) -BusLogic_CompletionCode_T; - - -/* - Define the Command Control Block (CCB) Opcodes. -*/ - -typedef enum -{ - BusLogic_InitiatorCCB = 0x00, - BusLogic_TargetCCB = 0x01, - BusLogic_InitiatorCCB_ScatterGather = 0x02, - BusLogic_InitiatorCCB_ResidualDataLength = 0x03, - BusLogic_InitiatorCCB_ScatterGatherResidual = 0x04, - BusLogic_BusDeviceReset = 0x81 -} -__attribute__ ((packed)) -BusLogic_CCB_Opcode_T; - - -/* - Define the CCB Data Direction Codes. -*/ - -typedef enum -{ - BusLogic_UncheckedDataTransfer = 0, - BusLogic_DataInLengthChecked = 1, - BusLogic_DataOutLengthChecked = 2, - BusLogic_NoDataTransfer = 3 -} -BusLogic_DataDirection_T; - - -/* - Define the Host Adapter Status Codes. The MultiMaster Firmware does not - return status code 0x0C; it uses 0x12 for both overruns and underruns. -*/ - -typedef enum -{ - BusLogic_CommandCompletedNormally = 0x00, - BusLogic_LinkedCommandCompleted = 0x0A, - BusLogic_LinkedCommandCompletedWithFlag = 0x0B, - BusLogic_DataUnderRun = 0x0C, - BusLogic_SCSISelectionTimeout = 0x11, - BusLogic_DataOverRun = 0x12, - BusLogic_UnexpectedBusFree = 0x13, - BusLogic_InvalidBusPhaseRequested = 0x14, - BusLogic_InvalidOutgoingMailboxActionCode = 0x15, - BusLogic_InvalidCommandOperationCode = 0x16, - BusLogic_LinkedCCBhasInvalidLUN = 0x17, - BusLogic_InvalidCommandParameter = 0x1A, - BusLogic_AutoRequestSenseFailed = 0x1B, - BusLogic_TaggedQueuingMessageRejected = 0x1C, - BusLogic_UnsupportedMessageReceived = 0x1D, - BusLogic_HostAdapterHardwareFailed = 0x20, - BusLogic_TargetFailedResponseToATN = 0x21, - BusLogic_HostAdapterAssertedRST = 0x22, - BusLogic_OtherDeviceAssertedRST = 0x23, - BusLogic_TargetDeviceReconnectedImproperly = 0x24, - BusLogic_HostAdapterAssertedBusDeviceReset = 0x25, - BusLogic_AbortQueueGenerated = 0x26, - BusLogic_HostAdapterSoftwareError = 0x27, - BusLogic_HostAdapterHardwareTimeoutError = 0x30, - BusLogic_SCSIParityErrorDetected = 0x34 -} -__attribute__ ((packed)) -BusLogic_HostAdapterStatus_T; - - -/* - Define the SCSI Target Device Status Codes. -*/ - -typedef enum -{ - BusLogic_OperationGood = 0x00, - BusLogic_CheckCondition = 0x02, - BusLogic_DeviceBusy = 0x08 -} -__attribute__ ((packed)) -BusLogic_TargetDeviceStatus_T; - - -/* - Define the Queue Tag Codes. -*/ - -typedef enum -{ - BusLogic_SimpleQueueTag = 0, - BusLogic_HeadOfQueueTag = 1, - BusLogic_OrderedQueueTag = 2, - BusLogic_ReservedQT = 3 -} -BusLogic_QueueTag_T; - - -/* - Define the SCSI Command Descriptor Block (CDB). -*/ - -#define BusLogic_CDB_MaxLength 12 - -typedef unsigned char SCSI_CDB_T[BusLogic_CDB_MaxLength]; - - -/* - Define the Scatter/Gather Segment structure required by the MultiMaster - Firmware Interface and the FlashPoint SCCB Manager. -*/ - -typedef struct BusLogic_ScatterGatherSegment -{ - BusLogic_ByteCount_T SegmentByteCount; /* Bytes 0-3 */ - BusLogic_BusAddress_T SegmentDataPointer; /* Bytes 4-7 */ -} -BusLogic_ScatterGatherSegment_T; - - -/* - Define the Driver CCB Status Codes. -*/ - -typedef enum -{ - BusLogic_CCB_Free = 0, - BusLogic_CCB_Active = 1, - BusLogic_CCB_Completed = 2, - BusLogic_CCB_Reset = 3 -} -__attribute__ ((packed)) -BusLogic_CCB_Status_T; - - -/* - Define the 32 Bit Mode Command Control Block (CCB) structure. The first 40 - bytes are defined by and common to both the MultiMaster Firmware and the - FlashPoint SCCB Manager. The next 60 bytes are defined by the FlashPoint - SCCB Manager. The remaining components are defined by the Linux BusLogic - Driver. Extended LUN Format CCBs differ from Legacy LUN Format 32 Bit Mode - CCBs only in having the TagEnable and QueueTag fields moved from byte 17 to - byte 1, and the Logical Unit field in byte 17 expanded to 6 bits. In theory, - Extended LUN Format CCBs can support up to 64 Logical Units, but in practice - many devices will respond improperly to Logical Units between 32 and 63, and - the SCSI-2 specification defines Bit 5 as LUNTAR. Extended LUN Format CCBs - are used by recent versions of the MultiMaster Firmware, as well as by the - FlashPoint SCCB Manager; the FlashPoint SCCB Manager only supports 32 Logical - Units. Since 64 Logical Units are unlikely to be needed in practice, and - since they are problematic for the above reasons, and since limiting them to - 5 bits simplifies the CCB structure definition, this driver only supports - 32 Logical Units per Target Device. -*/ - -typedef struct BusLogic_CCB -{ - /* - MultiMaster Firmware and FlashPoint SCCB Manager Common Portion. - */ - BusLogic_CCB_Opcode_T Opcode; /* Byte 0 */ - unsigned char :3; /* Byte 1 Bits 0-2 */ - BusLogic_DataDirection_T DataDirection:2; /* Byte 1 Bits 3-4 */ - boolean TagEnable:1; /* Byte 1 Bit 5 */ - BusLogic_QueueTag_T QueueTag:2; /* Byte 1 Bits 6-7 */ - unsigned char CDB_Length; /* Byte 2 */ - unsigned char SenseDataLength; /* Byte 3 */ - BusLogic_ByteCount_T DataLength; /* Bytes 4-7 */ - BusLogic_BusAddress_T DataPointer; /* Bytes 8-11 */ - unsigned char :8; /* Byte 12 */ - unsigned char :8; /* Byte 13 */ - BusLogic_HostAdapterStatus_T HostAdapterStatus; /* Byte 14 */ - BusLogic_TargetDeviceStatus_T TargetDeviceStatus; /* Byte 15 */ - unsigned char TargetID; /* Byte 16 */ - unsigned char LogicalUnit:5; /* Byte 17 Bits 0-4 */ - boolean LegacyTagEnable:1; /* Byte 17 Bit 5 */ - BusLogic_QueueTag_T LegacyQueueTag:2; /* Byte 17 Bits 6-7 */ - SCSI_CDB_T CDB; /* Bytes 18-29 */ - unsigned char :8; /* Byte 30 */ - unsigned char :8; /* Byte 31 */ - unsigned int :32; /* Bytes 32-35 */ - BusLogic_BusAddress_T SenseDataPointer; /* Bytes 36-39 */ - /* - FlashPoint SCCB Manager Defined Portion. - */ - void (*CallbackFunction)(struct BusLogic_CCB *); /* Bytes 40-43 */ - BusLogic_Base_Address_T BaseAddress; /* Bytes 44-47 */ - BusLogic_CompletionCode_T CompletionCode; /* Byte 48 */ -#ifndef CONFIG_SCSI_OMIT_FLASHPOINT - unsigned char :8; /* Byte 49 */ - unsigned short OS_Flags; /* Bytes 50-51 */ - unsigned char Private[48]; /* Bytes 52-99 */ -#endif - /* - BusLogic Linux Driver Defined Portion. - */ - boolean AllocationGroupHead; - BusLogic_CCB_Status_T Status; - unsigned long SerialNumber; - SCSI_Command_T *Command; - struct BusLogic_HostAdapter *HostAdapter; - struct BusLogic_CCB *Next; - struct BusLogic_CCB *NextAll; - BusLogic_ScatterGatherSegment_T - ScatterGatherList[BusLogic_ScatterGatherLimit]; -} -BusLogic_CCB_T; - - -/* - Define the 32 Bit Mode Outgoing Mailbox structure. -*/ - -typedef struct BusLogic_OutgoingMailbox -{ - BusLogic_BusAddress_T CCB; /* Bytes 0-3 */ - unsigned int :24; /* Bytes 4-6 */ - BusLogic_ActionCode_T ActionCode; /* Byte 7 */ -} -BusLogic_OutgoingMailbox_T; - - -/* - Define the 32 Bit Mode Incoming Mailbox structure. -*/ - -typedef struct BusLogic_IncomingMailbox -{ - BusLogic_BusAddress_T CCB; /* Bytes 0-3 */ - BusLogic_HostAdapterStatus_T HostAdapterStatus; /* Byte 4 */ - BusLogic_TargetDeviceStatus_T TargetDeviceStatus; /* Byte 5 */ - unsigned char :8; /* Byte 6 */ - BusLogic_CompletionCode_T CompletionCode; /* Byte 7 */ -} -BusLogic_IncomingMailbox_T; - - -/* - Define the BusLogic Driver Options structure. -*/ - -typedef struct BusLogic_DriverOptions -{ - unsigned short TaggedQueuingPermitted; - unsigned short TaggedQueuingPermittedMask; - unsigned short BusSettleTime; - BusLogic_LocalOptions_T LocalOptions; - unsigned char CommonQueueDepth; - unsigned char QueueDepth[BusLogic_MaxTargetDevices]; - BusLogic_ErrorRecoveryStrategy_T - ErrorRecoveryStrategy[BusLogic_MaxTargetDevices]; -} -BusLogic_DriverOptions_T; - - -/* - Define the Host Adapter Target Flags structure. -*/ - -typedef struct BusLogic_TargetFlags -{ - boolean TargetExists:1; - boolean TaggedQueuingSupported:1; - boolean WideTransfersSupported:1; - boolean TaggedQueuingActive:1; - boolean WideTransfersActive:1; - boolean CommandSuccessfulFlag:1; - boolean TargetInfoReported:1; -} -BusLogic_TargetFlags_T; - - -/* - Define the Host Adapter Target Statistics structure. -*/ - -#define BusLogic_SizeBuckets 10 - -typedef unsigned int BusLogic_CommandSizeBuckets_T[BusLogic_SizeBuckets]; - -typedef struct BusLogic_TargetStatistics -{ - unsigned int CommandsAttempted; - unsigned int CommandsCompleted; - unsigned int ReadCommands; - unsigned int WriteCommands; - BusLogic_ByteCounter_T TotalBytesRead; - BusLogic_ByteCounter_T TotalBytesWritten; - BusLogic_CommandSizeBuckets_T ReadCommandSizeBuckets; - BusLogic_CommandSizeBuckets_T WriteCommandSizeBuckets; - unsigned short CommandAbortsRequested; - unsigned short CommandAbortsAttempted; - unsigned short CommandAbortsCompleted; - unsigned short BusDeviceResetsRequested; - unsigned short BusDeviceResetsAttempted; - unsigned short BusDeviceResetsCompleted; - unsigned short HostAdapterResetsRequested; - unsigned short HostAdapterResetsAttempted; - unsigned short HostAdapterResetsCompleted; -} -BusLogic_TargetStatistics_T; - - -/* - Define the FlashPoint Card Handle data type. -*/ - -#define FlashPoint_BadCardHandle 0xFFFFFFFF - -typedef unsigned int FlashPoint_CardHandle_T; - - -/* - Define the FlashPoint Information structure. This structure is defined - by the FlashPoint SCCB Manager. -*/ - -typedef struct FlashPoint_Info -{ - BusLogic_Base_Address_T BaseAddress; /* Bytes 0-3 */ - boolean Present; /* Byte 4 */ - unsigned char IRQ_Channel; /* Byte 5 */ - unsigned char SCSI_ID; /* Byte 6 */ - unsigned char SCSI_LUN; /* Byte 7 */ - unsigned short FirmwareRevision; /* Bytes 8-9 */ - unsigned short SynchronousPermitted; /* Bytes 10-11 */ - unsigned short FastPermitted; /* Bytes 12-13 */ - unsigned short UltraPermitted; /* Bytes 14-15 */ - unsigned short DisconnectPermitted; /* Bytes 16-17 */ - unsigned short WidePermitted; /* Bytes 18-19 */ - boolean ParityCheckingEnabled:1; /* Byte 20 Bit 0 */ - boolean HostWideSCSI:1; /* Byte 20 Bit 1 */ - boolean HostSoftReset:1; /* Byte 20 Bit 2 */ - boolean ExtendedTranslationEnabled:1; /* Byte 20 Bit 3 */ - boolean LowByteTerminated:1; /* Byte 20 Bit 4 */ - boolean HighByteTerminated:1; /* Byte 20 Bit 5 */ - boolean ReportDataUnderrun:1; /* Byte 20 Bit 6 */ - boolean SCAM_Enabled:1; /* Byte 20 Bit 7 */ - boolean SCAM_Level2:1; /* Byte 21 Bit 0 */ - unsigned char :7; /* Byte 21 Bits 1-7 */ - unsigned char Family; /* Byte 22 */ - unsigned char BusType; /* Byte 23 */ - unsigned char ModelNumber[3]; /* Bytes 24-26 */ - unsigned char RelativeCardNumber; /* Byte 27 */ - unsigned char Reserved[4]; /* Bytes 28-31 */ - unsigned int OS_Reserved; /* Bytes 32-35 */ - unsigned char TranslationInfo[4]; /* Bytes 36-39 */ - unsigned int Reserved2[5]; /* Bytes 40-59 */ - unsigned int SecondaryRange; /* Bytes 60-63 */ -} -FlashPoint_Info_T; - - -/* - Define the BusLogic Driver Host Adapter structure. -*/ - -typedef struct BusLogic_HostAdapter -{ - SCSI_Host_T *SCSI_Host; - BusLogic_HostAdapterType_T HostAdapterType; - BusLogic_HostAdapterBusType_T HostAdapterBusType; - BusLogic_IO_Address_T IO_Address; - BusLogic_PCI_Address_T PCI_Address; - unsigned short AddressCount; - unsigned char HostNumber; - unsigned char ModelName[9]; - unsigned char FirmwareVersion[6]; - unsigned char FullModelName[18]; - unsigned char Bus; - unsigned char Device; - unsigned char IRQ_Channel; - unsigned char DMA_Channel; - unsigned char SCSI_ID; - boolean IRQ_ChannelAcquired:1; - boolean DMA_ChannelAcquired:1; - boolean ExtendedTranslationEnabled:1; - boolean ParityCheckingEnabled:1; - boolean BusResetEnabled:1; - boolean LevelSensitiveInterrupt:1; - boolean HostWideSCSI:1; - boolean HostDifferentialSCSI:1; - boolean HostSupportsSCAM:1; - boolean HostUltraSCSI:1; - boolean ExtendedLUNSupport:1; - boolean TerminationInfoValid:1; - boolean LowByteTerminated:1; - boolean HighByteTerminated:1; - boolean BounceBuffersRequired:1; - boolean StrictRoundRobinModeSupport:1; - boolean SCAM_Enabled:1; - boolean SCAM_Level2:1; - boolean HostAdapterInitialized:1; - boolean HostAdapterExternalReset:1; - boolean HostAdapterInternalError:1; - boolean ProcessCompletedCCBsActive; - volatile boolean HostAdapterCommandCompleted; - unsigned short HostAdapterScatterGatherLimit; - unsigned short DriverScatterGatherLimit; - unsigned short MaxTargetDevices; - unsigned short MaxLogicalUnits; - unsigned short MailboxCount; - unsigned short InitialCCBs; - unsigned short IncrementalCCBs; - unsigned short AllocatedCCBs; - unsigned short DriverQueueDepth; - unsigned short HostAdapterQueueDepth; - unsigned short UntaggedQueueDepth; - unsigned short CommonQueueDepth; - unsigned short BusSettleTime; - unsigned short SynchronousPermitted; - unsigned short FastPermitted; - unsigned short UltraPermitted; - unsigned short WidePermitted; - unsigned short DisconnectPermitted; - unsigned short TaggedQueuingPermitted; - unsigned short ExternalHostAdapterResets; - unsigned short HostAdapterInternalErrors; - unsigned short TargetDeviceCount; - unsigned short MessageBufferLength; - BusLogic_BusAddress_T BIOS_Address; - BusLogic_DriverOptions_T *DriverOptions; - FlashPoint_Info_T FlashPointInfo; - FlashPoint_CardHandle_T CardHandle; - struct BusLogic_HostAdapter *Next; - BusLogic_CCB_T *All_CCBs; - BusLogic_CCB_T *Free_CCBs; - BusLogic_CCB_T *FirstCompletedCCB; - BusLogic_CCB_T *LastCompletedCCB; - BusLogic_CCB_T *BusDeviceResetPendingCCB[BusLogic_MaxTargetDevices]; - BusLogic_ErrorRecoveryStrategy_T - ErrorRecoveryStrategy[BusLogic_MaxTargetDevices]; - BusLogic_TargetFlags_T TargetFlags[BusLogic_MaxTargetDevices]; - unsigned char QueueDepth[BusLogic_MaxTargetDevices]; - unsigned char SynchronousPeriod[BusLogic_MaxTargetDevices]; - unsigned char SynchronousOffset[BusLogic_MaxTargetDevices]; - unsigned char ActiveCommands[BusLogic_MaxTargetDevices]; - unsigned int CommandsSinceReset[BusLogic_MaxTargetDevices]; - unsigned long LastSequencePoint[BusLogic_MaxTargetDevices]; - unsigned long LastResetAttempted[BusLogic_MaxTargetDevices]; - unsigned long LastResetCompleted[BusLogic_MaxTargetDevices]; - BusLogic_OutgoingMailbox_T *FirstOutgoingMailbox; - BusLogic_OutgoingMailbox_T *LastOutgoingMailbox; - BusLogic_OutgoingMailbox_T *NextOutgoingMailbox; - BusLogic_IncomingMailbox_T *FirstIncomingMailbox; - BusLogic_IncomingMailbox_T *LastIncomingMailbox; - BusLogic_IncomingMailbox_T *NextIncomingMailbox; - BusLogic_TargetStatistics_T TargetStatistics[BusLogic_MaxTargetDevices]; - unsigned char MailboxSpace[BusLogic_MaxMailboxes - * (sizeof(BusLogic_OutgoingMailbox_T) - + sizeof(BusLogic_IncomingMailbox_T))]; - char MessageBuffer[BusLogic_MessageBufferSize]; -} -BusLogic_HostAdapter_T; - - -/* - Define a structure for the BIOS Disk Parameters. -*/ - -typedef struct BIOS_DiskParameters -{ - int Heads; - int Sectors; - int Cylinders; -} -BIOS_DiskParameters_T; - - -/* - Define a structure for the SCSI Inquiry command results. -*/ - -typedef struct SCSI_Inquiry -{ - unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */ - unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */ - unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */ - boolean RMB:1; /* Byte 1 Bit 7 */ - unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */ - unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */ - unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */ - unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */ - unsigned char :2; /* Byte 3 Bits 4-5 */ - boolean TrmIOP:1; /* Byte 3 Bit 6 */ - boolean AENC:1; /* Byte 3 Bit 7 */ - unsigned char AdditionalLength; /* Byte 4 */ - unsigned char :8; /* Byte 5 */ - unsigned char :8; /* Byte 6 */ - boolean SftRe:1; /* Byte 7 Bit 0 */ - boolean CmdQue:1; /* Byte 7 Bit 1 */ - boolean :1; /* Byte 7 Bit 2 */ - boolean Linked:1; /* Byte 7 Bit 3 */ - boolean Sync:1; /* Byte 7 Bit 4 */ - boolean WBus16:1; /* Byte 7 Bit 5 */ - boolean WBus32:1; /* Byte 7 Bit 6 */ - boolean RelAdr:1; /* Byte 7 Bit 7 */ - unsigned char VendorIdentification[8]; /* Bytes 8-15 */ - unsigned char ProductIdentification[16]; /* Bytes 16-31 */ - unsigned char ProductRevisionLevel[4]; /* Bytes 32-35 */ -} -SCSI_Inquiry_T; - - -/* - BusLogic_AcquireHostAdapterLock acquires exclusive access to Host Adapter. -*/ - -static inline -void BusLogic_AcquireHostAdapterLock(BusLogic_HostAdapter_T *HostAdapter, - ProcessorFlags_T *ProcessorFlags) -{ -} - - -/* - BusLogic_ReleaseHostAdapterLock releases exclusive access to Host Adapter. -*/ - -static inline -void BusLogic_ReleaseHostAdapterLock(BusLogic_HostAdapter_T *HostAdapter, - ProcessorFlags_T *ProcessorFlags) -{ -} - - -/* - BusLogic_AcquireHostAdapterLockIH acquires exclusive access to Host Adapter, - but is only called from the interrupt handler. -*/ - -static inline -void BusLogic_AcquireHostAdapterLockIH(BusLogic_HostAdapter_T *HostAdapter, - ProcessorFlags_T *ProcessorFlags) -{ - spin_lock_irqsave(&io_request_lock, *ProcessorFlags); -} - - -/* - BusLogic_ReleaseHostAdapterLockIH releases exclusive access to Host Adapter, - but is only called from the interrupt handler. -*/ - -static inline -void BusLogic_ReleaseHostAdapterLockIH(BusLogic_HostAdapter_T *HostAdapter, - ProcessorFlags_T *ProcessorFlags) -{ - spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags); -} - - -/* - Define functions to provide an abstraction for reading and writing the - Host Adapter I/O Registers. -*/ - -static inline -void BusLogic_SCSIBusReset(BusLogic_HostAdapter_T *HostAdapter) -{ - BusLogic_ControlRegister_T ControlRegister; - ControlRegister.All = 0; - ControlRegister.Bits.SCSIBusReset = true; - outb(ControlRegister.All, - HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); -} - -static inline -void BusLogic_InterruptReset(BusLogic_HostAdapter_T *HostAdapter) -{ - BusLogic_ControlRegister_T ControlRegister; - ControlRegister.All = 0; - ControlRegister.Bits.InterruptReset = true; - outb(ControlRegister.All, - HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); -} - -static inline -void BusLogic_SoftReset(BusLogic_HostAdapter_T *HostAdapter) -{ - BusLogic_ControlRegister_T ControlRegister; - ControlRegister.All = 0; - ControlRegister.Bits.SoftReset = true; - outb(ControlRegister.All, - HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); -} - -static inline -void BusLogic_HardReset(BusLogic_HostAdapter_T *HostAdapter) -{ - BusLogic_ControlRegister_T ControlRegister; - ControlRegister.All = 0; - ControlRegister.Bits.HardReset = true; - outb(ControlRegister.All, - HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); -} - -static inline -unsigned char BusLogic_ReadStatusRegister(BusLogic_HostAdapter_T *HostAdapter) -{ - return inb(HostAdapter->IO_Address + BusLogic_StatusRegisterOffset); -} - -static inline -void BusLogic_WriteCommandParameterRegister(BusLogic_HostAdapter_T - *HostAdapter, - unsigned char Value) -{ - outb(Value, - HostAdapter->IO_Address + BusLogic_CommandParameterRegisterOffset); -} - -static inline -unsigned char BusLogic_ReadDataInRegister(BusLogic_HostAdapter_T *HostAdapter) -{ - return inb(HostAdapter->IO_Address + BusLogic_DataInRegisterOffset); -} - -static inline -unsigned char BusLogic_ReadInterruptRegister(BusLogic_HostAdapter_T - *HostAdapter) -{ - return inb(HostAdapter->IO_Address + BusLogic_InterruptRegisterOffset); -} - -static inline -unsigned char BusLogic_ReadGeometryRegister(BusLogic_HostAdapter_T - *HostAdapter) -{ - return inb(HostAdapter->IO_Address + BusLogic_GeometryRegisterOffset); -} - - -/* - BusLogic_StartMailboxCommand issues an Execute Mailbox Command, which - notifies the Host Adapter that an entry has been made in an Outgoing - Mailbox. -*/ - -static inline -void BusLogic_StartMailboxCommand(BusLogic_HostAdapter_T *HostAdapter) -{ - BusLogic_WriteCommandParameterRegister(HostAdapter, - BusLogic_ExecuteMailboxCommand); -} - - -/* - BusLogic_Delay waits for Seconds to elapse. -*/ - -static inline void BusLogic_Delay(int Seconds) -{ - int Milliseconds = 1000 * Seconds; - unsigned long ProcessorFlags; - save_flags(ProcessorFlags); - sti(); - while (--Milliseconds >= 0) udelay(1000); - restore_flags(ProcessorFlags); -} - - -/* - Virtual_to_Bus and Bus_to_Virtual map between Kernel Virtual Addresses - and PCI/VLB/EISA/ISA Bus Addresses. -*/ - -static inline BusLogic_BusAddress_T Virtual_to_Bus(void *VirtualAddress) -{ - return (BusLogic_BusAddress_T) virt_to_bus(VirtualAddress); -} - -static inline void *Bus_to_Virtual(BusLogic_BusAddress_T BusAddress) -{ - return (void *) bus_to_virt(BusAddress); -} - - -/* - Virtual_to_32Bit_Virtual maps between Kernel Virtual Addresses and - 32 bit Kernel Virtual Addresses. This avoids compilation warnings - on 64 bit architectures. -*/ - -static inline -BusLogic_BusAddress_T Virtual_to_32Bit_Virtual(void *VirtualAddress) -{ - return (BusLogic_BusAddress_T) (unsigned long) VirtualAddress; -} - - -/* - BusLogic_IncrementErrorCounter increments Error Counter by 1, stopping at - 65535 rather than wrapping around to 0. -*/ - -static inline void BusLogic_IncrementErrorCounter(unsigned short *ErrorCounter) -{ - if (*ErrorCounter < 65535) (*ErrorCounter)++; -} - - -/* - BusLogic_IncrementByteCounter increments Byte Counter by Amount. -*/ - -static inline void BusLogic_IncrementByteCounter(BusLogic_ByteCounter_T - *ByteCounter, - unsigned int Amount) -{ - ByteCounter->Units += Amount; - if (ByteCounter->Units > 999999999) - { - ByteCounter->Units -= 1000000000; - ByteCounter->Billions++; - } -} - - -/* - BusLogic_IncrementSizeBucket increments the Bucket for Amount. -*/ - -static inline void BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T - CommandSizeBuckets, - unsigned int Amount) -{ - int Index = 0; - if (Amount < 8*1024) - { - if (Amount < 2*1024) - Index = (Amount < 1*1024 ? 0 : 1); - else Index = (Amount < 4*1024 ? 2 : 3); - } - else if (Amount < 128*1024) - { - if (Amount < 32*1024) - Index = (Amount < 16*1024 ? 4 : 5); - else Index = (Amount < 64*1024 ? 6 : 7); - } - else Index = (Amount < 256*1024 ? 8 : 9); - CommandSizeBuckets[Index]++; -} - - -/* - Define the version number of the FlashPoint Firmware (SCCB Manager). -*/ - -#define FlashPoint_FirmwareVersion "5.02" - - -/* - Define the possible return values from FlashPoint_HandleInterrupt. -*/ - -#define FlashPoint_NormalInterrupt 0x00 -#define FlashPoint_InternalError 0xFE -#define FlashPoint_ExternalBusReset 0xFF - - -/* - Define prototypes for the forward referenced BusLogic Driver - Internal Functions. -*/ - -static void BusLogic_QueueCompletedCCB(BusLogic_CCB_T *); -static void BusLogic_InterruptHandler(int, void *, Registers_T *); -static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *, - SCSI_Command_T *, unsigned int); -static void BusLogic_Message(BusLogic_MessageLevel_T, char *, - BusLogic_HostAdapter_T *, ...); - -/* - Declare the Initialization Functions. -*/ - -static void BusLogic_AnnounceDriver(BusLogic_HostAdapter_T *) __init; -static void BusLogic_RegisterHostAdapter(BusLogic_HostAdapter_T *) __init; -static void BusLogic_UnregisterHostAdapter(BusLogic_HostAdapter_T *) __init; -static boolean BusLogic_CreateInitialCCBs(BusLogic_HostAdapter_T *) __init; -static void BusLogic_DestroyCCBs(BusLogic_HostAdapter_T *) __init; -static void BusLogic_AppendProbeAddressISA(BusLogic_IO_Address_T) __init; -static void -BusLogic_InitializeProbeInfoListISA(BusLogic_HostAdapter_T *) __init; -static void BusLogic_SortProbeInfo(BusLogic_ProbeInfo_T *, int) __init; -static int -BusLogic_InitializeMultiMasterProbeInfo(BusLogic_HostAdapter_T *) __init; -static int -BusLogic_InitializeFlashPointProbeInfo(BusLogic_HostAdapter_T *) __init; -static void BusLogic_InitializeProbeInfoList(BusLogic_HostAdapter_T *) __init; -static boolean BusLogic_Failure(BusLogic_HostAdapter_T *, char *) __init; -static boolean BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *) __init; -static boolean BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *) __init; -static boolean -BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T *) __init; -static boolean -BusLogic_ReportHostAdapterConfiguration(BusLogic_HostAdapter_T *) __init; -static boolean BusLogic_AcquireResources(BusLogic_HostAdapter_T *) __init; -static void BusLogic_ReleaseResources(BusLogic_HostAdapter_T *) __init; -static boolean BusLogic_TargetDeviceInquiry(BusLogic_HostAdapter_T *) __init; -static void BusLogic_InitializeHostStructure(BusLogic_HostAdapter_T *, - SCSI_Host_T *) __init; -#if 0 /* XEN */ -static boolean BusLogic_ParseKeyword(char **, char *) __init; -static int BusLogic_ParseDriverOptions(char *) __init; -static int BusLogic_Setup(char *) __init; -#endif - - -#endif /* BusLogic_DriverVersion */ diff --git a/xen/drivers/scsi/FlashPoint.c.inc b/xen/drivers/scsi/FlashPoint.c.inc deleted file mode 100644 index 1416284e84..0000000000 --- a/xen/drivers/scsi/FlashPoint.c.inc +++ /dev/null @@ -1,12159 +0,0 @@ -/* - - FlashPoint.c -- FlashPoint SCCB Manager for Linux - - This file contains the FlashPoint SCCB Manager from BusLogic's FlashPoint - Driver Developer's Kit, with minor modifications by Leonard N. Zubkoff for - Linux compatibility. It was provided by BusLogic in the form of 16 separate - source files, which would have unnecessarily cluttered the scsi directory, so - the individual files have been combined into this single file. - - Copyright 1995-1996 by Mylex Corporation. All Rights Reserved - - This file is available under both the GNU General Public License - and a BSD-style copyright; see LICENSE.FlashPoint for details. - -*/ - - -#include - - -#ifndef CONFIG_SCSI_OMIT_FLASHPOINT - - -#define UNIX -#define FW_TYPE _SCCB_MGR_ -#define MAX_CARDS 8 -#undef BUSTYPE_PCI - - -#define OS_InPortByte(port) inb(port) -#define OS_InPortWord(port) inw(port) -#define OS_InPortLong(port) inl(port) -#define OS_OutPortByte(port, value) outb(value, port) -#define OS_OutPortWord(port, value) outw(value, port) -#define OS_OutPortLong(port, value) outl(value, port) -#define OS_Lock(x) -#define OS_UnLock(x) - - -/* - Define name replacements for compatibility with the Linux BusLogic Driver. -*/ - -#define SccbMgr_sense_adapter FlashPoint_ProbeHostAdapter -#define SccbMgr_config_adapter FlashPoint_HardwareResetHostAdapter -#define SccbMgr_unload_card FlashPoint_ReleaseHostAdapter -#define SccbMgr_start_sccb FlashPoint_StartCCB -#define SccbMgr_abort_sccb FlashPoint_AbortCCB -#define SccbMgr_my_int FlashPoint_InterruptPending -#define SccbMgr_isr FlashPoint_HandleInterrupt - - -/* - Define name replacements to avoid kernel namespace pollution. -*/ - -#define BL_Card FPT_BL_Card -#define BusMasterInit FPT_BusMasterInit -#define CalcCrc16 FPT_CalcCrc16 -#define CalcLrc FPT_CalcLrc -#define ChkIfChipInitialized FPT_ChkIfChipInitialized -#define DiagBusMaster FPT_DiagBusMaster -#define DiagEEPROM FPT_DiagEEPROM -#define DiagXbow FPT_DiagXbow -#define GetTarLun FPT_GetTarLun -#define RNVRamData FPT_RNVRamData -#define RdStack FPT_RdStack -#define SccbMgrTableInitAll FPT_SccbMgrTableInitAll -#define SccbMgrTableInitCard FPT_SccbMgrTableInitCard -#define SccbMgrTableInitTarget FPT_SccbMgrTableInitTarget -#define SccbMgr_bad_isr FPT_SccbMgr_bad_isr -#define SccbMgr_scsi_reset FPT_SccbMgr_scsi_reset -#define SccbMgr_timer_expired FPT_SccbMgr_timer_expired -#define SendMsg FPT_SendMsg -#define Wait FPT_Wait -#define Wait1Second FPT_Wait1Second -#define WrStack FPT_WrStack -#define XbowInit FPT_XbowInit -#define autoCmdCmplt FPT_autoCmdCmplt -#define autoLoadDefaultMap FPT_autoLoadDefaultMap -#define busMstrDataXferStart FPT_busMstrDataXferStart -#define busMstrSGDataXferStart FPT_busMstrSGDataXferStart -#define busMstrTimeOut FPT_busMstrTimeOut -#define dataXferProcessor FPT_dataXferProcessor -#define default_intena FPT_default_intena -#define hostDataXferAbort FPT_hostDataXferAbort -#define hostDataXferRestart FPT_hostDataXferRestart -#define inisci FPT_inisci -#define mbCards FPT_mbCards -#define nvRamInfo FPT_nvRamInfo -#define phaseBusFree FPT_phaseBusFree -#define phaseChkFifo FPT_phaseChkFifo -#define phaseCommand FPT_phaseCommand -#define phaseDataIn FPT_phaseDataIn -#define phaseDataOut FPT_phaseDataOut -#define phaseDecode FPT_phaseDecode -#define phaseIllegal FPT_phaseIllegal -#define phaseMsgIn FPT_phaseMsgIn -#define phaseMsgOut FPT_phaseMsgOut -#define phaseStatus FPT_phaseStatus -#define queueAddSccb FPT_queueAddSccb -#define queueCmdComplete FPT_queueCmdComplete -#define queueDisconnect FPT_queueDisconnect -#define queueFindSccb FPT_queueFindSccb -#define queueFlushSccb FPT_queueFlushSccb -#define queueFlushTargSccb FPT_queueFlushTargSccb -#define queueSearchSelect FPT_queueSearchSelect -#define queueSelectFail FPT_queueSelectFail -#define s_PhaseTbl FPT_s_PhaseTbl -#define scamHAString FPT_scamHAString -#define scamInfo FPT_scamInfo -#define scarb FPT_scarb -#define scasid FPT_scasid -#define scbusf FPT_scbusf -#define sccbMgrTbl FPT_sccbMgrTbl -#define schkdd FPT_schkdd -#define scini FPT_scini -#define sciso FPT_sciso -#define scmachid FPT_scmachid -#define scsavdi FPT_scsavdi -#define scsel FPT_scsel -#define scsell FPT_scsell -#define scsendi FPT_scsendi -#define scvalq FPT_scvalq -#define scwirod FPT_scwirod -#define scwiros FPT_scwiros -#define scwtsel FPT_scwtsel -#define scxferc FPT_scxferc -#define sdecm FPT_sdecm -#define sfm FPT_sfm -#define shandem FPT_shandem -#define sinits FPT_sinits -#define sisyncn FPT_sisyncn -#define sisyncr FPT_sisyncr -#define siwidn FPT_siwidn -#define siwidr FPT_siwidr -#define sres FPT_sres -#define sresb FPT_sresb -#define ssel FPT_ssel -#define ssenss FPT_ssenss -#define sssyncv FPT_sssyncv -#define stsyncn FPT_stsyncn -#define stwidn FPT_stwidn -#define sxfrp FPT_sxfrp -#define utilEERead FPT_utilEERead -#define utilEEReadOrg FPT_utilEEReadOrg -#define utilEESendCmdAddr FPT_utilEESendCmdAddr -#define utilEEWrite FPT_utilEEWrite -#define utilEEWriteOnOff FPT_utilEEWriteOnOff -#define utilUpdateResidual FPT_utilUpdateResidual - - -/*---------------------------------------------------------------------- - * - * - * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved - * - * This file is available under both the GNU General Public License - * and a BSD-style copyright; see LICENSE.FlashPoint for details. - * - * $Workfile: globals.h $ - * - * Description: Common shared global defines. - * - * $Date: 1996/09/04 01:26:13 $ - * - * $Revision: 1.11 $ - * - *----------------------------------------------------------------------*/ -#ifndef __GLOBALS_H__ -#define __GLOBALS_H__ - -#define _UCB_MGR_ 1 -#define _SCCB_MGR_ 2 - -/*#include */ - -#define MAX_CDBLEN 12 - -#define SCAM_LEV_2 1 - -#define CRCMASK 0xA001 - -/* In your osflags.h file, please ENSURE that only ONE OS FLAG - is on at a time !!! Also, please make sure you turn set the - variable FW_TYPE to either _UCB_MGR_ or _SCCB_MGR_ !!! */ - -#if defined(DOS) || defined(WIN95_16) || defined(OS2) || defined(OTHER_16) - #define COMPILER_16_BIT 1 -#elif defined(NETWARE) || defined(NT) || defined(WIN95_32) || defined(UNIX) || defined(OTHER_32) || defined(SOLARIS_REAL_MODE) - #define COMPILER_32_BIT 1 -#endif - - -#define BL_VENDOR_ID 0x104B -#define FP_DEVICE_ID 0x8130 -#define MM_DEVICE_ID 0x1040 - - -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE (!(FALSE)) -#endif - -#ifndef NULL -#define NULL 0 -#endif - -#define FAILURE 0xFFFFFFFFL - - -typedef unsigned char UCHAR; -typedef unsigned short USHORT; -typedef unsigned int UINT; -typedef unsigned long ULONG; -typedef unsigned char * PUCHAR; -typedef unsigned short* PUSHORT; -typedef unsigned long * PULONG; -typedef void * PVOID; - - -#if defined(COMPILER_16_BIT) -typedef unsigned char far * uchar_ptr; -typedef unsigned short far * ushort_ptr; -typedef unsigned long far * ulong_ptr; -#endif /* 16_BIT_COMPILER */ - -#if defined(COMPILER_32_BIT) -typedef unsigned char * uchar_ptr; -typedef unsigned short * ushort_ptr; -typedef unsigned long * ulong_ptr; -#endif /* 32_BIT_COMPILER */ - - -/* NEW TYPE DEFINITIONS (shared with Mylex North) - -** Use following type defines to avoid confusion in 16 and 32-bit -** environments. Avoid using 'int' as it denotes 16 bits in 16-bit -** environment and 32 in 32-bit environments. - -*/ - -#define s08bits char -#define s16bits short -#define s32bits long - -#define u08bits unsigned s08bits -#define u16bits unsigned s16bits -#define u32bits unsigned s32bits - -#if defined(COMPILER_16_BIT) - -typedef u08bits far * pu08bits; -typedef u16bits far * pu16bits; -typedef u32bits far * pu32bits; - -#endif /* COMPILER_16_BIT */ - -#if defined(COMPILER_32_BIT) - -typedef u08bits * pu08bits; -typedef u16bits * pu16bits; -typedef u32bits * pu32bits; - -#endif /* COMPILER_32_BIT */ - - -#define BIT(x) ((UCHAR)(1<<(x))) /* single-bit mask in bit position x */ -#define BITW(x) ((USHORT)(1<<(x))) /* single-bit mask in bit position x */ - - - -#if defined(DOS) -/*#include */ - #undef inportb /* undefine for Borland Lib */ - #undef inport /* they may have define I/O function in LIB */ - #undef outportb - #undef outport - - #define OS_InPortByte(ioport) inportb(ioport) - #define OS_InPortWord(ioport) inport(ioport) - #define OS_InPortLong(ioport) inportq(ioport, val) - #define OS_OutPortByte(ioport, val) outportb(ioport, val) - #define OS_OutPortWord(ioport, val) outport(ioport, val) - #define OS_OutPortLong(ioport) outportq(ioport, val) -#endif /* DOS */ - -#if defined(NETWARE) || defined(OTHER_32) || defined(OTHER_16) - extern u08bits OS_InPortByte(u32bits ioport); - extern u16bits OS_InPortWord(u32bits ioport); - extern u32bits OS_InPortLong(u32bits ioport); - - extern OS_InPortByteBuffer(u32bits ioport, pu08bits buffer, u32bits count); - extern OS_InPortWordBuffer(u32bits ioport, pu16bits buffer, u32bits count); - extern OS_OutPortByte(u32bits ioport, u08bits val); - extern OS_OutPortWord(u32bits ioport, u16bits val); - extern OS_OutPortLong(u32bits ioport, u32bits val); - extern OS_OutPortByteBuffer(u32bits ioport, pu08bits buffer, u32bits count); - extern OS_OutPortWordBuffer(u32bits ioport, pu16bits buffer, u32bits count); -#endif /* NETWARE || OTHER_32 || OTHER_16 */ - -#if defined (NT) || defined(WIN95_32) || defined(WIN95_16) - #if defined(NT) - - extern __declspec(dllimport) u08bits ScsiPortReadPortUchar(pu08bits ioport); - extern __declspec(dllimport) u16bits ScsiPortReadPortUshort(pu16bits ioport); - extern __declspec(dllimport) u32bits ScsiPortReadPortUlong(pu32bits ioport); - extern __declspec(dllimport) void ScsiPortWritePortUchar(pu08bits ioport, u08bits val); - extern __declspec(dllimport) void ScsiPortWritePortUshort(pu16bits port, u16bits val); - extern __declspec(dllimport) void ScsiPortWritePortUlong(pu32bits port, u32bits val); - - #else - - extern u08bits ScsiPortReadPortUchar(pu08bits ioport); - extern u16bits ScsiPortReadPortUshort(pu16bits ioport); - extern u32bits ScsiPortReadPortUlong(pu32bits ioport); - extern void ScsiPortWritePortUchar(pu08bits ioport, u08bits val); - extern void ScsiPortWritePortUshort(pu16bits port, u16bits val); - extern void ScsiPortWritePortUlong(pu32bits port, u32bits val); - #endif - - - #define OS_InPortByte(ioport) ScsiPortReadPortUchar((pu08bits) ioport) - #define OS_InPortWord(ioport) ScsiPortReadPortUshort((pu16bits) ioport) - #define OS_InPortLong(ioport) ScsiPortReadPortUlong((pu32bits) ioport) - - #define OS_OutPortByte(ioport, val) ScsiPortWritePortUchar((pu08bits) ioport, (u08bits) val) - #define OS_OutPortWord(ioport, val) ScsiPortWritePortUshort((pu16bits) ioport, (u16bits) val) - #define OS_OutPortLong(ioport, val) ScsiPortWritePortUlong((pu32bits) ioport, (u32bits) val) - #define OS_OutPortByteBuffer(ioport, buffer, count) \ - ScsiPortWritePortBufferUchar((pu08bits)&port, (pu08bits) buffer, (u32bits) count) - #define OS_OutPortWordBuffer(ioport, buffer, count) \ - ScsiPortWritePortBufferUshort((pu16bits)&port, (pu16bits) buffer, (u32bits) count) - - #define OS_Lock(x) - #define OS_UnLock(x) -#endif /* NT || WIN95_32 || WIN95_16 */ - -#if defined (UNIX) && !defined(OS_InPortByte) - #define OS_InPortByte(ioport) inb((u16bits)ioport) - #define OS_InPortWord(ioport) inw((u16bits)ioport) - #define OS_InPortLong(ioport) inl((u16bits)ioport) - #define OS_OutPortByte(ioport,val) outb((u16bits)ioport, (u08bits)val) - #define OS_OutPortWord(ioport,val) outw((u16bits)ioport, (u16bits)val) - #define OS_OutPortLong(ioport,val) outl((u16bits)ioport, (u32bits)val) - - #define OS_Lock(x) - #define OS_UnLock(x) -#endif /* UNIX */ - - -#if defined(OS2) - extern u08bits inb(u32bits ioport); - extern u16bits inw(u32bits ioport); - extern void outb(u32bits ioport, u08bits val); - extern void outw(u32bits ioport, u16bits val); - - #define OS_InPortByte(ioport) inb(ioport) - #define OS_InPortWord(ioport) inw(ioport) - #define OS_OutPortByte(ioport, val) outb(ioport, val) - #define OS_OutPortWord(ioport, val) outw(ioport, val) - extern u32bits OS_InPortLong(u32bits ioport); - extern void OS_OutPortLong(u32bits ioport, u32bits val); - - #define OS_Lock(x) - #define OS_UnLock(x) -#endif /* OS2 */ - -#if defined(SOLARIS_REAL_MODE) - -extern unsigned char inb(unsigned long ioport); -extern unsigned short inw(unsigned long ioport); - -#define OS_InPortByte(ioport) inb(ioport) -#define OS_InPortWord(ioport) inw(ioport) - -extern void OS_OutPortByte(unsigned long ioport, unsigned char val); -extern void OS_OutPortWord(unsigned long ioport, unsigned short val); -extern unsigned long OS_InPortLong(unsigned long ioport); -extern void OS_OutPortLong(unsigned long ioport, unsigned long val); - -#define OS_Lock(x) -#define OS_UnLock(x) - -#endif /* SOLARIS_REAL_MODE */ - -#endif /* __GLOBALS_H__ */ - -/*---------------------------------------------------------------------- - * - * - * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved - * - * This file is available under both the GNU General Public License - * and a BSD-style copyright; see LICENSE.FlashPoint for details. - * - * $Workfile: sccbmgr.h $ - * - * Description: Common shared SCCB Interface defines and SCCB - * Manager specifics defines. - * - * $Date: 1996/10/24 23:09:33 $ - * - * $Revision: 1.14 $ - * - *----------------------------------------------------------------------*/ - -#ifndef __SCCB_H__ -#define __SCCB_H__ - -/*#include */ -/*#include */ - -#if defined(BUGBUG) -#define debug_size 32 -#endif - -#if defined(DOS) - - typedef struct _SCCB near *PSCCB; - #if (FW_TYPE == _SCCB_MGR_) - typedef void (*CALL_BK_FN)(PSCCB); - #endif - -#elif defined(OS2) - - typedef struct _SCCB far *PSCCB; - #if (FW_TYPE == _SCCB_MGR_) - typedef void (far *CALL_BK_FN)(PSCCB); - #endif - -#else - - typedef struct _SCCB *PSCCB; - #if (FW_TYPE == _SCCB_MGR_) - typedef void (*CALL_BK_FN)(PSCCB); - #endif - -#endif - - -typedef struct SCCBMgr_info { - ULONG si_baseaddr; - UCHAR si_present; - UCHAR si_intvect; - UCHAR si_id; - UCHAR si_lun; - USHORT si_fw_revision; - USHORT si_per_targ_init_sync; - USHORT si_per_targ_fast_nego; - USHORT si_per_targ_ultra_nego; - USHORT si_per_targ_no_disc; - USHORT si_per_targ_wide_nego; - USHORT si_flags; - UCHAR si_card_family; - UCHAR si_bustype; - UCHAR si_card_model[3]; - UCHAR si_relative_cardnum; - UCHAR si_reserved[4]; - ULONG si_OS_reserved; - UCHAR si_XlatInfo[4]; - ULONG si_reserved2[5]; - ULONG si_secondary_range; -} SCCBMGR_INFO; - -#if defined(DOS) - typedef SCCBMGR_INFO * PSCCBMGR_INFO; -#else - #if defined (COMPILER_16_BIT) - typedef SCCBMGR_INFO far * PSCCBMGR_INFO; - #else - typedef SCCBMGR_INFO * PSCCBMGR_INFO; - #endif -#endif // defined(DOS) - - - - -#if (FW_TYPE==_SCCB_MGR_) - #define SCSI_PARITY_ENA 0x0001 - #define LOW_BYTE_TERM 0x0010 - #define HIGH_BYTE_TERM 0x0020 - #define BUSTYPE_PCI 0x3 -#endif - -#define SUPPORT_16TAR_32LUN 0x0002 -#define SOFT_RESET 0x0004 -#define EXTENDED_TRANSLATION 0x0008 -#define POST_ALL_UNDERRRUNS 0x0040 -#define FLAG_SCAM_ENABLED 0x0080 -#define FLAG_SCAM_LEVEL2 0x0100 - - - - -#define HARPOON_FAMILY 0x02 - - -#define ISA_BUS_CARD 0x01 -#define EISA_BUS_CARD 0x02 -#define PCI_BUS_CARD 0x03 -#define VESA_BUS_CARD 0x04 - -/* SCCB struc used for both SCCB and UCB manager compiles! - * The UCB Manager treats the SCCB as it's 'native hardware structure' - */ - - -#pragma pack(1) -typedef struct _SCCB { - UCHAR OperationCode; - UCHAR ControlByte; - UCHAR CdbLength; - UCHAR RequestSenseLength; - ULONG DataLength; - ULONG DataPointer; - UCHAR CcbRes[2]; - UCHAR HostStatus; - UCHAR TargetStatus; - UCHAR TargID; - UCHAR Lun; - UCHAR Cdb[12]; - UCHAR CcbRes1; - UCHAR Reserved1; - ULONG Reserved2; - ULONG SensePointer; - - - CALL_BK_FN SccbCallback; /* VOID (*SccbCallback)(); */ - ULONG SccbIOPort; /* Identifies board base port */ - UCHAR SccbStatus; - UCHAR SCCBRes2; - USHORT SccbOSFlags; - - - ULONG Sccb_XferCnt; /* actual transfer count */ - ULONG Sccb_ATC; - ULONG SccbVirtDataPtr; /* virtual addr for OS/2 */ - ULONG Sccb_res1; - USHORT Sccb_MGRFlags; - USHORT Sccb_sgseg; - UCHAR Sccb_scsimsg; /* identify msg for selection */ - UCHAR Sccb_tag; - UCHAR Sccb_scsistat; - UCHAR Sccb_idmsg; /* image of last msg in */ - PSCCB Sccb_forwardlink; - PSCCB Sccb_backlink; - ULONG Sccb_savedATC; - UCHAR Save_Cdb[6]; - UCHAR Save_CdbLen; - UCHAR Sccb_XferState; - ULONG Sccb_SGoffset; -#if (FW_TYPE == _UCB_MGR_) - PUCB Sccb_ucb_ptr; -#endif - } SCCB; - -#define SCCB_SIZE sizeof(SCCB) - -#pragma pack() - - - -#define SCSI_INITIATOR_COMMAND 0x00 -#define TARGET_MODE_COMMAND 0x01 -#define SCATTER_GATHER_COMMAND 0x02 -#define RESIDUAL_COMMAND 0x03 -#define RESIDUAL_SG_COMMAND 0x04 -#define RESET_COMMAND 0x81 - - -#define F_USE_CMD_Q 0x20 /*Inidcates TAGGED command. */ -#define TAG_TYPE_MASK 0xC0 /*Type of tag msg to send. */ -#define TAG_Q_MASK 0xE0 -#define SCCB_DATA_XFER_OUT 0x10 /* Write */ -#define SCCB_DATA_XFER_IN 0x08 /* Read */ - - -#define FOURTEEN_BYTES 0x00 /* Request Sense Buffer size */ -#define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */ - - -#define BUS_FREE_ST 0 -#define SELECT_ST 1 -#define SELECT_BDR_ST 2 /* Select w\ Bus Device Reset */ -#define SELECT_SN_ST 3 /* Select w\ Sync Nego */ -#define SELECT_WN_ST 4 /* Select w\ Wide Data Nego */ -#define SELECT_Q_ST 5 /* Select w\ Tagged Q'ing */ -#define COMMAND_ST 6 -#define DATA_OUT_ST 7 -#define DATA_IN_ST 8 -#define DISCONNECT_ST 9 -#define STATUS_ST 10 -#define ABORT_ST 11 -#define MESSAGE_ST 12 - - -#define F_HOST_XFER_DIR 0x01 -#define F_ALL_XFERRED 0x02 -#define F_SG_XFER 0x04 -#define F_AUTO_SENSE 0x08 -#define F_ODD_BALL_CNT 0x10 -#define F_NO_DATA_YET 0x80 - - -#define F_STATUSLOADED 0x01 -#define F_MSGLOADED 0x02 -#define F_DEV_SELECTED 0x04 - - -#define SCCB_COMPLETE 0x00 /* SCCB completed without error */ -#define SCCB_DATA_UNDER_RUN 0x0C -#define SCCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */ -#define SCCB_DATA_OVER_RUN 0x12 -#define SCCB_UNEXPECTED_BUS_FREE 0x13 /* Target dropped SCSI BSY */ -#define SCCB_PHASE_SEQUENCE_FAIL 0x14 /* Target bus phase sequence failure */ - -#define SCCB_INVALID_OP_CODE 0x16 /* SCCB invalid operation code */ -#define SCCB_INVALID_SCCB 0x1A /* Invalid SCCB - bad parameter */ -#define SCCB_GROSS_FW_ERR 0x27 /* Major problem! */ -#define SCCB_BM_ERR 0x30 /* BusMaster error. */ -#define SCCB_PARITY_ERR 0x34 /* SCSI parity error */ - - - -#if (FW_TYPE==_UCB_MGR_) - #define HBA_AUTO_SENSE_FAIL 0x1B - #define HBA_TQ_REJECTED 0x1C - #define HBA_UNSUPPORTED_MSG 0x1D - #define HBA_HW_ERROR 0x20 - #define HBA_ATN_NOT_RESPONDED 0x21 - #define HBA_SCSI_RESET_BY_ADAPTER 0x22 - #define HBA_SCSI_RESET_BY_TARGET 0x23 - #define HBA_WRONG_CONNECTION 0x24 - #define HBA_BUS_DEVICE_RESET 0x25 - #define HBA_ABORT_QUEUE 0x26 - -#else // these are not defined in BUDI/UCB - - #define SCCB_INVALID_DIRECTION 0x18 /* Invalid target direction */ - #define SCCB_DUPLICATE_SCCB 0x19 /* Duplicate SCCB */ - #define SCCB_SCSI_RST 0x35 /* SCSI RESET detected. */ - -#endif // (FW_TYPE==_UCB_MGR_) - - -#define SCCB_IN_PROCESS 0x00 -#define SCCB_SUCCESS 0x01 -#define SCCB_ABORT 0x02 -#define SCCB_NOT_FOUND 0x03 -#define SCCB_ERROR 0x04 -#define SCCB_INVALID 0x05 - -#define SCCB_SIZE sizeof(SCCB) - - - - -#if (FW_TYPE == _UCB_MGR_) - void SccbMgr_start_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb); - s32bits SccbMgr_abort_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb); - u08bits SccbMgr_my_int(CARD_HANDLE pCurrCard); - s32bits SccbMgr_isr(CARD_HANDLE pCurrCard); - void SccbMgr_scsi_reset(CARD_HANDLE pCurrCard); - void SccbMgr_timer_expired(CARD_HANDLE pCurrCard); - void SccbMgr_unload_card(CARD_HANDLE pCurrCard); - void SccbMgr_restore_foreign_state(CARD_HANDLE pCurrCard); - void SccbMgr_restore_native_state(CARD_HANDLE pCurrCard); - void SccbMgr_save_foreign_state(PADAPTER_INFO pAdapterInfo); - -#endif - - -#if (FW_TYPE == _SCCB_MGR_) - - #if defined (DOS) - int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo); - USHORT SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo); - void SccbMgr_start_sccb(USHORT pCurrCard, PSCCB p_SCCB); - int SccbMgr_abort_sccb(USHORT pCurrCard, PSCCB p_SCCB); - UCHAR SccbMgr_my_int(USHORT pCurrCard); - int SccbMgr_isr(USHORT pCurrCard); - void SccbMgr_scsi_reset(USHORT pCurrCard); - void SccbMgr_timer_expired(USHORT pCurrCard); - USHORT SccbMgr_status(USHORT pCurrCard); - void SccbMgr_unload_card(USHORT pCurrCard); - - #else //non-DOS - - int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo); - ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo); - void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_SCCB); - int SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_SCCB); - UCHAR SccbMgr_my_int(ULONG pCurrCard); - int SccbMgr_isr(ULONG pCurrCard); - void SccbMgr_scsi_reset(ULONG pCurrCard); - void SccbMgr_enable_int(ULONG pCurrCard); - void SccbMgr_disable_int(ULONG pCurrCard); - void SccbMgr_timer_expired(ULONG pCurrCard); - void SccbMgr_unload_card(ULONG pCurrCard); - - #endif -#endif // (FW_TYPE == _SCCB_MGR_) - -#endif /* __SCCB_H__ */ - -/*---------------------------------------------------------------------- - * - * - * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved - * - * This file is available under both the GNU General Public License - * and a BSD-style copyright; see LICENSE.FlashPoint for details. - * - * $Workfile: blx30.h $ - * - * Description: This module contains SCCB/UCB Manager implementation - * specific stuff. - * - * $Date: 1996/11/13 18:34:22 $ - * - * $Revision: 1.10 $ - * - *----------------------------------------------------------------------*/ - - -#ifndef __blx30_H__ -#define __blx30_H__ - -/*#include */ - -#define ORION_FW_REV 3110 - - - - -#define HARP_REVD 1 - - -#if defined(DOS) -#define QUEUE_DEPTH 8+1 /*1 for Normal disconnect 0 for Q'ing. */ -#else -#define QUEUE_DEPTH 254+1 /*1 for Normal disconnect 32 for Q'ing. */ -#endif // defined(DOS) - -#define MAX_MB_CARDS 4 /* Max. no of cards suppoerted on Mother Board */ - -#define WIDE_SCSI 1 - -#if defined(WIDE_SCSI) - #if defined(DOS) - #define MAX_SCSI_TAR 16 - #define MAX_LUN 8 - #define LUN_MASK 0x07 - #else - #define MAX_SCSI_TAR 16 - #define MAX_LUN 32 - #define LUN_MASK 0x1f - - #endif -#else - #define MAX_SCSI_TAR 8 - #define MAX_LUN 8 - #define LUN_MASK 0x07 -#endif - -#if defined(HARP_REVA) -#define SG_BUF_CNT 15 /*Number of prefetched elements. */ -#else -#define SG_BUF_CNT 16 /*Number of prefetched elements. */ -#endif - -#define SG_ELEMENT_SIZE 8 /*Eight byte per element. */ -#define SG_LOCAL_MASK 0x00000000L -#define SG_ELEMENT_MASK 0xFFFFFFFFL - - -#if (FW_TYPE == _UCB_MGR_) - #define OPC_DECODE_NORMAL 0x0f7f -#endif // _UCB_MGR_ - - - -#if defined(DOS) - -/*#include */ - #define RD_HARPOON(ioport) (OS_InPortByte(ioport)) - #define RDW_HARPOON(ioport) (OS_InPortWord(ioport)) - #define WR_HARPOON(ioport,val) (OS_OutPortByte(ioport,val)) - #define WRW_HARPOON(ioport,val) (OS_OutPortWord(ioport,val)) - - #define RD_HARP32(port,offset,data) asm{db 66h; \ - push ax; \ - mov dx,port; \ - add dx, offset; \ - db 66h; \ - in ax,dx; \ - db 66h; \ - mov word ptr data,ax;\ - db 66h; \ - pop ax} - - #define WR_HARP32(port,offset,data) asm{db 66h; \ - push ax; \ - mov dx,port; \ - add dx, offset; \ - db 66h; \ - mov ax,word ptr data;\ - db 66h; \ - out dx,ax; \ - db 66h; \ - pop ax} -#endif /* DOS */ - -#if defined(NETWARE) || defined(OTHER_32) || defined(OTHER_16) - #define RD_HARPOON(ioport) OS_InPortByte((unsigned long)ioport) - #define RDW_HARPOON(ioport) OS_InPortWord((unsigned long)ioport) - #define RD_HARP32(ioport,offset,data) (data = OS_InPortLong(ioport + offset)) - #define WR_HARPOON(ioport,val) OS_OutPortByte((ULONG)ioport,(UCHAR) val) - #define WRW_HARPOON(ioport,val) OS_OutPortWord((ULONG)ioport,(USHORT)val) - #define WR_HARP32(ioport,offset,data) OS_OutPortLong((ioport + offset), data) -#endif /* NETWARE || OTHER_32 || OTHER_16 */ - -#if defined(NT) || defined(WIN95_32) || defined(WIN95_16) - #define RD_HARPOON(ioport) OS_InPortByte((ULONG)ioport) - #define RDW_HARPOON(ioport) OS_InPortWord((ULONG)ioport) - #define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((ULONG)(ioport + offset))) - #define WR_HARPOON(ioport,val) OS_OutPortByte((ULONG)ioport,(UCHAR) val) - #define WRW_HARPOON(ioport,val) OS_OutPortWord((ULONG)ioport,(USHORT)val) - #define WR_HARP32(ioport,offset,data) OS_OutPortLong((ULONG)(ioport + offset), data) -#endif /* NT || WIN95_32 || WIN95_16 */ - -#if defined (UNIX) - #define RD_HARPOON(ioport) OS_InPortByte((u32bits)ioport) - #define RDW_HARPOON(ioport) OS_InPortWord((u32bits)ioport) - #define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((u32bits)(ioport + offset))) - #define WR_HARPOON(ioport,val) OS_OutPortByte((u32bits)ioport,(u08bits) val) - #define WRW_HARPOON(ioport,val) OS_OutPortWord((u32bits)ioport,(u16bits)val) - #define WR_HARP32(ioport,offset,data) OS_OutPortLong((u32bits)(ioport + offset), data) -#endif /* UNIX */ - -#if defined(OS2) - #define RD_HARPOON(ioport) OS_InPortByte((unsigned long)ioport) - #define RDW_HARPOON(ioport) OS_InPortWord((unsigned long)ioport) - #define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((ULONG)(ioport + offset))) - #define WR_HARPOON(ioport,val) OS_OutPortByte((ULONG)ioport,(UCHAR) val) - #define WRW_HARPOON(ioport,val) OS_OutPortWord((ULONG)ioport,(USHORT)val) - #define WR_HARP32(ioport,offset,data) OS_OutPortLong(((ULONG)(ioport + offset)), data) -#endif /* OS2 */ - -#if defined(SOLARIS_REAL_MODE) - - #define RD_HARPOON(ioport) OS_InPortByte((unsigned long)ioport) - #define RDW_HARPOON(ioport) OS_InPortWord((unsigned long)ioport) - #define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((ULONG)(ioport + offset))) - #define WR_HARPOON(ioport,val) OS_OutPortByte((ULONG)ioport,(UCHAR) val) - #define WRW_HARPOON(ioport,val) OS_OutPortWord((ULONG)ioport,(USHORT)val) - #define WR_HARP32(ioport,offset,data) OS_OutPortLong((ULONG)(ioport + offset), (ULONG)data) - -#endif /* SOLARIS_REAL_MODE */ - -#endif /* __BLX30_H__ */ - - -/*---------------------------------------------------------------------- - * - * - * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved - * - * This file is available under both the GNU General Public License - * and a BSD-style copyright; see LICENSE.FlashPoint for details. - * - * $Workfile: target.h $ - * - * Description: Definitions for Target related structures - * - * $Date: 1996/12/11 22:06:20 $ - * - * $Revision: 1.9 $ - * - *----------------------------------------------------------------------*/ - -#ifndef __TARGET__ -#define __TARGET__ - -/*#include */ -/*#include */ - - -#define TAR_SYNC_MASK (BIT(7)+BIT(6)) -#define SYNC_UNKNOWN 0x00 -#define SYNC_TRYING BIT(6) -#define SYNC_SUPPORTED (BIT(7)+BIT(6)) - -#define TAR_WIDE_MASK (BIT(5)+BIT(4)) -#define WIDE_DISABLED 0x00 -#define WIDE_ENABLED BIT(4) -#define WIDE_NEGOCIATED BIT(5) - -#define TAR_TAG_Q_MASK (BIT(3)+BIT(2)) -#define TAG_Q_UNKNOWN 0x00 -#define TAG_Q_TRYING BIT(2) -#define TAG_Q_REJECT BIT(3) -#define TAG_Q_SUPPORTED (BIT(3)+BIT(2)) - -#define TAR_ALLOW_DISC BIT(0) - - -#define EE_SYNC_MASK (BIT(0)+BIT(1)) -#define EE_SYNC_ASYNC 0x00 -#define EE_SYNC_5MB BIT(0) -#define EE_SYNC_10MB BIT(1) -#define EE_SYNC_20MB (BIT(0)+BIT(1)) - -#define EE_ALLOW_DISC BIT(6) -#define EE_WIDE_SCSI BIT(7) - - -#if defined(DOS) - typedef struct SCCBMgr_tar_info near *PSCCBMgr_tar_info; - -#elif defined(OS2) - typedef struct SCCBMgr_tar_info far *PSCCBMgr_tar_info; - -#else - typedef struct SCCBMgr_tar_info *PSCCBMgr_tar_info; - -#endif - - -typedef struct SCCBMgr_tar_info { - - PSCCB TarSelQ_Head; - PSCCB TarSelQ_Tail; - UCHAR TarLUN_CA; /*Contingent Allgiance */ - UCHAR TarTagQ_Cnt; - UCHAR TarSelQ_Cnt; - UCHAR TarStatus; - UCHAR TarEEValue; - UCHAR TarSyncCtrl; - UCHAR TarReserved[2]; /* for alignment */ - UCHAR LunDiscQ_Idx[MAX_LUN]; - UCHAR TarLUNBusy[MAX_LUN]; -} SCCBMGR_TAR_INFO; - -typedef struct NVRAMInfo { - UCHAR niModel; /* Model No. of card */ - UCHAR niCardNo; /* Card no. */ -#if defined(DOS) - USHORT niBaseAddr; /* Port Address of card */ -#else - ULONG niBaseAddr; /* Port Address of card */ -#endif - UCHAR niSysConf; /* Adapter Configuration byte - Byte 16 of eeprom map */ - UCHAR niScsiConf; /* SCSI Configuration byte - Byte 17 of eeprom map */ - UCHAR niScamConf; /* SCAM Configuration byte - Byte 20 of eeprom map */ - UCHAR niAdapId; /* Host Adapter ID - Byte 24 of eerpom map */ - UCHAR niSyncTbl[MAX_SCSI_TAR / 2]; /* Sync/Wide byte of targets */ - UCHAR niScamTbl[MAX_SCSI_TAR][4]; /* Compressed Scam name string of Targets */ -}NVRAMINFO; - -#if defined(DOS) -typedef NVRAMINFO near *PNVRamInfo; -#elif defined (OS2) -typedef NVRAMINFO far *PNVRamInfo; -#else -typedef NVRAMINFO *PNVRamInfo; -#endif - -#define MODEL_LT 1 -#define MODEL_DL 2 -#define MODEL_LW 3 -#define MODEL_DW 4 - - -typedef struct SCCBcard { - PSCCB currentSCCB; -#if (FW_TYPE==_SCCB_MGR_) - PSCCBMGR_INFO cardInfo; -#else - PADAPTER_INFO cardInfo; -#endif - -#if defined(DOS) - USHORT ioPort; -#else - ULONG ioPort; -#endif - - USHORT cmdCounter; - UCHAR discQCount; - UCHAR tagQ_Lst; - UCHAR cardIndex; - UCHAR scanIndex; - UCHAR globalFlags; - UCHAR ourId; - PNVRamInfo pNvRamInfo; - PSCCB discQ_Tbl[QUEUE_DEPTH]; - -}SCCBCARD; - -#if defined(DOS) -typedef struct SCCBcard near *PSCCBcard; -#elif defined (OS2) -typedef struct SCCBcard far *PSCCBcard; -#else -typedef struct SCCBcard *PSCCBcard; -#endif - - -#define F_TAG_STARTED 0x01 -#define F_CONLUN_IO 0x02 -#define F_DO_RENEGO 0x04 -#define F_NO_FILTER 0x08 -#define F_GREEN_PC 0x10 -#define F_HOST_XFER_ACT 0x20 -#define F_NEW_SCCB_CMD 0x40 -#define F_UPDATE_EEPROM 0x80 - - -#define ID_STRING_LENGTH 32 -#define TYPE_CODE0 0x63 /*Level2 Mstr (bits 7-6), */ - -#define TYPE_CODE1 00 /*No ID yet */ - -#define SLV_TYPE_CODE0 0xA3 /*Priority Bit set (bits 7-6), */ - -#define ASSIGN_ID 0x00 -#define SET_P_FLAG 0x01 -#define CFG_CMPLT 0x03 -#define DOM_MSTR 0x0F -#define SYNC_PTRN 0x1F - -#define ID_0_7 0x18 -#define ID_8_F 0x11 -#define ID_10_17 0x12 -#define ID_18_1F 0x0B -#define MISC_CODE 0x14 -#define CLR_P_FLAG 0x18 -#define LOCATE_ON 0x12 -#define LOCATE_OFF 0x0B - -#define LVL_1_MST 0x00 -#define LVL_2_MST 0x40 -#define DOM_LVL_2 0xC0 - - -#define INIT_SELTD 0x01 -#define LEVEL2_TAR 0x02 - - -enum scam_id_st { ID0,ID1,ID2,ID3,ID4,ID5,ID6,ID7,ID8,ID9,ID10,ID11,ID12, - ID13,ID14,ID15,ID_UNUSED,ID_UNASSIGNED,ID_ASSIGNED,LEGACY, - CLR_PRIORITY,NO_ID_AVAIL }; - -typedef struct SCCBscam_info { - - UCHAR id_string[ID_STRING_LENGTH]; - enum scam_id_st state; - -} SCCBSCAM_INFO, *PSCCBSCAM_INFO; - -#endif -/*---------------------------------------------------------------------- - * - * - * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved - * - * This file is available under both the GNU General Public License - * and a BSD-style copyright; see LICENSE.FlashPoint for details. - * - * $Workfile: scsi2.h $ - * - * Description: Register definitions for HARPOON ASIC. - * - * $Date: 1996/11/13 18:32:57 $ - * - * $Revision: 1.4 $ - * - *----------------------------------------------------------------------*/ - -#ifndef __SCSI_H__ -#define __SCSI_H__ - - - -#define SCSI_TEST_UNIT_READY 0x00 -#define SCSI_REZERO_UNIT 0x01 -#define SCSI_REQUEST_SENSE 0x03 -#define SCSI_FORMAT_UNIT 0x04 -#define SCSI_REASSIGN 0x07 -#define SCSI_READ 0x08 -#define SCSI_WRITE 0x0A -#define SCSI_SEEK 0x0B -#define SCSI_INQUIRY 0x12 -#define SCSI_MODE_SELECT 0x15 -#define SCSI_RESERVE_UNIT 0x16 -#define SCSI_RELEASE_UNIT 0x17 -#define SCSI_MODE_SENSE 0x1A -#define SCSI_START_STOP_UNIT 0x1B -#define SCSI_SEND_DIAGNOSTIC 0x1D -#define SCSI_READ_CAPACITY 0x25 -#define SCSI_READ_EXTENDED 0x28 -#define SCSI_WRITE_EXTENDED 0x2A -#define SCSI_SEEK_EXTENDED 0x2B -#define SCSI_WRITE_AND_VERIFY 0x2E -#define SCSI_VERIFY 0x2F -#define SCSI_READ_DEFECT_DATA 0x37 -#define SCSI_WRITE_BUFFER 0x3B -#define SCSI_READ_BUFFER 0x3C -#define SCSI_RECV_DIAGNOSTIC 0x1C -#define SCSI_READ_LONG 0x3E -#define SCSI_WRITE_LONG 0x3F -#define SCSI_LAST_SCSI_CMND SCSI_WRITE_LONG -#define SCSI_INVALID_CMND 0xFF - - - -#define SSGOOD 0x00 -#define SSCHECK 0x02 -#define SSCOND_MET 0x04 -#define SSBUSY 0x08 -#define SSRESERVATION_CONFLICT 0x18 -#define SSCMD_TERM 0x22 -#define SSQ_FULL 0x28 - - -#define SKNO_SEN 0x00 -#define SKRECOV_ERR 0x01 -#define SKNOT_RDY 0x02 -#define SKMED_ERR 0x03 -#define SKHW_ERR 0x04 -#define SKILL_REQ 0x05 -#define SKUNIT_ATTN 0x06 -#define SKDATA_PROTECT 0x07 -#define SKBLNK_CHK 0x08 -#define SKCPY_ABORT 0x0A -#define SKABORT_CMD 0x0B -#define SKEQUAL 0x0C -#define SKVOL_OVF 0x0D -#define SKMIS_CMP 0x0E - - -#define SMCMD_COMP 0x00 -#define SMEXT 0x01 -#define SMSAVE_DATA_PTR 0x02 -#define SMREST_DATA_PTR 0x03 -#define SMDISC 0x04 -#define SMINIT_DETEC_ERR 0x05 -#define SMABORT 0x06 -#define SMREJECT 0x07 -#define SMNO_OP 0x08 -#define SMPARITY 0x09 -#define SMDEV_RESET 0x0C -#define SMABORT_TAG 0x0D -#define SMINIT_RECOVERY 0x0F -#define SMREL_RECOVERY 0x10 - -#define SMIDENT 0x80 -#define DISC_PRIV 0x40 - - -#define SMSYNC 0x01 -#define SM10MBS 0x19 /* 100ns */ -#define SM5MBS 0x32 /* 200ns */ -#define SMOFFSET 0x0F /* Maxoffset value */ -#define SMWDTR 0x03 -#define SM8BIT 0x00 -#define SM16BIT 0x01 -#define SM32BIT 0x02 -#define SMIGNORWR 0x23 /* Ignore Wide Residue */ - - -#define ARBITRATION_DELAY 0x01 /* 2.4us using a 40Mhz clock */ -#define BUS_SETTLE_DELAY 0x01 /* 400ns */ -#define BUS_CLEAR_DELAY 0x01 /* 800ns */ - - - -#define SPHASE_TO 0x0A /* 10 second timeout waiting for */ -#define SCMD_TO 0x0F /* Overall command timeout */ - - - -#define SIX_BYTE_CMD 0x06 -#define TEN_BYTE_CMD 0x0A -#define TWELVE_BYTE_CMD 0x0C - -#define ASYNC 0x00 -#define PERI25NS 0x06 /* 25/4ns to next clock for xbow. */ -#define SYNC10MBS 0x19 -#define SYNC5MBS 0x32 -#define MAX_OFFSET 0x0F /* Maxbyteoffset for Sync Xfers */ - -#endif -/*---------------------------------------------------------------------- - * - * - * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved - * - * This file is available under both the GNU General Public License - * and a BSD-style copyright; see LICENSE.FlashPoint for details. - * - * $Workfile: eeprom.h $ - * - * Description: Definitions for EEPROM related structures - * - * $Date: 1996/11/13 18:28:39 $ - * - * $Revision: 1.4 $ - * - *----------------------------------------------------------------------*/ - -#ifndef __EEPROM__ -#define __EEPROM__ - -/*#include */ - -#define EEPROM_WD_CNT 256 - -#define EEPROM_CHECK_SUM 0 -#define FW_SIGNATURE 2 -#define MODEL_NUMB_0 4 -#define MODEL_NUMB_1 5 -#define MODEL_NUMB_2 6 -#define MODEL_NUMB_3 7 -#define MODEL_NUMB_4 8 -#define MODEL_NUMB_5 9 -#define IO_BASE_ADDR 10 -#define IRQ_NUMBER 12 -#define PCI_INT_PIN 13 -#define BUS_DELAY 14 /*On time in byte 14 off delay in 15 */ -#define SYSTEM_CONFIG 16 -#define SCSI_CONFIG 17 -#define BIOS_CONFIG 18 -#define SPIN_UP_DELAY 19 -#define SCAM_CONFIG 20 -#define ADAPTER_SCSI_ID 24 - - -#define IGNORE_B_SCAN 32 -#define SEND_START_ENA 34 -#define DEVICE_ENABLE 36 - -#define SYNC_RATE_TBL 38 -#define SYNC_RATE_TBL01 38 -#define SYNC_RATE_TBL23 40 -#define SYNC_RATE_TBL45 42 -#define SYNC_RATE_TBL67 44 -#define SYNC_RATE_TBL89 46 -#define SYNC_RATE_TBLab 48 -#define SYNC_RATE_TBLcd 50 -#define SYNC_RATE_TBLef 52 - - - -#define EE_SCAMBASE 256 - - - - #define DOM_MASTER (BIT(0) + BIT(1)) - #define SCAM_ENABLED BIT(2) - #define SCAM_LEVEL2 BIT(3) - - - #define RENEGO_ENA BITW(10) - #define CONNIO_ENA BITW(11) - #define GREEN_PC_ENA BITW(12) - - - #define AUTO_RATE_00 00 - #define AUTO_RATE_05 01 - #define AUTO_RATE_10 02 - #define AUTO_RATE_20 03 - - #define WIDE_NEGO_BIT BIT(7) - #define DISC_ENABLE_BIT BIT(6) - - -#endif -/*---------------------------------------------------------------------- - * - * - * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved - * - * This file is available under both the GNU General Public License - * and a BSD-style copyright; see LICENSE.FlashPoint for details. - * - * $Workfile: harpoon.h $ - * - * Description: Register definitions for HARPOON ASIC. - * - * $Date: 1997/07/09 21:44:36 $ - * - * $Revision: 1.9 $ - * - *----------------------------------------------------------------------*/ - - -/*#include */ - -#ifndef __HARPOON__ -#define __HARPOON__ - - - #define hp_vendor_id_0 0x00 /* LSB */ - #define ORION_VEND_0 0x4B - - #define hp_vendor_id_1 0x01 /* MSB */ - #define ORION_VEND_1 0x10 - - #define hp_device_id_0 0x02 /* LSB */ - #define ORION_DEV_0 0x30 - - #define hp_device_id_1 0x03 /* MSB */ - #define ORION_DEV_1 0x81 - - /* Sub Vendor ID and Sub Device ID only available in - Harpoon Version 2 and higher */ - - #define hp_sub_vendor_id_0 0x04 /* LSB */ - #define hp_sub_vendor_id_1 0x05 /* MSB */ - #define hp_sub_device_id_0 0x06 /* LSB */ - #define hp_sub_device_id_1 0x07 /* MSB */ - - - #define hp_dual_addr_lo 0x08 - #define hp_dual_addr_lmi 0x09 - #define hp_dual_addr_hmi 0x0A - #define hp_dual_addr_hi 0x0B - - #define hp_semaphore 0x0C - #define SCCB_MGR_ACTIVE BIT(0) - #define TICKLE_ME BIT(1) - #define SCCB_MGR_PRESENT BIT(3) - #define BIOS_IN_USE BIT(4) - - #define hp_user_defined_D 0x0D - - #define hp_reserved_E 0x0E - - #define hp_sys_ctrl 0x0F - - #define STOP_CLK BIT(0) /*Turn off BusMaster Clock */ - #define DRVR_RST BIT(1) /*Firmware Reset to 80C15 chip */ - #define HALT_MACH BIT(3) /*Halt State Machine */ - #define HARD_ABORT BIT(4) /*Hard Abort */ - #define DIAG_MODE BIT(5) /*Diagnostic Mode */ - - #define BM_ABORT_TMOUT 0x50 /*Halt State machine time out */ - - #define hp_sys_cfg 0x10 - - #define DONT_RST_FIFO BIT(7) /*Don't reset FIFO */ - - - #define hp_host_ctrl0 0x11 - - #define DUAL_ADDR_MODE BIT(0) /*Enable 64-bit addresses */ - #define IO_MEM_SPACE BIT(1) /*I/O Memory Space */ - #define RESOURCE_LOCK BIT(2) /*Enable Resource Lock */ - #define IGNOR_ACCESS_ERR BIT(3) /*Ignore Access Error */ - #define HOST_INT_EDGE BIT(4) /*Host interrupt level/edge mode sel */ - #define SIX_CLOCKS BIT(5) /*6 Clocks between Strobe */ - #define DMA_EVEN_PARITY BIT(6) /*Enable DMA Enen Parity */ - -/* - #define BURST_MODE BIT(0) -*/ - - #define hp_reserved_12 0x12 - - #define hp_host_blk_cnt 0x13 - - #define XFER_BLK1 0x00 /* 0 0 0 1 byte per block*/ - #define XFER_BLK2 0x01 /* 0 0 1 2 byte per block*/ - #define XFER_BLK4 0x02 /* 0 1 0 4 byte per block*/ - #define XFER_BLK8 0x03 /* 0 1 1 8 byte per block*/ - #define XFER_BLK16 0x04 /* 1 0 0 16 byte per block*/ - #define XFER_BLK32 0x05 /* 1 0 1 32 byte per block*/ - #define XFER_BLK64 0x06 /* 1 1 0 64 byte per block*/ - - #define BM_THRESHOLD 0x40 /* PCI mode can only xfer 16 bytes*/ - - - #define hp_reserved_14 0x14 - #define hp_reserved_15 0x15 - #define hp_reserved_16 0x16 - - #define hp_int_mask 0x17 - - #define INT_CMD_COMPL BIT(0) /* DMA command complete */ - #define INT_EXT_STATUS BIT(1) /* Extended Status Set */ - #define INT_SCSI BIT(2) /* Scsi block interrupt */ - #define INT_FIFO_RDY BIT(4) /* FIFO data ready */ - - - #define hp_xfer_cnt_lo 0x18 - #define hp_xfer_cnt_mi 0x19 - #define hp_xfer_cnt_hi 0x1A - #define hp_xfer_cmd 0x1B - - #define XFER_HOST_DMA 0x00 /* 0 0 0 Transfer Host -> DMA */ - #define XFER_DMA_HOST 0x01 /* 0 0 1 Transfer DMA -> Host */ - #define XFER_HOST_MPU 0x02 /* 0 1 0 Transfer Host -> MPU */ - #define XFER_MPU_HOST 0x03 /* 0 1 1 Transfer MPU -> Host */ - #define XFER_DMA_MPU 0x04 /* 1 0 0 Transfer DMA -> MPU */ - #define XFER_MPU_DMA 0x05 /* 1 0 1 Transfer MPU -> DMA */ - #define SET_SEMAPHORE 0x06 /* 1 1 0 Set Semaphore */ - #define XFER_NOP 0x07 /* 1 1 1 Transfer NOP */ - #define XFER_MB_MPU 0x06 /* 1 1 0 Transfer MB -> MPU */ - #define XFER_MB_DMA 0x07 /* 1 1 1 Transfer MB -> DMA */ - - - #define XFER_HOST_AUTO 0x00 /* 0 0 Auto Transfer Size */ - #define XFER_HOST_8BIT 0x08 /* 0 1 8 BIT Transfer Size */ - #define XFER_HOST_16BIT 0x10 /* 1 0 16 BIT Transfer Size */ - #define XFER_HOST_32BIT 0x18 /* 1 1 32 BIT Transfer Size */ - - #define XFER_DMA_8BIT 0x20 /* 0 1 8 BIT Transfer Size */ - #define XFER_DMA_16BIT 0x40 /* 1 0 16 BIT Transfer Size */ - - #define DISABLE_INT BIT(7) /*Do not interrupt at end of cmd. */ - - #define HOST_WRT_CMD ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT)) - #define HOST_RD_CMD ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT)) - #define WIDE_HOST_WRT_CMD ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_16BIT)) - #define WIDE_HOST_RD_CMD ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_16BIT)) - - #define hp_host_addr_lo 0x1C - #define hp_host_addr_lmi 0x1D - #define hp_host_addr_hmi 0x1E - #define hp_host_addr_hi 0x1F - - #define hp_pio_data 0x20 - #define hp_reserved_21 0x21 - #define hp_ee_ctrl 0x22 - - #define EXT_ARB_ACK BIT(7) - #define SCSI_TERM_ENA_H BIT(6) /* SCSI high byte terminator */ - #define SEE_MS BIT(5) - #define SEE_CS BIT(3) - #define SEE_CLK BIT(2) - #define SEE_DO BIT(1) - #define SEE_DI BIT(0) - - #define EE_READ 0x06 - #define EE_WRITE 0x05 - #define EWEN 0x04 - #define EWEN_ADDR 0x03C0 - #define EWDS 0x04 - #define EWDS_ADDR 0x0000 - - #define hp_brdctl 0x23 - - #define DAT_7 BIT(7) - #define DAT_6 BIT(6) - #define DAT_5 BIT(5) - #define BRD_STB BIT(4) - #define BRD_CS BIT(3) - #define BRD_WR BIT(2) - - #define hp_reserved_24 0x24 - #define hp_reserved_25 0x25 - - - - - #define hp_bm_ctrl 0x26 - - #define SCSI_TERM_ENA_L BIT(0) /*Enable/Disable external terminators */ - #define FLUSH_XFER_CNTR BIT(1) /*Flush transfer counter */ - #define BM_XFER_MIN_8 BIT(2) /*Enable bus master transfer of 9 */ - #define BIOS_ENA BIT(3) /*Enable BIOS/FLASH Enable */ - #define FORCE1_XFER BIT(5) /*Always xfer one byte in byte mode */ - #define FAST_SINGLE BIT(6) /*?? */ - - #define BMCTRL_DEFAULT (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L) - - #define hp_reserved_27 0x27 - - #define hp_sg_addr 0x28 - #define hp_page_ctrl 0x29 - - #define SCATTER_EN BIT(0) - #define SGRAM_ARAM BIT(1) - #define BIOS_SHADOW BIT(2) - #define G_INT_DISABLE BIT(3) /* Enable/Disable all Interrupts */ - #define NARROW_SCSI_CARD BIT(4) /* NARROW/WIDE SCSI config pin */ - - #define hp_reserved_2A 0x2A - #define hp_pci_cmd_cfg 0x2B - - #define IO_SPACE_ENA BIT(0) /*enable I/O space */ - #define MEM_SPACE_ENA BIT(1) /*enable memory space */ - #define BUS_MSTR_ENA BIT(2) /*enable bus master operation */ - #define MEM_WI_ENA BIT(4) /*enable Write and Invalidate */ - #define PAR_ERR_RESP BIT(6) /*enable parity error responce. */ - - #define hp_reserved_2C 0x2C - - #define hp_pci_stat_cfg 0x2D - - #define DATA_PARITY_ERR BIT(0) - #define REC_TARGET_ABORT BIT(4) /*received Target abort */ - #define REC_MASTER_ABORT BIT(5) /*received Master abort */ - #define SIG_SYSTEM_ERR BIT(6) - #define DETECTED_PAR_ERR BIT(7) - - #define hp_reserved_2E 0x2E - - #define hp_sys_status 0x2F - - #define SLV_DATA_RDY BIT(0) /*Slave data ready */ - #define XFER_CNT_ZERO BIT(1) /*Transfer counter = 0 */ - #define BM_FIFO_EMPTY BIT(2) /*FIFO empty */ - #define BM_FIFO_FULL BIT(3) /*FIFO full */ - #define HOST_OP_DONE BIT(4) /*host operation done */ - #define DMA_OP_DONE BIT(5) /*DMA operation done */ - #define SLV_OP_DONE BIT(6) /*Slave operation done */ - #define PWR_ON_FLAG BIT(7) /*Power on flag */ - - #define hp_reserved_30 0x30 - - #define hp_host_status0 0x31 - - #define HOST_TERM BIT(5) /*Host Terminal Count */ - #define HOST_TRSHLD BIT(6) /*Host Threshold */ - #define CONNECTED_2_HOST BIT(7) /*Connected to Host */ - - #define hp_reserved_32 0x32 - - #define hp_rev_num 0x33 - - #define REV_A_CONST 0x0E - #define REV_B_CONST 0x0E - - #define hp_stack_data 0x34 - #define hp_stack_addr 0x35 - - #define hp_ext_status 0x36 - - #define BM_FORCE_OFF BIT(0) /*Bus Master is forced to get off */ - #define PCI_TGT_ABORT BIT(0) /*PCI bus master transaction aborted */ - #define PCI_DEV_TMOUT BIT(1) /*PCI Device Time out */ - #define FIFO_TC_NOT_ZERO BIT(2) /*FIFO or transfer counter not zero */ - #define CHIP_RST_OCCUR BIT(3) /*Chip reset occurs */ - #define CMD_ABORTED BIT(4) /*Command aborted */ - #define BM_PARITY_ERR BIT(5) /*parity error on data received */ - #define PIO_OVERRUN BIT(6) /*Slave data overrun */ - #define BM_CMD_BUSY BIT(7) /*Bus master transfer command busy */ - #define BAD_EXT_STATUS (BM_FORCE_OFF | PCI_DEV_TMOUT | CMD_ABORTED | \ - BM_PARITY_ERR | PIO_OVERRUN) - - #define hp_int_status 0x37 - - #define BM_CMD_CMPL BIT(0) /*Bus Master command complete */ - #define EXT_STATUS_ON BIT(1) /*Extended status is valid */ - #define SCSI_INTERRUPT BIT(2) /*Global indication of a SCSI int. */ - #define BM_FIFO_RDY BIT(4) - #define INT_ASSERTED BIT(5) /* */ - #define SRAM_BUSY BIT(6) /*Scatter/Gather RAM busy */ - #define CMD_REG_BUSY BIT(7) - - - #define hp_fifo_cnt 0x38 - #define hp_curr_host_cnt 0x39 - #define hp_reserved_3A 0x3A - #define hp_fifo_in_addr 0x3B - - #define hp_fifo_out_addr 0x3C - #define hp_reserved_3D 0x3D - #define hp_reserved_3E 0x3E - #define hp_reserved_3F 0x3F - - - - extern USHORT default_intena; - - #define hp_intena 0x40 - - #define RESET BITW(7) - #define PROG_HLT BITW(6) - #define PARITY BITW(5) - #define FIFO BITW(4) - #define SEL BITW(3) - #define SCAM_SEL BITW(2) - #define RSEL BITW(1) - #define TIMEOUT BITW(0) - #define BUS_FREE BITW(15) - #define XFER_CNT_0 BITW(14) - #define PHASE BITW(13) - #define IUNKWN BITW(12) - #define ICMD_COMP BITW(11) - #define ITICKLE BITW(10) - #define IDO_STRT BITW(9) - #define ITAR_DISC BITW(8) - #define AUTO_INT (BITW(12)+BITW(11)+BITW(10)+BITW(9)+BITW(8)) - #define CLR_ALL_INT 0xFFFF - #define CLR_ALL_INT_1 0xFF00 - - #define hp_intstat 0x42 - - #define hp_scsisig 0x44 - - #define SCSI_SEL BIT(7) - #define SCSI_BSY BIT(6) - #define SCSI_REQ BIT(5) - #define SCSI_ACK BIT(4) - #define SCSI_ATN BIT(3) - #define SCSI_CD BIT(2) - #define SCSI_MSG BIT(1) - #define SCSI_IOBIT BIT(0) - - #define S_SCSI_PHZ (BIT(2)+BIT(1)+BIT(0)) - #define S_CMD_PH (BIT(2) ) - #define S_MSGO_PH (BIT(2)+BIT(1) ) - #define S_STAT_PH (BIT(2) +BIT(0)) - #define S_MSGI_PH (BIT(2)+BIT(1)+BIT(0)) - #define S_DATAI_PH ( BIT(0)) - #define S_DATAO_PH 0x00 - #define S_ILL_PH ( BIT(1) ) - - #define hp_scsictrl_0 0x45 - - #define NO_ARB BIT(7) - #define SEL_TAR BIT(6) - #define ENA_ATN BIT(4) - #define ENA_RESEL BIT(2) - #define SCSI_RST BIT(1) - #define ENA_SCAM_SEL BIT(0) - - - - #define hp_portctrl_0 0x46 - - #define SCSI_PORT BIT(7) - #define SCSI_INBIT BIT(6) - #define DMA_PORT BIT(5) - #define DMA_RD BIT(4) - #define HOST_PORT BIT(3) - #define HOST_WRT BIT(2) - #define SCSI_BUS_EN BIT(1) - #define START_TO BIT(0) - - #define hp_scsireset 0x47 - - #define SCSI_TAR BIT(7) - #define SCSI_INI BIT(6) - #define SCAM_EN BIT(5) - #define ACK_HOLD BIT(4) - #define DMA_RESET BIT(3) - #define HPSCSI_RESET BIT(2) - #define PROG_RESET BIT(1) - #define FIFO_CLR BIT(0) - - #define hp_xfercnt_0 0x48 - #define hp_xfercnt_1 0x49 - #define hp_xfercnt_2 0x4A - #define hp_xfercnt_3 0x4B - - #define hp_fifodata_0 0x4C - #define hp_fifodata_1 0x4D - #define hp_addstat 0x4E - - #define SCAM_TIMER BIT(7) - #define AUTO_RUNNING BIT(6) - #define FAST_SYNC BIT(5) - #define SCSI_MODE8 BIT(3) - #define SCSI_PAR_ERR BIT(0) - - #define hp_prgmcnt_0 0x4F - - #define AUTO_PC_MASK 0x3F - - #define hp_selfid_0 0x50 - #define hp_selfid_1 0x51 - #define hp_arb_id 0x52 - - #define ARB_ID (BIT(3) + BIT(2) + BIT(1) + BIT(0)) - - #define hp_select_id 0x53 - - #define RESEL_ID (BIT(7) + BIT(6) + BIT(5) + BIT(4)) - #define SELECT_ID (BIT(3) + BIT(2) + BIT(1) + BIT(0)) - - #define hp_synctarg_base 0x54 - #define hp_synctarg_12 0x54 - #define hp_synctarg_13 0x55 - #define hp_synctarg_14 0x56 - #define hp_synctarg_15 0x57 - - #define hp_synctarg_8 0x58 - #define hp_synctarg_9 0x59 - #define hp_synctarg_10 0x5A - #define hp_synctarg_11 0x5B - - #define hp_synctarg_4 0x5C - #define hp_synctarg_5 0x5D - #define hp_synctarg_6 0x5E - #define hp_synctarg_7 0x5F - - #define hp_synctarg_0 0x60 - #define hp_synctarg_1 0x61 - #define hp_synctarg_2 0x62 - #define hp_synctarg_3 0x63 - - #define RATE_20MB 0x00 - #define RATE_10MB ( BIT(5)) - #define RATE_6_6MB ( BIT(6) ) - #define RATE_5MB ( BIT(6)+BIT(5)) - #define RATE_4MB (BIT(7) ) - #define RATE_3_33MB (BIT(7) +BIT(5)) - #define RATE_2_85MB (BIT(7)+BIT(6) ) - #define RATE_2_5MB (BIT(7)+BIT(5)+BIT(6)) - #define NEXT_CLK BIT(5) - #define SLOWEST_SYNC (BIT(7)+BIT(6)+BIT(5)) - #define NARROW_SCSI BIT(4) - #define SYNC_OFFSET (BIT(3) + BIT(2) + BIT(1) + BIT(0)) - #define DEFAULT_ASYNC 0x00 - #define DEFAULT_OFFSET 0x0F - - #define hp_autostart_0 0x64 - #define hp_autostart_1 0x65 - #define hp_autostart_2 0x66 - #define hp_autostart_3 0x67 - - - - #define DISABLE 0x00 - #define AUTO_IMMED BIT(5) - #define SELECT BIT(6) - #define RESELECT (BIT(6)+BIT(5)) - #define BUSFREE BIT(7) - #define XFER_0 (BIT(7)+BIT(5)) - #define END_DATA (BIT(7)+BIT(6)) - #define MSG_PHZ (BIT(7)+BIT(6)+BIT(5)) - - #define hp_gp_reg_0 0x68 - #define hp_gp_reg_1 0x69 - #define hp_gp_reg_2 0x6A - #define hp_gp_reg_3 0x6B - - #define hp_seltimeout 0x6C - - - #define TO_2ms 0x54 /* 2.0503ms */ - #define TO_4ms 0x67 /* 3.9959ms */ - - #define TO_5ms 0x03 /* 4.9152ms */ - #define TO_10ms 0x07 /* 11.xxxms */ - #define TO_250ms 0x99 /* 250.68ms */ - #define TO_290ms 0xB1 /* 289.99ms */ - #define TO_350ms 0xD6 /* 350.62ms */ - #define TO_417ms 0xFF /* 417.79ms */ - - #define hp_clkctrl_0 0x6D - - #define PWR_DWN BIT(6) - #define ACTdeassert BIT(4) - #define ATNonErr BIT(3) - #define CLK_30MHZ BIT(1) - #define CLK_40MHZ (BIT(1) + BIT(0)) - #define CLK_50MHZ BIT(2) - - #define CLKCTRL_DEFAULT (ACTdeassert | CLK_40MHZ) - - #define hp_fiforead 0x6E - #define hp_fifowrite 0x6F - - #define hp_offsetctr 0x70 - #define hp_xferstat 0x71 - - #define FIFO_FULL BIT(7) - #define FIFO_EMPTY BIT(6) - #define FIFO_MASK 0x3F /* Mask for the FIFO count value. */ - #define FIFO_LEN 0x20 - - #define hp_portctrl_1 0x72 - - #define EVEN_HOST_P BIT(5) - #define INVT_SCSI BIT(4) - #define CHK_SCSI_P BIT(3) - #define HOST_MODE8 BIT(0) - #define HOST_MODE16 0x00 - - #define hp_xfer_pad 0x73 - - #define ID_UNLOCK BIT(3) - #define XFER_PAD BIT(2) - - #define hp_scsidata_0 0x74 - #define hp_scsidata_1 0x75 - #define hp_timer_0 0x76 - #define hp_timer_1 0x77 - - #define hp_reserved_78 0x78 - #define hp_reserved_79 0x79 - #define hp_reserved_7A 0x7A - #define hp_reserved_7B 0x7B - - #define hp_reserved_7C 0x7C - #define hp_reserved_7D 0x7D - #define hp_reserved_7E 0x7E - #define hp_reserved_7F 0x7F - - #define hp_aramBase 0x80 - #define BIOS_DATA_OFFSET 0x60 - #define BIOS_RELATIVE_CARD 0x64 - - - - - #define AUTO_LEN 0x80 - #define AR0 0x00 - #define AR1 BITW(8) - #define AR2 BITW(9) - #define AR3 (BITW(9) + BITW(8)) - #define SDATA BITW(10) - - #define NOP_OP 0x00 /* Nop command */ - - #define CRD_OP BITW(11) /* Cmp Reg. w/ Data */ - - #define CRR_OP BITW(12) /* Cmp Reg. w. Reg. */ - - #define CBE_OP (BITW(14)+BITW(12)+BITW(11)) /* Cmp SCSI cmd class & Branch EQ */ - - #define CBN_OP (BITW(14)+BITW(13)) /* Cmp SCSI cmd class & Branch NOT EQ */ - - #define CPE_OP (BITW(14)+BITW(11)) /* Cmp SCSI phs & Branch EQ */ - - #define CPN_OP (BITW(14)+BITW(12)) /* Cmp SCSI phs & Branch NOT EQ */ - - - #define ADATA_OUT 0x00 - #define ADATA_IN BITW(8) - #define ACOMMAND BITW(10) - #define ASTATUS (BITW(10)+BITW(8)) - #define AMSG_OUT (BITW(10)+BITW(9)) - #define AMSG_IN (BITW(10)+BITW(9)+BITW(8)) - #define AILLEGAL (BITW(9)+BITW(8)) - - - #define BRH_OP BITW(13) /* Branch */ - - - #define ALWAYS 0x00 - #define EQUAL BITW(8) - #define NOT_EQ BITW(9) - - #define TCB_OP (BITW(13)+BITW(11)) /* Test condition & branch */ - - - #define ATN_SET BITW(8) - #define ATN_RESET BITW(9) - #define XFER_CNT (BITW(9)+BITW(8)) - #define FIFO_0 BITW(10) - #define FIFO_NOT0 (BITW(10)+BITW(8)) - #define T_USE_SYNC0 (BITW(10)+BITW(9)) - - - #define MPM_OP BITW(15) /* Match phase and move data */ - - #define MDR_OP (BITW(12)+BITW(11)) /* Move data to Reg. */ - - #define MRR_OP BITW(14) /* Move DReg. to Reg. */ - - - #define S_IDREG (BIT(2)+BIT(1)+BIT(0)) - - - #define D_AR0 0x00 - #define D_AR1 BIT(0) - #define D_AR2 BIT(1) - #define D_AR3 (BIT(1) + BIT(0)) - #define D_SDATA BIT(2) - #define D_BUCKET (BIT(2) + BIT(1) + BIT(0)) - - - #define ADR_OP (BITW(13)+BITW(12)) /* Logical AND Reg. w. Data */ - - #define ADS_OP (BITW(14)+BITW(13)+BITW(12)) - - #define ODR_OP (BITW(13)+BITW(12)+BITW(11)) - - #define ODS_OP (BITW(14)+BITW(13)+BITW(12)+BITW(11)) - - #define STR_OP (BITW(15)+BITW(14)) /* Store to A_Reg. */ - - #define AINT_ENA1 0x00 - #define AINT_STAT1 BITW(8) - #define ASCSI_SIG BITW(9) - #define ASCSI_CNTL (BITW(9)+BITW(8)) - #define APORT_CNTL BITW(10) - #define ARST_CNTL (BITW(10)+BITW(8)) - #define AXFERCNT0 (BITW(10)+BITW(9)) - #define AXFERCNT1 (BITW(10)+BITW(9)+BITW(8)) - #define AXFERCNT2 BITW(11) - #define AFIFO_DATA (BITW(11)+BITW(8)) - #define ASCSISELID (BITW(11)+BITW(9)) - #define ASCSISYNC0 (BITW(11)+BITW(9)+BITW(8)) - - - #define RAT_OP (BITW(14)+BITW(13)+BITW(11)) - - #define SSI_OP (BITW(15)+BITW(11)) - - - #define SSI_ITAR_DISC (ITAR_DISC >> 8) - #define SSI_IDO_STRT (IDO_STRT >> 8) - #define SSI_IDI_STRT (IDO_STRT >> 8) - - #define SSI_ICMD_COMP (ICMD_COMP >> 8) - #define SSI_ITICKLE (ITICKLE >> 8) - - #define SSI_IUNKWN (IUNKWN >> 8) - #define SSI_INO_CC (IUNKWN >> 8) - #define SSI_IRFAIL (IUNKWN >> 8) - - - #define NP 0x10 /*Next Phase */ - #define NTCMD 0x02 /*Non- Tagged Command start */ - #define CMDPZ 0x04 /*Command phase */ - #define DINT 0x12 /*Data Out/In interrupt */ - #define DI 0x13 /*Data Out */ - #define MI 0x14 /*Message In */ - #define DC 0x19 /*Disconnect Message */ - #define ST 0x1D /*Status Phase */ - #define UNKNWN 0x24 /*Unknown bus action */ - #define CC 0x25 /*Command Completion failure */ - #define TICK 0x26 /*New target reselected us. */ - #define RFAIL 0x27 /*Reselection failed */ - #define SELCHK 0x28 /*Select & Check SCSI ID latch reg */ - - - #define ID_MSG_STRT hp_aramBase + 0x00 - #define NON_TAG_ID_MSG hp_aramBase + 0x06 - #define CMD_STRT hp_aramBase + 0x08 - #define SYNC_MSGS hp_aramBase + 0x08 - - - - - - #define TAG_STRT 0x00 - #define SELECTION_START 0x00 - #define DISCONNECT_START 0x10/2 - #define END_DATA_START 0x14/2 - #define NONTAG_STRT 0x02/2 - #define CMD_ONLY_STRT CMDPZ/2 - #define TICKLE_STRT TICK/2 - #define SELCHK_STRT SELCHK/2 - - - - -#define mEEPROM_CLK_DELAY(port) (RD_HARPOON(port+hp_intstat_1)) - -#define mWAIT_10MS(port) (RD_HARPOON(port+hp_intstat_1)) - - -#define CLR_XFER_CNT(port) (WR_HARPOON(port+hp_xfercnt_0, 0x00)) - -#define SET_XFER_CNT(port, data) (WR_HARP32(port,hp_xfercnt_0,data)) - -#define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;} -/* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \ - xfercnt <<= 16,\ - xfercnt |= RDW_HARPOON((USHORT)(port+hp_xfercnt_0))) - */ -#if defined(DOS) -#define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((USHORT)(port+hp_host_addr_lo), (USHORT)(addr & 0x0000FFFFL)),\ - addr >>= 16,\ - WRW_HARPOON((USHORT)(port+hp_host_addr_hmi), (USHORT)(addr & 0x0000FFFFL)),\ - WR_HARP32(port,hp_xfercnt_0,count),\ - WRW_HARPOON((USHORT)(port+hp_xfer_cnt_lo), (USHORT)(count & 0x0000FFFFL)),\ - count >>= 16,\ - WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF))) -#else -#define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((port+hp_host_addr_lo), (USHORT)(addr & 0x0000FFFFL)),\ - addr >>= 16,\ - WRW_HARPOON((port+hp_host_addr_hmi), (USHORT)(addr & 0x0000FFFFL)),\ - WR_HARP32(port,hp_xfercnt_0,count),\ - WRW_HARPOON((port+hp_xfer_cnt_lo), (USHORT)(count & 0x0000FFFFL)),\ - count >>= 16,\ - WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF))) -#endif - -#define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\ - WR_HARPOON(port+hp_scsisig, S_ILL_PH);} - - -#define ACCEPT_MSG_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\ - WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));} - -#define ACCEPT_STAT(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\ - WR_HARPOON(port+hp_scsisig, S_ILL_PH);} - -#define ACCEPT_STAT_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\ - WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));} - -#define DISABLE_AUTO(port) (WR_HARPOON(port+hp_scsireset, PROG_RESET),\ - WR_HARPOON(port+hp_scsireset, 0x00)) - -#define ARAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \ - (RD_HARPOON(p_port+hp_page_ctrl) | SGRAM_ARAM))) - -#define SGRAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \ - (RD_HARPOON(p_port+hp_page_ctrl) & ~SGRAM_ARAM))) - -#define MDISABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \ - (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE))) - -#define MENABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \ - (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE))) - - - -#endif - - -#if (FW_TYPE==_UCB_MGR_) -void ReadNVRam(PSCCBcard pCurrCard,PUCB p_ucb); -void WriteNVRam(PSCCBcard pCurrCard,PUCB p_ucb); -void UpdateCheckSum(u32bits baseport); -#endif // (FW_TYPE==_UCB_MGR_) - -#if defined(DOS) -UCHAR sfm(USHORT port, PSCCB pcurrSCCB); -void scsiStartAuto(USHORT port); -UCHAR sisyncn(USHORT port, UCHAR p_card, UCHAR syncFlag); -void ssel(USHORT port, UCHAR p_card); -void sres(USHORT port, UCHAR p_card, PSCCBcard pCurrCard); -void sdecm(UCHAR message, USHORT port, UCHAR p_card); -void shandem(USHORT port, UCHAR p_card,PSCCB pCurrSCCB); -void stsyncn(USHORT port, UCHAR p_card); -void sisyncr(USHORT port,UCHAR sync_pulse, UCHAR offset); -void sssyncv(USHORT p_port, UCHAR p_id, UCHAR p_sync_value, PSCCBMgr_tar_info currTar_Info); -void sresb(USHORT port, UCHAR p_card); -void sxfrp(USHORT p_port, UCHAR p_card); -void schkdd(USHORT port, UCHAR p_card); -UCHAR RdStack(USHORT port, UCHAR index); -void WrStack(USHORT portBase, UCHAR index, UCHAR data); -UCHAR ChkIfChipInitialized(USHORT ioPort); - -#if defined(V302) -UCHAR GetTarLun(USHORT port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tag, PUCHAR lun); -#endif - -void SendMsg(USHORT port, UCHAR message); -void queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, UCHAR error_code); -UCHAR scsellDOS(USHORT p_port, UCHAR targ_id); -#else -UCHAR sfm(ULONG port, PSCCB pcurrSCCB); -void scsiStartAuto(ULONG port); -UCHAR sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag); -void ssel(ULONG port, UCHAR p_card); -void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard); -void sdecm(UCHAR message, ULONG port, UCHAR p_card); -void shandem(ULONG port, UCHAR p_card,PSCCB pCurrSCCB); -void stsyncn(ULONG port, UCHAR p_card); -void sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset); -void sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value, PSCCBMgr_tar_info currTar_Info); -void sresb(ULONG port, UCHAR p_card); -void sxfrp(ULONG p_port, UCHAR p_card); -void schkdd(ULONG port, UCHAR p_card); -UCHAR RdStack(ULONG port, UCHAR index); -void WrStack(ULONG portBase, UCHAR index, UCHAR data); -UCHAR ChkIfChipInitialized(ULONG ioPort); - -#if defined(V302) -UCHAR GetTarLun(ULONG port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tar, PUCHAR lun); -#endif - -void SendMsg(ULONG port, UCHAR message); -void queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, UCHAR error_code); -#endif - -void ssenss(PSCCBcard pCurrCard); -void sinits(PSCCB p_sccb, UCHAR p_card); -void RNVRamData(PNVRamInfo pNvRamInfo); - -#if defined(WIDE_SCSI) - #if defined(DOS) - UCHAR siwidn(USHORT port, UCHAR p_card); - void stwidn(USHORT port, UCHAR p_card); - void siwidr(USHORT port, UCHAR width); - #else - UCHAR siwidn(ULONG port, UCHAR p_card); - void stwidn(ULONG port, UCHAR p_card); - void siwidr(ULONG port, UCHAR width); - #endif -#endif - - -void queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card); -void queueDisconnect(PSCCB p_SCCB, UCHAR p_card); -void queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_SCCB, UCHAR p_card); -void queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card); -void queueFlushSccb(UCHAR p_card, UCHAR error_code); -void queueAddSccb(PSCCB p_SCCB, UCHAR card); -UCHAR queueFindSccb(PSCCB p_SCCB, UCHAR p_card); -void utilUpdateResidual(PSCCB p_SCCB); -USHORT CalcCrc16(UCHAR buffer[]); -UCHAR CalcLrc(UCHAR buffer[]); - - -#if defined(DOS) -void Wait1Second(USHORT p_port); -void Wait(USHORT p_port, UCHAR p_delay); -void utilEEWriteOnOff(USHORT p_port,UCHAR p_mode); -void utilEEWrite(USHORT p_port, USHORT ee_data, USHORT ee_addr); -USHORT utilEERead(USHORT p_port, USHORT ee_addr); -USHORT utilEEReadOrg(USHORT p_port, USHORT ee_addr); -void utilEESendCmdAddr(USHORT p_port, UCHAR ee_cmd, USHORT ee_addr); -#else -void Wait1Second(ULONG p_port); -void Wait(ULONG p_port, UCHAR p_delay); -void utilEEWriteOnOff(ULONG p_port,UCHAR p_mode); -void utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr); -USHORT utilEERead(ULONG p_port, USHORT ee_addr); -USHORT utilEEReadOrg(ULONG p_port, USHORT ee_addr); -void utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr); -#endif - - - -#if defined(OS2) - void far phaseDataOut(ULONG port, UCHAR p_card); - void far phaseDataIn(ULONG port, UCHAR p_card); - void far phaseCommand(ULONG port, UCHAR p_card); - void far phaseStatus(ULONG port, UCHAR p_card); - void far phaseMsgOut(ULONG port, UCHAR p_card); - void far phaseMsgIn(ULONG port, UCHAR p_card); - void far phaseIllegal(ULONG port, UCHAR p_card); -#else - #if defined(DOS) - void phaseDataOut(USHORT port, UCHAR p_card); - void phaseDataIn(USHORT port, UCHAR p_card); - void phaseCommand(USHORT port, UCHAR p_card); - void phaseStatus(USHORT port, UCHAR p_card); - void phaseMsgOut(USHORT port, UCHAR p_card); - void phaseMsgIn(USHORT port, UCHAR p_card); - void phaseIllegal(USHORT port, UCHAR p_card); - #else - void phaseDataOut(ULONG port, UCHAR p_card); - void phaseDataIn(ULONG port, UCHAR p_card); - void phaseCommand(ULONG port, UCHAR p_card); - void phaseStatus(ULONG port, UCHAR p_card); - void phaseMsgOut(ULONG port, UCHAR p_card); - void phaseMsgIn(ULONG port, UCHAR p_card); - void phaseIllegal(ULONG port, UCHAR p_card); - #endif -#endif - -#if defined(DOS) -void phaseDecode(USHORT port, UCHAR p_card); -void phaseChkFifo(USHORT port, UCHAR p_card); -void phaseBusFree(USHORT p_port, UCHAR p_card); -#else -void phaseDecode(ULONG port, UCHAR p_card); -void phaseChkFifo(ULONG port, UCHAR p_card); -void phaseBusFree(ULONG p_port, UCHAR p_card); -#endif - - - - -#if defined(DOS) -void XbowInit(USHORT port, UCHAR scamFlg); -void BusMasterInit(USHORT p_port); -int DiagXbow(USHORT port); -int DiagBusMaster(USHORT port); -void DiagEEPROM(USHORT p_port); -#else -void XbowInit(ULONG port, UCHAR scamFlg); -void BusMasterInit(ULONG p_port); -int DiagXbow(ULONG port); -int DiagBusMaster(ULONG port); -void DiagEEPROM(ULONG p_port); -#endif - - - - -#if defined(DOS) -void busMstrAbort(USHORT port); -UCHAR busMstrTimeOut(USHORT port); -void dataXferProcessor(USHORT port, PSCCBcard pCurrCard); -void busMstrSGDataXferStart(USHORT port, PSCCB pCurrSCCB); -void busMstrDataXferStart(USHORT port, PSCCB pCurrSCCB); -void hostDataXferAbort(USHORT port, UCHAR p_card, PSCCB pCurrSCCB); -#else -void busMstrAbort(ULONG port); -UCHAR busMstrTimeOut(ULONG port); -void dataXferProcessor(ULONG port, PSCCBcard pCurrCard); -void busMstrSGDataXferStart(ULONG port, PSCCB pCurrSCCB); -void busMstrDataXferStart(ULONG port, PSCCB pCurrSCCB); -void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB); -#endif -void hostDataXferRestart(PSCCB currSCCB); - - -#if defined (DOS) -UCHAR SccbMgr_bad_isr(USHORT p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int); -#else -UCHAR SccbMgr_bad_isr(ULONG p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int); - -#endif - -void SccbMgrTableInitAll(void); -void SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card); -void SccbMgrTableInitTarget(UCHAR p_card, UCHAR target); - - - -void scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up); - -#if defined(DOS) -int scarb(USHORT p_port, UCHAR p_sel_type); -void scbusf(USHORT p_port); -void scsel(USHORT p_port); -void scasid(UCHAR p_card, USHORT p_port); -UCHAR scxferc(USHORT p_port, UCHAR p_data); -UCHAR scsendi(USHORT p_port, UCHAR p_id_string[]); -UCHAR sciso(USHORT p_port, UCHAR p_id_string[]); -void scwirod(USHORT p_port, UCHAR p_data_bit); -void scwiros(USHORT p_port, UCHAR p_data_bit); -UCHAR scvalq(UCHAR p_quintet); -UCHAR scsell(USHORT p_port, UCHAR targ_id); -void scwtsel(USHORT p_port); -void inisci(UCHAR p_card, USHORT p_port, UCHAR p_our_id); -void scsavdi(UCHAR p_card, USHORT p_port); -#else -int scarb(ULONG p_port, UCHAR p_sel_type); -void scbusf(ULONG p_port); -void scsel(ULONG p_port); -void scasid(UCHAR p_card, ULONG p_port); -UCHAR scxferc(ULONG p_port, UCHAR p_data); -UCHAR scsendi(ULONG p_port, UCHAR p_id_string[]); -UCHAR sciso(ULONG p_port, UCHAR p_id_string[]); -void scwirod(ULONG p_port, UCHAR p_data_bit); -void scwiros(ULONG p_port, UCHAR p_data_bit); -UCHAR scvalq(UCHAR p_quintet); -UCHAR scsell(ULONG p_port, UCHAR targ_id); -void scwtsel(ULONG p_port); -void inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id); -void scsavdi(UCHAR p_card, ULONG p_port); -#endif -UCHAR scmachid(UCHAR p_card, UCHAR p_id_string[]); - - -#if defined(DOS) -void autoCmdCmplt(USHORT p_port, UCHAR p_card); -void autoLoadDefaultMap(USHORT p_port); -#else -void autoCmdCmplt(ULONG p_port, UCHAR p_card); -void autoLoadDefaultMap(ULONG p_port); -#endif - - - -#if (FW_TYPE==_SCCB_MGR_) - void OS_start_timer(unsigned long ioport, unsigned long timeout); - void OS_stop_timer(unsigned long ioport, unsigned long timeout); - void OS_disable_int(unsigned char intvec); - void OS_enable_int(unsigned char intvec); - void OS_delay(unsigned long count); - int OS_VirtToPhys(u32bits CardHandle, u32bits *physaddr, u32bits *virtaddr); - #if !(defined(UNIX) || defined(OS2) || defined(SOLARIS_REAL_MODE)) - void OS_Lock(PSCCBMGR_INFO pCardInfo); - void OS_UnLock(PSCCBMGR_INFO pCardInfo); -#endif // if FW_TYPE == ... - -#endif - -extern SCCBCARD BL_Card[MAX_CARDS]; -extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR]; - - -#if defined(OS2) - extern void (far *s_PhaseTbl[8]) (ULONG, UCHAR); -#else - #if defined(DOS) - extern void (*s_PhaseTbl[8]) (USHORT, UCHAR); - #else - extern void (*s_PhaseTbl[8]) (ULONG, UCHAR); - #endif -#endif - -extern SCCBSCAM_INFO scamInfo[MAX_SCSI_TAR]; -extern NVRAMINFO nvRamInfo[MAX_MB_CARDS]; -#if defined(DOS) || defined(OS2) -extern UCHAR temp_id_string[ID_STRING_LENGTH]; -#endif -extern UCHAR scamHAString[]; - - -extern UCHAR mbCards; -#if defined(BUGBUG) -extern UCHAR debug_int[MAX_CARDS][debug_size]; -extern UCHAR debug_index[MAX_CARDS]; -void Debug_Load(UCHAR p_card, UCHAR p_bug_data); -#endif - -#if (FW_TYPE==_SCCB_MGR_) -#if defined(DOS) - extern UCHAR first_time; -#endif -#endif /* (FW_TYPE==_SCCB_MGR_) */ - -#if (FW_TYPE==_UCB_MGR_) -#if defined(DOS) - extern u08bits first_time; -#endif -#endif /* (FW_TYPE==_UCB_MGR_) */ - -#if defined(BUGBUG) -void Debug_Load(UCHAR p_card, UCHAR p_bug_data); -#endif - -extern unsigned int SccbGlobalFlags; - - -#ident "$Id: sccb.c 1.18 1997/06/10 16:47:04 mohan Exp $" -/*---------------------------------------------------------------------- - * - * - * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved - * - * This file is available under both the GNU General Public License - * and a BSD-style copyright; see LICENSE.FlashPoint for details. - * - * $Workfile: sccb.c $ - * - * Description: Functions relating to handling of the SCCB interface - * between the device driver and the HARPOON. - * - * $Date: 1997/06/10 16:47:04 $ - * - * $Revision: 1.18 $ - * - *----------------------------------------------------------------------*/ - -/*#include */ - -#if (FW_TYPE==_UCB_MGR_) - /*#include */ - /*#include */ -#endif - -/*#include */ -/*#include */ -/*#include */ -/*#include */ -/*#include */ -/*#include */ - - - -#if (FW_TYPE==_SCCB_MGR_) -#define mOS_Lock(card) OS_Lock((PSCCBMGR_INFO)(((PSCCBcard)card)->cardInfo)) -#define mOS_UnLock(card) OS_UnLock((PSCCBMGR_INFO)(((PSCCBcard)card)->cardInfo)) -#else /* FW_TYPE==_UCB_MGR_ */ -#define mOS_Lock(card) OS_Lock((u32bits)(((PSCCBcard)card)->ioPort)) -#define mOS_UnLock(card) OS_UnLock((u32bits)(((PSCCBcard)card)->ioPort)) -#endif - - -/* -extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR]; -extern SCCBCARD BL_Card[MAX_CARDS]; - -extern NVRAMINFO nvRamInfo[MAX_MB_CARDS]; -extern UCHAR mbCards; - -#if defined (OS2) - extern void (far *s_PhaseTbl[8]) (ULONG, UCHAR); -#else - #if defined(DOS) - extern void (*s_PhaseTbl[8]) (USHORT, UCHAR); - #else - extern void (*s_PhaseTbl[8]) (ULONG, UCHAR); - #endif -#endif - - -#if defined(BUGBUG) -extern UCHAR debug_int[MAX_CARDS][debug_size]; -extern UCHAR debug_index[MAX_CARDS]; -void Debug_Load(UCHAR p_card, UCHAR p_bug_data); -#endif -*/ - -#if (FW_TYPE==_SCCB_MGR_) - -/*--------------------------------------------------------------------- - * - * Function: SccbMgr_sense_adapter - * - * Description: Setup and/or Search for cards and return info to caller. - * - *---------------------------------------------------------------------*/ - -int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo) -{ -#if defined(DOS) -#else - static UCHAR first_time = 1; -#endif - - UCHAR i,j,id,ScamFlg; - USHORT temp,temp2,temp3,temp4,temp5,temp6; -#if defined(DOS) - USHORT ioport; -#else - ULONG ioport; -#endif - PNVRamInfo pCurrNvRam; - -#if defined(DOS) - ioport = (USHORT)pCardInfo->si_baseaddr; -#else - ioport = pCardInfo->si_baseaddr; -#endif - - - if (RD_HARPOON(ioport+hp_vendor_id_0) != ORION_VEND_0) - return((int)FAILURE); - - if ((RD_HARPOON(ioport+hp_vendor_id_1) != ORION_VEND_1)) - return((int)FAILURE); - - if ((RD_HARPOON(ioport+hp_device_id_0) != ORION_DEV_0)) - return((int)FAILURE); - - if ((RD_HARPOON(ioport+hp_device_id_1) != ORION_DEV_1)) - return((int)FAILURE); - - - if (RD_HARPOON(ioport+hp_rev_num) != 0x0f){ - -/* For new Harpoon then check for sub_device ID LSB - the bits(0-3) must be all ZERO for compatible with - current version of SCCBMgr, else skip this Harpoon - device. */ - - if (RD_HARPOON(ioport+hp_sub_device_id_0) & 0x0f) - return((int)FAILURE); - } - - if (first_time) - { - SccbMgrTableInitAll(); - first_time = 0; - mbCards = 0; - } - - if(RdStack(ioport, 0) != 0x00) { - if(ChkIfChipInitialized(ioport) == FALSE) - { - pCurrNvRam = NULL; - WR_HARPOON(ioport+hp_semaphore, 0x00); - XbowInit(ioport, 0); /*Must Init the SCSI before attempting */ - DiagEEPROM(ioport); - } - else - { - if(mbCards < MAX_MB_CARDS) { - pCurrNvRam = &nvRamInfo[mbCards]; - mbCards++; - pCurrNvRam->niBaseAddr = ioport; - RNVRamData(pCurrNvRam); - }else - return((int) FAILURE); - } - }else - pCurrNvRam = NULL; -#if defined (NO_BIOS_OPTION) - pCurrNvRam = NULL; - XbowInit(ioport, 0); /*Must Init the SCSI before attempting */ - DiagEEPROM(ioport); -#endif /* No BIOS Option */ - - WR_HARPOON(ioport+hp_clkctrl_0, CLKCTRL_DEFAULT); - WR_HARPOON(ioport+hp_sys_ctrl, 0x00); - - if(pCurrNvRam) - pCardInfo->si_id = pCurrNvRam->niAdapId; - else - pCardInfo->si_id = (UCHAR)(utilEERead(ioport, (ADAPTER_SCSI_ID/2)) & - (UCHAR)0x0FF); - - pCardInfo->si_lun = 0x00; - pCardInfo->si_fw_revision = ORION_FW_REV; - temp2 = 0x0000; - temp3 = 0x0000; - temp4 = 0x0000; - temp5 = 0x0000; - temp6 = 0x0000; - - for (id = 0; id < (16/2); id++) { - - if(pCurrNvRam){ - temp = (USHORT) pCurrNvRam->niSyncTbl[id]; - temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) + - (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000)); - }else - temp = utilEERead(ioport, (USHORT)((SYNC_RATE_TBL/2)+id)); - - for (i = 0; i < 2; temp >>=8,i++) { - - temp2 >>= 1; - temp3 >>= 1; - temp4 >>= 1; - temp5 >>= 1; - temp6 >>= 1; - switch (temp & 0x3) - { - case AUTO_RATE_20: /* Synchronous, 20 mega-transfers/second */ - temp6 |= 0x8000; /* Fall through */ - case AUTO_RATE_10: /* Synchronous, 10 mega-transfers/second */ - temp5 |= 0x8000; /* Fall through */ - case AUTO_RATE_05: /* Synchronous, 5 mega-transfers/second */ - temp2 |= 0x8000; /* Fall through */ - case AUTO_RATE_00: /* Asynchronous */ - break; - } - - if (temp & DISC_ENABLE_BIT) - temp3 |= 0x8000; - - if (temp & WIDE_NEGO_BIT) - temp4 |= 0x8000; - - } - } - - pCardInfo->si_per_targ_init_sync = temp2; - pCardInfo->si_per_targ_no_disc = temp3; - pCardInfo->si_per_targ_wide_nego = temp4; - pCardInfo->si_per_targ_fast_nego = temp5; - pCardInfo->si_per_targ_ultra_nego = temp6; - - if(pCurrNvRam) - i = pCurrNvRam->niSysConf; - else - i = (UCHAR)(utilEERead(ioport, (SYSTEM_CONFIG/2))); - - if(pCurrNvRam) - ScamFlg = pCurrNvRam->niScamConf; - else - ScamFlg = (UCHAR) utilEERead(ioport, SCAM_CONFIG/2); - - pCardInfo->si_flags = 0x0000; - - if (i & 0x01) - pCardInfo->si_flags |= SCSI_PARITY_ENA; - - if (!(i & 0x02)) - pCardInfo->si_flags |= SOFT_RESET; - - if (i & 0x10) - pCardInfo->si_flags |= EXTENDED_TRANSLATION; - - if (ScamFlg & SCAM_ENABLED) - pCardInfo->si_flags |= FLAG_SCAM_ENABLED; - - if (ScamFlg & SCAM_LEVEL2) - pCardInfo->si_flags |= FLAG_SCAM_LEVEL2; - - j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L); - if (i & 0x04) { - j |= SCSI_TERM_ENA_L; - } - WR_HARPOON(ioport+hp_bm_ctrl, j ); - - j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H); - if (i & 0x08) { - j |= SCSI_TERM_ENA_H; - } - WR_HARPOON(ioport+hp_ee_ctrl, j ); - - if (!(RD_HARPOON(ioport+hp_page_ctrl) & NARROW_SCSI_CARD)) - - pCardInfo->si_flags |= SUPPORT_16TAR_32LUN; - - pCardInfo->si_card_family = HARPOON_FAMILY; - pCardInfo->si_bustype = BUSTYPE_PCI; - - if(pCurrNvRam){ - pCardInfo->si_card_model[0] = '9'; - switch(pCurrNvRam->niModel & 0x0f){ - case MODEL_LT: - pCardInfo->si_card_model[1] = '3'; - pCardInfo->si_card_model[2] = '0'; - break; - case MODEL_LW: - pCardInfo->si_card_model[1] = '5'; - pCardInfo->si_card_model[2] = '0'; - break; - case MODEL_DL: - pCardInfo->si_card_model[1] = '3'; - pCardInfo->si_card_model[2] = '2'; - break; - case MODEL_DW: - pCardInfo->si_card_model[1] = '5'; - pCardInfo->si_card_model[2] = '2'; - break; - } - }else{ - temp = utilEERead(ioport, (MODEL_NUMB_0/2)); - pCardInfo->si_card_model[0] = (UCHAR)(temp >> 8); - temp = utilEERead(ioport, (MODEL_NUMB_2/2)); - - pCardInfo->si_card_model[1] = (UCHAR)(temp & 0x00FF); - pCardInfo->si_card_model[2] = (UCHAR)(temp >> 8); - } - - if (pCardInfo->si_card_model[1] == '3') - { - if (RD_HARPOON(ioport+hp_ee_ctrl) & BIT(7)) - pCardInfo->si_flags |= LOW_BYTE_TERM; - } - else if (pCardInfo->si_card_model[2] == '0') - { - temp = RD_HARPOON(ioport+hp_xfer_pad); - WR_HARPOON(ioport+hp_xfer_pad, (temp & ~BIT(4))); - if (RD_HARPOON(ioport+hp_ee_ctrl) & BIT(7)) - pCardInfo->si_flags |= LOW_BYTE_TERM; - WR_HARPOON(ioport+hp_xfer_pad, (temp | BIT(4))); - if (RD_HARPOON(ioport+hp_ee_ctrl) & BIT(7)) - pCardInfo->si_flags |= HIGH_BYTE_TERM; - WR_HARPOON(ioport+hp_xfer_pad, temp); - } - else - { - temp = RD_HARPOON(ioport+hp_ee_ctrl); - temp2 = RD_HARPOON(ioport+hp_xfer_pad); - WR_HARPOON(ioport+hp_ee_ctrl, (temp | SEE_CS)); - WR_HARPOON(ioport+hp_xfer_pad, (temp2 | BIT(4))); - temp3 = 0; - for (i = 0; i < 8; i++) - { - temp3 <<= 1; - if (!(RD_HARPOON(ioport+hp_ee_ctrl) & BIT(7))) - temp3 |= 1; - WR_HARPOON(ioport+hp_xfer_pad, (temp2 & ~BIT(4))); - WR_HARPOON(ioport+hp_xfer_pad, (temp2 | BIT(4))); - } - WR_HARPOON(ioport+hp_ee_ctrl, temp); - WR_HARPOON(ioport+hp_xfer_pad, temp2); - if (!(temp3 & BIT(7))) - pCardInfo->si_flags |= LOW_BYTE_TERM; - if (!(temp3 & BIT(6))) - pCardInfo->si_flags |= HIGH_BYTE_TERM; - } - - - ARAM_ACCESS(ioport); - - for ( i = 0; i < 4; i++ ) { - - pCardInfo->si_XlatInfo[i] = - RD_HARPOON(ioport+hp_aramBase+BIOS_DATA_OFFSET+i); - } - - /* return with -1 if no sort, else return with - logical card number sorted by BIOS (zero-based) */ - - pCardInfo->si_relative_cardnum = - (UCHAR)(RD_HARPOON(ioport+hp_aramBase+BIOS_RELATIVE_CARD)-1); - - SGRAM_ACCESS(ioport); - - s_PhaseTbl[0] = phaseDataOut; - s_PhaseTbl[1] = phaseDataIn; - s_PhaseTbl[2] = phaseIllegal; - s_PhaseTbl[3] = phaseIllegal; - s_PhaseTbl[4] = phaseCommand; - s_PhaseTbl[5] = phaseStatus; - s_PhaseTbl[6] = phaseMsgOut; - s_PhaseTbl[7] = phaseMsgIn; - - pCardInfo->si_present = 0x01; - -#if defined(BUGBUG) - - - for (i = 0; i < MAX_CARDS; i++) { - - for (id=0; idsi_baseaddr; -#else - ioport = pCardInfo->si_baseaddr; -#endif - - for(thisCard =0; thisCard <= MAX_CARDS; thisCard++) { - - if (thisCard == MAX_CARDS) { - - return(FAILURE); - } - - if (BL_Card[thisCard].ioPort == ioport) { - - CurrCard = &BL_Card[thisCard]; - SccbMgrTableInitCard(CurrCard,thisCard); - break; - } - - else if (BL_Card[thisCard].ioPort == 0x00) { - - BL_Card[thisCard].ioPort = ioport; - CurrCard = &BL_Card[thisCard]; - - if(mbCards) - for(i = 0; i < mbCards; i++){ - if(CurrCard->ioPort == nvRamInfo[i].niBaseAddr) - CurrCard->pNvRamInfo = &nvRamInfo[i]; - } - SccbMgrTableInitCard(CurrCard,thisCard); - CurrCard->cardIndex = thisCard; - CurrCard->cardInfo = pCardInfo; - - break; - } - } - - pCurrNvRam = CurrCard->pNvRamInfo; - - if(pCurrNvRam){ - ScamFlg = pCurrNvRam->niScamConf; - } - else{ - ScamFlg = (UCHAR) utilEERead(ioport, SCAM_CONFIG/2); - } - - - BusMasterInit(ioport); - XbowInit(ioport, ScamFlg); - -#if defined (NO_BIOS_OPTION) - - - if (DiagXbow(ioport)) return(FAILURE); - if (DiagBusMaster(ioport)) return(FAILURE); - -#endif /* No BIOS Option */ - - autoLoadDefaultMap(ioport); - - - for (i = 0,id = 0x01; i != pCardInfo->si_id; i++,id <<= 1){} - - WR_HARPOON(ioport+hp_selfid_0, id); - WR_HARPOON(ioport+hp_selfid_1, 0x00); - WR_HARPOON(ioport+hp_arb_id, pCardInfo->si_id); - CurrCard->ourId = pCardInfo->si_id; - - i = (UCHAR) pCardInfo->si_flags; - if (i & SCSI_PARITY_ENA) - WR_HARPOON(ioport+hp_portctrl_1,(HOST_MODE8 | CHK_SCSI_P)); - - j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L); - if (i & LOW_BYTE_TERM) - j |= SCSI_TERM_ENA_L; - WR_HARPOON(ioport+hp_bm_ctrl, j); - - j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H); - if (i & HIGH_BYTE_TERM) - j |= SCSI_TERM_ENA_H; - WR_HARPOON(ioport+hp_ee_ctrl, j ); - - - if (!(pCardInfo->si_flags & SOFT_RESET)) { - - sresb(ioport,thisCard); - - scini(thisCard, pCardInfo->si_id, 0); - } - - - - if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS) - CurrCard->globalFlags |= F_NO_FILTER; - - if(pCurrNvRam){ - if(pCurrNvRam->niSysConf & 0x10) - CurrCard->globalFlags |= F_GREEN_PC; - } - else{ - if (utilEERead(ioport, (SYSTEM_CONFIG/2)) & GREEN_PC_ENA) - CurrCard->globalFlags |= F_GREEN_PC; - } - - /* Set global flag to indicate Re-Negotiation to be done on all - ckeck condition */ - if(pCurrNvRam){ - if(pCurrNvRam->niScsiConf & 0x04) - CurrCard->globalFlags |= F_DO_RENEGO; - } - else{ - if (utilEERead(ioport, (SCSI_CONFIG/2)) & RENEGO_ENA) - CurrCard->globalFlags |= F_DO_RENEGO; - } - - if(pCurrNvRam){ - if(pCurrNvRam->niScsiConf & 0x08) - CurrCard->globalFlags |= F_CONLUN_IO; - } - else{ - if (utilEERead(ioport, (SCSI_CONFIG/2)) & CONNIO_ENA) - CurrCard->globalFlags |= F_CONLUN_IO; - } - - - temp = pCardInfo->si_per_targ_no_disc; - - for (i = 0,id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) { - - if (temp & id) - sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC; - } - - sync_bit_map = 0x0001; - - for (id = 0; id < (MAX_SCSI_TAR/2); id++) { - - if(pCurrNvRam){ - temp = (USHORT) pCurrNvRam->niSyncTbl[id]; - temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) + - (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000)); - }else - temp = utilEERead(ioport, (USHORT)((SYNC_RATE_TBL/2)+id)); - - for (i = 0; i < 2; temp >>=8,i++) { - - if (pCardInfo->si_per_targ_init_sync & sync_bit_map) { - - sccbMgrTbl[thisCard][id*2+i].TarEEValue = (UCHAR)temp; - } - - else { - sccbMgrTbl[thisCard][id*2+i].TarStatus |= SYNC_SUPPORTED; - sccbMgrTbl[thisCard][id*2+i].TarEEValue = - (UCHAR)(temp & ~EE_SYNC_MASK); - } - -#if defined(WIDE_SCSI) -/* if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) || - (id*2+i >= 8)){ -*/ - if (pCardInfo->si_per_targ_wide_nego & sync_bit_map){ - - sccbMgrTbl[thisCard][id*2+i].TarEEValue |= EE_WIDE_SCSI; - - } - - else { /* NARROW SCSI */ - sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED; - } - -#else - sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED; -#endif - - - sync_bit_map <<= 1; - - - - } - } - - WR_HARPOON((ioport+hp_semaphore), - (UCHAR)(RD_HARPOON((ioport+hp_semaphore)) | SCCB_MGR_PRESENT)); - -#if defined(DOS) - return((USHORT)CurrCard); -#else - return((ULONG)CurrCard); -#endif -} - -#else /* end (FW_TYPE==_SCCB_MGR_) */ - - - -STATIC s16bits FP_PresenceCheck(PMGR_INFO pMgrInfo) -{ - PMGR_ENTRYPNTS pMgr_EntryPnts = &pMgrInfo->mi_Functions; - - pMgr_EntryPnts->UCBMgr_probe_adapter = probe_adapter; - pMgr_EntryPnts->UCBMgr_init_adapter = init_adapter; - pMgr_EntryPnts->UCBMgr_start_UCB = SccbMgr_start_sccb; - pMgr_EntryPnts->UCBMgr_build_UCB = build_UCB; - pMgr_EntryPnts->UCBMgr_abort_UCB = SccbMgr_abort_sccb; - pMgr_EntryPnts->UCBMgr_my_int = SccbMgr_my_int; - pMgr_EntryPnts->UCBMgr_isr = SccbMgr_isr; - pMgr_EntryPnts->UCBMgr_scsi_reset = SccbMgr_scsi_reset; - pMgr_EntryPnts->UCBMgr_timer_expired = SccbMgr_timer_expired; -#ifndef NO_IOCTLS - pMgr_EntryPnts->UCBMgr_unload_card = SccbMgr_unload_card; - pMgr_EntryPnts->UCBMgr_save_foreign_state = - SccbMgr_save_foreign_state; - pMgr_EntryPnts->UCBMgr_restore_foreign_state = - SccbMgr_restore_foreign_state; - pMgr_EntryPnts->UCBMgr_restore_native_state = - SccbMgr_restore_native_state; -#endif /*NO_IOCTLS*/ - - pMgrInfo->mi_SGListFormat=0x01; - pMgrInfo->mi_DataPtrFormat=0x01; - pMgrInfo->mi_MaxSGElements= (u16bits) 0xffffffff; - pMgrInfo->mi_MgrPrivateLen=sizeof(SCCB); - pMgrInfo->mi_PCIVendorID=BL_VENDOR_ID; - pMgrInfo->mi_PCIDeviceID=FP_DEVICE_ID; - pMgrInfo->mi_MgrAttributes= ATTR_IO_MAPPED + - ATTR_PHYSICAL_ADDRESS + - ATTR_VIRTUAL_ADDRESS + - ATTR_OVERLAPPED_IO_IOCTLS_OK; - pMgrInfo->mi_IoRangeLen = 256; - return(0); -} - - - -/*--------------------------------------------------------------------- - * - * Function: probe_adapter - * - * Description: Setup and/or Search for cards and return info to caller. - * - *---------------------------------------------------------------------*/ -STATIC s32bits probe_adapter(PADAPTER_INFO pAdapterInfo) -{ - u16bits temp,temp2,temp3,temp4; - u08bits i,j,id; - -#if defined(DOS) -#else - static u08bits first_time = 1; -#endif - BASE_PORT ioport; - PNVRamInfo pCurrNvRam; - - ioport = (BASE_PORT)pAdapterInfo->ai_baseaddr; - - - - if (RD_HARPOON(ioport+hp_vendor_id_0) != ORION_VEND_0) - return(1); - - if ((RD_HARPOON(ioport+hp_vendor_id_1) != ORION_VEND_1)) - return(2); - - if ((RD_HARPOON(ioport+hp_device_id_0) != ORION_DEV_0)) - return(3); - - if ((RD_HARPOON(ioport+hp_device_id_1) != ORION_DEV_1)) - return(4); - - - if (RD_HARPOON(ioport+hp_rev_num) != 0x0f){ - - -/* For new Harpoon then check for sub_device ID LSB - the bits(0-3) must be all ZERO for compatible with - current version of SCCBMgr, else skip this Harpoon - device. */ - - if (RD_HARPOON(ioport+hp_sub_device_id_0) & 0x0f) - return(5); - } - - if (first_time) { - - SccbMgrTableInitAll(); - first_time = 0; - mbCards = 0; - } - - if(RdStack(ioport, 0) != 0x00) { - if(ChkIfChipInitialized(ioport) == FALSE) - { - pCurrNvRam = NULL; - WR_HARPOON(ioport+hp_semaphore, 0x00); - XbowInit(ioport, 0); /*Must Init the SCSI before attempting */ - DiagEEPROM(ioport); - } - else - { - if(mbCards < MAX_MB_CARDS) { - pCurrNvRam = &nvRamInfo[mbCards]; - mbCards++; - pCurrNvRam->niBaseAddr = ioport; - RNVRamData(pCurrNvRam); - }else - return((int) FAILURE); - } - }else - pCurrNvRam = NULL; - -#if defined (NO_BIOS_OPTION) - pCurrNvRam = NULL; - XbowInit(ioport, 0); /*Must Init the SCSI before attempting */ - DiagEEPROM(ioport); -#endif /* No BIOS Option */ - - WR_HARPOON(ioport+hp_clkctrl_0, CLKCTRL_DEFAULT); - WR_HARPOON(ioport+hp_sys_ctrl, 0x00); - - if(pCurrNvRam) - pAdapterInfo->ai_id = pCurrNvRam->niAdapId; - else - pAdapterInfo->ai_id = (u08bits)(utilEERead(ioport, (ADAPTER_SCSI_ID/2)) & - (u08bits)0x0FF); - - pAdapterInfo->ai_lun = 0x00; - pAdapterInfo->ai_fw_revision[0] = '3'; - pAdapterInfo->ai_fw_revision[1] = '1'; - pAdapterInfo->ai_fw_revision[2] = '1'; - pAdapterInfo->ai_fw_revision[3] = ' '; - pAdapterInfo->ai_NumChannels = 1; - - temp2 = 0x0000; - temp3 = 0x0000; - temp4 = 0x0000; - - for (id = 0; id < (16/2); id++) { - - if(pCurrNvRam){ - temp = (USHORT) pCurrNvRam->niSyncTbl[id]; - temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) + - (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000)); - }else - temp = utilEERead(ioport, (u16bits)((SYNC_RATE_TBL/2)+id)); - - for (i = 0; i < 2; temp >>=8,i++) { - - if ((temp & 0x03) != AUTO_RATE_00) { - - temp2 >>= 0x01; - temp2 |= 0x8000; - } - - else { - temp2 >>= 0x01; - } - - if (temp & DISC_ENABLE_BIT) { - - temp3 >>= 0x01; - temp3 |= 0x8000; - } - - else { - temp3 >>= 0x01; - } - - if (temp & WIDE_NEGO_BIT) { - - temp4 >>= 0x01; - temp4 |= 0x8000; - } - - else { - temp4 >>= 0x01; - } - - } - } - - pAdapterInfo->ai_per_targ_init_sync = temp2; - pAdapterInfo->ai_per_targ_no_disc = temp3; - pAdapterInfo->ai_per_targ_wide_nego = temp4; - if(pCurrNvRam) - i = pCurrNvRam->niSysConf; - else - i = (u08bits)(utilEERead(ioport, (SYSTEM_CONFIG/2))); - - /* - ** interrupts always level-triggered for FlashPoint - */ - pAdapterInfo->ai_stateinfo |= LEVEL_TRIG; - - if (i & 0x01) - pAdapterInfo->ai_stateinfo |= SCSI_PARITY_ENA; - - if (i & 0x02) /* SCSI Bus reset in AutoSCSI Set ? */ - { - if(pCurrNvRam) - { - j = pCurrNvRam->niScamConf; - } - else - { - j = (u08bits) utilEERead(ioport, SCAM_CONFIG/2); - } - if(j & SCAM_ENABLED) - { - if(j & SCAM_LEVEL2) - { - pAdapterInfo->ai_stateinfo |= SCAM2_ENA; - } - else - { - pAdapterInfo->ai_stateinfo |= SCAM1_ENA; - } - } - } - j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L); - if (i & 0x04) { - j |= SCSI_TERM_ENA_L; - pAdapterInfo->ai_stateinfo |= LOW_BYTE_TERM_ENA; - } - WR_HARPOON(ioport+hp_bm_ctrl, j ); - - j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H); - if (i & 0x08) { - j |= SCSI_TERM_ENA_H; - pAdapterInfo->ai_stateinfo |= HIGH_BYTE_TERM_ENA; - } - WR_HARPOON(ioport+hp_ee_ctrl, j ); - - if(RD_HARPOON(ioport + hp_page_ctrl) & BIOS_SHADOW) - { - pAdapterInfo->ai_FlashRomSize = 64 * 1024; /* 64k ROM */ - } - else - { - pAdapterInfo->ai_FlashRomSize = 32 * 1024; /* 32k ROM */ - } - - pAdapterInfo->ai_stateinfo |= (FAST20_ENA | TAG_QUEUE_ENA); - if (!(RD_HARPOON(ioport+hp_page_ctrl) & NARROW_SCSI_CARD)) - { - pAdapterInfo->ai_attributes |= (WIDE_CAPABLE | FAST20_CAPABLE - | SCAM2_CAPABLE - | TAG_QUEUE_CAPABLE - | SUPRESS_UNDERRRUNS_CAPABLE - | SCSI_PARITY_CAPABLE); - pAdapterInfo->ai_MaxTarg = 16; - pAdapterInfo->ai_MaxLun = 32; - } - else - { - pAdapterInfo->ai_attributes |= (FAST20_CAPABLE | SCAM2_CAPABLE - | TAG_QUEUE_CAPABLE - | SUPRESS_UNDERRRUNS_CAPABLE - | SCSI_PARITY_CAPABLE); - pAdapterInfo->ai_MaxTarg = 8; - pAdapterInfo->ai_MaxLun = 8; - } - - pAdapterInfo->ai_product_family = HARPOON_FAMILY; - pAdapterInfo->ai_HBAbustype = BUSTYPE_PCI; - - for (i=0;iai_card_model[i]=' '; /* initialize the ai_card_model */ - } - - if(pCurrNvRam){ - pAdapterInfo->ai_card_model[0] = '9'; - switch(pCurrNvRam->niModel & 0x0f){ - case MODEL_LT: - pAdapterInfo->ai_card_model[1] = '3'; - pAdapterInfo->ai_card_model[2] = '0'; - break; - case MODEL_LW: - pAdapterInfo->ai_card_model[1] = '5'; - pAdapterInfo->ai_card_model[2] = '0'; - break; - case MODEL_DL: - pAdapterInfo->ai_card_model[1] = '3'; - pAdapterInfo->ai_card_model[2] = '2'; - break; - case MODEL_DW: - pAdapterInfo->ai_card_model[1] = '5'; - pAdapterInfo->ai_card_model[2] = '2'; - break; - } - }else{ - temp = utilEERead(ioport, (MODEL_NUMB_0/2)); - pAdapterInfo->ai_card_model[0] = (u08bits)(temp >> 8); - temp = utilEERead(ioport, (MODEL_NUMB_2/2)); - - pAdapterInfo->ai_card_model[1] = (u08bits)(temp & 0x00FF); - pAdapterInfo->ai_card_model[2] = (u08bits)(temp >> 8); - } - - - - pAdapterInfo->ai_FiberProductType = 0; - - pAdapterInfo->ai_secondary_range = 0; - - for (i=0;iai_worldwidename[i]='\0'; - } - - for (i=0;iai_vendorstring[i]='\0'; - } - pAdapterInfo->ai_vendorstring[0]='B'; - pAdapterInfo->ai_vendorstring[1]='U'; - pAdapterInfo->ai_vendorstring[2]='S'; - pAdapterInfo->ai_vendorstring[3]='L'; - pAdapterInfo->ai_vendorstring[4]='O'; - pAdapterInfo->ai_vendorstring[5]='G'; - pAdapterInfo->ai_vendorstring[6]='I'; - pAdapterInfo->ai_vendorstring[7]='C'; - - for (i=0;iai_AdapterFamilyString[i]='\0'; - } - pAdapterInfo->ai_AdapterFamilyString[0]='F'; - pAdapterInfo->ai_AdapterFamilyString[1]='L'; - pAdapterInfo->ai_AdapterFamilyString[2]='A'; - pAdapterInfo->ai_AdapterFamilyString[3]='S'; - pAdapterInfo->ai_AdapterFamilyString[4]='H'; - pAdapterInfo->ai_AdapterFamilyString[5]='P'; - pAdapterInfo->ai_AdapterFamilyString[6]='O'; - pAdapterInfo->ai_AdapterFamilyString[7]='I'; - pAdapterInfo->ai_AdapterFamilyString[8]='N'; - pAdapterInfo->ai_AdapterFamilyString[9]='T'; - - ARAM_ACCESS(ioport); - - for ( i = 0; i < 4; i++ ) { - - pAdapterInfo->ai_XlatInfo[i] = - RD_HARPOON(ioport+hp_aramBase+BIOS_DATA_OFFSET+i); - } - - /* return with -1 if no sort, else return with - logical card number sorted by BIOS (zero-based) */ - - - pAdapterInfo->ai_relative_cardnum = - (u08bits)(RD_HARPOON(ioport+hp_aramBase+BIOS_RELATIVE_CARD)-1); - - SGRAM_ACCESS(ioport); - - s_PhaseTbl[0] = phaseDataOut; - s_PhaseTbl[1] = phaseDataIn; - s_PhaseTbl[2] = phaseIllegal; - s_PhaseTbl[3] = phaseIllegal; - s_PhaseTbl[4] = phaseCommand; - s_PhaseTbl[5] = phaseStatus; - s_PhaseTbl[6] = phaseMsgOut; - s_PhaseTbl[7] = phaseMsgIn; - - pAdapterInfo->ai_present = 0x01; - -#if defined(BUGBUG) - - - for (i = 0; i < MAX_CARDS; i++) { - - for (id=0; idai_baseaddr; - - for(thisCard =0; thisCard <= MAX_CARDS; thisCard++) { - - if (thisCard == MAX_CARDS) { - - return(FAILURE); - } - - if (BL_Card[thisCard].ioPort == ioport) { - - CurrCard = &BL_Card[thisCard]; - SccbMgrTableInitCard(CurrCard,thisCard); - break; - } - - else if (BL_Card[thisCard].ioPort == 0x00) { - - BL_Card[thisCard].ioPort = ioport; - CurrCard = &BL_Card[thisCard]; - - if(mbCards) - for(i = 0; i < mbCards; i++){ - if(CurrCard->ioPort == nvRamInfo[i].niBaseAddr) - CurrCard->pNvRamInfo = &nvRamInfo[i]; - } - SccbMgrTableInitCard(CurrCard,thisCard); - CurrCard->cardIndex = thisCard; - CurrCard->cardInfo = pCardInfo; - - break; - } - } - - pCurrNvRam = CurrCard->pNvRamInfo; - - - if(pCurrNvRam){ - ScamFlg = pCurrNvRam->niScamConf; - } - else{ - ScamFlg = (UCHAR) utilEERead(ioport, SCAM_CONFIG/2); - } - - - BusMasterInit(ioport); - XbowInit(ioport, ScamFlg); - -#if defined (NO_BIOS_OPTION) - - - if (DiagXbow(ioport)) return(FAILURE); - if (DiagBusMaster(ioport)) return(FAILURE); - -#endif /* No BIOS Option */ - - autoLoadDefaultMap(ioport); - - - for (i = 0,id = 0x01; i != pCardInfo->ai_id; i++,id <<= 1){} - - WR_HARPOON(ioport+hp_selfid_0, id); - WR_HARPOON(ioport+hp_selfid_1, 0x00); - WR_HARPOON(ioport+hp_arb_id, pCardInfo->ai_id); - CurrCard->ourId = (unsigned char) pCardInfo->ai_id; - - i = (u08bits) pCardInfo->ai_stateinfo; - if (i & SCSI_PARITY_ENA) - WR_HARPOON(ioport+hp_portctrl_1,(HOST_MODE8 | CHK_SCSI_P)); - - j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L); - if (i & LOW_BYTE_TERM_ENA) - j |= SCSI_TERM_ENA_L; - WR_HARPOON(ioport+hp_bm_ctrl, j); - - j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H); - if (i & HIGH_BYTE_TERM_ENA) - j |= SCSI_TERM_ENA_H; - WR_HARPOON(ioport+hp_ee_ctrl, j ); - - - if (!(pCardInfo->ai_stateinfo & NO_RESET_IN_INIT)) { - - sresb(ioport,thisCard); - - scini(thisCard, (u08bits) pCardInfo->ai_id, 0); - } - - - - if (pCardInfo->ai_stateinfo & SUPRESS_UNDERRRUNS_ENA) - CurrCard->globalFlags |= F_NO_FILTER; - - if(pCurrNvRam){ - if(pCurrNvRam->niSysConf & 0x10) - CurrCard->globalFlags |= F_GREEN_PC; - } - else{ - if (utilEERead(ioport, (SYSTEM_CONFIG/2)) & GREEN_PC_ENA) - CurrCard->globalFlags |= F_GREEN_PC; - } - - /* Set global flag to indicate Re-Negotiation to be done on all - ckeck condition */ - if(pCurrNvRam){ - if(pCurrNvRam->niScsiConf & 0x04) - CurrCard->globalFlags |= F_DO_RENEGO; - } - else{ - if (utilEERead(ioport, (SCSI_CONFIG/2)) & RENEGO_ENA) - CurrCard->globalFlags |= F_DO_RENEGO; - } - - if(pCurrNvRam){ - if(pCurrNvRam->niScsiConf & 0x08) - CurrCard->globalFlags |= F_CONLUN_IO; - } - else{ - if (utilEERead(ioport, (SCSI_CONFIG/2)) & CONNIO_ENA) - CurrCard->globalFlags |= F_CONLUN_IO; - } - - temp = pCardInfo->ai_per_targ_no_disc; - - for (i = 0,id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) { - - if (temp & id) - sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC; - } - - sync_bit_map = 0x0001; - - for (id = 0; id < (MAX_SCSI_TAR/2); id++){ - - if(pCurrNvRam){ - temp = (USHORT) pCurrNvRam->niSyncTbl[id]; - temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) + - (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000)); - }else - temp = utilEERead(ioport, (u16bits)((SYNC_RATE_TBL/2)+id)); - - for (i = 0; i < 2; temp >>=8,i++){ - - if (pCardInfo->ai_per_targ_init_sync & sync_bit_map){ - - sccbMgrTbl[thisCard][id*2+i].TarEEValue = (u08bits)temp; - } - - else { - sccbMgrTbl[thisCard][id*2+i].TarStatus |= SYNC_SUPPORTED; - sccbMgrTbl[thisCard][id*2+i].TarEEValue = - (u08bits)(temp & ~EE_SYNC_MASK); - } - -#if defined(WIDE_SCSI) -/* if ((pCardInfo->ai_per_targ_wide_nego & sync_bit_map) || - (id*2+i >= 8)){ -*/ - if (pCardInfo->ai_per_targ_wide_nego & sync_bit_map){ - - sccbMgrTbl[thisCard][id*2+i].TarEEValue |= EE_WIDE_SCSI; - - } - - else { /* NARROW SCSI */ - sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED; - } - -#else - sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED; -#endif - - - sync_bit_map <<= 1; - } - } - - - pCardInfo->ai_SGListFormat=0x01; - pCardInfo->ai_DataPtrFormat=0x01; - pCardInfo->ai_AEN_mask &= SCSI_RESET_COMPLETE; - - WR_HARPOON((ioport+hp_semaphore), - (u08bits)(RD_HARPOON((ioport+hp_semaphore)) | SCCB_MGR_PRESENT)); - - return((u32bits)CurrCard); - -} - - -/*--------------------------------------------------------------------- - * - * Function: build_ucb, exported to BUDI via UCBMgr_build_ucb entry - * - * Description: prepare fw portion of ucb. do not start, resource not guaranteed - * so don't manipulate anything that's derived from states which - * may change - * - *---------------------------------------------------------------------*/ -void build_UCB(CARD_HANDLE pCurrCard, PUCB p_ucb) -{ - - u08bits thisCard; - u08bits i,j; - - PSCCB p_sccb; - - - thisCard = ((PSCCBcard) pCurrCard)->cardIndex; - - - p_sccb=(PSCCB)p_ucb->UCB_MgrPrivatePtr; - - - p_sccb->Sccb_ucb_ptr=p_ucb; - - switch (p_ucb->UCB_opcode & (OPC_DEVICE_RESET+OPC_XFER_SG+OPC_CHK_RESIDUAL)) - { - case OPC_DEVICE_RESET: - p_sccb->OperationCode=RESET_COMMAND; - break; - case OPC_XFER_SG: - p_sccb->OperationCode=SCATTER_GATHER_COMMAND; - break; - case OPC_XFER_SG+OPC_CHK_RESIDUAL: - p_sccb->OperationCode=RESIDUAL_SG_COMMAND; - break; - case OPC_CHK_RESIDUAL: - - p_sccb->OperationCode=RESIDUAL_COMMAND; - break; - default: - p_sccb->OperationCode=SCSI_INITIATOR_COMMAND; - break; - } - - if (p_ucb->UCB_opcode & OPC_TQ_ENABLE) - { - p_sccb->ControlByte = (u08bits)((p_ucb->UCB_opcode & OPC_TQ_MASK)>>2) | F_USE_CMD_Q; - } - else - { - p_sccb->ControlByte = 0; - } - - - p_sccb->CdbLength = (u08bits)p_ucb->UCB_cdblen; - - if (p_ucb->UCB_opcode & OPC_NO_AUTO_SENSE) - { - p_sccb->RequestSenseLength = 0; - } - else - { - p_sccb->RequestSenseLength = (unsigned char) p_ucb->UCB_senselen; - } - - - if (p_ucb->UCB_opcode & OPC_XFER_SG) - { - p_sccb->DataPointer=p_ucb->UCB_virt_dataptr; - p_sccb->DataLength = (((u32bits)p_ucb->UCB_NumSgElements)<<3); - } - else - { - p_sccb->DataPointer=p_ucb->UCB_phys_dataptr; - p_sccb->DataLength=p_ucb->UCB_datalen; - }; - - p_sccb->HostStatus=0; - p_sccb->TargetStatus=0; - p_sccb->TargID=(unsigned char)p_ucb->UCB_targid; - p_sccb->Lun=(unsigned char) p_ucb->UCB_lun; - p_sccb->SccbIOPort=((PSCCBcard)pCurrCard)->ioPort; - - j=p_ucb->UCB_cdblen; - for (i=0;iCdb[i] = p_ucb->UCB_cdb[i]; - } - - p_sccb->SensePointer=p_ucb->UCB_phys_senseptr; - - sinits(p_sccb,thisCard); - -} -#ifndef NO_IOCTLS - -/*--------------------------------------------------------------------- - * - * Function: GetDevSyncRate - * - *---------------------------------------------------------------------*/ -STATIC int GetDevSyncRate(PSCCBcard pCurrCard,PUCB p_ucb) -{ - struct _SYNC_RATE_INFO * pSyncStr; - PSCCBMgr_tar_info currTar_Info; - BASE_PORT ioport; - u08bits scsiID, j; - -#if (FW_TYPE != _SCCB_MGR_) - if( p_ucb->UCB_targid >= pCurrCard->cardInfo->ai_MaxTarg ) - { - return(1); - } -#endif - - ioport = pCurrCard->ioPort; - pSyncStr = (struct _SYNC_RATE_INFO *) p_ucb->UCB_virt_dataptr; - scsiID = (u08bits) p_ucb->UCB_targid; - currTar_Info = &sccbMgrTbl[pCurrCard->cardIndex][scsiID]; - j = currTar_Info->TarSyncCtrl; - - switch (currTar_Info->TarEEValue & EE_SYNC_MASK) - { - case EE_SYNC_ASYNC: - pSyncStr->RequestMegaXferRate = 0x00; - break; - case EE_SYNC_5MB: - pSyncStr->RequestMegaXferRate = (j & NARROW_SCSI) ? 50 : 100; - break; - case EE_SYNC_10MB: - pSyncStr->RequestMegaXferRate = (j & NARROW_SCSI) ? 100 : 200; - break; - case EE_SYNC_20MB: - pSyncStr->RequestMegaXferRate = (j & NARROW_SCSI) ? 200 : 400; - break; - } - - switch ((j >> 5) & 0x07) - { - case 0x00: - if((j & 0x07) == 0x00) - { - pSyncStr->ActualMegaXferRate = 0x00; /* Async Mode */ - } - else - { - pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 200 : 400; - } - break; - case 0x01: - pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 100 : 200; - break; - case 0x02: - pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 66 : 122; - break; - case 0x03: - pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 50 : 100; - break; - case 0x04: - pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 40 : 80; - break; - case 0x05: - pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 33 : 66; - break; - case 0x06: - pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 28 : 56; - break; - case 0x07: - pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 25 : 50; - break; - } - pSyncStr->NegotiatedOffset = j & 0x0f; - - return(0); -} - -/*--------------------------------------------------------------------- - * - * Function: SetDevSyncRate - * - *---------------------------------------------------------------------*/ -STATIC int SetDevSyncRate(PSCCBcard pCurrCard, PUCB p_ucb) -{ - struct _SYNC_RATE_INFO * pSyncStr; - PSCCBMgr_tar_info currTar_Info; - BASE_PORT ioPort; - u08bits scsiID, i, j, syncVal; - u16bits syncOffset, actualXferRate; - union { - u08bits tempb[2]; - u16bits tempw; - }temp2; - -#if (FW_TYPE != _SCCB_MGR_) - if( p_ucb->UCB_targid >= pCurrCard->cardInfo->ai_MaxTarg ) - { - return(1); - } -#endif - - ioPort = pCurrCard->ioPort; - pSyncStr = (struct _SYNC_RATE_INFO *) p_ucb->UCB_virt_dataptr; - scsiID = (u08bits) p_ucb->UCB_targid; - currTar_Info = &sccbMgrTbl[pCurrCard->cardIndex][scsiID]; - i = RD_HARPOON(ioPort+hp_xfer_pad); /* Save current value */ - WR_HARPOON(ioPort+hp_xfer_pad, (i | ID_UNLOCK)); - WR_HARPOON(ioPort+hp_select_id, ((scsiID << 4) | scsiID)); - j = RD_HARPOON(ioPort+hp_synctarg_0); - WR_HARPOON(ioPort+hp_xfer_pad, i); /* restore value */ - - actualXferRate = pSyncStr->ActualMegaXferRate; - if(!(j & NARROW_SCSI)) - { - actualXferRate <<= 1; - } - if(actualXferRate == 0x00) - { - syncVal = EE_SYNC_ASYNC; /* Async Mode */ - } - if(actualXferRate == 0x0200) - { - syncVal = EE_SYNC_20MB; /* 20/40 MB Mode */ - } - if(actualXferRate > 0x0050 && actualXferRate < 0x0200 ) - { - syncVal = EE_SYNC_10MB; /* 10/20 MB Mode */ - } - else - { - syncVal = EE_SYNC_5MB; /* 5/10 MB Mode */ - } - if(currTar_Info->TarEEValue && EE_SYNC_MASK == syncVal) - return(0); - currTar_Info->TarEEValue = (currTar_Info->TarEEValue & !EE_SYNC_MASK) - | syncVal; - syncOffset = (SYNC_RATE_TBL + scsiID) / 2; - temp2.tempw = utilEERead(ioPort, syncOffset); - if(scsiID & 0x01) - { - temp2.tempb[0] = (temp2.tempb[0] & !EE_SYNC_MASK) | syncVal; - } - else - { - temp2.tempb[1] = (temp2.tempb[1] & !EE_SYNC_MASK) | syncVal; - } - utilEEWriteOnOff(ioPort, 1); - utilEEWrite(ioPort, temp2.tempw, syncOffset); - utilEEWriteOnOff(ioPort, 0); - UpdateCheckSum(ioPort); - - return(0); -} -/*--------------------------------------------------------------------- - * - * Function: GetDevWideMode - * - *---------------------------------------------------------------------*/ -int GetDevWideMode(PSCCBcard pCurrCard,PUCB p_ucb) -{ - u08bits *pData; - - pData = (u08bits *)p_ucb->UCB_virt_dataptr; - if(sccbMgrTbl[pCurrCard->cardIndex][p_ucb->UCB_targid].TarEEValue - & EE_WIDE_SCSI) - { - *pData = 1; - } - else - { - *pData = 0; - } - - return(0); -} - -/*--------------------------------------------------------------------- - * - * Function: SetDevWideMode - * - *---------------------------------------------------------------------*/ -int SetDevWideMode(PSCCBcard pCurrCard,PUCB p_ucb) -{ - u08bits *pData; - PSCCBMgr_tar_info currTar_Info; - BASE_PORT ioPort; - u08bits scsiID, scsiWideMode; - u16bits syncOffset; - union { - u08bits tempb[2]; - u16bits tempw; - }temp2; - -#if (FW_TYPE != _SCCB_MGR_) - if( !(pCurrCard->cardInfo->ai_attributes & WIDE_CAPABLE) ) - { - return(1); - } - - if( p_ucb->UCB_targid >= pCurrCard->cardInfo->ai_MaxTarg ) - { - return(1); - } -#endif - - ioPort = pCurrCard->ioPort; - pData = (u08bits *)p_ucb->UCB_virt_dataptr; - scsiID = (u08bits) p_ucb->UCB_targid; - currTar_Info = &sccbMgrTbl[pCurrCard->cardIndex][scsiID]; - - if(*pData) - { - if(currTar_Info->TarEEValue & EE_WIDE_SCSI) - { - return(0); - } - else - { - scsiWideMode = EE_WIDE_SCSI; - } - } - else - { - if(!currTar_Info->TarEEValue & EE_WIDE_SCSI) - { - return(0); - } - else - { - scsiWideMode = 0; - } - } - currTar_Info->TarEEValue = (currTar_Info->TarEEValue & !EE_WIDE_SCSI) - | scsiWideMode; - - syncOffset = (SYNC_RATE_TBL + scsiID) / 2; - temp2.tempw = utilEERead(ioPort, syncOffset); - if(scsiID & 0x01) - { - temp2.tempb[0] = (temp2.tempb[0] & !EE_WIDE_SCSI) | scsiWideMode; - } - else - { - temp2.tempb[1] = (temp2.tempb[1] & !EE_WIDE_SCSI) | scsiWideMode; - } - utilEEWriteOnOff(ioPort, 1); - utilEEWrite(ioPort, temp2.tempw, syncOffset); - utilEEWriteOnOff(ioPort, 0); - UpdateCheckSum(ioPort); - - return(0); -} - -/*--------------------------------------------------------------------- - * - * Function: ReadNVRam - * - *---------------------------------------------------------------------*/ -void ReadNVRam(PSCCBcard pCurrCard,PUCB p_ucb) -{ - u08bits *pdata; - u16bits i,numwrds,numbytes,offset,temp; - u08bits OneMore = FALSE; -#if defined(DOS) - u16bits ioport; -#else - u32bits ioport; -#endif - - numbytes = (u16bits) p_ucb->UCB_datalen; - ioport = pCurrCard->ioPort; - pdata = (u08bits *) p_ucb->UCB_virt_dataptr; - offset = (u16bits) (p_ucb->UCB_IOCTLParams[0]); - - - - if (offset & 0x1) - { - *((u16bits*) pdata) = utilEERead(ioport,(u16bits)((offset - 1) / 2)); /* 16 bit read */ - *pdata = *(pdata + 1); - ++offset; - ++pdata; - --numbytes; - } - - numwrds = numbytes / 2; - if (numbytes & 1) - OneMore = TRUE; - - for (i = 0; i < numwrds; i++) - { - *((u16bits*) pdata) = utilEERead(ioport,(u16bits)(offset / 2)); - pdata += 2; - offset += 2; - } - if (OneMore) - { - --pdata; - -- offset; - temp = utilEERead(ioport,(u16bits)(offset / 2)); - *pdata = (u08bits) (temp); - } - -} /* end proc ReadNVRam */ - - -/*--------------------------------------------------------------------- - * - * Function: WriteNVRam - * - *---------------------------------------------------------------------*/ -void WriteNVRam(PSCCBcard pCurrCard,PUCB p_ucb) -{ - u08bits *pdata; - u16bits i,numwrds,numbytes,offset, eeprom_end; - u08bits OneMore = FALSE; - union { - u08bits tempb[2]; - u16bits tempw; - } temp2; - -#if defined(DOS) - u16bits ioport; -#else - u32bits ioport; -#endif - - numbytes = (u16bits) p_ucb->UCB_datalen; - ioport = pCurrCard->ioPort; - pdata = (u08bits *) p_ucb->UCB_virt_dataptr; - offset = (u16bits) (p_ucb->UCB_IOCTLParams[0]); - - if (RD_HARPOON(ioport+hp_page_ctrl) & NARROW_SCSI_CARD) - eeprom_end = 512; - else - eeprom_end = 768; - - if(offset > eeprom_end) - return; - - if((offset + numbytes) > eeprom_end) - numbytes = eeprom_end - offset; - - utilEEWriteOnOff(ioport,1); /* Enable write access to the EEPROM */ - - - - if (offset & 0x1) - { - temp2.tempw = utilEERead(ioport,(u16bits)((offset - 1) / 2)); /* 16 bit read */ - temp2.tempb[1] = *pdata; - utilEEWrite(ioport, temp2.tempw, (u16bits)((offset -1) / 2)); - *pdata = *(pdata + 1); - ++offset; - ++pdata; - --numbytes; - } - - numwrds = numbytes / 2; - if (numbytes & 1) - OneMore = TRUE; - - for (i = 0; i < numwrds; i++) - { - utilEEWrite(ioport, *((pu16bits)pdata),(u16bits)(offset / 2)); - pdata += 2; - offset += 2; - } - if (OneMore) - { - - temp2.tempw = utilEERead(ioport,(u16bits)(offset / 2)); - temp2.tempb[0] = *pdata; - utilEEWrite(ioport, temp2.tempw, (u16bits)(offset / 2)); - } - utilEEWriteOnOff(ioport,0); /* Turn off write access */ - UpdateCheckSum((u32bits)ioport); - -} /* end proc WriteNVRam */ - - - -/*--------------------------------------------------------------------- - * - * Function: UpdateCheckSum - * - * Description: Update Check Sum in EEPROM - * - *---------------------------------------------------------------------*/ - - -void UpdateCheckSum(u32bits baseport) -{ - USHORT i,sum_data, eeprom_end; - - sum_data = 0x0000; - - - if (RD_HARPOON(baseport+hp_page_ctrl) & NARROW_SCSI_CARD) - eeprom_end = 512; - else - eeprom_end = 768; - - for (i = 1; i < eeprom_end/2; i++) - { - sum_data += utilEERead(baseport, i); - } - - utilEEWriteOnOff(baseport,1); /* Enable write access to the EEPROM */ - - utilEEWrite(baseport, sum_data, EEPROM_CHECK_SUM/2); - utilEEWriteOnOff(baseport,0); /* Turn off write access */ -} - -void SccbMgr_save_foreign_state(PADAPTER_INFO pAdapterInfo) -{ -} - - -void SccbMgr_restore_foreign_state(CARD_HANDLE pCurrCard) -{ -} - -void SccbMgr_restore_native_state(CARD_HANDLE pCurrCard) -{ -} - -#endif /* NO_IOCTLS */ - -#endif /* (FW_TYPE==_UCB_MGR_) */ - -#ifndef NO_IOCTLS -#if (FW_TYPE==_UCB_MGR_) -void SccbMgr_unload_card(CARD_HANDLE pCurrCard) -#else -#if defined(DOS) -void SccbMgr_unload_card(USHORT pCurrCard) -#else -void SccbMgr_unload_card(ULONG pCurrCard) -#endif -#endif -{ - UCHAR i; -#if defined(DOS) - USHORT portBase; - USHORT regOffset; -#else - ULONG portBase; - ULONG regOffset; -#endif - ULONG scamData; -#if defined(OS2) - ULONG far *pScamTbl; -#else - ULONG *pScamTbl; -#endif - PNVRamInfo pCurrNvRam; - - pCurrNvRam = ((PSCCBcard)pCurrCard)->pNvRamInfo; - - if(pCurrNvRam){ - WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel); - WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf); - WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf); - WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf); - WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId); - - for(i = 0; i < MAX_SCSI_TAR / 2; i++) - WrStack(pCurrNvRam->niBaseAddr, (UCHAR)(i+5), pCurrNvRam->niSyncTbl[i]); - - portBase = pCurrNvRam->niBaseAddr; - - for(i = 0; i < MAX_SCSI_TAR; i++){ - regOffset = hp_aramBase + 64 + i*4; -#if defined(OS2) - pScamTbl = (ULONG far *) &pCurrNvRam->niScamTbl[i]; -#else - pScamTbl = (ULONG *) &pCurrNvRam->niScamTbl[i]; -#endif - scamData = *pScamTbl; - WR_HARP32(portBase, regOffset, scamData); - } - - }else{ - WrStack(((PSCCBcard)pCurrCard)->ioPort, 0, 0); - } -} -#endif /* NO_IOCTLS */ - - -void RNVRamData(PNVRamInfo pNvRamInfo) -{ - UCHAR i; -#if defined(DOS) - USHORT portBase; - USHORT regOffset; -#else - ULONG portBase; - ULONG regOffset; -#endif - ULONG scamData; -#if defined (OS2) - ULONG far *pScamTbl; -#else - ULONG *pScamTbl; -#endif - - pNvRamInfo->niModel = RdStack(pNvRamInfo->niBaseAddr, 0); - pNvRamInfo->niSysConf = RdStack(pNvRamInfo->niBaseAddr, 1); - pNvRamInfo->niScsiConf = RdStack(pNvRamInfo->niBaseAddr, 2); - pNvRamInfo->niScamConf = RdStack(pNvRamInfo->niBaseAddr, 3); - pNvRamInfo->niAdapId = RdStack(pNvRamInfo->niBaseAddr, 4); - - for(i = 0; i < MAX_SCSI_TAR / 2; i++) - pNvRamInfo->niSyncTbl[i] = RdStack(pNvRamInfo->niBaseAddr, (UCHAR)(i+5)); - - portBase = pNvRamInfo->niBaseAddr; - - for(i = 0; i < MAX_SCSI_TAR; i++){ - regOffset = hp_aramBase + 64 + i*4; - RD_HARP32(portBase, regOffset, scamData); -#if defined(OS2) - pScamTbl = (ULONG far *) &pNvRamInfo->niScamTbl[i]; -#else - pScamTbl = (ULONG *) &pNvRamInfo->niScamTbl[i]; -#endif - *pScamTbl = scamData; - } - -} - -#if defined(DOS) -UCHAR RdStack(USHORT portBase, UCHAR index) -#else -UCHAR RdStack(ULONG portBase, UCHAR index) -#endif -{ - WR_HARPOON(portBase + hp_stack_addr, index); - return(RD_HARPOON(portBase + hp_stack_data)); -} - -#if defined(DOS) -void WrStack(USHORT portBase, UCHAR index, UCHAR data) -#else -void WrStack(ULONG portBase, UCHAR index, UCHAR data) -#endif -{ - WR_HARPOON(portBase + hp_stack_addr, index); - WR_HARPOON(portBase + hp_stack_data, data); -} - - -#if (FW_TYPE==_UCB_MGR_) -u08bits ChkIfChipInitialized(BASE_PORT ioPort) -#else -#if defined(DOS) -UCHAR ChkIfChipInitialized(USHORT ioPort) -#else -UCHAR ChkIfChipInitialized(ULONG ioPort) -#endif -#endif -{ - if((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != RdStack(ioPort, 4)) - return(FALSE); - if((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT) - != CLKCTRL_DEFAULT) - return(FALSE); - if((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) || - (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms)) - return(TRUE); - return(FALSE); - -} -/*--------------------------------------------------------------------- - * - * Function: SccbMgr_start_sccb - * - * Description: Start a command pointed to by p_Sccb. When the - * command is completed it will be returned via the - * callback function. - * - *---------------------------------------------------------------------*/ -#if (FW_TYPE==_UCB_MGR_) -void SccbMgr_start_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb) -#else -#if defined(DOS) -void SccbMgr_start_sccb(USHORT pCurrCard, PSCCB p_Sccb) -#else -void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_Sccb) -#endif -#endif -{ -#if defined(DOS) - USHORT ioport; -#else - ULONG ioport; -#endif - UCHAR thisCard, lun; - PSCCB pSaveSccb; - CALL_BK_FN callback; - -#if (FW_TYPE==_UCB_MGR_) - PSCCB p_Sccb; -#endif - - mOS_Lock((PSCCBcard)pCurrCard); - thisCard = ((PSCCBcard) pCurrCard)->cardIndex; - ioport = ((PSCCBcard) pCurrCard)->ioPort; - -#if (FW_TYPE==_UCB_MGR_) - p_Sccb = (PSCCB)p_ucb->UCB_MgrPrivatePtr; -#endif - - if((p_Sccb->TargID > MAX_SCSI_TAR) || (p_Sccb->Lun > MAX_LUN)) - { - -#if (FW_TYPE==_UCB_MGR_) - p_ucb->UCB_hbastat = SCCB_COMPLETE; - p_ucb->UCB_status=SCCB_ERROR; - callback = (CALL_BK_FN)p_ucb->UCB_callback; - if (callback) - callback(p_ucb); -#endif - -#if (FW_TYPE==_SCCB_MGR_) - p_Sccb->HostStatus = SCCB_COMPLETE; - p_Sccb->SccbStatus = SCCB_ERROR; - callback = (CALL_BK_FN)p_Sccb->SccbCallback; - if (callback) - callback(p_Sccb); -#endif - - mOS_UnLock((PSCCBcard)pCurrCard); - return; - } - -#if (FW_TYPE==_SCCB_MGR_) - sinits(p_Sccb,thisCard); -#endif - - -#if (FW_TYPE==_UCB_MGR_) -#ifndef NO_IOCTLS - - if (p_ucb->UCB_opcode & OPC_IOCTL) - { - - switch (p_ucb->UCB_IOCTLCommand) - { - case READ_NVRAM: - ReadNVRam((PSCCBcard)pCurrCard,p_ucb); - p_ucb->UCB_status=UCB_SUCCESS; - callback = (CALL_BK_FN)p_ucb->UCB_callback; - if (callback) - callback(p_ucb); - mOS_UnLock((PSCCBcard)pCurrCard); - return; - - case WRITE_NVRAM: - WriteNVRam((PSCCBcard)pCurrCard,p_ucb); - p_ucb->UCB_status=UCB_SUCCESS; - callback = (CALL_BK_FN)p_ucb->UCB_callback; - if (callback) - callback(p_ucb); - mOS_UnLock((PSCCBcard)pCurrCard); - return; - - case SEND_SCSI_PASSTHRU: -#if (FW_TYPE != _SCCB_MGR_) - if( p_ucb->UCB_targid >= - ((PSCCBcard)pCurrCard)->cardInfo->ai_MaxTarg ) - { - p_ucb->UCB_status = UCB_ERROR; - p_ucb->UCB_hbastat = HASTAT_HW_ERROR; - callback = (CALL_BK_FN)p_ucb->UCB_callback; - if (callback) - callback(p_ucb); - mOS_UnLock((PSCCBcard)pCurrCard); - return; - } -#endif - break; - - case HARD_RESET: - p_ucb->UCB_status = UCB_INVALID; - callback = (CALL_BK_FN)p_ucb->UCB_callback; - if (callback) - callback(p_ucb); - mOS_UnLock((PSCCBcard)pCurrCard); - return; - case GET_DEVICE_SYNCRATE: - if( !GetDevSyncRate((PSCCBcard)pCurrCard,p_ucb) ) - { - p_ucb->UCB_status = UCB_SUCCESS; - } - else - { - p_ucb->UCB_status = UCB_ERROR; - p_ucb->UCB_hbastat = HASTAT_HW_ERROR; - } - callback = (CALL_BK_FN)p_ucb->UCB_callback; - if (callback) - callback(p_ucb); - mOS_UnLock((PSCCBcard)pCurrCard); - return; - case SET_DEVICE_SYNCRATE: - if( !SetDevSyncRate((PSCCBcard)pCurrCard,p_ucb) ) - { - p_ucb->UCB_status = UCB_SUCCESS; - } - else - { - p_ucb->UCB_status = UCB_ERROR; - p_ucb->UCB_hbastat = HASTAT_HW_ERROR; - } - callback = (CALL_BK_FN)p_ucb->UCB_callback; - if (callback) - callback(p_ucb); - mOS_UnLock((PSCCBcard)pCurrCard); - return; - case GET_WIDE_MODE: - if( !GetDevWideMode((PSCCBcard)pCurrCard,p_ucb) ) - { - p_ucb->UCB_status = UCB_SUCCESS; - } - else - { - p_ucb->UCB_status = UCB_ERROR; - p_ucb->UCB_hbastat = HASTAT_HW_ERROR; - } - callback = (CALL_BK_FN)p_ucb->UCB_callback; - if (callback) - callback(p_ucb); - mOS_UnLock((PSCCBcard)pCurrCard); - return; - case SET_WIDE_MODE: - if( !SetDevWideMode((PSCCBcard)pCurrCard,p_ucb) ) - { - p_ucb->UCB_status = UCB_SUCCESS; - } - else - { - p_ucb->UCB_status = UCB_ERROR; - p_ucb->UCB_hbastat = HASTAT_HW_ERROR; - } - callback = (CALL_BK_FN)p_ucb->UCB_callback; - if (callback) - callback(p_ucb); - mOS_UnLock((PSCCBcard)pCurrCard); - return; - default: - p_ucb->UCB_status=UCB_INVALID; - callback = (CALL_BK_FN)p_ucb->UCB_callback; - if (callback) - callback(p_ucb); - mOS_UnLock((PSCCBcard)pCurrCard); - return; - } - } -#endif /* NO_IOCTLS */ -#endif /* (FW_TYPE==_UCB_MGR_) */ - - - if (!((PSCCBcard) pCurrCard)->cmdCounter) - { - WR_HARPOON(ioport+hp_semaphore, (RD_HARPOON(ioport+hp_semaphore) - | SCCB_MGR_ACTIVE)); - - if (((PSCCBcard) pCurrCard)->globalFlags & F_GREEN_PC) - { - WR_HARPOON(ioport+hp_clkctrl_0, CLKCTRL_DEFAULT); - WR_HARPOON(ioport+hp_sys_ctrl, 0x00); - } - } - - ((PSCCBcard)pCurrCard)->cmdCounter++; - - if (RD_HARPOON(ioport+hp_semaphore) & BIOS_IN_USE) { - - WR_HARPOON(ioport+hp_semaphore, (RD_HARPOON(ioport+hp_semaphore) - | TICKLE_ME)); - if(p_Sccb->OperationCode == RESET_COMMAND) - { - pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB; - ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; - queueSelectFail(&BL_Card[thisCard], thisCard); - ((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb; - } - else - { - queueAddSccb(p_Sccb,thisCard); - } - } - - else if ((RD_HARPOON(ioport+hp_page_ctrl) & G_INT_DISABLE)) { - - if(p_Sccb->OperationCode == RESET_COMMAND) - { - pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB; - ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; - queueSelectFail(&BL_Card[thisCard], thisCard); - ((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb; - } - else - { - queueAddSccb(p_Sccb,thisCard); - } - } - - else { - - MDISABLE_INT(ioport); - - if((((PSCCBcard) pCurrCard)->globalFlags & F_CONLUN_IO) && - ((sccbMgrTbl[thisCard][p_Sccb->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) - lun = p_Sccb->Lun; - else - lun = 0; - if ((((PSCCBcard) pCurrCard)->currentSCCB == NULL) && - (sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0) && - (sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun] - == FALSE)) { - - ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; - mOS_UnLock((PSCCBcard)pCurrCard); -#if defined(DOS) - ssel((USHORT)p_Sccb->SccbIOPort,thisCard); -#else - ssel(p_Sccb->SccbIOPort,thisCard); -#endif - mOS_Lock((PSCCBcard)pCurrCard); - } - - else { - - if(p_Sccb->OperationCode == RESET_COMMAND) - { - pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB; - ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; - queueSelectFail(&BL_Card[thisCard], thisCard); - ((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb; - } - else - { - queueAddSccb(p_Sccb,thisCard); - } - } - - - MENABLE_INT(ioport); - } - - mOS_UnLock((PSCCBcard)pCurrCard); -} - - -/*--------------------------------------------------------------------- - * - * Function: SccbMgr_abort_sccb - * - * Description: Abort the command pointed to by p_Sccb. When the - * command is completed it will be returned via the - * callback function. - * - *---------------------------------------------------------------------*/ -#if (FW_TYPE==_UCB_MGR_) -s32bits SccbMgr_abort_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb) -#else -#if defined(DOS) -int SccbMgr_abort_sccb(USHORT pCurrCard, PSCCB p_Sccb) -#else -int SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_Sccb) -#endif -#endif - -{ -#if defined(DOS) - USHORT ioport; -#else - ULONG ioport; -#endif - - UCHAR thisCard; - CALL_BK_FN callback; - UCHAR TID; - PSCCB pSaveSCCB; - PSCCBMgr_tar_info currTar_Info; - - -#if (FW_TYPE==_UCB_MGR_) - PSCCB p_Sccb; - p_Sccb=(PSCCB)p_ucb->UCB_MgrPrivatePtr; -#endif - - ioport = ((PSCCBcard) pCurrCard)->ioPort; - - thisCard = ((PSCCBcard)pCurrCard)->cardIndex; - - mOS_Lock((PSCCBcard)pCurrCard); - - if (RD_HARPOON(ioport+hp_page_ctrl) & G_INT_DISABLE) - { - mOS_UnLock((PSCCBcard)pCurrCard); - } - - else - { - - if (queueFindSccb(p_Sccb,thisCard)) - { - - mOS_UnLock((PSCCBcard)pCurrCard); - - ((PSCCBcard)pCurrCard)->cmdCounter--; - - if (!((PSCCBcard)pCurrCard)->cmdCounter) - WR_HARPOON(ioport+hp_semaphore,(RD_HARPOON(ioport+hp_semaphore) - & (UCHAR)(~(SCCB_MGR_ACTIVE | TICKLE_ME)) )); - -#if (FW_TYPE==_SCCB_MGR_) - p_Sccb->SccbStatus = SCCB_ABORT; - callback = p_Sccb->SccbCallback; - callback(p_Sccb); -#else - p_ucb->UCB_status=SCCB_ABORT; - callback = (CALL_BK_FN)p_ucb->UCB_callback; - callback(p_ucb); -#endif - - return(0); - } - - else - { - mOS_UnLock((PSCCBcard)pCurrCard); - - if (((PSCCBcard)pCurrCard)->currentSCCB == p_Sccb) - { - p_Sccb->SccbStatus = SCCB_ABORT; - return(0); - - } - - else - { - - TID = p_Sccb->TargID; - - - if(p_Sccb->Sccb_tag) - { - MDISABLE_INT(ioport); - if (((PSCCBcard) pCurrCard)->discQ_Tbl[p_Sccb->Sccb_tag]==p_Sccb) - { - p_Sccb->SccbStatus = SCCB_ABORT; - p_Sccb->Sccb_scsistat = ABORT_ST; -#if (FW_TYPE==_UCB_MGR_) - p_ucb->UCB_status=SCCB_ABORT; -#endif - p_Sccb->Sccb_scsimsg = SMABORT_TAG; - - if(((PSCCBcard) pCurrCard)->currentSCCB == NULL) - { - ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; - ssel(ioport, thisCard); - } - else - { - pSaveSCCB = ((PSCCBcard) pCurrCard)->currentSCCB; - ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; - queueSelectFail((PSCCBcard) pCurrCard, thisCard); - ((PSCCBcard) pCurrCard)->currentSCCB = pSaveSCCB; - } - } - MENABLE_INT(ioport); - return(0); - } - else - { - currTar_Info = &sccbMgrTbl[thisCard][p_Sccb->TargID]; - - if(BL_Card[thisCard].discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_Sccb->Lun]] - == p_Sccb) - { - p_Sccb->SccbStatus = SCCB_ABORT; - return(0); - } - } - } - } - } - return(-1); -} - - -/*--------------------------------------------------------------------- - * - * Function: SccbMgr_my_int - * - * Description: Do a quick check to determine if there is a pending - * interrupt for this card and disable the IRQ Pin if so. - * - *---------------------------------------------------------------------*/ -#if (FW_TYPE==_UCB_MGR_) -u08bits SccbMgr_my_int(CARD_HANDLE pCurrCard) -#else -#if defined(DOS) -UCHAR SccbMgr_my_int(USHORT pCurrCard) -#else -UCHAR SccbMgr_my_int(ULONG pCurrCard) -#endif -#endif -{ -#if defined(DOS) - USHORT ioport; -#else - ULONG ioport; -#endif - - ioport = ((PSCCBcard)pCurrCard)->ioPort; - - if (RD_HARPOON(ioport+hp_int_status) & INT_ASSERTED) - { - -#if defined(DOS) - MDISABLE_INT(ioport); -#endif - - return(TRUE); - } - - else - - return(FALSE); -} - - - -/*--------------------------------------------------------------------- - * - * Function: SccbMgr_isr - * - * Description: This is our entry point when an interrupt is generated - * by the card and the upper level driver passes it on to - * us. - * - *---------------------------------------------------------------------*/ -#if (FW_TYPE==_UCB_MGR_) -s32bits SccbMgr_isr(CARD_HANDLE pCurrCard) -#else -#if defined(DOS) -int SccbMgr_isr(USHORT pCurrCard) -#else -int SccbMgr_isr(ULONG pCurrCard) -#endif -#endif -{ - PSCCB currSCCB; - UCHAR thisCard,result,bm_status, bm_int_st; - USHORT hp_int; - UCHAR i, target; -#if defined(DOS) - USHORT ioport; -#else - ULONG ioport; -#endif - - mOS_Lock((PSCCBcard)pCurrCard); - - thisCard = ((PSCCBcard)pCurrCard)->cardIndex; - ioport = ((PSCCBcard)pCurrCard)->ioPort; - - MDISABLE_INT(ioport); - -#if defined(BUGBUG) - WR_HARPOON(ioport+hp_user_defined_D, RD_HARPOON(ioport+hp_int_status)); -#endif - - if ((bm_int_st=RD_HARPOON(ioport+hp_int_status)) & EXT_STATUS_ON) - bm_status = RD_HARPOON(ioport+hp_ext_status) & (UCHAR)BAD_EXT_STATUS; - else - bm_status = 0; - - WR_HARPOON(ioport+hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT)); - - mOS_UnLock((PSCCBcard)pCurrCard); - - while ((hp_int = RDW_HARPOON((ioport+hp_intstat)) & default_intena) | - bm_status) - { - - currSCCB = ((PSCCBcard)pCurrCard)->currentSCCB; - -#if defined(BUGBUG) - Debug_Load(thisCard,(UCHAR) 0XFF); - Debug_Load(thisCard,bm_int_st); - - Debug_Load(thisCard,hp_int_0); - Debug_Load(thisCard,hp_int_1); -#endif - - - if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) { - result = SccbMgr_bad_isr(ioport,thisCard,((PSCCBcard)pCurrCard),hp_int); - WRW_HARPOON((ioport+hp_intstat), (FIFO | TIMEOUT | RESET | SCAM_SEL)); - bm_status = 0; - - if (result) { - - mOS_Lock((PSCCBcard)pCurrCard); - MENABLE_INT(ioport); - mOS_UnLock((PSCCBcard)pCurrCard); - return(result); - } - } - - - else if (hp_int & ICMD_COMP) { - - if ( !(hp_int & BUS_FREE) ) { - /* Wait for the BusFree before starting a new command. We - must also check for being reselected since the BusFree - may not show up if another device reselects us in 1.5us or - less. SRR Wednesday, 3/8/1995. - */ - while (!(RDW_HARPOON((ioport+hp_intstat)) & (BUS_FREE | RSEL))) ; - } - - if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) - - phaseChkFifo(ioport, thisCard); - -/* WRW_HARPOON((ioport+hp_intstat), - (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0)); - */ - - WRW_HARPOON((ioport+hp_intstat), CLR_ALL_INT_1); - - autoCmdCmplt(ioport,thisCard); - - } - - - else if (hp_int & ITAR_DISC) - { - - if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) { - - phaseChkFifo(ioport, thisCard); - - } - - if (RD_HARPOON(ioport+hp_gp_reg_1) == SMSAVE_DATA_PTR) { - - WR_HARPOON(ioport+hp_gp_reg_1, 0x00); - currSCCB->Sccb_XferState |= F_NO_DATA_YET; - - currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC; - } - - currSCCB->Sccb_scsistat = DISCONNECT_ST; - queueDisconnect(currSCCB,thisCard); - - /* Wait for the BusFree before starting a new command. We - must also check for being reselected since the BusFree - may not show up if another device reselects us in 1.5us or - less. SRR Wednesday, 3/8/1995. - */ - while (!(RDW_HARPOON((ioport+hp_intstat)) & (BUS_FREE | RSEL)) && - !((RDW_HARPOON((ioport+hp_intstat)) & PHASE) && - RD_HARPOON((ioport+hp_scsisig)) == - (SCSI_BSY | SCSI_REQ | SCSI_CD | SCSI_MSG | SCSI_IOBIT))) ; - - /* - The additional loop exit condition above detects a timing problem - with the revision D/E harpoon chips. The caller should reset the - host adapter to recover when 0xFE is returned. - */ - if (!(RDW_HARPOON((ioport+hp_intstat)) & (BUS_FREE | RSEL))) - { - mOS_Lock((PSCCBcard)pCurrCard); - MENABLE_INT(ioport); - mOS_UnLock((PSCCBcard)pCurrCard); - return 0xFE; - } - - WRW_HARPOON((ioport+hp_intstat), (BUS_FREE | ITAR_DISC)); - - - ((PSCCBcard)pCurrCard)->globalFlags |= F_NEW_SCCB_CMD; - - } - - - else if (hp_int & RSEL) { - - WRW_HARPOON((ioport+hp_intstat), (PROG_HLT | RSEL | PHASE | BUS_FREE)); - - if (RDW_HARPOON((ioport+hp_intstat)) & ITAR_DISC) - { - if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) - { - phaseChkFifo(ioport, thisCard); - } - - if (RD_HARPOON(ioport+hp_gp_reg_1) == SMSAVE_DATA_PTR) - { - WR_HARPOON(ioport+hp_gp_reg_1, 0x00); - currSCCB->Sccb_XferState |= F_NO_DATA_YET; - currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC; - } - - WRW_HARPOON((ioport+hp_intstat), (BUS_FREE | ITAR_DISC)); - currSCCB->Sccb_scsistat = DISCONNECT_ST; - queueDisconnect(currSCCB,thisCard); - } - - sres(ioport,thisCard,((PSCCBcard)pCurrCard)); - phaseDecode(ioport,thisCard); - - } - - - else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE))) - { - - WRW_HARPOON((ioport+hp_intstat), (IDO_STRT | XFER_CNT_0)); - phaseDecode(ioport,thisCard); - - } - - - else if ( (hp_int & IUNKWN) || (hp_int & PROG_HLT) ) - { - WRW_HARPOON((ioport+hp_intstat), (PHASE | IUNKWN | PROG_HLT)); - if ((RD_HARPOON(ioport+hp_prgmcnt_0) & (UCHAR)0x3f)< (UCHAR)SELCHK) - { - phaseDecode(ioport,thisCard); - } - else - { - /* Harpoon problem some SCSI target device respond to selection - with short BUSY pulse (<400ns) this will make the Harpoon is not able - to latch the correct Target ID into reg. x53. - The work around require to correct this reg. But when write to this - reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we - need to read this reg first then restore it later. After update to 0x53 */ - - i = (UCHAR)(RD_HARPOON(ioport+hp_fifowrite)); - target = (UCHAR)(RD_HARPOON(ioport+hp_gp_reg_3)); - WR_HARPOON(ioport+hp_xfer_pad, (UCHAR) ID_UNLOCK); - WR_HARPOON(ioport+hp_select_id, (UCHAR)(target | target<<4)); - WR_HARPOON(ioport+hp_xfer_pad, (UCHAR) 0x00); - WR_HARPOON(ioport+hp_fifowrite, i); - WR_HARPOON(ioport+hp_autostart_3, (AUTO_IMMED+TAG_STRT)); - } - } - - else if (hp_int & XFER_CNT_0) { - - WRW_HARPOON((ioport+hp_intstat), XFER_CNT_0); - - schkdd(ioport,thisCard); - - } - - - else if (hp_int & BUS_FREE) { - - WRW_HARPOON((ioport+hp_intstat), BUS_FREE); - - if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) { - - hostDataXferAbort(ioport,thisCard,currSCCB); - } - - phaseBusFree(ioport,thisCard); - } - - - else if (hp_int & ITICKLE) { - - WRW_HARPOON((ioport+hp_intstat), ITICKLE); - ((PSCCBcard)pCurrCard)->globalFlags |= F_NEW_SCCB_CMD; - } - - - - if (((PSCCBcard)pCurrCard)->globalFlags & F_NEW_SCCB_CMD) { - - - ((PSCCBcard)pCurrCard)->globalFlags &= ~F_NEW_SCCB_CMD; - - - if (((PSCCBcard)pCurrCard)->currentSCCB == NULL) { - - queueSearchSelect(((PSCCBcard)pCurrCard),thisCard); - } - - if (((PSCCBcard)pCurrCard)->currentSCCB != NULL) { - ((PSCCBcard)pCurrCard)->globalFlags &= ~F_NEW_SCCB_CMD; - ssel(ioport,thisCard); - } - - break; - - } - - } /*end while */ - - mOS_Lock((PSCCBcard)pCurrCard); - MENABLE_INT(ioport); - mOS_UnLock((PSCCBcard)pCurrCard); - - return(0); -} - -/*--------------------------------------------------------------------- - * - * Function: Sccb_bad_isr - * - * Description: Some type of interrupt has occurred which is slightly - * out of the ordinary. We will now decode it fully, in - * this routine. This is broken up in an attempt to save - * processing time. - * - *---------------------------------------------------------------------*/ -#if defined(DOS) -UCHAR SccbMgr_bad_isr(USHORT p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int) -#else -UCHAR SccbMgr_bad_isr(ULONG p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int) -#endif -{ -#if defined(HARP_REVX) - ULONG timer; -#endif -UCHAR temp, ScamFlg; -PSCCBMgr_tar_info currTar_Info; -PNVRamInfo pCurrNvRam; - - - if (RD_HARPOON(p_port+hp_ext_status) & - (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN) ) - { - - if (pCurrCard->globalFlags & F_HOST_XFER_ACT) - { - - hostDataXferAbort(p_port,p_card, pCurrCard->currentSCCB); - } - - if (RD_HARPOON(p_port+hp_pci_stat_cfg) & REC_MASTER_ABORT) - - { - WR_HARPOON(p_port+hp_pci_stat_cfg, - (RD_HARPOON(p_port+hp_pci_stat_cfg) & ~REC_MASTER_ABORT)); - - WR_HARPOON(p_port+hp_host_blk_cnt, 0x00); - - } - - if (pCurrCard->currentSCCB != NULL) - { - - if (!pCurrCard->currentSCCB->HostStatus) - pCurrCard->currentSCCB->HostStatus = SCCB_BM_ERR; - - sxfrp(p_port,p_card); - - temp = (UCHAR)(RD_HARPOON(p_port+hp_ee_ctrl) & - (EXT_ARB_ACK | SCSI_TERM_ENA_H)); - WR_HARPOON(p_port+hp_ee_ctrl, ((UCHAR)temp | SEE_MS | SEE_CS)); - WR_HARPOON(p_port+hp_ee_ctrl, temp); - - if (!(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET))) - { - phaseDecode(p_port,p_card); - } - } - } - - - else if (p_int & RESET) - { - - WR_HARPOON(p_port+hp_clkctrl_0, CLKCTRL_DEFAULT); - WR_HARPOON(p_port+hp_sys_ctrl, 0x00); - if (pCurrCard->currentSCCB != NULL) { - - if (pCurrCard->globalFlags & F_HOST_XFER_ACT) - - hostDataXferAbort(p_port,p_card, pCurrCard->currentSCCB); - } - - - DISABLE_AUTO(p_port); - - sresb(p_port,p_card); - - while(RD_HARPOON(p_port+hp_scsictrl_0) & SCSI_RST) {} - - pCurrNvRam = pCurrCard->pNvRamInfo; - if(pCurrNvRam){ - ScamFlg = pCurrNvRam->niScamConf; - } - else{ - ScamFlg = (UCHAR) utilEERead(p_port, SCAM_CONFIG/2); - } - - XbowInit(p_port, ScamFlg); - - scini(p_card, pCurrCard->ourId, 0); - - return(0xFF); - } - - - else if (p_int & FIFO) { - - WRW_HARPOON((p_port+hp_intstat), FIFO); - -#if defined(HARP_REVX) - - for (timer=0x00FFFFFFL; timer != 0x00000000L; timer--) { - - if (RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY) - break; - - if (RDW_HARPOON((p_port+hp_intstat)) & BUS_FREE) - break; - } - - - if ( (RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY) && - (RD_HARPOON(p_port+hp_fiforead) != - RD_HARPOON(p_port+hp_fifowrite)) && - (RD_HARPOON(p_port+hp_xfercnt_0)) - ) - - WR_HARPOON((p_port+hp_xferstat), 0x01); - -/* else - */ -/* sxfrp(p_port,p_card); - */ -#else - if (pCurrCard->currentSCCB != NULL) - sxfrp(p_port,p_card); -#endif - } - - else if (p_int & TIMEOUT) - { - - DISABLE_AUTO(p_port); - - WRW_HARPOON((p_port+hp_intstat), - (PROG_HLT | TIMEOUT | SEL |BUS_FREE | PHASE | IUNKWN)); - - pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT; - - - currTar_Info = &sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID]; - if((pCurrCard->globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) - currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] = FALSE; - else - currTar_Info->TarLUNBusy[0] = FALSE; - - - if (currTar_Info->TarEEValue & EE_SYNC_MASK) - { - currTar_Info->TarSyncCtrl = 0; - currTar_Info->TarStatus &= ~TAR_SYNC_MASK; - } - - if (currTar_Info->TarEEValue & EE_WIDE_SCSI) - { - currTar_Info->TarStatus &= ~TAR_WIDE_MASK; - } - - sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,currTar_Info); - - queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card); - - } - -#if defined(SCAM_LEV_2) - - else if (p_int & SCAM_SEL) - { - - scarb(p_port,LEVEL2_TAR); - scsel(p_port); - scasid(p_card, p_port); - - scbusf(p_port); - - WRW_HARPOON((p_port+hp_intstat), SCAM_SEL); - } -#endif - - return(0x00); -} - - -/*--------------------------------------------------------------------- - * - * Function: SccbMgr_scsi_reset - * - * Description: A SCSI bus reset will be generated and all outstanding - * Sccbs will be returned via the callback. - * - *---------------------------------------------------------------------*/ -#if (FW_TYPE==_UCB_MGR_) -void SccbMgr_scsi_reset(CARD_HANDLE pCurrCard) -#else -#if defined(DOS) -void SccbMgr_scsi_reset(USHORT pCurrCard) -#else -void SccbMgr_scsi_reset(ULONG pCurrCard) -#endif -#endif -{ - UCHAR thisCard; - - thisCard = ((PSCCBcard)pCurrCard)->cardIndex; - - mOS_Lock((PSCCBcard)pCurrCard); - - if (((PSCCBcard) pCurrCard)->globalFlags & F_GREEN_PC) - { - WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_clkctrl_0, CLKCTRL_DEFAULT); - WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_sys_ctrl, 0x00); - } - - sresb(((PSCCBcard)pCurrCard)->ioPort,thisCard); - - if (RD_HARPOON(((PSCCBcard)pCurrCard)->ioPort+hp_ext_status) & BM_CMD_BUSY) - { - WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_page_ctrl, - (RD_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_page_ctrl) - & ~SCATTER_EN)); - - WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_sg_addr,0x00); - - ((PSCCBcard) pCurrCard)->globalFlags &= ~F_HOST_XFER_ACT; - busMstrTimeOut(((PSCCBcard) pCurrCard)->ioPort); - - WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_int_mask, - (INT_CMD_COMPL | SCSI_INTERRUPT)); - } - -/* - if (utilEERead(((PSCCBcard)pCurrCard)->ioPort, (SCAM_CONFIG/2)) - & SCAM_ENABLED) -*/ - scini(thisCard, ((PSCCBcard)pCurrCard)->ourId, 0); - -#if (FW_TYPE==_UCB_MGR_) - ((PSCCBcard)pCurrCard)->cardInfo->ai_AEN_routine(0x01,pCurrCard,0,0,0,0); -#endif - - mOS_UnLock((PSCCBcard)pCurrCard); -} - - -/*--------------------------------------------------------------------- - * - * Function: SccbMgr_timer_expired - * - * Description: This function allow me to kill my own job that has not - * yet completed, and has cause a timeout to occur. This - * timeout has caused the upper level driver to call this - * function. - * - *---------------------------------------------------------------------*/ - -#if (FW_TYPE==_UCB_MGR_) -void SccbMgr_timer_expired(CARD_HANDLE pCurrCard) -#else -#if defined(DOS) -void SccbMgr_timer_expired(USHORT pCurrCard) -#else -void SccbMgr_timer_expired(ULONG pCurrCard) -#endif -#endif -{ -} - -#if defined(DOS) -/*--------------------------------------------------------------------- - * - * Function: SccbMgr_status - * - * Description: This function returns the number of outstanding SCCB's. - * This is specific to the DOS enviroment, which needs this - * to help them keep protected and real mode commands staight. - * - *---------------------------------------------------------------------*/ - -USHORT SccbMgr_status(USHORT pCurrCard) -{ - return(BL_Card[pCurrCard].cmdCounter); -} -#endif - -/*--------------------------------------------------------------------- - * - * Function: SccbMgrTableInit - * - * Description: Initialize all Sccb manager data structures. - * - *---------------------------------------------------------------------*/ - -void SccbMgrTableInitAll() -{ - UCHAR thisCard; - - for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) - { - SccbMgrTableInitCard(&BL_Card[thisCard],thisCard); - - BL_Card[thisCard].ioPort = 0x00; - BL_Card[thisCard].cardInfo = NULL; - BL_Card[thisCard].cardIndex = 0xFF; - BL_Card[thisCard].ourId = 0x00; - BL_Card[thisCard].pNvRamInfo = NULL; - } -} - - -/*--------------------------------------------------------------------- - * - * Function: SccbMgrTableInit - * - * Description: Initialize all Sccb manager data structures. - * - *---------------------------------------------------------------------*/ - -void SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card) -{ - UCHAR scsiID, qtag; - - for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) - { - BL_Card[p_card].discQ_Tbl[qtag] = NULL; - } - - for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) - { - sccbMgrTbl[p_card][scsiID].TarStatus = 0; - sccbMgrTbl[p_card][scsiID].TarEEValue = 0; - SccbMgrTableInitTarget(p_card, scsiID); - } - - pCurrCard->scanIndex = 0x00; - pCurrCard->currentSCCB = NULL; - pCurrCard->globalFlags = 0x00; - pCurrCard->cmdCounter = 0x00; - pCurrCard->tagQ_Lst = 0x01; - pCurrCard->discQCount = 0; - - -} - - -/*--------------------------------------------------------------------- - * - * Function: SccbMgrTableInit - * - * Description: Initialize all Sccb manager data structures. - * - *---------------------------------------------------------------------*/ - -void SccbMgrTableInitTarget(UCHAR p_card, UCHAR target) -{ - - UCHAR lun, qtag; - PSCCBMgr_tar_info currTar_Info; - - currTar_Info = &sccbMgrTbl[p_card][target]; - - currTar_Info->TarSelQ_Cnt = 0; - currTar_Info->TarSyncCtrl = 0; - - currTar_Info->TarSelQ_Head = NULL; - currTar_Info->TarSelQ_Tail = NULL; - currTar_Info->TarTagQ_Cnt = 0; - currTar_Info->TarLUN_CA = FALSE; - - - for (lun = 0; lun < MAX_LUN; lun++) - { - currTar_Info->TarLUNBusy[lun] = FALSE; - currTar_Info->LunDiscQ_Idx[lun] = 0; - } - - for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) - { - if(BL_Card[p_card].discQ_Tbl[qtag] != NULL) - { - if(BL_Card[p_card].discQ_Tbl[qtag]->TargID == target) - { - BL_Card[p_card].discQ_Tbl[qtag] = NULL; - BL_Card[p_card].discQCount--; - } - } - } -} - -#if defined(BUGBUG) - -/***************************************************************** - * Save the current byte in the debug array - *****************************************************************/ - - -void Debug_Load(UCHAR p_card, UCHAR p_bug_data) -{ - debug_int[p_card][debug_index[p_card]] = p_bug_data; - debug_index[p_card]++; - - if (debug_index[p_card] == debug_size) - - debug_index[p_card] = 0; -} - -#endif -#ident "$Id: sccb_dat.c 1.10 1997/02/22 03:16:02 awin Exp $" -/*---------------------------------------------------------------------- - * - * - * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved - * - * This file is available under both the GNU General Public License - * and a BSD-style copyright; see LICENSE.FlashPoint for details. - * - * $Workfile: sccb_dat.c $ - * - * Description: Functions relating to handling of the SCCB interface - * between the device driver and the HARPOON. - * - * $Date: 1997/02/22 03:16:02 $ - * - * $Revision: 1.10 $ - * - *----------------------------------------------------------------------*/ - -/*#include */ - -#if (FW_TYPE==_UCB_MGR_) - /*#include */ -#endif - -/*#include */ -/*#include */ -/*#include */ -/*#include */ - -/* -** IMPORTANT NOTE!!! -** -** You MUST preassign all data to a valid value or zero. This is -** required due to the MS compiler bug under OS/2 and Solaris Real-Mode -** driver environment. -*/ - - -SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] = { { { 0 } } }; -SCCBCARD BL_Card[MAX_CARDS] = { { 0 } }; -SCCBSCAM_INFO scamInfo[MAX_SCSI_TAR] = { { { 0 } } }; -NVRAMINFO nvRamInfo[MAX_MB_CARDS] = { { 0 } }; - - -#if defined(OS2) -void (far *s_PhaseTbl[8]) (ULONG, UCHAR) = { 0 }; -UCHAR temp_id_string[ID_STRING_LENGTH] = { 0 }; -#elif defined(SOLARIS_REAL_MODE) || defined(__STDC__) -void (*s_PhaseTbl[8]) (ULONG, UCHAR) = { 0 }; -#else -void (*s_PhaseTbl[8]) (); -#endif - -#if defined(DOS) -UCHAR first_time = 0; -#endif - -UCHAR mbCards = 0; -UCHAR scamHAString[] = {0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C', \ - ' ', 'B', 'T', '-', '9', '3', '0', \ - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, \ - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; - -USHORT default_intena = 0; - -#if defined(BUGBUG) -UCHAR debug_int[MAX_CARDS][debug_size] = { 0 }; -UCHAR debug_index[MAX_CARDS] = { 0 }; -UCHAR reserved_1[3] = { 0 }; -#endif -#ident "$Id: scsi.c 1.23 1997/07/09 21:42:54 mohan Exp $" -/*---------------------------------------------------------------------- - * - * - * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved - * - * This file is available under both the GNU General Public License - * and a BSD-style copyright; see LICENSE.FlashPoint for details. - * - * $Workfile: scsi.c $ - * - * Description: Functions for handling SCSI bus functions such as - * selection/reselection, sync negotiation, message-in - * decoding. - * - * $Date: 1997/07/09 21:42:54 $ - * - * $Revision: 1.23 $ - * - *----------------------------------------------------------------------*/ - -/*#include */ - -#if (FW_TYPE==_UCB_MGR_) - /*#include */ -#endif - -/*#include */ -/*#include */ -/*#include */ -/*#include */ -/*#include */ -/*#include */ - - -/* -extern SCCBCARD BL_Card[MAX_CARDS]; -extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR]; -#if defined(BUGBUG) -void Debug_Load(UCHAR p_card, UCHAR p_bug_data); -#endif -*/ - -/*--------------------------------------------------------------------- - * - * Function: sfetm - * - * Description: Read in a message byte from the SCSI bus, and check - * for a parity error. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -UCHAR sfm(USHORT port, PSCCB pCurrSCCB) -#else -UCHAR sfm(ULONG port, PSCCB pCurrSCCB) -#endif -{ - UCHAR message; - USHORT TimeOutLoop; - - TimeOutLoop = 0; - while( (!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) && - (TimeOutLoop++ < 20000) ){} - - - WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); - - message = RD_HARPOON(port+hp_scsidata_0); - - WR_HARPOON(port+hp_scsisig, SCSI_ACK + S_MSGI_PH); - - - if (TimeOutLoop > 20000) - message = 0x00; /* force message byte = 0 if Time Out on Req */ - - if ((RDW_HARPOON((port+hp_intstat)) & PARITY) && - (RD_HARPOON(port+hp_addstat) & SCSI_PAR_ERR)) - { - WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); - WR_HARPOON(port+hp_xferstat, 0); - WR_HARPOON(port+hp_fiforead, 0); - WR_HARPOON(port+hp_fifowrite, 0); - if (pCurrSCCB != NULL) - { - pCurrSCCB->Sccb_scsimsg = SMPARITY; - } - message = 0x00; - do - { - ACCEPT_MSG_ATN(port); - TimeOutLoop = 0; - while( (!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) && - (TimeOutLoop++ < 20000) ){} - if (TimeOutLoop > 20000) - { - WRW_HARPOON((port+hp_intstat), PARITY); - return(message); - } - if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) != S_MSGI_PH) - { - WRW_HARPOON((port+hp_intstat), PARITY); - return(message); - } - WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); - - RD_HARPOON(port+hp_scsidata_0); - - WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); - - }while(1); - - } - WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); - WR_HARPOON(port+hp_xferstat, 0); - WR_HARPOON(port+hp_fiforead, 0); - WR_HARPOON(port+hp_fifowrite, 0); - return(message); -} - - -/*--------------------------------------------------------------------- - * - * Function: ssel - * - * Description: Load up automation and select target device. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void ssel(USHORT port, UCHAR p_card) -#else -void ssel(ULONG port, UCHAR p_card) -#endif -{ - -#if defined(DOS) - UCHAR auto_loaded, i, target, *theCCB; -#elif defined(OS2) - UCHAR auto_loaded, i, target; - UCHAR far *theCCB; -#else - UCHAR auto_loaded, i, target, *theCCB; -#endif - -#if defined(DOS) - USHORT cdb_reg; -#else - ULONG cdb_reg; -#endif - PSCCBcard CurrCard; - PSCCB currSCCB; - PSCCBMgr_tar_info currTar_Info; - UCHAR lastTag, lun; - - CurrCard = &BL_Card[p_card]; - currSCCB = CurrCard->currentSCCB; - target = currSCCB->TargID; - currTar_Info = &sccbMgrTbl[p_card][target]; - lastTag = CurrCard->tagQ_Lst; - - ARAM_ACCESS(port); - - - if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT) - currSCCB->ControlByte &= ~F_USE_CMD_Q; - - if(((CurrCard->globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - - lun = currSCCB->Lun; - else - lun = 0; - - -#if defined(DOS) - currTar_Info->TarLUNBusy[lun] = TRUE; - -#else - - if (CurrCard->globalFlags & F_TAG_STARTED) - { - if (!(currSCCB->ControlByte & F_USE_CMD_Q)) - { - if ((currTar_Info->TarLUN_CA == FALSE) - && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) - == TAG_Q_TRYING)) - { - - if (currTar_Info->TarTagQ_Cnt !=0) - { - currTar_Info->TarLUNBusy[lun] = TRUE; - queueSelectFail(CurrCard,p_card); - SGRAM_ACCESS(port); - return; - } - - else { - currTar_Info->TarLUNBusy[lun] = TRUE; - } - - } /*End non-tagged */ - - else { - currTar_Info->TarLUNBusy[lun] = TRUE; - } - - } /*!Use cmd Q Tagged */ - - else { - if (currTar_Info->TarLUN_CA == TRUE) - { - queueSelectFail(CurrCard,p_card); - SGRAM_ACCESS(port); - return; - } - - currTar_Info->TarLUNBusy[lun] = TRUE; - - } /*else use cmd Q tagged */ - - } /*if glob tagged started */ - - else { - currTar_Info->TarLUNBusy[lun] = TRUE; - } - -#endif /* DOS */ - - - - if((((CurrCard->globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) - || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) - { - if(CurrCard->discQCount >= QUEUE_DEPTH) - { - currTar_Info->TarLUNBusy[lun] = TRUE; - queueSelectFail(CurrCard,p_card); - SGRAM_ACCESS(port); - return; - } - for (i = 1; i < QUEUE_DEPTH; i++) - { - if (++lastTag >= QUEUE_DEPTH) lastTag = 1; - if (CurrCard->discQ_Tbl[lastTag] == NULL) - { - CurrCard->tagQ_Lst = lastTag; - currTar_Info->LunDiscQ_Idx[lun] = lastTag; - CurrCard->discQ_Tbl[lastTag] = currSCCB; - CurrCard->discQCount++; - break; - } - } - if(i == QUEUE_DEPTH) - { - currTar_Info->TarLUNBusy[lun] = TRUE; - queueSelectFail(CurrCard,p_card); - SGRAM_ACCESS(port); - return; - } - } - - - - auto_loaded = FALSE; - - WR_HARPOON(port+hp_select_id, target); - WR_HARPOON(port+hp_gp_reg_3, target); /* Use by new automation logic */ - - if (currSCCB->OperationCode == RESET_COMMAND) { - WRW_HARPOON((port+ID_MSG_STRT), (MPM_OP+AMSG_OUT+ - (currSCCB->Sccb_idmsg & ~DISC_PRIV))); - - WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+NP); - - currSCCB->Sccb_scsimsg = SMDEV_RESET; - - WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); - auto_loaded = TRUE; - currSCCB->Sccb_scsistat = SELECT_BDR_ST; - - if (currTar_Info->TarEEValue & EE_SYNC_MASK) - { - currTar_Info->TarSyncCtrl = 0; - currTar_Info->TarStatus &= ~TAR_SYNC_MASK; - } - -#if defined(WIDE_SCSI) - - if (currTar_Info->TarEEValue & EE_WIDE_SCSI) - { - currTar_Info->TarStatus &= ~TAR_WIDE_MASK; - } -#endif - - sssyncv(port, target, NARROW_SCSI,currTar_Info); - SccbMgrTableInitTarget(p_card, target); - - } - - else if(currSCCB->Sccb_scsistat == ABORT_ST) - { - WRW_HARPOON((port+ID_MSG_STRT), (MPM_OP+AMSG_OUT+ - (currSCCB->Sccb_idmsg & ~DISC_PRIV))); - - WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+CMDPZ); - - WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+ - (((UCHAR)(currSCCB->ControlByte & TAG_TYPE_MASK) - >> 6) | (UCHAR)0x20))); - WRW_HARPOON((port+SYNC_MSGS+2), - (MPM_OP+AMSG_OUT+currSCCB->Sccb_tag)); - WRW_HARPOON((port+SYNC_MSGS+4), (BRH_OP+ALWAYS+NP )); - - WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); - auto_loaded = TRUE; - - } - -#if defined(WIDE_SCSI) - - - else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) { - auto_loaded = siwidn(port,p_card); - currSCCB->Sccb_scsistat = SELECT_WN_ST; - } - -#endif - - - else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) - == SYNC_SUPPORTED)) { - auto_loaded = sisyncn(port,p_card, FALSE); - currSCCB->Sccb_scsistat = SELECT_SN_ST; - } - - - if (!auto_loaded) - { - -#if !defined(DOS) - if (currSCCB->ControlByte & F_USE_CMD_Q) - { - - CurrCard->globalFlags |= F_TAG_STARTED; - - if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) - == TAG_Q_REJECT) - { - currSCCB->ControlByte &= ~F_USE_CMD_Q; - - /* Fix up the start instruction with a jump to - Non-Tag-CMD handling */ - WRW_HARPOON((port+ID_MSG_STRT),BRH_OP+ALWAYS+NTCMD); - - WRW_HARPOON((port+NON_TAG_ID_MSG), - (MPM_OP+AMSG_OUT+currSCCB->Sccb_idmsg)); - - WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); - - /* Setup our STATE so we know what happend when - the wheels fall off. */ - currSCCB->Sccb_scsistat = SELECT_ST; - - currTar_Info->TarLUNBusy[lun] = TRUE; - } - - else - { - WRW_HARPOON((port+ID_MSG_STRT), (MPM_OP+AMSG_OUT+currSCCB->Sccb_idmsg)); - - WRW_HARPOON((port+ID_MSG_STRT+2), (MPM_OP+AMSG_OUT+ - (((UCHAR)(currSCCB->ControlByte & TAG_TYPE_MASK) - >> 6) | (UCHAR)0x20))); - - for (i = 1; i < QUEUE_DEPTH; i++) - { - if (++lastTag >= QUEUE_DEPTH) lastTag = 1; - if (CurrCard->discQ_Tbl[lastTag] == NULL) - { - WRW_HARPOON((port+ID_MSG_STRT+6), - (MPM_OP+AMSG_OUT+lastTag)); - CurrCard->tagQ_Lst = lastTag; - currSCCB->Sccb_tag = lastTag; - CurrCard->discQ_Tbl[lastTag] = currSCCB; - CurrCard->discQCount++; - break; - } - } - - - if ( i == QUEUE_DEPTH ) - { - currTar_Info->TarLUNBusy[lun] = TRUE; - queueSelectFail(CurrCard,p_card); - SGRAM_ACCESS(port); - return; - } - - currSCCB->Sccb_scsistat = SELECT_Q_ST; - - WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); - } - } - - else - { -#endif /* !DOS */ - - WRW_HARPOON((port+ID_MSG_STRT),BRH_OP+ALWAYS+NTCMD); - - WRW_HARPOON((port+NON_TAG_ID_MSG), - (MPM_OP+AMSG_OUT+currSCCB->Sccb_idmsg)); - - currSCCB->Sccb_scsistat = SELECT_ST; - - WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); -#if !defined(DOS) - } -#endif - - -#if defined(OS2) - theCCB = (UCHAR far *)&currSCCB->Cdb[0]; -#else - theCCB = (UCHAR *)&currSCCB->Cdb[0]; -#endif - - cdb_reg = port + CMD_STRT; - - for (i=0; i < currSCCB->CdbLength; i++) - { - WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB)); - cdb_reg +=2; - theCCB++; - } - - if (currSCCB->CdbLength != TWELVE_BYTE_CMD) - WRW_HARPOON(cdb_reg, (BRH_OP+ALWAYS+ NP)); - - } /* auto_loaded */ - -#if defined(WIDE_SCSI) - WRW_HARPOON((port+hp_fiforead), (USHORT) 0x00); - WR_HARPOON(port+hp_xferstat, 0x00); -#endif - - WRW_HARPOON((port+hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE)); - - WR_HARPOON(port+hp_portctrl_0,(SCSI_PORT)); - - - if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) - { - WR_HARPOON(port+hp_scsictrl_0, (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL)); - } - else - { - -/* auto_loaded = (RD_HARPOON(port+hp_autostart_3) & (UCHAR)0x1F); - auto_loaded |= AUTO_IMMED; */ - auto_loaded = AUTO_IMMED; - - DISABLE_AUTO(port); - - WR_HARPOON(port+hp_autostart_3, auto_loaded); - } - - SGRAM_ACCESS(port); -} - - -/*--------------------------------------------------------------------- - * - * Function: sres - * - * Description: Hookup the correct CCB and handle the incoming messages. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void sres(USHORT port, UCHAR p_card, PSCCBcard pCurrCard) -#else -void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard) -#endif -{ - -#if defined(V302) -#ifdef DOS - UCHAR our_target,message, msgRetryCount; - extern UCHAR lun, tag; -#else - UCHAR our_target,message,lun,tag, msgRetryCount; -#endif - -#else /* V302 */ - UCHAR our_target, message, lun = 0, tag, msgRetryCount; -#endif /* V302 */ - - - PSCCBMgr_tar_info currTar_Info; - PSCCB currSCCB; - - - - - if(pCurrCard->currentSCCB != NULL) - { - currTar_Info = &sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID]; - DISABLE_AUTO(port); - - - WR_HARPOON((port+hp_scsictrl_0),(ENA_RESEL | ENA_SCAM_SEL)); - - - currSCCB = pCurrCard->currentSCCB; - if(currSCCB->Sccb_scsistat == SELECT_WN_ST) - { - currTar_Info->TarStatus &= ~TAR_WIDE_MASK; - currSCCB->Sccb_scsistat = BUS_FREE_ST; - } - if(currSCCB->Sccb_scsistat == SELECT_SN_ST) - { - currTar_Info->TarStatus &= ~TAR_SYNC_MASK; - currSCCB->Sccb_scsistat = BUS_FREE_ST; - } - if(((pCurrCard->globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { - currTar_Info->TarLUNBusy[currSCCB->Lun] = FALSE; - if(currSCCB->Sccb_scsistat != ABORT_ST) - { - pCurrCard->discQCount--; - pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[currSCCB->Lun]] - = NULL; - } - } - else - { - currTar_Info->TarLUNBusy[0] = FALSE; - if(currSCCB->Sccb_tag) - { - if(currSCCB->Sccb_scsistat != ABORT_ST) - { - pCurrCard->discQCount--; - pCurrCard->discQ_Tbl[currSCCB->Sccb_tag] = NULL; - } - }else - { - if(currSCCB->Sccb_scsistat != ABORT_ST) - { - pCurrCard->discQCount--; - pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = NULL; - } - } - } - - queueSelectFail(&BL_Card[p_card],p_card); - } - -#if defined(WIDE_SCSI) - WRW_HARPOON((port+hp_fiforead), (USHORT) 0x00); -#endif - - - our_target = (UCHAR)(RD_HARPOON(port+hp_select_id) >> 4); - currTar_Info = &sccbMgrTbl[p_card][our_target]; - - - msgRetryCount = 0; - do - { - -#if defined(V302) - - message = GetTarLun(port, p_card, our_target, pCurrCard, &tag, &lun); - -#else /* V302 */ - - currTar_Info = &sccbMgrTbl[p_card][our_target]; - tag = 0; - - - while(!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) - { - if (! (RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) - { - - WRW_HARPOON((port+hp_intstat), PHASE); - return; - } - } - - WRW_HARPOON((port+hp_intstat), PHASE); - if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) - { - - message = sfm(port,pCurrCard->currentSCCB); - if (message) - { - - if (message <= (0x80 | LUN_MASK)) - { - lun = message & (UCHAR)LUN_MASK; - -#if !defined(DOS) - if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING) - { - if (currTar_Info->TarTagQ_Cnt != 0) - { - - if (!(currTar_Info->TarLUN_CA)) - { - ACCEPT_MSG(port); /*Release the ACK for ID msg. */ - - - message = sfm(port,pCurrCard->currentSCCB); - if (message) - { - ACCEPT_MSG(port); - } - - else - message = FALSE; - - if(message != FALSE) - { - tag = sfm(port,pCurrCard->currentSCCB); - - if (!(tag)) - message = FALSE; - } - - } /*C.A. exists! */ - - } /*End Q cnt != 0 */ - - } /*End Tag cmds supported! */ -#endif /* !DOS */ - - } /*End valid ID message. */ - - else - { - - ACCEPT_MSG_ATN(port); - } - - } /* End good id message. */ - - else - { - - message = FALSE; - } - } - else - { - ACCEPT_MSG_ATN(port); - - while (!(RDW_HARPOON((port+hp_intstat)) & (PHASE | RESET)) && - !(RD_HARPOON(port+hp_scsisig) & SCSI_REQ) && - (RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) ; - - return; - } - -#endif /* V302 */ - - if(message == FALSE) - { - msgRetryCount++; - if(msgRetryCount == 1) - { - SendMsg(port, SMPARITY); - } - else - { - SendMsg(port, SMDEV_RESET); - - sssyncv(port, our_target, NARROW_SCSI,currTar_Info); - - if (sccbMgrTbl[p_card][our_target].TarEEValue & EE_SYNC_MASK) - { - - sccbMgrTbl[p_card][our_target].TarStatus &= ~TAR_SYNC_MASK; - - } - - if (sccbMgrTbl[p_card][our_target].TarEEValue & EE_WIDE_SCSI) - { - - sccbMgrTbl[p_card][our_target].TarStatus &= ~TAR_WIDE_MASK; - } - - - queueFlushTargSccb(p_card, our_target, SCCB_COMPLETE); - SccbMgrTableInitTarget(p_card,our_target); - return; - } - } - }while(message == FALSE); - - - - if(((pCurrCard->globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { - currTar_Info->TarLUNBusy[lun] = TRUE; - pCurrCard->currentSCCB = pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]]; - if(pCurrCard->currentSCCB != NULL) - { - ACCEPT_MSG(port); - } - else - { - ACCEPT_MSG_ATN(port); - } - } - else - { - currTar_Info->TarLUNBusy[0] = TRUE; - - - if (tag) - { - if (pCurrCard->discQ_Tbl[tag] != NULL) - { - pCurrCard->currentSCCB = pCurrCard->discQ_Tbl[tag]; - currTar_Info->TarTagQ_Cnt--; - ACCEPT_MSG(port); - } - else - { - ACCEPT_MSG_ATN(port); - } - }else - { - pCurrCard->currentSCCB = pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]]; - if(pCurrCard->currentSCCB != NULL) - { - ACCEPT_MSG(port); - } - else - { - ACCEPT_MSG_ATN(port); - } - } - } - - if(pCurrCard->currentSCCB != NULL) - { - if(pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) - { - /* During Abort Tag command, the target could have got re-selected - and completed the command. Check the select Q and remove the CCB - if it is in the Select Q */ - queueFindSccb(pCurrCard->currentSCCB, p_card); - } - } - - - while (!(RDW_HARPOON((port+hp_intstat)) & (PHASE | RESET)) && - !(RD_HARPOON(port+hp_scsisig) & SCSI_REQ) && - (RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) ; -} - -#if defined(V302) - -#if defined(DOS) -UCHAR GetTarLun(USHORT port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tag, PUCHAR lun) -#else -UCHAR GetTarLun(ULONG port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tag, PUCHAR lun) -#endif -{ - UCHAR message; - PSCCBMgr_tar_info currTar_Info; - - - currTar_Info = &sccbMgrTbl[p_card][our_target]; - *tag = 0; - - - while(!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) - { - if (! (RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) - { - - WRW_HARPOON((port+hp_intstat), PHASE); - return(TRUE); - } - } - - WRW_HARPOON((port+hp_intstat), PHASE); - if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) - { - - message = sfm(port,pCurrCard->currentSCCB); - if (message) - { - - if (message <= (0x80 | LUN_MASK)) - { - *lun = message & (UCHAR)LUN_MASK; - -#if !defined(DOS) - if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING) - { - if (currTar_Info->TarTagQ_Cnt != 0) - { - - if (!(currTar_Info->TarLUN_CA)) - { - ACCEPT_MSG(port); /*Release the ACK for ID msg. */ - - - message = sfm(port,pCurrCard->currentSCCB); - if (message) - { - ACCEPT_MSG(port); - } - - else - return(FALSE); - - *tag = sfm(port,pCurrCard->currentSCCB); - - if (!(*tag)) return(FALSE); - - } /*C.A. exists! */ - - } /*End Q cnt != 0 */ - - } /*End Tag cmds supported! */ -#endif /* !DOS */ - - } /*End valid ID message. */ - - else - { - - ACCEPT_MSG_ATN(port); - } - - } /* End good id message. */ - - else - { - - return(FALSE); - } - } - else - { - ACCEPT_MSG_ATN(port); - return(TRUE); - } - return(TRUE); -} - -#endif /* V302 */ - -#if defined(DOS) -void SendMsg(USHORT port, UCHAR message) -#else -void SendMsg(ULONG port, UCHAR message) -#endif -{ - while(!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) - { - if (! (RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) - { - - WRW_HARPOON((port+hp_intstat), PHASE); - return; - } - } - - WRW_HARPOON((port+hp_intstat), PHASE); - if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) - { - WRW_HARPOON((port+hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0)); - - - WR_HARPOON(port+hp_portctrl_0, SCSI_BUS_EN); - - WR_HARPOON(port+hp_scsidata_0,message); - - WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); - - ACCEPT_MSG(port); - - WR_HARPOON(port+hp_portctrl_0, 0x00); - - if ((message == SMABORT) || (message == SMDEV_RESET) || - (message == SMABORT_TAG) ) - { - while(!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | PHASE))) {} - - if (RDW_HARPOON((port+hp_intstat)) & BUS_FREE) - { - WRW_HARPOON((port+hp_intstat), BUS_FREE); - } - } - } -} - -/*--------------------------------------------------------------------- - * - * Function: sdecm - * - * Description: Determine the proper responce to the message from the - * target device. - * - *---------------------------------------------------------------------*/ -#if defined(DOS) -void sdecm(UCHAR message, USHORT port, UCHAR p_card) -#else -void sdecm(UCHAR message, ULONG port, UCHAR p_card) -#endif -{ - PSCCB currSCCB; - PSCCBcard CurrCard; - PSCCBMgr_tar_info currTar_Info; - - CurrCard = &BL_Card[p_card]; - currSCCB = CurrCard->currentSCCB; - - currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID]; - - if (message == SMREST_DATA_PTR) - { - if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) - { - currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC; - - hostDataXferRestart(currSCCB); - } - - ACCEPT_MSG(port); - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - } - - else if (message == SMCMD_COMP) - { - - - if (currSCCB->Sccb_scsistat == SELECT_Q_ST) - { - currTar_Info->TarStatus &= ~(UCHAR)TAR_TAG_Q_MASK; - currTar_Info->TarStatus |= (UCHAR)TAG_Q_REJECT; - } - - ACCEPT_MSG(port); - - } - - else if ((message == SMNO_OP) || (message >= SMIDENT) - || (message == SMINIT_RECOVERY) || (message == SMREL_RECOVERY)) - { - - ACCEPT_MSG(port); - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - } - - else if (message == SMREJECT) - { - - if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) || - (currSCCB->Sccb_scsistat == SELECT_WN_ST) || - ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING ) || - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING ) ) - - { - WRW_HARPOON((port+hp_intstat), BUS_FREE); - - ACCEPT_MSG(port); - - - while ((!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) && - (!(RDW_HARPOON((port+hp_intstat)) & BUS_FREE))) {} - - if(currSCCB->Lun == 0x00) - { - if ((currSCCB->Sccb_scsistat == SELECT_SN_ST)) - { - - currTar_Info->TarStatus |= (UCHAR)SYNC_SUPPORTED; - - currTar_Info->TarEEValue &= ~EE_SYNC_MASK; - } - -#if defined(WIDE_SCSI) - else if ((currSCCB->Sccb_scsistat == SELECT_WN_ST)) - { - - - currTar_Info->TarStatus = (currTar_Info->TarStatus & - ~WIDE_ENABLED) | WIDE_NEGOCIATED; - - currTar_Info->TarEEValue &= ~EE_WIDE_SCSI; - - } -#endif - - else if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING ) - { - currTar_Info->TarStatus = (currTar_Info->TarStatus & - ~(UCHAR)TAR_TAG_Q_MASK) | TAG_Q_REJECT; - - - currSCCB->ControlByte &= ~F_USE_CMD_Q; - CurrCard->discQCount--; - CurrCard->discQ_Tbl[currSCCB->Sccb_tag] = NULL; - currSCCB->Sccb_tag = 0x00; - - } - } - - if (RDW_HARPOON((port+hp_intstat)) & BUS_FREE) - { - - - if(currSCCB->Lun == 0x00) - { - WRW_HARPOON((port+hp_intstat), BUS_FREE); - CurrCard->globalFlags |= F_NEW_SCCB_CMD; - } - } - - else - { - - if((CurrCard->globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) - currTar_Info->TarLUNBusy[currSCCB->Lun] = TRUE; - else - currTar_Info->TarLUNBusy[0] = TRUE; - - - currSCCB->ControlByte &= ~(UCHAR)F_USE_CMD_Q; - - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - - } - } - - else - { - ACCEPT_MSG(port); - - while ((!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) && - (!(RDW_HARPOON((port+hp_intstat)) & BUS_FREE))) {} - - if (!(RDW_HARPOON((port+hp_intstat)) & BUS_FREE)) - { - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - } - } - } - - else if (message == SMEXT) - { - - ACCEPT_MSG(port); - shandem(port,p_card,currSCCB); - } - - else if (message == SMIGNORWR) - { - - ACCEPT_MSG(port); /* ACK the RESIDUE MSG */ - - message = sfm(port,currSCCB); - - if(currSCCB->Sccb_scsimsg != SMPARITY) - ACCEPT_MSG(port); - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - } - - - else - { - - currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; - currSCCB->Sccb_scsimsg = SMREJECT; - - ACCEPT_MSG_ATN(port); - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - } -} - - -/*--------------------------------------------------------------------- - * - * Function: shandem - * - * Description: Decide what to do with the extended message. - * - *---------------------------------------------------------------------*/ -#if defined(DOS) -void shandem(USHORT port, UCHAR p_card, PSCCB pCurrSCCB) -#else -void shandem(ULONG port, UCHAR p_card, PSCCB pCurrSCCB) -#endif -{ - UCHAR length,message; - - length = sfm(port,pCurrSCCB); - if (length) - { - - ACCEPT_MSG(port); - message = sfm(port,pCurrSCCB); - if (message) - { - - if (message == SMSYNC) - { - - if (length == 0x03) - { - - ACCEPT_MSG(port); - stsyncn(port,p_card); - } - else - { - - pCurrSCCB->Sccb_scsimsg = SMREJECT; - ACCEPT_MSG_ATN(port); - } - } -#if defined(WIDE_SCSI) - else if (message == SMWDTR) - { - - if (length == 0x02) - { - - ACCEPT_MSG(port); - stwidn(port,p_card); - } - else - { - - pCurrSCCB->Sccb_scsimsg = SMREJECT; - ACCEPT_MSG_ATN(port); - - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - } - } -#endif - else - { - - pCurrSCCB->Sccb_scsimsg = SMREJECT; - ACCEPT_MSG_ATN(port); - - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - } - } - else - { - if(pCurrSCCB->Sccb_scsimsg != SMPARITY) - ACCEPT_MSG(port); - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - } - }else - { - if(pCurrSCCB->Sccb_scsimsg == SMPARITY) - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - } -} - - -/*--------------------------------------------------------------------- - * - * Function: sisyncn - * - * Description: Read in a message byte from the SCSI bus, and check - * for a parity error. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -UCHAR sisyncn(USHORT port, UCHAR p_card, UCHAR syncFlag) -#else -UCHAR sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag) -#endif -{ - PSCCB currSCCB; - PSCCBMgr_tar_info currTar_Info; - - currSCCB = BL_Card[p_card].currentSCCB; - currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID]; - - if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) { - - - WRW_HARPOON((port+ID_MSG_STRT), - (MPM_OP+AMSG_OUT+(currSCCB->Sccb_idmsg & ~(UCHAR)DISC_PRIV))); - - WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+CMDPZ); - - WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT )); - WRW_HARPOON((port+SYNC_MSGS+2), (MPM_OP+AMSG_OUT+0x03 )); - WRW_HARPOON((port+SYNC_MSGS+4), (MPM_OP+AMSG_OUT+SMSYNC)); - - - if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB) - - WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+ 12)); - - else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB) - - WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+ 25)); - - else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB) - - WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+ 50)); - - else - WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+ 00)); - - - WRW_HARPOON((port+SYNC_MSGS+8), (RAT_OP )); - WRW_HARPOON((port+SYNC_MSGS+10),(MPM_OP+AMSG_OUT+DEFAULT_OFFSET)); - WRW_HARPOON((port+SYNC_MSGS+12),(BRH_OP+ALWAYS+NP )); - - - if(syncFlag == FALSE) - { - WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); - currTar_Info->TarStatus = ((currTar_Info->TarStatus & - ~(UCHAR)TAR_SYNC_MASK) | (UCHAR)SYNC_TRYING); - } - else - { - WR_HARPOON(port+hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT)); - } - - - return(TRUE); - } - - else { - - currTar_Info->TarStatus |= (UCHAR)SYNC_SUPPORTED; - currTar_Info->TarEEValue &= ~EE_SYNC_MASK; - return(FALSE); - } -} - - - -/*--------------------------------------------------------------------- - * - * Function: stsyncn - * - * Description: The has sent us a Sync Nego message so handle it as - * necessary. - * - *---------------------------------------------------------------------*/ -#if defined(DOS) -void stsyncn(USHORT port, UCHAR p_card) -#else -void stsyncn(ULONG port, UCHAR p_card) -#endif -{ - UCHAR sync_msg,offset,sync_reg,our_sync_msg; - PSCCB currSCCB; - PSCCBMgr_tar_info currTar_Info; - - currSCCB = BL_Card[p_card].currentSCCB; - currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID]; - - sync_msg = sfm(port,currSCCB); - - if((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) - { - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - return; - } - - ACCEPT_MSG(port); - - - offset = sfm(port,currSCCB); - - if((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) - { - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - return; - } - - if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB) - - our_sync_msg = 12; /* Setup our Message to 20mb/s */ - - else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB) - - our_sync_msg = 25; /* Setup our Message to 10mb/s */ - - else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB) - - our_sync_msg = 50; /* Setup our Message to 5mb/s */ - else - - our_sync_msg = 0; /* Message = Async */ - - if (sync_msg < our_sync_msg) { - sync_msg = our_sync_msg; /*if faster, then set to max. */ - } - - if (offset == ASYNC) - sync_msg = ASYNC; - - if (offset > MAX_OFFSET) - offset = MAX_OFFSET; - - sync_reg = 0x00; - - if (sync_msg > 12) - - sync_reg = 0x20; /* Use 10MB/s */ - - if (sync_msg > 25) - - sync_reg = 0x40; /* Use 6.6MB/s */ - - if (sync_msg > 38) - - sync_reg = 0x60; /* Use 5MB/s */ - - if (sync_msg > 50) - - sync_reg = 0x80; /* Use 4MB/s */ - - if (sync_msg > 62) - - sync_reg = 0xA0; /* Use 3.33MB/s */ - - if (sync_msg > 75) - - sync_reg = 0xC0; /* Use 2.85MB/s */ - - if (sync_msg > 87) - - sync_reg = 0xE0; /* Use 2.5MB/s */ - - if (sync_msg > 100) { - - sync_reg = 0x00; /* Use ASYNC */ - offset = 0x00; - } - - -#if defined(WIDE_SCSI) - if (currTar_Info->TarStatus & WIDE_ENABLED) - - sync_reg |= offset; - - else - - sync_reg |= (offset | NARROW_SCSI); - -#else - sync_reg |= (offset | NARROW_SCSI); -#endif - - sssyncv(port,currSCCB->TargID,sync_reg,currTar_Info); - - - if (currSCCB->Sccb_scsistat == SELECT_SN_ST) { - - - ACCEPT_MSG(port); - - currTar_Info->TarStatus = ((currTar_Info->TarStatus & - ~(UCHAR)TAR_SYNC_MASK) | (UCHAR)SYNC_SUPPORTED); - - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - } - - else { - - - ACCEPT_MSG_ATN(port); - - sisyncr(port,sync_msg,offset); - - currTar_Info->TarStatus = ((currTar_Info->TarStatus & - ~(UCHAR)TAR_SYNC_MASK) | (UCHAR)SYNC_SUPPORTED); - } -} - - -/*--------------------------------------------------------------------- - * - * Function: sisyncr - * - * Description: Answer the targets sync message. - * - *---------------------------------------------------------------------*/ -#if defined(DOS) -void sisyncr(USHORT port,UCHAR sync_pulse, UCHAR offset) -#else -void sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset) -#endif -{ - ARAM_ACCESS(port); - WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT )); - WRW_HARPOON((port+SYNC_MSGS+2), (MPM_OP+AMSG_OUT+0x03 )); - WRW_HARPOON((port+SYNC_MSGS+4), (MPM_OP+AMSG_OUT+SMSYNC)); - WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+sync_pulse)); - WRW_HARPOON((port+SYNC_MSGS+8), (RAT_OP )); - WRW_HARPOON((port+SYNC_MSGS+10),(MPM_OP+AMSG_OUT+offset)); - WRW_HARPOON((port+SYNC_MSGS+12),(BRH_OP+ALWAYS+NP )); - SGRAM_ACCESS(port); - - WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); - WRW_HARPOON((port+hp_intstat), CLR_ALL_INT_1); - - WR_HARPOON(port+hp_autostart_3, (AUTO_IMMED+CMD_ONLY_STRT)); - - while (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | AUTO_INT))) {} -} - - - -#if defined(WIDE_SCSI) - -/*--------------------------------------------------------------------- - * - * Function: siwidn - * - * Description: Read in a message byte from the SCSI bus, and check - * for a parity error. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -UCHAR siwidn(USHORT port, UCHAR p_card) -#else -UCHAR siwidn(ULONG port, UCHAR p_card) -#endif -{ - PSCCB currSCCB; - PSCCBMgr_tar_info currTar_Info; - - currSCCB = BL_Card[p_card].currentSCCB; - currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID]; - - if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) { - - - WRW_HARPOON((port+ID_MSG_STRT), - (MPM_OP+AMSG_OUT+(currSCCB->Sccb_idmsg & ~(UCHAR)DISC_PRIV))); - - WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+CMDPZ); - - WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT )); - WRW_HARPOON((port+SYNC_MSGS+2), (MPM_OP+AMSG_OUT+0x02 )); - WRW_HARPOON((port+SYNC_MSGS+4), (MPM_OP+AMSG_OUT+SMWDTR)); - WRW_HARPOON((port+SYNC_MSGS+6), (RAT_OP )); - WRW_HARPOON((port+SYNC_MSGS+8), (MPM_OP+AMSG_OUT+ SM16BIT)); - WRW_HARPOON((port+SYNC_MSGS+10),(BRH_OP+ALWAYS+NP )); - - WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); - - - currTar_Info->TarStatus = ((currTar_Info->TarStatus & - ~(UCHAR)TAR_WIDE_MASK) | (UCHAR)WIDE_ENABLED); - - return(TRUE); - } - - else { - - currTar_Info->TarStatus = ((currTar_Info->TarStatus & - ~(UCHAR)TAR_WIDE_MASK) | WIDE_NEGOCIATED); - - currTar_Info->TarEEValue &= ~EE_WIDE_SCSI; - return(FALSE); - } -} - - - -/*--------------------------------------------------------------------- - * - * Function: stwidn - * - * Description: The has sent us a Wide Nego message so handle it as - * necessary. - * - *---------------------------------------------------------------------*/ -#if defined(DOS) -void stwidn(USHORT port, UCHAR p_card) -#else -void stwidn(ULONG port, UCHAR p_card) -#endif -{ - UCHAR width; - PSCCB currSCCB; - PSCCBMgr_tar_info currTar_Info; - - currSCCB = BL_Card[p_card].currentSCCB; - currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID]; - - width = sfm(port,currSCCB); - - if((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) - { - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - return; - } - - - if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI)) - width = 0; - - if (width) { - currTar_Info->TarStatus |= WIDE_ENABLED; - width = 0; - } - else { - width = NARROW_SCSI; - currTar_Info->TarStatus &= ~WIDE_ENABLED; - } - - - sssyncv(port,currSCCB->TargID,width,currTar_Info); - - - if (currSCCB->Sccb_scsistat == SELECT_WN_ST) - { - - - - currTar_Info->TarStatus |= WIDE_NEGOCIATED; - - if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_SUPPORTED)) - { - ACCEPT_MSG_ATN(port); - ARAM_ACCESS(port); - sisyncn(port,p_card, TRUE); - currSCCB->Sccb_scsistat = SELECT_SN_ST; - SGRAM_ACCESS(port); - } - else - { - ACCEPT_MSG(port); - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - } - } - - else { - - - ACCEPT_MSG_ATN(port); - - if (currTar_Info->TarEEValue & EE_WIDE_SCSI) - width = SM16BIT; - else - width = SM8BIT; - - siwidr(port,width); - - currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED); - } -} - - -/*--------------------------------------------------------------------- - * - * Function: siwidr - * - * Description: Answer the targets Wide nego message. - * - *---------------------------------------------------------------------*/ -#if defined(DOS) -void siwidr(USHORT port, UCHAR width) -#else -void siwidr(ULONG port, UCHAR width) -#endif -{ - ARAM_ACCESS(port); - WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT )); - WRW_HARPOON((port+SYNC_MSGS+2), (MPM_OP+AMSG_OUT+0x02 )); - WRW_HARPOON((port+SYNC_MSGS+4), (MPM_OP+AMSG_OUT+SMWDTR)); - WRW_HARPOON((port+SYNC_MSGS+6), (RAT_OP )); - WRW_HARPOON((port+SYNC_MSGS+8),(MPM_OP+AMSG_OUT+width)); - WRW_HARPOON((port+SYNC_MSGS+10),(BRH_OP+ALWAYS+NP )); - SGRAM_ACCESS(port); - - WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); - WRW_HARPOON((port+hp_intstat), CLR_ALL_INT_1); - - WR_HARPOON(port+hp_autostart_3, (AUTO_IMMED+CMD_ONLY_STRT)); - - while (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | AUTO_INT))) {} -} - -#endif - - - -/*--------------------------------------------------------------------- - * - * Function: sssyncv - * - * Description: Write the desired value to the Sync Register for the - * ID specified. - * - *---------------------------------------------------------------------*/ -#if defined(DOS) -void sssyncv(USHORT p_port, UCHAR p_id, UCHAR p_sync_value,PSCCBMgr_tar_info currTar_Info) -#else -void sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value,PSCCBMgr_tar_info currTar_Info) -#endif -{ - UCHAR index; - - index = p_id; - - switch (index) { - - case 0: - index = 12; /* hp_synctarg_0 */ - break; - case 1: - index = 13; /* hp_synctarg_1 */ - break; - case 2: - index = 14; /* hp_synctarg_2 */ - break; - case 3: - index = 15; /* hp_synctarg_3 */ - break; - case 4: - index = 8; /* hp_synctarg_4 */ - break; - case 5: - index = 9; /* hp_synctarg_5 */ - break; - case 6: - index = 10; /* hp_synctarg_6 */ - break; - case 7: - index = 11; /* hp_synctarg_7 */ - break; - case 8: - index = 4; /* hp_synctarg_8 */ - break; - case 9: - index = 5; /* hp_synctarg_9 */ - break; - case 10: - index = 6; /* hp_synctarg_10 */ - break; - case 11: - index = 7; /* hp_synctarg_11 */ - break; - case 12: - index = 0; /* hp_synctarg_12 */ - break; - case 13: - index = 1; /* hp_synctarg_13 */ - break; - case 14: - index = 2; /* hp_synctarg_14 */ - break; - case 15: - index = 3; /* hp_synctarg_15 */ - - } - - WR_HARPOON(p_port+hp_synctarg_base+index, p_sync_value); - - currTar_Info->TarSyncCtrl = p_sync_value; -} - - -/*--------------------------------------------------------------------- - * - * Function: sresb - * - * Description: Reset the desired card's SCSI bus. - * - *---------------------------------------------------------------------*/ -#if defined(DOS) -void sresb(USHORT port, UCHAR p_card) -#else -void sresb(ULONG port, UCHAR p_card) -#endif -{ - UCHAR scsiID, i; - - PSCCBMgr_tar_info currTar_Info; - - WR_HARPOON(port+hp_page_ctrl, - (RD_HARPOON(port+hp_page_ctrl) | G_INT_DISABLE)); - WRW_HARPOON((port+hp_intstat), CLR_ALL_INT); - - WR_HARPOON(port+hp_scsictrl_0, SCSI_RST); - - scsiID = RD_HARPOON(port+hp_seltimeout); - WR_HARPOON(port+hp_seltimeout,TO_5ms); - WRW_HARPOON((port+hp_intstat), TIMEOUT); - - WR_HARPOON(port+hp_portctrl_0,(SCSI_PORT | START_TO)); - - while (!(RDW_HARPOON((port+hp_intstat)) & TIMEOUT)) {} - - WR_HARPOON(port+hp_seltimeout,scsiID); - - WR_HARPOON(port+hp_scsictrl_0, ENA_SCAM_SEL); - - Wait(port, TO_5ms); - - WRW_HARPOON((port+hp_intstat), CLR_ALL_INT); - - WR_HARPOON(port+hp_int_mask, (RD_HARPOON(port+hp_int_mask) | 0x00)); - - for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) - { - currTar_Info = &sccbMgrTbl[p_card][scsiID]; - - if (currTar_Info->TarEEValue & EE_SYNC_MASK) - { - currTar_Info->TarSyncCtrl = 0; - currTar_Info->TarStatus &= ~TAR_SYNC_MASK; - } - - if (currTar_Info->TarEEValue & EE_WIDE_SCSI) - { - currTar_Info->TarStatus &= ~TAR_WIDE_MASK; - } - - sssyncv(port, scsiID, NARROW_SCSI,currTar_Info); - - SccbMgrTableInitTarget(p_card, scsiID); - } - - BL_Card[p_card].scanIndex = 0x00; - BL_Card[p_card].currentSCCB = NULL; - BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT - | F_NEW_SCCB_CMD); - BL_Card[p_card].cmdCounter = 0x00; - BL_Card[p_card].discQCount = 0x00; - BL_Card[p_card].tagQ_Lst = 0x01; - - for(i = 0; i < QUEUE_DEPTH; i++) - BL_Card[p_card].discQ_Tbl[i] = NULL; - - WR_HARPOON(port+hp_page_ctrl, - (RD_HARPOON(port+hp_page_ctrl) & ~G_INT_DISABLE)); - -} - -/*--------------------------------------------------------------------- - * - * Function: ssenss - * - * Description: Setup for the Auto Sense command. - * - *---------------------------------------------------------------------*/ -void ssenss(PSCCBcard pCurrCard) -{ - UCHAR i; - PSCCB currSCCB; - - currSCCB = pCurrCard->currentSCCB; - - - currSCCB->Save_CdbLen = currSCCB->CdbLength; - - for (i = 0; i < 6; i++) { - - currSCCB->Save_Cdb[i] = currSCCB->Cdb[i]; - } - - currSCCB->CdbLength = SIX_BYTE_CMD; - currSCCB->Cdb[0] = SCSI_REQUEST_SENSE; - currSCCB->Cdb[1] = currSCCB->Cdb[1] & (UCHAR)0xE0; /*Keep LUN. */ - currSCCB->Cdb[2] = 0x00; - currSCCB->Cdb[3] = 0x00; - currSCCB->Cdb[4] = currSCCB->RequestSenseLength; - currSCCB->Cdb[5] = 0x00; - - currSCCB->Sccb_XferCnt = (unsigned long)currSCCB->RequestSenseLength; - - currSCCB->Sccb_ATC = 0x00; - - currSCCB->Sccb_XferState |= F_AUTO_SENSE; - - currSCCB->Sccb_XferState &= ~F_SG_XFER; - - currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(UCHAR)DISC_PRIV; - - currSCCB->ControlByte = 0x00; - - currSCCB->Sccb_MGRFlags &= F_STATUSLOADED; -} - - - -/*--------------------------------------------------------------------- - * - * Function: sxfrp - * - * Description: Transfer data into the bit bucket until the device - * decides to switch phase. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void sxfrp(USHORT p_port, UCHAR p_card) -#else -void sxfrp(ULONG p_port, UCHAR p_card) -#endif -{ - UCHAR curr_phz; - - - DISABLE_AUTO(p_port); - - if (BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) { - - hostDataXferAbort(p_port,p_card,BL_Card[p_card].currentSCCB); - - } - - /* If the Automation handled the end of the transfer then do not - match the phase or we will get out of sync with the ISR. */ - - if (RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | XFER_CNT_0 | AUTO_INT)) - return; - - WR_HARPOON(p_port+hp_xfercnt_0, 0x00); - - curr_phz = RD_HARPOON(p_port+hp_scsisig) & (UCHAR)S_SCSI_PHZ; - - WRW_HARPOON((p_port+hp_intstat), XFER_CNT_0); - - - WR_HARPOON(p_port+hp_scsisig, curr_phz); - - while ( !(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET)) && - (curr_phz == (RD_HARPOON(p_port+hp_scsisig) & (UCHAR)S_SCSI_PHZ)) ) - { - if (curr_phz & (UCHAR)SCSI_IOBIT) - { - WR_HARPOON(p_port+hp_portctrl_0, (SCSI_PORT | HOST_PORT | SCSI_INBIT)); - - if (!(RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY)) - { - RD_HARPOON(p_port+hp_fifodata_0); - } - } - else - { - WR_HARPOON(p_port+hp_portctrl_0, (SCSI_PORT | HOST_PORT | HOST_WRT)); - if (RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY) - { - WR_HARPOON(p_port+hp_fifodata_0,0xFA); - } - } - } /* End of While loop for padding data I/O phase */ - - while ( !(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET))) - { - if (RD_HARPOON(p_port+hp_scsisig) & SCSI_REQ) - break; - } - - WR_HARPOON(p_port+hp_portctrl_0, (SCSI_PORT | HOST_PORT | SCSI_INBIT)); - while (!(RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY)) - { - RD_HARPOON(p_port+hp_fifodata_0); - } - - if ( !(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET))) - { - WR_HARPOON(p_port+hp_autostart_0, (AUTO_IMMED+DISCONNECT_START)); - while (!(RDW_HARPOON((p_port+hp_intstat)) & AUTO_INT)) {} - - if (RDW_HARPOON((p_port+hp_intstat)) & (ICMD_COMP | ITAR_DISC)) - while (!(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RSEL))) ; - } -} - - -/*--------------------------------------------------------------------- - * - * Function: schkdd - * - * Description: Make sure data has been flushed from both FIFOs and abort - * the operations if necessary. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void schkdd(USHORT port, UCHAR p_card) -#else -void schkdd(ULONG port, UCHAR p_card) -#endif -{ - USHORT TimeOutLoop; - UCHAR sPhase; - - PSCCB currSCCB; - - currSCCB = BL_Card[p_card].currentSCCB; - - - if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) && - (currSCCB->Sccb_scsistat != DATA_IN_ST)) { - return; - } - - - - if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) - { - - currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt-1); - - currSCCB->Sccb_XferCnt = 1; - - currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT; - WRW_HARPOON((port+hp_fiforead), (USHORT) 0x00); - WR_HARPOON(port+hp_xferstat, 0x00); - } - - else - { - - currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt; - - currSCCB->Sccb_XferCnt = 0; - } - - if ((RDW_HARPOON((port+hp_intstat)) & PARITY) && - (currSCCB->HostStatus == SCCB_COMPLETE)) { - - currSCCB->HostStatus = SCCB_PARITY_ERR; - WRW_HARPOON((port+hp_intstat), PARITY); - } - - - hostDataXferAbort(port,p_card,currSCCB); - - - while (RD_HARPOON(port+hp_scsisig) & SCSI_ACK) {} - - TimeOutLoop = 0; - - while(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY) - { - if (RDW_HARPOON((port+hp_intstat)) & BUS_FREE) { - return; - } - if (RD_HARPOON(port+hp_offsetctr) & (UCHAR)0x1F) { - break; - } - if (RDW_HARPOON((port+hp_intstat)) & RESET) { - return; - } - if ((RD_HARPOON(port+hp_scsisig) & SCSI_REQ) || (TimeOutLoop++>0x3000) ) - break; - } - - sPhase = RD_HARPOON(port+hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ); - if ((!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) || - (RD_HARPOON(port+hp_offsetctr) & (UCHAR)0x1F) || - (sPhase == (SCSI_BSY | S_DATAO_PH)) || - (sPhase == (SCSI_BSY | S_DATAI_PH))) - { - - WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); - - if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) - { - if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) { - phaseDataIn(port,p_card); - } - - else { - phaseDataOut(port,p_card); - } - } - else - { - sxfrp(port,p_card); - if (!(RDW_HARPOON((port+hp_intstat)) & - (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) - { - WRW_HARPOON((port+hp_intstat), AUTO_INT); - phaseDecode(port,p_card); - } - } - - } - - else { - WR_HARPOON(port+hp_portctrl_0, 0x00); - } -} - - -/*--------------------------------------------------------------------- - * - * Function: sinits - * - * Description: Setup SCCB manager fields in this SCCB. - * - *---------------------------------------------------------------------*/ - -void sinits(PSCCB p_sccb, UCHAR p_card) -{ - PSCCBMgr_tar_info currTar_Info; - - if((p_sccb->TargID > MAX_SCSI_TAR) || (p_sccb->Lun > MAX_LUN)) - { - return; - } - currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID]; - - p_sccb->Sccb_XferState = 0x00; - p_sccb->Sccb_XferCnt = p_sccb->DataLength; - - if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) || - (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) { - - p_sccb->Sccb_SGoffset = 0; - p_sccb->Sccb_XferState = F_SG_XFER; - p_sccb->Sccb_XferCnt = 0x00; - } - - if (p_sccb->DataLength == 0x00) - - p_sccb->Sccb_XferState |= F_ALL_XFERRED; - - if (p_sccb->ControlByte & F_USE_CMD_Q) - { - if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT) - p_sccb->ControlByte &= ~F_USE_CMD_Q; - - else - currTar_Info->TarStatus |= TAG_Q_TRYING; - } - -/* For !single SCSI device in system & device allow Disconnect - or command is tag_q type then send Cmd with Disconnect Enable - else send Cmd with Disconnect Disable */ - -/* - if (((!(BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) && - (currTar_Info->TarStatus & TAR_ALLOW_DISC)) || - (currTar_Info->TarStatus & TAG_Q_TRYING)) { -*/ - if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) || - (currTar_Info->TarStatus & TAG_Q_TRYING)) { - p_sccb->Sccb_idmsg = (UCHAR)(SMIDENT | DISC_PRIV) | p_sccb->Lun; - } - - else { - - p_sccb->Sccb_idmsg = (UCHAR)SMIDENT | p_sccb->Lun; - } - - p_sccb->HostStatus = 0x00; - p_sccb->TargetStatus = 0x00; - p_sccb->Sccb_tag = 0x00; - p_sccb->Sccb_MGRFlags = 0x00; - p_sccb->Sccb_sgseg = 0x00; - p_sccb->Sccb_ATC = 0x00; - p_sccb->Sccb_savedATC = 0x00; -/* - p_sccb->SccbVirtDataPtr = 0x00; - p_sccb->Sccb_forwardlink = NULL; - p_sccb->Sccb_backlink = NULL; - */ - p_sccb->Sccb_scsistat = BUS_FREE_ST; - p_sccb->SccbStatus = SCCB_IN_PROCESS; - p_sccb->Sccb_scsimsg = SMNO_OP; - -} - - -#ident "$Id: phase.c 1.11 1997/01/31 02:08:49 mohan Exp $" -/*---------------------------------------------------------------------- - * - * - * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved - * - * This file is available under both the GNU General Public License - * and a BSD-style copyright; see LICENSE.FlashPoint for details. - * - * $Workfile: phase.c $ - * - * Description: Functions to intially handle the SCSI bus phase when - * the target asserts request (and the automation is not - * enabled to handle the situation). - * - * $Date: 1997/01/31 02:08:49 $ - * - * $Revision: 1.11 $ - * - *----------------------------------------------------------------------*/ - -/*#include */ - -#if (FW_TYPE==_UCB_MGR_) - /*#include */ -#endif - -/*#include */ -/*#include */ -/*#include */ -/*#include */ -/*#include */ - - -/* -extern SCCBCARD BL_Card[MAX_CARDS]; -extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR]; - -#if defined(OS2) - extern void (far *s_PhaseTbl[8]) (ULONG, UCHAR); -#else - #if defined(DOS) - extern void (*s_PhaseTbl[8]) (USHORT, UCHAR); - #else - extern void (*s_PhaseTbl[8]) (ULONG, UCHAR); - #endif -#endif -*/ - -/*--------------------------------------------------------------------- - * - * Function: Phase Decode - * - * Description: Determine the phase and call the appropriate function. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void phaseDecode(USHORT p_port, UCHAR p_card) -#else -void phaseDecode(ULONG p_port, UCHAR p_card) -#endif -{ - unsigned char phase_ref; -#if defined(OS2) - void (far *phase) (ULONG, UCHAR); -#else - #if defined(DOS) - void (*phase) (USHORT, UCHAR); - #else - void (*phase) (ULONG, UCHAR); - #endif -#endif - - - DISABLE_AUTO(p_port); - - phase_ref = (UCHAR) (RD_HARPOON(p_port+hp_scsisig) & S_SCSI_PHZ); - - phase = s_PhaseTbl[phase_ref]; - - (*phase)(p_port, p_card); /* Call the correct phase func */ -} - - - -/*--------------------------------------------------------------------- - * - * Function: Data Out Phase - * - * Description: Start up both the BusMaster and Xbow. - * - *---------------------------------------------------------------------*/ - -#if defined(OS2) -void far phaseDataOut(ULONG port, UCHAR p_card) -#else -#if defined(DOS) -void phaseDataOut(USHORT port, UCHAR p_card) -#else -void phaseDataOut(ULONG port, UCHAR p_card) -#endif -#endif -{ - - PSCCB currSCCB; - - currSCCB = BL_Card[p_card].currentSCCB; - if (currSCCB == NULL) - { - return; /* Exit if No SCCB record */ - } - - currSCCB->Sccb_scsistat = DATA_OUT_ST; - currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET); - - WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); - - WRW_HARPOON((port+hp_intstat), XFER_CNT_0); - - WR_HARPOON(port+hp_autostart_0, (END_DATA+END_DATA_START)); - - dataXferProcessor(port, &BL_Card[p_card]); - -#if defined(NOBUGBUG) - if (RDW_HARPOON((port+hp_intstat)) & XFER_CNT_0) - WRW_HARPOON((port+hp_intstat), XFER_CNT_0); - -#endif - - - if (currSCCB->Sccb_XferCnt == 0) { - - - if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) && - (currSCCB->HostStatus == SCCB_COMPLETE)) - currSCCB->HostStatus = SCCB_DATA_OVER_RUN; - - sxfrp(port,p_card); - if (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | RESET))) - phaseDecode(port,p_card); - } -} - - -/*--------------------------------------------------------------------- - * - * Function: Data In Phase - * - * Description: Startup the BusMaster and the XBOW. - * - *---------------------------------------------------------------------*/ - -#if defined(OS2) -void far phaseDataIn(ULONG port, UCHAR p_card) -#else -#if defined(DOS) -void phaseDataIn(USHORT port, UCHAR p_card) -#else -void phaseDataIn(ULONG port, UCHAR p_card) -#endif -#endif -{ - - PSCCB currSCCB; - - currSCCB = BL_Card[p_card].currentSCCB; - - if (currSCCB == NULL) - { - return; /* Exit if No SCCB record */ - } - - - currSCCB->Sccb_scsistat = DATA_IN_ST; - currSCCB->Sccb_XferState |= F_HOST_XFER_DIR; - currSCCB->Sccb_XferState &= ~F_NO_DATA_YET; - - WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); - - WRW_HARPOON((port+hp_intstat), XFER_CNT_0); - - WR_HARPOON(port+hp_autostart_0, (END_DATA+END_DATA_START)); - - dataXferProcessor(port, &BL_Card[p_card]); - - if (currSCCB->Sccb_XferCnt == 0) { - - - if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) && - (currSCCB->HostStatus == SCCB_COMPLETE)) - currSCCB->HostStatus = SCCB_DATA_OVER_RUN; - - sxfrp(port,p_card); - if (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | RESET))) - phaseDecode(port,p_card); - - } -} - -/*--------------------------------------------------------------------- - * - * Function: Command Phase - * - * Description: Load the CDB into the automation and start it up. - * - *---------------------------------------------------------------------*/ - -#if defined(OS2) -void far phaseCommand(ULONG p_port, UCHAR p_card) -#else -#if defined(DOS) -void phaseCommand(USHORT p_port, UCHAR p_card) -#else -void phaseCommand(ULONG p_port, UCHAR p_card) -#endif -#endif -{ - PSCCB currSCCB; -#if defined(DOS) - USHORT cdb_reg; -#else - ULONG cdb_reg; -#endif - UCHAR i; - - currSCCB = BL_Card[p_card].currentSCCB; - - if (currSCCB->OperationCode == RESET_COMMAND) { - - currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; - currSCCB->CdbLength = SIX_BYTE_CMD; - } - - WR_HARPOON(p_port+hp_scsisig, 0x00); - - ARAM_ACCESS(p_port); - - - cdb_reg = p_port + CMD_STRT; - - for (i=0; i < currSCCB->CdbLength; i++) { - - if (currSCCB->OperationCode == RESET_COMMAND) - - WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00)); - - else - WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + currSCCB->Cdb[i])); - cdb_reg +=2; - } - - if (currSCCB->CdbLength != TWELVE_BYTE_CMD) - WRW_HARPOON(cdb_reg, (BRH_OP+ALWAYS+ NP)); - - WR_HARPOON(p_port+hp_portctrl_0,(SCSI_PORT)); - - currSCCB->Sccb_scsistat = COMMAND_ST; - - WR_HARPOON(p_port+hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT)); - SGRAM_ACCESS(p_port); -} - - -/*--------------------------------------------------------------------- - * - * Function: Status phase - * - * Description: Bring in the status and command complete message bytes - * - *---------------------------------------------------------------------*/ - -#if defined(OS2) -void far phaseStatus(ULONG port, UCHAR p_card) -#else -#if defined(DOS) -void phaseStatus(USHORT port, UCHAR p_card) -#else -void phaseStatus(ULONG port, UCHAR p_card) -#endif -#endif -{ - /* Start-up the automation to finish off this command and let the - isr handle the interrupt for command complete when it comes in. - We could wait here for the interrupt to be generated? - */ - - WR_HARPOON(port+hp_scsisig, 0x00); - - WR_HARPOON(port+hp_autostart_0, (AUTO_IMMED+END_DATA_START)); -} - - -/*--------------------------------------------------------------------- - * - * Function: Phase Message Out - * - * Description: Send out our message (if we have one) and handle whatever - * else is involed. - * - *---------------------------------------------------------------------*/ - -#if defined(OS2) -void far phaseMsgOut(ULONG port, UCHAR p_card) -#else -#if defined(DOS) -void phaseMsgOut(USHORT port, UCHAR p_card) -#else -void phaseMsgOut(ULONG port, UCHAR p_card) -#endif -#endif -{ - UCHAR message,scsiID; - PSCCB currSCCB; - PSCCBMgr_tar_info currTar_Info; - - currSCCB = BL_Card[p_card].currentSCCB; - - if (currSCCB != NULL) { - - message = currSCCB->Sccb_scsimsg; - scsiID = currSCCB->TargID; - - if (message == SMDEV_RESET) - { - - - currTar_Info = &sccbMgrTbl[p_card][scsiID]; - currTar_Info->TarSyncCtrl = 0; - sssyncv(port, scsiID, NARROW_SCSI,currTar_Info); - - if (sccbMgrTbl[p_card][scsiID].TarEEValue & EE_SYNC_MASK) - { - - sccbMgrTbl[p_card][scsiID].TarStatus &= ~TAR_SYNC_MASK; - - } - - if (sccbMgrTbl[p_card][scsiID].TarEEValue & EE_WIDE_SCSI) - { - - sccbMgrTbl[p_card][scsiID].TarStatus &= ~TAR_WIDE_MASK; - } - - - queueFlushSccb(p_card,SCCB_COMPLETE); - SccbMgrTableInitTarget(p_card,scsiID); - } - else if (currSCCB->Sccb_scsistat == ABORT_ST) - { - currSCCB->HostStatus = SCCB_COMPLETE; - if(BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] != NULL) - { - BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL; - sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--; - } - - } - - else if (currSCCB->Sccb_scsistat < COMMAND_ST) - { - - - if(message == SMNO_OP) - { - currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED; - - ssel(port,p_card); - return; - } - } - else - { - - - if (message == SMABORT) - - queueFlushSccb(p_card,SCCB_COMPLETE); - } - - } - else - { - message = SMABORT; - } - - WRW_HARPOON((port+hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0)); - - - WR_HARPOON(port+hp_portctrl_0, SCSI_BUS_EN); - - WR_HARPOON(port+hp_scsidata_0,message); - - WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); - - ACCEPT_MSG(port); - - WR_HARPOON(port+hp_portctrl_0, 0x00); - - if ((message == SMABORT) || (message == SMDEV_RESET) || - (message == SMABORT_TAG) ) - { - - while(!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | PHASE))) {} - - if (RDW_HARPOON((port+hp_intstat)) & BUS_FREE) - { - WRW_HARPOON((port+hp_intstat), BUS_FREE); - - if (currSCCB != NULL) - { - - if((BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE; - else - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE; - - queueCmdComplete(&BL_Card[p_card],currSCCB, p_card); - } - - else - { - BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; - } - } - - else - { - - sxfrp(port,p_card); - } - } - - else - { - - if(message == SMPARITY) - { - currSCCB->Sccb_scsimsg = SMNO_OP; - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - } - else - { - sxfrp(port,p_card); - } - } -} - - -/*--------------------------------------------------------------------- - * - * Function: Message In phase - * - * Description: Bring in the message and determine what to do with it. - * - *---------------------------------------------------------------------*/ - -#if defined(OS2) -void far phaseMsgIn(ULONG port, UCHAR p_card) -#else -#if defined(DOS) -void phaseMsgIn(USHORT port, UCHAR p_card) -#else -void phaseMsgIn(ULONG port, UCHAR p_card) -#endif -#endif -{ - UCHAR message; - PSCCB currSCCB; - - currSCCB = BL_Card[p_card].currentSCCB; - - if (BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) - { - - phaseChkFifo(port, p_card); - } - - message = RD_HARPOON(port+hp_scsidata_0); - if ((message == SMDISC) || (message == SMSAVE_DATA_PTR)) - { - - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+END_DATA_START)); - - } - - else - { - - message = sfm(port,currSCCB); - if (message) - { - - - sdecm(message,port,p_card); - - } - else - { - if(currSCCB->Sccb_scsimsg != SMPARITY) - ACCEPT_MSG(port); - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - } - } - -} - - -/*--------------------------------------------------------------------- - * - * Function: Illegal phase - * - * Description: Target switched to some illegal phase, so all we can do - * is report an error back to the host (if that is possible) - * and send an ABORT message to the misbehaving target. - * - *---------------------------------------------------------------------*/ - -#if defined(OS2) -void far phaseIllegal(ULONG port, UCHAR p_card) -#else -#if defined(DOS) -void phaseIllegal(USHORT port, UCHAR p_card) -#else -void phaseIllegal(ULONG port, UCHAR p_card) -#endif -#endif -{ - PSCCB currSCCB; - - currSCCB = BL_Card[p_card].currentSCCB; - - WR_HARPOON(port+hp_scsisig, RD_HARPOON(port+hp_scsisig)); - if (currSCCB != NULL) { - - currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; - currSCCB->Sccb_scsistat = ABORT_ST; - currSCCB->Sccb_scsimsg = SMABORT; - } - - ACCEPT_MSG_ATN(port); -} - - - -/*--------------------------------------------------------------------- - * - * Function: Phase Check FIFO - * - * Description: Make sure data has been flushed from both FIFOs and abort - * the operations if necessary. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void phaseChkFifo(USHORT port, UCHAR p_card) -#else -void phaseChkFifo(ULONG port, UCHAR p_card) -#endif -{ - ULONG xfercnt; - PSCCB currSCCB; - - currSCCB = BL_Card[p_card].currentSCCB; - - if (currSCCB->Sccb_scsistat == DATA_IN_ST) - { - - while((!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) && - (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY)) {} - - - if (!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) - { - currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt; - - currSCCB->Sccb_XferCnt = 0; - - if ((RDW_HARPOON((port+hp_intstat)) & PARITY) && - (currSCCB->HostStatus == SCCB_COMPLETE)) - { - currSCCB->HostStatus = SCCB_PARITY_ERR; - WRW_HARPOON((port+hp_intstat), PARITY); - } - - hostDataXferAbort(port,p_card,currSCCB); - - dataXferProcessor(port, &BL_Card[p_card]); - - while((!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) && - (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY)) {} - - } - } /*End Data In specific code. */ - - - -#if defined(DOS) - asm { mov dx,port; - add dx,hp_xfercnt_2; - in al,dx; - dec dx; - xor ah,ah; - mov word ptr xfercnt+2,ax; - in al,dx; - dec dx; - mov ah,al; - in al,dx; - mov word ptr xfercnt,ax; - } -#else - GET_XFER_CNT(port,xfercnt); -#endif - - - WR_HARPOON(port+hp_xfercnt_0, 0x00); - - - WR_HARPOON(port+hp_portctrl_0, 0x00); - - currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt); - - currSCCB->Sccb_XferCnt = xfercnt; - - if ((RDW_HARPOON((port+hp_intstat)) & PARITY) && - (currSCCB->HostStatus == SCCB_COMPLETE)) { - - currSCCB->HostStatus = SCCB_PARITY_ERR; - WRW_HARPOON((port+hp_intstat), PARITY); - } - - - hostDataXferAbort(port,p_card,currSCCB); - - - WR_HARPOON(port+hp_fifowrite, 0x00); - WR_HARPOON(port+hp_fiforead, 0x00); - WR_HARPOON(port+hp_xferstat, 0x00); - - WRW_HARPOON((port+hp_intstat), XFER_CNT_0); -} - - -/*--------------------------------------------------------------------- - * - * Function: Phase Bus Free - * - * Description: We just went bus free so figure out if it was - * because of command complete or from a disconnect. - * - *---------------------------------------------------------------------*/ -#if defined(DOS) -void phaseBusFree(USHORT port, UCHAR p_card) -#else -void phaseBusFree(ULONG port, UCHAR p_card) -#endif -{ - PSCCB currSCCB; - - currSCCB = BL_Card[p_card].currentSCCB; - - if (currSCCB != NULL) - { - - DISABLE_AUTO(port); - - - if (currSCCB->OperationCode == RESET_COMMAND) - { - - if((BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE; - else - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE; - - queueCmdComplete(&BL_Card[p_card], currSCCB, p_card); - - queueSearchSelect(&BL_Card[p_card],p_card); - - } - - else if(currSCCB->Sccb_scsistat == SELECT_SN_ST) - { - sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= - (UCHAR)SYNC_SUPPORTED; - sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK; - } - - else if(currSCCB->Sccb_scsistat == SELECT_WN_ST) - { - sccbMgrTbl[p_card][currSCCB->TargID].TarStatus = - (sccbMgrTbl[p_card][currSCCB->TargID]. - TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED; - - sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_WIDE_SCSI; - } - -#if !defined(DOS) - else if(currSCCB->Sccb_scsistat == SELECT_Q_ST) - { - /* Make sure this is not a phony BUS_FREE. If we were - reselected or if BUSY is NOT on then this is a - valid BUS FREE. SRR Wednesday, 5/10/1995. */ - - if ((!(RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) || - (RDW_HARPOON((port+hp_intstat)) & RSEL)) - { - sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_TAG_Q_MASK; - sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= TAG_Q_REJECT; - } - - else - { - return; - } - } -#endif - - else - { - - currSCCB->Sccb_scsistat = BUS_FREE_ST; - - if (!currSCCB->HostStatus) - { - currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; - } - - if((BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE; - else - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE; - - queueCmdComplete(&BL_Card[p_card], currSCCB, p_card); - return; - } - - - BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; - - } /*end if !=null */ -} - - - - -#ident "$Id: automate.c 1.14 1997/01/31 02:11:46 mohan Exp $" -/*---------------------------------------------------------------------- - * - * - * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved - * - * This file is available under both the GNU General Public License - * and a BSD-style copyright; see LICENSE.FlashPoint for details. - * - * $Workfile: automate.c $ - * - * Description: Functions relating to programming the automation of - * the HARPOON. - * - * $Date: 1997/01/31 02:11:46 $ - * - * $Revision: 1.14 $ - * - *----------------------------------------------------------------------*/ - -/*#include */ - -#if (FW_TYPE==_UCB_MGR_) - /*#include */ -#endif - -/*#include */ -/*#include */ -/*#include */ -/*#include */ -/*#include */ - -/* -extern SCCBCARD BL_Card[MAX_CARDS]; -extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR]; -extern SCCBCARD BL_Card[MAX_CARDS]; -*/ - -/*--------------------------------------------------------------------- - * - * Function: Auto Load Default Map - * - * Description: Load the Automation RAM with the defualt map values. - * - *---------------------------------------------------------------------*/ -#if defined(DOS) -void autoLoadDefaultMap(USHORT p_port) -#else -void autoLoadDefaultMap(ULONG p_port) -#endif -{ -#if defined(DOS) - USHORT map_addr; -#else - ULONG map_addr; -#endif - - ARAM_ACCESS(p_port); - map_addr = p_port + hp_aramBase; - - WRW_HARPOON(map_addr, (MPM_OP+AMSG_OUT+ 0xC0)); /*ID MESSAGE */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+AMSG_OUT+ 0x20)); /*SIMPLE TAG QUEUEING MSG */ - map_addr +=2; - WRW_HARPOON(map_addr, RAT_OP); /*RESET ATTENTION */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+AMSG_OUT+ 0x00)); /*TAG ID MSG */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 0 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 1 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 2 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 3 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 4 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 5 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 6 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 7 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 8 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 9 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 10 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 11 */ - map_addr +=2; - WRW_HARPOON(map_addr, (CPE_OP+ADATA_OUT+ DINT)); /*JUMP IF DATA OUT */ - map_addr +=2; - WRW_HARPOON(map_addr, (TCB_OP+FIFO_0+ DI)); /*JUMP IF NO DATA IN FIFO */ - map_addr +=2; /*This means AYNC DATA IN */ - WRW_HARPOON(map_addr, (SSI_OP+ SSI_IDO_STRT)); /*STOP AND INTERRUPT */ - map_addr +=2; - WRW_HARPOON(map_addr, (CPE_OP+ADATA_IN+DINT)); /*JUMP IF NOT DATA IN PHZ */ - map_addr +=2; - WRW_HARPOON(map_addr, (CPN_OP+AMSG_IN+ ST)); /*IF NOT MSG IN CHECK 4 DATA IN */ - map_addr +=2; - WRW_HARPOON(map_addr, (CRD_OP+SDATA+ 0x02)); /*SAVE DATA PTR MSG? */ - map_addr +=2; - WRW_HARPOON(map_addr, (BRH_OP+NOT_EQ+ DC)); /*GO CHECK FOR DISCONNECT MSG */ - map_addr +=2; - WRW_HARPOON(map_addr, (MRR_OP+SDATA+ D_AR1)); /*SAVE DATA PTRS MSG */ - map_addr +=2; - WRW_HARPOON(map_addr, (CPN_OP+AMSG_IN+ ST)); /*IF NOT MSG IN CHECK DATA IN */ - map_addr +=2; - WRW_HARPOON(map_addr, (CRD_OP+SDATA+ 0x04)); /*DISCONNECT MSG? */ - map_addr +=2; - WRW_HARPOON(map_addr, (BRH_OP+NOT_EQ+ UNKNWN));/*UKNKNOWN MSG */ - map_addr +=2; - WRW_HARPOON(map_addr, (MRR_OP+SDATA+ D_BUCKET));/*XFER DISCONNECT MSG */ - map_addr +=2; - WRW_HARPOON(map_addr, (SSI_OP+ SSI_ITAR_DISC));/*STOP AND INTERRUPT */ - map_addr +=2; - WRW_HARPOON(map_addr, (CPN_OP+ASTATUS+ UNKNWN));/*JUMP IF NOT STATUS PHZ. */ - map_addr +=2; - WRW_HARPOON(map_addr, (MRR_OP+SDATA+ D_AR0)); /*GET STATUS BYTE */ - map_addr +=2; - WRW_HARPOON(map_addr, (CPN_OP+AMSG_IN+ CC)); /*ERROR IF NOT MSG IN PHZ */ - map_addr +=2; - WRW_HARPOON(map_addr, (CRD_OP+SDATA+ 0x00)); /*CHECK FOR CMD COMPLETE MSG. */ - map_addr +=2; - WRW_HARPOON(map_addr, (BRH_OP+NOT_EQ+ CC)); /*ERROR IF NOT CMD COMPLETE MSG. */ - map_addr +=2; - WRW_HARPOON(map_addr, (MRR_OP+SDATA+ D_BUCKET));/*GET CMD COMPLETE MSG */ - map_addr +=2; - WRW_HARPOON(map_addr, (SSI_OP+ SSI_ICMD_COMP));/*END OF COMMAND */ - map_addr +=2; - - WRW_HARPOON(map_addr, (SSI_OP+ SSI_IUNKWN)); /*RECEIVED UNKNOWN MSG BYTE */ - map_addr +=2; - WRW_HARPOON(map_addr, (SSI_OP+ SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */ - map_addr +=2; - WRW_HARPOON(map_addr, (SSI_OP+ SSI_ITICKLE)); /*BIOS Tickled the Mgr */ - map_addr +=2; - WRW_HARPOON(map_addr, (SSI_OP+ SSI_IRFAIL)); /*EXPECTED ID/TAG MESSAGES AND */ - map_addr +=2; /* DIDN'T GET ONE */ - WRW_HARPOON(map_addr, (CRR_OP+AR3+ S_IDREG)); /* comp SCSI SEL ID & AR3*/ - map_addr +=2; - WRW_HARPOON(map_addr, (BRH_OP+EQUAL+ 0x00)); /*SEL ID OK then Conti. */ - map_addr +=2; - WRW_HARPOON(map_addr, (SSI_OP+ SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */ - - - - SGRAM_ACCESS(p_port); -} - -/*--------------------------------------------------------------------- - * - * Function: Auto Command Complete - * - * Description: Post command back to host and find another command - * to execute. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void autoCmdCmplt(USHORT p_port, UCHAR p_card) -#else -void autoCmdCmplt(ULONG p_port, UCHAR p_card) -#endif -{ - PSCCB currSCCB; - UCHAR status_byte; - - currSCCB = BL_Card[p_card].currentSCCB; - - status_byte = RD_HARPOON(p_port+hp_gp_reg_0); - - sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = FALSE; - - if (status_byte != SSGOOD) { - - if (status_byte == SSQ_FULL) { - - - if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE; - if(BL_Card[p_card].discQCount != 0) - BL_Card[p_card].discQCount--; - BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL; - } - else - { - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE; - if(currSCCB->Sccb_tag) - { - if(BL_Card[p_card].discQCount != 0) - BL_Card[p_card].discQCount--; - BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL; - }else - { - if(BL_Card[p_card].discQCount != 0) - BL_Card[p_card].discQCount--; - BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL; - } - } - - currSCCB->Sccb_MGRFlags |= F_STATUSLOADED; - - queueSelectFail(&BL_Card[p_card],p_card); - - return; - } - - if(currSCCB->Sccb_scsistat == SELECT_SN_ST) - { - sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= - (UCHAR)SYNC_SUPPORTED; - - sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK; - BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; - - if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE; - if(BL_Card[p_card].discQCount != 0) - BL_Card[p_card].discQCount--; - BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL; - } - else - { - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE; - if(currSCCB->Sccb_tag) - { - if(BL_Card[p_card].discQCount != 0) - BL_Card[p_card].discQCount--; - BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL; - }else - { - if(BL_Card[p_card].discQCount != 0) - BL_Card[p_card].discQCount--; - BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL; - } - } - return; - - } - - if(currSCCB->Sccb_scsistat == SELECT_WN_ST) - { - - sccbMgrTbl[p_card][currSCCB->TargID].TarStatus = - (sccbMgrTbl[p_card][currSCCB->TargID]. - TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED; - - sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_WIDE_SCSI; - BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; - - if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE; - if(BL_Card[p_card].discQCount != 0) - BL_Card[p_card].discQCount--; - BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL; - } - else - { - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE; - if(currSCCB->Sccb_tag) - { - if(BL_Card[p_card].discQCount != 0) - BL_Card[p_card].discQCount--; - BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL; - }else - { - if(BL_Card[p_card].discQCount != 0) - BL_Card[p_card].discQCount--; - BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL; - } - } - return; - - } - - if (status_byte == SSCHECK) - { - if(BL_Card[p_card].globalFlags & F_DO_RENEGO) - { - if (sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue & EE_SYNC_MASK) - { - sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_SYNC_MASK; - } - if (sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue & EE_WIDE_SCSI) - { - sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_WIDE_MASK; - } - } - } - - if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) { - - currSCCB->SccbStatus = SCCB_ERROR; - currSCCB->TargetStatus = status_byte; - - if (status_byte == SSCHECK) { - - sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA - = TRUE; - - -#if (FW_TYPE==_SCCB_MGR_) - if (currSCCB->RequestSenseLength != NO_AUTO_REQUEST_SENSE) { - - if (currSCCB->RequestSenseLength == 0) - currSCCB->RequestSenseLength = 14; - - ssenss(&BL_Card[p_card]); - BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; - - if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE; - if(BL_Card[p_card].discQCount != 0) - BL_Card[p_card].discQCount--; - BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL; - } - else - { - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE; - if(currSCCB->Sccb_tag) - { - if(BL_Card[p_card].discQCount != 0) - BL_Card[p_card].discQCount--; - BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL; - }else - { - if(BL_Card[p_card].discQCount != 0) - BL_Card[p_card].discQCount--; - BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL; - } - } - return; - } -#else - if ((!(currSCCB->Sccb_ucb_ptr->UCB_opcode & OPC_NO_AUTO_SENSE)) && - (currSCCB->RequestSenseLength)) - { - ssenss(&BL_Card[p_card]); - BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; - - if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE; - if(BL_Card[p_card].discQCount != 0) - BL_Card[p_card].discQCount--; - BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL; - } - else - { - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE; - if(currSCCB->Sccb_tag) - { - if(BL_Card[p_card].discQCount != 0) - BL_Card[p_card].discQCount--; - BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL; - }else - { - if(BL_Card[p_card].discQCount != 0) - BL_Card[p_card].discQCount--; - BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL; - } - } - return; - } - -#endif - } - } - } - - - if((BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE; - else - sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE; - - - queueCmdComplete(&BL_Card[p_card], currSCCB, p_card); -} -#ident "$Id: busmstr.c 1.8 1997/01/31 02:10:27 mohan Exp $" -/*---------------------------------------------------------------------- - * - * - * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved - * - * This file is available under both the GNU General Public License - * and a BSD-style copyright; see LICENSE.FlashPoint for details. - * - * $Workfile: busmstr.c $ - * - * Description: Functions to start, stop, and abort BusMaster operations. - * - * $Date: 1997/01/31 02:10:27 $ - * - * $Revision: 1.8 $ - * - *----------------------------------------------------------------------*/ - -/*#include */ - -#if (FW_TYPE==_UCB_MGR_) - /*#include */ -#endif - -/*#include */ -/*#include */ -/*#include */ -/*#include */ -/*#include */ - - -/* -extern SCCBCARD BL_Card[MAX_CARDS]; -extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR]; -*/ - -#define SHORT_WAIT 0x0000000F -#define LONG_WAIT 0x0000FFFFL - -#if defined(BUGBUG) -void Debug_Load(UCHAR p_card, UCHAR p_bug_data); -#endif - -/*--------------------------------------------------------------------- - * - * Function: Data Transfer Processor - * - * Description: This routine performs two tasks. - * (1) Start data transfer by calling HOST_DATA_XFER_START - * function. Once data transfer is started, (2) Depends - * on the type of data transfer mode Scatter/Gather mode - * or NON Scatter/Gather mode. In NON Scatter/Gather mode, - * this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for - * data transfer done. In Scatter/Gather mode, this routine - * checks bus master command complete and dual rank busy - * bit to keep chaining SC transfer command. Similarly, - * in Scatter/Gather mode, it checks Sccb_MGRFlag - * (F_HOST_XFER_ACT bit) for data transfer done. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void dataXferProcessor(USHORT port, PSCCBcard pCurrCard) -#else -void dataXferProcessor(ULONG port, PSCCBcard pCurrCard) -#endif -{ - PSCCB currSCCB; - - currSCCB = pCurrCard->currentSCCB; - - if (currSCCB->Sccb_XferState & F_SG_XFER) - { - if (pCurrCard->globalFlags & F_HOST_XFER_ACT) - - { - currSCCB->Sccb_sgseg += (UCHAR)SG_BUF_CNT; - currSCCB->Sccb_SGoffset = 0x00; - } - pCurrCard->globalFlags |= F_HOST_XFER_ACT; - - busMstrSGDataXferStart(port, currSCCB); - } - - else - { - if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) - { - pCurrCard->globalFlags |= F_HOST_XFER_ACT; - - busMstrDataXferStart(port, currSCCB); - } - } -} - - -/*--------------------------------------------------------------------- - * - * Function: BusMaster Scatter Gather Data Transfer Start - * - * Description: - * - *---------------------------------------------------------------------*/ -#if defined(DOS) -void busMstrSGDataXferStart(USHORT p_port, PSCCB pcurrSCCB) -#else -void busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB) -#endif -{ - ULONG count,addr,tmpSGCnt; - UINT sg_index; - UCHAR sg_count, i; -#if defined(DOS) - USHORT reg_offset; -#else - ULONG reg_offset; -#endif - - - if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) { - - count = ((ULONG) HOST_RD_CMD)<<24; - } - - else { - count = ((ULONG) HOST_WRT_CMD)<<24; - } - - sg_count = 0; - tmpSGCnt = 0; - sg_index = pcurrSCCB->Sccb_sgseg; - reg_offset = hp_aramBase; - - - i = (UCHAR) (RD_HARPOON(p_port+hp_page_ctrl) & ~(SGRAM_ARAM|SCATTER_EN)); - - - WR_HARPOON(p_port+hp_page_ctrl, i); - - while ((sg_count < (UCHAR)SG_BUF_CNT) && - ((ULONG)(sg_index * (UINT)SG_ELEMENT_SIZE) < pcurrSCCB->DataLength) ) { - -#if defined(COMPILER_16_BIT) && !defined(DOS) - tmpSGCnt += *(((ULONG far *)pcurrSCCB->DataPointer)+ - (sg_index * 2)); - - count |= *(((ULONG far *)pcurrSCCB->DataPointer)+ - (sg_index * 2)); - - addr = *(((ULONG far *)pcurrSCCB->DataPointer)+ - ((sg_index * 2) + 1)); - -#else - tmpSGCnt += *(((ULONG *)pcurrSCCB->DataPointer)+ - (sg_index * 2)); - - count |= *(((ULONG *)pcurrSCCB->DataPointer)+ - (sg_index * 2)); - - addr = *(((ULONG *)pcurrSCCB->DataPointer)+ - ((sg_index * 2) + 1)); -#endif - - - if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) { - - addr += ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset); - count = (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset; - - tmpSGCnt = count & 0x00FFFFFFL; - } - - WR_HARP32(p_port,reg_offset,addr); - reg_offset +=4; - - WR_HARP32(p_port,reg_offset,count); - reg_offset +=4; - - count &= 0xFF000000L; - sg_index++; - sg_count++; - - } /*End While */ - - pcurrSCCB->Sccb_XferCnt = tmpSGCnt; - - WR_HARPOON(p_port+hp_sg_addr,(sg_count<<4)); - - if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) { - - WR_HARP32(p_port,hp_xfercnt_0,tmpSGCnt); - - - WR_HARPOON(p_port+hp_portctrl_0,(DMA_PORT | SCSI_PORT | SCSI_INBIT)); - WR_HARPOON(p_port+hp_scsisig, S_DATAI_PH); - } - - else { - - - if ((!(RD_HARPOON(p_port+hp_synctarg_0) & NARROW_SCSI)) && - (tmpSGCnt & 0x000000001)) - { - - pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT; - tmpSGCnt--; - } - - - WR_HARP32(p_port,hp_xfercnt_0,tmpSGCnt); - - WR_HARPOON(p_port+hp_portctrl_0,(SCSI_PORT | DMA_PORT | DMA_RD)); - WR_HARPOON(p_port+hp_scsisig, S_DATAO_PH); - } - - - WR_HARPOON(p_port+hp_page_ctrl, (UCHAR) (i | SCATTER_EN)); - -} - - -/*--------------------------------------------------------------------- - * - * Function: BusMaster Data Transfer Start - * - * Description: - * - *---------------------------------------------------------------------*/ -#if defined(DOS) -void busMstrDataXferStart(USHORT p_port, PSCCB pcurrSCCB) -#else -void busMstrDataXferStart(ULONG p_port, PSCCB pcurrSCCB) -#endif -{ - ULONG addr,count; - - if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) { - - count = pcurrSCCB->Sccb_XferCnt; - - addr = (ULONG) pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC; - } - - else { - addr = pcurrSCCB->SensePointer; - count = pcurrSCCB->RequestSenseLength; - - } - -#if defined(DOS) - asm { mov dx,p_port; - mov ax,word ptr count; - add dx,hp_xfer_cnt_lo; - out dx,al; - inc dx; - xchg ah,al - out dx,al; - inc dx; - mov ax,word ptr count+2; - out dx,al; - inc dx; - inc dx; - mov ax,word ptr addr; - out dx,al; - inc dx; - xchg ah,al - out dx,al; - inc dx; - mov ax,word ptr addr+2; - out dx,al; - inc dx; - xchg ah,al - out dx,al; - } - - WR_HARP32(p_port,hp_xfercnt_0,count); - -#else - HP_SETUP_ADDR_CNT(p_port,addr,count); -#endif - - - if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) { - - WR_HARPOON(p_port+hp_portctrl_0,(DMA_PORT | SCSI_PORT | SCSI_INBIT)); - WR_HARPOON(p_port+hp_scsisig, S_DATAI_PH); - - WR_HARPOON(p_port+hp_xfer_cmd, - (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT)); - } - - else { - - WR_HARPOON(p_port+hp_portctrl_0,(SCSI_PORT | DMA_PORT | DMA_RD)); - WR_HARPOON(p_port+hp_scsisig, S_DATAO_PH); - - WR_HARPOON(p_port+hp_xfer_cmd, - (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT)); - - } -} - - -/*--------------------------------------------------------------------- - * - * Function: BusMaster Timeout Handler - * - * Description: This function is called after a bus master command busy time - * out is detected. This routines issue halt state machine - * with a software time out for command busy. If command busy - * is still asserted at the end of the time out, it issues - * hard abort with another software time out. It hard abort - * command busy is also time out, it'll just give up. - * - *---------------------------------------------------------------------*/ -#if defined(DOS) -UCHAR busMstrTimeOut(USHORT p_port) -#else -UCHAR busMstrTimeOut(ULONG p_port) -#endif -{ - ULONG timeout; - - timeout = LONG_WAIT; - - WR_HARPOON(p_port+hp_sys_ctrl, HALT_MACH); - - while ((!(RD_HARPOON(p_port+hp_ext_status) & CMD_ABORTED)) && timeout--) {} - - - - if (RD_HARPOON(p_port+hp_ext_status) & BM_CMD_BUSY) { - WR_HARPOON(p_port+hp_sys_ctrl, HARD_ABORT); - - timeout = LONG_WAIT; - while ((RD_HARPOON(p_port+hp_ext_status) & BM_CMD_BUSY) && timeout--) {} - } - - RD_HARPOON(p_port+hp_int_status); /*Clear command complete */ - - if (RD_HARPOON(p_port+hp_ext_status) & BM_CMD_BUSY) { - return(TRUE); - } - - else { - return(FALSE); - } -} - - -/*--------------------------------------------------------------------- - * - * Function: Host Data Transfer Abort - * - * Description: Abort any in progress transfer. - * - *---------------------------------------------------------------------*/ -#if defined(DOS) -void hostDataXferAbort(USHORT port, UCHAR p_card, PSCCB pCurrSCCB) -#else -void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB) -#endif -{ - - ULONG timeout; - ULONG remain_cnt; - UINT sg_ptr; - - BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT; - - if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) { - - - if (!(RD_HARPOON(port+hp_int_status) & INT_CMD_COMPL)) { - - WR_HARPOON(port+hp_bm_ctrl, (RD_HARPOON(port+hp_bm_ctrl) | FLUSH_XFER_CNTR)); - timeout = LONG_WAIT; - - while ((RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) && timeout--) {} - - WR_HARPOON(port+hp_bm_ctrl, (RD_HARPOON(port+hp_bm_ctrl) & ~FLUSH_XFER_CNTR)); - - if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { - - if (busMstrTimeOut(port)) { - - if (pCurrSCCB->HostStatus == 0x00) - - pCurrSCCB->HostStatus = SCCB_BM_ERR; - - } - - if (RD_HARPOON(port+hp_int_status) & INT_EXT_STATUS) - - if (RD_HARPOON(port+hp_ext_status) & BAD_EXT_STATUS) - - if (pCurrSCCB->HostStatus == 0x00) - - { - pCurrSCCB->HostStatus = SCCB_BM_ERR; -#if defined(BUGBUG) - WR_HARPOON(port+hp_dual_addr_lo, - RD_HARPOON(port+hp_ext_status)); -#endif - } - } - } - } - - else if (pCurrSCCB->Sccb_XferCnt) { - - if (pCurrSCCB->Sccb_XferState & F_SG_XFER) { - - - WR_HARPOON(port+hp_page_ctrl, (RD_HARPOON(port+hp_page_ctrl) & - ~SCATTER_EN)); - - WR_HARPOON(port+hp_sg_addr,0x00); - - sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT; - - if (sg_ptr > (UINT)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE)) { - - sg_ptr = (UINT)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE); - } - - remain_cnt = pCurrSCCB->Sccb_XferCnt; - - while (remain_cnt < 0x01000000L) { - - sg_ptr--; - -#if defined(COMPILER_16_BIT) && !defined(DOS) - if (remain_cnt > (ULONG)(*(((ULONG far *)pCurrSCCB-> - DataPointer) + (sg_ptr * 2)))) { - - remain_cnt -= (ULONG)(*(((ULONG far *)pCurrSCCB-> - DataPointer) + (sg_ptr * 2))); - } - -#else - if (remain_cnt > (ULONG)(*(((ULONG *)pCurrSCCB-> - DataPointer) + (sg_ptr * 2)))) { - - remain_cnt -= (ULONG)(*(((ULONG *)pCurrSCCB-> - DataPointer) + (sg_ptr * 2))); - } -#endif - - else { - - break; - } - } - - - - if (remain_cnt < 0x01000000L) { - - - pCurrSCCB->Sccb_SGoffset = remain_cnt; - - pCurrSCCB->Sccb_sgseg = (USHORT)sg_ptr; - - - if ((ULONG)(sg_ptr * SG_ELEMENT_SIZE) == pCurrSCCB->DataLength - && (remain_cnt == 0)) - - pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED; - } - - else { - - - if (pCurrSCCB->HostStatus == 0x00) { - - pCurrSCCB->HostStatus = SCCB_GROSS_FW_ERR; - } - } - } - - - if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) { - - - if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { - - busMstrTimeOut(port); - } - - else { - - if (RD_HARPOON(port+hp_int_status) & INT_EXT_STATUS) { - - if (RD_HARPOON(port+hp_ext_status) & BAD_EXT_STATUS) { - - if (pCurrSCCB->HostStatus == 0x00) { - - pCurrSCCB->HostStatus = SCCB_BM_ERR; -#if defined(BUGBUG) - WR_HARPOON(port+hp_dual_addr_lo, - RD_HARPOON(port+hp_ext_status)); -#endif - } - } - } - - } - } - - else { - - - if ((RD_HARPOON(port+hp_fifo_cnt)) >= BM_THRESHOLD) { - - timeout = SHORT_WAIT; - - while ((RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) && - ((RD_HARPOON(port+hp_fifo_cnt)) >= BM_THRESHOLD) && - timeout--) {} - } - - if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { - - WR_HARPOON(port+hp_bm_ctrl, (RD_HARPOON(port+hp_bm_ctrl) | - FLUSH_XFER_CNTR)); - - timeout = LONG_WAIT; - - while ((RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) && - timeout--) {} - - WR_HARPOON(port+hp_bm_ctrl, (RD_HARPOON(port+hp_bm_ctrl) & - ~FLUSH_XFER_CNTR)); - - - if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { - - if (pCurrSCCB->HostStatus == 0x00) { - - pCurrSCCB->HostStatus = SCCB_BM_ERR; - } - - busMstrTimeOut(port); - } - } - - if (RD_HARPOON(port+hp_int_status) & INT_EXT_STATUS) { - - if (RD_HARPOON(port+hp_ext_status) & BAD_EXT_STATUS) { - - if (pCurrSCCB->HostStatus == 0x00) { - - pCurrSCCB->HostStatus = SCCB_BM_ERR; -#if defined(BUGBUG) - WR_HARPOON(port+hp_dual_addr_lo, - RD_HARPOON(port+hp_ext_status)); -#endif - } - } - } - } - - } - - else { - - - if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { - - timeout = LONG_WAIT; - - while ((RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) && timeout--) {} - - if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { - - if (pCurrSCCB->HostStatus == 0x00) { - - pCurrSCCB->HostStatus = SCCB_BM_ERR; - } - - busMstrTimeOut(port); - } - } - - - if (RD_HARPOON(port+hp_int_status) & INT_EXT_STATUS) { - - if (RD_HARPOON(port+hp_ext_status) & BAD_EXT_STATUS) { - - if (pCurrSCCB->HostStatus == 0x00) { - - pCurrSCCB->HostStatus = SCCB_BM_ERR; -#if defined(BUGBUG) - WR_HARPOON(port+hp_dual_addr_lo, - RD_HARPOON(port+hp_ext_status)); -#endif - } - } - - } - - if (pCurrSCCB->Sccb_XferState & F_SG_XFER) { - - WR_HARPOON(port+hp_page_ctrl, (RD_HARPOON(port+hp_page_ctrl) & - ~SCATTER_EN)); - - WR_HARPOON(port+hp_sg_addr,0x00); - - pCurrSCCB->Sccb_sgseg += SG_BUF_CNT; - - pCurrSCCB->Sccb_SGoffset = 0x00; - - - if ((ULONG)(pCurrSCCB->Sccb_sgseg * SG_ELEMENT_SIZE) >= - pCurrSCCB->DataLength) { - - pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED; - - pCurrSCCB->Sccb_sgseg = (USHORT)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE); - - } - } - - else { - - if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE)) - - pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED; - } - } - - WR_HARPOON(port+hp_int_mask,(INT_CMD_COMPL | SCSI_INTERRUPT)); -} - - - -/*--------------------------------------------------------------------- - * - * Function: Host Data Transfer Restart - * - * Description: Reset the available count due to a restore data - * pointers message. - * - *---------------------------------------------------------------------*/ -void hostDataXferRestart(PSCCB currSCCB) -{ - ULONG data_count; - UINT sg_index; -#if defined(COMPILER_16_BIT) && !defined(DOS) - ULONG far *sg_ptr; -#else - ULONG *sg_ptr; -#endif - - if (currSCCB->Sccb_XferState & F_SG_XFER) { - - currSCCB->Sccb_XferCnt = 0; - - sg_index = 0xffff; /*Index by long words into sg list. */ - data_count = 0; /*Running count of SG xfer counts. */ - -#if defined(COMPILER_16_BIT) && !defined(DOS) - sg_ptr = (ULONG far *)currSCCB->DataPointer; -#else - sg_ptr = (ULONG *)currSCCB->DataPointer; -#endif - - while (data_count < currSCCB->Sccb_ATC) { - - sg_index++; - data_count += *(sg_ptr+(sg_index * 2)); - } - - if (data_count == currSCCB->Sccb_ATC) { - - currSCCB->Sccb_SGoffset = 0; - sg_index++; - } - - else { - currSCCB->Sccb_SGoffset = data_count - currSCCB->Sccb_ATC; - } - - currSCCB->Sccb_sgseg = (USHORT)sg_index; - } - - else { - currSCCB->Sccb_XferCnt = currSCCB->DataLength - currSCCB->Sccb_ATC; - } -} -#ident "$Id: scam.c 1.17 1997/03/20 23:49:37 mohan Exp $" -/*---------------------------------------------------------------------- - * - * - * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved - * - * This file is available under both the GNU General Public License - * and a BSD-style copyright; see LICENSE.FlashPoint for details. - * - * $Workfile: scam.c $ - * - * Description: Functions relating to handling of the SCAM selection - * and the determination of the SCSI IDs to be assigned - * to all perspective SCSI targets. - * - * $Date: 1997/03/20 23:49:37 $ - * - * $Revision: 1.17 $ - * - *----------------------------------------------------------------------*/ - -/*#include */ - -#if (FW_TYPE==_UCB_MGR_) - /*#include */ -#endif - -/*#include */ -/*#include */ -/*#include */ -/*#include */ -/*#include */ -/*#include */ - - - -/* -extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR]; -extern SCCBCARD BL_Card[MAX_CARDS]; -extern SCCBSCAM_INFO scamInfo[MAX_SCSI_TAR]; -extern NVRAMINFO nvRamInfo[MAX_MB_CARDS]; -#if defined(DOS) || defined(OS2) -extern UCHAR temp_id_string[ID_STRING_LENGTH]; -#endif -extern UCHAR scamHAString[]; -*/ -/*--------------------------------------------------------------------- - * - * Function: scini - * - * Description: Setup all data structures necessary for SCAM selection. - * - *---------------------------------------------------------------------*/ - -void scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up) -{ - -#if defined(SCAM_LEV_2) - UCHAR loser,assigned_id; -#endif -#if defined(DOS) - - USHORT p_port; -#else - ULONG p_port; -#endif - - UCHAR i,k,ScamFlg ; - PSCCBcard currCard; - PNVRamInfo pCurrNvRam; - - currCard = &BL_Card[p_card]; - p_port = currCard->ioPort; - pCurrNvRam = currCard->pNvRamInfo; - - - if(pCurrNvRam){ - ScamFlg = pCurrNvRam->niScamConf; - i = pCurrNvRam->niSysConf; - } - else{ - ScamFlg = (UCHAR) utilEERead(p_port, SCAM_CONFIG/2); - i = (UCHAR)(utilEERead(p_port, (SYSTEM_CONFIG/2))); - } - if(!(i & 0x02)) /* check if reset bus in AutoSCSI parameter set */ - return; - - inisci(p_card,p_port, p_our_id); - - /* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW - too slow to return to SCAM selection */ - - /* if (p_power_up) - Wait1Second(p_port); - else - Wait(p_port, TO_250ms); */ - - Wait1Second(p_port); - -#if defined(SCAM_LEV_2) - - if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) - { - while (!(scarb(p_port,INIT_SELTD))) {} - - scsel(p_port); - - do { - scxferc(p_port,SYNC_PTRN); - scxferc(p_port,DOM_MSTR); - loser = scsendi(p_port,&scamInfo[p_our_id].id_string[0]); - } while ( loser == 0xFF ); - - scbusf(p_port); - - if ((p_power_up) && (!loser)) - { - sresb(p_port,p_card); - Wait(p_port, TO_250ms); - - while (!(scarb(p_port,INIT_SELTD))) {} - - scsel(p_port); - - do { - scxferc(p_port, SYNC_PTRN); - scxferc(p_port, DOM_MSTR); - loser = scsendi(p_port,&scamInfo[p_our_id]. - id_string[0]); - } while ( loser == 0xFF ); - - scbusf(p_port); - } - } - - else - { - loser = FALSE; - } - - - if (!loser) - { - -#endif /* SCAM_LEV_2 */ - - scamInfo[p_our_id].state = ID_ASSIGNED; - - - if (ScamFlg & SCAM_ENABLED) - { - - for (i=0; i < MAX_SCSI_TAR; i++) - { - if ((scamInfo[i].state == ID_UNASSIGNED) || - (scamInfo[i].state == ID_UNUSED)) - { - if (scsell(p_port,i)) - { - scamInfo[i].state = LEGACY; - if ((scamInfo[i].id_string[0] != 0xFF) || - (scamInfo[i].id_string[1] != 0xFA)) - { - - scamInfo[i].id_string[0] = 0xFF; - scamInfo[i].id_string[1] = 0xFA; - if(pCurrNvRam == NULL) - currCard->globalFlags |= F_UPDATE_EEPROM; - } - } - } - } - - sresb(p_port,p_card); - Wait1Second(p_port); - while (!(scarb(p_port,INIT_SELTD))) {} - scsel(p_port); - scasid(p_card, p_port); - } - -#if defined(SCAM_LEV_2) - - } - - else if ((loser) && (ScamFlg & SCAM_ENABLED)) - { - scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0; - assigned_id = FALSE; - scwtsel(p_port); - - do { - while (scxferc(p_port,0x00) != SYNC_PTRN) {} - - i = scxferc(p_port,0x00); - if (i == ASSIGN_ID) - { - if (!(scsendi(p_port,&scamInfo[p_our_id].id_string[0]))) - { - i = scxferc(p_port,0x00); - if (scvalq(i)) - { - k = scxferc(p_port,0x00); - - if (scvalq(k)) - { - currCard->ourId = - ((UCHAR)(i<<3)+(k & (UCHAR)7)) & (UCHAR) 0x3F; - inisci(p_card, p_port, p_our_id); - scamInfo[currCard->ourId].state = ID_ASSIGNED; - scamInfo[currCard->ourId].id_string[0] - = SLV_TYPE_CODE0; - assigned_id = TRUE; - } - } - } - } - - else if (i == SET_P_FLAG) - { - if (!(scsendi(p_port, - &scamInfo[p_our_id].id_string[0]))) - scamInfo[p_our_id].id_string[0] |= 0x80; - } - }while (!assigned_id); - - while (scxferc(p_port,0x00) != CFG_CMPLT) {} - } - -#endif /* SCAM_LEV_2 */ - if (ScamFlg & SCAM_ENABLED) - { - scbusf(p_port); - if (currCard->globalFlags & F_UPDATE_EEPROM) - { - scsavdi(p_card, p_port); - currCard->globalFlags &= ~F_UPDATE_EEPROM; - } - } - - -#if defined(DOS) - for (i=0; i < MAX_SCSI_TAR; i++) - { - if (((ScamFlg & SCAM_ENABLED) && (scamInfo[i].state == LEGACY)) - || (i != p_our_id)) - { - scsellDOS(p_port,i); - } - } -#endif - -/* - for (i=0,k=0; i < MAX_SCSI_TAR; i++) - { - if ((scamInfo[i].state == ID_ASSIGNED) || - (scamInfo[i].state == LEGACY)) - k++; - } - - if (k==2) - currCard->globalFlags |= F_SINGLE_DEVICE; - else - currCard->globalFlags &= ~F_SINGLE_DEVICE; -*/ -} - - -/*--------------------------------------------------------------------- - * - * Function: scarb - * - * Description: Gain control of the bus and wait SCAM select time (250ms) - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -int scarb(USHORT p_port, UCHAR p_sel_type) -#else -int scarb(ULONG p_port, UCHAR p_sel_type) -#endif -{ - if (p_sel_type == INIT_SELTD) - { - - while (RD_HARPOON(p_port+hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {} - - - if (RD_HARPOON(p_port+hp_scsisig) & SCSI_SEL) - return(FALSE); - - if (RD_HARPOON(p_port+hp_scsidata_0) != 00) - return(FALSE); - - WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) | SCSI_BSY)); - - if (RD_HARPOON(p_port+hp_scsisig) & SCSI_SEL) { - - WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) & - ~SCSI_BSY)); - return(FALSE); - } - - - WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) | SCSI_SEL)); - - if (RD_HARPOON(p_port+hp_scsidata_0) != 00) { - - WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) & - ~(SCSI_BSY | SCSI_SEL))); - return(FALSE); - } - } - - - WR_HARPOON(p_port+hp_clkctrl_0, (RD_HARPOON(p_port+hp_clkctrl_0) - & ~ACTdeassert)); - WR_HARPOON(p_port+hp_scsireset, SCAM_EN); - WR_HARPOON(p_port+hp_scsidata_0, 0x00); -#if defined(WIDE_SCSI) - WR_HARPOON(p_port+hp_scsidata_1, 0x00); -#endif - WR_HARPOON(p_port+hp_portctrl_0, SCSI_BUS_EN); - - WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) | SCSI_MSG)); - - WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) - & ~SCSI_BSY)); - - Wait(p_port,TO_250ms); - - return(TRUE); -} - - -/*--------------------------------------------------------------------- - * - * Function: scbusf - * - * Description: Release the SCSI bus and disable SCAM selection. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void scbusf(USHORT p_port) -#else -void scbusf(ULONG p_port) -#endif -{ - WR_HARPOON(p_port+hp_page_ctrl, - (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)); - - - WR_HARPOON(p_port+hp_scsidata_0, 0x00); - - WR_HARPOON(p_port+hp_portctrl_0, (RD_HARPOON(p_port+hp_portctrl_0) - & ~SCSI_BUS_EN)); - - WR_HARPOON(p_port+hp_scsisig, 0x00); - - - WR_HARPOON(p_port+hp_scsireset, (RD_HARPOON(p_port+hp_scsireset) - & ~SCAM_EN)); - - WR_HARPOON(p_port+hp_clkctrl_0, (RD_HARPOON(p_port+hp_clkctrl_0) - | ACTdeassert)); - -#if defined(SCAM_LEV_2) - WRW_HARPOON((p_port+hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL)); -#else - WRW_HARPOON((p_port+hp_intstat), (BUS_FREE | AUTO_INT)); -#endif - - WR_HARPOON(p_port+hp_page_ctrl, - (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)); -} - - - -/*--------------------------------------------------------------------- - * - * Function: scasid - * - * Description: Assign an ID to all the SCAM devices. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void scasid(UCHAR p_card, USHORT p_port) -#else -void scasid(UCHAR p_card, ULONG p_port) -#endif -{ -#if defined(DOS) || defined(OS2) - /* Use external defined in global space area, instead of Stack - space. WIN/95 DOS doesnot work TINY mode. The OS doesnot intialize - SS equal to DS. Thus the array allocated on stack doesnot get - access correctly */ -#else - UCHAR temp_id_string[ID_STRING_LENGTH]; -#endif - - UCHAR i,k,scam_id; - UCHAR crcBytes[3]; - PNVRamInfo pCurrNvRam; - ushort_ptr pCrcBytes; - - pCurrNvRam = BL_Card[p_card].pNvRamInfo; - - i=FALSE; - - while (!i) - { - - for (k=0; k < ID_STRING_LENGTH; k++) - { - temp_id_string[k] = (UCHAR) 0x00; - } - - scxferc(p_port,SYNC_PTRN); - scxferc(p_port,ASSIGN_ID); - - if (!(sciso(p_port,&temp_id_string[0]))) - { - if(pCurrNvRam){ - pCrcBytes = (ushort_ptr)&crcBytes[0]; - *pCrcBytes = CalcCrc16(&temp_id_string[0]); - crcBytes[2] = CalcLrc(&temp_id_string[0]); - temp_id_string[1] = crcBytes[2]; - temp_id_string[2] = crcBytes[0]; - temp_id_string[3] = crcBytes[1]; - for(k = 4; k < ID_STRING_LENGTH; k++) - temp_id_string[k] = (UCHAR) 0x00; - } - i = scmachid(p_card,temp_id_string); - - if (i == CLR_PRIORITY) - { - scxferc(p_port,MISC_CODE); - scxferc(p_port,CLR_P_FLAG); - i = FALSE; /*Not the last ID yet. */ - } - - else if (i != NO_ID_AVAIL) - { - if (i < 8 ) - scxferc(p_port,ID_0_7); - else - scxferc(p_port,ID_8_F); - - scam_id = (i & (UCHAR) 0x07); - - - for (k=1; k < 0x08; k <<= 1) - if (!( k & i )) - scam_id += 0x08; /*Count number of zeros in DB0-3. */ - - scxferc(p_port,scam_id); - - i = FALSE; /*Not the last ID yet. */ - } - } - - else - { - i = TRUE; - } - - } /*End while */ - - scxferc(p_port,SYNC_PTRN); - scxferc(p_port,CFG_CMPLT); -} - - - - - -/*--------------------------------------------------------------------- - * - * Function: scsel - * - * Description: Select all the SCAM devices. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void scsel(USHORT p_port) -#else -void scsel(ULONG p_port) -#endif -{ - - WR_HARPOON(p_port+hp_scsisig, SCSI_SEL); - scwiros(p_port, SCSI_MSG); - - WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY)); - - - WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD)); - WR_HARPOON(p_port+hp_scsidata_0, (UCHAR)(RD_HARPOON(p_port+hp_scsidata_0) | - (UCHAR)(BIT(7)+BIT(6)))); - - - WR_HARPOON(p_port+hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD)); - scwiros(p_port, SCSI_SEL); - - WR_HARPOON(p_port+hp_scsidata_0, (UCHAR)(RD_HARPOON(p_port+hp_scsidata_0) & - ~(UCHAR)BIT(6))); - scwirod(p_port, BIT(6)); - - WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD)); -} - - - -/*--------------------------------------------------------------------- - * - * Function: scxferc - * - * Description: Handshake the p_data (DB4-0) across the bus. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -UCHAR scxferc(USHORT p_port, UCHAR p_data) -#else -UCHAR scxferc(ULONG p_port, UCHAR p_data) -#endif -{ - UCHAR curr_data, ret_data; - - curr_data = p_data | BIT(7) | BIT(5); /*Start with DB7 & DB5 asserted. */ - - WR_HARPOON(p_port+hp_scsidata_0, curr_data); - - curr_data &= ~BIT(7); - - WR_HARPOON(p_port+hp_scsidata_0, curr_data); - - scwirod(p_port,BIT(7)); /*Wait for DB7 to be released. */ - while (!(RD_HARPOON(p_port+hp_scsidata_0) & BIT(5))); - - ret_data = (RD_HARPOON(p_port+hp_scsidata_0) & (UCHAR) 0x1F); - - curr_data |= BIT(6); - - WR_HARPOON(p_port+hp_scsidata_0, curr_data); - - curr_data &= ~BIT(5); - - WR_HARPOON(p_port+hp_scsidata_0, curr_data); - - scwirod(p_port,BIT(5)); /*Wait for DB5 to be released. */ - - curr_data &= ~(BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0)); /*Release data bits */ - curr_data |= BIT(7); - - WR_HARPOON(p_port+hp_scsidata_0, curr_data); - - curr_data &= ~BIT(6); - - WR_HARPOON(p_port+hp_scsidata_0, curr_data); - - scwirod(p_port,BIT(6)); /*Wait for DB6 to be released. */ - - return(ret_data); -} - - -/*--------------------------------------------------------------------- - * - * Function: scsendi - * - * Description: Transfer our Identification string to determine if we - * will be the dominant master. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -UCHAR scsendi(USHORT p_port, UCHAR p_id_string[]) -#else -UCHAR scsendi(ULONG p_port, UCHAR p_id_string[]) -#endif -{ - UCHAR ret_data,byte_cnt,bit_cnt,defer; - - defer = FALSE; - - for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) { - - for (bit_cnt = 0x80; bit_cnt != 0 ; bit_cnt >>= 1) { - - if (defer) - ret_data = scxferc(p_port,00); - - else if (p_id_string[byte_cnt] & bit_cnt) - - ret_data = scxferc(p_port,02); - - else { - - ret_data = scxferc(p_port,01); - if (ret_data & 02) - defer = TRUE; - } - - if ((ret_data & 0x1C) == 0x10) - return(0x00); /*End of isolation stage, we won! */ - - if (ret_data & 0x1C) - return(0xFF); - - if ((defer) && (!(ret_data & 0x1F))) - return(0x01); /*End of isolation stage, we lost. */ - - } /*bit loop */ - - } /*byte loop */ - - if (defer) - return(0x01); /*We lost */ - else - return(0); /*We WON! Yeeessss! */ -} - - - -/*--------------------------------------------------------------------- - * - * Function: sciso - * - * Description: Transfer the Identification string. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -UCHAR sciso(USHORT p_port, UCHAR p_id_string[]) -#else -UCHAR sciso(ULONG p_port, UCHAR p_id_string[]) -#endif -{ - UCHAR ret_data,the_data,byte_cnt,bit_cnt; - - the_data = 0; - - for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) { - - for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) { - - ret_data = scxferc(p_port,0); - - if (ret_data & 0xFC) - return(0xFF); - - else { - - the_data <<= 1; - if (ret_data & BIT(1)) { - the_data |= 1; - } - } - - if ((ret_data & 0x1F) == 0) - { -/* - if(bit_cnt != 0 || bit_cnt != 8) - { - byte_cnt = 0; - bit_cnt = 0; - scxferc(p_port, SYNC_PTRN); - scxferc(p_port, ASSIGN_ID); - continue; - } -*/ - if (byte_cnt) - return(0x00); - else - return(0xFF); - } - - } /*bit loop */ - - p_id_string[byte_cnt] = the_data; - - } /*byte loop */ - - return(0); -} - - - -/*--------------------------------------------------------------------- - * - * Function: scwirod - * - * Description: Sample the SCSI data bus making sure the signal has been - * deasserted for the correct number of consecutive samples. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void scwirod(USHORT p_port, UCHAR p_data_bit) -#else -void scwirod(ULONG p_port, UCHAR p_data_bit) -#endif -{ - UCHAR i; - - i = 0; - while ( i < MAX_SCSI_TAR ) { - - if (RD_HARPOON(p_port+hp_scsidata_0) & p_data_bit) - - i = 0; - - else - - i++; - - } -} - - - -/*--------------------------------------------------------------------- - * - * Function: scwiros - * - * Description: Sample the SCSI Signal lines making sure the signal has been - * deasserted for the correct number of consecutive samples. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void scwiros(USHORT p_port, UCHAR p_data_bit) -#else -void scwiros(ULONG p_port, UCHAR p_data_bit) -#endif -{ - UCHAR i; - - i = 0; - while ( i < MAX_SCSI_TAR ) { - - if (RD_HARPOON(p_port+hp_scsisig) & p_data_bit) - - i = 0; - - else - - i++; - - } -} - - -/*--------------------------------------------------------------------- - * - * Function: scvalq - * - * Description: Make sure we received a valid data byte. - * - *---------------------------------------------------------------------*/ - -UCHAR scvalq(UCHAR p_quintet) -{ - UCHAR count; - - for (count=1; count < 0x08; count<<=1) { - if (!(p_quintet & count)) - p_quintet -= 0x80; - } - - if (p_quintet & 0x18) - return(FALSE); - - else - return(TRUE); -} - - -/*--------------------------------------------------------------------- - * - * Function: scsell - * - * Description: Select the specified device ID using a selection timeout - * less than 4ms. If somebody responds then it is a legacy - * drive and this ID must be marked as such. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -UCHAR scsell(USHORT p_port, UCHAR targ_id) -#else -UCHAR scsell(ULONG p_port, UCHAR targ_id) -#endif -{ -#if defined(DOS) - USHORT i; -#else - ULONG i; -#endif - - WR_HARPOON(p_port+hp_page_ctrl, - (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)); - - ARAM_ACCESS(p_port); - - WR_HARPOON(p_port+hp_addstat,(RD_HARPOON(p_port+hp_addstat) | SCAM_TIMER)); - WR_HARPOON(p_port+hp_seltimeout,TO_4ms); - - - for (i = p_port+CMD_STRT; i < p_port+CMD_STRT+12; i+=2) { - WRW_HARPOON(i, (MPM_OP+ACOMMAND)); - } - WRW_HARPOON(i, (BRH_OP+ALWAYS+ NP)); - - WRW_HARPOON((p_port+hp_intstat), - (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT)); - - WR_HARPOON(p_port+hp_select_id, targ_id); - - WR_HARPOON(p_port+hp_portctrl_0, SCSI_PORT); - WR_HARPOON(p_port+hp_autostart_3, (SELECT | CMD_ONLY_STRT)); - WR_HARPOON(p_port+hp_scsictrl_0, (SEL_TAR | ENA_RESEL)); - - - while (!(RDW_HARPOON((p_port+hp_intstat)) & - (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {} - - if (RDW_HARPOON((p_port+hp_intstat)) & RESET) - Wait(p_port, TO_250ms); - - DISABLE_AUTO(p_port); - - WR_HARPOON(p_port+hp_addstat,(RD_HARPOON(p_port+hp_addstat) & ~SCAM_TIMER)); - WR_HARPOON(p_port+hp_seltimeout,TO_290ms); - - SGRAM_ACCESS(p_port); - - if (RDW_HARPOON((p_port+hp_intstat)) & (RESET | TIMEOUT) ) { - - WRW_HARPOON((p_port+hp_intstat), - (RESET | TIMEOUT | SEL | BUS_FREE | PHASE)); - - WR_HARPOON(p_port+hp_page_ctrl, - (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)); - - return(FALSE); /*No legacy device */ - } - - else { - - while(!(RDW_HARPOON((p_port+hp_intstat)) & BUS_FREE)) { - if (RD_HARPOON(p_port+hp_scsisig) & SCSI_REQ) - { - WR_HARPOON(p_port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); - ACCEPT_MSG(p_port); - } - } - - WRW_HARPOON((p_port+hp_intstat), CLR_ALL_INT_1); - - WR_HARPOON(p_port+hp_page_ctrl, - (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)); - - return(TRUE); /*Found one of them oldies! */ - } -} - -#if defined(DOS) -/*--------------------------------------------------------------------- - * - * Function: scsell for DOS - * - * Description: Select the specified device ID using a selection timeout - * less than 2ms. This was specially required to solve - * the problem with Plextor 12X CD-ROM drive. This drive - * was responding the Selection at the end of 4ms and - * hanging the system. - * - *---------------------------------------------------------------------*/ - -UCHAR scsellDOS(USHORT p_port, UCHAR targ_id) -{ - USHORT i; - - WR_HARPOON(p_port+hp_page_ctrl, - (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)); - - ARAM_ACCESS(p_port); - - WR_HARPOON(p_port+hp_addstat,(RD_HARPOON(p_port+hp_addstat) | SCAM_TIMER)); - WR_HARPOON(p_port+hp_seltimeout,TO_2ms); - - - for (i = p_port+CMD_STRT; i < p_port+CMD_STRT+12; i+=2) { - WRW_HARPOON(i, (MPM_OP+ACOMMAND)); - } - WRW_HARPOON(i, (BRH_OP+ALWAYS+ NP)); - - WRW_HARPOON((p_port+hp_intstat), - (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT)); - - WR_HARPOON(p_port+hp_select_id, targ_id); - - WR_HARPOON(p_port+hp_portctrl_0, SCSI_PORT); - WR_HARPOON(p_port+hp_autostart_3, (SELECT | CMD_ONLY_STRT)); - WR_HARPOON(p_port+hp_scsictrl_0, (SEL_TAR | ENA_RESEL)); - - - while (!(RDW_HARPOON((p_port+hp_intstat)) & - (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {} - - if (RDW_HARPOON((p_port+hp_intstat)) & RESET) - Wait(p_port, TO_250ms); - - DISABLE_AUTO(p_port); - - WR_HARPOON(p_port+hp_addstat,(RD_HARPOON(p_port+hp_addstat) & ~SCAM_TIMER)); - WR_HARPOON(p_port+hp_seltimeout,TO_290ms); - - SGRAM_ACCESS(p_port); - - if (RDW_HARPOON((p_port+hp_intstat)) & (RESET | TIMEOUT) ) { - - WRW_HARPOON((p_port+hp_intstat), - (RESET | TIMEOUT | SEL | BUS_FREE | PHASE)); - - WR_HARPOON(p_port+hp_page_ctrl, - (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)); - - return(FALSE); /*No legacy device */ - } - - else { - - while(!(RDW_HARPOON((p_port+hp_intstat)) & BUS_FREE)) { - if (RD_HARPOON(p_port+hp_scsisig) & SCSI_REQ) - { - WR_HARPOON(p_port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); - ACCEPT_MSG(p_port); - } - } - - WRW_HARPOON((p_port+hp_intstat), CLR_ALL_INT_1); - - WR_HARPOON(p_port+hp_page_ctrl, - (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)); - - return(TRUE); /*Found one of them oldies! */ - } -} -#endif /* DOS */ - -/*--------------------------------------------------------------------- - * - * Function: scwtsel - * - * Description: Wait to be selected by another SCAM initiator. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void scwtsel(USHORT p_port) -#else -void scwtsel(ULONG p_port) -#endif -{ - while(!(RDW_HARPOON((p_port+hp_intstat)) & SCAM_SEL)) {} -} - - -/*--------------------------------------------------------------------- - * - * Function: inisci - * - * Description: Setup the data Structure with the info from the EEPROM. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void inisci(UCHAR p_card, USHORT p_port, UCHAR p_our_id) -#else -void inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id) -#endif -{ - UCHAR i,k,max_id; - USHORT ee_data; - PNVRamInfo pCurrNvRam; - - pCurrNvRam = BL_Card[p_card].pNvRamInfo; - - if (RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD) - max_id = 0x08; - - else - max_id = 0x10; - - if(pCurrNvRam){ - for(i = 0; i < max_id; i++){ - - for(k = 0; k < 4; k++) - scamInfo[i].id_string[k] = pCurrNvRam->niScamTbl[i][k]; - for(k = 4; k < ID_STRING_LENGTH; k++) - scamInfo[i].id_string[k] = (UCHAR) 0x00; - - if(scamInfo[i].id_string[0] == 0x00) - scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */ - else - scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */ - - } - }else { - for (i=0; i < max_id; i++) - { - for (k=0; k < ID_STRING_LENGTH; k+=2) - { - ee_data = utilEERead(p_port, (USHORT)((EE_SCAMBASE/2) + - (USHORT) (i*((USHORT)ID_STRING_LENGTH/2)) + (USHORT)(k/2))); - scamInfo[i].id_string[k] = (UCHAR) ee_data; - ee_data >>= 8; - scamInfo[i].id_string[k+1] = (UCHAR) ee_data; - } - - if ((scamInfo[i].id_string[0] == 0x00) || - (scamInfo[i].id_string[0] == 0xFF)) - - scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */ - - else - scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */ - - } - } - for(k = 0; k < ID_STRING_LENGTH; k++) - scamInfo[p_our_id].id_string[k] = scamHAString[k]; - -} - -/*--------------------------------------------------------------------- - * - * Function: scmachid - * - * Description: Match the Device ID string with our values stored in - * the EEPROM. - * - *---------------------------------------------------------------------*/ - -UCHAR scmachid(UCHAR p_card, UCHAR p_id_string[]) -{ - - UCHAR i,k,match; - - - for (i=0; i < MAX_SCSI_TAR; i++) { - -#if !defined(SCAM_LEV_2) - if (scamInfo[i].state == ID_UNASSIGNED) - { -#endif - match = TRUE; - - for (k=0; k < ID_STRING_LENGTH; k++) - { - if (p_id_string[k] != scamInfo[i].id_string[k]) - match = FALSE; - } - - if (match) - { - scamInfo[i].state = ID_ASSIGNED; - return(i); - } - -#if !defined(SCAM_LEV_2) - } -#endif - - } - - - - if (p_id_string[0] & BIT(5)) - i = 8; - else - i = MAX_SCSI_TAR; - - if (((p_id_string[0] & 0x06) == 0x02) || ((p_id_string[0] & 0x06) == 0x04)) - match = p_id_string[1] & (UCHAR) 0x1F; - else - match = 7; - - while (i > 0) - { - i--; - - if (scamInfo[match].state == ID_UNUSED) - { - for (k=0; k < ID_STRING_LENGTH; k++) - { - scamInfo[match].id_string[k] = p_id_string[k]; - } - - scamInfo[match].state = ID_ASSIGNED; - - if(BL_Card[p_card].pNvRamInfo == NULL) - BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM; - return(match); - - } - - - match--; - - if (match == 0xFF) - { - if (p_id_string[0] & BIT(5)) - match = 7; - else - match = MAX_SCSI_TAR-1; - } - } - - - - if (p_id_string[0] & BIT(7)) - { - return(CLR_PRIORITY); - } - - - if (p_id_string[0] & BIT(5)) - i = 8; - else - i = MAX_SCSI_TAR; - - if (((p_id_string[0] & 0x06) == 0x02) || ((p_id_string[0] & 0x06) == 0x04)) - match = p_id_string[1] & (UCHAR) 0x1F; - else - match = 7; - - while (i > 0) - { - - i--; - - if (scamInfo[match].state == ID_UNASSIGNED) - { - for (k=0; k < ID_STRING_LENGTH; k++) - { - scamInfo[match].id_string[k] = p_id_string[k]; - } - - scamInfo[match].id_string[0] |= BIT(7); - scamInfo[match].state = ID_ASSIGNED; - if(BL_Card[p_card].pNvRamInfo == NULL) - BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM; - return(match); - - } - - - match--; - - if (match == 0xFF) - { - if (p_id_string[0] & BIT(5)) - match = 7; - else - match = MAX_SCSI_TAR-1; - } - } - - return(NO_ID_AVAIL); -} - - -/*--------------------------------------------------------------------- - * - * Function: scsavdi - * - * Description: Save off the device SCAM ID strings. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void scsavdi(UCHAR p_card, USHORT p_port) -#else -void scsavdi(UCHAR p_card, ULONG p_port) -#endif -{ - UCHAR i,k,max_id; - USHORT ee_data,sum_data; - - - sum_data = 0x0000; - - for (i = 1; i < EE_SCAMBASE/2; i++) - { - sum_data += utilEERead(p_port, i); - } - - - utilEEWriteOnOff(p_port,1); /* Enable write access to the EEPROM */ - - if (RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD) - max_id = 0x08; - - else - max_id = 0x10; - - for (i=0; i < max_id; i++) - { - - for (k=0; k < ID_STRING_LENGTH; k+=2) - { - ee_data = scamInfo[i].id_string[k+1]; - ee_data <<= 8; - ee_data |= scamInfo[i].id_string[k]; - sum_data += ee_data; - utilEEWrite(p_port, ee_data, (USHORT)((EE_SCAMBASE/2) + - (USHORT)(i*((USHORT)ID_STRING_LENGTH/2)) + (USHORT)(k/2))); - } - } - - - utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM/2); - utilEEWriteOnOff(p_port,0); /* Turn off write access */ -} -#ident "$Id: diagnose.c 1.10 1997/06/10 16:51:47 mohan Exp $" -/*---------------------------------------------------------------------- - * - * - * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved - * - * This file is available under both the GNU General Public License - * and a BSD-style copyright; see LICENSE.FlashPoint for details. - * - * $Workfile: diagnose.c $ - * - * Description: Diagnostic funtions for testing the integrity of - * the HARPOON. - * - * $Date: 1997/06/10 16:51:47 $ - * - * $Revision: 1.10 $ - * - *----------------------------------------------------------------------*/ - -/*#include */ - -#if (FW_TYPE==_UCB_MGR_) - /*#include */ -#endif - -/*#include */ -/*#include */ -/*#include */ -/*#include */ -/*#include */ - -/*--------------------------------------------------------------------- - * - * Function: XbowInit - * - * Description: Setup the Xbow for normal operation. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void XbowInit(USHORT port, UCHAR ScamFlg) -#else -void XbowInit(ULONG port, UCHAR ScamFlg) -#endif -{ -UCHAR i; - - i = RD_HARPOON(port+hp_page_ctrl); - WR_HARPOON(port+hp_page_ctrl, (UCHAR) (i | G_INT_DISABLE)); - - WR_HARPOON(port+hp_scsireset,0x00); - WR_HARPOON(port+hp_portctrl_1,HOST_MODE8); - - WR_HARPOON(port+hp_scsireset,(DMA_RESET | HPSCSI_RESET | PROG_RESET | \ - FIFO_CLR)); - - WR_HARPOON(port+hp_scsireset,SCSI_INI); - - WR_HARPOON(port+hp_clkctrl_0,CLKCTRL_DEFAULT); - - WR_HARPOON(port+hp_scsisig,0x00); /* Clear any signals we might */ - WR_HARPOON(port+hp_scsictrl_0,ENA_SCAM_SEL); - - WRW_HARPOON((port+hp_intstat), CLR_ALL_INT); - -#if defined(SCAM_LEV_2) - default_intena = RESET | RSEL | PROG_HLT | TIMEOUT | - BUS_FREE | XFER_CNT_0 | AUTO_INT; - - if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) - default_intena |= SCAM_SEL; - -#else - default_intena = RESET | RSEL | PROG_HLT | TIMEOUT | - BUS_FREE | XFER_CNT_0 | AUTO_INT; -#endif - WRW_HARPOON((port+hp_intena), default_intena); - - WR_HARPOON(port+hp_seltimeout,TO_290ms); - - /* Turn on SCSI_MODE8 for narrow cards to fix the - strapping issue with the DUAL CHANNEL card */ - if (RD_HARPOON(port+hp_page_ctrl) & NARROW_SCSI_CARD) - WR_HARPOON(port+hp_addstat,SCSI_MODE8); - -#if defined(NO_BIOS_OPTION) - - WR_HARPOON(port+hp_synctarg_0,NARROW_SCSI); - WR_HARPOON(port+hp_synctarg_1,NARROW_SCSI); - WR_HARPOON(port+hp_synctarg_2,NARROW_SCSI); - WR_HARPOON(port+hp_synctarg_3,NARROW_SCSI); - WR_HARPOON(port+hp_synctarg_4,NARROW_SCSI); - WR_HARPOON(port+hp_synctarg_5,NARROW_SCSI); - WR_HARPOON(port+hp_synctarg_6,NARROW_SCSI); - WR_HARPOON(port+hp_synctarg_7,NARROW_SCSI); - WR_HARPOON(port+hp_synctarg_8,NARROW_SCSI); - WR_HARPOON(port+hp_synctarg_9,NARROW_SCSI); - WR_HARPOON(port+hp_synctarg_10,NARROW_SCSI); - WR_HARPOON(port+hp_synctarg_11,NARROW_SCSI); - WR_HARPOON(port+hp_synctarg_12,NARROW_SCSI); - WR_HARPOON(port+hp_synctarg_13,NARROW_SCSI); - WR_HARPOON(port+hp_synctarg_14,NARROW_SCSI); - WR_HARPOON(port+hp_synctarg_15,NARROW_SCSI); - -#endif - WR_HARPOON(port+hp_page_ctrl, i); - -} - - -/*--------------------------------------------------------------------- - * - * Function: BusMasterInit - * - * Description: Initialize the BusMaster for normal operations. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void BusMasterInit(USHORT p_port) -#else -void BusMasterInit(ULONG p_port) -#endif -{ - - - WR_HARPOON(p_port+hp_sys_ctrl, DRVR_RST); - WR_HARPOON(p_port+hp_sys_ctrl, 0x00); - - WR_HARPOON(p_port+hp_host_blk_cnt, XFER_BLK64); - - - WR_HARPOON(p_port+hp_bm_ctrl, (BMCTRL_DEFAULT)); - - WR_HARPOON(p_port+hp_ee_ctrl, (SCSI_TERM_ENA_H)); - - -#if defined(NT) - - WR_HARPOON(p_port+hp_pci_cmd_cfg, (RD_HARPOON(p_port+hp_pci_cmd_cfg) - & ~MEM_SPACE_ENA)); - -#endif - - RD_HARPOON(p_port+hp_int_status); /*Clear interrupts. */ - WR_HARPOON(p_port+hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT)); - WR_HARPOON(p_port+hp_page_ctrl, (RD_HARPOON(p_port+hp_page_ctrl) & - ~SCATTER_EN)); -} - - -/*--------------------------------------------------------------------- - * - * Function: DiagXbow - * - * Description: Test Xbow integrity. Non-zero return indicates an error. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -int DiagXbow(USHORT port) -#else -int DiagXbow(ULONG port) -#endif -{ - unsigned char fifo_cnt,loop_cnt; - - unsigned char fifodata[5]; - fifodata[0] = 0x00; - fifodata[1] = 0xFF; - fifodata[2] = 0x55; - fifodata[3] = 0xAA; - fifodata[4] = 0x00; - - - WRW_HARPOON((port+hp_intstat), CLR_ALL_INT); - WRW_HARPOON((port+hp_intena), 0x0000); - - WR_HARPOON(port+hp_seltimeout,TO_5ms); - - WR_HARPOON(port+hp_portctrl_0,START_TO); - - - for(fifodata[4] = 0x01; fifodata[4] != (UCHAR) 0; fifodata[4] = fifodata[4] << 1) { - - WR_HARPOON(port+hp_selfid_0,fifodata[4]); - WR_HARPOON(port+hp_selfid_1,fifodata[4]); - - if ((RD_HARPOON(port+hp_selfid_0) != fifodata[4]) || - (RD_HARPOON(port+hp_selfid_1) != fifodata[4])) - return(1); - } - - - for(loop_cnt = 0; loop_cnt < 4; loop_cnt++) { - - WR_HARPOON(port+hp_portctrl_0,(HOST_PORT | HOST_WRT | START_TO)); - - - for (fifo_cnt = 0; fifo_cnt < FIFO_LEN; fifo_cnt++) { - - WR_HARPOON(port+hp_fifodata_0, fifodata[loop_cnt]); - } - - - if (!(RD_HARPOON(port+hp_xferstat) & FIFO_FULL)) - return(1); - - - WR_HARPOON(port+hp_portctrl_0,(HOST_PORT | START_TO)); - - for (fifo_cnt = 0; fifo_cnt < FIFO_LEN; fifo_cnt++) { - - if (RD_HARPOON(port+hp_fifodata_0) != fifodata[loop_cnt]) - return(1); - } - - - if (!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) - return(1); - } - - - while(!(RDW_HARPOON((port+hp_intstat)) & TIMEOUT)) {} - - - WR_HARPOON(port+hp_seltimeout,TO_290ms); - - WRW_HARPOON((port+hp_intstat), CLR_ALL_INT); - - WRW_HARPOON((port+hp_intena), default_intena); - - return(0); -} - - -/*--------------------------------------------------------------------- - * - * Function: DiagBusMaster - * - * Description: Test BusMaster integrity. Non-zero return indicates an - * error. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -int DiagBusMaster(USHORT port) -#else -int DiagBusMaster(ULONG port) -#endif -{ - UCHAR testdata; - - for(testdata = (UCHAR) 1; testdata != (UCHAR)0; testdata = testdata << 1) { - - WR_HARPOON(port+hp_xfer_cnt_lo,testdata); - WR_HARPOON(port+hp_xfer_cnt_mi,testdata); - WR_HARPOON(port+hp_xfer_cnt_hi,testdata); - WR_HARPOON(port+hp_host_addr_lo,testdata); - WR_HARPOON(port+hp_host_addr_lmi,testdata); - WR_HARPOON(port+hp_host_addr_hmi,testdata); - WR_HARPOON(port+hp_host_addr_hi,testdata); - - if ((RD_HARPOON(port+hp_xfer_cnt_lo) != testdata) || - (RD_HARPOON(port+hp_xfer_cnt_mi) != testdata) || - (RD_HARPOON(port+hp_xfer_cnt_hi) != testdata) || - (RD_HARPOON(port+hp_host_addr_lo) != testdata) || - (RD_HARPOON(port+hp_host_addr_lmi) != testdata) || - (RD_HARPOON(port+hp_host_addr_hmi) != testdata) || - (RD_HARPOON(port+hp_host_addr_hi) != testdata)) - - return(1); - } - RD_HARPOON(port+hp_int_status); /*Clear interrupts. */ - return(0); -} - - - -/*--------------------------------------------------------------------- - * - * Function: DiagEEPROM - * - * Description: Verfiy checksum and 'Key' and initialize the EEPROM if - * neccessary. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void DiagEEPROM(USHORT p_port) -#else -void DiagEEPROM(ULONG p_port) -#endif - -{ - USHORT index,temp,max_wd_cnt; - - if (RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD) - max_wd_cnt = EEPROM_WD_CNT; - else - max_wd_cnt = EEPROM_WD_CNT * 2; - - temp = utilEERead(p_port, FW_SIGNATURE/2); - - if (temp == 0x4641) { - - for (index = 2; index < max_wd_cnt; index++) { - - temp += utilEERead(p_port, index); - - } - - if (temp == utilEERead(p_port, EEPROM_CHECK_SUM/2)) { - - return; /*EEPROM is Okay so return now! */ - } - } - - - utilEEWriteOnOff(p_port,(UCHAR)1); - - for (index = 0; index < max_wd_cnt; index++) { - - utilEEWrite(p_port, 0x0000, index); - } - - temp = 0; - - utilEEWrite(p_port, 0x4641, FW_SIGNATURE/2); - temp += 0x4641; - utilEEWrite(p_port, 0x3920, MODEL_NUMB_0/2); - temp += 0x3920; - utilEEWrite(p_port, 0x3033, MODEL_NUMB_2/2); - temp += 0x3033; - utilEEWrite(p_port, 0x2020, MODEL_NUMB_4/2); - temp += 0x2020; - utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG/2); - temp += 0x70D3; - utilEEWrite(p_port, 0x0010, BIOS_CONFIG/2); - temp += 0x0010; - utilEEWrite(p_port, 0x0003, SCAM_CONFIG/2); - temp += 0x0003; - utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID/2); - temp += 0x0007; - - utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN/2); - temp += 0x0000; - utilEEWrite(p_port, 0x0000, SEND_START_ENA/2); - temp += 0x0000; - utilEEWrite(p_port, 0x0000, DEVICE_ENABLE/2); - temp += 0x0000; - - utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01/2); - temp += 0x4242; - utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23/2); - temp += 0x4242; - utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45/2); - temp += 0x4242; - utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67/2); - temp += 0x4242; - utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89/2); - temp += 0x4242; - utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab/2); - temp += 0x4242; - utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd/2); - temp += 0x4242; - utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef/2); - temp += 0x4242; - - - utilEEWrite(p_port, 0x6C46, 64/2); /*PRODUCT ID */ - temp += 0x6C46; - utilEEWrite(p_port, 0x7361, 66/2); /* FlashPoint LT */ - temp += 0x7361; - utilEEWrite(p_port, 0x5068, 68/2); - temp += 0x5068; - utilEEWrite(p_port, 0x696F, 70/2); - temp += 0x696F; - utilEEWrite(p_port, 0x746E, 72/2); - temp += 0x746E; - utilEEWrite(p_port, 0x4C20, 74/2); - temp += 0x4C20; - utilEEWrite(p_port, 0x2054, 76/2); - temp += 0x2054; - utilEEWrite(p_port, 0x2020, 78/2); - temp += 0x2020; - - index = ((EE_SCAMBASE/2)+(7*16)); - utilEEWrite(p_port, (0x0700+TYPE_CODE0), index); - temp += (0x0700+TYPE_CODE0); - index++; - utilEEWrite(p_port, 0x5542, index); /*Vendor ID code */ - temp += 0x5542; /* BUSLOGIC */ - index++; - utilEEWrite(p_port, 0x4C53, index); - temp += 0x4C53; - index++; - utilEEWrite(p_port, 0x474F, index); - temp += 0x474F; - index++; - utilEEWrite(p_port, 0x4349, index); - temp += 0x4349; - index++; - utilEEWrite(p_port, 0x5442, index); /*Vendor unique code */ - temp += 0x5442; /* BT- 930 */ - index++; - utilEEWrite(p_port, 0x202D, index); - temp += 0x202D; - index++; - utilEEWrite(p_port, 0x3339, index); - temp += 0x3339; - index++; /*Serial # */ - utilEEWrite(p_port, 0x2030, index); /* 01234567 */ - temp += 0x2030; - index++; - utilEEWrite(p_port, 0x5453, index); - temp += 0x5453; - index++; - utilEEWrite(p_port, 0x5645, index); - temp += 0x5645; - index++; - utilEEWrite(p_port, 0x2045, index); - temp += 0x2045; - index++; - utilEEWrite(p_port, 0x202F, index); - temp += 0x202F; - index++; - utilEEWrite(p_port, 0x4F4A, index); - temp += 0x4F4A; - index++; - utilEEWrite(p_port, 0x204E, index); - temp += 0x204E; - index++; - utilEEWrite(p_port, 0x3539, index); - temp += 0x3539; - - - - utilEEWrite(p_port, temp, EEPROM_CHECK_SUM/2); - - utilEEWriteOnOff(p_port,(UCHAR)0); - -} - -#ident "$Id: utility.c 1.23 1997/06/10 16:55:06 mohan Exp $" -/*---------------------------------------------------------------------- - * - * - * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved - * - * This file is available under both the GNU General Public License - * and a BSD-style copyright; see LICENSE.FlashPoint for details. - * - * $Workfile: utility.c $ - * - * Description: Utility functions relating to queueing and EEPROM - * manipulation and any other garbage functions. - * - * $Date: 1997/06/10 16:55:06 $ - * - * $Revision: 1.23 $ - * - *----------------------------------------------------------------------*/ -/*#include */ - -#if (FW_TYPE==_UCB_MGR_) - /*#include */ -#endif - -/*#include */ -/*#include */ -/*#include */ -/*#include */ -/*#include */ - - -/* -extern SCCBCARD BL_Card[MAX_CARDS]; -extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR]; -extern unsigned int SccbGlobalFlags; -*/ - -/*--------------------------------------------------------------------- - * - * Function: Queue Search Select - * - * Description: Try to find a new command to execute. - * - *---------------------------------------------------------------------*/ - -void queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card) -{ - UCHAR scan_ptr, lun; - PSCCBMgr_tar_info currTar_Info; - PSCCB pOldSccb; - - scan_ptr = pCurrCard->scanIndex; - do - { - currTar_Info = &sccbMgrTbl[p_card][scan_ptr]; - if((pCurrCard->globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) - { - if (currTar_Info->TarSelQ_Cnt != 0) - { - - scan_ptr++; - if (scan_ptr == MAX_SCSI_TAR) - scan_ptr = 0; - - for(lun=0; lun < MAX_LUN; lun++) - { - if(currTar_Info->TarLUNBusy[lun] == FALSE) - { - - pCurrCard->currentSCCB = currTar_Info->TarSelQ_Head; - pOldSccb = NULL; - - while((pCurrCard->currentSCCB != NULL) && - (lun != pCurrCard->currentSCCB->Lun)) - { - pOldSccb = pCurrCard->currentSCCB; - pCurrCard->currentSCCB = (PSCCB)(pCurrCard->currentSCCB)-> - Sccb_forwardlink; - } - if(pCurrCard->currentSCCB == NULL) - continue; - if(pOldSccb != NULL) - { - pOldSccb->Sccb_forwardlink = (PSCCB)(pCurrCard->currentSCCB)-> - Sccb_forwardlink; - pOldSccb->Sccb_backlink = (PSCCB)(pCurrCard->currentSCCB)-> - Sccb_backlink; - currTar_Info->TarSelQ_Cnt--; - } - else - { - currTar_Info->TarSelQ_Head = (PSCCB)(pCurrCard->currentSCCB)->Sccb_forwardlink; - - if (currTar_Info->TarSelQ_Head == NULL) - { - currTar_Info->TarSelQ_Tail = NULL; - currTar_Info->TarSelQ_Cnt = 0; - } - else - { - currTar_Info->TarSelQ_Cnt--; - currTar_Info->TarSelQ_Head->Sccb_backlink = (PSCCB)NULL; - } - } - pCurrCard->scanIndex = scan_ptr; - - pCurrCard->globalFlags |= F_NEW_SCCB_CMD; - - break; - } - } - } - - else - { - scan_ptr++; - if (scan_ptr == MAX_SCSI_TAR) { - scan_ptr = 0; - } - } - - } - else - { - if ((currTar_Info->TarSelQ_Cnt != 0) && - (currTar_Info->TarLUNBusy[0] == FALSE)) - { - - pCurrCard->currentSCCB = currTar_Info->TarSelQ_Head; - - currTar_Info->TarSelQ_Head = (PSCCB)(pCurrCard->currentSCCB)->Sccb_forwardlink; - - if (currTar_Info->TarSelQ_Head == NULL) - { - currTar_Info->TarSelQ_Tail = NULL; - currTar_Info->TarSelQ_Cnt = 0; - } - else - { - currTar_Info->TarSelQ_Cnt--; - currTar_Info->TarSelQ_Head->Sccb_backlink = (PSCCB)NULL; - } - - scan_ptr++; - if (scan_ptr == MAX_SCSI_TAR) - scan_ptr = 0; - - pCurrCard->scanIndex = scan_ptr; - - pCurrCard->globalFlags |= F_NEW_SCCB_CMD; - - break; - } - - else - { - scan_ptr++; - if (scan_ptr == MAX_SCSI_TAR) - { - scan_ptr = 0; - } - } - } - } while (scan_ptr != pCurrCard->scanIndex); -} - - -/*--------------------------------------------------------------------- - * - * Function: Queue Select Fail - * - * Description: Add the current SCCB to the head of the Queue. - * - *---------------------------------------------------------------------*/ - -void queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card) -{ - UCHAR thisTarg; - PSCCBMgr_tar_info currTar_Info; - - if (pCurrCard->currentSCCB != NULL) - { - thisTarg = (UCHAR)(((PSCCB)(pCurrCard->currentSCCB))->TargID); - currTar_Info = &sccbMgrTbl[p_card][thisTarg]; - - pCurrCard->currentSCCB->Sccb_backlink = (PSCCB)NULL; - - pCurrCard->currentSCCB->Sccb_forwardlink = currTar_Info->TarSelQ_Head; - - if (currTar_Info->TarSelQ_Cnt == 0) - { - currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB; - } - - else - { - currTar_Info->TarSelQ_Head->Sccb_backlink = pCurrCard->currentSCCB; - } - - - currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB; - - pCurrCard->currentSCCB = NULL; - currTar_Info->TarSelQ_Cnt++; - } -} -/*--------------------------------------------------------------------- - * - * Function: Queue Command Complete - * - * Description: Call the callback function with the current SCCB. - * - *---------------------------------------------------------------------*/ - -void queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_sccb, UCHAR p_card) -{ - -#if (FW_TYPE==_UCB_MGR_) - - u08bits SCSIcmd; - CALL_BK_FN callback; - PSCCBMgr_tar_info currTar_Info; - - PUCB p_ucb; - p_ucb=p_sccb->Sccb_ucb_ptr; - - SCSIcmd = p_sccb->Cdb[0]; - - - if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) - { - - if ((p_ucb->UCB_opcode & OPC_CHK_UNDER_OVER_RUN) && - (p_sccb->HostStatus == SCCB_COMPLETE) && - (p_sccb->TargetStatus != SSCHECK)) - - if ((SCSIcmd == SCSI_READ) || - (SCSIcmd == SCSI_WRITE) || - (SCSIcmd == SCSI_READ_EXTENDED) || - (SCSIcmd == SCSI_WRITE_EXTENDED) || - (SCSIcmd == SCSI_WRITE_AND_VERIFY) || - (SCSIcmd == SCSI_START_STOP_UNIT) || - (pCurrCard->globalFlags & F_NO_FILTER) - ) - p_sccb->HostStatus = SCCB_DATA_UNDER_RUN; - } - - p_ucb->UCB_status=SCCB_SUCCESS; - - if ((p_ucb->UCB_hbastat=p_sccb->HostStatus) || (p_ucb->UCB_scsistat=p_sccb->TargetStatus)) - { - p_ucb->UCB_status=SCCB_ERROR; - } - - if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) || - (p_sccb->OperationCode == RESIDUAL_COMMAND)) - { - - utilUpdateResidual(p_sccb); - - p_ucb->UCB_datalen=p_sccb->DataLength; - } - - pCurrCard->cmdCounter--; - if (!pCurrCard->cmdCounter) - { - - if (pCurrCard->globalFlags & F_GREEN_PC) - { - WR_HARPOON(pCurrCard->ioPort+hp_clkctrl_0,(PWR_DWN | CLKCTRL_DEFAULT)); - WR_HARPOON(pCurrCard->ioPort+hp_sys_ctrl, STOP_CLK); - } - - WR_HARPOON(pCurrCard->ioPort+hp_semaphore, - (RD_HARPOON(pCurrCard->ioPort+hp_semaphore) & ~SCCB_MGR_ACTIVE)); - } - - if(pCurrCard->discQCount != 0) - { - currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID]; - if(((pCurrCard->globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { - pCurrCard->discQCount--; - pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_sccb->Lun]] = NULL; - } - else - { - if(p_sccb->Sccb_tag) - { - pCurrCard->discQCount--; - pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL; - }else - { - pCurrCard->discQCount--; - pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = NULL; - } - } - - } - callback = (CALL_BK_FN)p_ucb->UCB_callback; - callback(p_ucb); - pCurrCard->globalFlags |= F_NEW_SCCB_CMD; - pCurrCard->currentSCCB = NULL; -} - - - - -#else - - UCHAR i, SCSIcmd; - CALL_BK_FN callback; - PSCCBMgr_tar_info currTar_Info; - - SCSIcmd = p_sccb->Cdb[0]; - - - if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) { - - if ((p_sccb->ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN)) && - (p_sccb->HostStatus == SCCB_COMPLETE) && - (p_sccb->TargetStatus != SSCHECK)) - - if ((SCSIcmd == SCSI_READ) || - (SCSIcmd == SCSI_WRITE) || - (SCSIcmd == SCSI_READ_EXTENDED) || - (SCSIcmd == SCSI_WRITE_EXTENDED) || - (SCSIcmd == SCSI_WRITE_AND_VERIFY) || - (SCSIcmd == SCSI_START_STOP_UNIT) || - (pCurrCard->globalFlags & F_NO_FILTER) - ) - p_sccb->HostStatus = SCCB_DATA_UNDER_RUN; - } - - - if(p_sccb->SccbStatus == SCCB_IN_PROCESS) - { - if (p_sccb->HostStatus || p_sccb->TargetStatus) - p_sccb->SccbStatus = SCCB_ERROR; - else - p_sccb->SccbStatus = SCCB_SUCCESS; - } - - if (p_sccb->Sccb_XferState & F_AUTO_SENSE) { - - p_sccb->CdbLength = p_sccb->Save_CdbLen; - for (i=0; i < 6; i++) { - p_sccb->Cdb[i] = p_sccb->Save_Cdb[i]; - } - } - - if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) || - (p_sccb->OperationCode == RESIDUAL_COMMAND)) { - - utilUpdateResidual(p_sccb); - } - - pCurrCard->cmdCounter--; - if (!pCurrCard->cmdCounter) { - - if (pCurrCard->globalFlags & F_GREEN_PC) { - WR_HARPOON(pCurrCard->ioPort+hp_clkctrl_0,(PWR_DWN | CLKCTRL_DEFAULT)); - WR_HARPOON(pCurrCard->ioPort+hp_sys_ctrl, STOP_CLK); - } - - WR_HARPOON(pCurrCard->ioPort+hp_semaphore, - (RD_HARPOON(pCurrCard->ioPort+hp_semaphore) & ~SCCB_MGR_ACTIVE)); - - } - - if(pCurrCard->discQCount != 0) - { - currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID]; - if(((pCurrCard->globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { - pCurrCard->discQCount--; - pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_sccb->Lun]] = NULL; - } - else - { - if(p_sccb->Sccb_tag) - { - pCurrCard->discQCount--; - pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL; - }else - { - pCurrCard->discQCount--; - pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = NULL; - } - } - - } - - callback = (CALL_BK_FN)p_sccb->SccbCallback; - callback(p_sccb); - pCurrCard->globalFlags |= F_NEW_SCCB_CMD; - pCurrCard->currentSCCB = NULL; -} -#endif /* ( if FW_TYPE==...) */ - - -/*--------------------------------------------------------------------- - * - * Function: Queue Disconnect - * - * Description: Add SCCB to our disconnect array. - * - *---------------------------------------------------------------------*/ -void queueDisconnect(PSCCB p_sccb, UCHAR p_card) -{ - PSCCBMgr_tar_info currTar_Info; - - currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID]; - - if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { - BL_Card[p_card].discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_sccb->Lun]] = p_sccb; - } - else - { - if (p_sccb->Sccb_tag) - { - BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] = p_sccb; - sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] = FALSE; - sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++; - }else - { - BL_Card[p_card].discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = p_sccb; - } - } - BL_Card[p_card].currentSCCB = NULL; -} - - -/*--------------------------------------------------------------------- - * - * Function: Queue Flush SCCB - * - * Description: Flush all SCCB's back to the host driver for this target. - * - *---------------------------------------------------------------------*/ - -void queueFlushSccb(UCHAR p_card, UCHAR error_code) -{ - UCHAR qtag,thisTarg; - PSCCB currSCCB; - PSCCBMgr_tar_info currTar_Info; - - currSCCB = BL_Card[p_card].currentSCCB; - if(currSCCB != NULL) - { - thisTarg = (UCHAR)currSCCB->TargID; - currTar_Info = &sccbMgrTbl[p_card][thisTarg]; - - for (qtag=0; qtagTargID == thisTarg)) - { - - BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (UCHAR)error_code; - - queueCmdComplete(&BL_Card[p_card],BL_Card[p_card].discQ_Tbl[qtag], p_card); - - BL_Card[p_card].discQ_Tbl[qtag] = NULL; - currTar_Info->TarTagQ_Cnt--; - - } - } - } - -} - -/*--------------------------------------------------------------------- - * - * Function: Queue Flush Target SCCB - * - * Description: Flush all SCCB's back to the host driver for this target. - * - *---------------------------------------------------------------------*/ - -void queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, UCHAR error_code) -{ - UCHAR qtag; - PSCCBMgr_tar_info currTar_Info; - - currTar_Info = &sccbMgrTbl[p_card][thisTarg]; - - for (qtag=0; qtagTargID == thisTarg)) - { - - BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (UCHAR)error_code; - - queueCmdComplete(&BL_Card[p_card],BL_Card[p_card].discQ_Tbl[qtag], p_card); - - BL_Card[p_card].discQ_Tbl[qtag] = NULL; - currTar_Info->TarTagQ_Cnt--; - - } - } - -} - - - - - -void queueAddSccb(PSCCB p_SCCB, UCHAR p_card) -{ - PSCCBMgr_tar_info currTar_Info; - currTar_Info = &sccbMgrTbl[p_card][p_SCCB->TargID]; - - p_SCCB->Sccb_forwardlink = NULL; - - p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail; - - if (currTar_Info->TarSelQ_Cnt == 0) { - - currTar_Info->TarSelQ_Head = p_SCCB; - } - - else { - - currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB; - } - - - currTar_Info->TarSelQ_Tail = p_SCCB; - currTar_Info->TarSelQ_Cnt++; -} - - -/*--------------------------------------------------------------------- - * - * Function: Queue Find SCCB - * - * Description: Search the target select Queue for this SCCB, and - * remove it if found. - * - *---------------------------------------------------------------------*/ - -UCHAR queueFindSccb(PSCCB p_SCCB, UCHAR p_card) -{ - PSCCB q_ptr; - PSCCBMgr_tar_info currTar_Info; - - currTar_Info = &sccbMgrTbl[p_card][p_SCCB->TargID]; - - q_ptr = currTar_Info->TarSelQ_Head; - - while(q_ptr != NULL) { - - if (q_ptr == p_SCCB) { - - - if (currTar_Info->TarSelQ_Head == q_ptr) { - - currTar_Info->TarSelQ_Head = q_ptr->Sccb_forwardlink; - } - - if (currTar_Info->TarSelQ_Tail == q_ptr) { - - currTar_Info->TarSelQ_Tail = q_ptr->Sccb_backlink; - } - - if (q_ptr->Sccb_forwardlink != NULL) { - q_ptr->Sccb_forwardlink->Sccb_backlink = q_ptr->Sccb_backlink; - } - - if (q_ptr->Sccb_backlink != NULL) { - q_ptr->Sccb_backlink->Sccb_forwardlink = q_ptr->Sccb_forwardlink; - } - - currTar_Info->TarSelQ_Cnt--; - - return(TRUE); - } - - else { - q_ptr = q_ptr->Sccb_forwardlink; - } - } - - - return(FALSE); - -} - - -/*--------------------------------------------------------------------- - * - * Function: Utility Update Residual Count - * - * Description: Update the XferCnt to the remaining byte count. - * If we transferred all the data then just write zero. - * If Non-SG transfer then report Total Cnt - Actual Transfer - * Cnt. For SG transfers add the count fields of all - * remaining SG elements, as well as any partial remaining - * element. - * - *---------------------------------------------------------------------*/ - -void utilUpdateResidual(PSCCB p_SCCB) -{ - ULONG partial_cnt; - UINT sg_index; -#if defined(COMPILER_16_BIT) && !defined(DOS) - ULONG far *sg_ptr; -#else - ULONG *sg_ptr; -#endif - - if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) { - - p_SCCB->DataLength = 0x0000; - } - - else if (p_SCCB->Sccb_XferState & F_SG_XFER) { - - partial_cnt = 0x0000; - - sg_index = p_SCCB->Sccb_sgseg; - -#if defined(COMPILER_16_BIT) && !defined(DOS) - sg_ptr = (ULONG far *)p_SCCB->DataPointer; -#else - sg_ptr = (ULONG *)p_SCCB->DataPointer; -#endif - - if (p_SCCB->Sccb_SGoffset) { - - partial_cnt = p_SCCB->Sccb_SGoffset; - sg_index++; - } - - while ( ((ULONG)sg_index * (ULONG)SG_ELEMENT_SIZE) < - p_SCCB->DataLength ) { - - partial_cnt += *(sg_ptr+(sg_index * 2)); - sg_index++; - } - - p_SCCB->DataLength = partial_cnt; - } - - else { - - p_SCCB->DataLength -= p_SCCB->Sccb_ATC; - } -} - - -/*--------------------------------------------------------------------- - * - * Function: Wait 1 Second - * - * Description: Wait for 1 second. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void Wait1Second(USHORT p_port) -#else -void Wait1Second(ULONG p_port) -#endif -{ - UCHAR i; - - for(i=0; i < 4; i++) { - - Wait(p_port, TO_250ms); - - if ((RD_HARPOON(p_port+hp_scsictrl_0) & SCSI_RST)) - break; - - if((RDW_HARPOON((p_port+hp_intstat)) & SCAM_SEL)) - break; - } -} - - -/*--------------------------------------------------------------------- - * - * Function: Wait - * - * Description: Wait the desired delay. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void Wait(USHORT p_port, UCHAR p_delay) -#else -void Wait(ULONG p_port, UCHAR p_delay) -#endif -{ - UCHAR old_timer; - UCHAR green_flag; - - old_timer = RD_HARPOON(p_port+hp_seltimeout); - - green_flag=RD_HARPOON(p_port+hp_clkctrl_0); - WR_HARPOON(p_port+hp_clkctrl_0, CLKCTRL_DEFAULT); - - WR_HARPOON(p_port+hp_seltimeout,p_delay); - WRW_HARPOON((p_port+hp_intstat), TIMEOUT); - WRW_HARPOON((p_port+hp_intena), (default_intena & ~TIMEOUT)); - - - WR_HARPOON(p_port+hp_portctrl_0, - (RD_HARPOON(p_port+hp_portctrl_0) | START_TO)); - - while (!(RDW_HARPOON((p_port+hp_intstat)) & TIMEOUT)) { - - if ((RD_HARPOON(p_port+hp_scsictrl_0) & SCSI_RST)) - break; - - if ((RDW_HARPOON((p_port+hp_intstat)) & SCAM_SEL)) - break; - } - - WR_HARPOON(p_port+hp_portctrl_0, - (RD_HARPOON(p_port+hp_portctrl_0) & ~START_TO)); - - WRW_HARPOON((p_port+hp_intstat), TIMEOUT); - WRW_HARPOON((p_port+hp_intena), default_intena); - - WR_HARPOON(p_port+hp_clkctrl_0,green_flag); - - WR_HARPOON(p_port+hp_seltimeout,old_timer); -} - - -/*--------------------------------------------------------------------- - * - * Function: Enable/Disable Write to EEPROM - * - * Description: The EEPROM must first be enabled for writes - * A total of 9 clocks are needed. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void utilEEWriteOnOff(USHORT p_port,UCHAR p_mode) -#else -void utilEEWriteOnOff(ULONG p_port,UCHAR p_mode) -#endif -{ - UCHAR ee_value; - - ee_value = (UCHAR)(RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H)); - - if (p_mode) - - utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR); - - else - - - utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR); - - WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */ - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); /*Turn off Master Select */ -} - - -/*--------------------------------------------------------------------- - * - * Function: Write EEPROM - * - * Description: Write a word to the EEPROM at the specified - * address. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void utilEEWrite(USHORT p_port, USHORT ee_data, USHORT ee_addr) -#else -void utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr) -#endif -{ - - UCHAR ee_value; - USHORT i; - - ee_value = (UCHAR)((RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H))| - (SEE_MS | SEE_CS)); - - - - utilEESendCmdAddr(p_port, EE_WRITE, ee_addr); - - - ee_value |= (SEE_MS + SEE_CS); - - for(i = 0x8000; i != 0; i>>=1) { - - if (i & ee_data) - ee_value |= SEE_DO; - else - ee_value &= ~SEE_DO; - - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - ee_value |= SEE_CLK; /* Clock data! */ - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - ee_value &= ~SEE_CLK; - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - } - ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H); - WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS)); - - Wait(p_port, TO_10ms); - - WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS)); /* Set CS to EEPROM */ - WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS)); /* Turn off CS */ - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); /* Turn off Master Select */ -} - -/*--------------------------------------------------------------------- - * - * Function: Read EEPROM - * - * Description: Read a word from the EEPROM at the desired - * address. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -USHORT utilEERead(USHORT p_port, USHORT ee_addr) -#else -USHORT utilEERead(ULONG p_port, USHORT ee_addr) -#endif -{ - USHORT i, ee_data1, ee_data2; - - i = 0; - ee_data1 = utilEEReadOrg(p_port, ee_addr); - do - { - ee_data2 = utilEEReadOrg(p_port, ee_addr); - - if(ee_data1 == ee_data2) - return(ee_data1); - - ee_data1 = ee_data2; - i++; - - }while(i < 4); - - return(ee_data1); -} - -/*--------------------------------------------------------------------- - * - * Function: Read EEPROM Original - * - * Description: Read a word from the EEPROM at the desired - * address. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -USHORT utilEEReadOrg(USHORT p_port, USHORT ee_addr) -#else -USHORT utilEEReadOrg(ULONG p_port, USHORT ee_addr) -#endif -{ - - UCHAR ee_value; - USHORT i, ee_data; - - ee_value = (UCHAR)((RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H))| - (SEE_MS | SEE_CS)); - - - utilEESendCmdAddr(p_port, EE_READ, ee_addr); - - - ee_value |= (SEE_MS + SEE_CS); - ee_data = 0; - - for(i = 1; i <= 16; i++) { - - ee_value |= SEE_CLK; /* Clock data! */ - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - ee_value &= ~SEE_CLK; - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - - ee_data <<= 1; - - if (RD_HARPOON(p_port+hp_ee_ctrl) & SEE_DI) - ee_data |= 1; - } - - ee_value &= ~(SEE_MS + SEE_CS); - WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */ - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); /*Turn off Master Select */ - - return(ee_data); -} - - -/*--------------------------------------------------------------------- - * - * Function: Send EE command and Address to the EEPROM - * - * Description: Transfers the correct command and sends the address - * to the eeprom. - * - *---------------------------------------------------------------------*/ - -#if defined(DOS) -void utilEESendCmdAddr(USHORT p_port, UCHAR ee_cmd, USHORT ee_addr) -#else -void utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr) -#endif -{ - UCHAR ee_value; - UCHAR narrow_flg; - - USHORT i; - - - narrow_flg= (UCHAR)(RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD); - - - ee_value = SEE_MS; - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - - ee_value |= SEE_CS; /* Set CS to EEPROM */ - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - - - for(i = 0x04; i != 0; i>>=1) { - - if (i & ee_cmd) - ee_value |= SEE_DO; - else - ee_value &= ~SEE_DO; - - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - ee_value |= SEE_CLK; /* Clock data! */ - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - ee_value &= ~SEE_CLK; - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - } - - - if (narrow_flg) - i = 0x0080; - - else - i = 0x0200; - - - while (i != 0) { - - if (i & ee_addr) - ee_value |= SEE_DO; - else - ee_value &= ~SEE_DO; - - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - ee_value |= SEE_CLK; /* Clock data! */ - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - ee_value &= ~SEE_CLK; - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - - i >>= 1; - } -} - -USHORT CalcCrc16(UCHAR buffer[]) -{ - USHORT crc=0; - int i,j; - USHORT ch; - for (i=0; i < ID_STRING_LENGTH; i++) - { - ch = (USHORT) buffer[i]; - for(j=0; j < 8; j++) - { - if ((crc ^ ch) & 1) - crc = (crc >> 1) ^ CRCMASK; - else - crc >>= 1; - ch >>= 1; - } - } - return(crc); -} - -UCHAR CalcLrc(UCHAR buffer[]) -{ - int i; - UCHAR lrc; - lrc = 0; - for(i = 0; i < ID_STRING_LENGTH; i++) - lrc ^= buffer[i]; - return(lrc); -} - - - -/* - The following inline definitions avoid type conflicts. -*/ - -static inline unsigned char -FlashPoint__ProbeHostAdapter(FlashPoint_Info_T *FlashPointInfo) -{ - return FlashPoint_ProbeHostAdapter((PSCCBMGR_INFO) FlashPointInfo); -} - - -static inline FlashPoint_CardHandle_T -FlashPoint__HardwareResetHostAdapter(FlashPoint_Info_T *FlashPointInfo) -{ - return FlashPoint_HardwareResetHostAdapter((PSCCBMGR_INFO) FlashPointInfo); -} - -static inline void -FlashPoint__ReleaseHostAdapter(FlashPoint_CardHandle_T CardHandle) -{ - FlashPoint_ReleaseHostAdapter(CardHandle); -} - - -static inline void -FlashPoint__StartCCB(FlashPoint_CardHandle_T CardHandle, BusLogic_CCB_T *CCB) -{ - FlashPoint_StartCCB(CardHandle, (PSCCB) CCB); -} - - -static inline void -FlashPoint__AbortCCB(FlashPoint_CardHandle_T CardHandle, BusLogic_CCB_T *CCB) -{ - FlashPoint_AbortCCB(CardHandle, (PSCCB) CCB); -} - - -static inline boolean -FlashPoint__InterruptPending(FlashPoint_CardHandle_T CardHandle) -{ - return FlashPoint_InterruptPending(CardHandle); -} - - -static inline int -FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle) -{ - return FlashPoint_HandleInterrupt(CardHandle); -} - - -#define FlashPoint_ProbeHostAdapter FlashPoint__ProbeHostAdapter -#define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter -#define FlashPoint_ReleaseHostAdapter FlashPoint__ReleaseHostAdapter -#define FlashPoint_StartCCB FlashPoint__StartCCB -#define FlashPoint_AbortCCB FlashPoint__AbortCCB -#define FlashPoint_InterruptPending FlashPoint__InterruptPending -#define FlashPoint_HandleInterrupt FlashPoint__HandleInterrupt - - -/* - FlashPoint_InquireTargetInfo returns the Synchronous Period, Synchronous - Offset, and Wide Transfers Active information for TargetID on CardHandle. -*/ - -void FlashPoint_InquireTargetInfo(FlashPoint_CardHandle_T CardHandle, - int TargetID, - unsigned char *SynchronousPeriod, - unsigned char *SynchronousOffset, - unsigned char *WideTransfersActive) -{ - SCCBMGR_TAR_INFO *TargetInfo = - &sccbMgrTbl[((SCCBCARD *)CardHandle)->cardIndex][TargetID]; - if ((TargetInfo->TarSyncCtrl & SYNC_OFFSET) > 0) - { - *SynchronousPeriod = 5 * ((TargetInfo->TarSyncCtrl >> 5) + 1); - *SynchronousOffset = TargetInfo->TarSyncCtrl & SYNC_OFFSET; - } - else - { - *SynchronousPeriod = 0; - *SynchronousOffset = 0; - } - *WideTransfersActive = (TargetInfo->TarSyncCtrl & NARROW_SCSI ? 0 : 1); -} - - -#else /* CONFIG_SCSI_OMIT_FLASHPOINT */ - - -/* - Define prototypes for the FlashPoint SCCB Manager Functions. -*/ - -extern unsigned char FlashPoint_ProbeHostAdapter(FlashPoint_Info_T *); -extern FlashPoint_CardHandle_T - FlashPoint_HardwareResetHostAdapter(FlashPoint_Info_T *); -extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, BusLogic_CCB_T *); -extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, BusLogic_CCB_T *); -extern boolean FlashPoint_InterruptPending(FlashPoint_CardHandle_T); -extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T); -extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T); -extern void FlashPoint_InquireTargetInfo(FlashPoint_CardHandle_T, - int, unsigned char *, - unsigned char *, unsigned char *); - - -#endif /* CONFIG_SCSI_OMIT_FLASHPOINT */ diff --git a/xen/drivers/scsi/Makefile b/xen/drivers/scsi/Makefile deleted file mode 100644 index cdce09cd40..0000000000 --- a/xen/drivers/scsi/Makefile +++ /dev/null @@ -1,21 +0,0 @@ - -include $(BASEDIR)/Rules.mk - -# naive OBJS rule gets link order wrong -SCSI_OBJS := scsi.o hosts.o scsicam.o scsi_dma.o scsi_error.o -SCSI_OBJS += scsi_ioctl.o scsi_lib.o scsi_merge.o scsi_proc.o -SCSI_OBJS += scsi_queue.o scsi_scan.o scsi_syms.o scsi_obsolete.o -SCSI_OBJS += constants.o sd.o aacraid/aacraid.o aic7xxx/aic7xxx.o -SCSI_OBJS += megaraid.o BusLogic.o sym53c8xx_2/sym53c8xx.o - -default: $(OBJS) - $(MAKE) -C aacraid - $(MAKE) -C aic7xxx - $(MAKE) -C sym53c8xx_2 - $(LD) -r -o driver.o $(SCSI_OBJS) - -clean: - $(MAKE) -C aacraid clean - $(MAKE) -C aic7xxx clean - $(MAKE) -C sym53c8xx_2 clean - rm -f *.o *~ core diff --git a/xen/drivers/scsi/aacraid/Makefile b/xen/drivers/scsi/aacraid/Makefile deleted file mode 100644 index b7235fca4b..0000000000 --- a/xen/drivers/scsi/aacraid/Makefile +++ /dev/null @@ -1,13 +0,0 @@ - -include $(BASEDIR)/Rules.mk - -CFLAGS += -I$(BASEDIR)/drivers/scsi - -default: $(OBJS) - $(LD) -r -o aacraid.o $(OBJS) - -clean: - rm -f *.o *~ core - - - diff --git a/xen/drivers/scsi/aacraid/README b/xen/drivers/scsi/aacraid/README deleted file mode 100644 index 617258fdc8..0000000000 --- a/xen/drivers/scsi/aacraid/README +++ /dev/null @@ -1,55 +0,0 @@ -AACRAID Driver for Linux (take two) - -Introduction -------------------------- -The aacraid driver adds support for Adaptec (http://www.adaptec.com) -RAID controllers. This is a major rewrite from the original -Adaptec supplied driver. It has signficantly cleaned up both the code -and the running binary size (the module is less than half the size of -the original). - -Supported Cards/Chipsets -------------------------- - Dell Computer Corporation PERC 2 Quad Channel - Dell Computer Corporation PERC 2/Si - Dell Computer Corporation PERC 3/Si - Dell Computer Corporation PERC 3/Di - HP NetRAID-4M - ADAPTEC 2120S - ADAPTEC 2200S - ADAPTEC 5400S - Legend S220 - Legend S230 - Adaptec 3230S - Adaptec 3240S - ASR-2020S PCI-X - AAR-2410SA SATA - -People -------------------------- -Alan Cox -Christoph Hellwig (small cleanups/fixes) -Matt Domsch (revision ioctl, adapter messages) -Deanna Bonds (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers - added new ioctls, changed scsi interface to use new error handler, - increased the number of fibs and outstanding commands to a container) - - (fixed 64bit and 64G memory model, changed confusing naming convention - where fibs that go to the hardware are consistently called hw_fibs and - not just fibs like the name of the driver tracking structure) -Mark Salyzyn Fixed panic issues and added some new product ids for upcoming hbas. - -Original Driver -------------------------- -Adaptec Unix OEM Product Group - -Mailing List -------------------------- -linux-aacraid-devel@dell.com (Interested parties troll here) -http://mbserver.adaptec.com/ (Currently more Community Support than Devel Support) -Also note this is very different to Brian's original driver -so don't expect him to support it. -Adaptec does support this driver. Contact either tech support or Mark Salyzyn. - -Original by Brian Boerner February 2001 -Rewritten by Alan Cox, November 2001 diff --git a/xen/drivers/scsi/aacraid/TODO b/xen/drivers/scsi/aacraid/TODO deleted file mode 100644 index f9ac6ac884..0000000000 --- a/xen/drivers/scsi/aacraid/TODO +++ /dev/null @@ -1,5 +0,0 @@ -o Testing -o More testing -o Feature request: display the firmware/bios/etc revisions in the - /proc info -o 2.5.0 and beyond. diff --git a/xen/drivers/scsi/aacraid/aachba.c b/xen/drivers/scsi/aacraid/aachba.c deleted file mode 100644 index 41aefb7925..0000000000 --- a/xen/drivers/scsi/aacraid/aachba.c +++ /dev/null @@ -1,1745 +0,0 @@ -/* - * Adaptec AAC series RAID controller driver - * (c) Copyright 2001 Red Hat Inc. - * - * based on the old aacraid driver that is.. - * Adaptec aacraid device driver for Linux. - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -/*#include */ -/*#include */ -#include -#define MAJOR_NR SCSI_DISK0_MAJOR /* For DEVICE_NR() */ -#include -#include "scsi.h" -#include "hosts.h" -#include "sd.h" - -#include "aacraid.h" - -/* SCSI Commands */ -/* TODO: dmb - use the ones defined in include/scsi/scsi.h */ - -#define SS_TEST 0x00 /* Test unit ready */ -#define SS_REZERO 0x01 /* Rezero unit */ -#define SS_REQSEN 0x03 /* Request Sense */ -#define SS_REASGN 0x07 /* Reassign blocks */ -#define SS_READ 0x08 /* Read 6 */ -#define SS_WRITE 0x0A /* Write 6 */ -#define SS_INQUIR 0x12 /* inquiry */ -#define SS_ST_SP 0x1B /* Start/Stop unit */ -#define SS_LOCK 0x1E /* prevent/allow medium removal */ -#define SS_RESERV 0x16 /* Reserve */ -#define SS_RELES 0x17 /* Release */ -#define SS_MODESEN 0x1A /* Mode Sense 6 */ -#define SS_RDCAP 0x25 /* Read Capacity */ -#define SM_READ 0x28 /* Read 10 */ -#define SM_WRITE 0x2A /* Write 10 */ -#define SS_SEEK 0x2B /* Seek */ - -/* values for inqd_pdt: Peripheral device type in plain English */ -#define INQD_PDT_DA 0x00 /* Direct-access (DISK) device */ -#define INQD_PDT_PROC 0x03 /* Processor device */ -#define INQD_PDT_CHNGR 0x08 /* Changer (jukebox, scsi2) */ -#define INQD_PDT_COMM 0x09 /* Communication device (scsi2) */ -#define INQD_PDT_NOLUN2 0x1f /* Unknown Device (scsi2) */ -#define INQD_PDT_NOLUN 0x7f /* Logical Unit Not Present */ - -#define INQD_PDT_DMASK 0x1F /* Peripheral Device Type Mask */ -#define INQD_PDT_QMASK 0xE0 /* Peripheral Device Qualifer Mask */ - -#define TARGET_LUN_TO_CONTAINER(target, lun) (target) -#define CONTAINER_TO_TARGET(cont) ((cont)) -#define CONTAINER_TO_LUN(cont) (0) - -#define MAX_FIB_DATA (sizeof(struct hw_fib) - sizeof(FIB_HEADER)) - -#define MAX_DRIVER_SG_SEGMENT_COUNT 17 - -/* - * Sense keys - */ -#define SENKEY_NO_SENSE 0x00 -#define SENKEY_UNDEFINED 0x01 -#define SENKEY_NOT_READY 0x02 -#define SENKEY_MEDIUM_ERR 0x03 -#define SENKEY_HW_ERR 0x04 -#define SENKEY_ILLEGAL 0x05 -#define SENKEY_ATTENTION 0x06 -#define SENKEY_PROTECTED 0x07 -#define SENKEY_BLANK 0x08 -#define SENKEY_V_UNIQUE 0x09 -#define SENKEY_CPY_ABORT 0x0A -#define SENKEY_ABORT 0x0B -#define SENKEY_EQUAL 0x0C -#define SENKEY_VOL_OVERFLOW 0x0D -#define SENKEY_MISCOMP 0x0E -#define SENKEY_RESERVED 0x0F - -/* - * Sense codes - */ - -#define SENCODE_NO_SENSE 0x00 -#define SENCODE_END_OF_DATA 0x00 -#define SENCODE_BECOMING_READY 0x04 -#define SENCODE_INIT_CMD_REQUIRED 0x04 -#define SENCODE_PARAM_LIST_LENGTH_ERROR 0x1A -#define SENCODE_INVALID_COMMAND 0x20 -#define SENCODE_LBA_OUT_OF_RANGE 0x21 -#define SENCODE_INVALID_CDB_FIELD 0x24 -#define SENCODE_LUN_NOT_SUPPORTED 0x25 -#define SENCODE_INVALID_PARAM_FIELD 0x26 -#define SENCODE_PARAM_NOT_SUPPORTED 0x26 -#define SENCODE_PARAM_VALUE_INVALID 0x26 -#define SENCODE_RESET_OCCURRED 0x29 -#define SENCODE_LUN_NOT_SELF_CONFIGURED_YET 0x3E -#define SENCODE_INQUIRY_DATA_CHANGED 0x3F -#define SENCODE_SAVING_PARAMS_NOT_SUPPORTED 0x39 -#define SENCODE_DIAGNOSTIC_FAILURE 0x40 -#define SENCODE_INTERNAL_TARGET_FAILURE 0x44 -#define SENCODE_INVALID_MESSAGE_ERROR 0x49 -#define SENCODE_LUN_FAILED_SELF_CONFIG 0x4c -#define SENCODE_OVERLAPPED_COMMAND 0x4E - -/* - * Additional sense codes - */ - -#define ASENCODE_NO_SENSE 0x00 -#define ASENCODE_END_OF_DATA 0x05 -#define ASENCODE_BECOMING_READY 0x01 -#define ASENCODE_INIT_CMD_REQUIRED 0x02 -#define ASENCODE_PARAM_LIST_LENGTH_ERROR 0x00 -#define ASENCODE_INVALID_COMMAND 0x00 -#define ASENCODE_LBA_OUT_OF_RANGE 0x00 -#define ASENCODE_INVALID_CDB_FIELD 0x00 -#define ASENCODE_LUN_NOT_SUPPORTED 0x00 -#define ASENCODE_INVALID_PARAM_FIELD 0x00 -#define ASENCODE_PARAM_NOT_SUPPORTED 0x01 -#define ASENCODE_PARAM_VALUE_INVALID 0x02 -#define ASENCODE_RESET_OCCURRED 0x00 -#define ASENCODE_LUN_NOT_SELF_CONFIGURED_YET 0x00 -#define ASENCODE_INQUIRY_DATA_CHANGED 0x03 -#define ASENCODE_SAVING_PARAMS_NOT_SUPPORTED 0x00 -#define ASENCODE_DIAGNOSTIC_FAILURE 0x80 -#define ASENCODE_INTERNAL_TARGET_FAILURE 0x00 -#define ASENCODE_INVALID_MESSAGE_ERROR 0x00 -#define ASENCODE_LUN_FAILED_SELF_CONFIG 0x00 -#define ASENCODE_OVERLAPPED_COMMAND 0x00 - -#define BYTE0(x) (unsigned char)(x) -#define BYTE1(x) (unsigned char)((x) >> 8) -#define BYTE2(x) (unsigned char)((x) >> 16) -#define BYTE3(x) (unsigned char)((x) >> 24) - -/*------------------------------------------------------------------------------ - * S T R U C T S / T Y P E D E F S - *----------------------------------------------------------------------------*/ -/* SCSI inquiry data */ -struct inquiry_data { - u8 inqd_pdt; /* Peripheral qualifier | Peripheral Device Type */ - u8 inqd_dtq; /* RMB | Device Type Qualifier */ - u8 inqd_ver; /* ISO version | ECMA version | ANSI-approved version */ - u8 inqd_rdf; /* AENC | TrmIOP | Response data format */ - u8 inqd_len; /* Additional length (n-4) */ - u8 inqd_pad1[2]; /* Reserved - must be zero */ - u8 inqd_pad2; /* RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */ - u8 inqd_vid[8]; /* Vendor ID */ - u8 inqd_pid[16]; /* Product ID */ - u8 inqd_prl[4]; /* Product Revision Level */ -}; - -struct sense_data { - u8 error_code; /* 70h (current errors), 71h(deferred errors) */ - u8 valid:1; /* A valid bit of one indicates that the information */ - /* field contains valid information as defined in the - * SCSI-2 Standard. - */ - u8 segment_number; /* Only used for COPY, COMPARE, or COPY AND VERIFY Commands */ - u8 sense_key:4; /* Sense Key */ - u8 reserved:1; - u8 ILI:1; /* Incorrect Length Indicator */ - u8 EOM:1; /* End Of Medium - reserved for random access devices */ - u8 filemark:1; /* Filemark - reserved for random access devices */ - - u8 information[4]; /* for direct-access devices, contains the unsigned - * logical block address or residue associated with - * the sense key - */ - u8 add_sense_len; /* number of additional sense bytes to follow this field */ - u8 cmnd_info[4]; /* not used */ - u8 ASC; /* Additional Sense Code */ - u8 ASCQ; /* Additional Sense Code Qualifier */ - u8 FRUC; /* Field Replaceable Unit Code - not used */ - u8 bit_ptr:3; /* indicates which byte of the CDB or parameter data - * was in error - */ - u8 BPV:1; /* bit pointer valid (BPV): 1- indicates that - * the bit_ptr field has valid value - */ - u8 reserved2:2; - u8 CD:1; /* command data bit: 1- illegal parameter in CDB. - * 0- illegal parameter in data. - */ - u8 SKSV:1; - u8 field_ptr[2]; /* byte of the CDB or parameter data in error */ -}; - -/* - * M O D U L E G L O B A L S - */ - -static struct fsa_scsi_hba *fsa_dev[MAXIMUM_NUM_ADAPTERS]; /* SCSI Device Instance Pointers */ -static struct sense_data sense_data[MAXIMUM_NUM_CONTAINERS]; -static void get_sd_devname(int disknum, char *buffer); -static unsigned long aac_build_sg(Scsi_Cmnd* scsicmd, struct sgmap* sgmap); -static unsigned long aac_build_sg64(Scsi_Cmnd* scsicmd, struct sgmap64* psg); -static int aac_send_srb_fib(Scsi_Cmnd* scsicmd); -#ifdef AAC_DETAILED_STATUS_INFO -static char *aac_get_status_string(u32 status); -#endif - -/* - * Non dasd selection is handled entirely in aachba now - */ - -MODULE_PARM(nondasd, "i"); -MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on"); - -static int nondasd = -1; - -/** - * aac_get_containers - list containers - * @common: adapter to probe - * - * Make a list of all containers on this controller - */ -int aac_get_containers(struct aac_dev *dev) -{ - struct fsa_scsi_hba *fsa_dev_ptr; - u32 index; - int status = 0; - struct aac_query_mount *dinfo; - struct aac_mount *dresp; - struct fib * fibptr; - unsigned instance; - - fsa_dev_ptr = &(dev->fsa_dev); - instance = dev->scsi_host_ptr->unique_id; - - if (!(fibptr = fib_alloc(dev))) - return -ENOMEM; - - for (index = 0; index < MAXIMUM_NUM_CONTAINERS; index++) { - fib_init(fibptr); - dinfo = (struct aac_query_mount *) fib_data(fibptr); - - dinfo->command = cpu_to_le32(VM_NameServe); - dinfo->count = cpu_to_le32(index); - dinfo->type = cpu_to_le32(FT_FILESYS); - - status = fib_send(ContainerCommand, - fibptr, - sizeof (struct aac_query_mount), - FsaNormal, - 1, 1, - NULL, NULL); - if (status < 0 ) { - printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n"); - break; - } - dresp = (struct aac_mount *)fib_data(fibptr); - - if ((le32_to_cpu(dresp->status) == ST_OK) && - (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && - (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { - fsa_dev_ptr->valid[index] = 1; - fsa_dev_ptr->type[index] = le32_to_cpu(dresp->mnt[0].vol); - fsa_dev_ptr->size[index] = le32_to_cpu(dresp->mnt[0].capacity); - if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) - fsa_dev_ptr->ro[index] = 1; - } - fib_complete(fibptr); - /* - * If there are no more containers, then stop asking. - */ - if ((index + 1) >= le32_to_cpu(dresp->count)) - break; - } - fib_free(fibptr); - fsa_dev[instance] = fsa_dev_ptr; - return status; -} - -/** - * probe_container - query a logical volume - * @dev: device to query - * @cid: container identifier - * - * Queries the controller about the given volume. The volume information - * is updated in the struct fsa_scsi_hba structure rather than returned. - */ - -static int probe_container(struct aac_dev *dev, int cid) -{ - struct fsa_scsi_hba *fsa_dev_ptr; - int status; - struct aac_query_mount *dinfo; - struct aac_mount *dresp; - struct fib * fibptr; - unsigned instance; - - fsa_dev_ptr = &(dev->fsa_dev); - instance = dev->scsi_host_ptr->unique_id; - - if (!(fibptr = fib_alloc(dev))) - return -ENOMEM; - - fib_init(fibptr); - - dinfo = (struct aac_query_mount *)fib_data(fibptr); - - dinfo->command = cpu_to_le32(VM_NameServe); - dinfo->count = cpu_to_le32(cid); - dinfo->type = cpu_to_le32(FT_FILESYS); - - status = fib_send(ContainerCommand, - fibptr, - sizeof(struct aac_query_mount), - FsaNormal, - 1, 1, - NULL, NULL); - if (status < 0) { - printk(KERN_WARNING "aacraid: probe_containers query failed.\n"); - goto error; - } - - dresp = (struct aac_mount *) fib_data(fibptr); - - if ((le32_to_cpu(dresp->status) == ST_OK) && - (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && - (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { - fsa_dev_ptr->valid[cid] = 1; - fsa_dev_ptr->type[cid] = le32_to_cpu(dresp->mnt[0].vol); - fsa_dev_ptr->size[cid] = le32_to_cpu(dresp->mnt[0].capacity); - if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) - fsa_dev_ptr->ro[cid] = 1; - } - -error: - fib_complete(fibptr); - fib_free(fibptr); - - return status; -} - -/* Local Structure to set SCSI inquiry data strings */ -struct scsi_inq { - char vid[8]; /* Vendor ID */ - char pid[16]; /* Product ID */ - char prl[4]; /* Product Revision Level */ -}; - -/** - * InqStrCopy - string merge - * @a: string to copy from - * @b: string to copy to - * - * Copy a String from one location to another - * without copying \0 - */ - -static void inqstrcpy(char *a, char *b) -{ - - while(*a != (char)0) - *b++ = *a++; -} - -static char *container_types[] = { - "None", - "Volume", - "Mirror", - "Stripe", - "RAID5", - "SSRW", - "SSRO", - "Morph", - "Legacy", - "RAID4", - "RAID10", - "RAID00", - "V-MIRRORS", - "PSEUDO R4", - "RAID50", - "Unknown" -}; - - - -/* Function: setinqstr - * - * Arguments: [1] pointer to void [1] int - * - * Purpose: Sets SCSI inquiry data strings for vendor, product - * and revision level. Allows strings to be set in platform dependant - * files instead of in OS dependant driver source. - */ - -static void setinqstr(int devtype, void *data, int tindex) -{ - struct scsi_inq *str; - char *findit; - struct aac_driver_ident *mp; - - mp = aac_get_driver_ident(devtype); - - str = (struct scsi_inq *)(data); /* cast data to scsi inq block */ - - inqstrcpy (mp->vname, str->vid); - inqstrcpy (mp->model, str->pid); /* last six chars reserved for vol type */ - - findit = str->pid; - - for ( ; *findit != ' '; findit++); /* walk till we find a space then incr by 1 */ - findit++; - - if (tindex < (sizeof(container_types)/sizeof(char *))){ - inqstrcpy (container_types[tindex], findit); - } - inqstrcpy ("V1.0", str->prl); -} - -void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code, - u8 a_sense_code, u8 incorrect_length, - u8 bit_pointer, u16 field_pointer, - u32 residue) -{ - sense_buf[0] = 0xF0; /* Sense data valid, err code 70h (current error) */ - sense_buf[1] = 0; /* Segment number, always zero */ - - if (incorrect_length) { - sense_buf[2] = sense_key | 0x20; /* Set ILI bit | sense key */ - sense_buf[3] = BYTE3(residue); - sense_buf[4] = BYTE2(residue); - sense_buf[5] = BYTE1(residue); - sense_buf[6] = BYTE0(residue); - } else - sense_buf[2] = sense_key; /* Sense key */ - - if (sense_key == SENKEY_ILLEGAL) - sense_buf[7] = 10; /* Additional sense length */ - else - sense_buf[7] = 6; /* Additional sense length */ - - sense_buf[12] = sense_code; /* Additional sense code */ - sense_buf[13] = a_sense_code; /* Additional sense code qualifier */ - if (sense_key == SENKEY_ILLEGAL) { - sense_buf[15] = 0; - - if (sense_code == SENCODE_INVALID_PARAM_FIELD) - sense_buf[15] = 0x80; /* Std sense key specific field */ - /* Illegal parameter is in the parameter block */ - - if (sense_code == SENCODE_INVALID_CDB_FIELD) - sense_buf[15] = 0xc0; /* Std sense key specific field */ - /* Illegal parameter is in the CDB block */ - sense_buf[15] |= bit_pointer; - sense_buf[16] = field_pointer >> 8; /* MSB */ - sense_buf[17] = field_pointer; /* LSB */ - } -} - -static void aac_io_done(Scsi_Cmnd * scsicmd) -{ - unsigned long cpu_flags; - spin_lock_irqsave(&io_request_lock, cpu_flags); - scsicmd->scsi_done(scsicmd); - spin_unlock_irqrestore(&io_request_lock, cpu_flags); -} - -static void __aac_io_done(Scsi_Cmnd * scsicmd) -{ - scsicmd->scsi_done(scsicmd); -} - -int aac_get_adapter_info(struct aac_dev* dev) -{ - struct fib* fibptr; - struct aac_adapter_info* info; - int rcode; - u32 tmp; - if (!(fibptr = fib_alloc(dev))) - return -ENOMEM; - - fib_init(fibptr); - info = (struct aac_adapter_info*) fib_data(fibptr); - - memset(info,0,sizeof(struct aac_adapter_info)); - - rcode = fib_send(RequestAdapterInfo, - fibptr, - sizeof(struct aac_adapter_info), - FsaNormal, - 1, 1, - NULL, - NULL); - - memcpy(&dev->adapter_info, info, sizeof(struct aac_adapter_info)); - - tmp = dev->adapter_info.kernelrev; - printk(KERN_INFO "%s%d: kernel %d.%d.%d build %d\n", - dev->name, dev->id, - tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff, - dev->adapter_info.kernelbuild); - tmp = dev->adapter_info.monitorrev; - printk(KERN_INFO "%s%d: monitor %d.%d.%d build %d\n", - dev->name, dev->id, - tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff, - dev->adapter_info.monitorbuild); - tmp = dev->adapter_info.biosrev; - printk(KERN_INFO "%s%d: bios %d.%d.%d build %d\n", - dev->name, dev->id, - tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff, - dev->adapter_info.biosbuild); - printk(KERN_INFO "%s%d: serial %x%x\n", - dev->name, dev->id, - dev->adapter_info.serial[0], - dev->adapter_info.serial[1]); - - dev->nondasd_support = 0; - dev->raid_scsi_mode = 0; - if(dev->adapter_info.options & AAC_OPT_NONDASD){ - dev->nondasd_support = 1; - } - - /* - * If the firmware supports ROMB RAID/SCSI mode and we are currently - * in RAID/SCSI mode, set the flag. For now if in this mode we will - * force nondasd support on. If we decide to allow the non-dasd flag - * additional changes changes will have to be made to support - * RAID/SCSI. the function aac_scsi_cmd in this module will have to be - * changed to support the new dev->raid_scsi_mode flag instead of - * leaching off of the dev->nondasd_support flag. Also in linit.c the - * function aac_detect will have to be modified where it sets up the - * max number of channels based on the aac->nondasd_support flag only. - */ - if ((dev->adapter_info.options & AAC_OPT_SCSI_MANAGED) - && (dev->adapter_info.options & AAC_OPT_RAID_SCSI_MODE)) - { - dev->nondasd_support = 1; - dev->raid_scsi_mode = 1; - } - if (dev->raid_scsi_mode != 0) - printk(KERN_INFO "%s%d: ROMB RAID/SCSI mode enabled\n",dev->name, dev->id); - - if (nondasd != -1) - dev->nondasd_support = (nondasd!=0); - - if(dev->nondasd_support != 0) - printk(KERN_INFO "%s%d: Non-DASD support enabled\n",dev->name, dev->id); - - dev->pae_support = 0; - if( (sizeof(dma_addr_t) > 4) && (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)){ - dev->pae_support = 1; - } - /* TODO - dmb temporary until fw can set this bit */ - dev->pae_support = (BITS_PER_LONG >= 64); - if(dev->pae_support != 0) - { - printk(KERN_INFO "%s%d: 64 Bit PAE enabled\n", dev->name, dev->id); - pci_set_dma_mask(dev->pdev, (dma_addr_t)0xFFFFFFFFFFFFFFFFULL); - } - - fib_complete(fibptr); - fib_free(fibptr); - - return rcode; -} - - -static void read_callback(void *context, struct fib * fibptr) -{ - struct aac_dev *dev; - struct aac_read_reply *readreply; - Scsi_Cmnd *scsicmd; - u32 lba; - u32 cid; - - scsicmd = (Scsi_Cmnd *) context; - - dev = (struct aac_dev *)scsicmd->host->hostdata; - cid =TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun); - - lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; - dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies)); - - if (fibptr == NULL) - BUG(); - - if(scsicmd->use_sg) - pci_unmap_sg(dev->pdev, - (struct scatterlist *)scsicmd->buffer, - scsicmd->use_sg, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - else if(scsicmd->request_bufflen) - pci_unmap_single(dev->pdev, (dma_addr_t)(unsigned long)scsicmd->SCp.ptr, - scsicmd->request_bufflen, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - readreply = (struct aac_read_reply *)fib_data(fibptr); - if (le32_to_cpu(readreply->status) == ST_OK) - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - else { - printk(KERN_WARNING "read_callback: read failed, status = %d\n", readreply->status); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; - set_sense((u8 *) &sense_data[cid], - SENKEY_HW_ERR, - SENCODE_INTERNAL_TARGET_FAILURE, - ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, - 0, 0); - } - fib_complete(fibptr); - fib_free(fibptr); - - aac_io_done(scsicmd); -} - -static void write_callback(void *context, struct fib * fibptr) -{ - struct aac_dev *dev; - struct aac_write_reply *writereply; - Scsi_Cmnd *scsicmd; - u32 lba; - u32 cid; - - scsicmd = (Scsi_Cmnd *) context; - dev = (struct aac_dev *)scsicmd->host->hostdata; - cid = TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun); - - lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; - dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies)); - if (fibptr == NULL) - BUG(); - - if(scsicmd->use_sg) - pci_unmap_sg(dev->pdev, - (struct scatterlist *)scsicmd->buffer, - scsicmd->use_sg, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - else if(scsicmd->request_bufflen) - pci_unmap_single(dev->pdev, (dma_addr_t)(unsigned long)scsicmd->SCp.ptr, - scsicmd->request_bufflen, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - - writereply = (struct aac_write_reply *) fib_data(fibptr); - if (le32_to_cpu(writereply->status) == ST_OK) - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - else { - printk(KERN_WARNING "write_callback: write failed, status = %d\n", writereply->status); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; - set_sense((u8 *) &sense_data[cid], - SENKEY_HW_ERR, - SENCODE_INTERNAL_TARGET_FAILURE, - ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, - 0, 0); - } - - fib_complete(fibptr); - fib_free(fibptr); - aac_io_done(scsicmd); -} - -int aac_read(Scsi_Cmnd * scsicmd, int cid) -{ - u32 lba; - u32 count; - int status; - - u16 fibsize; - struct aac_dev *dev; - struct fib * cmd_fibcontext; - - dev = (struct aac_dev *)scsicmd->host->hostdata; - /* - * Get block address and transfer length - */ - if (scsicmd->cmnd[0] == SS_READ) /* 6 byte command */ - { - dprintk((KERN_DEBUG "aachba: received a read(6) command on target %d.\n", cid)); - - lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; - count = scsicmd->cmnd[4]; - - if (count == 0) - count = 256; - } else { - dprintk((KERN_DEBUG "aachba: received a read(10) command on target %d.\n", cid)); - - lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; - count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; - } - dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies)); - /* - * Alocate and initialize a Fib - */ - if (!(cmd_fibcontext = fib_alloc(dev))) { - scsicmd->result = DID_ERROR << 16; - aac_io_done(scsicmd); - return (-1); - } - - fib_init(cmd_fibcontext); - - if(dev->pae_support == 1){ - struct aac_read64 *readcmd; - readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext); - readcmd->command = cpu_to_le32(VM_CtHostRead64); - readcmd->cid = cpu_to_le16(cid); - readcmd->sector_count = cpu_to_le16(count); - readcmd->block = cpu_to_le32(lba); - readcmd->pad = cpu_to_le16(0); - readcmd->flags = cpu_to_le16(0); - - aac_build_sg64(scsicmd, &readcmd->sg); - if(readcmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT) - BUG(); - fibsize = sizeof(struct aac_read64) + ((readcmd->sg.count - 1) * sizeof (struct sgentry64)); - /* - * Now send the Fib to the adapter - */ - status = fib_send(ContainerCommand64, - cmd_fibcontext, - fibsize, - FsaNormal, - 0, 1, - (fib_callback) read_callback, - (void *) scsicmd); - } else { - struct aac_read *readcmd; - readcmd = (struct aac_read *) fib_data(cmd_fibcontext); - readcmd->command = cpu_to_le32(VM_CtBlockRead); - readcmd->cid = cpu_to_le32(cid); - readcmd->block = cpu_to_le32(lba); - readcmd->count = cpu_to_le32(count * 512); - - if (count * 512 > (64 * 1024)) - BUG(); - - aac_build_sg(scsicmd, &readcmd->sg); - if(readcmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT) - BUG(); - fibsize = sizeof(struct aac_read) + ((readcmd->sg.count - 1) * sizeof (struct sgentry)); - /* - * Now send the Fib to the adapter - */ - status = fib_send(ContainerCommand, - cmd_fibcontext, - fibsize, - FsaNormal, - 0, 1, - (fib_callback) read_callback, - (void *) scsicmd); - } - - - /* - * Check that the command queued to the controller - */ - if (status == -EINPROGRESS) - return 0; - - printk(KERN_WARNING "aac_read: fib_send failed with status: %d.\n", status); - /* - * For some reason, the Fib didn't queue, return QUEUE_FULL - */ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | QUEUE_FULL; - aac_io_done(scsicmd); - fib_complete(cmd_fibcontext); - fib_free(cmd_fibcontext); - return -1; -} - -static int aac_write(Scsi_Cmnd * scsicmd, int cid) -{ - u32 lba; - u32 count; - int status; - u16 fibsize; - struct aac_dev *dev; - struct fib * cmd_fibcontext; - - dev = (struct aac_dev *)scsicmd->host->hostdata; - /* - * Get block address and transfer length - */ - if (scsicmd->cmnd[0] == SS_WRITE) /* 6 byte command */ - { - lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; - count = scsicmd->cmnd[4]; - if (count == 0) - count = 256; - } else { - dprintk((KERN_DEBUG "aachba: received a write(10) command on target %d.\n", cid)); - lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; - count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; - } - dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies)); - /* - * Allocate and initialize a Fib then setup a BlockWrite command - */ - if (!(cmd_fibcontext = fib_alloc(dev))) { - scsicmd->result = DID_ERROR << 16; - aac_io_done(scsicmd); - return -1; - } - fib_init(cmd_fibcontext); - - if(dev->pae_support == 1) - { - struct aac_write64 *writecmd; - writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext); - writecmd->command = cpu_to_le32(VM_CtHostWrite64); - writecmd->cid = cpu_to_le16(cid); - writecmd->sector_count = cpu_to_le16(count); - writecmd->block = cpu_to_le32(lba); - writecmd->pad = cpu_to_le16(0); - writecmd->flags = cpu_to_le16(0); - - aac_build_sg64(scsicmd, &writecmd->sg); - if(writecmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT) - BUG(); - fibsize = sizeof(struct aac_write64) + ((writecmd->sg.count - 1) * sizeof (struct sgentry64)); - /* - * Now send the Fib to the adapter - */ - status = fib_send(ContainerCommand64, - cmd_fibcontext, - fibsize, - FsaNormal, - 0, 1, - (fib_callback) write_callback, - (void *) scsicmd); - } - else - { - struct aac_write *writecmd; - writecmd = (struct aac_write *) fib_data(cmd_fibcontext); - writecmd->command = cpu_to_le32(VM_CtBlockWrite); - writecmd->cid = cpu_to_le32(cid); - writecmd->block = cpu_to_le32(lba); - writecmd->count = cpu_to_le32(count * 512); - writecmd->sg.count = cpu_to_le32(1); - /* ->stable is not used - it did mean which type of write */ - - if (count * 512 > (64 * 1024)) - BUG(); - aac_build_sg(scsicmd, &writecmd->sg); - if(writecmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT) - BUG(); - fibsize = sizeof(struct aac_write) + ((writecmd->sg.count - 1) * sizeof (struct sgentry)); - /* - * Now send the Fib to the adapter - */ - status = fib_send(ContainerCommand, - cmd_fibcontext, - fibsize, - FsaNormal, - 0, 1, - (fib_callback) write_callback, - (void *) scsicmd); - } - - /* - * Check that the command queued to the controller - */ - if (status == -EINPROGRESS) - return 0; - - printk(KERN_WARNING "aac_write: fib_send failed with status: %d\n", status); - /* - * For some reason, the Fib didn't queue, return QUEUE_FULL - */ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | QUEUE_FULL; - aac_io_done(scsicmd); - - fib_complete(cmd_fibcontext); - fib_free(cmd_fibcontext); - return -1; -} - - -/** - * aac_scsi_cmd() - Process SCSI command - * @scsicmd: SCSI command block - * @wait: 1 if the user wants to await completion - * - * Emulate a SCSI command and queue the required request for the - * aacraid firmware. - */ - -int aac_scsi_cmd(Scsi_Cmnd * scsicmd) -{ - u32 cid = 0; - struct fsa_scsi_hba *fsa_dev_ptr; - int cardtype; - int ret; - struct aac_dev *dev = (struct aac_dev *)scsicmd->host->hostdata; - - cardtype = dev->cardtype; - - fsa_dev_ptr = fsa_dev[scsicmd->host->unique_id]; - - /* - * If the bus, target or lun is out of range, return fail - * Test does not apply to ID 16, the pseudo id for the controller - * itself. - */ - if (scsicmd->target != scsicmd->host->this_id) { - if ((scsicmd->channel == 0) ){ - if( (scsicmd->target >= AAC_MAX_TARGET) || (scsicmd->lun != 0)){ - scsicmd->result = DID_NO_CONNECT << 16; - __aac_io_done(scsicmd); - return 0; - } - cid = TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun); - - /* - * If the target container doesn't exist, it may have - * been newly created - */ - if (fsa_dev_ptr->valid[cid] == 0) { - switch (scsicmd->cmnd[0]) { - case SS_INQUIR: - case SS_RDCAP: - case SS_TEST: - spin_unlock_irq(&io_request_lock); - probe_container(dev, cid); - spin_lock_irq(&io_request_lock); - if (fsa_dev_ptr->valid[cid] == 0) { - scsicmd->result = DID_NO_CONNECT << 16; - __aac_io_done(scsicmd); - return 0; - } - default: - break; - } - } - /* - * If the target container still doesn't exist, - * return failure - */ - if (fsa_dev_ptr->valid[cid] == 0) { - scsicmd->result = DID_BAD_TARGET << 16; - __aac_io_done(scsicmd); - return -1; - } - } else { /* check for physical non-dasd devices */ - if(dev->nondasd_support == 1){ - return aac_send_srb_fib(scsicmd); - } else { - scsicmd->result = DID_NO_CONNECT << 16; - __aac_io_done(scsicmd); - return 0; - } - } - } - /* - * else Command for the controller itself - */ - else if ((scsicmd->cmnd[0] != SS_INQUIR) && /* only INQUIRY & TUR cmnd supported for controller */ - (scsicmd->cmnd[0] != SS_TEST)) - { - dprintk((KERN_WARNING "Only INQUIRY & TUR command supported for controller, rcvd = 0x%x.\n", scsicmd->cmnd[0])); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; - set_sense((u8 *) &sense_data[cid], - SENKEY_ILLEGAL, - SENCODE_INVALID_COMMAND, - ASENCODE_INVALID_COMMAND, 0, 0, 0, 0); - __aac_io_done(scsicmd); - return -1; - } - - - /* Handle commands here that don't really require going out to the adapter */ - switch (scsicmd->cmnd[0]) { - case SS_INQUIR: - { - struct inquiry_data *inq_data_ptr; - - dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->target)); - inq_data_ptr = (struct inquiry_data *)scsicmd->request_buffer; - memset(inq_data_ptr, 0, sizeof (struct inquiry_data)); - - inq_data_ptr->inqd_ver = 2; /* claim compliance to SCSI-2 */ - inq_data_ptr->inqd_dtq = 0x80; /* set RMB bit to one indicating that the medium is removable */ - inq_data_ptr->inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ - inq_data_ptr->inqd_len = 31; - /*Format for "pad2" is RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */ - inq_data_ptr->inqd_pad2= 0x32 ; /*WBus16|Sync|CmdQue */ - /* - * Set the Vendor, Product, and Revision Level - * see: .c i.e. aac.c - */ - setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr->type[cid]); - if (scsicmd->target == scsicmd->host->this_id) - inq_data_ptr->inqd_pdt = INQD_PDT_PROC; /* Processor device */ - else - inq_data_ptr->inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); - return 0; - } - case SS_RDCAP: - { - int capacity; - char *cp; - - dprintk((KERN_DEBUG "READ CAPACITY command.\n")); - capacity = fsa_dev_ptr->size[cid] - 1; - cp = scsicmd->request_buffer; - cp[0] = (capacity >> 24) & 0xff; - cp[1] = (capacity >> 16) & 0xff; - cp[2] = (capacity >> 8) & 0xff; - cp[3] = (capacity >> 0) & 0xff; - cp[4] = 0; - cp[5] = 0; - cp[6] = 2; - cp[7] = 0; - - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); - - return 0; - } - - case SS_MODESEN: - { - char *mode_buf; - - dprintk((KERN_DEBUG "MODE SENSE command.\n")); - mode_buf = scsicmd->request_buffer; - mode_buf[0] = 0; /* Mode data length (MSB) */ - mode_buf[1] = 6; /* Mode data length (LSB) */ - mode_buf[2] = 0; /* Medium type - default */ - mode_buf[3] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */ - mode_buf[4] = 0; /* reserved */ - mode_buf[5] = 0; /* reserved */ - mode_buf[6] = 0; /* Block descriptor length (MSB) */ - mode_buf[7] = 0; /* Block descriptor length (LSB) */ - - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); - - return 0; - } - case SS_REQSEN: - dprintk((KERN_DEBUG "REQUEST SENSE command.\n")); - memcpy(scsicmd->sense_buffer, &sense_data[cid], sizeof (struct sense_data)); - memset(&sense_data[cid], 0, sizeof (struct sense_data)); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); - return (0); - - case SS_LOCK: - dprintk((KERN_DEBUG "LOCK command.\n")); - if (scsicmd->cmnd[4]) - fsa_dev_ptr->locked[cid] = 1; - else - fsa_dev_ptr->locked[cid] = 0; - - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); - return 0; - /* - * These commands are all No-Ops - */ - case SS_TEST: - case SS_RESERV: - case SS_RELES: - case SS_REZERO: - case SS_REASGN: - case SS_SEEK: - case SS_ST_SP: - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); - return (0); - } - - switch (scsicmd->cmnd[0]) - { - case SS_READ: - case SM_READ: - /* - * Hack to keep track of ordinal number of the device that - * corresponds to a container. Needed to convert - * containers to /dev/sd device names - */ - - spin_unlock_irq(&io_request_lock); - fsa_dev_ptr->devno[cid] = DEVICE_NR(scsicmd->request.rq_dev); - ret = aac_read(scsicmd, cid); - spin_lock_irq(&io_request_lock); - return ret; - - case SS_WRITE: - case SM_WRITE: - spin_unlock_irq(&io_request_lock); - ret = aac_write(scsicmd, cid); - spin_lock_irq(&io_request_lock); - return ret; - default: - /* - * Unhandled commands - */ - printk(KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; - set_sense((u8 *) &sense_data[cid], - SENKEY_ILLEGAL, SENCODE_INVALID_COMMAND, - ASENCODE_INVALID_COMMAND, 0, 0, 0, 0); - __aac_io_done(scsicmd); - return -1; - } -} - -static int query_disk(struct aac_dev *dev, void *arg) -{ - struct aac_query_disk qd; - struct fsa_scsi_hba *fsa_dev_ptr; - - fsa_dev_ptr = &(dev->fsa_dev); - if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk))) - return -EFAULT; - if (qd.cnum == -1) - qd.cnum = TARGET_LUN_TO_CONTAINER(qd.target, qd.lun); - else if ((qd.bus == -1) && (qd.target == -1) && (qd.lun == -1)) - { - if (qd.cnum < 0 || qd.cnum > MAXIMUM_NUM_CONTAINERS) - return -EINVAL; - qd.instance = dev->scsi_host_ptr->host_no; - qd.bus = 0; - qd.target = CONTAINER_TO_TARGET(qd.cnum); - qd.lun = CONTAINER_TO_LUN(qd.cnum); - } - else return -EINVAL; - - qd.valid = fsa_dev_ptr->valid[qd.cnum]; - qd.locked = fsa_dev_ptr->locked[qd.cnum]; - qd.deleted = fsa_dev_ptr->deleted[qd.cnum]; - - if (fsa_dev_ptr->devno[qd.cnum] == -1) - qd.unmapped = 1; - else - qd.unmapped = 0; - - get_sd_devname(fsa_dev_ptr->devno[qd.cnum], qd.name); - - if (copy_to_user(arg, &qd, sizeof (struct aac_query_disk))) - return -EFAULT; - return 0; -} - -static void get_sd_devname(int disknum, char *buffer) -{ - if (disknum < 0) { - sprintf(buffer, "%s", ""); - return; - } - - if (disknum < 26) - sprintf(buffer, "sd%c", 'a' + disknum); - else { - unsigned int min1; - unsigned int min2; - /* - * For larger numbers of disks, we need to go to a new - * naming scheme. - */ - min1 = disknum / 26; - min2 = disknum % 26; - sprintf(buffer, "sd%c%c", 'a' + min1 - 1, 'a' + min2); - } -} - -static int force_delete_disk(struct aac_dev *dev, void *arg) -{ - struct aac_delete_disk dd; - struct fsa_scsi_hba *fsa_dev_ptr; - - fsa_dev_ptr = &(dev->fsa_dev); - - if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk))) - return -EFAULT; - - if (dd.cnum > MAXIMUM_NUM_CONTAINERS) - return -EINVAL; - /* - * Mark this container as being deleted. - */ - fsa_dev_ptr->deleted[dd.cnum] = 1; - /* - * Mark the container as no longer valid - */ - fsa_dev_ptr->valid[dd.cnum] = 0; - return 0; -} - -static int delete_disk(struct aac_dev *dev, void *arg) -{ - struct aac_delete_disk dd; - struct fsa_scsi_hba *fsa_dev_ptr; - - fsa_dev_ptr = &(dev->fsa_dev); - - if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk))) - return -EFAULT; - - if (dd.cnum > MAXIMUM_NUM_CONTAINERS) - return -EINVAL; - /* - * If the container is locked, it can not be deleted by the API. - */ - if (fsa_dev_ptr->locked[dd.cnum]) - return -EBUSY; - else { - /* - * Mark the container as no longer being valid. - */ - fsa_dev_ptr->valid[dd.cnum] = 0; - fsa_dev_ptr->devno[dd.cnum] = -1; - return 0; - } -} - -int aac_dev_ioctl(struct aac_dev *dev, int cmd, void *arg) -{ - switch (cmd) { - case FSACTL_QUERY_DISK: - return query_disk(dev, arg); - case FSACTL_DELETE_DISK: - return delete_disk(dev, arg); - case FSACTL_FORCE_DELETE_DISK: - return force_delete_disk(dev, arg); - case 2131: - return aac_get_containers(dev); - default: - return -ENOTTY; - } -} - -/** - * - * aac_srb_callback - * @context: the context set in the fib - here it is scsi cmd - * @fibptr: pointer to the fib - * - * Handles the completion of a scsi command to a non dasd device - * - */ - -static void aac_srb_callback(void *context, struct fib * fibptr) -{ - struct aac_dev *dev; - struct aac_srb_reply *srbreply; - Scsi_Cmnd *scsicmd; - - scsicmd = (Scsi_Cmnd *) context; - dev = (struct aac_dev *)scsicmd->host->hostdata; - - if (fibptr == NULL) - BUG(); - - srbreply = (struct aac_srb_reply *) fib_data(fibptr); - - scsicmd->sense_buffer[0] = '\0'; // initialize sense valid flag to false - // calculate resid for sg - scsicmd->resid = scsicmd->request_bufflen - srbreply->data_xfer_length; - - if(scsicmd->use_sg) - pci_unmap_sg(dev->pdev, - (struct scatterlist *)scsicmd->buffer, - scsicmd->use_sg, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - else if(scsicmd->request_bufflen) - pci_unmap_single(dev->pdev, (ulong)scsicmd->SCp.ptr, scsicmd->request_bufflen, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - - /* - * First check the fib status - */ - - if (le32_to_cpu(srbreply->status) != ST_OK){ - int len; - printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status)); - len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))? - sizeof(scsicmd->sense_buffer):srbreply->sense_data_size; - scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; - memcpy(scsicmd->sense_buffer, srbreply->sense_data, len); - } - - /* - * Next check the srb status - */ - switch( (le32_to_cpu(srbreply->srb_status))&0x3f){ - case SRB_STATUS_ERROR_RECOVERY: - case SRB_STATUS_PENDING: - case SRB_STATUS_SUCCESS: - if(scsicmd->cmnd[0] == INQUIRY ){ - u8 b; - u8 b1; - /* We can't expose disk devices because we can't tell whether they - * are the raw container drives or stand alone drives. If they have - * the removable bit set then we should expose them though. - */ - b = (*(u8*)scsicmd->buffer)&0x1f; - b1 = ((u8*)scsicmd->buffer)[1]; - if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER - || (b==TYPE_DISK && (b1&0x80)) ){ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; - /* - * We will allow disk devices if in RAID/SCSI mode and - * the channel is 2 - */ - } else if((dev->raid_scsi_mode)&&(scsicmd->channel == 2)){ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; - } else { - scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; - } - } else { - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; - } - break; - case SRB_STATUS_DATA_OVERRUN: - switch(scsicmd->cmnd[0]){ - case READ_6: - case WRITE_6: - case READ_10: - case WRITE_10: - case READ_12: - case WRITE_12: - if(le32_to_cpu(srbreply->data_xfer_length) < scsicmd->underflow ) { - printk(KERN_WARNING"aacraid: SCSI CMD underflow\n"); - } else { - printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun\n"); - } - scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; - break; - case INQUIRY: { - u8 b; - u8 b1; - /* We can't expose disk devices because we can't tell whether they - * are the raw container drives or stand alone drives - */ - b = (*(u8*)scsicmd->buffer)&0x0f; - b1 = ((u8*)scsicmd->buffer)[1]; - if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER - || (b==TYPE_DISK && (b1&0x80)) ){ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; - /* - * We will allow disk devices if in RAID/SCSI mode and - * the channel is 2 - */ - } else if((dev->raid_scsi_mode)&&(scsicmd->channel == 2)){ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; - } else { - scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; - } - break; - } - default: - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; - break; - } - break; - case SRB_STATUS_ABORTED: - scsicmd->result = DID_ABORT << 16 | ABORT << 8; - break; - case SRB_STATUS_ABORT_FAILED: - // Not sure about this one - but assuming the hba was trying to abort for some reason - scsicmd->result = DID_ERROR << 16 | ABORT << 8; - break; - case SRB_STATUS_PARITY_ERROR: - scsicmd->result = DID_PARITY << 16 | MSG_PARITY_ERROR << 8; - break; - case SRB_STATUS_NO_DEVICE: - case SRB_STATUS_INVALID_PATH_ID: - case SRB_STATUS_INVALID_TARGET_ID: - case SRB_STATUS_INVALID_LUN: - case SRB_STATUS_SELECTION_TIMEOUT: - scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; - break; - - case SRB_STATUS_COMMAND_TIMEOUT: - case SRB_STATUS_TIMEOUT: - scsicmd->result = DID_TIME_OUT << 16 | COMMAND_COMPLETE << 8; - break; - - case SRB_STATUS_BUSY: - scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; - break; - - case SRB_STATUS_BUS_RESET: - scsicmd->result = DID_RESET << 16 | COMMAND_COMPLETE << 8; - break; - - case SRB_STATUS_MESSAGE_REJECTED: - scsicmd->result = DID_ERROR << 16 | MESSAGE_REJECT << 8; - break; - case SRB_STATUS_REQUEST_FLUSHED: - case SRB_STATUS_ERROR: - case SRB_STATUS_INVALID_REQUEST: - case SRB_STATUS_REQUEST_SENSE_FAILED: - case SRB_STATUS_NO_HBA: - case SRB_STATUS_UNEXPECTED_BUS_FREE: - case SRB_STATUS_PHASE_SEQUENCE_FAILURE: - case SRB_STATUS_BAD_SRB_BLOCK_LENGTH: - case SRB_STATUS_DELAYED_RETRY: - case SRB_STATUS_BAD_FUNCTION: - case SRB_STATUS_NOT_STARTED: - case SRB_STATUS_NOT_IN_USE: - case SRB_STATUS_FORCE_ABORT: - case SRB_STATUS_DOMAIN_VALIDATION_FAIL: - default: -#ifdef AAC_DETAILED_STATUS_INFO - printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",le32_to_cpu(srbreply->srb_status&0x3f),aac_get_status_string(le32_to_cpu(srbreply->srb_status)), scsicmd->cmnd[0], le32_to_cpu(srbreply->scsi_status) ); -#endif - scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; - break; - } - if (le32_to_cpu(srbreply->scsi_status) == 0x02 ){ // Check Condition - int len; - scsicmd->result |= CHECK_CONDITION; - len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))? - sizeof(scsicmd->sense_buffer):srbreply->sense_data_size; - printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", le32_to_cpu(srbreply->status), len); - memcpy(scsicmd->sense_buffer, srbreply->sense_data, len); - } - /* - * OR in the scsi status (already shifted up a bit) - */ - scsicmd->result |= le32_to_cpu(srbreply->scsi_status); - - fib_complete(fibptr); - fib_free(fibptr); - aac_io_done(scsicmd); -} - -/** - * - * aac_send_scb_fib - * @scsicmd: the scsi command block - * - * This routine will form a FIB and fill in the aac_srb from the - * scsicmd passed in. - */ - -static int aac_send_srb_fib(Scsi_Cmnd* scsicmd) -{ - struct fib* cmd_fibcontext; - struct aac_dev* dev; - int status; - struct aac_srb *srbcmd; - u16 fibsize; - u32 flag; - u32 timeout; - - if( scsicmd->target > 15 || scsicmd->lun > 7) { - scsicmd->result = DID_NO_CONNECT << 16; - __aac_io_done(scsicmd); - return 0; - } - - dev = (struct aac_dev *)scsicmd->host->hostdata; - switch(scsicmd->sc_data_direction){ - case SCSI_DATA_WRITE: - flag = SRB_DataOut; - break; - case SCSI_DATA_UNKNOWN: - flag = SRB_DataIn | SRB_DataOut; - break; - case SCSI_DATA_READ: - flag = SRB_DataIn; - break; - case SCSI_DATA_NONE: - default: - flag = SRB_NoDataXfer; - break; - } - - - /* - * Allocate and initialize a Fib then setup a BlockWrite command - */ - if (!(cmd_fibcontext = fib_alloc(dev))) { - scsicmd->result = DID_ERROR << 16; - __aac_io_done(scsicmd); - return -1; - } - fib_init(cmd_fibcontext); - - srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext); - srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); - srbcmd->channel = cpu_to_le32(aac_logical_to_phys(scsicmd->channel)); - srbcmd->target = cpu_to_le32(scsicmd->target); - srbcmd->lun = cpu_to_le32(scsicmd->lun); - srbcmd->flags = cpu_to_le32(flag); - timeout = (scsicmd->timeout-jiffies)/HZ; - if(timeout == 0){ - timeout = 1; - } - srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds - srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter - srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len); - - if( dev->pae_support ==1 ) { - aac_build_sg64(scsicmd, (struct sgmap64*) &srbcmd->sg); - srbcmd->count = cpu_to_le32(scsicmd->request_bufflen); - - memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); - memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len); - /* - * Build Scatter/Gather list - */ - fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry64)); - - /* - * Now send the Fib to the adapter - */ - status = fib_send(ScsiPortCommand64, cmd_fibcontext, fibsize, FsaNormal, 0, 1, - (fib_callback) aac_srb_callback, (void *) scsicmd); - } else { - aac_build_sg(scsicmd, (struct sgmap*)&srbcmd->sg); - srbcmd->count = cpu_to_le32(scsicmd->request_bufflen); - - memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); - memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len); - /* - * Build Scatter/Gather list - */ - fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry)); - - /* - * Now send the Fib to the adapter - */ - status = fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1, - (fib_callback) aac_srb_callback, (void *) scsicmd); - } - /* - * Check that the command queued to the controller - */ - if (status == -EINPROGRESS){ - return 0; - } - - printk(KERN_WARNING "aac_srb: fib_send failed with status: %d\n", status); - /* - * For some reason, the Fib didn't queue, return QUEUE_FULL - */ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | QUEUE_FULL; - __aac_io_done(scsicmd); - - fib_complete(cmd_fibcontext); - fib_free(cmd_fibcontext); - - return -1; -} - -static unsigned long aac_build_sg(Scsi_Cmnd* scsicmd, struct sgmap* psg) -{ - struct aac_dev *dev; - unsigned long byte_count = 0; - - dev = (struct aac_dev *)scsicmd->host->hostdata; - // Get rid of old data - psg->count = cpu_to_le32(0); - psg->sg[0].addr = cpu_to_le32(NULL); - psg->sg[0].count = cpu_to_le32(0); - if (scsicmd->use_sg) { - struct scatterlist *sg; - int i; - int sg_count; - sg = (struct scatterlist *) scsicmd->request_buffer; - - sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - psg->count = cpu_to_le32(sg_count); - - byte_count = 0; - - for (i = 0; i < sg_count; i++) { - psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg)); - psg->sg[i].count = cpu_to_le32(sg_dma_len(sg)); - byte_count += sg_dma_len(sg); - sg++; - } - /* hba wants the size to be exact */ - if(byte_count > scsicmd->request_bufflen){ - psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen); - byte_count = scsicmd->request_bufflen; - } - /* Check for command underflow */ - if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ - printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n", - byte_count, scsicmd->underflow); - } - } - else if(scsicmd->request_bufflen) { - dma_addr_t addr; - addr = pci_map_single(dev->pdev, - scsicmd->request_buffer, - scsicmd->request_bufflen, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - psg->count = cpu_to_le32(1); - psg->sg[0].addr = cpu_to_le32(addr); - psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); - /* Cast to pointer from integer of different size */ - scsicmd->SCp.ptr = (void *)addr; - byte_count = scsicmd->request_bufflen; - } - return byte_count; -} - - -static unsigned long aac_build_sg64(Scsi_Cmnd* scsicmd, struct sgmap64* psg) -{ - struct aac_dev *dev; - unsigned long byte_count = 0; - u64 le_addr; - - dev = (struct aac_dev *)scsicmd->host->hostdata; - // Get rid of old data - psg->count = cpu_to_le32(0); - psg->sg[0].addr[0] = cpu_to_le32(NULL); - psg->sg[0].addr[1] = cpu_to_le32(NULL); - psg->sg[0].count = cpu_to_le32(0); - if (scsicmd->use_sg) { - struct scatterlist *sg; - int i; - int sg_count; - sg = (struct scatterlist *) scsicmd->request_buffer; - - sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - psg->count = cpu_to_le32(sg_count); - - byte_count = 0; - - for (i = 0; i < sg_count; i++) { - le_addr = cpu_to_le64(sg_dma_address(sg)); - psg->sg[i].addr[1] = (u32)(le_addr>>32); - psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff); - psg->sg[i].count = cpu_to_le32(sg_dma_len(sg)); - byte_count += sg_dma_len(sg); - sg++; - } - /* hba wants the size to be exact */ - if(byte_count > scsicmd->request_bufflen){ - psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen); - byte_count = scsicmd->request_bufflen; - } - /* Check for command underflow */ - if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ - printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n", - byte_count, scsicmd->underflow); - } - } - else if(scsicmd->request_bufflen) { - dma_addr_t addr; - addr = pci_map_single(dev->pdev, - scsicmd->request_buffer, - scsicmd->request_bufflen, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - psg->count = cpu_to_le32(1); - le_addr = cpu_to_le64(addr); - psg->sg[0].addr[1] = (u32)(le_addr>>32); - psg->sg[0].addr[0] = (u32)(le_addr & 0xffffffff); - psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); - /* Cast to pointer from integer of different size */ - scsicmd->SCp.ptr = (void *)addr; - byte_count = scsicmd->request_bufflen; - } - return byte_count; -} - -#ifdef AAC_DETAILED_STATUS_INFO - -struct aac_srb_status_info { - u32 status; - char *str; -}; - - -static struct aac_srb_status_info srb_status_info[] = { - { SRB_STATUS_PENDING, "Pending Status"}, - { SRB_STATUS_SUCCESS, "Success"}, - { SRB_STATUS_ABORTED, "Aborted Command"}, - { SRB_STATUS_ABORT_FAILED, "Abort Failed"}, - { SRB_STATUS_ERROR, "Error Event"}, - { SRB_STATUS_BUSY, "Device Busy"}, - { SRB_STATUS_INVALID_REQUEST, "Invalid Request"}, - { SRB_STATUS_INVALID_PATH_ID, "Invalid Path ID"}, - { SRB_STATUS_NO_DEVICE, "No Device"}, - { SRB_STATUS_TIMEOUT, "Timeout"}, - { SRB_STATUS_SELECTION_TIMEOUT, "Selection Timeout"}, - { SRB_STATUS_COMMAND_TIMEOUT, "Command Timeout"}, - { SRB_STATUS_MESSAGE_REJECTED, "Message Rejected"}, - { SRB_STATUS_BUS_RESET, "Bus Reset"}, - { SRB_STATUS_PARITY_ERROR, "Parity Error"}, - { SRB_STATUS_REQUEST_SENSE_FAILED,"Request Sense Failed"}, - { SRB_STATUS_NO_HBA, "No HBA"}, - { SRB_STATUS_DATA_OVERRUN, "Data Overrun/Data Underrun"}, - { SRB_STATUS_UNEXPECTED_BUS_FREE,"Unexpected Bus Free"}, - { SRB_STATUS_PHASE_SEQUENCE_FAILURE,"Phase Error"}, - { SRB_STATUS_BAD_SRB_BLOCK_LENGTH,"Bad Srb Block Length"}, - { SRB_STATUS_REQUEST_FLUSHED, "Request Flushed"}, - { SRB_STATUS_DELAYED_RETRY, "Delayed Retry"}, - { SRB_STATUS_INVALID_LUN, "Invalid LUN"}, - { SRB_STATUS_INVALID_TARGET_ID, "Invalid TARGET ID"}, - { SRB_STATUS_BAD_FUNCTION, "Bad Function"}, - { SRB_STATUS_ERROR_RECOVERY, "Error Recovery"}, - { SRB_STATUS_NOT_STARTED, "Not Started"}, - { SRB_STATUS_NOT_IN_USE, "Not In Use"}, - { SRB_STATUS_FORCE_ABORT, "Force Abort"}, - { SRB_STATUS_DOMAIN_VALIDATION_FAIL,"Domain Validation Failure"}, - { 0xff, "Unknown Error"} -}; - -char *aac_get_status_string(u32 status) -{ - int i; - - for(i=0; i < (sizeof(srb_status_info)/sizeof(struct aac_srb_status_info)); i++ ){ - if(srb_status_info[i].status == status){ - return srb_status_info[i].str; - } - } - - return "Bad Status Code"; -} - -#endif diff --git a/xen/drivers/scsi/aacraid/aacraid.h b/xen/drivers/scsi/aacraid/aacraid.h deleted file mode 100644 index da59eee2fc..0000000000 --- a/xen/drivers/scsi/aacraid/aacraid.h +++ /dev/null @@ -1,1420 +0,0 @@ -//#define dprintk(x) printk x -#if (!defined(dprintk)) -# define dprintk(x) -#endif - -#include -#include - -/*------------------------------------------------------------------------------ - * D E F I N E S - *----------------------------------------------------------------------------*/ - -#define MAXIMUM_NUM_CONTAINERS 31 -#define MAXIMUM_NUM_ADAPTERS 8 - -#define AAC_NUM_FIB 578 -//#define AAC_NUM_IO_FIB 512 -#define AAC_NUM_IO_FIB 100 - -#define AAC_MAX_TARGET (MAXIMUM_NUM_CONTAINERS+1) -//#define AAC_MAX_TARGET (16) -#define AAC_MAX_LUN (8) - -/* - * These macros convert from physical channels to virtual channels - */ -#define CONTAINER_CHANNEL (0) -#define aac_phys_to_logical(x) (x+1) -#define aac_logical_to_phys(x) (x?x-1:0) - -#define AAC_DETAILED_STATUS_INFO - -struct diskparm -{ - int heads; - int sectors; - int cylinders; -}; - - -/* - * DON'T CHANGE THE ORDER, this is set by the firmware - */ - -#define CT_NONE 0 -#define CT_VOLUME 1 -#define CT_MIRROR 2 -#define CT_STRIPE 3 -#define CT_RAID5 4 -#define CT_SSRW 5 -#define CT_SSRO 6 -#define CT_MORPH 7 -#define CT_PASSTHRU 8 -#define CT_RAID4 9 -#define CT_RAID10 10 /* stripe of mirror */ -#define CT_RAID00 11 /* stripe of stripe */ -#define CT_VOLUME_OF_MIRRORS 12 /* volume of mirror */ -#define CT_PSEUDO_RAID 13 /* really raid4 */ -#define CT_LAST_VOLUME_TYPE 14 - -/* - * Types of objects addressable in some fashion by the client. - * This is a superset of those objects handled just by the filesystem - * and includes "raw" objects that an administrator would use to - * configure containers and filesystems. - */ - -#define FT_REG 1 /* regular file */ -#define FT_DIR 2 /* directory */ -#define FT_BLK 3 /* "block" device - reserved */ -#define FT_CHR 4 /* "character special" device - reserved */ -#define FT_LNK 5 /* symbolic link */ -#define FT_SOCK 6 /* socket */ -#define FT_FIFO 7 /* fifo */ -#define FT_FILESYS 8 /* ADAPTEC's "FSA"(tm) filesystem */ -#define FT_DRIVE 9 /* physical disk - addressable in scsi by bus/target/lun */ -#define FT_SLICE 10 /* virtual disk - raw volume - slice */ -#define FT_PARTITION 11 /* FSA partition - carved out of a slice - building block for containers */ -#define FT_VOLUME 12 /* Container - Volume Set */ -#define FT_STRIPE 13 /* Container - Stripe Set */ -#define FT_MIRROR 14 /* Container - Mirror Set */ -#define FT_RAID5 15 /* Container - Raid 5 Set */ -#define FT_DATABASE 16 /* Storage object with "foreign" content manager */ - -/* - * Host side memory scatter gather list - * Used by the adapter for read, write, and readdirplus operations - * We have seperate 32 and 64 bit version because even - * on 64 bit systems not all cards support the 64 bit version - */ -struct sgentry { - u32 addr; /* 32-bit address. */ - u32 count; /* Length. */ -}; - -struct sgentry64 { - u32 addr[2]; /* 64-bit addr. 2 pieces for data alignment */ - u32 count; /* Length. */ -}; - -/* - * SGMAP - * - * This is the SGMAP structure for all commands that use - * 32-bit addressing. - */ - -struct sgmap { - u32 count; - struct sgentry sg[1]; -}; - -struct sgmap64 { - u32 count; - struct sgentry64 sg[1]; -}; - -struct creation_info -{ - u8 buildnum; /* e.g., 588 */ - u8 usec; /* e.g., 588 */ - u8 via; /* e.g., 1 = FSU, - * 2 = API - */ - u8 year; /* e.g., 1997 = 97 */ - u32 date; /* - * unsigned Month :4; // 1 - 12 - * unsigned Day :6; // 1 - 32 - * unsigned Hour :6; // 0 - 23 - * unsigned Minute :6; // 0 - 60 - * unsigned Second :6; // 0 - 60 - */ - u32 serial[2]; /* e.g., 0x1DEADB0BFAFAF001 */ -}; - - -/* - * Define all the constants needed for the communication interface - */ - -/* - * Define how many queue entries each queue will have and the total - * number of entries for the entire communication interface. Also define - * how many queues we support. - * - * This has to match the controller - */ - -#define NUMBER_OF_COMM_QUEUES 8 // 4 command; 4 response -#define HOST_HIGH_CMD_ENTRIES 4 -#define HOST_NORM_CMD_ENTRIES 8 -#define ADAP_HIGH_CMD_ENTRIES 4 -#define ADAP_NORM_CMD_ENTRIES 512 -#define HOST_HIGH_RESP_ENTRIES 4 -#define HOST_NORM_RESP_ENTRIES 512 -#define ADAP_HIGH_RESP_ENTRIES 4 -#define ADAP_NORM_RESP_ENTRIES 8 - -#define TOTAL_QUEUE_ENTRIES \ - (HOST_NORM_CMD_ENTRIES + HOST_HIGH_CMD_ENTRIES + ADAP_NORM_CMD_ENTRIES + ADAP_HIGH_CMD_ENTRIES + \ - HOST_NORM_RESP_ENTRIES + HOST_HIGH_RESP_ENTRIES + ADAP_NORM_RESP_ENTRIES + ADAP_HIGH_RESP_ENTRIES) - - -/* - * Set the queues on a 16 byte alignment - */ - -#define QUEUE_ALIGNMENT 16 - -/* - * The queue headers define the Communication Region queues. These - * are physically contiguous and accessible by both the adapter and the - * host. Even though all queue headers are in the same contiguous block - * they will be represented as individual units in the data structures. - */ - -struct aac_entry { - u32 size; /* Size in bytes of Fib which this QE points to */ - u32 addr; /* Receiver address of the FIB */ -}; - -/* - * The adapter assumes the ProducerIndex and ConsumerIndex are grouped - * adjacently and in that order. - */ - -struct aac_qhdr { - u64 header_addr; /* Address to hand the adapter to access to this queue head */ - u32 *producer; /* The producer index for this queue (host address) */ - u32 *consumer; /* The consumer index for this queue (host address) */ -}; - -/* - * Define all the events which the adapter would like to notify - * the host of. - */ - -#define HostNormCmdQue 1 /* Change in host normal priority command queue */ -#define HostHighCmdQue 2 /* Change in host high priority command queue */ -#define HostNormRespQue 3 /* Change in host normal priority response queue */ -#define HostHighRespQue 4 /* Change in host high priority response queue */ -#define AdapNormRespNotFull 5 -#define AdapHighRespNotFull 6 -#define AdapNormCmdNotFull 7 -#define AdapHighCmdNotFull 8 -#define SynchCommandComplete 9 -#define AdapInternalError 0xfe /* The adapter detected an internal error shutting down */ - -/* - * Define all the events the host wishes to notify the - * adapter of. The first four values much match the Qid the - * corresponding queue. - */ - -#define AdapNormCmdQue 2 -#define AdapHighCmdQue 3 -#define AdapNormRespQue 6 -#define AdapHighRespQue 7 -#define HostShutdown 8 -#define HostPowerFail 9 -#define FatalCommError 10 -#define HostNormRespNotFull 11 -#define HostHighRespNotFull 12 -#define HostNormCmdNotFull 13 -#define HostHighCmdNotFull 14 -#define FastIo 15 -#define AdapPrintfDone 16 - -/* - * Define all the queues that the adapter and host use to communicate - * Number them to match the physical queue layout. - */ - -enum aac_queue_types { - HostNormCmdQueue = 0, /* Adapter to host normal priority command traffic */ - HostHighCmdQueue, /* Adapter to host high priority command traffic */ - AdapNormCmdQueue, /* Host to adapter normal priority command traffic */ - AdapHighCmdQueue, /* Host to adapter high priority command traffic */ - HostNormRespQueue, /* Adapter to host normal priority response traffic */ - HostHighRespQueue, /* Adapter to host high priority response traffic */ - AdapNormRespQueue, /* Host to adapter normal priority response traffic */ - AdapHighRespQueue /* Host to adapter high priority response traffic */ -}; - -/* - * Assign type values to the FSA communication data structures - */ - -#define FIB_MAGIC 0x0001 - -/* - * Define the priority levels the FSA communication routines support. - */ - -#define FsaNormal 1 -#define FsaHigh 2 - -/* - * Define the FIB. The FIB is the where all the requested data and - * command information are put to the application on the FSA adapter. - */ - -struct aac_fibhdr { - u32 XferState; // Current transfer state for this CCB - u16 Command; // Routing information for the destination - u8 StructType; // Type FIB - u8 Flags; // Flags for FIB - u16 Size; // Size of this FIB in bytes - u16 SenderSize; // Size of the FIB in the sender (for response sizing) - u32 SenderFibAddress; // Host defined data in the FIB - u32 ReceiverFibAddress; // Logical address of this FIB for the adapter - u32 SenderData; // Place holder for the sender to store data - union { - struct { - u32 _ReceiverTimeStart; // Timestamp for receipt of fib - u32 _ReceiverTimeDone; // Timestamp for completion of fib - } _s; -// struct aac_list_head _FibLinks; // Used to link Adapter Initiated Fibs on the host - } _u; -}; - -//#define FibLinks _u._FibLinks - -#define FIB_DATA_SIZE_IN_BYTES (512 - sizeof(struct aac_fibhdr)) - - -struct hw_fib { - struct aac_fibhdr header; - u8 data[FIB_DATA_SIZE_IN_BYTES]; // Command specific data -}; - -/* - * FIB commands - */ - -#define TestCommandResponse 1 -#define TestAdapterCommand 2 -/* - * Lowlevel and comm commands - */ -#define LastTestCommand 100 -#define ReinitHostNormCommandQueue 101 -#define ReinitHostHighCommandQueue 102 -#define ReinitHostHighRespQueue 103 -#define ReinitHostNormRespQueue 104 -#define ReinitAdapNormCommandQueue 105 -#define ReinitAdapHighCommandQueue 107 -#define ReinitAdapHighRespQueue 108 -#define ReinitAdapNormRespQueue 109 -#define InterfaceShutdown 110 -#define DmaCommandFib 120 -#define StartProfile 121 -#define TermProfile 122 -#define SpeedTest 123 -#define TakeABreakPt 124 -#define RequestPerfData 125 -#define SetInterruptDefTimer 126 -#define SetInterruptDefCount 127 -#define GetInterruptDefStatus 128 -#define LastCommCommand 129 -/* - * Filesystem commands - */ -#define NuFileSystem 300 -#define UFS 301 -#define HostFileSystem 302 -#define LastFileSystemCommand 303 -/* - * Container Commands - */ -#define ContainerCommand 500 -#define ContainerCommand64 501 -/* - * Cluster Commands - */ -#define ClusterCommand 550 -/* - * Scsi Port commands (scsi passthrough) - */ -#define ScsiPortCommand 600 -#define ScsiPortCommand64 601 -/* - * Misc house keeping and generic adapter initiated commands - */ -#define AifRequest 700 -#define CheckRevision 701 -#define FsaHostShutdown 702 -#define RequestAdapterInfo 703 -#define IsAdapterPaused 704 -#define SendHostTime 705 -#define LastMiscCommand 706 - -// -// Commands that will target the failover level on the FSA adapter -// - -enum fib_xfer_state { - HostOwned = (1<<0), - AdapterOwned = (1<<1), - FibInitialized = (1<<2), - FibEmpty = (1<<3), - AllocatedFromPool = (1<<4), - SentFromHost = (1<<5), - SentFromAdapter = (1<<6), - ResponseExpected = (1<<7), - NoResponseExpected = (1<<8), - AdapterProcessed = (1<<9), - HostProcessed = (1<<10), - HighPriority = (1<<11), - NormalPriority = (1<<12), - Async = (1<<13), - AsyncIo = (1<<13), // rpbfix: remove with new regime - PageFileIo = (1<<14), // rpbfix: remove with new regime - ShutdownRequest = (1<<15), - LazyWrite = (1<<16), // rpbfix: remove with new regime - AdapterMicroFib = (1<<17), - BIOSFibPath = (1<<18), - FastResponseCapable = (1<<19), - ApiFib = (1<<20) // Its an API Fib. -}; - -/* - * The following defines needs to be updated any time there is an - * incompatible change made to the aac_init structure. - */ - -#define ADAPTER_INIT_STRUCT_REVISION 3 - -struct aac_init -{ - u32 InitStructRevision; - u32 MiniPortRevision; - u32 fsrev; - u32 CommHeaderAddress; - u32 FastIoCommAreaAddress; - u32 AdapterFibsPhysicalAddress; - u32 AdapterFibsVirtualAddress; - u32 AdapterFibsSize; - u32 AdapterFibAlign; - u32 printfbuf; - u32 printfbufsiz; - u32 HostPhysMemPages; // number of 4k pages of host physical memory - u32 HostElapsedSeconds; // number of seconds since 1970. -}; - -enum aac_log_level { - LOG_INIT = 10, - LOG_INFORMATIONAL = 20, - LOG_WARNING = 30, - LOG_LOW_ERROR = 40, - LOG_MEDIUM_ERROR = 50, - LOG_HIGH_ERROR = 60, - LOG_PANIC = 70, - LOG_DEBUG = 80, - LOG_WINDBG_PRINT = 90 -}; - -#define FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT 0x030b -#define FSAFS_NTC_FIB_CONTEXT 0x030c - -struct aac_dev; - -struct adapter_ops -{ - void (*adapter_interrupt)(struct aac_dev *dev); - void (*adapter_notify)(struct aac_dev *dev, u32 event); - void (*adapter_enable_int)(struct aac_dev *dev, u32 event); - void (*adapter_disable_int)(struct aac_dev *dev, u32 event); - int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 *status); -}; - -/* - * Define which interrupt handler needs to be installed - */ - -struct aac_driver_ident -{ - u16 vendor; - u16 device; - u16 subsystem_vendor; - u16 subsystem_device; - int (*init)(struct aac_dev *dev, unsigned long num); - char * name; - char * vname; - char * model; - u16 channels; - int quirks; -#define AAC_QUIRK_31BIT 1 -}; - -/* - * The adapter interface specs all queues to be located in the same - * physically contigous block. The host structure that defines the - * commuication queues will assume they are each a seperate physically - * contigous memory region that will support them all being one big - * contigous block. - * There is a command and response queue for each level and direction of - * commuication. These regions are accessed by both the host and adapter. - */ - -struct aac_queue { - u64 logical; /* This is the address we give the adapter */ - struct aac_entry *base; /* This is the system virtual address */ - struct aac_qhdr headers; /* A pointer to the producer and consumer queue headers for this queue */ - u32 entries; /* Number of queue entries on this queue */ -#if 0 - wait_queue_head_t qfull; /* Event to wait on if the queue is full */ - wait_queue_head_t cmdready; /* Indicates there is a Command ready from the adapter on this queue. */ -#endif /* This is only valid for adapter to host command queues. */ - spinlock_t *lock; /* Spinlock for this queue must take this lock before accessing the lock */ - spinlock_t lockdata; /* Actual lock (used only on one side of the lock) */ - unsigned long SavedIrql; /* Previous IRQL when the spin lock is taken */ - u32 padding; /* Padding - FIXME - can remove I believe */ - struct list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */ - /* only valid for command queues which receive entries from the adapter. */ - struct list_head pendingq; /* A queue of outstanding fib's to the adapter. */ - unsigned long numpending; /* Number of entries on outstanding queue. */ - struct aac_dev * dev; /* Back pointer to adapter structure */ -}; - -/* - * Message queues. The order here is important, see also the - * queue type ordering - */ - -struct aac_queue_block -{ - struct aac_queue queue[8]; -}; - -/* - * SaP1 Message Unit Registers - */ - -struct sa_drawbridge_CSR { - // Offset | Name - u32 reserved[10]; // 00h-27h | Reserved - u8 LUT_Offset; // 28h | Looup Table Offset - u8 reserved1[3]; // 29h-2bh | Reserved - u32 LUT_Data; // 2ch | Looup Table Data - u32 reserved2[26]; // 30h-97h | Reserved - u16 PRICLEARIRQ; // 98h | Primary Clear Irq - u16 SECCLEARIRQ; // 9ah | Secondary Clear Irq - u16 PRISETIRQ; // 9ch | Primary Set Irq - u16 SECSETIRQ; // 9eh | Secondary Set Irq - u16 PRICLEARIRQMASK; // a0h | Primary Clear Irq Mask - u16 SECCLEARIRQMASK; // a2h | Secondary Clear Irq Mask - u16 PRISETIRQMASK; // a4h | Primary Set Irq Mask - u16 SECSETIRQMASK; // a6h | Secondary Set Irq Mask - u32 MAILBOX0; // a8h | Scratchpad 0 - u32 MAILBOX1; // ach | Scratchpad 1 - u32 MAILBOX2; // b0h | Scratchpad 2 - u32 MAILBOX3; // b4h | Scratchpad 3 - u32 MAILBOX4; // b8h | Scratchpad 4 - u32 MAILBOX5; // bch | Scratchpad 5 - u32 MAILBOX6; // c0h | Scratchpad 6 - u32 MAILBOX7; // c4h | Scratchpad 7 - - u32 ROM_Setup_Data; // c8h | Rom Setup and Data - u32 ROM_Control_Addr; // cch | Rom Control and Address - - u32 reserved3[12]; // d0h-ffh | reserved - u32 LUT[64]; // 100h-1ffh| Lookup Table Entries - - // - // TO DO - // need to add DMA, I2O, UART, etc registers form 80h to 364h - // - -}; - -#define Mailbox0 SaDbCSR.MAILBOX0 -#define Mailbox1 SaDbCSR.MAILBOX1 -#define Mailbox2 SaDbCSR.MAILBOX2 -#define Mailbox3 SaDbCSR.MAILBOX3 -#define Mailbox4 SaDbCSR.MAILBOX4 -#define Mailbox5 SaDbCSR.MAILBOX5 -#define Mailbox7 SaDbCSR.MAILBOX7 - -#define DoorbellReg_p SaDbCSR.PRISETIRQ -#define DoorbellReg_s SaDbCSR.SECSETIRQ -#define DoorbellClrReg_p SaDbCSR.PRICLEARIRQ - - -#define DOORBELL_0 cpu_to_le16(0x0001) -#define DOORBELL_1 cpu_to_le16(0x0002) -#define DOORBELL_2 cpu_to_le16(0x0004) -#define DOORBELL_3 cpu_to_le16(0x0008) -#define DOORBELL_4 cpu_to_le16(0x0010) -#define DOORBELL_5 cpu_to_le16(0x0020) -#define DOORBELL_6 cpu_to_le16(0x0040) - - -#define PrintfReady DOORBELL_5 -#define PrintfDone DOORBELL_5 - -struct sa_registers { - struct sa_drawbridge_CSR SaDbCSR; /* 98h - c4h */ -}; - - -#define Sa_MINIPORT_REVISION 1 - -#define sa_readw(AEP, CSR) readl(&((AEP)->regs.sa->CSR)) -#define sa_readl(AEP, CSR) readl(&((AEP)->regs.sa->CSR)) -#define sa_writew(AEP, CSR, value) writew(value, &((AEP)->regs.sa->CSR)) -#define sa_writel(AEP, CSR, value) writel(value, &((AEP)->regs.sa->CSR)) - -/* - * Rx Message Unit Registers - */ - -struct rx_mu_registers { - // Local | PCI* | Name - // | | - u32 ARSR; // 1300h | 00h | APIC Register Select Register - u32 reserved0; // 1304h | 04h | Reserved - u32 AWR; // 1308h | 08h | APIC Window Register - u32 reserved1; // 130Ch | 0Ch | Reserved - u32 IMRx[2]; // 1310h | 10h | Inbound Message Registers - u32 OMRx[2]; // 1318h | 18h | Outbound Message Registers - u32 IDR; // 1320h | 20h | Inbound Doorbell Register - u32 IISR; // 1324h | 24h | Inbound Interrupt Status Register - u32 IIMR; // 1328h | 28h | Inbound Interrupt Mask Register - u32 ODR; // 132Ch | 2Ch | Outbound Doorbell Register - u32 OISR; // 1330h | 30h | Outbound Interrupt Status Register - u32 OIMR; // 1334h | 34h | Outbound Interrupt Mask Register - // * Must access through ATU Inbound Translation Window -}; - -struct rx_inbound { - u32 Mailbox[8]; -}; - -#define InboundMailbox0 IndexRegs.Mailbox[0] -#define InboundMailbox1 IndexRegs.Mailbox[1] -#define InboundMailbox2 IndexRegs.Mailbox[2] -#define InboundMailbox3 IndexRegs.Mailbox[3] -#define InboundMailbox4 IndexRegs.Mailbox[4] - -#define INBOUNDDOORBELL_0 cpu_to_le32(0x00000001) -#define INBOUNDDOORBELL_1 cpu_to_le32(0x00000002) -#define INBOUNDDOORBELL_2 cpu_to_le32(0x00000004) -#define INBOUNDDOORBELL_3 cpu_to_le32(0x00000008) -#define INBOUNDDOORBELL_4 cpu_to_le32(0x00000010) -#define INBOUNDDOORBELL_5 cpu_to_le32(0x00000020) -#define INBOUNDDOORBELL_6 cpu_to_le32(0x00000040) - -#define OUTBOUNDDOORBELL_0 cpu_to_le32(0x00000001) -#define OUTBOUNDDOORBELL_1 cpu_to_le32(0x00000002) -#define OUTBOUNDDOORBELL_2 cpu_to_le32(0x00000004) -#define OUTBOUNDDOORBELL_3 cpu_to_le32(0x00000008) -#define OUTBOUNDDOORBELL_4 cpu_to_le32(0x00000010) - -#define InboundDoorbellReg MUnit.IDR -#define OutboundDoorbellReg MUnit.ODR - -struct rx_registers { - struct rx_mu_registers MUnit; // 1300h - 1334h - u32 reserved1[6]; // 1338h - 134ch - struct rx_inbound IndexRegs; -}; - -#define rx_readb(AEP, CSR) readb(&((AEP)->regs.rx->CSR)) -#define rx_readl(AEP, CSR) readl(&((AEP)->regs.rx->CSR)) -#define rx_writeb(AEP, CSR, value) writeb(value, &((AEP)->regs.rx->CSR)) -#define rx_writel(AEP, CSR, value) writel(value, &((AEP)->regs.rx->CSR)) - -struct fib; - -typedef void (*fib_callback)(void *ctxt, struct fib *fibctx); - -struct aac_fib_context { - s16 type; // used for verification of structure - s16 size; - ulong jiffies; // used for cleanup - dmb changed to ulong - struct list_head next; // used to link context's into a linked list -#if 0 - struct semaphore wait_sem; // this is used to wait for the next fib to arrive. -#endif - int wait; // Set to true when thread is in WaitForSingleObject - unsigned long count; // total number of FIBs on FibList - struct list_head fib_list; // this holds fibs which should be 32 bit addresses -}; - -struct fsa_scsi_hba { - u32 size[MAXIMUM_NUM_CONTAINERS]; - u32 type[MAXIMUM_NUM_CONTAINERS]; - u8 valid[MAXIMUM_NUM_CONTAINERS]; - u8 ro[MAXIMUM_NUM_CONTAINERS]; - u8 locked[MAXIMUM_NUM_CONTAINERS]; - u8 deleted[MAXIMUM_NUM_CONTAINERS]; - s32 devno[MAXIMUM_NUM_CONTAINERS]; -}; - -struct fib { - void *next; /* this is used by the allocator */ - s16 type; - s16 size; - /* - * The Adapter that this I/O is destined for. - */ - struct aac_dev *dev; -#if 0 - /* - * This is the event the sendfib routine will wait on if the - * caller did not pass one and this is synch io. - */ - struct semaphore event_wait; -#endif - spinlock_t event_lock; - - u32 done; /* gets set to 1 when fib is complete */ - fib_callback callback; - void *callback_data; - u32 flags; // u32 dmb was ulong - /* - * The following is used to put this fib context onto the - * Outstanding I/O queue. - */ - struct list_head queue; - /* - * And for the internal issue/reply queues (we may be able - * to merge these two) - */ - struct list_head fiblink; - void *data; - struct hw_fib *hw_fib; /* Actual shared object */ - dma_addr_t hw_fib_pa; /* physical address of hw_fib*/ -}; - -/* - * Adapter Information Block - * - * This is returned by the RequestAdapterInfo block - */ - -struct aac_adapter_info -{ - u32 platform; - u32 cpu; - u32 subcpu; - u32 clock; - u32 execmem; - u32 buffermem; - u32 totalmem; - u32 kernelrev; - u32 kernelbuild; - u32 monitorrev; - u32 monitorbuild; - u32 hwrev; - u32 hwbuild; - u32 biosrev; - u32 biosbuild; - u32 cluster; - u32 clusterchannelmask; - u32 serial[2]; - u32 battery; - u32 options; - u32 OEM; -}; - -/* - * Battery platforms - */ -#define AAC_BAT_REQ_PRESENT (1) -#define AAC_BAT_REQ_NOTPRESENT (2) -#define AAC_BAT_OPT_PRESENT (3) -#define AAC_BAT_OPT_NOTPRESENT (4) -#define AAC_BAT_NOT_SUPPORTED (5) -/* - * cpu types - */ -#define AAC_CPU_SIMULATOR (1) -#define AAC_CPU_I960 (2) -#define AAC_CPU_STRONGARM (3) - -/* - * Supported Options - */ -#define AAC_OPT_SNAPSHOT cpu_to_le32(1) -#define AAC_OPT_CLUSTERS cpu_to_le32(1<<1) -#define AAC_OPT_WRITE_CACHE cpu_to_le32(1<<2) -#define AAC_OPT_64BIT_DATA cpu_to_le32(1<<3) -#define AAC_OPT_HOST_TIME_FIB cpu_to_le32(1<<4) -#define AAC_OPT_RAID50 cpu_to_le32(1<<5) -#define AAC_OPT_4GB_WINDOW cpu_to_le32(1<<6) -#define AAC_OPT_SCSI_UPGRADEABLE cpu_to_le32(1<<7) -#define AAC_OPT_SOFT_ERR_REPORT cpu_to_le32(1<<8) -#define AAC_OPT_SUPPORTED_RECONDITION cpu_to_le32(1<<9) -#define AAC_OPT_SGMAP_HOST64 cpu_to_le32(1<<10) -#define AAC_OPT_ALARM cpu_to_le32(1<<11) -#define AAC_OPT_NONDASD cpu_to_le32(1<<12) -#define AAC_OPT_SCSI_MANAGED cpu_to_le32(1<<13) -#define AAC_OPT_RAID_SCSI_MODE cpu_to_le32(1<<14) -#define AAC_OPT_SUPPLEMENT_ADAPTER_INFO cpu_to_le32(1<<15) - -struct aac_dev -{ - struct aac_dev *next; - const char *name; - int id; - - u16 irq_mask; - /* - * Map for 128 fib objects (64k) - */ - dma_addr_t hw_fib_pa; - struct hw_fib *hw_fib_va; - ulong fib_base_va; - /* - * Fib Headers - */ - struct fib *fibs; - - struct fib *free_fib; - struct fib *timeout_fib; - spinlock_t fib_lock; - - struct aac_queue_block *queues; - /* - * The user API will use an IOCTL to register itself to receive - * FIBs from the adapter. The following list is used to keep - * track of all the threads that have requested these FIBs. The - * mutex is used to synchronize access to all data associated - * with the adapter fibs. - */ - struct list_head fib_list; - - struct adapter_ops a_ops; - unsigned long fsrev; /* Main driver's revision number */ - - struct aac_init *init; /* Holds initialization info to communicate with adapter */ - dma_addr_t init_pa; /* Holds physical address of the init struct */ - - struct pci_dev *pdev; /* Our PCI interface */ - void * printfbuf; /* pointer to buffer used for printf's from the adapter */ - void * comm_addr; /* Base address of Comm area */ - dma_addr_t comm_phys; /* Physical Address of Comm area */ - size_t comm_size; - - struct Scsi_Host *scsi_host_ptr; - struct fsa_scsi_hba fsa_dev; -#if 0 - pid_t thread_pid; -#endif - int cardtype; - - /* - * The following is the device specific extension. - */ - union - { - struct sa_registers *sa; - struct rx_registers *rx; - } regs; - /* - * The following is the number of the individual adapter - */ - u32 devnum; - u32 aif_thread; -#if 0 - struct completion aif_completion; -#endif - struct aac_adapter_info adapter_info; - /* These are in adapter info but they are in the io flow so - * lets break them out so we don't have to do an AND to check them - */ - u8 nondasd_support; - u8 pae_support; - u8 raid_scsi_mode; -}; - -#define AllocateAndMapFibSpace(dev, MapFibContext) \ - dev->a_ops.AllocateAndMapFibSpace(dev, MapFibContext) - -#define UnmapAndFreeFibSpace(dev, MapFibContext) \ - dev->a_ops.UnmapAndFreeFibSpace(dev, MapFibContext) - -#define aac_adapter_interrupt(dev) \ - dev->a_ops.adapter_interrupt(dev) - -#define aac_adapter_notify(dev, event) \ - dev->a_ops.adapter_notify(dev, event) - -#define aac_adapter_enable_int(dev, event) \ - dev->a_ops.adapter_enable_int(dev, event) - -#define aac_adapter_disable_int(dev, event) \ - dev->a_ops.adapter_disable_int(dev, event) - - - -#define FIB_CONTEXT_FLAG_TIMED_OUT (0x00000001) - -/* - * Define the command values - */ - -#define Null 0 -#define GetAttributes 1 -#define SetAttributes 2 -#define Lookup 3 -#define ReadLink 4 -#define Read 5 -#define Write 6 -#define Create 7 -#define MakeDirectory 8 -#define SymbolicLink 9 -#define MakeNode 10 -#define Removex 11 -#define RemoveDirectoryx 12 -#define Rename 13 -#define Link 14 -#define ReadDirectory 15 -#define ReadDirectoryPlus 16 -#define FileSystemStatus 17 -#define FileSystemInfo 18 -#define PathConfigure 19 -#define Commit 20 -#define Mount 21 -#define UnMount 22 -#define Newfs 23 -#define FsCheck 24 -#define FsSync 25 -#define SimReadWrite 26 -#define SetFileSystemStatus 27 -#define BlockRead 28 -#define BlockWrite 29 -#define NvramIoctl 30 -#define FsSyncWait 31 -#define ClearArchiveBit 32 -#define SetAcl 33 -#define GetAcl 34 -#define AssignAcl 35 -#define FaultInsertion 36 /* Fault Insertion Command */ -#define CrazyCache 37 /* Crazycache */ - -#define MAX_FSACOMMAND_NUM 38 - - -/* - * Define the status returns. These are very unixlike although - * most are not in fact used - */ - -#define ST_OK 0 -#define ST_PERM 1 -#define ST_NOENT 2 -#define ST_IO 5 -#define ST_NXIO 6 -#define ST_E2BIG 7 -#define ST_ACCES 13 -#define ST_EXIST 17 -#define ST_XDEV 18 -#define ST_NODEV 19 -#define ST_NOTDIR 20 -#define ST_ISDIR 21 -#define ST_INVAL 22 -#define ST_FBIG 27 -#define ST_NOSPC 28 -#define ST_ROFS 30 -#define ST_MLINK 31 -#define ST_WOULDBLOCK 35 -#define ST_NAMETOOLONG 63 -#define ST_NOTEMPTY 66 -#define ST_DQUOT 69 -#define ST_STALE 70 -#define ST_REMOTE 71 -#define ST_BADHANDLE 10001 -#define ST_NOT_SYNC 10002 -#define ST_BAD_COOKIE 10003 -#define ST_NOTSUPP 10004 -#define ST_TOOSMALL 10005 -#define ST_SERVERFAULT 10006 -#define ST_BADTYPE 10007 -#define ST_JUKEBOX 10008 -#define ST_NOTMOUNTED 10009 -#define ST_MAINTMODE 10010 -#define ST_STALEACL 10011 - -/* - * On writes how does the client want the data written. - */ - -#define CACHE_CSTABLE 1 -#define CACHE_UNSTABLE 2 - -/* - * Lets the client know at which level the data was commited on - * a write request - */ - -#define CMFILE_SYNCH_NVRAM 1 -#define CMDATA_SYNCH_NVRAM 2 -#define CMFILE_SYNCH 3 -#define CMDATA_SYNCH 4 -#define CMUNSTABLE 5 - -struct aac_read -{ - u32 command; - u32 cid; - u32 block; - u32 count; - struct sgmap sg; // Must be last in struct because it is variable -}; - -struct aac_read64 -{ - u32 command; - u16 cid; - u16 sector_count; - u32 block; - u16 pad; - u16 flags; - struct sgmap64 sg; // Must be last in struct because it is variable -}; - -struct aac_read_reply -{ - u32 status; - u32 count; -}; - -struct aac_write -{ - u32 command; - u32 cid; - u32 block; - u32 count; - u32 stable; // Not used - struct sgmap sg; // Must be last in struct because it is variable -}; - -struct aac_write64 -{ - u32 command; - u16 cid; - u16 sector_count; - u32 block; - u16 pad; - u16 flags; - struct sgmap64 sg; // Must be last in struct because it is variable -}; -struct aac_write_reply -{ - u32 status; - u32 count; - u32 committed; -}; - -struct aac_srb -{ - u32 function; - u32 channel; - u32 target; - u32 lun; - u32 timeout; - u32 flags; - u32 count; // Data xfer size - u32 retry_limit; - u32 cdb_size; - u8 cdb[16]; - struct sgmap sg; -}; - - - -#define AAC_SENSE_BUFFERSIZE 30 - -struct aac_srb_reply -{ - u32 status; - u32 srb_status; - u32 scsi_status; - u32 data_xfer_length; - u32 sense_data_size; - u8 sense_data[AAC_SENSE_BUFFERSIZE]; // Can this be SCSI_SENSE_BUFFERSIZE -}; -/* - * SRB Flags - */ -#define SRB_NoDataXfer 0x0000 -#define SRB_DisableDisconnect 0x0004 -#define SRB_DisableSynchTransfer 0x0008 -#define SRB_BypassFrozenQueue 0x0010 -#define SRB_DisableAutosense 0x0020 -#define SRB_DataIn 0x0040 -#define SRB_DataOut 0x0080 - -/* - * SRB Functions - set in aac_srb->function - */ -#define SRBF_ExecuteScsi 0x0000 -#define SRBF_ClaimDevice 0x0001 -#define SRBF_IO_Control 0x0002 -#define SRBF_ReceiveEvent 0x0003 -#define SRBF_ReleaseQueue 0x0004 -#define SRBF_AttachDevice 0x0005 -#define SRBF_ReleaseDevice 0x0006 -#define SRBF_Shutdown 0x0007 -#define SRBF_Flush 0x0008 -#define SRBF_AbortCommand 0x0010 -#define SRBF_ReleaseRecovery 0x0011 -#define SRBF_ResetBus 0x0012 -#define SRBF_ResetDevice 0x0013 -#define SRBF_TerminateIO 0x0014 -#define SRBF_FlushQueue 0x0015 -#define SRBF_RemoveDevice 0x0016 -#define SRBF_DomainValidation 0x0017 - -/* - * SRB SCSI Status - set in aac_srb->scsi_status - */ -#define SRB_STATUS_PENDING 0x00 -#define SRB_STATUS_SUCCESS 0x01 -#define SRB_STATUS_ABORTED 0x02 -#define SRB_STATUS_ABORT_FAILED 0x03 -#define SRB_STATUS_ERROR 0x04 -#define SRB_STATUS_BUSY 0x05 -#define SRB_STATUS_INVALID_REQUEST 0x06 -#define SRB_STATUS_INVALID_PATH_ID 0x07 -#define SRB_STATUS_NO_DEVICE 0x08 -#define SRB_STATUS_TIMEOUT 0x09 -#define SRB_STATUS_SELECTION_TIMEOUT 0x0A -#define SRB_STATUS_COMMAND_TIMEOUT 0x0B -#define SRB_STATUS_MESSAGE_REJECTED 0x0D -#define SRB_STATUS_BUS_RESET 0x0E -#define SRB_STATUS_PARITY_ERROR 0x0F -#define SRB_STATUS_REQUEST_SENSE_FAILED 0x10 -#define SRB_STATUS_NO_HBA 0x11 -#define SRB_STATUS_DATA_OVERRUN 0x12 -#define SRB_STATUS_UNEXPECTED_BUS_FREE 0x13 -#define SRB_STATUS_PHASE_SEQUENCE_FAILURE 0x14 -#define SRB_STATUS_BAD_SRB_BLOCK_LENGTH 0x15 -#define SRB_STATUS_REQUEST_FLUSHED 0x16 -#define SRB_STATUS_DELAYED_RETRY 0x17 -#define SRB_STATUS_INVALID_LUN 0x20 -#define SRB_STATUS_INVALID_TARGET_ID 0x21 -#define SRB_STATUS_BAD_FUNCTION 0x22 -#define SRB_STATUS_ERROR_RECOVERY 0x23 -#define SRB_STATUS_NOT_STARTED 0x24 -#define SRB_STATUS_NOT_IN_USE 0x30 -#define SRB_STATUS_FORCE_ABORT 0x31 -#define SRB_STATUS_DOMAIN_VALIDATION_FAIL 0x32 - -/* - * Object-Server / Volume-Manager Dispatch Classes - */ - -#define VM_Null 0 -#define VM_NameServe 1 -#define VM_ContainerConfig 2 -#define VM_Ioctl 3 -#define VM_FilesystemIoctl 4 -#define VM_CloseAll 5 -#define VM_CtBlockRead 6 -#define VM_CtBlockWrite 7 -#define VM_SliceBlockRead 8 /* raw access to configured "storage objects" */ -#define VM_SliceBlockWrite 9 -#define VM_DriveBlockRead 10 /* raw access to physical devices */ -#define VM_DriveBlockWrite 11 -#define VM_EnclosureMgt 12 /* enclosure management */ -#define VM_Unused 13 /* used to be diskset management */ -#define VM_CtBlockVerify 14 -#define VM_CtPerf 15 /* performance test */ -#define VM_CtBlockRead64 16 -#define VM_CtBlockWrite64 17 -#define VM_CtBlockVerify64 18 -#define VM_CtHostRead64 19 -#define VM_CtHostWrite64 20 - -#define MAX_VMCOMMAND_NUM 21 /* used for sizing stats array - leave last */ - -/* - * Descriptive information (eg, vital stats) - * that a content manager might report. The - * FileArray filesystem component is one example - * of a content manager. Raw mode might be - * another. - */ - -struct aac_fsinfo { - u32 fsTotalSize; /* Consumed by fs, incl. metadata */ - u32 fsBlockSize; - u32 fsFragSize; - u32 fsMaxExtendSize; - u32 fsSpaceUnits; - u32 fsMaxNumFiles; - u32 fsNumFreeFiles; - u32 fsInodeDensity; -}; /* valid iff ObjType == FT_FILESYS && !(ContentState & FSCS_NOTCLEAN) */ - -union aac_contentinfo { - struct aac_fsinfo filesys; /* valid iff ObjType == FT_FILESYS && !(ContentState & FSCS_NOTCLEAN) */ -}; - -/* - * Query for "mountable" objects, ie, objects that are typically - * associated with a drive letter on the client (host) side. - */ - -struct aac_mntent { - u32 oid; - u8 name[16]; // if applicable - struct creation_info create_info; // if applicable - u32 capacity; - u32 vol; // substrate structure - u32 obj; // FT_FILESYS, FT_DATABASE, etc. - u32 state; // unready for mounting, readonly, etc. - union aac_contentinfo fileinfo; // Info specific to content manager (eg, filesystem) - u32 altoid; // != oid <==> snapshot or broken mirror exists -}; - -#define FSCS_NOTCLEAN 0x0001 /* fsck is neccessary before mounting */ -#define FSCS_READONLY 0x0002 /* possible result of broken mirror */ -#define FSCS_HIDDEN 0x0004 /* should be ignored - set during a clear */ - -struct aac_query_mount { - u32 command; - u32 type; - u32 count; -}; - -struct aac_mount { - u32 status; - u32 type; /* should be same as that requested */ - u32 count; - struct aac_mntent mnt[1]; -}; - -/* - * The following command is sent to shut down each container. - */ - -struct aac_close { - u32 command; - u32 cid; -}; - -struct aac_query_disk -{ - s32 cnum; - s32 bus; - s32 target; - s32 lun; - u32 valid; - u32 locked; - u32 deleted; - s32 instance; - s8 name[10]; - u32 unmapped; -}; - -struct aac_delete_disk { - u32 disknum; - u32 cnum; -}; - -struct fib_ioctl -{ - char *fibctx; - int wait; - char *fib; -}; - -struct revision -{ - u32 compat; - u32 version; - u32 build; -}; - -/* - * Ugly - non Linux like ioctl coding for back compat. - */ - -#define CTL_CODE(function, method) ( \ - (4<< 16) | ((function) << 2) | (method) \ -) - -/* - * Define the method codes for how buffers are passed for I/O and FS - * controls - */ - -#define METHOD_BUFFERED 0 -#define METHOD_NEITHER 3 - -/* - * Filesystem ioctls - */ - -#define FSACTL_SENDFIB CTL_CODE(2050, METHOD_BUFFERED) -#define FSACTL_SEND_RAW_SRB CTL_CODE(2067, METHOD_BUFFERED) -#define FSACTL_DELETE_DISK 0x163 -#define FSACTL_QUERY_DISK 0x173 -#define FSACTL_OPEN_GET_ADAPTER_FIB CTL_CODE(2100, METHOD_BUFFERED) -#define FSACTL_GET_NEXT_ADAPTER_FIB CTL_CODE(2101, METHOD_BUFFERED) -#define FSACTL_CLOSE_GET_ADAPTER_FIB CTL_CODE(2102, METHOD_BUFFERED) -#define FSACTL_MINIPORT_REV_CHECK CTL_CODE(2107, METHOD_BUFFERED) -#define FSACTL_GET_PCI_INFO CTL_CODE(2119, METHOD_BUFFERED) -#define FSACTL_FORCE_DELETE_DISK CTL_CODE(2120, METHOD_NEITHER) - - -struct aac_common -{ - /* - * If this value is set to 1 then interrupt moderation will occur - * in the base commuication support. - */ - u32 irq_mod; - u32 peak_fibs; - u32 zero_fibs; - u32 fib_timeouts; - /* - * Statistical counters in debug mode - */ -#ifdef DBG - u32 FibsSent; - u32 FibRecved; - u32 NoResponseSent; - u32 NoResponseRecved; - u32 AsyncSent; - u32 AsyncRecved; - u32 NormalSent; - u32 NormalRecved; -#endif -}; - -extern struct aac_common aac_config; - - -/* - * The following macro is used when sending and receiving FIBs. It is - * only used for debugging. - */ - -#if DBG -#define FIB_COUNTER_INCREMENT(counter) (counter)++ -#else -#define FIB_COUNTER_INCREMENT(counter) -#endif - -/* - * Adapter direct commands - * Monitor/Kernel API - */ - -#define BREAKPOINT_REQUEST cpu_to_le32(0x00000004) -#define INIT_STRUCT_BASE_ADDRESS cpu_to_le32(0x00000005) -#define READ_PERMANENT_PARAMETERS cpu_to_le32(0x0000000a) -#define WRITE_PERMANENT_PARAMETERS cpu_to_le32(0x0000000b) -#define HOST_CRASHING cpu_to_le32(0x0000000d) -#define SEND_SYNCHRONOUS_FIB cpu_to_le32(0x0000000c) -#define GET_ADAPTER_PROPERTIES cpu_to_le32(0x00000019) -#define RE_INIT_ADAPTER cpu_to_le32(0x000000ee) - -/* - * Adapter Status Register - * - * Phase Staus mailbox is 32bits: - * <31:16> = Phase Status - * <15:0> = Phase - * - * The adapter reports is present state through the phase. Only - * a single phase should be ever be set. Each phase can have multiple - * phase status bits to provide more detailed information about the - * state of the board. Care should be taken to ensure that any phase - * status bits that are set when changing the phase are also valid - * for the new phase or be cleared out. Adapter software (monitor, - * iflash, kernel) is responsible for properly maintining the phase - * status mailbox when it is running. - * - * MONKER_API Phases - * - * Phases are bit oriented. It is NOT valid to have multiple bits set - */ - -#define SELF_TEST_FAILED cpu_to_le32(0x00000004) -#define KERNEL_UP_AND_RUNNING cpu_to_le32(0x00000080) -#define KERNEL_PANIC cpu_to_le32(0x00000100) - -/* - * Doorbell bit defines - */ - -#define DoorBellPrintfDone cpu_to_le32(1<<5) // Host -> Adapter -#define DoorBellAdapterNormCmdReady cpu_to_le32(1<<1) // Adapter -> Host -#define DoorBellAdapterNormRespReady cpu_to_le32(1<<2) // Adapter -> Host -#define DoorBellAdapterNormCmdNotFull cpu_to_le32(1<<3) // Adapter -> Host -#define DoorBellAdapterNormRespNotFull cpu_to_le32(1<<4) // Adapter -> Host -#define DoorBellPrintfReady cpu_to_le32(1<<5) // Adapter -> Host - -/* - * For FIB communication, we need all of the following things - * to send back to the user. - */ - -#define AifCmdEventNotify 1 /* Notify of event */ -#define AifEnContainerChange 4 /* Container configuration change */ -#define AifCmdJobProgress 2 /* Progress report */ -#define AifCmdAPIReport 3 /* Report from other user of API */ -#define AifCmdDriverNotify 4 /* Notify host driver of event */ -#define AifDenMorphComplete 200 /* A morph operation completed */ -#define AifDenVolumeExtendComplete 201 /* A volume expand operation completed */ -#define AifReqJobList 100 /* Gets back complete job list */ -#define AifReqJobsForCtr 101 /* Gets back jobs for specific container */ -#define AifReqJobsForScsi 102 /* Gets back jobs for specific SCSI device */ -#define AifReqJobReport 103 /* Gets back a specific job report or list of them */ -#define AifReqTerminateJob 104 /* Terminates job */ -#define AifReqSuspendJob 105 /* Suspends a job */ -#define AifReqResumeJob 106 /* Resumes a job */ -#define AifReqSendAPIReport 107 /* API generic report requests */ -#define AifReqAPIJobStart 108 /* Start a job from the API */ -#define AifReqAPIJobUpdate 109 /* Update a job report from the API */ -#define AifReqAPIJobFinish 110 /* Finish a job from the API */ - -/* - * Adapter Initiated FIB command structures. Start with the adapter - * initiated FIBs that really come from the adapter, and get responded - * to by the host. - */ - -struct aac_aifcmd { - u32 command; /* Tell host what type of notify this is */ - u32 seqnum; /* To allow ordering of reports (if necessary) */ - u8 data[1]; /* Undefined length (from kernel viewpoint) */ -}; - -const char *aac_driverinfo(struct Scsi_Host *); -struct fib *fib_alloc(struct aac_dev *dev); -int fib_setup(struct aac_dev *dev); -void fib_map_free(struct aac_dev *dev); -void fib_free(struct fib * context); -void fib_init(struct fib * context); -void fib_dealloc(struct fib * context); -void aac_printf(struct aac_dev *dev, u32 val); -int fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt); -int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry); -int aac_consumer_avail(struct aac_dev * dev, struct aac_queue * q); -void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum); -int fib_complete(struct fib * context); -#define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data) -int aac_detach(struct aac_dev *dev); -struct aac_dev *aac_init_adapter(struct aac_dev *dev); -int aac_get_containers(struct aac_dev *dev); -int aac_scsi_cmd(Scsi_Cmnd *scsi_cmnd_ptr); -int aac_dev_ioctl(struct aac_dev *dev, int cmd, void *arg); -int aac_do_ioctl(struct aac_dev * dev, int cmd, void *arg); -int aac_rx_init(struct aac_dev *dev, unsigned long devNumber); -int aac_sa_init(struct aac_dev *dev, unsigned long devNumber); -unsigned int aac_response_normal(struct aac_queue * q); -unsigned int aac_command_normal(struct aac_queue * q); -void aac_command_thread(struct aac_dev * dev); -int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx); -int fib_adapter_complete(struct fib * fibptr, unsigned short size); -struct aac_driver_ident* aac_get_driver_ident(int devtype); -int aac_get_adapter_info(struct aac_dev* dev); diff --git a/xen/drivers/scsi/aacraid/commctrl.c b/xen/drivers/scsi/aacraid/commctrl.c deleted file mode 100644 index bf4d92a2ff..0000000000 --- a/xen/drivers/scsi/aacraid/commctrl.c +++ /dev/null @@ -1,445 +0,0 @@ -/* - * Adaptec AAC series RAID controller driver - * (c) Copyright 2001 Red Hat Inc. - * - * based on the old aacraid driver that is.. - * Adaptec aacraid device driver for Linux. - * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Module Name: - * commctrl.c - * - * Abstract: Contains all routines for control of the AFA comm layer - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -/*#include */ -#include -/*#include */ -#include -#include "scsi.h" -#include "hosts.h" - -#include "aacraid.h" - -/** - * ioctl_send_fib - send a FIB from userspace - * @dev: adapter is being processed - * @arg: arguments to the ioctl call - * - * This routine sends a fib to the adapter on behalf of a user level - * program. - */ - -static int ioctl_send_fib(struct aac_dev * dev, void *arg) -{ - struct hw_fib * kfib; - struct fib *fibptr; - - fibptr = fib_alloc(dev); - if(fibptr == NULL) - return -ENOMEM; - - kfib = fibptr->hw_fib; - /* - * First copy in the header so that we can check the size field. - */ - if (copy_from_user((void *)kfib, arg, sizeof(struct aac_fibhdr))) { - fib_free(fibptr); - return -EFAULT; - } - /* - * Since we copy based on the fib header size, make sure that we - * will not overrun the buffer when we copy the memory. Return - * an error if we would. - */ - if(le32_to_cpu(kfib->header.Size) > sizeof(struct hw_fib) - sizeof(struct aac_fibhdr)) { - fib_free(fibptr); - return -EINVAL; - } - - if (copy_from_user((void *) kfib, arg, le32_to_cpu(kfib->header.Size) + sizeof(struct aac_fibhdr))) { - fib_free(fibptr); - return -EFAULT; - } - - if (kfib->header.Command == cpu_to_le32(TakeABreakPt)) { - aac_adapter_interrupt(dev); - /* - * Since we didn't really send a fib, zero out the state to allow - * cleanup code not to assert. - */ - kfib->header.XferState = 0; - } else { - if (fib_send(kfib->header.Command, fibptr, le32_to_cpu(kfib->header.Size) , FsaNormal, - 1, 1, NULL, NULL) != 0) - { - fib_free(fibptr); - return -EINVAL; - } - if (fib_complete(fibptr) != 0) { - fib_free(fibptr); - return -EINVAL; - } - } - /* - * Make sure that the size returned by the adapter (which includes - * the header) is less than or equal to the size of a fib, so we - * don't corrupt application data. Then copy that size to the user - * buffer. (Don't try to add the header information again, since it - * was already included by the adapter.) - */ - - if (copy_to_user(arg, (void *)kfib, kfib->header.Size)) { - fib_free(fibptr); - return -EFAULT; - } - fib_free(fibptr); - return 0; -} - -/** - * open_getadapter_fib - Get the next fib - * - * This routine will get the next Fib, if available, from the AdapterFibContext - * passed in from the user. - */ - -static int open_getadapter_fib(struct aac_dev * dev, void *arg) -{ - struct aac_fib_context * fibctx; - int status; - unsigned long flags; - - fibctx = kmalloc(sizeof(struct aac_fib_context), GFP_KERNEL); - if (fibctx == NULL) { - status = -ENOMEM; - } else { - fibctx->type = FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT; - fibctx->size = sizeof(struct aac_fib_context); -#if 0 - /* - * Initialize the mutex used to wait for the next AIF. - */ - init_MUTEX_LOCKED(&fibctx->wait_sem); -#endif - fibctx->wait = 0; - /* - * Initialize the fibs and set the count of fibs on - * the list to 0. - */ - fibctx->count = 0; - INIT_LIST_HEAD(&fibctx->fib_list); - fibctx->jiffies = jiffies/HZ; - /* - * Now add this context onto the adapter's - * AdapterFibContext list. - */ - spin_lock_irqsave(&dev->fib_lock, flags); - list_add_tail(&fibctx->next, &dev->fib_list); - spin_unlock_irqrestore(&dev->fib_lock, flags); - if (copy_to_user(arg, &fibctx, sizeof(struct aac_fib_context *))) { - status = -EFAULT; - } else { - status = 0; - } - } - return status; -} - -/** - * next_getadapter_fib - get the next fib - * @dev: adapter to use - * @arg: ioctl argument - * - * This routine will get the next Fib, if available, from the AdapterFibContext - * passed in from the user. - */ - -static int next_getadapter_fib(struct aac_dev * dev, void *arg) -{ - struct fib_ioctl f; - struct aac_fib_context *fibctx, *aifcp; - struct fib * fib; - int status; - struct list_head * entry; - int found; - unsigned long flags; - - if(copy_from_user((void *)&f, arg, sizeof(struct fib_ioctl))) - return -EFAULT; - /* - * Extract the AdapterFibContext from the Input parameters. - */ - fibctx = (struct aac_fib_context *) f.fibctx; - - /* - * Verify that the HANDLE passed in was a valid AdapterFibContext - * - * Search the list of AdapterFibContext addresses on the adapter - * to be sure this is a valid address - */ - found = 0; - entry = dev->fib_list.next; - - while(entry != &dev->fib_list) { - aifcp = list_entry(entry, struct aac_fib_context, next); - if(fibctx == aifcp) { /* We found a winner */ - found = 1; - break; - } - entry = entry->next; - } - if (found == 0) { - dprintk ((KERN_INFO "Fib not found\n")); - return -EINVAL; - } - - if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) || - (fibctx->size != sizeof(struct aac_fib_context))) { - dprintk ((KERN_INFO "Fib Context corrupt?\n")); - return -EINVAL; - } - status = 0; - spin_lock_irqsave(&dev->fib_lock, flags); - /* - * If there are no fibs to send back, then either wait or return - * -EAGAIN - */ -return_fib: - if (!list_empty(&fibctx->fib_list)) { - struct list_head * entry; - /* - * Pull the next fib from the fibs - */ - entry = fibctx->fib_list.next; - list_del(entry); - - fib = list_entry(entry, struct fib, fiblink); - fibctx->count--; - spin_unlock_irqrestore(&dev->fib_lock, flags); - if (copy_to_user(f.fib, fib->hw_fib, sizeof(struct hw_fib))) { - kfree(fib->hw_fib); - kfree(fib); - return -EFAULT; - } - /* - * Free the space occupied by this copy of the fib. - */ - kfree(fib->hw_fib); - kfree(fib); - status = 0; - } else { - spin_unlock_irqrestore(&dev->fib_lock, flags); - if (f.wait) { -#if 0 - if(down_interruptible(&fibctx->wait_sem) < 0) { - status = -EINTR; - } else { -#else - { -#endif - /* Lock again and retry */ - spin_lock_irqsave(&dev->fib_lock, flags); - goto return_fib; - } - } else { - status = -EAGAIN; - } - } - fibctx->jiffies = jiffies/HZ; - return status; -} - -int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context * fibctx) -{ - struct fib *fib; - - /* - * First free any FIBs that have not been consumed. - */ - while (!list_empty(&fibctx->fib_list)) { - struct list_head * entry; - /* - * Pull the next fib from the fibs - */ - entry = fibctx->fib_list.next; - list_del(entry); - fib = list_entry(entry, struct fib, fiblink); - fibctx->count--; - /* - * Free the space occupied by this copy of the fib. - */ - kfree(fib->hw_fib); - kfree(fib); - } - /* - * Remove the Context from the AdapterFibContext List - */ - list_del(&fibctx->next); - /* - * Invalidate context - */ - fibctx->type = 0; - /* - * Free the space occupied by the Context - */ - kfree(fibctx); - return 0; -} - -/** - * close_getadapter_fib - close down user fib context - * @dev: adapter - * @arg: ioctl arguments - * - * This routine will close down the fibctx passed in from the user. - */ - -static int close_getadapter_fib(struct aac_dev * dev, void *arg) -{ - struct aac_fib_context *fibctx, *aifcp; - int status; - unsigned long flags; - struct list_head * entry; - int found; - - /* - * Extract the fibctx from the input parameters - */ - fibctx = arg; - - /* - * Verify that the HANDLE passed in was a valid AdapterFibContext - * - * Search the list of AdapterFibContext addresses on the adapter - * to be sure this is a valid address - */ - - found = 0; - entry = dev->fib_list.next; - - while(entry != &dev->fib_list) { - aifcp = list_entry(entry, struct aac_fib_context, next); - if(fibctx == aifcp) { /* We found a winner */ - found = 1; - break; - } - entry = entry->next; - } - - if(found == 0) - return 0; /* Already gone */ - - if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) || - (fibctx->size != sizeof(struct aac_fib_context))) - return -EINVAL; - spin_lock_irqsave(&dev->fib_lock, flags); - status = aac_close_fib_context(dev, fibctx); - spin_unlock_irqrestore(&dev->fib_lock, flags); - return status; -} - -/** - * check_revision - close down user fib context - * @dev: adapter - * @arg: ioctl arguments - * - * This routine returns the firmware version. - * Under Linux, there have been no version incompatibilities, so this is simple! - */ - -static int check_revision(struct aac_dev *dev, void *arg) -{ - struct revision response; - - response.compat = 1; - response.version = dev->adapter_info.kernelrev; - response.build = dev->adapter_info.kernelbuild; - - if (copy_to_user(arg, &response, sizeof(response))) - return -EFAULT; - return 0; -} - - -struct aac_pci_info { - u32 bus; - u32 slot; -}; - - -int aac_get_pci_info(struct aac_dev* dev, void* arg) -{ - struct aac_pci_info pci_info; - - pci_info.bus = dev->pdev->bus->number; - pci_info.slot = PCI_SLOT(dev->pdev->devfn); - - if(copy_to_user( arg, (void*)&pci_info, sizeof(struct aac_pci_info))) - return -EFAULT; - return 0; - } - - -int aac_do_ioctl(struct aac_dev * dev, int cmd, void *arg) -{ - int status; - - /* - * HBA gets first crack - */ - - status = aac_dev_ioctl(dev, cmd, arg); - if(status != -ENOTTY) - return status; - - switch (cmd) { - case FSACTL_MINIPORT_REV_CHECK: - status = check_revision(dev, arg); - break; - case FSACTL_SENDFIB: - status = ioctl_send_fib(dev, arg); - break; - case FSACTL_OPEN_GET_ADAPTER_FIB: - status = open_getadapter_fib(dev, arg); - break; - case FSACTL_GET_NEXT_ADAPTER_FIB: - status = next_getadapter_fib(dev, arg); - break; - case FSACTL_CLOSE_GET_ADAPTER_FIB: - status = close_getadapter_fib(dev, arg); - break; - case FSACTL_GET_PCI_INFO: - status = aac_get_pci_info(dev,arg); - break; - default: - status = -ENOTTY; - break; - } - return status; -} - diff --git a/xen/drivers/scsi/aacraid/comminit.c b/xen/drivers/scsi/aacraid/comminit.c deleted file mode 100644 index 991bcb4225..0000000000 --- a/xen/drivers/scsi/aacraid/comminit.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Adaptec AAC series RAID controller driver - * (c) Copyright 2001 Red Hat Inc. - * - * based on the old aacraid driver that is.. - * Adaptec aacraid device driver for Linux. - * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Module Name: - * comminit.c - * - * Abstract: This supports the initialization of the host adapter commuication interface. - * This is a platform dependent module for the pci cyclone board. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -/*#include */ -#include -/*#include */ -#include "scsi.h" -#include "hosts.h" - -#include "aacraid.h" - -struct aac_common aac_config; - -static struct aac_dev *devices; - -static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long commsize, unsigned long commalign) -{ - unsigned char *base; - unsigned long size, align; - unsigned long fibsize = 4096; - unsigned long printfbufsiz = 256; - struct aac_init *init; - dma_addr_t phys; - - size = fibsize + sizeof(struct aac_init) + commsize + commalign + printfbufsiz; - - base = pci_alloc_consistent(dev->pdev, size, &phys); - if(base == NULL) - { - printk(KERN_ERR "aacraid: unable to create mapping.\n"); - return 0; - } - dev->comm_addr = (void *)base; - dev->comm_phys = phys; - dev->comm_size = size; - - dev->init = (struct aac_init *)(base + fibsize); - dev->init_pa = phys + fibsize; - - init = dev->init; - - init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); - init->MiniPortRevision = cpu_to_le32(Sa_MINIPORT_REVISION); - init->fsrev = cpu_to_le32(dev->fsrev); - - /* - * Adapter Fibs are the first thing allocated so that they - * start page aligned - */ - dev->fib_base_va = (ulong)base; - - /* We submit the physical address for AIF tags to limit to 32 bits */ - init->AdapterFibsVirtualAddress = cpu_to_le32((u32)phys); - init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys); - init->AdapterFibsSize = cpu_to_le32(fibsize); - init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib)); - init->HostPhysMemPages = cpu_to_le32(4096); // number of 4k pages of host physical memory - - /* - * Increment the base address by the amount already used - */ - base = base + fibsize + sizeof(struct aac_init); - phys = (dma_addr_t)((ulong)phys + fibsize + sizeof(struct aac_init)); - /* - * Align the beginning of Headers to commalign - */ - align = (commalign - ((unsigned long)(base) & (commalign - 1))); - base = base + align; - phys = phys + align; - /* - * Fill in addresses of the Comm Area Headers and Queues - */ - *commaddr = base; - init->CommHeaderAddress = cpu_to_le32((u32)phys); - /* - * Increment the base address by the size of the CommArea - */ - base = base + commsize; - phys = phys + commsize; - /* - * Place the Printf buffer area after the Fast I/O comm area. - */ - dev->printfbuf = (void *)base; - init->printfbuf = cpu_to_le32(phys); - init->printfbufsiz = cpu_to_le32(printfbufsiz); - memset(base, 0, printfbufsiz); - return 1; -} - -static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, int qsize) -{ - q->numpending = 0; - q->dev = dev; - INIT_LIST_HEAD(&q->pendingq); -#if 0 - init_waitqueue_head(&q->cmdready); -#endif - INIT_LIST_HEAD(&q->cmdq); -#if 0 - init_waitqueue_head(&q->qfull); -#endif - spin_lock_init(&q->lockdata); - q->lock = &q->lockdata; - q->headers.producer = mem; - q->headers.consumer = mem+1; - *(q->headers.producer) = cpu_to_le32(qsize); - *(q->headers.consumer) = cpu_to_le32(qsize); - q->entries = qsize; -} - -/** - * aac_send_shutdown - shutdown an adapter - * @dev: Adapter to shutdown - * - * This routine will send a VM_CloseAll (shutdown) request to the adapter. - */ - -static int aac_send_shutdown(struct aac_dev * dev) -{ - struct fib * fibctx; - struct aac_close *cmd; - int status; - - fibctx = fib_alloc(dev); - fib_init(fibctx); - - cmd = (struct aac_close *) fib_data(fibctx); - - cmd->command = cpu_to_le32(VM_CloseAll); - cmd->cid = cpu_to_le32(0xffffffff); - - status = fib_send(ContainerCommand, - fibctx, - sizeof(struct aac_close), - FsaNormal, - 1, 1, - NULL, NULL); - - if (status == 0) - fib_complete(fibctx); - fib_free(fibctx); - return status; -} - -/** - * aac_detach - detach adapter - * @detach: adapter to disconnect - * - * Disconnect and shutdown an AAC based adapter, freeing resources - * as we go. - */ - -int aac_detach(struct aac_dev *detach) -{ - struct aac_dev **dev = &devices; - - while(*dev) - { - if(*dev == detach) - { - *dev = detach->next; - aac_send_shutdown(detach); - fib_map_free(detach); - pci_free_consistent(detach->pdev, detach->comm_size, detach->comm_addr, detach->comm_phys); - kfree(detach->queues); - return 1; - } - dev=&((*dev)->next); - } - BUG(); - return 0; -} - -/** - * aac_comm_init - Initialise FSA data structures - * @dev: Adapter to intialise - * - * Initializes the data structures that are required for the FSA commuication - * interface to operate. - * Returns - * 1 - if we were able to init the commuication interface. - * 0 - If there were errors initing. This is a fatal error. - */ - -int aac_comm_init(struct aac_dev * dev) -{ - unsigned long hdrsize = (sizeof(u32) * NUMBER_OF_COMM_QUEUES) * 2; - unsigned long queuesize = sizeof(struct aac_entry) * TOTAL_QUEUE_ENTRIES; - u32 *headers; - struct aac_entry * queues; - unsigned long size; - struct aac_queue_block * comm = dev->queues; - - /* - * Now allocate and initialize the zone structures used as our - * pool of FIB context records. The size of the zone is based - * on the system memory size. We also initialize the mutex used - * to protect the zone. - */ - spin_lock_init(&dev->fib_lock); - - /* - * Allocate the physically contigous space for the commuication - * queue headers. - */ - - size = hdrsize + queuesize; - - if (!aac_alloc_comm(dev, (void * *)&headers, size, QUEUE_ALIGNMENT)) - return -ENOMEM; - - queues = (struct aac_entry *)(((ulong)headers) + hdrsize); - - /* Adapter to Host normal priority Command queue */ - comm->queue[HostNormCmdQueue].base = queues; - aac_queue_init(dev, &comm->queue[HostNormCmdQueue], headers, HOST_NORM_CMD_ENTRIES); - queues += HOST_NORM_CMD_ENTRIES; - headers += 2; - - /* Adapter to Host high priority command queue */ - comm->queue[HostHighCmdQueue].base = queues; - aac_queue_init(dev, &comm->queue[HostHighCmdQueue], headers, HOST_HIGH_CMD_ENTRIES); - - queues += HOST_HIGH_CMD_ENTRIES; - headers +=2; - - /* Host to adapter normal priority command queue */ - comm->queue[AdapNormCmdQueue].base = queues; - aac_queue_init(dev, &comm->queue[AdapNormCmdQueue], headers, ADAP_NORM_CMD_ENTRIES); - - queues += ADAP_NORM_CMD_ENTRIES; - headers += 2; - - /* host to adapter high priority command queue */ - comm->queue[AdapHighCmdQueue].base = queues; - aac_queue_init(dev, &comm->queue[AdapHighCmdQueue], headers, ADAP_HIGH_CMD_ENTRIES); - - queues += ADAP_HIGH_CMD_ENTRIES; - headers += 2; - - /* adapter to host normal priority response queue */ - comm->queue[HostNormRespQueue].base = queues; - aac_queue_init(dev, &comm->queue[HostNormRespQueue], headers, HOST_NORM_RESP_ENTRIES); - - queues += HOST_NORM_RESP_ENTRIES; - headers += 2; - - /* adapter to host high priority response queue */ - comm->queue[HostHighRespQueue].base = queues; - aac_queue_init(dev, &comm->queue[HostHighRespQueue], headers, HOST_HIGH_RESP_ENTRIES); - - queues += HOST_HIGH_RESP_ENTRIES; - headers += 2; - - /* host to adapter normal priority response queue */ - comm->queue[AdapNormRespQueue].base = queues; - aac_queue_init(dev, &comm->queue[AdapNormRespQueue], headers, ADAP_NORM_RESP_ENTRIES); - - queues += ADAP_NORM_RESP_ENTRIES; - headers += 2; - - /* host to adapter high priority response queue */ - comm->queue[AdapHighRespQueue].base = queues; - aac_queue_init(dev, &comm->queue[AdapHighRespQueue], headers, ADAP_HIGH_RESP_ENTRIES); - - comm->queue[AdapNormCmdQueue].lock = comm->queue[HostNormRespQueue].lock; - comm->queue[AdapHighCmdQueue].lock = comm->queue[HostHighRespQueue].lock; - comm->queue[AdapNormRespQueue].lock = comm->queue[HostNormCmdQueue].lock; - comm->queue[AdapHighRespQueue].lock = comm->queue[HostHighCmdQueue].lock; - - return 0; -} - -struct aac_dev *aac_init_adapter(struct aac_dev *dev) -{ - /* - * Ok now init the communication subsystem - */ - dev->queues = (struct aac_queue_block *) kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL); - if (dev->queues == NULL) { - printk(KERN_ERR "Error could not allocate comm region.\n"); - return NULL; - } - memset(dev->queues, 0, sizeof(struct aac_queue_block)); - - if (aac_comm_init(dev)<0){ - kfree(dev->queues); - return NULL; - } - /* - * Initialize the list of fibs - */ - if(fib_setup(dev)<0){ - kfree(dev->queues); - return NULL; - } - - INIT_LIST_HEAD(&dev->fib_list); -#if 0 - init_completion(&dev->aif_completion); -#endif - /* - * Add this adapter in to our dev List. - */ - dev->next = devices; - devices = dev; - return dev; -} - - diff --git a/xen/drivers/scsi/aacraid/commsup.c b/xen/drivers/scsi/aacraid/commsup.c deleted file mode 100644 index c44465cf6d..0000000000 --- a/xen/drivers/scsi/aacraid/commsup.c +++ /dev/null @@ -1,1052 +0,0 @@ -/* - * Adaptec AAC series RAID controller driver - * (c) Copyright 2001 Red Hat Inc. - * - * based on the old aacraid driver that is.. - - * Adaptec aacraid device driver for Linux. - * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Module Name: - * commsup.c - * - * Abstract: Contain all routines that are required for FSA host/adapter - * commuication. - * - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -/*#include */ -/*#include */ -#include -#include - -#include -#include - -#include "scsi.h" -#include "hosts.h" - -#include "aacraid.h" - -/** - * fib_map_alloc - allocate the fib objects - * @dev: Adapter to allocate for - * - * Allocate and map the shared PCI space for the FIB blocks used to - * talk to the Adaptec firmware. - */ - -static int fib_map_alloc(struct aac_dev *dev) -{ - if((dev->hw_fib_va = pci_alloc_consistent(dev->pdev, sizeof(struct hw_fib) * AAC_NUM_FIB, &dev->hw_fib_pa))==NULL) - return -ENOMEM; - return 0; -} - -/** - * fib_map_free - free the fib objects - * @dev: Adapter to free - * - * Free the PCI mappings and the memory allocated for FIB blocks - * on this adapter. - */ - -void fib_map_free(struct aac_dev *dev) -{ - pci_free_consistent(dev->pdev, sizeof(struct hw_fib) * AAC_NUM_FIB, dev->hw_fib_va, dev->hw_fib_pa); -} - -/** - * fib_setup - setup the fibs - * @dev: Adapter to set up - * - * Allocate the PCI space for the fibs, map it and then intialise the - * fib area, the unmapped fib data and also the free list - */ - -int fib_setup(struct aac_dev * dev) -{ - struct fib *fibptr; - struct hw_fib *hw_fib_va; - dma_addr_t hw_fib_pa; - int i; - - if(fib_map_alloc(dev)<0) - return -ENOMEM; - - hw_fib_va = dev->hw_fib_va; - hw_fib_pa = dev->hw_fib_pa; - memset(hw_fib_va, 0, sizeof(struct hw_fib) * AAC_NUM_FIB); - /* - * Initialise the fibs - */ - for (i = 0, fibptr = &dev->fibs[i]; i < AAC_NUM_FIB; i++, fibptr++) - { - fibptr->dev = dev; - fibptr->hw_fib = hw_fib_va; - fibptr->data = (void *) fibptr->hw_fib->data; - fibptr->next = fibptr+1; /* Forward chain the fibs */ -#if 0 - init_MUTEX_LOCKED(&fibptr->event_wait); -#endif - spin_lock_init(&fibptr->event_lock); - hw_fib_va->header.XferState = cpu_to_le32(0xffffffff); - hw_fib_va->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib)); - fibptr->hw_fib_pa = hw_fib_pa; - hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + sizeof(struct hw_fib)); - hw_fib_pa = hw_fib_pa + sizeof(struct hw_fib); - } - /* - * Add the fib chain to the free list - */ - dev->fibs[AAC_NUM_FIB-1].next = NULL; - /* - * Enable this to debug out of queue space - */ - dev->free_fib = &dev->fibs[0]; - return 0; -} - -/** - * fib_alloc - allocate a fib - * @dev: Adapter to allocate the fib for - * - * Allocate a fib from the adapter fib pool. If the pool is empty we - * wait for fibs to become free. - */ - -struct fib * fib_alloc(struct aac_dev *dev) -{ - struct fib * fibptr; - unsigned long flags; - - spin_lock_irqsave(&dev->fib_lock, flags); - fibptr = dev->free_fib; - if(!fibptr) - BUG(); - dev->free_fib = fibptr->next; - spin_unlock_irqrestore(&dev->fib_lock, flags); - /* - * Set the proper node type code and node byte size - */ - fibptr->type = FSAFS_NTC_FIB_CONTEXT; - fibptr->size = sizeof(struct fib); - /* - * Null out fields that depend on being zero at the start of - * each I/O - */ - fibptr->hw_fib->header.XferState = cpu_to_le32(0); - fibptr->callback = NULL; - fibptr->callback_data = NULL; - - return fibptr; -} - -/** - * fib_free - free a fib - * @fibptr: fib to free up - * - * Frees up a fib and places it on the appropriate queue - * (either free or timed out) - */ - -void fib_free(struct fib * fibptr) -{ - unsigned long flags; - - spin_lock_irqsave(&fibptr->dev->fib_lock, flags); - - if (fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT) { - aac_config.fib_timeouts++; - fibptr->next = fibptr->dev->timeout_fib; - fibptr->dev->timeout_fib = fibptr; - } else { - if (fibptr->hw_fib->header.XferState != 0) { - printk(KERN_WARNING "fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", - (void*)fibptr, fibptr->hw_fib->header.XferState); - } - fibptr->next = fibptr->dev->free_fib; - fibptr->dev->free_fib = fibptr; - } - spin_unlock_irqrestore(&fibptr->dev->fib_lock, flags); -} - -/** - * fib_init - initialise a fib - * @fibptr: The fib to initialize - * - * Set up the generic fib fields ready for use - */ - -void fib_init(struct fib *fibptr) -{ - struct hw_fib *hw_fib = fibptr->hw_fib; - - hw_fib->header.StructType = FIB_MAGIC; - hw_fib->header.Size = cpu_to_le16(sizeof(struct hw_fib)); - hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable); - hw_fib->header.SenderFibAddress = cpu_to_le32(fibptr->hw_fib_pa); - hw_fib->header.ReceiverFibAddress = cpu_to_le32(fibptr->hw_fib_pa); - hw_fib->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib)); -} - -/** - * fib_deallocate - deallocate a fib - * @fibptr: fib to deallocate - * - * Will deallocate and return to the free pool the FIB pointed to by the - * caller. - */ - -void fib_dealloc(struct fib * fibptr) -{ - struct hw_fib *hw_fib = fibptr->hw_fib; - if(hw_fib->header.StructType != FIB_MAGIC) - BUG(); - hw_fib->header.XferState = cpu_to_le32(0); -} - -/* - * Commuication primitives define and support the queuing method we use to - * support host to adapter commuication. All queue accesses happen through - * these routines and are the only routines which have a knowledge of the - * how these queues are implemented. - */ - -/** - * aac_get_entry - get a queue entry - * @dev: Adapter - * @qid: Queue Number - * @entry: Entry return - * @index: Index return - * @nonotify: notification control - * - * With a priority the routine returns a queue entry if the queue has free entries. If the queue - * is full(no free entries) than no entry is returned and the function returns 0 otherwise 1 is - * returned. - */ - -static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entry, u32 * index, unsigned long *nonotify) -{ - struct aac_queue * q; - - /* - * All of the queues wrap when they reach the end, so we check - * to see if they have reached the end and if they have we just - * set the index back to zero. This is a wrap. You could or off - * the high bits in all updates but this is a bit faster I think. - */ - - q = &dev->queues->queue[qid]; - - *index = le32_to_cpu(*(q->headers.producer)); - if ((*index - 2) == le32_to_cpu(*(q->headers.consumer))) - *nonotify = 1; - - if (qid == AdapHighCmdQueue) { - if (*index >= ADAP_HIGH_CMD_ENTRIES) - *index = 0; - } else if (qid == AdapNormCmdQueue) { - if (*index >= ADAP_NORM_CMD_ENTRIES) - *index = 0; /* Wrap to front of the Producer Queue. */ - } - else if (qid == AdapHighRespQueue) - { - if (*index >= ADAP_HIGH_RESP_ENTRIES) - *index = 0; - } - else if (qid == AdapNormRespQueue) - { - if (*index >= ADAP_NORM_RESP_ENTRIES) - *index = 0; /* Wrap to front of the Producer Queue. */ - } - else BUG(); - - if (*index + 1 == le32_to_cpu(*(q->headers.consumer))) { /* Queue is full */ - printk(KERN_WARNING "Queue %d full, %ld outstanding.\n", qid, q->numpending); - return 0; - } else { - *entry = q->base + *index; - return 1; - } -} - -/** - * aac_queue_get - get the next free QE - * @dev: Adapter - * @index: Returned index - * @priority: Priority of fib - * @fib: Fib to associate with the queue entry - * @wait: Wait if queue full - * @fibptr: Driver fib object to go with fib - * @nonotify: Don't notify the adapter - * - * Gets the next free QE off the requested priorty adapter command - * queue and associates the Fib with the QE. The QE represented by - * index is ready to insert on the queue when this routine returns - * success. - */ - -static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify) -{ - struct aac_entry * entry = NULL; - int map = 0; - struct aac_queue * q = &dev->queues->queue[qid]; - - spin_lock_irqsave(q->lock, q->SavedIrql); - - if (qid == AdapHighCmdQueue || qid == AdapNormCmdQueue) - { - /* if no entries wait for some if caller wants to */ - while (!aac_get_entry(dev, qid, &entry, index, nonotify)) - { - printk(KERN_ERR "GetEntries failed\n"); - } - /* - * Setup queue entry with a command, status and fib mapped - */ - entry->size = cpu_to_le32(le16_to_cpu(hw_fib->header.Size)); - map = 1; - } - else if (qid == AdapHighRespQueue || qid == AdapNormRespQueue) - { - while(!aac_get_entry(dev, qid, &entry, index, nonotify)) - { - /* if no entries wait for some if caller wants to */ - } - /* - * Setup queue entry with command, status and fib mapped - */ - entry->size = cpu_to_le32(le16_to_cpu(hw_fib->header.Size)); - entry->addr = hw_fib->header.SenderFibAddress; - /* Restore adapters pointer to the FIB */ - hw_fib->header.ReceiverFibAddress = hw_fib->header.SenderFibAddress; /* Let the adapter now where to find its data */ - map = 0; - } - /* - * If MapFib is true than we need to map the Fib and put pointers - * in the queue entry. - */ - if (map) - entry->addr = fibptr->hw_fib_pa; - return 0; -} - - -/** - * aac_insert_entry - insert a queue entry - * @dev: Adapter - * @index: Index of entry to insert - * @qid: Queue number - * @nonotify: Suppress adapter notification - * - * Gets the next free QE off the requested priorty adapter command - * queue and associates the Fib with the QE. The QE represented by - * index is ready to insert on the queue when this routine returns - * success. - */ - -static int aac_insert_entry(struct aac_dev * dev, u32 index, u32 qid, unsigned long nonotify) -{ - struct aac_queue * q = &dev->queues->queue[qid]; - - if(q == NULL) - BUG(); - *(q->headers.producer) = cpu_to_le32(index + 1); - spin_unlock_irqrestore(q->lock, q->SavedIrql); - - if (qid == AdapHighCmdQueue || - qid == AdapNormCmdQueue || - qid == AdapHighRespQueue || - qid == AdapNormRespQueue) - { - if (!nonotify) - aac_adapter_notify(dev, qid); - } - else - printk("Suprise insert!\n"); - return 0; -} - -/* - * Define the highest level of host to adapter communication routines. - * These routines will support host to adapter FS commuication. These - * routines have no knowledge of the commuication method used. This level - * sends and receives FIBs. This level has no knowledge of how these FIBs - * get passed back and forth. - */ - -/** - * fib_send - send a fib to the adapter - * @command: Command to send - * @fibptr: The fib - * @size: Size of fib data area - * @priority: Priority of Fib - * @wait: Async/sync select - * @reply: True if a reply is wanted - * @callback: Called with reply - * @callback_data: Passed to callback - * - * Sends the requested FIB to the adapter and optionally will wait for a - * response FIB. If the caller does not wish to wait for a response than - * an event to wait on must be supplied. This event will be set when a - * response FIB is received from the adapter. - */ - -int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority, int wait, int reply, fib_callback callback, void * callback_data) -{ - u32 index; - u32 qid; - struct aac_dev * dev = fibptr->dev; - unsigned long nointr = 0; - struct hw_fib * hw_fib = fibptr->hw_fib; - struct aac_queue * q; - unsigned long flags = 0; - - if (!(le32_to_cpu(hw_fib->header.XferState) & HostOwned)) - return -EBUSY; - /* - * There are 5 cases with the wait and reponse requested flags. - * The only invalid cases are if the caller requests to wait and - * does not request a response and if the caller does not want a - * response and the Fibis not allocated from pool. If a response - * is not requesed the Fib will just be deallocaed by the DPC - * routine when the response comes back from the adapter. No - * further processing will be done besides deleting the Fib. We - * will have a debug mode where the adapter can notify the host - * it had a problem and the host can log that fact. - */ - if (wait && !reply) { - return -EINVAL; - } else if (!wait && reply) { - hw_fib->header.XferState |= cpu_to_le32(Async | ResponseExpected); - FIB_COUNTER_INCREMENT(aac_config.AsyncSent); - } else if (!wait && !reply) { - hw_fib->header.XferState |= cpu_to_le32(NoResponseExpected); - FIB_COUNTER_INCREMENT(aac_config.NoResponseSent); - } else if (wait && reply) { - hw_fib->header.XferState |= cpu_to_le32(ResponseExpected); - FIB_COUNTER_INCREMENT(aac_config.NormalSent); - } - /* - * Map the fib into 32bits by using the fib number - */ - -// hw_fib->header.SenderFibAddress = ((u32)(fibptr-dev->fibs)) << 1; - hw_fib->header.SenderFibAddress = cpu_to_le32((u32)(ulong)fibptr->hw_fib_pa); - hw_fib->header.SenderData = (u32)(fibptr - dev->fibs); - /* - * Set FIB state to indicate where it came from and if we want a - * response from the adapter. Also load the command from the - * caller. - * - * Map the hw fib pointer as a 32bit value - */ - hw_fib->header.Command = cpu_to_le16(command); - hw_fib->header.XferState |= cpu_to_le32(SentFromHost); - fibptr->hw_fib->header.Flags = 0; /* 0 the flags field - internal only*/ - /* - * Set the size of the Fib we want to send to the adapter - */ - hw_fib->header.Size = cpu_to_le16(sizeof(struct aac_fibhdr) + size); - if (le16_to_cpu(hw_fib->header.Size) > le16_to_cpu(hw_fib->header.SenderSize)) { - return -EMSGSIZE; - } - /* - * Get a queue entry connect the FIB to it and send an notify - * the adapter a command is ready. - */ - if (priority == FsaHigh) { - hw_fib->header.XferState |= cpu_to_le32(HighPriority); - qid = AdapHighCmdQueue; - } else { - hw_fib->header.XferState |= cpu_to_le32(NormalPriority); - qid = AdapNormCmdQueue; - } - q = &dev->queues->queue[qid]; - - if(wait) - spin_lock_irqsave(&fibptr->event_lock, flags); - if(aac_queue_get( dev, &index, qid, hw_fib, 1, fibptr, &nointr)<0) - return -EWOULDBLOCK; - dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index)); - dprintk((KERN_DEBUG "Fib contents:.\n")); - dprintk((KERN_DEBUG " Command = %d.\n", hw_fib->header.Command)); - dprintk((KERN_DEBUG " XferState = %x.\n", hw_fib->header.XferState)); - dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib)); - dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); - dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); - /* - * Fill in the Callback and CallbackContext if we are not - * going to wait. - */ - if (!wait) { - fibptr->callback = callback; - fibptr->callback_data = callback_data; - } - FIB_COUNTER_INCREMENT(aac_config.FibsSent); - list_add_tail(&fibptr->queue, &q->pendingq); - q->numpending++; - - fibptr->done = 0; - fibptr->flags = 0; - - if(aac_insert_entry(dev, index, qid, (nointr & aac_config.irq_mod)) < 0) - return -EWOULDBLOCK; - /* - * If the caller wanted us to wait for response wait now. - */ - - if (wait) { - spin_unlock_irqrestore(&fibptr->event_lock, flags); - while (!fibptr->done) - aac_command_thread(dev); - if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) - return -ETIMEDOUT; - else - return 0; - } - /* - * If the user does not want a response than return success otherwise - * return pending - */ - if (reply) - return -EINPROGRESS; - else - return 0; -} - -/** - * aac_consumer_get - get the top of the queue - * @dev: Adapter - * @q: Queue - * @entry: Return entry - * - * Will return a pointer to the entry on the top of the queue requested that - * we are a consumer of, and return the address of the queue entry. It does - * not change the state of the queue. - */ - -int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry) -{ - u32 index; - int status; - if (le32_to_cpu(*q->headers.producer) == le32_to_cpu(*q->headers.consumer)) { - status = 0; - } else { - /* - * The consumer index must be wrapped if we have reached - * the end of the queue, else we just use the entry - * pointed to by the header index - */ - if (le32_to_cpu(*q->headers.consumer) >= q->entries) - index = 0; - else - index = le32_to_cpu(*q->headers.consumer); - *entry = q->base + index; - status = 1; - } - return(status); -} - -int aac_consumer_avail(struct aac_dev *dev, struct aac_queue * q) -{ - return (le32_to_cpu(*q->headers.producer) != le32_to_cpu(*q->headers.consumer)); -} - - -/** - * aac_consumer_free - free consumer entry - * @dev: Adapter - * @q: Queue - * @qid: Queue ident - * - * Frees up the current top of the queue we are a consumer of. If the - * queue was full notify the producer that the queue is no longer full. - */ - -void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid) -{ - int wasfull = 0; - u32 notify; - - if ((le32_to_cpu(*q->headers.producer)+1) == le32_to_cpu(*q->headers.consumer)) - wasfull = 1; - - if (le32_to_cpu(*q->headers.consumer) >= q->entries) - *q->headers.consumer = cpu_to_le32(1); - else - *q->headers.consumer = cpu_to_le32(le32_to_cpu(*q->headers.consumer)+1); - - if (wasfull) { - switch (qid) { - - case HostNormCmdQueue: - notify = HostNormCmdNotFull; - break; - case HostHighCmdQueue: - notify = HostHighCmdNotFull; - break; - case HostNormRespQueue: - notify = HostNormRespNotFull; - break; - case HostHighRespQueue: - notify = HostHighRespNotFull; - break; - default: - BUG(); - return; - } - aac_adapter_notify(dev, notify); - } -} - -/** - * fib_adapter_complete - complete adapter issued fib - * @fibptr: fib to complete - * @size: size of fib - * - * Will do all necessary work to complete a FIB that was sent from - * the adapter. - */ - -int fib_adapter_complete(struct fib * fibptr, unsigned short size) -{ - struct hw_fib * hw_fib = fibptr->hw_fib; - struct aac_dev * dev = fibptr->dev; - unsigned long nointr = 0; - if (le32_to_cpu(hw_fib->header.XferState) == 0) - return 0; - /* - * If we plan to do anything check the structure type first. - */ - if ( hw_fib->header.StructType != FIB_MAGIC ) { - return -EINVAL; - } - /* - * This block handles the case where the adapter had sent us a - * command and we have finished processing the command. We - * call completeFib when we are done processing the command - * and want to send a response back to the adapter. This will - * send the completed cdb to the adapter. - */ - if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) { - hw_fib->header.XferState |= cpu_to_le32(HostProcessed); - if (hw_fib->header.XferState & cpu_to_le32(HighPriority)) { - u32 index; - if (size) - { - size += sizeof(struct aac_fibhdr); - if (size > le16_to_cpu(hw_fib->header.SenderSize)) - return -EMSGSIZE; - hw_fib->header.Size = cpu_to_le16(size); - } - if(aac_queue_get(dev, &index, AdapHighRespQueue, hw_fib, 1, NULL, &nointr) < 0) { - return -EWOULDBLOCK; - } - if (aac_insert_entry(dev, index, AdapHighRespQueue, (nointr & (int)aac_config.irq_mod)) != 0) { - } - } - else if (hw_fib->header.XferState & NormalPriority) - { - u32 index; - - if (size) { - size += sizeof(struct aac_fibhdr); - if (size > le16_to_cpu(hw_fib->header.SenderSize)) - return -EMSGSIZE; - hw_fib->header.Size = cpu_to_le16(size); - } - if (aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr) < 0) - return -EWOULDBLOCK; - if (aac_insert_entry(dev, index, AdapNormRespQueue, - (nointr & (int)aac_config.irq_mod)) != 0) - { - } - } - } - else - { - printk(KERN_WARNING "fib_adapter_complete: Unknown xferstate detected.\n"); - BUG(); - } - return 0; -} - -/** - * fib_complete - fib completion handler - * @fib: FIB to complete - * - * Will do all necessary work to complete a FIB. - */ - -int fib_complete(struct fib * fibptr) -{ - struct hw_fib * hw_fib = fibptr->hw_fib; - - /* - * Check for a fib which has already been completed - */ - - if (hw_fib->header.XferState == cpu_to_le32(0)) - return 0; - /* - * If we plan to do anything check the structure type first. - */ - - if (hw_fib->header.StructType != FIB_MAGIC) - return -EINVAL; - /* - * This block completes a cdb which orginated on the host and we - * just need to deallocate the cdb or reinit it. At this point the - * command is complete that we had sent to the adapter and this - * cdb could be reused. - */ - if((hw_fib->header.XferState & cpu_to_le32(SentFromHost)) && - (hw_fib->header.XferState & cpu_to_le32(AdapterProcessed))) - { - fib_dealloc(fibptr); - } - else if(hw_fib->header.XferState & cpu_to_le32(SentFromHost)) - { - /* - * This handles the case when the host has aborted the I/O - * to the adapter because the adapter is not responding - */ - fib_dealloc(fibptr); - } else if(hw_fib->header.XferState & cpu_to_le32(HostOwned)) { - fib_dealloc(fibptr); - } else { - BUG(); - } - return 0; -} - -/** - * aac_printf - handle printf from firmware - * @dev: Adapter - * @val: Message info - * - * Print a message passed to us by the controller firmware on the - * Adaptec board - */ - -void aac_printf(struct aac_dev *dev, u32 val) -{ - int length = val & 0xffff; - int level = (val >> 16) & 0xffff; - char *cp = dev->printfbuf; - - /* - * The size of the printfbuf is set in port.c - * There is no variable or define for it - */ - if (length > 255) - length = 255; - if (cp[length] != 0) - cp[length] = 0; - if (level == LOG_HIGH_ERROR) - printk(KERN_WARNING "aacraid:%s", cp); - else - printk(KERN_INFO "aacraid:%s", cp); - memset(cp, 0, 256); -} - - -/** - * aac_handle_aif - Handle a message from the firmware - * @dev: Which adapter this fib is from - * @fibptr: Pointer to fibptr from adapter - * - * This routine handles a driver notify fib from the adapter and - * dispatches it to the appropriate routine for handling. - */ - -#define CONTAINER_TO_BUS(cont) (0) -#define CONTAINER_TO_TARGET(cont) ((cont)) -#define CONTAINER_TO_LUN(cont) (0) - -static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) -{ -#if 0 - struct hw_fib * hw_fib = fibptr->hw_fib; - struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data; - int busy; - u32 container; - mm_segment_t fs; - - /* Sniff for container changes */ - dprintk ((KERN_INFO "AifCmdDriverNotify=%x\n", le32_to_cpu(*(u32 *)aifcmd->data))); - switch (le32_to_cpu(*(u32 *)aifcmd->data)) { - case AifDenMorphComplete: - case AifDenVolumeExtendComplete: - case AifEnContainerChange: /* Not really a driver notify Event */ - - busy = 0; - container = le32_to_cpu(((u32 *)aifcmd->data)[1]); - dprintk ((KERN_INFO "container=%d(%d,%d,%d,%d) ", - container, - (dev && dev->scsi_host_ptr) - ? dev->scsi_host_ptr->host_no - : -1, - CONTAINER_TO_BUS(container), - CONTAINER_TO_TARGET(container), - CONTAINER_TO_LUN(container))); - - /* - * Find the Scsi_Device associated with the SCSI address, - * and mark it as changed, invalidating the cache. This deals - * with changes to existing device IDs. - */ - - if ((dev != (struct aac_dev *)NULL) - && (dev->scsi_host_ptr != (struct Scsi_Host *)NULL)) { - Scsi_Device * device; - - for (device = dev->scsi_host_ptr->host_queue; - device != (Scsi_Device *)NULL; - device = device->next) { - dprintk((KERN_INFO - "aifd: device (%d,%d,%d,%d)?\n", - dev->scsi_host_ptr->host_no, - device->channel, - device->id, - device->lun)); - if ((device->channel == CONTAINER_TO_BUS(container)) - && (device->id == CONTAINER_TO_TARGET(container)) - && (device->lun == CONTAINER_TO_LUN(container))) { - busy |= (device->access_count != 0); - if (busy == 0) { - device->removable = TRUE; - } - } - } - } - dprintk (("busy=%d\n", busy)); - - /* - * if (busy == 0) { - * scan_scsis(dev->scsi_host_ptr, 1, - * CONTAINER_TO_BUS(container), - * CONTAINER_TO_TARGET(container), - * CONTAINER_TO_LUN(container)); - * } - * is not exported as accessible, so we need to go around it - * another way. So, we look for the "proc/scsi/scsi" entry in - * the proc filesystem (using proc_scsi as a shortcut) and send - * it a message. This deals with new devices that have - * appeared. If the device has gone offline, scan_scsis will - * also discover this, but we do not want the device to - * go away. We need to check the access_count for the - * device since we are not wanting the devices to go away. - */ - if (busy == 0 && proc_scsi != NULL) { - struct proc_dir_entry * entry; - - dprintk((KERN_INFO "proc_scsi=%p ", proc_scsi)); - for (entry = proc_scsi->subdir; entry != (struct proc_dir_entry *)NULL; entry = entry->next) { - dprintk(("\"%.*s\"[%d]=%x ", entry->namelen, - entry->name, entry->namelen, entry->low_ino)); - if ((entry->low_ino != 0) && (entry->namelen == 4) && (memcmp ("scsi", entry->name, 4) == 0)) { - dprintk(("%p->write_proc=%p ", entry, entry->write_proc)); - if (entry->write_proc != (int (*)(struct file *, const char *, unsigned long, void *))NULL) { - char buffer[80]; - int length; - - sprintf (buffer, - "scsi add-single-device %d %d %d %d\n", - dev->scsi_host_ptr->host_no, - CONTAINER_TO_BUS(container), - CONTAINER_TO_TARGET(container), - CONTAINER_TO_LUN(container)); - length = strlen (buffer); - dprintk((KERN_INFO "echo %.*s > /proc/scsi/scsi\n", length-1, buffer)); - fs = get_fs(); - set_fs(get_ds()); - length = entry->write_proc(NULL, buffer, length, NULL); - set_fs(fs); - dprintk((KERN_INFO "returns %d\n", length)); - } - break; - } - } - } - } -#endif -} - -/** - * aac_command_thread - command processing thread - * @dev: Adapter to monitor - * - * Waits on the commandready event in it's queue. When the event gets set - * it will pull FIBs off it's queue. It will continue to pull FIBs off - * until the queue is empty. When the queue is empty it will wait for - * more FIBs. - */ -void aac_command_thread(struct aac_dev * dev) -{ - struct hw_fib *hw_fib, *hw_newfib; - struct fib *fib, *newfib; - struct aac_queue_block *queues = dev->queues; - struct aac_fib_context *fibctx; - unsigned long flags; - static spinlock_t lock = SPIN_LOCK_UNLOCKED; - - spin_lock_irqsave(&lock, flags); - - { - spin_lock(queues->queue[HostNormCmdQueue].lock); - while(!list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) { - struct list_head *entry; - struct aac_aifcmd * aifcmd; - - entry = queues->queue[HostNormCmdQueue].cmdq.next; - list_del(entry); - - spin_unlock(queues->queue[HostNormCmdQueue].lock); - fib = list_entry(entry, struct fib, fiblink); - /* - * We will process the FIB here or pass it to a - * worker thread that is TBD. We Really can't - * do anything at this point since we don't have - * anything defined for this thread to do. - */ - hw_fib = fib->hw_fib; - - memset(fib, 0, sizeof(struct fib)); - fib->type = FSAFS_NTC_FIB_CONTEXT; - fib->size = sizeof( struct fib ); - fib->hw_fib = hw_fib; - fib->data = hw_fib->data; - fib->dev = dev; - /* - * We only handle AifRequest fibs from the adapter. - */ - aifcmd = (struct aac_aifcmd *) hw_fib->data; - if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) { - /* Handle Driver Notify Events */ - aac_handle_aif(dev, fib); - *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); - fib_adapter_complete(fib, sizeof(u32)); - } else { - struct list_head *entry; - /* The u32 here is important and intended. We are using - 32bit wrapping time to fit the adapter field */ - - u32 time_now, time_last; - unsigned long flagv; - - /* Sniff events */ - if (aifcmd->command == cpu_to_le32(AifCmdEventNotify)) - aac_handle_aif(dev, fib); - - time_now = jiffies/HZ; - - spin_lock_irqsave(&dev->fib_lock, flagv); - entry = dev->fib_list.next; - /* - * For each Context that is on the - * fibctxList, make a copy of the - * fib, and then set the event to wake up the - * thread that is waiting for it. - */ - while (entry != &dev->fib_list) { - /* - * Extract the fibctx - */ - fibctx = list_entry(entry, struct aac_fib_context, next); - /* - * Check if the queue is getting - * backlogged - */ - if (fibctx->count > 20) - { - /* - * It's *not* jiffies folks, - * but jiffies / HZ, so do not - * panic ... - */ - time_last = fibctx->jiffies; - /* - * Has it been > 2 minutes - * since the last read off - * the queue? - */ - if ((time_now - time_last) > 120) { - entry = entry->next; - aac_close_fib_context(dev, fibctx); - continue; - } - } - /* - * Warning: no sleep allowed while - * holding spinlock - */ - hw_newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC); - newfib = kmalloc(sizeof(struct fib), GFP_ATOMIC); - if (newfib && hw_newfib) { - /* - * Make the copy of the FIB - * FIXME: check if we need to fix other fields up - */ - memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib)); - memcpy(newfib, fib, sizeof(struct fib)); - newfib->hw_fib = hw_newfib; - /* - * Put the FIB onto the - * fibctx's fibs - */ - list_add_tail(&newfib->fiblink, &fibctx->fib_list); - fibctx->count++; - } else { - printk(KERN_WARNING "aifd: didn't allocate NewFib.\n"); - if(newfib) - kfree(newfib); - if(hw_newfib) - kfree(hw_newfib); - } - entry = entry->next; - } - /* - * Set the status of this FIB - */ - *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); - fib_adapter_complete(fib, sizeof(u32)); - spin_unlock_irqrestore(&dev->fib_lock, flagv); - } - spin_lock(queues->queue[HostNormCmdQueue].lock); - kfree(fib); - } - /* - * There are no more AIF's - */ - spin_unlock(queues->queue[HostNormCmdQueue].lock); - } - - spin_unlock_irqrestore(&lock, flags); -} diff --git a/xen/drivers/scsi/aacraid/dpcsup.c b/xen/drivers/scsi/aacraid/dpcsup.c deleted file mode 100644 index 952166d532..0000000000 --- a/xen/drivers/scsi/aacraid/dpcsup.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Adaptec AAC series RAID controller driver - * (c) Copyright 2001 Red Hat Inc. - * - * based on the old aacraid driver that is.. - * Adaptec aacraid device driver for Linux. - * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Module Name: - * dpcsup.c - * - * Abstract: All DPC processing routines for the cyclone board occur here. - * - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -/*#include */ -#include -/*#include */ -#include "scsi.h" -#include "hosts.h" - -#include "aacraid.h" - -/** - * aac_response_normal - Handle command replies - * @q: Queue to read from - * - * This DPC routine will be run when the adapter interrupts us to let us - * know there is a response on our normal priority queue. We will pull off - * all QE there are and wake up all the waiters before exiting. We will - * take a spinlock out on the queue before operating on it. - */ - -unsigned int aac_response_normal(struct aac_queue * q) -{ - struct aac_dev * dev = q->dev; - struct aac_entry *entry; - struct hw_fib * hwfib; - struct fib * fib; - int consumed = 0; - unsigned long flags; - - spin_lock_irqsave(q->lock, flags); - - /* - * Keep pulling response QEs off the response queue and waking - * up the waiters until there are no more QEs. We then return - * back to the system. If no response was requesed we just - * deallocate the Fib here and continue. - */ - while(aac_consumer_get(dev, q, &entry)) - { - u32 fast ; - fast = (entry->addr & cpu_to_le32(0x01)); -// fib = &dev->fibs[(entry->addr >> 1)]; -// hwfib = fib->hw_fib; - hwfib = bus_to_virt(le32_to_cpu(entry->addr & cpu_to_le32(~0x01))); - fib = &dev->fibs[hwfib->header.SenderData]; - - aac_consumer_free(dev, q, HostNormRespQueue); - /* - * Remove this fib from the Outstanding I/O queue. - * But only if it has not already been timed out. - * - * If the fib has been timed out already, then just - * continue. The caller has already been notified that - * the fib timed out. - */ - if (!(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) { - list_del(&fib->queue); - dev->queues->queue[AdapNormCmdQueue].numpending--; - } else { - printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags); - continue; - } - spin_unlock_irqrestore(q->lock, flags); - - if (fast) { - /* - * Doctor the fib - */ - *(u32 *)hwfib->data = cpu_to_le32(ST_OK); - hwfib->header.XferState |= cpu_to_le32(AdapterProcessed); - } - - FIB_COUNTER_INCREMENT(aac_config.FibRecved); - - if (hwfib->header.Command == cpu_to_le16(NuFileSystem)) - { - u32 *pstatus = (u32 *)hwfib->data; - if (*pstatus & cpu_to_le32(0xffff0000)) - *pstatus = cpu_to_le32(ST_OK); - } - if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) - { - if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected)) - FIB_COUNTER_INCREMENT(aac_config.NoResponseRecved); - else - FIB_COUNTER_INCREMENT(aac_config.AsyncRecved); - /* - * NOTE: we cannot touch the fib after this - * call, because it may have been deallocated. - */ - fib->callback(fib->callback_data, fib); - } else { -#if 0 - unsigned long flagv; - spin_lock_irqsave(&fib->event_lock, flagv); -#endif - fib->done = 1; -#if 0 - up(&fib->event_wait); - spin_unlock_irqrestore(&fib->event_lock, flagv); -#endif - FIB_COUNTER_INCREMENT(aac_config.NormalRecved); - } - consumed++; - spin_lock_irqsave(q->lock, flags); - } - - if (consumed > aac_config.peak_fibs) - aac_config.peak_fibs = consumed; - if (consumed == 0) - aac_config.zero_fibs++; - - spin_unlock_irqrestore(q->lock, flags); - return 0; -} - - -/** - * aac_command_normal - handle commands - * @q: queue to process - * - * This DPC routine will be queued when the adapter interrupts us to - * let us know there is a command on our normal priority queue. We will - * pull off all QE there are and wake up all the waiters before exiting. - * We will take a spinlock out on the queue before operating on it. - */ - -unsigned int aac_command_normal(struct aac_queue *q) -{ - struct aac_dev * dev = q->dev; - struct aac_entry *entry; - unsigned long flags; - - spin_lock_irqsave(q->lock, flags); - - /* - * Keep pulling response QEs off the response queue and waking - * up the waiters until there are no more QEs. We then return - * back to the system. - */ - dprintk((KERN_INFO - "dev=%p, dev->comm_phys=%x, dev->comm_addr=%p, dev->comm_size=%u\n", - dev, (u32)dev->comm_phys, dev->comm_addr, (unsigned)dev->comm_size)); - - while(aac_consumer_get(dev, q, &entry)) - { - struct fib fibctx; - struct fib *fib = &fibctx; - u32 hw_fib_pa = le32_to_cpu(entry->addr & cpu_to_le32(~0x01)); - struct hw_fib * hw_fib_va = ((dev->comm_phys <= hw_fib_pa) - && (hw_fib_pa < (dev->comm_phys + dev->comm_size))) - ? dev->comm_addr + (hw_fib_pa - dev->comm_phys) - : /* inconceivable */ bus_to_virt(hw_fib_pa); - dprintk((KERN_INFO "hw_fib_pa=%x hw_fib_va=%p\n", hw_fib_pa, hw_fib_va)); - - /* - * Allocate a FIB at all costs. For non queued stuff - * we can just use the stack so we are happy. We need - * a fib object in order to manage the linked lists - */ - if (dev->aif_thread) - if((fib = kmalloc(sizeof(struct fib), GFP_ATOMIC))==NULL) - fib = &fibctx; - - memset(fib, 0, sizeof(struct fib)); - INIT_LIST_HEAD(&fib->fiblink); - fib->type = FSAFS_NTC_FIB_CONTEXT; - fib->size = sizeof(struct fib); - fib->hw_fib = hw_fib_va; - fib->data = hw_fib_va->data; - fib->dev = dev; - - if (dev->aif_thread && fib != &fibctx) - { - list_add_tail(&fib->fiblink, &q->cmdq); - aac_consumer_free(dev, q, HostNormCmdQueue); -#if 0 - wake_up_interruptible(&q->cmdready); -#endif - } else { - aac_consumer_free(dev, q, HostNormCmdQueue); - spin_unlock_irqrestore(q->lock, flags); - /* - * Set the status of this FIB - */ - *(u32 *)hw_fib_va->data = cpu_to_le32(ST_OK); - fib_adapter_complete(fib, sizeof(u32)); - spin_lock_irqsave(q->lock, flags); - } - } - spin_unlock_irqrestore(q->lock, flags); - return 0; -} diff --git a/xen/drivers/scsi/aacraid/linit.c b/xen/drivers/scsi/aacraid/linit.c deleted file mode 100644 index 19d6135e98..0000000000 --- a/xen/drivers/scsi/aacraid/linit.c +++ /dev/null @@ -1,777 +0,0 @@ -/* - * Adaptec AAC series RAID controller driver - * (c) Copyright 2001 Red Hat Inc. - * - * based on the old aacraid driver that is.. - * Adaptec aacraid device driver for Linux. - * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Module Name: - * linit.c - * - * Abstract: Linux Driver entry module for Adaptec RAID Array Controller - * - * Provides the following driver entry points: - * aac_detect() - * aac_release() - * aac_queuecommand() - * aac_resetcommand() - * aac_biosparm() - * - */ - -#define AAC_DRIVER_VERSION "1.1.2" -#define AAC_DRIVER_BUILD_DATE __DATE__ " " __TIME__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -/*#include */ -/*#include */ -#include -#include "scsi.h" -#include "hosts.h" - -#include "aacraid.h" -#include "sd.h" - -#define AAC_DRIVERNAME "aacraid" - -MODULE_AUTHOR("Red Hat Inc and Adaptec"); -MODULE_DESCRIPTION("Supports Dell PERC2, 2/Si, 3/Si, 3/Di, Adaptec Advanced Raid Products, and HP NetRAID-4M devices. http://domsch.com/linux/ or http://linux.adaptec.com"); -MODULE_LICENSE("GPL"); -MODULE_PARM(paemode, "i"); -MODULE_PARM_DESC(paemode, "Control whether dma addressing is using PAE. 0=off, 1=on"); - -#if 0 -static int paemode = -1; -#endif - -struct aac_dev *aac_devices[MAXIMUM_NUM_ADAPTERS]; - -static unsigned aac_count = 0; -static int aac_cfg_major = -1; - -/* - * Because of the way Linux names scsi devices, the order in this table has - * become important. Check for on-board Raid first, add-in cards second. - * - * dmb - For now we add the number of channels to this structure. - * In the future we should add a fib that reports the number of channels - * for the card. At that time we can remove the channels from here - */ - -static struct aac_driver_ident aac_drivers[] = { - { 0x1028, 0x0001, 0x1028, 0x0001, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 2/Si (Iguana/PERC2Si) */ - { 0x1028, 0x0002, 0x1028, 0x0002, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Opal/PERC3Di) */ - { 0x1028, 0x0003, 0x1028, 0x0003, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Si (SlimFast/PERC3Si */ - { 0x1028, 0x0004, 0x1028, 0x00d0, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Iguana FlipChip/PERC3DiF */ - { 0x1028, 0x0002, 0x1028, 0x00d1, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Viper/PERC3DiV) */ - { 0x1028, 0x0002, 0x1028, 0x00d9, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Lexus/PERC3DiL) */ - { 0x1028, 0x000a, 0x1028, 0x0106, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Jaguar/PERC3DiJ) */ - { 0x1028, 0x000a, 0x1028, 0x011b, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Dagger/PERC3DiD) */ - { 0x1028, 0x000a, 0x1028, 0x0121, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Boxster/PERC3DiB) */ - { 0x9005, 0x0283, 0x9005, 0x0283, aac_rx_init, "aacraid", "ADAPTEC ", "catapult ", 2 }, /* catapult */ - { 0x9005, 0x0284, 0x9005, 0x0284, aac_rx_init, "aacraid", "ADAPTEC ", "tomcat ", 2 }, /* tomcat */ - { 0x9005, 0x0285, 0x9005, 0x0286, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1, AAC_QUIRK_31BIT },/* Adaptec 2120S (Crusader) */ - { 0x9005, 0x0285, 0x9005, 0x0285, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT },/* Adaptec 2200S (Vulcan) */ - { 0x9005, 0x0285, 0x9005, 0x0287, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT },/* Adaptec 2200S (Vulcan-2m) */ - { 0x9005, 0x0285, 0x17aa, 0x0286, aac_rx_init, "aacraid", "Legend ", "Legend S220 ", 1 }, /* Legend S220 (Legend Crusader) */ - { 0x9005, 0x0285, 0x17aa, 0x0287, aac_rx_init, "aacraid", "Legend ", "Legend S230 ", 2 }, /* Legend S230 (Legend Vulcan) */ - - { 0x9005, 0x0285, 0x9005, 0x0288, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3230S ", 2 }, /* Adaptec 3230S (Harrier) */ - { 0x9005, 0x0285, 0x9005, 0x0289, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3240S ", 2 }, /* Adaptec 3240S (Tornado) */ - { 0x9005, 0x0285, 0x9005, 0x028a, aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020S PCI-X ", 2 }, /* ASR-2020S PCI-X ZCR (Skyhawk) */ - { 0x9005, 0x0285, 0x9005, 0x028b, aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020S PCI-X ", 2 }, /* ASR-2020S SO-DIMM PCI-X ZCR (Terminator) */ - { 0x9005, 0x0285, 0x9005, 0x0290, aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 2 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */ - { 0x9005, 0x0285, 0x1028, 0x0291, aac_rx_init, "aacraid", "DELL ", "CERC SATA RAID 2 ", 2 }, /* CERC SATA RAID 2 PCI SATA 8ch (DellCorsair) */ - { 0x9005, 0x0285, 0x9005, 0x0292, aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 2 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ - { 0x9005, 0x0285, 0x9005, 0x0293, aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA ", 2 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ - { 0x9005, 0x0285, 0x9005, 0x0294, aac_rx_init, "aacraid", "ADAPTEC ", "SO-DIMM SATA ZCR ", 2 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ - /* ServeRAID */ -/* { 0x9005, 0x0250, 0x1014, 0x0279, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec ", 2 }, */ /* (Marco) */ -/* { 0x9005, 0x0250, 0x1014, 0x028c, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec ", 2 }, */ /* (Sebring)*/ - - { 0x9005, 0x0285, 0x1028, 0x0287, aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2 }, /* Perc 320/DC*/ - { 0x1011, 0x0046, 0x9005, 0x0365, aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4 }, /* Adaptec 5400S (Mustang)*/ - { 0x1011, 0x0046, 0x9005, 0x0364, aac_sa_init, "aacraid", "ADAPTEC ", "AAC-364 ", 4 }, /* Adaptec 5400S (Mustang)*/ - { 0x1011, 0x0046, 0x9005, 0x1364, aac_sa_init, "percraid", "DELL ", "PERCRAID ", 4 }, /* Dell PERC2 "Quad Channel" */ - { 0x1011, 0x0046, 0x103c, 0x10c2, aac_sa_init, "hpnraid", "HP ", "NetRAID ", 4 } /* HP NetRAID-4M */ -}; - -#define NUM_AACTYPES (sizeof(aac_drivers) / sizeof(struct aac_driver_ident)) -static int num_aacdrivers = NUM_AACTYPES; - -#if 0 -static int aac_cfg_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); -static int aac_cfg_open(struct inode * inode, struct file * file); -static int aac_cfg_release(struct inode * inode,struct file * file); - -static struct file_operations aac_cfg_fops = { - owner: THIS_MODULE, - ioctl: aac_cfg_ioctl, - open: aac_cfg_open, - release: aac_cfg_release -}; -#endif - -static int aac_detect(Scsi_Host_Template *); -static int aac_release(struct Scsi_Host *); -static int aac_queuecommand(Scsi_Cmnd *, void (*CompletionRoutine)(Scsi_Cmnd *)); -static int aac_biosparm(Scsi_Disk *, kdev_t, int *); -#ifdef CONFIG_PROC_FS -static int aac_procinfo(char *, char **, off_t, int, int, int); -#endif -static int aac_ioctl(Scsi_Device *, int, void *); -static int aac_eh_abort(Scsi_Cmnd * cmd); -static int aac_eh_device_reset(Scsi_Cmnd* cmd); -static int aac_eh_bus_reset(Scsi_Cmnd* cmd); -static int aac_eh_reset(Scsi_Cmnd* cmd); - -static void aac_queuedepth(struct Scsi_Host *, Scsi_Device *); - -/** - * aac_detect - Probe for aacraid cards - * @template: SCSI driver template - * - * Probe for AAC Host Adapters initialize, register, and report the - * configuration of each AAC Host Adapter found. - * Returns the number of adapters successfully initialized and - * registered. - * Initializes all data necessary for this particular SCSI driver. - * Notes: - * The detect routine must not call any of the mid level functions - * to queue commands because things are not guaranteed to be set - * up yet. The detect routine can send commands to the host adapter - * as long as the program control will not be passed to scsi.c in - * the processing of the command. Note especially that - * scsi_malloc/scsi_free must not be called. - * - */ - -static int aac_detect(Scsi_Host_Template *template) -{ - int index; - int container; - u16 vendor_id, device_id; - struct Scsi_Host *host_ptr; - struct pci_dev *dev = NULL; - struct aac_dev *aac; - struct fsa_scsi_hba *fsa_dev_ptr; - char *name = NULL; - - printk(KERN_INFO "Red Hat/Adaptec aacraid driver (%s %s)\n", AAC_DRIVER_VERSION, AAC_DRIVER_BUILD_DATE); - - /* setting up the proc directory structure */ - template->proc_name = "aacraid"; - spin_unlock_irq(&io_request_lock); - - for( index = 0; index != num_aacdrivers; index++ ) - { - device_id = aac_drivers[index].device; - vendor_id = aac_drivers[index].vendor; - name = aac_drivers[index].name; - dprintk((KERN_DEBUG "Checking %s %x/%x/%x/%x.\n", - name, vendor_id, device_id, - aac_drivers[index].subsystem_vendor, - aac_drivers[index].subsystem_device)); - - dev = NULL; - while((dev = pci_find_device(vendor_id, device_id, dev))) { - if (pci_enable_device(dev)) - continue; - pci_set_master(dev); - - if(aac_drivers[index].quirks & AAC_QUIRK_31BIT) - pci_set_dma_mask(dev, 0x7FFFFFFFULL); - else - pci_set_dma_mask(dev, 0xFFFFFFFFULL); - - if((dev->subsystem_vendor != aac_drivers[index].subsystem_vendor) || - (dev->subsystem_device != aac_drivers[index].subsystem_device)) - continue; - - dprintk((KERN_DEBUG "%s device detected.\n", name)); - dprintk((KERN_DEBUG "%x/%x/%x/%x.\n", vendor_id, device_id, - aac_drivers[index].subsystem_vendor, aac_drivers[index].subsystem_device)); - /* - * scsi_register() allocates memory for a Scsi_Hosts structure and - * links it into the linked list of host adapters. This linked list - * contains the data for all possible scsi hosts. - * This is similar to the Scsi_Host_Template, except that we have - * one entry for each actual physical host adapter on the system, - * stored as a linked list. If there are two AAC boards, then we - * will need to make two Scsi_Host entries, but there will be only - * one Scsi_Host_Template entry. The second argument to scsi_register() - * specifies the size of the extra memory we want to hold any device - * specific information. - */ - host_ptr = scsi_register( template, sizeof(struct aac_dev) ); - if(host_ptr == NULL) - continue; - /* Increment the host adapter count */ - aac_count++; - /* - * These three parameters can be used to allow for wide SCSI - * and for host adapters that support multiple buses. - */ - host_ptr->irq = dev->irq; /* Adapter IRQ number */ - /* host_ptr->base = ( char * )(dev->resource[0].start & ~0xff); */ - host_ptr->base = dev->resource[0].start; - scsi_set_pci_device(host_ptr, dev); - dprintk((KERN_DEBUG "Device base address = 0x%lx [0x%lx].\n", host_ptr->base, dev->resource[0].start)); - dprintk((KERN_DEBUG "Device irq = 0x%x.\n", dev->irq)); - /* - * The unique_id field is a unique identifier that must - * be assigned so that we have some way of identifying - * each host adapter properly and uniquely. For hosts - * that do not support more than one card in the - * system, this does not need to be set. It is - * initialized to zero in scsi_register(). This is the - * value returned as aac->id. - */ - host_ptr->unique_id = aac_count - 1; - /* - * This function is called after the device list has - * been built to find the tagged queueing depth - * supported for each device. - */ - host_ptr->select_queue_depths = aac_queuedepth; - aac = (struct aac_dev *)host_ptr->hostdata; - /* attach a pointer back to Scsi_Host */ - aac->scsi_host_ptr = host_ptr; - aac->pdev = dev; - aac->name = aac->scsi_host_ptr->hostt->name; - aac->id = aac->scsi_host_ptr->unique_id; - aac->cardtype = index; - - aac->fibs = (struct fib*) kmalloc(sizeof(struct fib)*AAC_NUM_FIB, GFP_KERNEL); - spin_lock_init(&aac->fib_lock); - - /* Initialize the ordinal number of the device to -1 */ - fsa_dev_ptr = &(aac->fsa_dev); - for( container = 0; container < MAXIMUM_NUM_CONTAINERS; container++ ) - fsa_dev_ptr->devno[container] = -1; - - dprintk((KERN_DEBUG "Initializing Hardware...\n")); - if((*aac_drivers[index].init)(aac , host_ptr->unique_id) != 0) - { - /* device initialization failed */ - printk(KERN_WARNING "aacraid: device initialization failed.\n"); - scsi_unregister(host_ptr); - aac_count--; - continue; - } - dprintk((KERN_DEBUG "%s:%d device initialization successful.\n", name, host_ptr->unique_id)); - aac_get_adapter_info(aac); - if(aac->nondasd_support == 1) - { - /* - * max channel will be the physical channels plus 1 virtual channel - * all containers are on the virtual channel 0 - * physical channels are address by their actual physical number+1 - */ - host_ptr->max_channel = aac_drivers[index].channels+1; - } else { - host_ptr->max_channel = 1; - } - dprintk((KERN_DEBUG "Device has %d logical channels\n", host_ptr->max_channel)); - aac_get_containers(aac); - aac_devices[aac_count-1] = aac; - - /* - * dmb - we may need to move the setting of these parms somewhere else once - * we get a fib that can report the actual numbers - */ - host_ptr->max_id = AAC_MAX_TARGET; - host_ptr->max_lun = AAC_MAX_LUN; - } - } - -#if 0 - if( aac_count ){ - if((aac_cfg_major = register_chrdev( 0, "aac", &aac_cfg_fops))<0) - printk(KERN_WARNING "aacraid: unable to register \"aac\" device.\n"); - } -#endif - spin_lock_irq(&io_request_lock); - - template->present = aac_count; /* # of cards of this type found */ - return aac_count; -} - -/** - * aac_release - release SCSI host resources - * @host_ptr: SCSI host to clean up - * - * Release all resources previously acquired to support a specific Host - * Adapter and unregister the AAC Host Adapter. - * - * BUGS: Does not wait for the thread it kills to die. - */ - -static int aac_release(struct Scsi_Host *host_ptr) -{ - struct aac_dev *dev; - dprintk((KERN_DEBUG "aac_release.\n")); - dev = (struct aac_dev *)host_ptr->hostdata; -#if 0 - /* - * kill any threads we started - */ - kill_proc(dev->thread_pid, SIGKILL, 0); - wait_for_completion(&dev->aif_completion); -#endif - /* - * Call the comm layer to detach from this adapter - */ - aac_detach(dev); - /* Check free orderings... */ - /* remove interrupt binding */ - free_irq(host_ptr->irq, dev); - iounmap((void * )dev->regs.sa); - /* unregister adapter */ - scsi_unregister(host_ptr); - /* - * FIXME: This assumes no hot plugging is going on... - */ - if( aac_cfg_major >= 0 ) - { -#if 0 - unregister_chrdev(aac_cfg_major, "aac"); -#endif - aac_cfg_major = -1; - } - return 0; -} - -/** - * aac_queuecommand - queue a SCSI command - * @scsi_cmnd_ptr: SCSI command to queue - * @CompletionRoutine: Function to call on command completion - * - * Queues a command for execution by the associated Host Adapter. - */ - -static int aac_queuecommand(Scsi_Cmnd *scsi_cmnd_ptr, void (*complete)(Scsi_Cmnd *)) -{ - int ret; - - scsi_cmnd_ptr->scsi_done = complete; - /* - * aac_scsi_cmd() handles command processing, setting the - * result code and calling completion routine. - */ - if((ret = aac_scsi_cmd(scsi_cmnd_ptr)) != 0) - dprintk((KERN_DEBUG "aac_scsi_cmd failed.\n")); - return ret; -} - -/** - * aac_driverinfo - Returns the host adapter name - * @host_ptr: Scsi host to report on - * - * Returns a static string describing the device in question - */ - -const char *aac_driverinfo(struct Scsi_Host *host_ptr) -{ - struct aac_dev *dev = (struct aac_dev *)host_ptr->hostdata; - return aac_drivers[dev->cardtype].name; -} - -/** - * aac_get_driver_ident - * @devtype: index into lookup table - * - * Returns a pointer to the entry in the driver lookup table. - */ -struct aac_driver_ident* aac_get_driver_ident(int devtype) -{ - return &aac_drivers[devtype]; -} - -/** - * aac_biosparm - return BIOS parameters for disk - * @disk: SCSI disk object to process - * @device: kdev_t of the disk in question - * @geom: geometry block to fill in - * - * Return the Heads/Sectors/Cylinders BIOS Disk Parameters for Disk. - * The default disk geometry is 64 heads, 32 sectors, and the appropriate - * number of cylinders so as not to exceed drive capacity. In order for - * disks equal to or larger than 1 GB to be addressable by the BIOS - * without exceeding the BIOS limitation of 1024 cylinders, Extended - * Translation should be enabled. With Extended Translation enabled, - * drives between 1 GB inclusive and 2 GB exclusive are given a disk - * geometry of 128 heads and 32 sectors, and drives above 2 GB inclusive - * are given a disk geometry of 255 heads and 63 sectors. However, if - * the BIOS detects that the Extended Translation setting does not match - * the geometry in the partition table, then the translation inferred - * from the partition table will be used by the BIOS, and a warning may - * be displayed. - */ - -static int aac_biosparm(Scsi_Disk *disk, kdev_t dev, int *geom) -{ - struct diskparm *param = (struct diskparm *)geom; -#if 0 - struct buffer_head * buf; -#endif - - dprintk((KERN_DEBUG "aac_biosparm.\n")); - - /* - * Assuming extended translation is enabled - #REVISIT# - */ - if( disk->capacity >= 2 * 1024 * 1024 ) /* 1 GB in 512 byte sectors */ - { - if( disk->capacity >= 4 * 1024 * 1024 ) /* 2 GB in 512 byte sectors */ - { - param->heads = 255; - param->sectors = 63; - } - else - { - param->heads = 128; - param->sectors = 32; - } - } - else - { - param->heads = 64; - param->sectors = 32; - } - - param->cylinders = disk->capacity/(param->heads * param->sectors); - -#if 0 - /* - * Read the first 1024 bytes from the disk device - */ - - buf = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, block_size(dev)); - if(buf == NULL) - return 0; - /* - * If the boot sector partition table is valid, search for a partition - * table entry whose end_head matches one of the standard geometry - * translations ( 64/32, 128/32, 255/63 ). - */ - - if(*(unsigned short *)(buf->b_data + 0x1fe) == cpu_to_le16(0xaa55)) - { - struct partition *first = (struct partition * )(buf->b_data + 0x1be); - struct partition *entry = first; - int saved_cylinders = param->cylinders; - int num; - unsigned char end_head, end_sec; - - for(num = 0; num < 4; num++) - { - end_head = entry->end_head; - end_sec = entry->end_sector & 0x3f; - - if(end_head == 63) - { - param->heads = 64; - param->sectors = 32; - break; - } - else if(end_head == 127) - { - param->heads = 128; - param->sectors = 32; - break; - } - else if(end_head == 254) - { - param->heads = 255; - param->sectors = 63; - break; - } - entry++; - } - - if(num == 4) - { - end_head = first->end_head; - end_sec = first->end_sector & 0x3f; - } - - param->cylinders = disk->capacity / (param->heads * param->sectors); - - if(num < 4 && end_sec == param->sectors) - { - if(param->cylinders != saved_cylinders) - dprintk((KERN_DEBUG "Adopting geometry: heads=%d, sectors=%d from partition table %d.\n", - param->heads, param->sectors, num)); - } - else if(end_head > 0 || end_sec > 0) - { - dprintk((KERN_DEBUG "Strange geometry: heads=%d, sectors=%d in partition table %d.\n", - end_head + 1, end_sec, num)); - dprintk((KERN_DEBUG "Using geometry: heads=%d, sectors=%d.\n", - param->heads, param->sectors)); - } - } - brelse(buf); -#endif - return 0; -} - -/** - * aac_queuedepth - compute queue depths - * @host: SCSI host in question - * @dev: SCSI device we are considering - * - * Selects queue depths for each target device based on the host adapter's - * total capacity and the queue depth supported by the target device. - * A queue depth of one automatically disables tagged queueing. - */ - -static void aac_queuedepth(struct Scsi_Host * host, Scsi_Device * dev ) -{ - Scsi_Device * dptr; - - dprintk((KERN_DEBUG "aac_queuedepth.\n")); - dprintk((KERN_DEBUG "Device # Q Depth Online\n")); - dprintk((KERN_DEBUG "---------------------------\n")); - for(dptr = dev; dptr != NULL; dptr = dptr->next) - { - if(dptr->host == host) - { - dptr->queue_depth = 10; - dprintk((KERN_DEBUG " %2d %d %d\n", - dptr->id, dptr->queue_depth, dptr->online)); - } - } -} - - -/** - * aac_eh_abort - Abort command if possible. - * @cmd: SCSI command block to abort - * - * Called when the midlayer wishes to abort a command. We don't support - * this facility, and our firmware looks after life for us. We just - * report this as failing - */ - -static int aac_eh_abort(Scsi_Cmnd *cmd) -{ - return FAILED; -} - -/** - * aac_eh_device_reset - Reset command handling - * @cmd: SCSI command block causing the reset - * - * Issue a reset of a SCSI device. We are ourselves not truely a SCSI - * controller and our firmware will do the work for us anyway. Thus this - * is a no-op. We just return FAILED. - */ - -static int aac_eh_device_reset(Scsi_Cmnd *cmd) -{ - return FAILED; -} - -/** - * aac_eh_bus_reset - Reset command handling - * @scsi_cmd: SCSI command block causing the reset - * - * Issue a reset of a SCSI bus. We are ourselves not truely a SCSI - * controller and our firmware will do the work for us anyway. Thus this - * is a no-op. We just return FAILED. - */ - -static int aac_eh_bus_reset(Scsi_Cmnd* cmd) -{ - return FAILED; -} - -/** - * aac_eh_hba_reset - Reset command handling - * @scsi_cmd: SCSI command block causing the reset - * - * Issue a reset of a SCSI host. If things get this bad then arguably we should - * go take a look at what the host adapter is doing and see if something really - * broke (as can occur at least on my Dell QC card if a drive keeps failing spinup) - */ - -static int aac_eh_reset(Scsi_Cmnd* cmd) -{ - printk(KERN_ERR "aacraid: Host adapter reset request. SCSI hang ?\n"); - return FAILED; -} - -/** - * aac_ioctl - Handle SCSI ioctls - * @scsi_dev_ptr: scsi device to operate upon - * @cmd: ioctl command to use issue - * @arg: ioctl data pointer - * - * Issue an ioctl on an aacraid device. Returns a standard unix error code or - * zero for success - */ - -static int aac_ioctl(Scsi_Device * scsi_dev_ptr, int cmd, void * arg) -{ - struct aac_dev *dev; - dprintk((KERN_DEBUG "aac_ioctl.\n")); - dev = (struct aac_dev *)scsi_dev_ptr->host->hostdata; - return aac_do_ioctl(dev, cmd, arg); -} - -#if 0 /* XEN */ -/** - * aac_cfg_open - open a configuration file - * @inode: inode being opened - * @file: file handle attached - * - * Called when the configuration device is opened. Does the needed - * set up on the handle and then returns - * - * Bugs: This needs extending to check a given adapter is present - * so we can support hot plugging, and to ref count adapters. - */ - -static int aac_cfg_open(struct inode * inode, struct file * file ) -{ - unsigned minor_number = MINOR(inode->i_rdev); - if(minor_number >= aac_count) - return -ENODEV; - return 0; -} - -/** - * aac_cfg_release - close down an AAC config device - * @inode: inode of configuration file - * @file: file handle of configuration file - * - * Called when the last close of the configuration file handle - * is performed. - */ - -static int aac_cfg_release(struct inode * inode, struct file * file ) -{ - return 0; -} - -/** - * aac_cfg_ioctl - AAC configuration request - * @inode: inode of device - * @file: file handle - * @cmd: ioctl command code - * @arg: argument - * - * Handles a configuration ioctl. Currently this involves wrapping it - * up and feeding it into the nasty windowsalike glue layer. - * - * Bugs: Needs locking against parallel ioctls lower down - * Bugs: Needs to handle hot plugging - */ - -static int aac_cfg_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg ) -{ - struct aac_dev *dev = aac_devices[MINOR(inode->i_rdev)]; - return aac_do_ioctl(dev, cmd, (void *)arg); -} -#endif /* 0 (XEN) */ - -/* - * To use the low level SCSI driver support using the linux kernel loadable - * module interface we should initialize the global variable driver_interface - * (datatype Scsi_Host_Template) and then include the file scsi_module.c. - */ - -static Scsi_Host_Template driver_template = { -#if 0 - module: THIS_MODULE, -#endif - name: "AAC", -#if 0 - proc_info: aac_procinfo, -#endif - detect: aac_detect, - release: aac_release, - info: aac_driverinfo, - ioctl: aac_ioctl, - queuecommand: aac_queuecommand, - bios_param: aac_biosparm, - can_queue: AAC_NUM_IO_FIB, - this_id: 16, - sg_tablesize: 16, - max_sectors: 128, - cmd_per_lun: AAC_NUM_IO_FIB, - eh_abort_handler: aac_eh_abort, - eh_device_reset_handler:aac_eh_device_reset, - eh_bus_reset_handler: aac_eh_bus_reset, - eh_host_reset_handler: aac_eh_reset, - use_new_eh_code: 1, - - use_clustering: ENABLE_CLUSTERING, -}; - -#include "../scsi_module.c.inc" - -#ifdef CONFIG_PROC_FS -/** - * aac_procinfo - Implement /proc/scsi// - * @proc_buffer: memory buffer for I/O - * @start_ptr: pointer to first valid data - * @offset: offset into file - * @bytes_available: space left - * @host_no: scsi host ident - * @write: direction of I/O - * - * Used to export driver statistics and other infos to the world outside - * the kernel using the proc file system. Also provides an interface to - * feed the driver with information. - * - * For reads - * - if offset > 0 return 0 - * - if offset == 0 write data to proc_buffer and set the start_ptr to - * beginning of proc_buffer, return the number of characters written. - * For writes - * - writes currently not supported, return 0 - * - * Bugs: Only offset zero is handled - */ - -static int aac_procinfo(char *proc_buffer, char **start_ptr,off_t offset, - int bytes_available, int host_no, int write) -{ - if(write || offset > 0) - return 0; - *start_ptr = proc_buffer; - return sprintf(proc_buffer, - "Adaptec Raid Controller %s %s, scsi hba number %d\n", - AAC_DRIVER_VERSION, AAC_DRIVER_BUILD_DATE, - host_no); -} -#endif - -EXPORT_NO_SYMBOLS; diff --git a/xen/drivers/scsi/aacraid/rx.c b/xen/drivers/scsi/aacraid/rx.c deleted file mode 100644 index 87e24b9af8..0000000000 --- a/xen/drivers/scsi/aacraid/rx.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Adaptec AAC series RAID controller driver - * (c) Copyright 2001 Red Hat Inc. - * - * based on the old aacraid driver that is.. - * Adaptec aacraid device driver for Linux. - * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Module Name: - * rx.c - * - * Abstract: Hardware miniport for Drawbridge specific hardware functions. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/*#include */ -/*#include */ -#include "scsi.h" -#include "hosts.h" - -#include "aacraid.h" - -static void aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - struct aac_dev *dev = dev_id; - unsigned long bellbits; - u8 intstat, mask; - intstat = rx_readb(dev, MUnit.OISR); - /* - * Read mask and invert because drawbridge is reversed. - * This allows us to only service interrupts that have - * been enabled. - */ - mask = ~(rx_readb(dev, MUnit.OIMR)); - /* Check to see if this is our interrupt. If it isn't just return */ - if (intstat & mask) - { - bellbits = rx_readl(dev, OutboundDoorbellReg); - if (bellbits & DoorBellPrintfReady) { - aac_printf(dev, le32_to_cpu(rx_readl (dev, IndexRegs.Mailbox[5]))); - rx_writel(dev, MUnit.ODR,DoorBellPrintfReady); - rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); - } - else if (bellbits & DoorBellAdapterNormCmdReady) { - aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); - } - else if (bellbits & DoorBellAdapterNormRespReady) { - aac_response_normal(&dev->queues->queue[HostNormRespQueue]); - rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); - } - else if (bellbits & DoorBellAdapterNormCmdNotFull) { - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); - } - else if (bellbits & DoorBellAdapterNormRespNotFull) { - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); - } - } -} - -/** - * aac_rx_enable_interrupt - Enable event reporting - * @dev: Adapter - * @event: Event to enable - * - * Enable event reporting from the i960 for a given event. - */ - -static void aac_rx_enable_interrupt(struct aac_dev * dev, u32 event) -{ - switch (event) { - - case HostNormCmdQue: - dev->irq_mask &= ~(OUTBOUNDDOORBELL_1); - break; - - case HostNormRespQue: - dev->irq_mask &= ~(OUTBOUNDDOORBELL_2); - break; - - case AdapNormCmdNotFull: - dev->irq_mask &= ~(OUTBOUNDDOORBELL_3); - break; - - case AdapNormRespNotFull: - dev->irq_mask &= ~(OUTBOUNDDOORBELL_4); - break; - } -} - -/** - * aac_rx_disable_interrupt - Disable event reporting - * @dev: Adapter - * @event: Event to enable - * - * Disable event reporting from the i960 for a given event. - */ - -static void aac_rx_disable_interrupt(struct aac_dev *dev, u32 event) -{ - switch (event) { - - case HostNormCmdQue: - dev->irq_mask |= (OUTBOUNDDOORBELL_1); - break; - - case HostNormRespQue: - dev->irq_mask |= (OUTBOUNDDOORBELL_2); - break; - - case AdapNormCmdNotFull: - dev->irq_mask |= (OUTBOUNDDOORBELL_3); - break; - - case AdapNormRespNotFull: - dev->irq_mask |= (OUTBOUNDDOORBELL_4); - break; - } -} - -/** - * rx_sync_cmd - send a command and wait - * @dev: Adapter - * @command: Command to execute - * @p1: first parameter - * @ret: adapter status - * - * This routine will send a synchronous comamnd to the adapter and wait - * for its completion. - */ - -static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) -{ - unsigned long start; - int ok; - /* - * Write the command into Mailbox 0 - */ - rx_writel(dev, InboundMailbox0, cpu_to_le32(command)); - /* - * Write the parameters into Mailboxes 1 - 4 - */ - rx_writel(dev, InboundMailbox1, cpu_to_le32(p1)); - rx_writel(dev, InboundMailbox2, 0); - rx_writel(dev, InboundMailbox3, 0); - rx_writel(dev, InboundMailbox4, 0); - /* - * Clear the synch command doorbell to start on a clean slate. - */ - rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); - /* - * Disable doorbell interrupts - */ - rx_writeb(dev, MUnit.OIMR, rx_readb(dev, MUnit.OIMR) | 0x04); - /* - * Force the completion of the mask register write before issuing - * the interrupt. - */ - rx_readb (dev, MUnit.OIMR); - /* - * Signal that there is a new synch command - */ - rx_writel(dev, InboundDoorbellReg, INBOUNDDOORBELL_0); - - ok = 0; - start = jiffies; - - /* - * Wait up to 30 seconds - */ - while (time_before(jiffies, start+30*HZ)) - { - udelay(5); /* Delay 5 microseconds to let Mon960 get info. */ - /* - * Mon960 will set doorbell0 bit when it has completed the command. - */ - if (rx_readl(dev, OutboundDoorbellReg) & OUTBOUNDDOORBELL_0) { - /* - * Clear the doorbell. - */ - rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); - ok = 1; - break; - } -#if 0 - /* - * Yield the processor in case we are slow - */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); -#else - /* XXX SMH: not in xen we don't */ - mdelay(50); -#endif - } - if (ok != 1) { - /* - * Restore interrupt mask even though we timed out - */ - rx_writeb(dev, MUnit.OIMR, rx_readl(dev, MUnit.OIMR) & 0xfb); - return -ETIMEDOUT; - } - /* - * Pull the synch status from Mailbox 0. - */ - *status = le32_to_cpu(rx_readl(dev, IndexRegs.Mailbox[0])); - /* - * Clear the synch command doorbell. - */ - rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); - /* - * Restore interrupt mask - */ - rx_writeb(dev, MUnit.OIMR, rx_readl(dev, MUnit.OIMR) & 0xfb); - return 0; - -} - -/** - * aac_rx_interrupt_adapter - interrupt adapter - * @dev: Adapter - * - * Send an interrupt to the i960 and breakpoint it. - */ - -static void aac_rx_interrupt_adapter(struct aac_dev *dev) -{ - u32 ret; - rx_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret); -} - -/** - * aac_rx_notify_adapter - send an event to the adapter - * @dev: Adapter - * @event: Event to send - * - * Notify the i960 that something it probably cares about has - * happened. - */ - -static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event) -{ - switch (event) { - - case AdapNormCmdQue: - rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_1); - break; - case HostNormRespNotFull: - rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_4); - break; - case AdapNormRespQue: - rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_2); - break; - case HostNormCmdNotFull: - rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3); - break; - case HostShutdown: -// rx_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, &ret); - break; - case FastIo: - rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6); - break; - case AdapPrintfDone: - rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_5); - break; - default: - BUG(); - break; - } -} - -/** - * aac_rx_start_adapter - activate adapter - * @dev: Adapter - * - * Start up processing on an i960 based AAC adapter - */ - -static void aac_rx_start_adapter(struct aac_dev *dev) -{ - u32 status; - struct aac_init *init; - - init = dev->init; - init->HostElapsedSeconds = cpu_to_le32(jiffies/HZ); - /* - * Tell the adapter we are back and up and running so it will scan - * its command queues and enable our interrupts - */ - dev->irq_mask = (DoorBellPrintfReady | OUTBOUNDDOORBELL_1 | OUTBOUNDDOORBELL_2 | OUTBOUNDDOORBELL_3 | OUTBOUNDDOORBELL_4); - /* - * First clear out all interrupts. Then enable the one's that we - * can handle. - */ - rx_writeb(dev, MUnit.OIMR, 0xff); - rx_writel(dev, MUnit.ODR, 0xffffffff); -// rx_writeb(dev, MUnit.OIMR, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK); - rx_writeb(dev, MUnit.OIMR, 0xfb); - - // We can only use a 32 bit address here - rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &status); -} - -/** - * aac_rx_init - initialize an i960 based AAC card - * @dev: device to configure - * @devnum: adapter number - * - * Allocate and set up resources for the i960 based AAC variants. The - * device_interface in the commregion will be allocated and linked - * to the comm region. - */ - -int aac_rx_init(struct aac_dev *dev, unsigned long num) -{ - unsigned long start; - unsigned long status; - int instance; - const char * name; - - dev->devnum = num; - instance = dev->id; - name = dev->name; - - /* - * Map in the registers from the adapter. - */ - if((dev->regs.rx = (struct rx_registers *)ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL) - { - printk(KERN_WARNING "aacraid: unable to map i960.\n" ); - return -1; - } - /* - * Check to see if the board failed any self tests. - */ - if (rx_readl(dev, IndexRegs.Mailbox[7]) & SELF_TEST_FAILED) { - printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance); - return -1; - } - /* - * Check to see if the board panic'd while booting. - */ - if (rx_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_PANIC) { - printk(KERN_ERR "%s%d: adapter kernel panic'd.\n", dev->name, instance); - return -1; - } - start = jiffies; - /* - * Wait for the adapter to be up and running. Wait up to 3 minutes - */ - while (!(rx_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_UP_AND_RUNNING)) - { - if(time_after(jiffies, start+180*HZ)) - { - status = rx_readl(dev, IndexRegs.Mailbox[7]) >> 16; - printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %ld.\n", dev->name, instance, status); - return -1; - } -#if 0 - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); -#else - /* XXX SMH: no sleeping for us (we're the xen idle task) */ - mdelay(50); -#endif - } - if (request_irq(dev->scsi_host_ptr->irq, aac_rx_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0) - { - printk(KERN_ERR "%s%d: Interrupt unavailable.\n", name, instance); - return -1; - } - /* - * Fill in the function dispatch table. - */ - dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter; - dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt; - dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt; - dev->a_ops.adapter_notify = aac_rx_notify_adapter; - dev->a_ops.adapter_sync_cmd = rx_sync_cmd; - - if (aac_init_adapter(dev) == NULL) - return -1; - /* - * Tell the adapter that all is configured, and it can start - * accepting requests - */ - aac_rx_start_adapter(dev); - return 0; -} diff --git a/xen/drivers/scsi/aacraid/sa.c b/xen/drivers/scsi/aacraid/sa.c deleted file mode 100644 index 125d763c29..0000000000 --- a/xen/drivers/scsi/aacraid/sa.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Adaptec AAC series RAID controller driver - * (c) Copyright 2001 Red Hat Inc. - * - * based on the old aacraid driver that is.. - * Adaptec aacraid device driver for Linux. - * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Module Name: - * sa.c - * - * Abstract: Drawbridge specific support functions - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/*#include */ -/*#include */ -#include "scsi.h" -#include "hosts.h" - -#include "aacraid.h" - -static void aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - struct aac_dev *dev = dev_id; - unsigned short intstat, mask; - - intstat = sa_readw(dev, DoorbellReg_p); - /* - * Read mask and invert because drawbridge is reversed. - * This allows us to only service interrupts that have been enabled. - */ - mask = ~(sa_readw(dev, SaDbCSR.PRISETIRQMASK)); - - /* Check to see if this is our interrupt. If it isn't just return */ - - if (intstat & mask) { - if (intstat & PrintfReady) { - aac_printf(dev, le32_to_cpu(sa_readl(dev, Mailbox5))); - sa_writew(dev, DoorbellClrReg_p, PrintfReady); /* clear PrintfReady */ - sa_writew(dev, DoorbellReg_s, PrintfDone); - } else if (intstat & DOORBELL_1) { // dev -> Host Normal Command Ready - aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); - sa_writew(dev, DoorbellClrReg_p, DOORBELL_1); - } else if (intstat & DOORBELL_2) { // dev -> Host Normal Response Ready - aac_response_normal(&dev->queues->queue[HostNormRespQueue]); - sa_writew(dev, DoorbellClrReg_p, DOORBELL_2); - } else if (intstat & DOORBELL_3) { // dev -> Host Normal Command Not Full - sa_writew(dev, DoorbellClrReg_p, DOORBELL_3); - } else if (intstat & DOORBELL_4) { // dev -> Host Normal Response Not Full - sa_writew(dev, DoorbellClrReg_p, DOORBELL_4); - } - } -} - -/** - * aac_sa_enable_interrupt - enable an interrupt event - * @dev: Which adapter to enable. - * @event: Which adapter event. - * - * This routine will enable the corresponding adapter event to cause an interrupt on - * the host. - */ - -void aac_sa_enable_interrupt(struct aac_dev *dev, u32 event) -{ - switch (event) { - - case HostNormCmdQue: - sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_1); - break; - - case HostNormRespQue: - sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_2); - break; - - case AdapNormCmdNotFull: - sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_3); - break; - - case AdapNormRespNotFull: - sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_4); - break; - } -} - -/** - * aac_sa_disable_interrupt - disable an interrupt event - * @dev: Which adapter to enable. - * @event: Which adapter event. - * - * This routine will enable the corresponding adapter event to cause an interrupt on - * the host. - */ - -void aac_sa_disable_interrupt (struct aac_dev *dev, u32 event) -{ - switch (event) { - - case HostNormCmdQue: - sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_1); - break; - - case HostNormRespQue: - sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_2); - break; - - case AdapNormCmdNotFull: - sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_3); - break; - - case AdapNormRespNotFull: - sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_4); - break; - } -} - -/** - * aac_sa_notify_adapter - handle adapter notification - * @dev: Adapter that notification is for - * @event: Event to notidy - * - * Notify the adapter of an event - */ - -void aac_sa_notify_adapter(struct aac_dev *dev, u32 event) -{ - switch (event) { - - case AdapNormCmdQue: - sa_writew(dev, DoorbellReg_s,DOORBELL_1); - break; - case HostNormRespNotFull: - sa_writew(dev, DoorbellReg_s,DOORBELL_4); - break; - case AdapNormRespQue: - sa_writew(dev, DoorbellReg_s,DOORBELL_2); - break; - case HostNormCmdNotFull: - sa_writew(dev, DoorbellReg_s,DOORBELL_3); - break; - case HostShutdown: - //sa_sync_cmd(dev, HOST_CRASHING, 0, &ret); - break; - case FastIo: - sa_writew(dev, DoorbellReg_s,DOORBELL_6); - break; - case AdapPrintfDone: - sa_writew(dev, DoorbellReg_s,DOORBELL_5); - break; - default: - BUG(); - break; - } -} - - -/** - * sa_sync_cmd - send a command and wait - * @dev: Adapter - * @command: Command to execute - * @p1: first parameter - * @ret: adapter status - * - * This routine will send a synchronous comamnd to the adapter and wait - * for its completion. - */ - -static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret) -{ - unsigned long start; - int ok; - /* - * Write the Command into Mailbox 0 - */ - sa_writel(dev, Mailbox0, cpu_to_le32(command)); - /* - * Write the parameters into Mailboxes 1 - 4 - */ - sa_writel(dev, Mailbox1, cpu_to_le32(p1)); - sa_writel(dev, Mailbox2, 0); - sa_writel(dev, Mailbox3, 0); - sa_writel(dev, Mailbox4, 0); - /* - * Clear the synch command doorbell to start on a clean slate. - */ - sa_writew(dev, DoorbellClrReg_p, DOORBELL_0); - /* - * Signal that there is a new synch command - */ - sa_writew(dev, DoorbellReg_s, DOORBELL_0); - - ok = 0; - start = jiffies; - - while(time_before(jiffies, start+30*HZ)) - { - /* - * Delay 5uS so that the monitor gets access - */ - udelay(5); - /* - * Mon110 will set doorbell0 bit when it has - * completed the command. - */ - if(sa_readw(dev, DoorbellReg_p) & DOORBELL_0) { - ok = 1; - break; - } -#if 0 - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); -#else - mdelay(100); -#endif - } - - if (ok != 1) - return -ETIMEDOUT; - /* - * Clear the synch command doorbell. - */ - sa_writew(dev, DoorbellClrReg_p, DOORBELL_0); - /* - * Pull the synch status from Mailbox 0. - */ - *ret = le32_to_cpu(sa_readl(dev, Mailbox0)); - return 0; -} - -/** - * aac_sa_interrupt_adapter - interrupt an adapter - * @dev: Which adapter to enable. - * - * Breakpoint an adapter. - */ - -static void aac_sa_interrupt_adapter (struct aac_dev *dev) -{ - u32 ret; - sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret); -} - -/** - * aac_sa_start_adapter - activate adapter - * @dev: Adapter - * - * Start up processing on an ARM based AAC adapter - */ - -static void aac_sa_start_adapter(struct aac_dev *dev) -{ - u32 ret; - struct aac_init *init; - /* - * Fill in the remaining pieces of the init. - */ - init = dev->init; - init->HostElapsedSeconds = cpu_to_le32(jiffies/HZ); - - dprintk(("INIT\n")); - /* - * Tell the adapter we are back and up and running so it will scan its command - * queues and enable our interrupts - */ - dev->irq_mask = (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4); - /* - * First clear out all interrupts. Then enable the one's that - * we can handle. - */ - dprintk(("MASK\n")); - sa_writew(dev, SaDbCSR.PRISETIRQMASK, cpu_to_le16(0xffff)); - sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4)); - dprintk(("SYNCCMD\n")); - /* We can only use a 32 bit address here */ - sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &ret); -} - -/** - * aac_sa_init - initialize an ARM based AAC card - * @dev: device to configure - * @devnum: adapter number - * - * Allocate and set up resources for the ARM based AAC variants. The - * device_interface in the commregion will be allocated and linked - * to the comm region. - */ - -int aac_sa_init(struct aac_dev *dev, unsigned long devnum) -{ - unsigned long start; - unsigned long status; - int instance; - const char *name; - - dev->devnum = devnum; - - dprintk(("PREINST\n")); - instance = dev->id; - name = dev->name; - - /* - * Map in the registers from the adapter. - */ - dprintk(("PREMAP\n")); - - if((dev->regs.sa = (struct sa_registers *)ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL) - { - printk(KERN_WARNING "aacraid: unable to map ARM.\n" ); - return -1; - } - /* - * Check to see if the board failed any self tests. - */ - if (sa_readl(dev, Mailbox7) & SELF_TEST_FAILED) { - printk(KERN_WARNING "%s%d: adapter self-test failed.\n", name, instance); - return -1; - } - /* - * Check to see if the board panic'd while booting. - */ - if (sa_readl(dev, Mailbox7) & KERNEL_PANIC) { - printk(KERN_WARNING "%s%d: adapter kernel panic'd.\n", name, instance); - return -1; - } - start = jiffies; - /* - * Wait for the adapter to be up and running. Wait up to 3 minutes. - */ - while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) { - if (time_after(jiffies, start+180*HZ)) { - status = sa_readl(dev, Mailbox7) >> 16; - printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %d.\n", name, instance, le32_to_cpu(status)); - return -1; - } -#if 0 - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); -#else - mdelay(100); -#endif - } - - dprintk(("ATIRQ\n")); - if (request_irq(dev->scsi_host_ptr->irq, aac_sa_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev ) < 0) { - printk(KERN_WARNING "%s%d: Interrupt unavailable.\n", name, instance); - return -1; - } - - /* - * Fill in the function dispatch table. - */ - - dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter; - dev->a_ops.adapter_enable_int = aac_sa_enable_interrupt; - dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt; - dev->a_ops.adapter_notify = aac_sa_notify_adapter; - dev->a_ops.adapter_sync_cmd = sa_sync_cmd; - - dprintk(("FUNCDONE\n")); - - if(aac_init_adapter(dev) == NULL) - return -1; - - dprintk(("NEWADAPTDONE\n")); -#if 0 - /* - * Start any kernel threads needed - */ - dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0); - if (dev->thread_pid < 0) { - printk(KERN_ERR "aacraid: Unable to create command thread.\n"); - return -1; - } -#endif - /* - * Tell the adapter that all is configure, and it can start - * accepting requests - */ - dprintk(("STARTING\n")); - aac_sa_start_adapter(dev); - dprintk(("STARTED\n")); - return 0; -} - diff --git a/xen/drivers/scsi/aic7xxx/Makefile b/xen/drivers/scsi/aic7xxx/Makefile deleted file mode 100644 index dd98ae8d37..0000000000 --- a/xen/drivers/scsi/aic7xxx/Makefile +++ /dev/null @@ -1,74 +0,0 @@ -# -# drivers/scsi/aic7xxx/Makefile -# -# Makefile for the Linux aic7xxx SCSI driver. -# - -O_TARGET := aic7xxx_drv.o - -include $(BASEDIR)/Rules.mk -#CFLAGS += -I$(BASEDIR)/drivers/scsi - -#list-multi := aic7xxx.o aic79xx.o - -#obj-$(CONFIG_SCSI_AIC7XXX) += aic7xxx.o -#ifeq ($(CONFIG_PCI),y) -#obj-$(CONFIG_SCSI_AIC79XX) += aic79xx.o -#endif - -#EXTRA_CFLAGS += -g - -# Platform Specific Files -obj-aic7xxx = aic7xxx_osm.o aic7xxx_proc.o aic7770_osm.o -#PCI Specific Platform Files -#ifeq ($(CONFIG_PCI),y) -obj-aic7xxx += aic7xxx_osm_pci.o -#endif -# Core Files -obj-aic7xxx += aic7xxx_core.o aic7xxx_93cx6.o aic7770.o -#PCI Specific Core Files -#ifeq ($(CONFIG_PCI),y) -obj-aic7xxx += aic7xxx_pci.o -#endif - -# Platform Specific U320 Files -#obj-aic79xx = aic79xx_osm.o -#obj-aic79xx += aic79xx_proc.o -#obj-aic79xx += aic79xx_osm_pci.o -obj-aic7xxx += aic79xx_osm.o -obj-aic7xxx += aic79xx_proc.o -obj-aic7xxx += aic79xx_osm_pci.o -# Core Files -#obj-aic79xx += aic79xx_core.o -#obj-aic79xx += aic79xx_pci.o -obj-aic7xxx += aic79xx_core.o -obj-aic7xxx += aic79xx_pci.o - -default: aic7xxx.o - -aic7xxx_core.o: aic7xxx_seq.h -$(obj-aic7xxx): aic7xxx_reg.h -aic7xxx.o: aic7xxx_seq.h aic7xxx_reg.h $(obj-aic7xxx) - $(LD) $(LD_RFLAG) -r -o $@ $(obj-aic7xxx) - -aic79xx_core.o: aic79xx_seq.h -$(obj-aic79xx): aic79xx_reg.h -aic79xx.o: aic79xx_seq.h aic79xx_reg.h $(obj-aic79xx) - $(LD) $(LD_RFLAG) -r -o $@ $(obj-aic79xx) - -#ifeq ($(CONFIG_AIC7XXX_BUILD_FIRMWARE),y) -#aic7xxx_seq.h aic7xxx_reg.h: aic7xxx.seq aic7xxx.reg aicasm/aicasm -# aicasm/aicasm -I. -r aic7xxx_reg.h -o aic7xxx_seq.h aic7xxx.seq -#endif - -#ifeq ($(CONFIG_AIC79XX_BUILD_FIRMWARE),y) -#aic79xx_seq.h aic79xx_reg.h: aic79xx.seq aic79xx.reg aicasm/aicasm -# aicasm/aicasm -I. -r aic79xx_reg.h -o aic79xx_seq.h aic79xx.seq -#endif - -#aicasm/aicasm: aicasm/*.[chyl] -# $(MAKE) -C aicasm - -clean: - rm -f *.o *~ core - diff --git a/xen/drivers/scsi/aic7xxx/aic7770.c b/xen/drivers/scsi/aic7xxx/aic7770.c deleted file mode 100644 index 045f54c1e2..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic7770.c +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Product specific probe and attach routines for: - * 27/284X and aic7770 motherboard SCSI controllers - * - * Copyright (c) 1994-1998, 2000, 2001 Justin T. Gibbs. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/aic7xxx/aic7770.c#21 $ - * - * $FreeBSD: src/sys/dev/aic7xxx/aic7770.c,v 1.1 2000/09/16 20:02:27 gibbs Exp $ - */ - -#ifdef __linux__ -#include "aic7xxx_osm.h" -#include "aic7xxx_inline.h" -#include "aic7xxx_93cx6.h" -#else -#include -#include -#include -#endif - -#define ID_AIC7770 0x04907770 -#define ID_AHA_274x 0x04907771 -#define ID_AHA_284xB 0x04907756 /* BIOS enabled */ -#define ID_AHA_284x 0x04907757 /* BIOS disabled*/ - -static int aha2840_load_seeprom(struct ahc_softc *ahc); -static ahc_device_setup_t ahc_aic7770_VL_setup; -static ahc_device_setup_t ahc_aic7770_EISA_setup;; -static ahc_device_setup_t ahc_aic7770_setup; - - -struct aic7770_identity aic7770_ident_table [] = -{ - { - ID_AHA_274x, - 0xFFFFFFFF, - "Adaptec 274X SCSI adapter", - ahc_aic7770_EISA_setup - }, - { - ID_AHA_284xB, - 0xFFFFFFFE, - "Adaptec 284X SCSI adapter", - ahc_aic7770_VL_setup - }, - /* Generic chip probes for devices we don't know 'exactly' */ - { - ID_AIC7770, - 0xFFFFFFFF, - "Adaptec aic7770 SCSI adapter", - ahc_aic7770_EISA_setup - } -}; -const int ahc_num_aic7770_devs = NUM_ELEMENTS(aic7770_ident_table); - -struct aic7770_identity * -aic7770_find_device(uint32_t id) -{ - struct aic7770_identity *entry; - int i; - - for (i = 0; i < ahc_num_aic7770_devs; i++) { - entry = &aic7770_ident_table[i]; - if (entry->full_id == (id & entry->id_mask)) - return (entry); - } - return (NULL); -} - -int -aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io) -{ - u_long l; - u_long s; - int error; - int have_seeprom; - u_int hostconf; - u_int irq; - u_int intdef; - - error = entry->setup(ahc); - have_seeprom = 0; - if (error != 0) - return (error); - - error = aic7770_map_registers(ahc, io); - if (error != 0) - return (error); - - /* - * Before we continue probing the card, ensure that - * its interrupts are *disabled*. We don't want - * a misstep to hang the machine in an interrupt - * storm. - */ - ahc_intr_enable(ahc, FALSE); - - ahc->description = entry->name; - error = ahc_softc_init(ahc); - - error = ahc_reset(ahc); - if (error != 0) - return (error); - - /* Make sure we have a valid interrupt vector */ - intdef = ahc_inb(ahc, INTDEF); - irq = intdef & VECTOR; - switch (irq) { - case 9: - case 10: - case 11: - case 12: - case 14: - case 15: - break; - default: - printf("aic7770_config: illegal irq setting %d\n", intdef); - return (ENXIO); - } - - if ((intdef & EDGE_TRIG) != 0) - ahc->flags |= AHC_EDGE_INTERRUPT; - - switch (ahc->chip & (AHC_EISA|AHC_VL)) { - case AHC_EISA: - { - u_int biosctrl; - u_int scsiconf; - u_int scsiconf1; - - biosctrl = ahc_inb(ahc, HA_274_BIOSCTRL); - scsiconf = ahc_inb(ahc, SCSICONF); - scsiconf1 = ahc_inb(ahc, SCSICONF + 1); - - /* Get the primary channel information */ - if ((biosctrl & CHANNEL_B_PRIMARY) != 0) - ahc->flags |= 1; - - if ((biosctrl & BIOSMODE) == BIOSDISABLED) { - ahc->flags |= AHC_USEDEFAULTS; - } else { - if ((ahc->features & AHC_WIDE) != 0) { - ahc->our_id = scsiconf1 & HWSCSIID; - if (scsiconf & TERM_ENB) - ahc->flags |= AHC_TERM_ENB_A; - } else { - ahc->our_id = scsiconf & HSCSIID; - ahc->our_id_b = scsiconf1 & HSCSIID; - if (scsiconf & TERM_ENB) - ahc->flags |= AHC_TERM_ENB_A; - if (scsiconf1 & TERM_ENB) - ahc->flags |= AHC_TERM_ENB_B; - } - } - if ((ahc_inb(ahc, HA_274_BIOSGLOBAL) & HA_274_EXTENDED_TRANS)) - ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B; - break; - } - case AHC_VL: - { - have_seeprom = aha2840_load_seeprom(ahc); - break; - } - default: - break; - } - if (have_seeprom == 0) { - free(ahc->seep_config, M_DEVBUF); - ahc->seep_config = NULL; - } - - /* - * Ensure autoflush is enabled - */ - ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~AUTOFLUSHDIS); - - /* Setup the FIFO threshold and the bus off time */ - hostconf = ahc_inb(ahc, HOSTCONF); - ahc_outb(ahc, BUSSPD, hostconf & DFTHRSH); - ahc_outb(ahc, BUSTIME, (hostconf << 2) & BOFF); - - /* - * Generic aic7xxx initialization. - */ - error = ahc_init(ahc); - if (error != 0) - return (error); - - error = aic7770_map_int(ahc, irq); - if (error != 0) - return (error); - - ahc_list_lock(&l); - /* - * Link this softc in with all other ahc instances. - */ - ahc_softc_insert(ahc); - - /* - * Enable the board's BUS drivers - */ - ahc_outb(ahc, BCTL, ENABLE); - - /* - * Allow interrupts. - */ - ahc_lock(ahc, &s); - ahc_intr_enable(ahc, TRUE); - ahc_unlock(ahc, &s); - - ahc_list_unlock(&l); - - return (0); -} - -/* - * Read the 284x SEEPROM. - */ -static int -aha2840_load_seeprom(struct ahc_softc *ahc) -{ - struct seeprom_descriptor sd; - struct seeprom_config *sc; - int have_seeprom; - uint8_t scsi_conf; - - sd.sd_ahc = ahc; - sd.sd_control_offset = SEECTL_2840; - sd.sd_status_offset = STATUS_2840; - sd.sd_dataout_offset = STATUS_2840; - sd.sd_chip = C46; - sd.sd_MS = 0; - sd.sd_RDY = EEPROM_TF; - sd.sd_CS = CS_2840; - sd.sd_CK = CK_2840; - sd.sd_DO = DO_2840; - sd.sd_DI = DI_2840; - sc = ahc->seep_config; - - if (bootverbose) - printf("%s: Reading SEEPROM...", ahc_name(ahc)); - have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)&sc, - /*start_addr*/0, sizeof(sc)/2); - - if (have_seeprom) { - - if (ahc_verify_cksum(sc) == 0) { - if(bootverbose) - printf ("checksum error\n"); - have_seeprom = 0; - } else if (bootverbose) { - printf("done.\n"); - } - } - - if (!have_seeprom) { - if (bootverbose) - printf("%s: No SEEPROM available\n", ahc_name(ahc)); - ahc->flags |= AHC_USEDEFAULTS; - } else { - /* - * Put the data we've collected down into SRAM - * where ahc_init will find it. - */ - int i; - int max_targ; - uint16_t discenable; - - max_targ = (ahc->features & AHC_WIDE) != 0 ? 16 : 8; - discenable = 0; - for (i = 0; i < max_targ; i++){ - uint8_t target_settings; - - target_settings = (sc->device_flags[i] & CFXFER) << 4; - if (sc->device_flags[i] & CFSYNCH) - target_settings |= SOFS; - if (sc->device_flags[i] & CFWIDEB) - target_settings |= WIDEXFER; - if (sc->device_flags[i] & CFDISC) - discenable |= (0x01 << i); - ahc_outb(ahc, TARG_SCSIRATE + i, target_settings); - } - ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff)); - ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff)); - - ahc->our_id = sc->brtime_id & CFSCSIID; - - scsi_conf = (ahc->our_id & 0x7); - if (sc->adapter_control & CFSPARITY) - scsi_conf |= ENSPCHK; - if (sc->adapter_control & CFRESETB) - scsi_conf |= RESET_SCSI; - - if (sc->bios_control & CF284XEXTEND) - ahc->flags |= AHC_EXTENDED_TRANS_A; - /* Set SCSICONF info */ - ahc_outb(ahc, SCSICONF, scsi_conf); - - if (sc->adapter_control & CF284XSTERM) - ahc->flags |= AHC_TERM_ENB_A; - } - return (have_seeprom); -} - -static int -ahc_aic7770_VL_setup(struct ahc_softc *ahc) -{ - int error; - - error = ahc_aic7770_setup(ahc); - ahc->chip |= AHC_VL; - return (error); -} - -static int -ahc_aic7770_EISA_setup(struct ahc_softc *ahc) -{ - int error; - - error = ahc_aic7770_setup(ahc); - ahc->chip |= AHC_EISA; - return (error); -} - -static int -ahc_aic7770_setup(struct ahc_softc *ahc) -{ - ahc->channel = 'A'; - ahc->channel_b = 'B'; - ahc->chip = AHC_AIC7770; - ahc->features = AHC_AIC7770_FE; - ahc->bugs |= AHC_TMODE_WIDEODD_BUG; - ahc->flags |= AHC_PAGESCBS; - return (0); -} diff --git a/xen/drivers/scsi/aic7xxx/aic7770_osm.c b/xen/drivers/scsi/aic7xxx/aic7770_osm.c deleted file mode 100644 index 80d25528e9..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic7770_osm.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Linux driver attachment glue for aic7770 based controllers. - * - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7770_osm.c#11 $ - */ - -#include "aic7xxx_osm.h" - -#define MINSLOT 1 -#define NUMSLOTS 16 -#define IDOFFSET 0x80 - -int -aic7770_linux_probe(Scsi_Host_Template *template) -{ -#if defined(__i386__) || defined(__alpha__) - struct aic7770_identity *entry; - struct ahc_softc *ahc; - int i, slot; - int eisaBase; - int found; - - eisaBase = 0x1000 + AHC_EISA_SLOT_OFFSET; - found = 0; - for (slot = 1; slot < NUMSLOTS; eisaBase+=0x1000, slot++) { - uint32_t eisa_id; - size_t id_size; - - if (check_region(eisaBase, AHC_EISA_IOSIZE) != 0) - continue; - - eisa_id = 0; - id_size = sizeof(eisa_id); - for (i = 0; i < 4; i++) { - /* VLcards require priming*/ - outb(0x80 + i, eisaBase + IDOFFSET); - eisa_id |= inb(eisaBase + IDOFFSET + i) - << ((id_size-i-1) * 8); - } - if (eisa_id & 0x80000000) - continue; /* no EISA card in slot */ - - entry = aic7770_find_device(eisa_id); - if (entry != NULL) { - char buf[80]; - char *name; - int error; - - /* - * Allocate a softc for this card and - * set it up for attachment by our - * common detect routine. - */ - sprintf(buf, "ahc_eisa:%d", slot); - name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); - if (name == NULL) - break; - strcpy(name, buf); - ahc = ahc_alloc(template, name); - if (ahc == NULL) { - /* - * If we can't allocate this one, - * chances are we won't be able to - * allocate future card structures. - */ - break; - } - error = aic7770_config(ahc, entry, eisaBase); - if (error != 0) { - ahc->bsh.ioport = 0; - ahc_free(ahc); - continue; - } - found++; - } - } - return (found); -#else - return (0); -#endif -} - -int -aic7770_map_registers(struct ahc_softc *ahc, u_int port) -{ - /* - * Lock out other contenders for our i/o space. - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - request_region(port, AHC_EISA_IOSIZE, "aic7xxx"); -#else - if (request_region(port, AHC_EISA_IOSIZE, "aic7xxx") == 0) - return (ENOMEM); -#endif - ahc->tag = BUS_SPACE_PIO; - ahc->bsh.ioport = port; - return (0); -} - -int -aic7770_map_int(struct ahc_softc *ahc, u_int irq) -{ - int error; - int shared; - - shared = 0; - if ((ahc->flags & AHC_EDGE_INTERRUPT) == 0) - shared = SA_SHIRQ; - - error = request_irq(irq, ahc_linux_isr, shared, "aic7xxx", ahc); - if (error == 0) - ahc->platform_data->irq = irq; - - return (-error); -} diff --git a/xen/drivers/scsi/aic7xxx/aic79xx.h b/xen/drivers/scsi/aic7xxx/aic79xx.h deleted file mode 100644 index b4a8abb226..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic79xx.h +++ /dev/null @@ -1,1297 +0,0 @@ -/* - * Core definitions and data structures shareable across OS platforms. - * - * Copyright (c) 1994-2001 Justin T. Gibbs. - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#46 $ - * - * $FreeBSD$ - */ - -#ifndef _AIC79XX_H_ -#define _AIC79XX_H_ - -/* Register Definitions */ -#include "aic79xx_reg.h" - -/************************* Forward Declarations *******************************/ -struct ahd_platform_data; -struct scb_platform_data; - -/****************************** Useful Macros *********************************/ -#ifndef MAX -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -#ifndef MIN -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(*array)) - -#define ALL_CHANNELS '\0' -#define ALL_TARGETS_MASK 0xFFFF -#define INITIATOR_WILDCARD (~0) -#define SCB_LIST_NULL 0xFF00 -#define SCB_LIST_NULL_LE (ahd_htole16(SCB_LIST_NULL)) -#define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL) - -#define SCSIID_TARGET(ahd, scsiid) \ - (((scsiid) & TID) >> TID_SHIFT) -#define SCSIID_OUR_ID(scsiid) \ - ((scsiid) & OID) -#define SCSIID_CHANNEL(ahd, scsiid) ('A') -#define SCB_IS_SCSIBUS_B(ahd, scb) (0) -#define SCB_GET_OUR_ID(scb) \ - SCSIID_OUR_ID((scb)->hscb->scsiid) -#define SCB_GET_TARGET(ahd, scb) \ - SCSIID_TARGET((ahd), (scb)->hscb->scsiid) -#define SCB_GET_CHANNEL(ahd, scb) \ - SCSIID_CHANNEL(ahd, (scb)->hscb->scsiid) -#define SCB_GET_LUN(scb) \ - ((scb)->hscb->lun) -#define SCB_GET_TARGET_OFFSET(ahd, scb) \ - SCB_GET_TARGET(ahd, scb) -#define SCB_GET_TARGET_MASK(ahd, scb) \ - (0x01 << (SCB_GET_TARGET_OFFSET(ahd, scb))) -/* - * TCLs have the following format: TTTTLLLLLLLL - */ -#define TCL_TARGET_OFFSET(tcl) \ - ((((tcl) >> 4) & TID) >> 4) -#define TCL_LUN(tcl) \ - (tcl & (AHD_NUM_LUNS_NONPKT - 1)) -#define BUILD_TCL(scsiid, lun) \ - ((lun) | (((scsiid) & TID) << 4)) -#define BUILD_TCL_RAW(target, channel, lun) \ - ((lun) | ((target) << 8)) - -#define SCB_GET_TAG(scb) \ - ahd_le16toh(scb->hscb->tag) - -#ifndef AHD_TARGET_MODE -#undef AHD_TMODE_ENABLE -#define AHD_TMODE_ENABLE 0 -#endif - -/**************************** Driver Constants ********************************/ -/* - * The maximum number of supported targets. - */ -#define AHD_NUM_TARGETS 16 - -/* - * The maximum number of supported luns. - * The identify message only supports 64 luns in non-packetized transfers. - * You can have 2^64 luns when information unit transfers are enabled, - * but until we see a need to support that many, we support 256. - */ -#define AHD_NUM_LUNS_NONPKT 64 -#define AHD_NUM_LUNS 256 - -/* - * The maximum transfer per S/G segment. - */ -#define AHD_MAXTRANSFER_SIZE 0x00ffffff /* limited by 24bit counter */ - -/* - * The maximum amount of SCB storage in hardware on a controller. - * This value represents an upper bound. Due to software design, - * we may not be able to use this number. - */ -#define AHD_SCB_MAX 512 - -/* - * The maximum number of concurrent transactions supported per driver instance. - * Sequencer Control Blocks (SCBs) store per-transaction information. - * We are limited to 510 because: - * 1) SCB storage space holds us to at most 512. - * 2) Our input queue scheme requires one SCB to always be reserved - * in advance of queuing any SCBs. This takes us down to 511. - * 3) To handle our output queue correctly on machines that only - * support 32bit stores, we must clear the array 4 bytes at a - * time. To avoid colliding with a DMA write from the sequencer, - * we must be sure that 2, 16bit slots are empty when we write to - * clear the queue. This restricts us to only 511 SCBs: 1 that - * just completed and the known additional empty slot in the queue - * that precedes it. -#define AHD_MAX_QUEUE 510 - */ -#define AHD_MAX_QUEUE 255 - -/* - * Define the size of our QIN and QOUT FIFOs. They must be a power of 2 - * in size and accomodate as many transactions as can be queued concurrently. - */ -#define AHD_QIN_SIZE 512 -#define AHD_QOUT_SIZE 512 - -#define AHD_QIN_WRAP(x) ((x) & (AHD_QIN_SIZE-1)) -#define AHD_QOUT_WRAP(x) ((x) & (AHD_QOUT_SIZE-1)) - -/* - * The maximum amount of SCB storage we allocate in host memory. This - * number should reflect the 1 additional SCB we require to handle our - * qinfifo mechanism. - */ -#define AHD_SCB_MAX_ALLOC (AHD_MAX_QUEUE+1) - -/* - * Ring Buffer of incoming target commands. - * We allocate 256 to simplify the logic in the sequencer - * by using the natural wrap point of an 8bit counter. - */ -#define AHD_TMODE_CMDS 256 - -/* Reset line assertion time in us */ -#define AHD_BUSRESET_DELAY 250 - -/******************* Chip Characteristics/Operating Settings *****************/ -/* - * Chip Type - * The chip order is from least sophisticated to most sophisticated. - */ -typedef enum { - AHD_NONE = 0x0000, - AHD_CHIPID_MASK = 0x00FF, - AHD_AIC7901 = 0x0001, - AHD_AIC7902 = 0x0002, - AHD_PCI = 0x0100, /* Bus type PCI */ - AHD_PCIX = 0x0200, /* Bus type PCIX */ - AHD_BUS_MASK = 0x0F00 -} ahd_chip; - -/* - * Features available in each chip type. - */ -typedef enum { - AHD_FENONE = 0x00000, - AHD_WIDE = 0x00001, /* Wide Channel */ - AHD_MULTI_FUNC = 0x00100, /* Multi-Function Twin Channel Device */ - AHD_TARGETMODE = 0x01000, /* Has tested target mode support */ - AHD_MULTIROLE = 0x02000, /* Space for two roles at a time */ - AHD_REMOVABLE = 0x00000, /* Hot-Swap supported - None so far*/ - AHD_AIC7901_FE = AHD_FENONE, - AHD_AIC7902_FE = AHD_MULTI_FUNC -} ahd_feature; - -/* - * Bugs in the silicon that we work around in software. - */ -typedef enum { - AHD_BUGNONE = 0x0000, - AHD_SENT_SCB_UPDATE_BUG = 0x0001, - AHD_ABORT_LQI_BUG = 0x0002, - AHD_PKT_BITBUCKET_BUG = 0x0004, - AHD_LONG_SETIMO_BUG = 0x0008, - AHD_NLQICRC_DELAYED_BUG = 0x0010, - AHD_SCSIRST_BUG = 0x0020, - AHD_PCIX_ARBITER_BUG = 0x0040, - AHD_PCIX_SPLIT_BUG = 0x0080, - AHD_PCIX_CHIPRST_BUG = 0x0100, - AHD_PCIX_MMAPIO_BUG = 0x0200, - /* Bug workarounds that can be disabled on non-PCIX busses. */ - AHD_PCIX_BUG_MASK = AHD_PCIX_ARBITER_BUG - | AHD_PCIX_SPLIT_BUG - | AHD_PCIX_CHIPRST_BUG - | AHD_PCIX_MMAPIO_BUG, - AHD_LQO_ATNO_BUG = 0x0400, - AHD_AUTOFLUSH_BUG = 0x0800, - AHD_CLRLQO_AUTOCLR_BUG = 0x1000, - AHD_PKTIZED_STATUS_BUG = 0x2000 -} ahd_bug; - -/* - * Configuration specific settings. - * The driver determines these settings by probing the - * chip/controller's configuration. - */ -typedef enum { - AHD_FNONE = 0x00000, - AHD_PRIMARY_CHANNEL = 0x00003,/* - * The channel that should - * be probed first. - */ - AHD_USEDEFAULTS = 0x00004,/* - * For cards without an seeprom - * or a BIOS to initialize the chip's - * SRAM, we use the default target - * settings. - */ - AHD_SEQUENCER_DEBUG = 0x00008, - AHD_RESET_BUS_A = 0x00010, - AHD_EXTENDED_TRANS_A = 0x00020, - AHD_TERM_ENB_A = 0x00040, - AHD_SPCHK_ENB_A = 0x00080, - AHD_STPWLEVEL_A = 0x00100, - AHD_INITIATORROLE = 0x00200,/* - * Allow initiator operations on - * this controller. - */ - AHD_TARGETROLE = 0x00400,/* - * Allow target operations on this - * controller. - */ - AHD_RESOURCE_SHORTAGE = 0x00800, - AHD_TQINFIFO_BLOCKED = 0x01000,/* Blocked waiting for ATIOs */ - AHD_INT50_SPEEDFLEX = 0x02000,/* - * Internal 50pin connector - * sits behind an aic3860 - */ - AHD_BIOS_ENABLED = 0x04000, - AHD_ALL_INTERRUPTS = 0x08000, - AHD_39BIT_ADDRESSING = 0x10000,/* Use 39 bit addressing scheme. */ - AHD_64BIT_ADDRESSING = 0x20000,/* Use 64 bit addressing scheme. */ - AHD_CURRENT_SENSING = 0x40000, - AHD_SCB_CONFIG_USED = 0x80000,/* No SEEPROM but SCB had info. */ - AHD_CPQ_BOARD = 0x100000 -} ahd_flag; - -/************************* Hardware SCB Definition ***************************/ - -/* - * The driver keeps up to MAX_SCB scb structures per card in memory. The SCB - * consists of a "hardware SCB" mirroring the fields availible on the card - * and additional information the kernel stores for each transaction. - * - * To minimize space utilization, a portion of the hardware scb stores - * different data during different portions of a SCSI transaction. - * As initialized by the host driver for the initiator role, this area - * contains the SCSI cdb (or a pointer to the cdb) to be executed. After - * the cdb has been presented to the target, this area serves to store - * residual transfer information and the SCSI status byte. - * For the target role, the contents of this area do not change, but - * still serve a different purpose than for the initiator role. See - * struct target_data for details. - */ - -/* - * Status information embedded in the shared poriton of - * an SCB after passing the cdb to the target. The kernel - * driver will only read this data for transactions that - * complete abnormally. - */ -struct initiator_status { - uint32_t residual_datacnt; /* Residual in the current S/G seg */ - uint32_t residual_sgptr; /* The next S/G for this transfer */ - uint8_t scsi_status; /* Standard SCSI status byte */ -}; - -struct target_status { - uint32_t residual_datacnt; /* Residual in the current S/G seg */ - uint32_t residual_sgptr; /* The next S/G for this transfer */ - uint8_t scsi_status; /* SCSI status to give to initiator */ - uint8_t target_phases; /* Bitmap of phases to execute */ - uint8_t data_phase; /* Data-In or Data-Out */ - uint8_t initiator_tag; /* Initiator's transaction tag */ -}; - -/* - * Initiator mode SCB shared data area. - * If the embedded CDB is 12 bytes or less, we embed - * the sense buffer address in the SCB. This allows - * us to retrieve sense information without interupting - * the host in packetized mode. - */ -typedef uint32_t sense_addr_t; -#define MAX_CDB_LEN 16 -#define MAX_CDB_LEN_WITH_SENSE_ADDR (MAX_CDB_LEN - sizeof(sense_addr_t)) -union initiator_data { - uint64_t cdbptr; - uint8_t cdb[MAX_CDB_LEN]; - struct { - uint8_t cdb[MAX_CDB_LEN_WITH_SENSE_ADDR]; - sense_addr_t sense_addr; - } cdb_plus_saddr; -}; - -/* - * Target mode version of the shared data SCB segment. - */ -struct target_data { - uint32_t spare[2]; - uint8_t scsi_status; /* SCSI status to give to initiator */ - uint8_t target_phases; /* Bitmap of phases to execute */ - uint8_t data_phase; /* Data-In or Data-Out */ - uint8_t initiator_tag; /* Initiator's transaction tag */ -}; - -struct hardware_scb { -/*0*/ union { - union initiator_data idata; - struct target_data tdata; - struct initiator_status istatus; - struct target_status tstatus; - } shared_data; -/* - * A word about residuals. - * The scb is presented to the sequencer with the dataptr and datacnt - * fields initialized to the contents of the first S/G element to - * transfer. The sgptr field is initialized to the bus address for - * the S/G element that follows the first in the in core S/G array - * or'ed with the SG_FULL_RESID flag. Sgptr may point to an invalid - * S/G entry for this transfer (single S/G element transfer with the - * first elements address and length preloaded in the dataptr/datacnt - * fields). If no transfer is to occur, sgptr is set to SG_LIST_NULL. - * The SG_FULL_RESID flag ensures that the residual will be correctly - * noted even if no data transfers occur. Once the data phase is entered, - * the residual sgptr and datacnt are loaded from the sgptr and the - * datacnt fields. After each S/G element's dataptr and length are - * loaded into the hardware, the residual sgptr is advanced. After - * each S/G element is expired, its datacnt field is checked to see - * if the LAST_SEG flag is set. If so, SG_LIST_NULL is set in the - * residual sg ptr and the transfer is considered complete. If the - * sequencer determines that there is a residual in the tranfer, or - * there is non-zero status, it will set the SG_STATUS_VALID flag in - * sgptr and dma the scb back into host memory. To sumarize: - * - * Sequencer: - * o A residual has occurred if SG_FULL_RESID is set in sgptr, - * or residual_sgptr does not have SG_LIST_NULL set. - * - * o We are transfering the last segment if residual_datacnt has - * the SG_LAST_SEG flag set. - * - * Host: - * o A residual can only have occurred if a completed scb has the - * SG_STATUS_VALID flag set. Inspection of the SCSI status field, - * the residual_datacnt, and the residual_sgptr field will tell - * for sure. - * - * o residual_sgptr and sgptr refer to the "next" sg entry - * and so may point beyond the last valid sg entry for the - * transfer. - */ -#define SG_PTR_MASK 0xFFFFFFF8 -/*16*/ uint8_t cdb_len; -/*17*/ uint8_t task_management; -/*18*/ uint16_t tag; -/*20*/ uint32_t next_hscb_busaddr; -/*24*/ uint64_t dataptr; -/*32*/ uint32_t datacnt; /* Byte 3 is spare. */ -/*36*/ uint32_t sgptr; -/*40*/ uint8_t control; /* See SCB_CONTROL in aic79xx.reg for details */ -/*41*/ uint8_t scsiid; /* - * Selection out Id - * Our Id (bits 0-3) Their ID (bits 4-7) - */ -/*42*/ uint8_t lun; -/*43*/ uint8_t task_attribute_nonpkt_tag; -/*44*/ uint32_t hscb_busaddr; -/******* Fields below are not Downloaded (Sequencer may use for scratch) ******/ -/*48*/ uint8_t spare[16]; -}; - -/************************ Kernel SCB Definitions ******************************/ -/* - * Some fields of the SCB are OS dependent. Here we collect the - * definitions for elements that all OS platforms need to include - * in there SCB definition. - */ - -/* - * Definition of a scatter/gather element as transfered to the controller. - * The aic7xxx chips only support a 24bit length. We use the top byte of - * the length to store additional address bits and a flag to indicate - * that a given segment terminates the transfer. This gives us an - * addressable range of 512GB on machines with 64bit PCI or with chips - * that can support dual address cycles on 32bit PCI busses. - */ -struct ahd_dma_seg { - uint32_t addr; - uint32_t len; -#define AHD_DMA_LAST_SEG 0x80000000 -#define AHD_SG_HIGH_ADDR_MASK 0x7F000000 -#define AHD_SG_LEN_MASK 0x00FFFFFF -}; - -struct ahd_dma64_seg { - uint64_t addr; - uint32_t len; - uint32_t pad; -}; - -struct map_node { - bus_dmamap_t dmamap; - bus_addr_t physaddr; - uint8_t *vaddr; - SLIST_ENTRY(map_node) links; -}; - -/* - * The current state of this SCB. - */ -typedef enum { - SCB_FREE = 0x0000, - SCB_TRANSMISSION_ERROR = 0x0001,/* - * We detected a parity or CRC - * error that has effected the - * payload of the command. This - * flag is checked when normal - * status is returned to catch - * the case of a target not - * responding to our attempt - * to report the error. - */ - SCB_OTHERTCL_TIMEOUT = 0x0002,/* - * Another device was active - * during the first timeout for - * this SCB so we gave ourselves - * an additional timeout period - * in case it was hogging the - * bus. - */ - SCB_DEVICE_RESET = 0x0004, - SCB_SENSE = 0x0008, - SCB_CDB32_PTR = 0x0010, - SCB_RECOVERY_SCB = 0x0020, - SCB_AUTO_NEGOTIATE = 0x0040,/* Negotiate to achieve goal. */ - SCB_NEGOTIATE = 0x0080,/* Negotiation forced for command. */ - SCB_ABORT = 0x0100, - SCB_UNTAGGEDQ = 0x0200, - SCB_ACTIVE = 0x0400, - SCB_TARGET_IMMEDIATE = 0x0800, - SCB_PACKETIZED = 0x1000, - SCB_EXPECT_PPR_BUSFREE = 0x2000, - SCB_PKT_SENSE = 0x4000, - SCB_CMDPHASE_ABORT = 0x8000 -} scb_flag; - -struct scb { - struct hardware_scb *hscb; - union { - SLIST_ENTRY(scb) sle; - TAILQ_ENTRY(scb) tqe; - } links; - LIST_ENTRY(scb) pending_links; - ahd_io_ctx_t io_ctx; - struct ahd_softc *ahd_softc; - scb_flag flags; -#ifndef __linux__ - bus_dmamap_t dmamap; -#endif - struct scb_platform_data *platform_data; - struct map_node *hscb_map; - struct map_node *sg_map; - struct map_node *sense_map; - void *sg_list; - uint8_t *sense_data; - bus_addr_t sg_list_busaddr; - bus_addr_t sense_busaddr; - u_int sg_count;/* How full ahd_dma_seg is */ -}; - -struct scb_data { - SLIST_HEAD(, scb) free_scbs; /* - * Pool of SCBs ready to be assigned - * commands to execute. - */ - struct scb *scbindex[AHD_SCB_MAX]; - /* - * Mapping from tag to SCB. - */ - /* - * "Bus" addresses of our data structures. - */ - bus_dma_tag_t hscb_dmat; /* dmat for our hardware SCB array */ - bus_dma_tag_t sg_dmat; /* dmat for our sg segments */ - bus_dma_tag_t sense_dmat; /* dmat for our sense buffers */ - SLIST_HEAD(, map_node) hscb_maps; - SLIST_HEAD(, map_node) sg_maps; - SLIST_HEAD(, map_node) sense_maps; - int scbs_left; /* unallocated scbs in head map_node */ - int sgs_left; /* unallocated sgs in head map_node */ - int sense_left; /* unallocated sense in head map_node */ - uint16_t numscbs; - uint16_t maxhscbs; /* Number of SCBs on the card */ - uint8_t init_level; /* - * How far we've initialized - * this structure. - */ -}; - -/************************ Target Mode Definitions *****************************/ - -/* - * Connection desciptor for select-in requests in target mode. - */ -struct target_cmd { - uint8_t scsiid; /* Our ID and the initiator's ID */ - uint8_t identify; /* Identify message */ - uint8_t bytes[22]; /* - * Bytes contains any additional message - * bytes terminated by 0xFF. The remainder - * is the cdb to execute. - */ - uint8_t cmd_valid; /* - * When a command is complete, the firmware - * will set cmd_valid to all bits set. - * After the host has seen the command, - * the bits are cleared. This allows us - * to just peek at host memory to determine - * if more work is complete. cmd_valid is on - * an 8 byte boundary to simplify setting - * it on aic7880 hardware which only has - * limited direct access to the DMA FIFO. - */ - uint8_t pad[7]; -}; - -/* - * Number of events we can buffer up if we run out - * of immediate notify ccbs. - */ -#define AHD_TMODE_EVENT_BUFFER_SIZE 8 -struct ahd_tmode_event { - uint8_t initiator_id; - uint8_t event_type; /* MSG type or EVENT_TYPE_BUS_RESET */ -#define EVENT_TYPE_BUS_RESET 0xFF - uint8_t event_arg; -}; - -/* - * Per enabled lun target mode state. - * As this state is directly influenced by the host OS'es target mode - * environment, we let the OS module define it. Forward declare the - * structure here so we can store arrays of them, etc. in OS neutral - * data structures. - */ -#ifdef AHD_TARGET_MODE -struct ahd_tmode_lstate { - struct cam_path *path; - struct ccb_hdr_slist accept_tios; - struct ccb_hdr_slist immed_notifies; - struct ahd_tmode_event event_buffer[AHD_TMODE_EVENT_BUFFER_SIZE]; - uint8_t event_r_idx; - uint8_t event_w_idx; -}; -#else -struct ahd_tmode_lstate; -#endif - -/******************** Transfer Negotiation Datastructures *********************/ -#define AHD_TRANS_CUR 0x01 /* Modify current neogtiation status */ -#define AHD_TRANS_ACTIVE 0x03 /* Assume this target is on the bus */ -#define AHD_TRANS_GOAL 0x04 /* Modify negotiation goal */ -#define AHD_TRANS_USER 0x08 /* Modify user negotiation settings */ -#define AHD_PERIOD_ASYNC 0xFF -#define AHD_PERIOD_10MHz 0x19 - -/* - * Transfer Negotiation Information. - */ -struct ahd_transinfo { - uint8_t protocol_version; /* SCSI Revision level */ - uint8_t transport_version; /* SPI Revision level */ - uint8_t width; /* Bus width */ - uint8_t period; /* Sync rate factor */ - uint8_t offset; /* Sync offset */ - uint8_t ppr_options; /* Parallel Protocol Request options */ -}; - -/* - * Per-initiator current, goal and user transfer negotiation information. */ -struct ahd_initiator_tinfo { - struct ahd_transinfo curr; - struct ahd_transinfo goal; - struct ahd_transinfo user; -}; - -/* - * Per enabled target ID state. - * Pointers to lun target state as well as sync/wide negotiation information - * for each initiator<->target mapping. For the initiator role we pretend - * that we are the target and the targets are the initiators since the - * negotiation is the same regardless of role. - */ -struct ahd_tmode_tstate { - struct ahd_tmode_lstate* enabled_luns[AHD_NUM_LUNS]; - struct ahd_initiator_tinfo transinfo[AHD_NUM_TARGETS]; - - /* - * Per initiator state bitmasks. - */ - uint16_t auto_negotiate;/* Auto Negotiation Required */ - uint16_t discenable; /* Disconnection allowed */ - uint16_t tagenable; /* Tagged Queuing allowed */ -}; - -/* - * Points of interest along the negotiated transfer scale. - */ -#define AHD_SYNCRATE_MAX 0x8 -#define AHD_SYNCRATE_160 0x8 -#define AHD_SYNCRATE_PACED 0x8 -#define AHD_SYNCRATE_DT 0x9 -#define AHD_SYNCRATE_ULTRA2 0xa -#define AHD_SYNCRATE_ULTRA 0xc -#define AHD_SYNCRATE_FAST 0x19 -#define AHD_SYNCRATE_MIN_DT AHD_SYNCRATE_FAST -#define AHD_SYNCRATE_SYNC 0x32 -#define AHD_SYNCRATE_MIN 0x60 -#define AHD_SYNCRATE_ASYNC 0xFF - -/* - * In RevA, the synctable uses a 120MHz rate for the period - * factor 8 and 160MHz for the period factor 7. The 120MHz - * rate never made it into the official SCSI spec, so we must - * compensate when setting the negotiation table for Rev A - * parts. - */ -#define AHD_SYNCRATE_REVA_120 0x8 -#define AHD_SYNCRATE_REVA_160 0x7 - -/***************************** Lookup Tables **********************************/ -/* - * Phase -> name and message out response - * to parity errors in each phase table. - */ -struct ahd_phase_table_entry { - uint8_t phase; - uint8_t mesg_out; /* Message response to parity errors */ - char *phasemsg; -}; - -/************************** Serial EEPROM Format ******************************/ - -struct seeprom_config { -/* - * Per SCSI ID Configuration Flags - */ - uint16_t device_flags[16]; /* words 0-15 */ -#define CFXFER 0x003F /* synchronous transfer rate */ -#define CFXFER_ASYNC 0x3F -#define CFQAS 0x0040 /* Negotiate QAS */ -#define CFPACKETIZED 0x0080 /* Negotiate Packetized Transfers */ -#define CFSTART 0x0100 /* send start unit SCSI command */ -#define CFINCBIOS 0x0200 /* include in BIOS scan */ -#define CFDISC 0x0400 /* enable disconnection */ -#define CFMULTILUNDEV 0x0800 /* Probe multiple luns in BIOS scan */ -#define CFWIDEB 0x1000 /* wide bus device */ -#define CFHOSTMANAGED 0x8000 /* Managed by a RAID controller */ - -/* - * BIOS Control Bits - */ - uint16_t bios_control; /* word 16 */ -#define CFSUPREM 0x0001 /* support all removeable drives */ -#define CFSUPREMB 0x0002 /* support removeable boot drives */ -#define CFBIOSSTATE 0x000C /* BIOS Action State */ -#define CFBS_DISABLED 0x00 -#define CFBS_ENABLED 0x04 -#define CFBS_DISABLED_SCAN 0x08 -#define CFENABLEDV 0x0010 /* Perform Domain Validation */ -#define CFCTRL_A 0x0020 /* BIOS displays Ctrl-A message */ -#define CFSPARITY 0x0040 /* SCSI parity */ -#define CFEXTEND 0x0080 /* extended translation enabled */ -#define CFBOOTCD 0x0100 /* Support Bootable CD-ROM */ -#define CFMSG_LEVEL 0x0600 /* BIOS Message Level */ -#define CFMSG_VERBOSE 0x0000 -#define CFMSG_SILENT 0x0200 -#define CFMSG_DIAG 0x0400 -#define CFRESETB 0x0800 /* reset SCSI bus at boot */ -/* UNUSED 0xf000 */ - -/* - * Host Adapter Control Bits - */ - uint16_t adapter_control; /* word 17 */ -#define CFAUTOTERM 0x0001 /* Perform Auto termination */ -#define CFSTERM 0x0002 /* SCSI low byte termination */ -#define CFWSTERM 0x0004 /* SCSI high byte termination */ -#define CFSEAUTOTERM 0x0008 /* Ultra2 Perform secondary Auto Term*/ -#define CFSELOWTERM 0x0010 /* Ultra2 secondary low term */ -#define CFSEHIGHTERM 0x0020 /* Ultra2 secondary high term */ -#define CFSTPWLEVEL 0x0040 /* Termination level control */ -#define CFBIOSAUTOTERM 0x0080 /* Perform Auto termination */ -#define CFTERM_MENU 0x0100 /* BIOS displays termination menu */ -#define CFCLUSTERENB 0x8000 /* Cluster Enable */ - -/* - * Bus Release Time, Host Adapter ID - */ - uint16_t brtime_id; /* word 18 */ -#define CFSCSIID 0x000f /* host adapter SCSI ID */ -/* UNUSED 0x00f0 */ -#define CFBRTIME 0xff00 /* bus release time/PCI Latency Time */ - -/* - * Maximum targets - */ - uint16_t max_targets; /* word 19 */ -#define CFMAXTARG 0x00ff /* maximum targets */ -#define CFBOOTLUN 0x0f00 /* Lun to boot from */ -#define CFBOOTID 0xf000 /* Target to boot from */ - uint16_t res_1[10]; /* words 20-29 */ - uint16_t signature; /* BIOS Signature */ -#define CFSIGNATURE 0x400 - uint16_t checksum; /* word 31 */ -}; - -/****************************** Flexport Logic ********************************/ -#define FLXADDR_TERMCTL 0x0 -#define FLX_TERMCTL_ENSECHIGH 0x8 -#define FLX_TERMCTL_ENSECLOW 0x4 -#define FLX_TERMCTL_ENPRIHIGH 0x2 -#define FLX_TERMCTL_ENPRILOW 0x1 -#define FLXADDR_ROMSTAT_CURSENSECTL 0x1 -#define FLX_ROMSTAT_SEECFG 0xF0 -#define FLX_ROMSTAT_EECFG 0x0F -#define FLX_ROMSTAT_SEE_93C66 0x00 -#define FLX_ROMSTAT_SEE_NONE 0xF0 -#define FLX_ROMSTAT_EE_512x8 0x0 -#define FLX_ROMSTAT_EE_1MBx8 0x1 -#define FLX_ROMSTAT_EE_2MBx8 0x2 -#define FLX_ROMSTAT_EE_4MBx8 0x3 -#define FLX_ROMSTAT_EE_16MBx8 0x4 -#define CURSENSE_ENB 0x1 -#define FLXADDR_FLEXSTAT 0x2 -#define FLX_FSTAT_BUSY 0x1 -#define FLXADDR_CURRENT_STAT 0x4 -#define FLX_CSTAT_SEC_HIGH 0xC0 -#define FLX_CSTAT_SEC_LOW 0x30 -#define FLX_CSTAT_PRI_HIGH 0x0C -#define FLX_CSTAT_PRI_LOW 0x03 -#define FLX_CSTAT_MASK 0x03 -#define FLX_CSTAT_SHIFT 2 -#define FLX_CSTAT_OKAY 0x0 -#define FLX_CSTAT_OVER 0x1 -#define FLX_CSTAT_UNDER 0x2 -#define FLX_CSTAT_INVALID 0x3 - -int ahd_read_seeprom(struct ahd_softc *ahd, uint16_t *buf, - u_int start_addr, u_int count); - -int ahd_write_seeprom(struct ahd_softc *ahd, uint16_t *buf, - u_int start_addr, u_int count); -int ahd_wait_seeprom(struct ahd_softc *ahd); -int ahd_verify_cksum(struct seeprom_config *sc); -int ahd_acquire_seeprom(struct ahd_softc *ahd); -void ahd_release_seeprom(struct ahd_softc *ahd); - -/**************************** Message Buffer *********************************/ -typedef enum { - MSG_FLAG_NONE = 0x00, - MSG_FLAG_EXPECT_PPR_BUSFREE = 0x01, - MSG_FLAG_IU_REQ_CHANGED = 0x02, - MSG_FLAG_EXPECT_IDE_BUSFREE = 0x04, - MSG_FLAG_PACKETIZED = 0x08 -} ahd_msg_flags; - -typedef enum { - MSG_TYPE_NONE = 0x00, - MSG_TYPE_INITIATOR_MSGOUT = 0x01, - MSG_TYPE_INITIATOR_MSGIN = 0x02, - MSG_TYPE_TARGET_MSGOUT = 0x03, - MSG_TYPE_TARGET_MSGIN = 0x04 -} ahd_msg_type; - -typedef enum { - MSGLOOP_IN_PROG, - MSGLOOP_MSGCOMPLETE, - MSGLOOP_TERMINATED -} msg_loop_stat; - -/*********************** Software Configuration Structure *********************/ -TAILQ_HEAD(scb_tailq, scb); - -struct ahd_suspend_channel_state { - uint8_t scsiseq; - uint8_t sxfrctl0; - uint8_t sxfrctl1; - uint8_t simode0; - uint8_t simode1; - uint8_t seltimer; - uint8_t seqctl; -}; - -struct ahd_suspend_state { - struct ahd_suspend_channel_state channel[2]; - uint8_t optionmode; - uint8_t dscommand0; - uint8_t dspcistatus; - /* hsmailbox */ - uint8_t crccontrol1; - uint8_t scbbaddr; - /* Host and sequencer SCB counts */ - uint8_t dff_thrsh; - uint8_t *scratch_ram; - uint8_t *btt; -}; - -typedef void (*ahd_bus_intr_t)(struct ahd_softc *); - -typedef enum { - AHD_MODE_DFF0, - AHD_MODE_DFF1, - AHD_MODE_CCHAN, - AHD_MODE_SCSI, - AHD_MODE_CFG, - AHD_MODE_UNKNOWN -} ahd_mode; - -#define AHD_MK_MSK(x) (0x01 << (x)) -#define AHD_MODE_DFF0_MSK AHD_MK_MSK(AHD_MODE_DFF0) -#define AHD_MODE_DFF1_MSK AHD_MK_MSK(AHD_MODE_DFF1) -#define AHD_MODE_CCHAN_MSK AHD_MK_MSK(AHD_MODE_CCHAN) -#define AHD_MODE_SCSI_MSK AHD_MK_MSK(AHD_MODE_SCSI) -#define AHD_MODE_CFG_MSK AHD_MK_MSK(AHD_MODE_CFG) -#define AHD_MODE_UNKNOWN_MSK AHD_MK_MSK(AHD_MODE_UNKNOWN) -#define AHD_MODE_ANY_MSK (~0) - -typedef uint8_t ahd_mode_state; - -typedef void ahd_callback_t (void *); - -struct ahd_softc { - bus_space_tag_t tags[2]; - bus_space_handle_t bshs[2]; -#ifndef __linux__ - bus_dma_tag_t buffer_dmat; /* dmat for buffer I/O */ -#endif - struct scb_data scb_data; - - struct scb *next_queued_scb; - - /* - * SCBs that have been sent to the controller - */ - LIST_HEAD(, scb) pending_scbs; - - /* - * Current register window mode information. - */ - ahd_mode dst_mode; - ahd_mode src_mode; - - /* - * Saved register window mode information - * used for restore on next unpause. - */ - ahd_mode saved_dst_mode; - ahd_mode saved_src_mode; - - /* - * Counting lock for deferring the release of additional - * untagged transactions from the untagged_queues. When - * the lock is decremented to 0, all queues in the - * untagged_queues array are run. - */ - u_int untagged_queue_lock; - - /* - * Per-target queue of untagged-transactions. The - * transaction at the head of the queue is the - * currently pending untagged transaction for the - * target. The driver only allows a single untagged - * transaction per target. - */ - struct scb_tailq untagged_queues[AHD_NUM_TARGETS]; - - /* - * Platform specific data. - */ - struct ahd_platform_data *platform_data; - - /* - * Platform specific device information. - */ - ahd_dev_softc_t dev_softc; - - /* - * Bus specific device information. - */ - ahd_bus_intr_t bus_intr; - - /* - * Target mode related state kept on a per enabled lun basis. - * Targets that are not enabled will have null entries. - * As an initiator, we keep one target entry for our initiator - * ID to store our sync/wide transfer settings. - */ - struct ahd_tmode_tstate *enabled_targets[AHD_NUM_TARGETS]; - - /* - * The black hole device responsible for handling requests for - * disabled luns on enabled targets. - */ - struct ahd_tmode_lstate *black_hole; - - /* - * Device instance currently on the bus awaiting a continue TIO - * for a command that was not given the disconnect priveledge. - */ - struct ahd_tmode_lstate *pending_device; - - /* - * Timer handles for timer driven callbacks. - */ - ahd_timer_t reset_timer; - - /* - * Card characteristics - */ - ahd_chip chip; - ahd_feature features; - ahd_bug bugs; - ahd_flag flags; - struct seeprom_config *seep_config; - - /* Values to store in the SEQCTL register for pause and unpause */ - uint8_t unpause; - uint8_t pause; - - /* Command Queues */ - uint16_t qoutfifonext; - uint16_t qinfifonext; - uint16_t qinfifo[AHD_SCB_MAX]; - uint16_t *qoutfifo; - - /* Critical Section Data */ - struct cs *critical_sections; - u_int num_critical_sections; - - /* Buffer for handling packetized bitbucket. */ - uint8_t *overrun_buf; - - /* Links for chaining softcs */ - TAILQ_ENTRY(ahd_softc) links; - - /* Channel Names ('A', 'B', etc.) */ - char channel; - - /* Initiator Bus ID */ - uint8_t our_id; - - /* - * PCI error detection. - */ - int unsolicited_ints; - - /* - * Target incoming command FIFO. - */ - struct target_cmd *targetcmds; - uint8_t tqinfifonext; - - /* - * Incoming and outgoing message handling. - */ - uint8_t send_msg_perror; - ahd_msg_flags msg_flags; - ahd_msg_type msg_type; - uint8_t msgout_buf[12];/* Message we are sending */ - uint8_t msgin_buf[12];/* Message we are receiving */ - u_int msgout_len; /* Length of message to send */ - u_int msgout_index; /* Current index in msgout */ - u_int msgin_index; /* Current index in msgin */ - - /* - * Mapping information for data structures shared - * between the sequencer and kernel. - */ - bus_dma_tag_t parent_dmat; - bus_dma_tag_t shared_data_dmat; - bus_dmamap_t shared_data_dmamap; - bus_addr_t shared_data_busaddr; - - /* Information saved through suspend/resume cycles */ - struct ahd_suspend_state suspend_state; - - /* Number of enabled target mode device on this card */ - u_int enabled_luns; - - /* Initialization level of this data structure */ - u_int init_level; - - /* PCI cacheline size. */ - u_int pci_cachesize; - - /* Per-Unit descriptive information */ - const char *description; - const char *bus_description; - char *name; - int unit; - - /* Selection Timer settings */ - int seltime; - - uint16_t user_discenable;/* Disconnection allowed */ - uint16_t user_tagenable;/* Tagged Queuing allowed */ -}; - -TAILQ_HEAD(ahd_softc_tailq, ahd_softc); -extern struct ahd_softc_tailq ahd_tailq; - -/************************ Active Device Information ***************************/ -typedef enum { - ROLE_UNKNOWN, - ROLE_INITIATOR, - ROLE_TARGET -} role_t; - -struct ahd_devinfo { - int our_scsiid; - int target_offset; - uint16_t target_mask; - u_int target; - u_int lun; - char channel; - role_t role; /* - * Only guaranteed to be correct if not - * in the busfree state. - */ -}; - -/****************************** PCI Structures ********************************/ -#define AHD_PCI_IOADDR0 PCIR_MAPS /* I/O BAR*/ -#define AHD_PCI_MEMADDR (PCIR_MAPS + 4) /* Memory BAR */ -#define AHD_PCI_IOADDR1 (PCIR_MAPS + 12)/* Second I/O BAR */ - -typedef int (ahd_device_setup_t)(struct ahd_softc *); - -struct ahd_pci_identity { - uint64_t full_id; - uint64_t id_mask; - char *name; - ahd_device_setup_t *setup; -}; -extern struct ahd_pci_identity ahd_pci_ident_table []; -extern const u_int ahd_num_pci_devs; - -/***************************** VL/EISA Declarations ***************************/ -struct aic7770_identity { - uint32_t full_id; - uint32_t id_mask; - char *name; - ahd_device_setup_t *setup; -}; -extern struct aic7770_identity aic7770_ident_table []; -extern const int ahd_num_aic7770_devs; - -#define AHD_EISA_SLOT_OFFSET 0xc00 -#define AHD_EISA_IOSIZE 0x100 - -/*************************** Function Declarations ****************************/ -/******************************************************************************/ -u_int ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl); -void ahd_set_disconnected_list(struct ahd_softc *ahd, - u_int target, u_int lun, - u_int scbid); -void ahd_busy_tcl(struct ahd_softc *ahd, - u_int tcl, u_int busyid); -static __inline void ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl); -static __inline void -ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl) -{ - ahd_busy_tcl(ahd, tcl, SCB_LIST_NULL); -} - -/***************************** PCI Front End *********************************/ -struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t); -int ahd_pci_config(struct ahd_softc *, - struct ahd_pci_identity *); - -/*************************** EISA/VL Front End ********************************/ -struct aic7770_identity *aic7770_find_device(uint32_t); -int aic7770_config(struct ahd_softc *ahd, - struct aic7770_identity *); - -/************************** SCB and SCB queue management **********************/ -int ahd_probe_scbs(struct ahd_softc *); -void ahd_run_untagged_queues(struct ahd_softc *ahd); -void ahd_run_untagged_queue(struct ahd_softc *ahd, - struct scb_tailq *queue); -void ahd_qinfifo_requeue_tail(struct ahd_softc *ahd, - struct scb *scb); -int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, - int target, char channel, int lun, - u_int tag, role_t role); - -/****************************** Initialization ********************************/ -struct ahd_softc *ahd_alloc(void *platform_arg, char *name); -int ahd_softc_init(struct ahd_softc *); -void ahd_controller_info(struct ahd_softc *ahd, char *buf); -int ahd_init(struct ahd_softc *ahd); -int ahd_default_config(struct ahd_softc *ahd); -int ahd_parse_cfgdata(struct ahd_softc *ahd, - struct seeprom_config *sc); -void ahd_intr_enable(struct ahd_softc *ahd, int enable); -void ahd_pause_and_flushwork(struct ahd_softc *ahd); -int ahd_suspend(struct ahd_softc *ahd); -int ahd_resume(struct ahd_softc *ahd); -void ahd_softc_insert(struct ahd_softc *); -struct ahd_softc *ahd_find_softc(struct ahd_softc *ahd); -void ahd_set_unit(struct ahd_softc *, int); -void ahd_set_name(struct ahd_softc *, char *); -void ahd_alloc_scbs(struct ahd_softc *ahd); -void ahd_free(struct ahd_softc *ahd); -int ahd_reset(struct ahd_softc *ahd); -void ahd_shutdown(void *arg); -int ahd_write_flexport(struct ahd_softc *ahd, - u_int addr, u_int value); -int ahd_read_flexport(struct ahd_softc *ahd, u_int addr, - uint8_t *value); -int ahd_wait_flexport(struct ahd_softc *ahd); - -/*************************** Interrupt Services *******************************/ -void ahd_pci_intr(struct ahd_softc *ahd); -void ahd_clear_intstat(struct ahd_softc *ahd); -void ahd_run_qoutfifo(struct ahd_softc *ahd); -#ifdef AHD_TARGET_MODE -void ahd_run_tqinfifo(struct ahd_softc *ahd, int paused); -#endif -void ahd_handle_hwerrint(struct ahd_softc *ahd); -void ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat); -void ahd_handle_scsiint(struct ahd_softc *ahd, - u_int intstat); -void ahd_clear_critical_section(struct ahd_softc *ahd); - -/***************************** Error Recovery *********************************/ -typedef enum { - SEARCH_COMPLETE, - SEARCH_COUNT, - SEARCH_REMOVE, - SEARCH_PRINT -} ahd_search_action; -int ahd_search_qinfifo(struct ahd_softc *ahd, int target, - char channel, int lun, u_int tag, - role_t role, uint32_t status, - ahd_search_action action); -int ahd_search_disc_list(struct ahd_softc *ahd, int target, - char channel, int lun, u_int tag, - int stop_on_first, int remove, - int save_state); -void ahd_freeze_devq(struct ahd_softc *ahd, struct scb *scb); -int ahd_reset_channel(struct ahd_softc *ahd, char channel, - int initiate_reset); -int ahd_abort_scbs(struct ahd_softc *ahd, int target, - char channel, int lun, u_int tag, - role_t role, uint32_t status); -void ahd_restart(struct ahd_softc *ahd); -void ahd_clear_fifo(struct ahd_softc *ahd, u_int fifo); -void ahd_handle_scb_status(struct ahd_softc *ahd, - struct scb *scb); -void ahd_handle_scsi_status(struct ahd_softc *ahd, - struct scb *scb); -void ahd_calc_residual(struct ahd_softc *ahd, - struct scb *scb); -/*************************** Utility Functions ********************************/ -struct ahd_phase_table_entry* - ahd_lookup_phase_entry(int phase); -void ahd_compile_devinfo(struct ahd_devinfo *devinfo, - u_int our_id, u_int target, - u_int lun, char channel, - role_t role); -/************************** Transfer Negotiation ******************************/ -void ahd_find_syncrate(struct ahd_softc *ahd, u_int *period, - u_int *ppr_options, u_int maxsync); -void ahd_validate_offset(struct ahd_softc *ahd, - struct ahd_initiator_tinfo *tinfo, - u_int period, u_int *offset, - int wide, role_t role); -void ahd_validate_width(struct ahd_softc *ahd, - struct ahd_initiator_tinfo *tinfo, - u_int *bus_width, - role_t role); -int ahd_update_neg_request(struct ahd_softc*, - struct ahd_devinfo*, - struct ahd_tmode_tstate*, - struct ahd_initiator_tinfo*, - int /*force*/); -void ahd_set_width(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo, - u_int width, u_int type, int paused); -void ahd_set_syncrate(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo, - u_int period, u_int offset, - u_int ppr_options, - u_int type, int paused); -typedef enum { - AHD_QUEUE_NONE, - AHD_QUEUE_BASIC, - AHD_QUEUE_TAGGED -} ahd_queue_alg; - -void ahd_set_tags(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo, - ahd_queue_alg alg); - -/**************************** Target Mode *************************************/ -#ifdef AHD_TARGET_MODE -void ahd_send_lstate_events(struct ahd_softc *, - struct ahd_tmode_lstate *); -void ahd_handle_en_lun(struct ahd_softc *ahd, - struct cam_sim *sim, union ccb *ccb); -cam_status ahd_find_tmode_devs(struct ahd_softc *ahd, - struct cam_sim *sim, union ccb *ccb, - struct ahd_tmode_tstate **tstate, - struct ahd_tmode_lstate **lstate, - int notfound_failure); -#ifndef AHD_TMODE_ENABLE -#define AHD_TMODE_ENABLE 0 -#endif -#endif -/******************************* Debug ***************************************/ -#ifdef AHD_DEBUG -extern uint32_t ahd_debug; -#define AHD_SHOW_MISC 0x001 -#define AHD_SHOW_SENSE 0x002 -#define AHD_DUMP_SEEPROM 0x004 -#define AHD_SHOW_TERMCTL 0x008 -#define AHD_SHOW_MEMORY 0x010 -#define AHD_SHOW_MESSAGES 0x020 -#define AHD_SHOW_MODEPTR 0x040 -#define AHD_SHOW_SELTO 0x080 -#define AHD_SHOW_FIFOS 0x100 -#define AHD_SHOW_QFULL 0x200 -#define AHD_SHOW_QUEUE 0x400 -#define AHD_SHOW_TQIN 0x800 -#endif -void ahd_print_scb(struct scb *scb); -void ahd_dump_sglist(struct scb *scb); -void ahd_dump_all_cards_state(void); -void ahd_dump_card_state(struct ahd_softc *ahd); -void ahd_dump_scbs(struct ahd_softc *ahd); -#endif /* _AIC79XX_H_ */ diff --git a/xen/drivers/scsi/aic7xxx/aic79xx.reg b/xen/drivers/scsi/aic7xxx/aic79xx.reg deleted file mode 100644 index b681bd3ea3..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic79xx.reg +++ /dev/null @@ -1,3716 +0,0 @@ -/* - * Aic79xx register and scratch ram definitions. - * - * Copyright (c) 1994-2001 Justin T. Gibbs. - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $FreeBSD$ - */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#34 $" - -/* - * This file is processed by the aic7xxx_asm utility for use in assembling - * firmware for the aic79xx family of SCSI host adapters as well as to generate - * a C header file for use in the kernel portion of the Aic79xx driver. - */ - -/* Register window Modes */ -#define M_DFF0 0 -#define M_DFF1 1 -#define M_CCHAN 2 -#define M_SCSI 3 -#define M_CFG 4 -#define M_DST_SHIFT 4 - -#define MK_MODE(src, dst) ((src) | ((dst) << M_DST_SHIFT)) -#define SET_MODE(src, dst) \ - SET_SRC_MODE src; \ - SET_DST_MODE dst; \ - mvi MK_MODE(src, dst) call set_mode_work_around - -/* - * Mode Pointer - * Controls which of the 5, 512byte, address spaces should be used - * as the source and destination of any register accesses in our - * register window. - */ -register MODE_PTR { - address 0x000 - access_mode RW - mask DST_MODE 0x70 - mask SRC_MODE 0x07 - mode_pointer -} - -const SRC_MODE_SHIFT 0 -const DST_MODE_SHIFT 4 - -/* - * Host Interrupt Status - */ -register INTSTAT { - address 0x001 - access_mode RW - bit HWERRINT 0x80 - bit BRKADRINT 0x40 - bit SWTMINT 0x20 - bit PCIINT 0x10 - bit SCSIINT 0x08 - bit SEQINT 0x04 - bit CMDCMPLT 0x02 - bit SPLTINT 0x01 - mask INT_PEND 0xFF -} - -/* - * Sequencer Interrupt Code - */ -register SEQINTCODE { - address 0x002 - access_mode RW - mask BAD_PHASE 1 /* unknown scsi bus phase */ - mask SEND_REJECT 2 /* sending a message reject */ - mask PROTO_VIOLATION 3 /* Protocol Violation */ - mask NO_MATCH 4 /* no cmd match for reconnect */ - mask IGN_WIDE_RES 5 /* Complex IGN Wide Res Msg */ - mask PDATA_REINIT 6 /* - * Returned to data phase - * that requires data - * transfer pointers to be - * recalculated from the - * transfer residual. - */ - mask HOST_MSG_LOOP 7 /* - * The bus is ready for the - * host to perform another - * message transaction. This - * mechanism is used for things - * like sync/wide negotiation - * that require a kernel based - * message state engine. - */ - mask BAD_STATUS 8 /* Bad status from target */ - mask DATA_OVERRUN 9 /* - * Target attempted to write - * beyond the bounds of its - * command. - */ - mask MKMSG_FAILED 10 /* - * Target completed command - * without honoring our ATN - * request to issue a message. - */ - mask MISSED_BUSFREE 11 /* - * The sequencer never saw - * the bus go free after - * either a command complete - * or disconnect message. - */ - mask SCB_MISMATCH 12 /* - * Downloaded SCB's tag does - * not match the entry we - * intended to download. - */ - mask NO_FREE_SCB 13 /* - * get_free_or_disc_scb failed. - */ - mask OUT_OF_RANGE 14 - mask NO_FREE_FIFO 15 - mask DUMP_CARD_STATE 16 - mask ILLEGAL_PHASE 17 - mask INVALID_SEQINT 18 - mask CFG4ISTAT_INTR 19 - mask STATUS_OVERRUN 20 - mask CFG4OVERRUN 21 - mask SNAPSHOTCLRCHN 22 - mask MONITORDRAIN 23 - mask ENTERING_NONPACK 24 - mask PCIX_ARBITOR_WW 25 -} - -/* - * Clear Host Interrupt - */ -register CLRINT { - address 0x003 - access_mode WO - bit CLRBRKADRINT 0x40 - bit CLRSWTMINT 0x20 - bit CLRSCSIINT 0x08 - bit CLRSEQINT 0x04 - bit CLRCMDINT 0x02 - bit CLRSPLTINT 0x01 -} - -/* - * Error Register - */ -register ERROR { - address 0x004 - access_mode RO - bit CIOPARERR 0x80 - bit MPARERR 0x20 - bit DPARERR 0x10 - bit SQPARERR 0x08 - bit ILLOPCODE 0x04 - bit DSCTMOUT 0x02 -} - -/* - * Clear Error - */ -register CLRERR { - address 0x004 - access_mode WO - bit CLRCIOPARERR 0x80 - bit CLRMPARERR 0x20 - bit CLRDPARERR 0x10 - bit CLRSQPARERR 0x08 - bit CLRILLOPCODE 0x04 - bit CLRDSCTMOUT 0x02 -} - -/* - * Host Control Register - * Overall host control of the device. - */ -register HCNTRL { - address 0x005 - access_mode RW - bit POWRDN 0x40 - bit SWINT 0x10 - bit HCNTRL3 0x08 - bit PAUSE 0x04 - bit INTEN 0x02 - bit CHIPRST 0x01 - bit CHIPRSTACK 0x01 -} - -/* - * Host New SCB Queue Offset - */ -register HNSCB_QOFF { - address 0x006 - access_mode RW - size 2 -} - -/* - * Host Empty SCB Queue Offset - */ -register HESCB_QOFF { - address 0x008 - access_mode RW -} - -/* - * Host Mailbox - */ -register HS_MAILBOX { - address 0x0B - access_mode RW - mask HOST_TQINPOS 0x80 /* Boundary at either 0 or 128 */ -} - -/* - * Sequencer Interupt Status - */ -register SEQINTSTAT { - address 0x0C - access_mode RO - bit SEQ_SWTMRTO 0x10 - bit SEQ_SEQINT 0x08 - bit SEQ_SCSIINT 0x04 - bit SEQ_PCIINT 0x02 - bit SEQ_SPLTINT 0x01 -} - -/* - * Clear SEQ Interrupt - */ -register CLRSEQINTSTAT { - address 0x0C0 - access_mode WO - bit CLRSEQ_SWTMRTO 0x10 - bit CLRSEQ_SEQINT 0x08 - bit CLRSEQ_SCSIINT 0x04 - bit CLRSEQ_PCIINT 0x02 - bit CLRSEQ_SPLTINT 0x01 -} - -/* - * Software Timer - */ -register SWTIMER { - address 0x0E0 - access_mode RW - size 2 -} - -/* - * SEQ New SCB Queue Offset - */ -register SNSCB_QOFF { - address 0x010 - access_mode RW - size 2 - modes M_CCHAN -} - -/* - * SEQ Empty SCB Queue Offset - */ -register SESCB_QOFF { - address 0x012 - access_mode RW - modes M_CCHAN -} - -/* - * SEQ Done SCB Queue Offset - */ -register SDSCB_QOFF { - address 0x014 - access_mode RW - modes M_CCHAN - size 2 -} - -/* - * Queue Offset Control & Status - */ -register QOFF_CTLSTA { - address 0x016 - access_mode RW - modes M_CCHAN - bit EMPTY_SCB_AVAIL 0x80 - bit NEW_SCB_AVAIL 0x40 - bit SDSCB_ROLLOVR 0x20 - bit HS_MAILBOX_ACT 0x10 - mask SCB_QSIZE 0x0F - mask SCB_QSIZE_4 0x00 - mask SCB_QSIZE_8 0x01 - mask SCB_QSIZE_16 0x02 - mask SCB_QSIZE_32 0x03 - mask SCB_QSIZE_64 0x04 - mask SCB_QSIZE_128 0x05 - mask SCB_QSIZE_256 0x06 - mask SCB_QSIZE_512 0x07 - mask SCB_QSIZE_1024 0x08 - mask SCB_QSIZE_2048 0x09 - mask SCB_QSIZE_4096 0x0A - mask SCB_QSIZE_8192 0x0B - mask SCB_QSIZE_16384 0x0C -} - -/* - * Interrupt Control - */ -register INTCTL { - address 0x018 - access_mode RW - bit SWTMINTMASK 0x80 - bit SWTMINTEN 0x40 - bit SWTIMER_START 0x20 - bit AUTOCLRCMDINT 0x10 - bit PCIINTEN 0x08 - bit SCSIINTEN 0x04 - bit SEQINTEN 0x02 - bit SPLTINTEN 0x01 -} - -/* - * Data FIFO Control - */ -register DFCNTRL { - address 0x019 - access_mode RW - modes M_DFF0, M_DFF1 - bit PRELOADEN 0x80 - bit SCSIEN 0x20 - bit SCSIENACK 0x20 - bit HDMAEN 0x08 - bit HDMAENACK 0x08 - bit DIRECTION 0x04 - bit DIRECTIONACK 0x04 - bit FIFOFLUSH 0x02 - bit FIFOFLUSHACK 0x02 - bit DIRECTIONEN 0x01 -} - -/* - * Device Space Command 0 - */ -register DSCOMMAND0 { - address 0x019 - access_mode RW - modes M_CFG - bit CACHETHEN 0x80 /* Cache Threshold enable */ - bit DPARCKEN 0x40 /* Data Parity Check Enable */ - bit MPARCKEN 0x20 /* Memory Parity Check Enable */ - bit EXTREQLCK 0x10 /* External Request Lock */ - bit CIOPARCKEN 0x01 /* Internal bus parity error enable */ -} - -/* - * Data FIFO Status - */ -register DFSTATUS { - address 0x01A - access_mode RO - modes M_DFF0, M_DFF1 - bit PRELOAD_AVAIL 0x80 - bit PKT_PRELOAD_AVAIL 0x40 - bit MREQPEND 0x10 - bit HDONE 0x08 - bit DFTHRESH 0x04 - bit FIFOFULL 0x02 - bit FIFOEMP 0x01 -} - -/* - * S/G Cache Pointer - */ -register SG_CACHE_PRE { - address 0x01B - access_mode WO - modes M_DFF0, M_DFF1 - mask SG_ADDR_MASK 0xf8 - bit ODD_SEG 0x04 - bit LAST_SEG 0x02 -} - -register SG_CACHE_SHADOW { - address 0x01B - access_mode RO - modes M_DFF0, M_DFF1 - mask SG_ADDR_MASK 0xf8 - bit ODD_SEG 0x04 - bit LAST_SEG 0x02 - bit LAST_SEG_DONE 0x01 -} - -/* - * Arbiter Control - */ -register ARBCTL { - address 0x01B - access_mode RW - modes M_CFG - bit RESET_HARB 0x80 - bit RETRY_SWEN 0x08 - mask USE_TIME 0x07 -} - -/* - * Data Channel Host Address - */ -register HADDR { - address 0x070 - access_mode RW - size 8 - modes M_DFF0, M_DFF1 -} - -/* - * Host Overlay DMA Address - */ -register HODMAADR { - address 0x070 - access_mode RW - size 8 - modes M_SCSI -} - -/* - * Data Channel Host Count - */ -register HCNT { - address 0x078 - access_mode RW - size 3 - modes M_DFF0, M_DFF1 -} - -/* - * Host Overlay DMA Count - */ -register HODMACNT { - address 0x078 - access_mode RW - size 2 - modes M_SCSI -} - -/* - * Host Overlay DMA Enable - */ -register HODMAEN { - address 0x07A - access_mode RW - modes M_SCSI -} - -/* - * Scatter/Gather Host Address - */ -register SGHADDR { - address 0x07C - access_mode RW - size 8 - modes M_DFF0, M_DFF1 -} - -/* - * SCB Host Address - */ -register SCBHADDR { - address 0x07C - access_mode RW - size 8 - modes M_CCHAN -} - -/* - * Scatter/Gather Host Count - */ -register SGHCNT { - address 0x084 - access_mode RW - modes M_DFF0, M_DFF1 -} - -/* - * SCB Host Count - */ -register SCBHCNT { - address 0x084 - access_mode RW - modes M_CCHAN -} - -/* - * Data FIFO Threshold - */ -register DFF_THRSH { - address 0x088 - access_mode RW - modes M_CFG - mask WR_DFTHRSH 0x70 - mask RD_DFTHRSH 0x07 - mask RD_DFTHRSH_MIN 0x00 - mask RD_DFTHRSH_25 0x01 - mask RD_DFTHRSH_50 0x02 - mask RD_DFTHRSH_63 0x03 - mask RD_DFTHRSH_75 0x04 - mask RD_DFTHRSH_85 0x05 - mask RD_DFTHRSH_90 0x06 - mask RD_DFTHRSH_MAX 0x07 - mask WR_DFTHRSH_MIN 0x00 - mask WR_DFTHRSH_25 0x10 - mask WR_DFTHRSH_50 0x20 - mask WR_DFTHRSH_63 0x30 - mask WR_DFTHRSH_75 0x40 - mask WR_DFTHRSH_85 0x50 - mask WR_DFTHRSH_90 0x60 - mask WR_DFTHRSH_MAX 0x70 -} - -/* - * ROM Address - */ -register ROMADDR { - address 0x08A - access_mode RW - size 3 -} - -/* - * ROM Control - */ -register ROMCNTRL { - address 0x08D - access_mode RW - mask ROMOP 0xE0 - mask ROMSPD 0x18 - bit REPEAT 0x02 - bit RDY 0x01 -} - -/* - * ROM Data - */ -register ROMDATA { - address 0x08E - access_mode RW -} - -/* - * Data Channel Receive Message 0 - */ -register DCHRXMSG0 { - address 0x090 - access_mode RO - modes M_DFF0, M_DFF1 - mask CDNUM 0xF8 - mask CFNUM 0x07 -} - -/* - * CMC Recieve Message 0 - */ -register CMCRXMSG0 { - address 0x090 - access_mode RO - modes M_CCHAN - mask CDNUM 0xF8 - mask CFNUM 0x07 -} - -/* - * Overlay Recieve Message 0 - */ -register OVLYRXMSG0 { - address 0x090 - access_mode RO - modes M_SCSI - mask CDNUM 0xF8 - mask CFNUM 0x07 -} - -/* - * Relaxed Order Enable - */ -register ROENABLE { - address 0x090 - access_mode RW - modes M_CFG - bit MSIROEN 0x20 - bit OVLYROEN 0x10 - bit CMCROEN 0x08 - bit SGROEN 0x04 - bit DCH1ROEN 0x02 - bit DCH0ROEN 0x01 -} - -/* - * Data Channel Receive Message 1 - */ -register DCHRXMSG1 { - address 0x091 - access_mode RO - modes M_DFF0, M_DFF1 - mask CBNUM 0xFF -} - -/* - * CMC Recieve Message 1 - */ -register CMCRXMSG1 { - address 0x091 - access_mode RO - modes M_CCHAN - mask CBNUM 0xFF -} - -/* - * Overlay Recieve Message 1 - */ -register OVLYRXMSG1 { - address 0x091 - access_mode RO - modes M_SCSI - mask CBNUM 0xFF -} - -/* - * No Snoop Enable - */ -register NSENABLE { - address 0x091 - access_mode RW - modes M_CFG - bit MSINSEN 0x20 - bit OVLYNSEN 0x10 - bit CMCNSEN 0x08 - bit SGNSEN 0x04 - bit DCH1NSEN 0x02 - bit DCH0NSEN 0x01 -} - -/* - * Data Channel Receive Message 2 - */ -register DCHRXMSG2 { - address 0x092 - access_mode RO - modes M_DFF0, M_DFF1 - mask MINDEX 0xFF -} - -/* - * CMC Recieve Message 2 - */ -register CMCRXMSG2 { - address 0x092 - access_mode RO - modes M_CCHAN - mask MINDEX 0xFF -} - -/* - * Overlay Recieve Message 2 - */ -register OVLYRXMSG2 { - address 0x092 - access_mode RO - modes M_SCSI - mask MINDEX 0xFF -} - -/* - * Outstanding Split Transactions - */ -register OST { - address 0x092 - access_mode RW - modes M_CFG -} - -/* - * Data Channel Receive Message 3 - */ -register DCHRXMSG3 { - address 0x093 - access_mode RO - modes M_DFF0, M_DFF1 - mask MCLASS 0x0F -} - -/* - * CMC Recieve Message 3 - */ -register CMCRXMSG3 { - address 0x093 - access_mode RO - modes M_CCHAN - mask MCLASS 0x0F -} - -/* - * Overlay Recieve Message 3 - */ -register OVLYRXMSG3 { - address 0x093 - access_mode RO - modes M_SCSI - mask MCLASS 0x0F -} - -/* - * PCI-X Control - */ -register PCIXCTL { - address 0x093 - access_mode RW - modes M_CFG - bit SERRPULSE 0x80 - bit UNEXPSCIEN 0x20 - bit SPLTSMADIS 0x10 - bit SPLTSTADIS 0x08 - bit SRSPDPEEN 0x04 - bit TSCSERREN 0x02 - bit CMPABCDIS 0x01 -} - -/* - * CMC Sequencer Byte Count - */ -register CMCSEQBCNT { - address 0x094 - access_mode RO - modes M_CCHAN -} - -/* - * Overlay Sequencer Byte Count - */ -register OVLYSEQBCNT { - address 0x094 - access_mode RO - modes M_SCSI -} - -/* - * Data Channel Sequencer Byte Count - */ -register DCHSEQBCNT { - address 0x094 - access_mode RO - size 2 - modes M_DFF0, M_DFF1 -} - -/* - * Data Channel Split Status 0 - */ -register DCHSPLTSTAT0 { - address 0x096 - access_mode RW - modes M_DFF0, M_DFF1 - bit STAETERM 0x80 - bit SCBCERR 0x40 - bit SCADERR 0x20 - bit SCDATBUCKET 0x10 - bit CNTNOTCMPLT 0x08 - bit RXOVRUN 0x04 - bit RXSCEMSG 0x02 - bit RXSPLTRSP 0x01 -} - -/* - * CMC Split Status 0 - */ -register CMCSPLTSTAT0 { - address 0x096 - access_mode RW - modes M_CCHAN - bit STAETERM 0x80 - bit SCBCERR 0x40 - bit SCADERR 0x20 - bit SCDATBUCKET 0x10 - bit CNTNOTCMPLT 0x08 - bit RXOVRUN 0x04 - bit RXSCEMSG 0x02 - bit RXSPLTRSP 0x01 -} - -/* - * Overlay Split Status 0 - */ -register OVLYSPLTSTAT0 { - address 0x096 - access_mode RW - modes M_SCSI - bit STAETERM 0x80 - bit SCBCERR 0x40 - bit SCADERR 0x20 - bit SCDATBUCKET 0x10 - bit CNTNOTCMPLT 0x08 - bit RXOVRUN 0x04 - bit RXSCEMSG 0x02 - bit RXSPLTRSP 0x01 -} - -/* - * Data Channel Split Status 1 - */ -register DCHSPLTSTAT1 { - address 0x097 - access_mode RW - modes M_DFF0, M_DFF1 - bit RXDATABUCKET 0x01 -} - -/* - * CMC Split Status 1 - */ -register CMCSPLTSTAT1 { - address 0x097 - access_mode RW - modes M_CCHAN - bit RXDATABUCKET 0x01 -} - -/* - * Overlay Split Status 1 - */ -register OVLYSPLTSTAT1 { - address 0x097 - access_mode RW - modes M_SCSI - bit RXDATABUCKET 0x01 -} - -/* - * S/G Receive Message 0 - */ -register SGRXMSG0 { - address 0x098 - access_mode RO - modes M_DFF0, M_DFF1 - mask CDNUM 0xF8 - mask CFNUM 0x07 -} - -/* - * S/G Receive Message 1 - */ -register SGRXMSG1 { - address 0x099 - access_mode RO - modes M_DFF0, M_DFF1 - mask CBNUM 0xFF -} - -/* - * S/G Receive Message 2 - */ -register SGRXMSG2 { - address 0x09A - access_mode RO - modes M_DFF0, M_DFF1 - mask MINDEX 0xFF -} - -/* - * S/G Receive Message 3 - */ -register SGRXMSG3 { - address 0x09B - access_mode RO - modes M_DFF0, M_DFF1 - mask MCLASS 0x0F -} - -/* - * Slave Split Out Address 0 - */ -register SLVSPLTOUTADR0 { - address 0x098 - access_mode RO - modes M_SCSI - mask LOWER_ADDR 0x7F -} - -/* - * Slave Split Out Address 1 - */ -register SLVSPLTOUTADR1 { - address 0x099 - access_mode RO - modes M_SCSI - mask REQ_DNUM 0xF8 - mask REQ_FNUM 0x07 -} - -/* - * Slave Split Out Address 2 - */ -register SLVSPLTOUTADR2 { - address 0x09A - access_mode RO - modes M_SCSI - mask REQ_BNUM 0xFF -} - -/* - * Slave Split Out Address 3 - */ -register SLVSPLTOUTADR3 { - address 0x09B - access_mode RO - modes M_SCSI - bit RLXORD 020 - mask TAG_NUM 0x1F -} - -/* - * SG Sequencer Byte Count - */ -register SGSEQBCNT { - address 0x09C - access_mode RO - modes M_DFF0, M_DFF1 -} - -/* - * Slave Split Out Attribute 0 - */ -register SLVSPLTOUTATTR0 { - address 0x09C - access_mode RO - modes M_SCSI - mask LOWER_BCNT 0xFF -} - -/* - * Slave Split Out Attribute 1 - */ -register SLVSPLTOUTATTR1 { - address 0x09D - access_mode RO - modes M_SCSI - mask CMPLT_DNUM 0xF8 - mask CMPLT_FNUM 0x07 -} - -/* - * Slave Split Out Attribute 2 - */ -register SLVSPLTOUTATTR2 { - address 0x09E - access_mode RO - size 2 - modes M_SCSI - mask CMPLT_BNUM 0xFF -} -/* - * S/G Split Status 0 - */ -register SGSPLTSTAT0 { - address 0x09E - access_mode RW - modes M_DFF0, M_DFF1 - bit STAETERM 0x80 - bit SCBCERR 0x40 - bit SCADERR 0x20 - bit SCDATBUCKET 0x10 - bit CNTNOTCMPLT 0x08 - bit RXOVRUN 0x04 - bit RXSCEMSG 0x02 - bit RXSPLTRSP 0x01 -} - -/* - * S/G Split Status 1 - */ -register SGSPLTSTAT1 { - address 0x09F - access_mode RW - modes M_DFF0, M_DFF1 - bit RXDATABUCKET 0x01 -} - -/* - * Special Function - */ -register SFUNCT { - address 0x09f - access_mode RW - modes M_CFG - mask TEST_GROUP 0xF0 - mask TEST_NUM 0x0F -} - -/* - * Data FIFO 0 PCI Status - */ -register DF0PCISTAT { - address 0x0A0 - access_mode RW - modes M_CFG - bit DPE 0x80 - bit SSE 0x40 - bit RMA 0x20 - bit RTA 0x10 - bit SCAAPERR 0x08 - bit RDPERR 0x04 - bit TWATERR 0x02 - bit DPR 0x01 -} - -/* - * Data FIFO 1 PCI Status - */ -register DF1PCISTAT { - address 0x0A1 - access_mode RW - modes M_CFG - bit DPE 0x80 - bit SSE 0x40 - bit RMA 0x20 - bit RTA 0x10 - bit SCAAPERR 0x08 - bit RDPERR 0x04 - bit TWATERR 0x02 - bit DPR 0x01 -} - -/* - * S/G PCI Status - */ -register SGPCISTAT { - address 0x0A2 - access_mode RW - modes M_CFG - bit DPE 0x80 - bit SSE 0x40 - bit RMA 0x20 - bit RTA 0x10 - bit SCAAPERR 0x08 - bit RDPERR 0x04 - bit DPR 0x01 -} - -/* - * CMC PCI Status - */ -register CMCPCISTAT { - address 0x0A3 - access_mode RW - modes M_CFG - bit DPE 0x80 - bit SSE 0x40 - bit RMA 0x20 - bit RTA 0x10 - bit SCAAPERR 0x08 - bit RDPERR 0x04 - bit TWATERR 0x02 - bit DPR 0x01 -} - -/* - * Overlay PCI Status - */ -register OVLYPCISTAT { - address 0x0A4 - access_mode RW - modes M_CFG - bit DPE 0x80 - bit SSE 0x40 - bit RMA 0x20 - bit RTA 0x10 - bit SCAAPERR 0x08 - bit RDPERR 0x04 - bit DPR 0x01 -} - -/* - * PCI Status for MSI Master DMA Transfer - */ -register MSIPCISTAT { - address 0x0A6 - access_mode RW - modes M_CFG - bit SSE 0x40 - bit RMA 0x20 - bit RTA 0x10 - bit CLRPENDMSI 0x08 - bit TWATERR 0x02 - bit DPR 0x01 -} - -/* - * PCI Status for Target - */ -register TARGPCISTAT { - address 0x0A6 - access_mode RW - modes M_CFG - bit DPE 0x80 - bit SSE 0x40 - bit STA 0x08 - bit TWATERR 0x02 -} - -/* - * LQ Packet In - * The last LQ Packet recieved - */ -register LQIN { - address 0x020 - access_mode RW - size 20 - modes M_DFF0, M_DFF1, M_SCSI -} - -/* - * SCB Type Pointer - * SCB offset for Target Mode SCB type information - */ -register TYPEPTR { - address 0x020 - access_mode RW - modes M_CFG -} - -/* - * Queue Tag Pointer - * SCB offset to the Two Byte tag identifier used for target mode. - */ -register TAGPTR { - address 0x021 - access_mode RW - modes M_CFG -} - -/* - * Logical Unit Number Pointer - * SCB offset to the LSB (little endian) of the lun field. - */ -register LUNPTR { - address 0x022 - access_mode RW - modes M_CFG -} - -/* - * Data Length Pointer - * SCB offset for the 4 byte data length field in target mode. - */ -register DATALENPTR { - address 0x023 - access_mode RW - modes M_CFG -} - -/* - * Status Length Pointer - * SCB offset to the two byte status field in target SCBs. - */ -register STATLENPTR { - address 0x024 - access_mode RW - modes M_CFG -} - -/* - * Command Length Pointer - * Scb offset for the CDB length field in initiator SCBs. - */ -register CMDLENPTR { - address 0x025 - access_mode RW - modes M_CFG -} - -/* - * Task Attribute Pointer - * Scb offset for the byte field specifying the attribute byte - * to be used in command packets. - */ -register ATTRPTR { - address 0x026 - access_mode RW - modes M_CFG -} - -/* - * Task Management Flags Pointer - * Scb offset for the byte field specifying the attribute flags - * byte to be used in command packets. - */ -register FLAGPTR { - address 0x027 - access_mode RW - modes M_CFG -} - -/* - * Command Pointer - * Scb offset for the first byte in the CDB for initiator SCBs. - */ -register CMDPTR { - address 0x028 - access_mode RW - modes M_CFG -} - -/* - * Queue Next Pointer - * Scb offset for the 2 byte "next scb link". - */ -register QNEXTPTR { - address 0x029 - access_mode RW - modes M_CFG -} - -/* - * SCSI ID Pointer - * Scb offset to the value to place in the SCSIID register - * during target mode connections. - */ -register IDPTR { - address 0x02A - access_mode RW - modes M_CFG -} - -/* - * Command Aborted Byte Pointer - * Offset to the SCB flags field that includes the - * "SCB aborted" status bit. - */ -register ABRTBYTEPTR { - address 0x02B - access_mode RW - modes M_CFG -} - -/* - * Command Aborted Bit Pointer - * Bit offset in the SCB flags field for "SCB aborted" status. - */ -register ABRTBITPTR { - address 0x02C - access_mode RW - modes M_CFG -} - -/* - * Logical Unit Number Length - * The length, in bytes, of the SCB lun field. - */ -register LUNLEN { - address 0x030 - access_mode RW - modes M_CFG -} - -/* - * CDB Limit - * The size, in bytes, of the embedded CDB field in initator SCBs. - */ -register CDBLIMIT { - address 0x031 - access_mode RW - modes M_CFG -} - -/* - * Maximum Commands - * The maximum number of commands to issue during a - * single packetized connection. - */ -register MAXCMD { - address 0x032 - access_mode RW - modes M_CFG -} - -/* - * Maximum Command Counter - * The number of commands already sent during this connection - */ -register MAXCMDCNT { - address 0x033 - access_mode RW - modes M_CFG -} - -/* - * LQ Packet Reserved Bytes - * The bytes to be sent in the currently reserved fileds - * of all LQ packets. - */ -register LQRSVD01 { - address 0x034 - access_mode RW - modes M_SCSI -} -register LQRSVD16 { - address 0x035 - access_mode RW - modes M_SCSI -} -register LQRSVD17 { - address 0x036 - access_mode RW - modes M_SCSI -} - -/* - * Command Reserved 0 - * The byte to be sent for the reserved byte 0 of - * outgoing command packets. - */ -register CMDRSVD0 { - address 0x037 - access_mode RW - modes M_CFG -} - -/* - * LQ Manager Control 0 - */ -register LQCTL0 { - address 0x038 - access_mode RW - modes M_CFG - mask LQITARGCLT 0xC0 - mask LQIINITGCLT 0x30 - mask LQ0TARGCLT 0x0C - mask LQ0INITGCLT 0x03 -} - -/* - * LQ Manager Control 1 - */ -register LQCTL1 { - address 0x038 - access_mode RW - modes M_DFF0, M_DFF1, M_SCSI - bit PCI2PCI 0x04 - bit SINGLECMD 0x02 - bit ABORTPENDING 0x01 -} - -/* - * LQ Manager Control 2 - */ -register LQCTL2 { - address 0x039 - access_mode RW - modes M_DFF0, M_DFF1, M_SCSI - bit LQIRETRY 0x80 - bit LQICONTINUE 0x40 - bit LQITOIDLE 0x20 - bit LQIPAUSE 0x10 - bit LQORETRY 0x08 - bit LQOCONTINUE 0x04 - bit LQOTOIDLE 0x02 - bit LQOPAUSE 0x01 -} - -/* - * SCSI RAM BIST0 - */ -register SCSBIST0 { - address 0x039 - access_mode RW - modes M_CFG - bit GSBISTERR 0x40 - bit GSBISTDONE 0x20 - bit GSBISTRUN 0x10 - bit OSBISTERR 0x04 - bit OSBISTDONE 0x02 - bit OSBISTRUN 0x01 -} - -/* - * SCSI Sequence Control0 - */ -register SCSISEQ0 { - address 0x03A - access_mode RW - modes M_DFF0, M_DFF1, M_SCSI - bit TEMODEO 0x80 - bit ENSELO 0x40 - bit ENARBO 0x20 - bit FORCEBUSFREE 0x10 - bit SCSIRSTO 0x01 -} - -/* - * SCSI RAM BIST 1 - */ -register SCSBIST1 { - address 0x03A - access_mode RW - modes M_CFG - bit NTBISTERR 0x04 - bit NTBISTDONE 0x02 - bit NTBISTRUN 0x01 -} - -/* - * SCSI Sequence Control 1 - */ -register SCSISEQ1 { - address 0x03B - access_mode RW - modes M_DFF0, M_DFF1, M_SCSI - bit MANUALCTL 0x40 - bit ENSELI 0x20 - bit ENRSELI 0x10 - mask MANUALP 0x0C - bit ENAUTOATNP 0x02 - bit ALTSTIM 0x01 -} - -/* - * SCSI Transfer Control 0 - */ -register SXFRCTL0 { - address 0x03C - access_mode RW - modes M_SCSI - bit DFON 0x80 - bit DFPEXP 0x40 - bit BIOSCANCELEN 0x10 - bit SPIOEN 0x08 -} - -/* - * SCSI Transfer Control 1 - */ -register SXFRCTL1 { - address 0x03D - access_mode RW - modes M_SCSI - bit BITBUCKET 0x80 - bit ENSACHK 0x40 - bit ENSPCHK 0x20 - mask STIMESEL 0x18 - bit ENSTIMER 0x04 - bit ACTNEGEN 0x02 - bit STPWEN 0x01 -} - -/* - * SCSI Transfer Control 2 - */ -register SXFRCTL2 { - address 0x03E - access_mode RW - modes M_SCSI - bit AUTORSTDIS 0x10 - bit CMDDMAEN 0x08 - mask ASU 0x07 -} - -/* - * SCSI Bus Initiator IDs - * Bitmask of observed initiators on the bus. - */ -register BUSINITID { - address 0x03C - access_mode RW - modes M_CFG - size 2 -} - -/* - * Data Length Counters - * Packet byte counter. - */ -register DLCOUNT { - address 0x03C - access_mode RW - modes M_DFF0, M_DFF1 - size 3 -} - -/* - * Data FIFO Status - */ -register DFFSTAT { - address 0x03F - access_mode RW - modes M_SCSI - bit FIFO1FREE 0x20 - bit FIFO0FREE 0x10 - bit CURRFIFO 0x01 -} - -/* - * SCSI Bus Target IDs - * Bitmask of observed targets on the bus. - */ -register BUSTARGID { - address 0x03E - access_mode RW - modes M_CFG - size 2 -} - -/* - * SCSI Control Signal Out - */ -register SCSISIGO { - address 0x040 - access_mode RW - modes M_DFF0, M_DFF1, M_SCSI - bit CDO 0x80 - bit IOO 0x40 - bit MSGO 0x20 - bit ATNO 0x10 - bit SELO 0x08 - bit BSYO 0x04 - bit REQO 0x02 - bit ACKO 0x01 -/* - * Possible phases to write into SCSISIG0 - */ - mask PHASE_MASK CDO|IOO|MSGO - mask P_DATAOUT 0x00 - mask P_DATAIN IOO - mask P_DATAOUT_DT P_DATAOUT|MSGO - mask P_DATAIN_DT P_DATAIN|MSGO - mask P_COMMAND CDO - mask P_MESGOUT CDO|MSGO - mask P_STATUS CDO|IOO - mask P_MESGIN CDO|IOO|MSGO -} - -register SCSISIGI { - address 0x041 - access_mode RO - modes M_DFF0, M_DFF1, M_SCSI - bit CDI 0x80 - bit IOI 0x40 - bit MSGI 0x20 - bit ATNI 0x10 - bit SELI 0x08 - bit BSYI 0x04 - bit REQI 0x02 - bit ACKI 0x01 -/* - * Possible phases in SCSISIGI - */ - mask PHASE_MASK CDI|IOI|MSGI - mask P_DATAOUT 0x00 - mask P_DATAIN IOI - mask P_DATAOUT_DT P_DATAOUT|MSGI - mask P_DATAIN_DT P_DATAIN|MSGI - mask P_COMMAND CDI - mask P_MESGOUT CDI|MSGI - mask P_STATUS CDI|IOI - mask P_MESGIN CDI|IOI|MSGI -} - -/* - * Multiple Target IDs - * Bitmask of ids to respond as a target. - */ -register MULTARGID { - address 0x040 - access_mode RW - modes M_CFG - size 2 -} - -/* - * SCSI Phase - */ -register SCSIPHASE { - address 0x042 - access_mode RO - modes M_DFF0, M_DFF1, M_SCSI - bit STATUS_PHASE 0x20 - bit COMMAND_PHASE 0x10 - bit MSG_IN_PHASE 0x08 - bit MSG_OUT_PHASE 0x04 - bit DATA_IN_PHASE 0x02 - bit DATA_OUT_PHASE 0x01 - mask DATA_PHASE_MASK 0x03 -} - -/* - * SCSI Data 0 Image - */ -register SCSIDAT0_IMG { - address 0x043 - access_mode RW - modes M_DFF0, M_DFF1, M_SCSI -} - -/* - * SCSI Latched Data - */ -register SCSIDAT { - address 0x044 - access_mode RW - modes M_DFF0, M_DFF1, M_SCSI - size 2 -} - -/* - * SCSI Data Bus - */ -register SCSIBUS { - address 0x046 - access_mode RW - modes M_DFF0, M_DFF1, M_SCSI - size 2 -} - -/* - * Target ID In - */ -register TARGIDIN { - address 0x048 - access_mode RO - modes M_DFF0, M_DFF1, M_SCSI - bit CLKOUT 0x80 - mask TARGID 0x0F -} - -/* - * Selection/Reselection ID - * Upper four bits are the device id. The ONEBIT is set when the re/selecting - * device did not set its own ID. - */ -register SELID { - address 0x049 - access_mode RW - modes M_DFF0, M_DFF1, M_SCSI - mask SELID_MASK 0xf0 - bit ONEBIT 0x08 -} - -/* - * SCSI Block Control - * Controls Bus type and channel selection. SELWIDE allows for the - * coexistence of 8bit and 16bit devices on a wide bus. - */ -register SBLKCTL { - address 0x04A - access_mode RW - modes M_DFF0, M_DFF1, M_SCSI - bit DIAGLEDEN 0x80 - bit DIAGLEDON 0x40 - bit ENAB40 0x08 /* LVD transceiver active */ - bit ENAB20 0x04 /* SE/HVD transceiver active */ - bit SELWIDE 0x02 -} - -/* - * Option Mode - */ -register OPTIONMODE { - address 0x04A - access_mode RW - modes M_CFG - bit BIOSCANCTL 0x80 - bit AUTOACKEN 0x40 - bit BIASCANCTL 0x20 - bit BUSFREEREV 0x10 - bit ENDGFORMCHK 0x04 - bit AUTO_MSGOUT_DE 0x02 - mask OPTIONMODE_DEFAULTS AUTO_MSGOUT_DE -} - -/* - * SCSI Status 0 - */ -register SSTAT0 { - address 0x04B - access_mode RO - modes M_DFF0, M_DFF1, M_SCSI - bit TARGET 0x80 /* Board acting as target */ - bit SELDO 0x40 /* Selection Done */ - bit SELDI 0x20 /* Board has been selected */ - bit SELINGO 0x10 /* Selection In Progress */ - bit IOERR 0x08 /* LVD Tranceiver mode changed */ - bit OVERRUN 0x04 /* SCSI Offset overrun detected */ - bit SPIORDY 0x02 /* SCSI PIO Ready */ - bit ARBDO 0x01 /* Arbitration Done Out */ -} - -/* - * Clear SCSI Interrupt 0 - * Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT0. - */ -register CLRSINT0 { - address 0x04B - access_mode WO - modes M_DFF0, M_DFF1, M_SCSI - bit CLRSELDO 0x40 - bit CLRSELDI 0x20 - bit CLRSELINGO 0x10 - bit CLRIOERR 0x08 - bit CLROVERRUN 0x04 - bit CLRSPIORDY 0x02 - bit CLRARBDO 0x01 -} - -/* - * SCSI Interrupt Mode 0 - * Setting any bit will enable the corresponding function - * in SIMODE0 to interrupt via the IRQ pin. - */ -register SIMODE0 { - address 0x04B - access_mode RW - modes M_CFG - bit ENSELDO 0x40 - bit ENSELDI 0x20 - bit ENSELINGO 0x10 - bit ENIOERR 0x08 - bit ENOVERRUN 0x04 - bit ENSPIORDY 0x02 - bit ENARBDO 0x01 -} - -/* - * SCSI Status 1 - */ -register SSTAT1 { - address 0x04C - access_mode RO - modes M_DFF0, M_DFF1, M_SCSI - bit SELTO 0x80 - bit ATNTARG 0x40 - bit SCSIRSTI 0x20 - bit PHASEMIS 0x10 - bit BUSFREE 0x08 - bit SCSIPERR 0x04 - bit STRB2FAST 0x02 - bit REQINIT 0x01 -} - -/* - * Clear SCSI Interrupt 1 - * Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT1. - */ -register CLRSINT1 { - address 0x04c - access_mode WO - modes M_DFF0, M_DFF1, M_SCSI - bit CLRSELTIMEO 0x80 - bit CLRATNO 0x40 - bit CLRSCSIRSTI 0x20 - bit CLRBUSFREE 0x08 - bit CLRSCSIPERR 0x04 - bit CLRSTRB2FAST 0x02 - bit CLRREQINIT 0x01 -} - -/* - * SCSI Status 2 - */ -register SSTAT2 { - address 0x04d - access_mode RO - modes M_DFF0, M_DFF1, M_SCSI - mask BUSFREETIME 0xc0 - mask BUSFREE_LQO 0x40 - mask BUSFREE_DFF0 0x80 - mask BUSFREE_DFF1 0xC0 - bit NONPACKREQ 0x20 - bit EXP_ACTIVE 0x10 /* SCSI Expander Active */ - bit BSYX 0x08 /* Busy Expander */ - bit WIDE_RES 0x04 /* Modes 0 and 1 only */ - bit SDONE 0x02 /* Modes 0 and 1 only */ - bit DMADONE 0x01 /* Modes 0 and 1 only */ -} - -/* - * Clear SCSI Interrupt 2 - */ -register CLRSINT2 { - address 0x04D - access_mode WO - modes M_DFF0, M_DFF1, M_SCSI - bit CLRNONPACKREQ 0x20 - bit CLRWIDE_RES 0x04 /* Modes 0 and 1 only */ - bit CLRSDONE 0x02 /* Modes 0 and 1 only */ - bit CLRDMADONE 0x01 /* Modes 0 and 1 only */ -} - -/* - * SCSI Interrupt Mode 2 - */ -register SIMODE2 { - address 0x04D - access_mode RW - modes M_CFG - bit ENWIDE_RES 0x04 - bit ENSDONE 0x02 - bit ENDMADONE 0x01 -} - -/* - * Physical Error Diagnosis - */ -register PERRDIAG { - address 0x04E - access_mode RO - modes M_DFF0, M_DFF1, M_SCSI - bit HIZERO 0x80 - bit HIPERR 0x40 - bit PREVPHASE 0x20 - bit PARITYERR 0x10 - bit AIPERR 0x08 - bit CRCERR 0x04 - bit DGFORMERR 0x02 - bit DTERR 0x01 -} - -/* - * LQI Manager Current State - */ -register LQISTATE { - address 0x04E - access_mode RO - modes M_CFG -} - -/* - * SCSI Offset Count - */ -register SOFFCNT { - address 0x04F - access_mode RO - modes M_DFF0, M_DFF1, M_SCSI -} - -/* - * LQO Manager Current State - */ -register LQOSTATE { - address 0x04F - access_mode RO - modes M_CFG -} - -/* - * LQI Manager Status - */ -register LQISTAT0 { - address 0x050 - access_mode RO - modes M_DFF0, M_DFF1, M_SCSI - bit LQIATNQAS 0x20 - bit LQICRCT1 0x10 - bit LQICRCT2 0x08 - bit LQIBADLQT 0x04 - bit LQIATNLQ 0x02 - bit LQIATNCMD 0x01 -} - -/* - * Clear LQI Interrupts 0 - */ -register CLRLQIINTO { - address 0x050 - access_mode WO - modes M_DFF0, M_DFF1, M_SCSI - bit CLRLQIATNQAS 0x20 - bit CLRLQICRCT1 0x10 - bit CLRLQICRCT2 0x08 - bit CLRLQIBADLQT 0x04 - bit CLRLQIATNLQ 0x02 - bit CLRLQIATNCMD 0x01 -} - -/* - * LQI Manager Interrupt Mode 0 - */ -register LQIMODE0 { - address 0x050 - access_mode RW - modes M_CFG - bit ENLQIATNQASK 0x20 - bit ENLQICRCT1 0x10 - bit ENLQICRCT2 0x08 - bit ENLQIBADLQT 0x04 - bit ENLQIATNLQ 0x02 - bit ENLQIATNCMD 0x01 -} - -/* - * LQI Manager Status 1 - */ -register LQISTAT1 { - address 0x051 - access_mode RO - modes M_DFF0, M_DFF1, M_SCSI - mask LQIPHASE_LQ 0x80 - mask LQIPHASE_NLQ 0x40 - bit LQIABORT 0x20 - mask LQICRCI_LQ 0x10 - mask LQICRCI_NLQ 0x08 - bit LQIBADLQI 0x04 - mask LQIOVERI_LQ 0x02 - mask LQIOVERI_NLQ 0x01 -} - -/* - * Clear LQI Manager Interrupts1 - */ -register CLRLQIINT1 { - address 0x051 - access_mode WO - modes M_DFF0, M_DFF1, M_SCSI - mask CLRLQIPHASE_LQ 0x80 - mask CLRLQIPHASE_NLQ 0x40 - bit CLRLIQABORT 0x20 - mask CLRLQICRCI_LQ 0x10 - mask CLRLQICRCI_NLQ 0x08 - bit CLRLQIBADLQI 0x04 - mask CLRLQIOVERI_LQ 0x02 - mask CLRLQIOVERI_NLQ 0x01 -} - -/* - * LQI Manager Interrupt Mode 1 - */ -register LQIMODE1 { - address 0x051 - access_mode RW - modes M_CFG - mask ENLQIPHASE_LQ 0x80 - mask ENLQIPHASE_NLQ 0x40 - bit ENLIQABORT 0x20 - mask ENLQICRCI_LQ 0x10 - mask ENLQICRCI_NLQ 0x08 - bit ENLQIBADLQI 0x04 - mask ENLQIOVERI_LQ 0x02 - mask ENLQIOVERI_NLQ 0x01 -} - -/* - * LQI Manager Status 2 - */ -register LQISTAT2 { - address 0x052 - access_mode RO - modes M_DFF0, M_DFF1, M_SCSI - bit PACKETIZED 0x80 - bit LQIPHASE_OUTPKT 0x40 - bit LQIWORKONLQ 0x20 - bit LQIWAITFIFO 0x10 - bit LQISTOPPKT 0x08 - bit LQISTOPLQ 0x04 - bit LQISTOPCMD 0x02 - bit LQIGSAVAIL 0x01 -} - -/* - * SCSI Status 3 - */ -register SSTAT3 { - address 0x053 - access_mode RO - modes M_DFF0, M_DFF1, M_SCSI - bit NTRAMPERR 0x02 - bit OSRAMPERR 0x01 -} - -/* - * Clear SCSI Status 3 - */ -register CLRSINT3 { - address 0x053 - access_mode WO - modes M_DFF0, M_DFF1, M_SCSI - bit CLRNTRAMPERR 0x02 - bit CLROSRAMPERR 0x01 -} - -/* - * SCSI Interrupt Mode 3 - */ -register SIMODE3 { - address 0x053 - access_mode RW - modes M_CFG - bit ENNTRAMPERR 0x02 - bit ENOSRAMPERR 0x01 -} - -/* - * LQO Manager Status 0 - */ -register LQOSTAT0 { - address 0x054 - access_mode RO - modes M_DFF0, M_DFF1, M_SCSI - bit LQOTARGSCBPERR 0x10 - bit LQOSTOPT2 0x08 - bit LQOATNLQ 0x04 - bit LQOATNPKT 0x02 - bit LQOTCRC 0x01 -} - -/* - * Clear LQO Manager interrupt 0 - */ -register CLRLQOINT0 { - address 0x054 - access_mode WO - modes M_DFF0, M_DFF1, M_SCSI - bit CLRLQOTARGSCBPERR 0x10 - bit CLRLQOSTOPT2 0x08 - bit CLRLQOATNLQ 0x04 - bit CLRLQOATNPKT 0x02 - bit CLRLQOTCRC 0x01 -} - -/* - * LQO Manager Interrupt Mode 0 - */ -register LQOMODE0 { - address 0x054 - access_mode RW - modes M_CFG - bit ENLQOTARGSCBPERR 0x10 - bit ENLQOSTOPT2 0x08 - bit ENLQOATNLQ 0x04 - bit ENLQOATNPKT 0x02 - bit ENLQOTCRC 0x01 -} - -/* - * LQO Manager Status 1 - */ -register LQOSTAT1 { - address 0x055 - access_mode RO - modes M_DFF0, M_DFF1, M_SCSI - bit LQOINITSCBPERR 0x10 - bit LQOSTOPI2 0x08 - bit LQOBADQAS 0x04 - bit LQOBUSFREE 0x02 - bit LQOPHACHGINPKT 0x01 -} - -/* - * Clear LOQ Interrupt 1 - */ -register CLRLQOINT1 { - address 0x055 - access_mode WO - modes M_DFF0, M_DFF1, M_SCSI - bit CLRLQOINITSCBPERR 0x10 - bit CLRLQOSTOPI2 0x08 - bit CLRLQOBADQAS 0x04 - bit CLRLQOBUSFREE 0x02 - bit CLRLQOPHACHGINPKT 0x01 -} - -/* - * LQO Manager Interrupt Mode 1 - */ -register LQOMODE1 { - address 0x055 - access_mode RW - modes M_CFG - bit ENLQOINITSCBPERR 0x10 - bit ENLQOSTOPI2 0x08 - bit ENLQOBADQAS 0x04 - bit ENLQOBUSFREE 0x02 - bit ENLQOPHACHGINPKT 0x01 -} - -/* - * LQO Manager Status 2 - */ -register LQOSTAT2 { - address 0x056 - access_mode RO - modes M_DFF0, M_DFF1, M_SCSI - mask LQOPKT 0xE0 - bit LQOWAITFIFO 0x10 - bit LQOPHACHGOUTPKT 0x02 /* outside of packet boundaries. */ - bit LQOSTOP0 0x01 /* Stopped after sending all packets */ -} - -/* - * Output Synchronizer Space Count - */ -register OS_SPACE_CNT { - address 0x056 - access_mode RO - modes M_CFG -} - -/* - * SCSI Interrupt Mode 1 - * Setting any bit will enable the corresponding function - * in SIMODE1 to interrupt via the IRQ pin. - */ -register SIMODE1 { - address 0x057 - access_mode RW - modes M_DFF0, M_DFF1, M_SCSI - bit ENSELTIMO 0x80 - bit ENATNTARG 0x40 - bit ENSCSIRST 0x20 - bit ENPHASEMIS 0x10 - bit ENBUSFREE 0x08 - bit ENSCSIPERR 0x04 - bit ENSTRB2FAST 0x02 - bit ENREQINIT 0x01 -} - -/* - * Good Status FIFO - */ -register GSFIFO { - address 0x058 - access_mode RO - size 2 - modes M_DFF0, M_DFF1, M_SCSI -} - -/* - * Data FIFO SCSI Transfer Control - */ -register DFFSXFRCTL { - address 0x05A - access_mode RW - modes M_DFF0, M_DFF1 - bit CLRSHCNT 0x04 - bit CLRCHN 0x02 - bit RSTCHN 0x01 -} - -/* - * Next SCSI Control Block - */ -register NEXTSCB { - address 0x05A - access_mode RW - size 2 - modes M_SCSI -} - -/* - * SEQ Interrupts - */ -register SEQINTSRC { - address 0x05B - access_mode RO - modes M_DFF0, M_DFF1 - bit CTXTDONE 0x40 - bit SAVEPTRS 0x20 - bit CFG4DATA 0x10 - bit CFG4ISTAT 0x08 - bit CFG4TSTAT 0x04 - bit CFG4ICMD 0x02 - bit CFG4TCMD 0x01 -} - -/* - * Clear Arp Interrupts - */ -register CLRSEQINTSRC { - address 0x05B - access_mode WO - modes M_DFF0, M_DFF1 - bit CLRCTXTDONE 0x40 - bit CLRSAVEPTRS 0x20 - bit CLRCFG4DATA 0x10 - bit CLRCFG4ISTAT 0x08 - bit CLRCFG4TSTAT 0x04 - bit CLRCFG4ICMD 0x02 - bit CLRCFG4TCMD 0x01 -} - -/* - * SEQ Interrupt Enabled (Shared) - */ -register SEQIMODE { - address 0x05C - access_mode RW - modes M_DFF0, M_DFF1 - bit ENCTXTDONE 0x40 - bit ENSAVEPTRS 0x20 - bit ENCFG4DATA 0x10 - bit ENCFG4ISTAT 0x08 - bit ENCFG4TSTAT 0x04 - bit ENCFG4ICMD 0x02 - bit ENCFG4TCMD 0x01 -} - -/* - * Current SCSI Control Block - */ -register CURRSCB { - address 0x05C - access_mode RW - size 2 - modes M_SCSI -} - -/* - * Data FIFO Status - */ -register MDFFSTAT { - address 0x05D - access_mode RO - modes M_DFF0, M_DFF1 - bit LASTSDONE 0x10 - bit SHVALID 0x08 - bit DLZERO 0x04 /* FIFO data ends on packet boundary. */ - bit DATAINFIFO 0x02 - bit FIFOFREE 0x01 -} - -/* - * CRC Control - */ -register CRCCONTROL { - address 0x05d - access_mode RW - modes M_CFG - bit CRCVALCHKEN 0x40 -} - -/* - * SCSI Test Control - */ -register SCSITEST { - address 0x05E - access_mode RW - modes M_CFG - bit CNTRTEST 0x08 - bit SEL_TXPLL_DEBUG 0x04 -} - -/* - * Data FIFO Queue Tag - */ -register DFFTAG { - address 0x05E - access_mode RW - size 2 - modes M_DFF0, M_DFF1 -} - -/* - * Last SCSI Control Block - */ -register LASTSCB { - address 0x05E - access_mode RW - size 2 - modes M_SCSI -} - -/* - * SCSI I/O Cell Power-down Control - */ -register IOPDNCTL { - address 0x05F - access_mode RW - modes M_CFG - bit DISABLE_OE 0x80 - bit PDN_IDIST 0x04 - bit PDN_DIFFSENSE 0x01 -} - -/* - * Shaddow Host Address. - */ -register SHADDR { - address 0x060 - access_mode RO - size 8 - modes M_DFF0, M_DFF1 -} - -/* - * Data Group CRC Interval. - */ -register DGRPCRCI { - address 0x060 - access_mode RW - size 2 - modes M_CFG -} - -/* - * Data Transfer Negotiation Address - */ -register NEGOADDR { - address 0x060 - access_mode RW - modes M_SCSI -} - -/* - * Data Transfer Negotiation Data - Period Byte - */ -register NEGPERIOD { - address 0x061 - access_mode RW - modes M_SCSI -} - -/* - * Packetized CRC Interval - */ -register PACKCRCI { - address 0x062 - access_mode RW - size 2 - modes M_CFG -} - -/* - * Data Transfer Negotiation Data - Offset Byte - */ -register NEGOFFSET { - address 0x062 - access_mode RW - modes M_SCSI -} - -/* - * Data Transfer Negotiation Data - PPR Options - */ -register NEGPPROPTS { - address 0x063 - access_mode RW - modes M_SCSI - bit PPROPT_PACE 0x08 - bit PPROPT_QAS 0x04 - bit PPROPT_DT 0x02 - bit PPROPT_IUT 0x01 -} - -/* - * Data Transfer Negotiation Data - Connection Options - */ -register NEGCONOPTS { - address 0x064 - access_mode RW - modes M_SCSI - bit ENAIP 0x08 - bit ENAUTOATNI 0x04 - bit ENAUTOATNO 0x02 - bit WIDEXFER 0x01 -} - -/* - * Negotiation Table Annex Column Index. - */ -register ANNEXCOL { - address 0x065 - access_mode RW - modes M_SCSI -} - -const AHD_ANNEXCOL_PRECOMP 4 -const AHD_PRECOMP_MASK 0x07 -const AHD_PRECOMP_CUTBACK_17 0x04 -const AHD_PRECOMP_CUTBACK_29 0x06 -const AHD_PRECOMP_CUTBACK_37 0x07 -const AHD_PRECOMP_FASTSLEW 0x40 -const AHD_NUM_ANNEXCOLS 4 - -/* - * Negotiation Table Annex Data Port. - */ -register ANNEXDAT { - address 0x066 - access_mode RW - modes M_SCSI -} - -/* - * Initiator's Own Id. - * The SCSI ID to use for Selection Out and seen during a reselection.. - */ -register IOWNID { - address 0x067 - access_mode RW - modes M_SCSI -} - -/* - * 960MHz Phase-Locked Loop Control 0 - */ -register PLL960CTL0 { - address 0x068 - access_mode RW - modes M_CFG - bit PLL_VCOSEL 0x80 - bit PLL_PWDN 0x40 - mask PLL_NS 0x30 - bit PLL_ENLUD 0x08 - bit PLL_ENLPF 0x04 - bit PLL_DLPF 0x02 - bit PLL_ENFBM 0x01 -} - -/* - * Target Own Id - */ -register TOWNID { - address 0x069 - access_mode RW - modes M_SCSI -} - -/* - * 960MHz Phase-Locked Loop Control 1 - */ -register PLL960CTL1 { - address 0x069 - access_mode RW - modes M_CFG - bit PLL_CNTEN 0x80 - bit PLL_CNTCLR 0x40 - bit PLL_RST 0x01 -} - -/* - * Expander Signature - */ -register XSIG { - address 0x06A - access_mode RW - modes M_SCSI -} - -/* - * Shadow Byte Count - */ -register SHCNT { - address 0x068 - access_mode RW - size 3 - modes M_DFF0, M_DFF1 -} - -/* - * Selection Out ID - */ -register SELOID { - address 0x06B - access_mode RW - modes M_SCSI -} - -/* - * 960-MHz Phase-Locked Loop Test Count - */ -register PLL960CNT0 { - address 0x06A - access_mode RO - size 2 - modes M_CFG -} - -/* - * 400-MHz Phase-Locked Loop Control 0 - */ -register PLL400CTL0 { - address 0x06C - access_mode RW - modes M_CFG - bit PLL_VCOSEL 0x80 - bit PLL_PWDN 0x40 - mask PLL_NS 0x30 - bit PLL_ENLUD 0x08 - bit PLL_ENLPF 0x04 - bit PLL_DLPF 0x02 - bit PLL_ENFBM 0x01 -} - -/* - * Arbitration Fairness - */ -register FAIRNESS { - address 0x06C - access_mode RW - size 2 - modes M_SCSI -} - -/* - * 400-MHz Phase-Locked Loop Control 1 - */ -register PLL400CTL1 { - address 0x06D - access_mode RW - modes M_CFG - bit PLL_CNTEN 0x80 - bit PLL_CNTCLR 0x40 - bit PLL_RST 0x01 -} - -/* - * Arbitration Unfairness - */ -register UNFAIRNESS { - address 0x06E - access_mode RW - size 2 - modes M_SCSI -} - -/* - * 400-MHz Phase-Locked Loop Test Count - */ -register PLL400CNT0 { - address 0x06E - access_mode RO - size 2 - modes M_CFG -} - -/* - * SCB Page Pointer - */ -register SCBPTR { - address 0x0A8 - access_mode RW - size 2 - modes M_DFF0, M_DFF1, M_CCHAN, M_SCSI -} - -/* - * CMC SCB Array Count - * Number of bytes to transfer between CMC SCB memory and SCBRAM. - * Transfers must be 8byte aligned and sized. - */ -register CCSCBACNT { - address 0x0AB - access_mode RW - modes M_CCHAN -} - -/* - * SCB Autopointer - * SCB-Next Address Snooping logic. When an SCB is transferred to - * the card, the next SCB address to be used by the CMC array can - * be autoloaded from that transfer. - */ -register SCBAUTOPTR { - address 0x0AB - access_mode RW - modes M_CFG - bit AUSCBPTR_EN 0x80 - mask SCBPTR_ADDR 0x38 - mask SCBPTR_OFF 0x07 -} - -/* - * CMC SG Ram Address Pointer - */ -register CCSGADDR { - address 0x0AC - access_mode RW - modes M_DFF0, M_DFF1 -} - -/* - * CMC SCB RAM Address Pointer - */ -register CCSCBADDR { - address 0x0AC - access_mode RW - modes M_CCHAN -} - -/* - * CMC SCB Ram Back-up Address Pointer - * Indicates the true stop location of transfers halted prior - * to SCBHCNT going to 0. - */ -register CCSCBADR_BK { - address 0x0AC - access_mode RO - modes M_CFG -} - -/* - * CMC SG Control - */ -register CCSGCTL { - address 0x0AD - access_mode RW - modes M_DFF0, M_DFF1 - bit CCSGDONE 0x80 - bit SG_CACHE_AVAIL 0x10 - bit CCSGEN 0x08 - bit SG_FETCH_REQ 0x02 - bit CCSGRESET 0x01 -} - -/* - * CMD SCB Control - */ -register CCSCBCTL { - address 0x0AD - access_mode RW - modes M_CCHAN - bit CCSCBDONE 0x80 - bit ARRDONE 0x40 - bit CCARREN 0x10 - bit CCSCBEN 0x08 - bit CCSCBDIR 0x04 - bit CCSCBRESET 0x01 -} - -/* - * CMC Ram BIST - */ -register CMC_RAMBIST { - address 0x0AD - access_mode RW - modes M_CFG - bit SG_ELEMENT_SIZE 0x80 - bit SCBRAMBIST_FAIL 0x40 - bit SG_BIST_FAIL 0x20 - bit SG_BIST_EN 0x10 - bit CMC_BUFFER_BIST_FAIL 0x02 - bit CMC_BUFFER_BIST_EN 0x01 -} - -/* - * CMC SG RAM Data Port - */ -register CCSGRAM { - address 0x0B0 - access_mode RW - modes M_DFF0, M_DFF1 -} - -/* - * CMC SCB RAM Data Port - */ -register CCSCBRAM { - address 0x0B0 - access_mode RW - modes M_CCHAN -} - -/* - * Flex DMA Address. - */ -register FLEXADR { - address 0x0B0 - access_mode RW - size 3 - modes M_SCSI -} - -/* - * Flex DMA Byte Count - */ -register FLEXCNT { - address 0x0B3 - access_mode RW - size 2 - modes M_SCSI -} - -/* - * Flex DMA Status - */ -register FLEXDMASTAT { - address 0x0B5 - access_mode RW - modes M_SCSI - bit FLEXDMAERR 0x02 - bit FLEXDMADONE 0x01 -} - -/* - * Flex DMA Data Port - */ -register FLEXDATA { - address 0x0B6 - access_mode RW - modes M_SCSI -} - -/* - * Board Data - */ -register BRDDAT { - address 0x0B8 - access_mode RW - modes M_SCSI -} - -/* - * Board Control - */ -register BRDCTL { - address 0x0B9 - access_mode RW - modes M_SCSI - bit FLXARBACK 0x80 - bit FLXARBREQ 0x40 - mask BRDADDR 0x38 - bit BRDEN 0x04 - bit BRDRW 0x02 - bit BRDSTB 0x01 -} - -/* - * Serial EEPROM Address - */ -register SEEADR { - address 0x0BA - access_mode RW - modes M_SCSI -} - -/* - * Serial EEPROM Data - */ -register SEEDAT { - address 0x0BC - access_mode RW - size 2 - modes M_SCSI -} - -/* - * Serial EEPROM Status - */ -register SEESTAT { - address 0x0BE - access_mode RO - modes M_SCSI - bit INIT_DONE 0x80 - mask SEEOPCODE 0x70 - bit LDALTID_L 0x08 - bit SEEARBACK 0x04 - bit SEEBUSY 0x02 - bit SEESTART 0x01 -} - -/* - * Serial EEPROM Control - */ -register SEECTL { - address 0x0BE - access_mode RW - modes M_SCSI - mask SEEOPCODE 0x70 - mask SEEOP_ERASE 0x70 - mask SEEOP_READ 0x60 - mask SEEOP_WRITE 0x50 - /* - * The following four commands use special - * addresses for differentiation. - */ - mask SEEOP_ERAL 0x40 - mask SEEOP_EWEN 0x40 - mask SEEOP_WALL 0x40 - mask SEEOP_EWDS 0x40 - bit SEERST 0x02 - bit SEESTART 0x01 -} - -const SEEOP_ERAL_ADDR 0x80 -const SEEOP_EWEN_ADDR 0xC0 -const SEEOP_WRAL_ADDR 0x40 -const SEEOP_EWDS_ADDR 0x00 - -/* - * SCB Counter - */ -register SCBCNT { - address 0x0BF - access_mode RW - modes M_SCSI -} - -/* - * Data FIFO Write Address - * Pointer to the next QWD location to be written to the data FIFO. - */ -register DFWADDR { - address 0x0C0 - access_mode RW - size 2 - modes M_DFF0, M_DFF1 -} - -/* - * DSP Filter Control - */ -register DSPFLTRCTL { - address 0x0C0 - access_mode RW - modes M_CFG - bit FLTRDISABLE 0x20 - bit EDGESENSE 0x10 - mask DSPFCNTSEL 0x0F -} - -/* - * DSP Data Channel Control - */ -register DSPDATACTL { - address 0x0C1 - access_mode RW - modes M_CFG - bit BYPASSENAB 0x80 - bit DESQDIS 0x10 - bit RCVROFFSTDIS 0x04 - bit XMITOFFSTDIS 0x02 -} - -/* - * Data FIFO Read Address - * Pointer to the next QWD location to be read from the data FIFO. - */ -register DFRADDR { - address 0x0C2 - access_mode RW - size 2 - modes M_DFF0, M_DFF1 -} - -/* - * DSP REQ Control - */ -register DSPREQCTL { - address 0x0C2 - access_mode RW - modes M_CFG - mask MANREQCTL 0xC0 - mask MANREQDLY 0x3F -} - -/* - * DSP ACK Control - */ -register DSPACKCTL { - address 0x0C3 - access_mode RW - modes M_CFG - mask MANACKCTL 0xC0 - mask MANACKDLY 0x3F -} - -/* - * Data FIFO Data - * Read/Write byte port into the data FIFO. The read and write - * FIFO pointers increment with each read and write respectively - * to this port. - */ -register DFDAT { - address 0x0C4 - access_mode RW - modes M_DFF0, M_DFF1 -} - -/* - * DSP Channel Select - */ -register DSPSELECT { - address 0x0C4 - access_mode RW - modes M_CFG - bit AUTOINCEN 0x80 - mask DSPSEL 0x1F -} - -const NUMDSPS 0x14 - -/* - * Write Bias Control - */ -register WRTBIASCTL { - address 0x0C5 - access_mode WO - modes M_CFG - bit AUTOXBCDIS 0x80 - mask XMITMANVAL 0x3F -} - -const WRTBIASCTL_CPQ_DEFAULT 0x97 - -/* - * Receiver Bias Control - */ -register RCVRBIOSCTL { - address 0x0C6 - access_mode WO - modes M_CFG - bit AUTORBCDIS 0x80 - mask RCVRMANVAL 0x3F -} - -/* - * Write Bias Calculator - */ -register WRTBIASCALC { - address 0x0C7 - access_mode RO - modes M_CFG -} - -/* - * Data FIFO Pointers - * Contains the byte offset from DFWADDR and DWRADDR to the current - * FIFO write/read locations. - */ -register DFPTRS { - address 0x0C8 - access_mode RW - modes M_DFF0, M_DFF1 -} - -/* - * Receiver Bias Calculator - */ -register RCVRBIASCALC { - address 0x0C8 - access_mode RO - modes M_CFG -} - -/* - * Data FIFO Debug Control - */ -register DFDBCTL { - address 0x0C8 - access_mode RW - modes M_DFF0, M_DFF1 - bit DFF_CIO_WR_RDY 0x20 - bit DFF_CIO_RD_RDY 0x10 - bit DFF_DIR_ERR 0x08 - bit DFF_RAMBIST_FAIL 0x04 - bit DFF_RAMBIST_DONE 0x02 - bit DFF_RAMBIST_EN 0x01 -} - -/* - * Data FIFO Backup Read Pointer - * Contains the data FIFO address to be restored if the last - * data accessed from the data FIFO was not transferred successfully. - */ -register DFBKPTR { - address 0x0C9 - access_mode RW - size 2 - modes M_DFF0, M_DFF1 -} - -/* - * Skew Calculator - */ -register SKEWCALC { - address 0x0C9 - access_mode RO - modes M_CFG -} - -/* - * Data FIFO Space Count - * Number of FIFO locations that are free. - */ -register DFSCNT { - address 0x0CC - access_mode RO - size 2 - modes M_DFF0, M_DFF1 -} - -/* - * Data FIFO Byte Count - * Number of filled FIFO locations. - */ -register DFBCNT { - address 0x0CE - access_mode RO - size 2 - modes M_DFF0, M_DFF1 -} - -/* - * Sequencer Program Overlay Address. - * Low address must be written prior to high address. - */ -register OVLYADDR { - address 0x0D4 - modes M_SCSI - size 2 - access_mode RW -} - -/* - * Sequencer Control 0 - * Error detection mode, speed configuration, - * single step, breakpoints and program load. - */ -register SEQCTL0 { - address 0x0D6 - access_mode RW - bit PERRORDIS 0x80 - bit PAUSEDIS 0x40 - bit FAILDIS 0x20 - bit FASTMODE 0x10 - bit BRKADRINTEN 0x08 - bit STEP 0x04 - bit SEQRESET 0x02 - bit LOADRAM 0x01 -} - -/* - * Sequencer Control 1 - * Instruction RAM Diagnostics - */ -register SEQCTL1 { - address 0x0D7 - access_mode RW - bit OVRLAY_DATA_CHK 0x08 - bit RAMBIST_DONE 0x04 - bit RAMBIST_FAIL 0x02 - bit RAMBIST_EN 0x01 -} - -/* - * Sequencer Flags - * Zero and Carry state of the ALU. - */ -register FLAGS { - address 0x0D8 - access_mode RO - bit ZERO 0x02 - bit CARRY 0x01 -} - -/* - * Sequencer Interrupt Control - */ -register SEQINTCTL { - address 0x0D9 - access_mode RW - bit INTVEC1DSL 0x80 - bit INT1_CONTEXT 0x20 - bit SCS_SEQ_INT1M1 0x10 - bit SCS_SEQ_INT1M0 0x08 - mask INTMASK 0x06 - bit IRET 0x01 -} - -/* - * Sequencer RAM Data Port - * Single byte window into the Sequencer Instruction Ram area starting - * at the address specified by OVLYADDR. To write a full instruction word, - * simply write four bytes in succession. OVLYADDR will increment after the - * most significant instrution byte (the byte with the parity bit) is written. - */ -register SEQRAM { - address 0x0DA - access_mode RW -} - -/* - * Sequencer Program Counter - * Low byte must be written prior to high byte. - */ -register PRGMCNT { - address 0x0DE - access_mode RW - size 2 -} - -/* - * Accumulator - */ -register ACCUM { - address 0x0E0 - access_mode RW - accumulator -} - -/* - * Source Index Register - * Incrementing index for reads of SINDIR and the destination (low byte only) - * for any immediate operands passed in jmp, jc, jnc, call instructions. - * Example: - * mvi 0xFF call some_routine; - * - * Will set SINDEX[0] to 0xFF and call the routine "some_routine. - */ -register SINDEX { - address 0x0E2 - access_mode RW - size 2 - sindex -} - -/* - * Destination Index Register - * Incrementing index for writes to DINDIR. Can be used as a scratch register. - */ -register DINDEX { - address 0x0E4 - access_mode RW - size 2 -} - -/* - * Break Address - * Sequencer instruction breakpoint address address. - */ -register BRKADDR0 { - address 0x0E6 - access_mode RW -} - -register BRKADDR1 { - address 0x0E6 - access_mode RW - bit BRKDIS 0x80 /* Disable Breakpoint */ -} - -/* - * All Ones - * All reads to this register return the value 0xFF. - */ -register ALLONES { - address 0x0E8 - access_mode RO - allones -} - -/* - * All Zeros - * All reads to this register return the value 0. - */ -register ALLZEROS { - address 0x0EA - access_mode RO - allzeros -} - -/* - * No Destination - * Writes to this register have no effect. - */ -register NONE { - address 0x0EA - access_mode WO - none -} - -/* - * Source Index Indirect - * Reading this register is equivalent to reading (register_base + SINDEX) and - * incrementing SINDEX by 1. - */ -register SINDIR { - address 0x0EC - access_mode RO -} - -/* - * Destination Index Indirect - * Writing this register is equivalent to writing to (register_base + DINDEX) - * and incrementing DINDEX by 1. - */ -register DINDIR { - address 0x0ED - access_mode WO -} - -/* - * Function One - * 2's complement to bit value conversion. Write the 2's complement value - * (0-7 only) to the top nibble and retrieve the bit indexed by that value - * on the next read of this register. - * Example: - * Write 0x60 - * Read 0x40 - */ -register FUNCTION1 { - address 0x0F0 - access_mode RW -} - -/* - * Stack - * Window into the stack. Each stack location is 10 bits wide reported - * low byte followed by high byte. There are 8 stack locations. - */ -register STACK { - address 0x0F2 - access_mode RW -} - -/* - * Interrupt Vector 1 Address - * Interrupt branch address for SCS SEQ_INT1 mode 0 and 1 interrupts. - */ -register INTVEC1_ADDR { - address 0x0F4 - access_mode RW - size 2 - modes M_CFG -} - -/* - * Current Address - * Address of the SEQRAM instruction currently executing instruction. - */ -register CURADDR { - address 0x0F4 - access_mode RW - size 2 - modes M_SCSI -} - -/* - * Interrupt Vector 2 Address - * Interrupt branch address for HST_SEQ_INT2 interrupts. - */ -register INTVEC2_ADDR { - address 0x0F6 - access_mode RW - size 2 - modes M_CFG -} - -/* - * Last Address - * Address of the SEQRAM instruction executed prior to the current instruction. - */ -register LASTADDR { - address 0x0F6 - access_mode RW - size 2 - modes M_SCSI -} - -register AHD_PCI_CONFIG_BASE { - address 0x100 - access_mode RW - size 256 - modes M_CFG -} - -/* ---------------------- Scratch RAM Offsets ------------------------- */ -scratch_ram { - /* Mode Specific */ - address 0x0A0 - size 8 - modes 0, 1, 2, 3 - REG0 { - size 2 - } - REG1 { - size 2 - } - REG2 { - size 2 - } - SG_STATE { - size 1 - bit SEGS_AVAIL 0x01 - bit LOADING_NEEDED 0x02 - bit FETCH_INPROG 0x04 - } - /* - * Track whether the transfer byte count for - * the current data phase is odd. - */ - DATA_COUNT_ODD { - size 1 - } -} - -scratch_ram { - /* Mode Specific */ - address 0x0F8 - size 8 - modes 0, 1, 2, 3 - LONGJMP_ADDR { - size 2 - } - LONGJMP_SCB { - size 2 - } - ACCUM_SAVE { - size 1 - } -} - - -scratch_ram { - address 0x100 - size 128 - modes 0, 1, 2, 3 - /* - * Per "other-id" execution queues. We use an array of - * tail pointers into lists of SCBs sorted by "other-id". - * The execution head pointer threads the head SCBs for - * each list. - */ - WAITING_SCB_TAILS { - size 32 - } - WAITING_TID_HEAD { - size 2 - } - WAITING_TID_TAIL { - size 2 - } - /* - * SCBID of the next SCB in the new SCB queue. - */ - NEXT_QUEUED_SCB_ADDR { - size 4 - } - /* - * head of list of SCBs that have - * completed but have not been - * put into the qoutfifo. - */ - COMPLETE_SCB_HEAD { - size 2 - } - /* - * The list of completed SCBs in - * the active DMA. - */ - COMPLETE_SCB_DMAINPROG_HEAD { - size 2 - } - /* - * head of list of SCBs that have - * completed but need to be uploaded - * to the host prior to being completed. - */ - COMPLETE_DMA_SCB_HEAD { - size 2 - } - /* Counting semaphore to prevent new select-outs */ - QFREEZE_COUNT { - size 2 - } - /* - * Mode to restore on idle_loop exit. - */ - SAVED_MODE { - size 1 - } - /* - * Single byte buffer used to designate the type or message - * to send to a target. - */ - MSG_OUT { - size 1 - } - /* Parameters for DMA Logic */ - DMAPARAMS { - size 1 - bit PRELOADEN 0x80 - bit WIDEODD 0x40 - bit SCSIEN 0x20 - bit SDMAEN 0x10 - bit SDMAENACK 0x10 - bit HDMAEN 0x08 - bit HDMAENACK 0x08 - bit DIRECTION 0x04 /* Set indicates PCI->SCSI */ - bit FIFOFLUSH 0x02 - bit FIFORESET 0x01 - } - SEQ_FLAGS { - size 1 - bit NOT_IDENTIFIED 0x80 - bit TARGET_CMD_IS_TAGGED 0x40 - bit NO_CDB_SENT 0x40 - bit DPHASE 0x20 - /* Target flags */ - bit TARG_CMD_PENDING 0x10 - bit CMDPHASE_PENDING 0x08 - bit DPHASE_PENDING 0x04 - bit SPHASE_PENDING 0x02 - bit NO_DISCONNECT 0x01 - } - /* - * Temporary storage for the - * target/channel/lun of a - * reconnecting target - */ - SAVED_SCSIID { - size 1 - } - SAVED_LUN { - size 1 - } - /* - * The last bus phase as seen by the sequencer. - */ - LASTPHASE { - size 1 - bit CDI 0x80 - bit IOI 0x40 - bit MSGI 0x20 - mask PHASE_MASK CDI|IOI|MSGI - mask P_DATAOUT 0x00 - mask P_DATAIN IOI - mask P_DATAOUT_DT P_DATAOUT|MSGO - mask P_DATAIN_DT P_DATAIN|MSGO - mask P_COMMAND CDI - mask P_MESGOUT CDI|MSGI - mask P_STATUS CDI|IOI - mask P_MESGIN CDI|IOI|MSGI - mask P_BUSFREE 0x01 - } - /* - * Base address of our shared data with the kernel driver in host - * memory. This includes the qoutfifo and target mode - * incoming command queue. - */ - SHARED_DATA_ADDR { - size 4 - } - /* - * Pointer to location in host memory for next - * position in the qoutfifo. - */ - QOUTFIFO_NEXT_ADDR { - size 4 - } - /* - * Kernel and sequencer offsets into the queue of - * incoming target mode command descriptors. The - * queue is full when the KERNEL_TQINPOS == TQINPOS. - */ - KERNEL_TQINPOS { - size 1 - } - TQINPOS { - size 1 - } - ARG_1 { - size 1 - mask SEND_MSG 0x80 - mask SEND_SENSE 0x40 - mask SEND_REJ 0x20 - mask MSGOUT_PHASEMIS 0x10 - mask EXIT_MSG_LOOP 0x08 - mask CONT_MSG_LOOP_WRITE 0x04 - mask CONT_MSG_LOOP_READ 0x03 - mask CONT_MSG_LOOP_TARG 0x02 - alias RETURN_1 - } - ARG_2 { - size 1 - alias RETURN_2 - } - - /* - * Snapshot of MSG_OUT taken after each message is sent. - */ - LAST_MSG { - size 1 - } - - /* - * Sequences the kernel driver has okayed for us. This allows - * the driver to do things like prevent initiator or target - * operations. - */ - SCSISEQ_TEMPLATE { - size 1 - bit MANUALCTL 0x40 - bit ENSELI 0x20 - bit ENRSELI 0x10 - mask MANUALP 0x0C - bit ENAUTOATNP 0x02 - bit ALTSTIM 0x01 - } - - /* - * The initiator specified tag for this target mode transaction. - */ - INITIATOR_TAG { - size 1 - } - - SEQ_FLAGS2 { - size 1 - bit SCB_DMA 0x01 - bit TARGET_MSG_PENDING 0x02 - bit SELECTOUT_QFROZEN 0x04 - } - /* - * Target-mode CDB type to CDB length table used - * in non-packetized operation. - */ - CMDSIZE_TABLE { - size 8 - } -} - -/************************* Hardware SCB Definition ****************************/ -scb { - address 0x180 - size 64 - modes 0, 1, 2, 3 - SCB_RESIDUAL_DATACNT { - size 4 - alias SCB_CDB_STORE - } - SCB_RESIDUAL_SGPTR { - size 4 - alias SCB_CDB_PTR - mask SG_ADDR_MASK 0xf8 /* In the last byte */ - bit SG_OVERRUN_RESID 0x02 /* In the first byte */ - bit SG_LIST_NULL 0x01 /* In the first byte */ - } - SCB_SCSI_STATUS { - size 1 - } - SCB_TARGET_PHASES { - size 1 - } - SCB_TARGET_DATA_DIR { - size 1 - } - SCB_TARGET_ITAG { - size 1 - } - SCB_SENSE_BUSADDR { - /* - * Only valid if CDB length is less than 13 bytes or - * we are using a CDB pointer. Otherwise contains - * the last 4 bytes of embedded cdb information. - */ - size 4 - alias SCB_NEXT_COMPLETE - } - SCB_CDB_LEN { - size 1 - bit SCB_CDB_LEN_PTR 0x80 /* CDB in host memory */ - } - SCB_TASK_MANAGEMENT { - size 1 - } - SCB_TAG { - size 2 - } - SCB_NEXT { - alias SCB_NEXT_SCB_BUSADDR - size 2 - } - SCB_NEXT2 { - size 2 - } - SCB_DATAPTR { - size 8 - } - SCB_DATACNT { - /* - * The last byte is really the high address bits for - * the data address. - */ - size 4 - bit SG_LAST_SEG 0x80 /* In the fourth byte */ - mask SG_HIGH_ADDR_BITS 0x7F /* In the fourth byte */ - } - SCB_SGPTR { - size 4 - bit SG_STATUS_VALID 0x04 /* In the first byte */ - bit SG_FULL_RESID 0x02 /* In the first byte */ - bit SG_LIST_NULL 0x01 /* In the first byte */ - } - SCB_CONTROL { - size 1 - bit TARGET_SCB 0x80 - bit DISCENB 0x40 - bit TAG_ENB 0x20 - bit MK_MESSAGE 0x10 - bit STATUS_RCVD 0x08 - bit DISCONNECTED 0x04 - mask SCB_TAG_TYPE 0x03 - } - SCB_SCSIID { - size 1 - mask TID 0xF0 - mask OID 0x0F - } - SCB_LUN { - size 1 - mask LID 0xff - } - SCB_TASK_ATTRIBUTE { - size 1 - alias SCB_NONPACKET_TAG - } - SCB_BUSADDR { - size 4 - } - SCB_DISCONNECTED_LISTS { - size 16 - } -} - -/*********************************** Constants ********************************/ -const SEQ_STACK_SIZE 8 -const MK_MESSAGE_BIT_OFFSET 4 -const TID_SHIFT 4 -const TARGET_CMD_CMPLT 0xfe -const INVALID_ADDR 0x80 -#define SCB_LIST_NULL 0xff - -const CCSGADDR_MAX 0x80 -const CCSCBADDR_MAX 0x80 -const CCSGRAM_MAXSEGS 16 - -/* Selection Timeout Timer Constants */ -const STIMESEL_SHIFT 3 -const STIMESEL_MIN 0x18 -const STIMESEL_BUG_ADJ 0x8 - -/* WDTR Message values */ -const BUS_8_BIT 0x00 -const BUS_16_BIT 0x01 -const BUS_32_BIT 0x02 - -/* Offset maximums */ -const MAX_OFFSET 0xfe -const MAX_OFFSET_PACED 0x7f -const HOST_MSG 0xff - -/* - * The size of our sense buffers. - * Sense buffer mapping can be handled in either of two ways. - * The first is to allocate a dmamap for each transaction. - * Depending on the architecture, dmamaps can be costly. The - * alternative is to statically map the buffers in much the same - * way we handle our scatter gather lists. The driver implements - * the later. - */ -const AHD_SENSE_BUFSIZE 256 - -/* Target mode command processing constants */ -const CMD_GROUP_CODE_SHIFT 0x05 - -const STATUS_BUSY 0x08 -const STATUS_QUEUE_FULL 0x28 -const STATUS_PKT_SENSE 0xFF -const TARGET_DATA_IN 1 - -const SCB_TRANSFER_SIZE 48 -/* PKT_OVERRUN_BUFSIZE must be a multiple of 256 less than 64K */ -const PKT_OVERRUN_BUFSIZE 512 - -/* - * Downloaded (kernel inserted) constants - */ -const SG_PREFETCH_CNT download -const SG_PREFETCH_CNT_LIMIT download -const SG_PREFETCH_ALIGN_MASK download -const SG_PREFETCH_ADDR_MASK download -const SG_SIZEOF download -const PKT_OVERRUN_BUFOFFSET download - -/* - * BIOS SCB offsets - */ -const NVRAM_SCB_OFFSET 0x2C diff --git a/xen/drivers/scsi/aic7xxx/aic79xx.seq b/xen/drivers/scsi/aic7xxx/aic79xx.seq deleted file mode 100644 index 0fb657516c..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic79xx.seq +++ /dev/null @@ -1,1723 +0,0 @@ -/* - * Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD. - * - * Copyright (c) 1994-2001 Justin T. Gibbs. - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $FreeBSD$ - */ - -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#42 $" -PATCH_ARG_LIST = "struct ahd_softc *ahd" - -#include "aic79xx.reg" -#include "scsi_message.h" - -idle_loop: - SET_MODE(M_SCSI, M_SCSI); - test SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus; - test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz idle_loop_checkbus; - cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus; - /* - * ENSELO is cleared by a SELDO, so we must test for SELDO - * one last time. - */ -BEGIN_CRITICAL; - test SSTAT0, SELDO jnz select_out; -END_CRITICAL; - call start_selection; -idle_loop_checkbus: -BEGIN_CRITICAL; - test SSTAT0, SELDO jnz select_out; -END_CRITICAL; - test SSTAT0, SELDI jnz select_in; - test SCSIPHASE, ~DATA_PHASE_MASK jz idle_loop_check_nonpackreq; - test SCSISIGO, ATNO jz idle_loop_check_nonpackreq; - call unexpected_nonpkt_phase_find_ctxt; -idle_loop_check_nonpackreq: - test SSTAT2, NONPACKREQ jz idle_loop_scsi; - call unexpected_nonpkt_phase_find_ctxt; -idle_loop_scsi: -BEGIN_CRITICAL; - test LQISTAT2, LQIGSAVAIL jz idle_loop_service_fifos; - /* - * We have received good status for this transaction. There may - * still be data in our FIFOs draining to the host. Setup - * monitoring of the draining process or complete the SCB. - */ -good_status_IU_done: - bmov SCBPTR, GSFIFO, 2; - clr SCB_SCSI_STATUS; - or SCB_CONTROL, STATUS_RCVD; - - /* - * Since this status did not consume a FIFO, we have to - * be a bit more dilligent in how we check for FIFOs pertaining - * to this transaction. There are three states that a FIFO still - * transferring data may be in. - * - * 1) Configured and draining to the host, with a pending CLRCHN. - * 2) Configured and draining to the host, no pending CLRCHN. - * 3) Pending cfg4data, fifo not empty. - * - * For case 1, we assume that our DMA post of the completed command - * will occur after the FIFO finishes draining due to the higher - * priority of data FIFO transfers relative to command channel - * transfers. - * - * Case 2 can be detected by noticing that a longjmp is active for the - * FIFO and LONGJMP_SCB matches our SCB. In this case, we allow - * the routine servicing the FIFO to complete the SCB. - * - * Case 3 implies either a pending or yet to occur save data - * pointers for this same context in the other FIFO. So, if - * we detect case 2, we will properly defer the post of the SCB - * and achieve the desired result. The pending cfg4data will - * notice that status has been received and complete the SCB. - */ - test SCB_SGPTR, SG_LIST_NULL jz good_status_check_fifos; - /* - * All segments have been loaded (or no data transfer), so - * it is safe to complete the command. Since this was a - * cheap command to check for completion, loop to see if - * more entries can be removed from the GSFIFO. - */ - call complete; -END_CRITICAL; - jmp idle_loop_scsi; -BEGIN_CRITICAL; -good_status_check_fifos: - clc; - bmov ARG_1, SCBPTR, 2; - SET_MODE(M_DFF0, M_DFF0); - call check_fifo; - jc idle_loop_service_fifos; - SET_MODE(M_DFF1, M_DFF1); - call check_fifo; - jc idle_loop_service_fifos; - SET_MODE(M_SCSI, M_SCSI); - call queue_scb_completion; -END_CRITICAL; -idle_loop_service_fifos: - SET_MODE(M_DFF0, M_DFF0); - test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo; - call longjmp; -idle_loop_next_fifo: - SET_MODE(M_DFF1, M_DFF1); - test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_last_fifo_done; - call longjmp; -idle_loop_last_fifo_done: - call idle_loop_cchan; - jmp idle_loop; - -idle_loop_cchan: - SET_MODE(M_CCHAN, M_CCHAN); - test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle; - test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog; - test CCSCBCTL, CCSCBDONE jz return; - /* FALLTHROUGH */ -scbdma_tohost_done: - test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone; - /* - * A complete SCB upload requires no intervention. - * The SCB is already on the COMPLETE_SCB list - * and its completion notification will now be - * handled just like any other SCB. - */ - and CCSCBCTL, ~(CCARREN|CCSCBEN) ret; -fill_qoutfifo_dmadone: - and CCSCBCTL, ~(CCARREN|CCSCBEN); - mvi INTSTAT, CMDCMPLT; - mvi COMPLETE_SCB_DMAINPROG_HEAD[1], SCB_LIST_NULL; - bmov QOUTFIFO_NEXT_ADDR, SCBHADDR, 4; - test QOFF_CTLSTA, SDSCB_ROLLOVR jz return; - bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4 ret; - -fetch_new_scb_inprog: - test CCSCBCTL, ARRDONE jz return; -fetch_new_scb_done: - and CCSCBCTL, ~(CCARREN|CCSCBEN); - bmov REG0, SCBPTR, 2; - /* Update the next SCB address to download. */ - bmov NEXT_QUEUED_SCB_ADDR, SCB_NEXT_SCB_BUSADDR, 4; - mvi SCB_NEXT[1], SCB_LIST_NULL; - mvi SCB_NEXT2[1], SCB_LIST_NULL; - /* - * SCBs that want to send messages are always - * queued independently. This ensures that they - * are at the head of the SCB list to select out - * to a target and we will see the MK_MESSAGE flag. - */ - test SCB_CONTROL, MK_MESSAGE jnz first_new_target_scb; - shr SINDEX, 3, SCB_SCSIID; - and SINDEX, ~0x1; - mvi SINDEX[1], (WAITING_SCB_TAILS >> 8); - bmov DINDEX, SINDEX, 2; - bmov SCBPTR, SINDIR, 2; - bmov DINDIR, REG0, 2; - cmp SCBPTR[1], SCB_LIST_NULL je first_new_target_scb; - bmov SCB_NEXT, REG0, 2; -fetch_new_scb_fini: - /* Increment our position in the QINFIFO. */ - mov NONE, SNSCB_QOFF ret; -first_new_target_scb: - cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je first_new_scb; - bmov SCBPTR, WAITING_TID_TAIL, 2; - bmov SCB_NEXT2, REG0, 2; - bmov WAITING_TID_TAIL, REG0, 2; - /* Increment our position in the QINFIFO. */ - mov NONE, SNSCB_QOFF ret; -first_new_scb: - bmov WAITING_TID_HEAD, REG0, 2; - bmov WAITING_TID_TAIL, REG0, 2; - /* Increment our position in the QINFIFO. */ - mov NONE, SNSCB_QOFF ret; - -scbdma_idle: - /* - * Give precedence to downloading new SCBs to execute - * unless select-outs are currently frozen. - * XXX Use a timer to prevent completion starvation. - */ - test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz . + 2; -BEGIN_CRITICAL; - test QOFF_CTLSTA, NEW_SCB_AVAIL jnz fetch_new_scb; - cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne dma_complete_scb; - cmp COMPLETE_SCB_HEAD[1], SCB_LIST_NULL je return; - /* FALLTHROUGH */ -fill_qoutfifo: - /* - * Keep track of the SCBs we are dmaing just - * in case the DMA fails or is aborted. - */ - bmov COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2; - mvi CCSCBCTL, CCSCBRESET; - bmov SCBHADDR, QOUTFIFO_NEXT_ADDR, 4; - bmov CCSCBRAM, COMPLETE_SCB_HEAD, 2; - bmov SCBPTR, COMPLETE_SCB_HEAD, 2; - jmp fill_qoutfifo_first_entry; -fill_qoutfifo_loop: - bmov CCSCBRAM, SCB_NEXT_COMPLETE, 2; - bmov SCBPTR, SCB_NEXT_COMPLETE, 2; -fill_qoutfifo_first_entry: - mov NONE, SDSCB_QOFF; - cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je fill_qoutfifo_done; - cmp CCSCBADDR, CCSCBADDR_MAX je fill_qoutfifo_done; - test QOFF_CTLSTA, SDSCB_ROLLOVR jz fill_qoutfifo_loop; -fill_qoutfifo_done: - mov SCBHCNT, CCSCBADDR; - mvi CCSCBCTL, CCSCBEN|CCSCBRESET; - bmov COMPLETE_SCB_HEAD, SCB_NEXT_COMPLETE, 2; - mvi SCB_NEXT_COMPLETE[1], SCB_LIST_NULL ret; - -fetch_new_scb: - bmov SCBHADDR, NEXT_QUEUED_SCB_ADDR, 4; - mvi CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET jmp dma_scb; -dma_complete_scb: - bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2; - bmov SCBHADDR, SCB_BUSADDR, 4; - mvi CCARREN|CCSCBEN|CCSCBRESET call dma_scb; - /* - * Now that we've started the DMA, push us onto - * the normal completion queue to have our SCBID - * posted to the kernel. - */ - bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; - bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; - bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; -END_CRITICAL; - -/* - * Either post or fetch an SCB from host memory. The caller - * is responsible for polling for transfer completion. - * - * Prerequisits: Mode == M_CCHAN - * SINDEX contains CCSCBCTL flags - * SCBHADDR set to Host SCB address - * SCBPTR set to SCB src location on "push" operations - */ -SET_SRC_MODE M_CCHAN; -SET_DST_MODE M_CCHAN; -dma_scb: - mvi SCBHCNT, SCB_TRANSFER_SIZE; - mov CCSCBCTL, SINDEX; - or SEQ_FLAGS2, SCB_DMA ret; - -BEGIN_CRITICAL; -setjmp_setscb: - bmov LONGJMP_SCB, SCBPTR, 2; -setjmp: - bmov LONGJMP_ADDR, STACK, 2 ret; -setjmp_inline: - bmov LONGJMP_ADDR, STACK, 2; -longjmp: - bmov STACK, LONGJMP_ADDR, 2 ret; -END_CRITICAL; - -/************************ Packetized LongJmp Routines *************************/ -/* - * Must disable interrupts when setting the mode pointer - * register as an interrupt occurring mid update will - * fail to store the new mode value for restoration on - * an iret. - */ -set_mode_work_around: - mvi SEQINTCTL, INTVEC1DSL; - mov MODE_PTR, SINDEX; - clr SEQINTCTL ret; - -SET_SRC_MODE M_SCSI; -SET_DST_MODE M_SCSI; -start_selection: -BEGIN_CRITICAL; - if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) { - /* - * Razor #494 - * Rev A hardware fails to update LAST/CURR/NEXTSCB - * correctly after a packetized selection in several - * situations: - * - * 1) If only one command existed in the the queue, the - * LAST/CURR/NEXTSCB are unchanged. - * - * 2) In a non QAS, protocol allowed phase change, - * the queue is shifted 1 too far. LASTSCB is - * the last SCB that was correctly processed. - * - * 3) In the QAS case, if the full list of commands - * was successfully sent, NEXTSCB is NULL and neither - * CURRSCB nor LASTSCB can be trusted. We must - * manually walk the list counting MAXCMDCNT elements - * to find the last SCB that was sent correctly. - * - * To simplify the workaround for this bug in SELDO - * handling, we initialize LASTSCB prior to enabling - * selection so we can rely on it even for case #1 above. - */ - bmov LASTSCB, WAITING_TID_HEAD, 2; - } - bmov CURRSCB, WAITING_TID_HEAD, 2; - bmov SCBPTR, WAITING_TID_HEAD, 2; - shr SELOID, 4, SCB_SCSIID; - /* - * If we want to send a message to the device, ensure - * we are selecting with atn irregardless of our packetized - * agreement. Since SPI4 only allows target reset or PPR - * messages if this is a packetized connection, the change - * to our negotiation table entry for this selection will - * be cleared when the message is acted on. - */ - test SCB_CONTROL, MK_MESSAGE jz . + 3; - mov NEGOADDR, SELOID; - or NEGCONOPTS, ENAUTOATNO; - or SCSISEQ0, ENSELO ret; -END_CRITICAL; - -/* - * Allocate a FIFO for a non-packetized transaction. - * For some reason unkown to me, both FIFOs must be free before we - * can allocate a FIFO for a non-packetized transaction. This - * may be fixed in Rev B. - */ -allocate_fifo_loop: - /* - * Do whatever work is required to free a FIFO. - */ - SET_MODE(M_DFF0, M_DFF0); - test LONGJMP_ADDR[1], INVALID_ADDR jnz . + 2; - call longjmp; - SET_MODE(M_DFF1, M_DFF1); - test LONGJMP_ADDR[1], INVALID_ADDR jnz . + 2; - call longjmp; - SET_MODE(M_SCSI, M_SCSI); -allocate_fifo: - and A, FIFO0FREE|FIFO1FREE, DFFSTAT; - cmp A, FIFO0FREE|FIFO1FREE jne allocate_fifo_loop; -take_fifo: - bmov ARG_1, SCBPTR, 2; - or DFFSTAT, CURRFIFO; - SET_MODE(M_DFF1, M_DFF1); - bmov SCBPTR, ARG_1, 2 ret; - -/* - * We have been reselected as an initiator - * or selected as a target. - */ -SET_SRC_MODE M_SCSI; -SET_DST_MODE M_SCSI; -select_in: - or SXFRCTL0, SPIOEN; - and SAVED_SCSIID, SELID_MASK, SELID; - and A, OID, IOWNID; - or SAVED_SCSIID, A; - mvi CLRSINT0, CLRSELDI; - jmp ITloop; - -/* - * We have successfully selected out. - * - * Clear SELDO. - * Dequeue all SCBs sent from the waiting queue - * Requeue all SCBs *not* sent to the tail of the waiting queue - * Take Razor #494 into account for above. - * - * In Packetized Mode: - * Return to the idle loop. Our interrupt handler will take - * care of any incoming L_Qs. - * - * In Non-Packetize Mode: - * Continue to our normal state machine. - */ -SET_SRC_MODE M_SCSI; -SET_DST_MODE M_SCSI; -select_out: -BEGIN_CRITICAL; - /* Clear out all SCBs that have been successfully sent. */ - if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) { - /* - * For packetized, the LQO manager clears ENSELO on - * the assertion of SELDO. If we are non-packetized, - * LASTSCB and CURRSCB are acuate. - */ - test SCSISEQ0, ENSELO jnz use_lastscb; - - /* - * The update is correct for LQOSTAT1 errors. All - * but LQOBUSFREE are handled by kernel interrupts. - * If we see LQOBUSFREE, return to the idle loop. - * Once we are out of the select_out critical section, - * the kernel will cleanup the LQOBUSFREE and we will - * eventually restart the selection if appropriate. - */ - test LQOSTAT1, LQOBUSFREE jnz idle_loop; - - /* - * On a phase change oustside of packet boundaries, - * LASTSCB points to the currently active SCB context - * on the bus. - */ - test LQOSTAT2, LQOPHACHGOUTPKT jnz use_lastscb; - - /* - * If the hardware has traversed the whole list, NEXTSCB - * will be NULL, CURRSCB and LASTSCB cannot be trusted, - * but MAXCMDCNT is accurate. If we stop part way through - * the list or only had one command to issue, NEXTSCB[1] is - * not NULL and LASTSCB is the last command to go out. - */ - cmp NEXTSCB[1], SCB_LIST_NULL jne use_lastscb; - - /* - * Brute force walk. - */ - bmov SCBPTR, WAITING_TID_HEAD, 2; - mvi SEQINTCTL, INTVEC1DSL; - mvi MODE_PTR, MK_MODE(M_CFG, M_CFG); - mov A, MAXCMDCNT; - mvi MODE_PTR, MK_MODE(M_SCSI, M_SCSI); - clr SEQINTCTL; -find_lastscb_loop: - dec A; - test A, 0xFF jz found_last_sent_scb; - bmov SCBPTR, SCB_NEXT, 2; - jmp find_lastscb_loop; -use_lastscb: - bmov SCBPTR, LASTSCB, 2; -found_last_sent_scb: - bmov CURRSCB, SCBPTR, 2; -curscb_ww_done: - } else { - /* - * Untested - Verify with Rev B. - */ - bmov SCBPTR, CURRSCB, 2; - } - /* - * Requeue any SCBs not sent, to the tail of the waiting Q. - */ - cmp SCB_NEXT[1], SCB_LIST_NULL je select_out_list_done; - - /* - * We know that neither the per-TID list nor the list of - * TIDs is empty. Use this knowledge to our advantage. - */ - bmov REG0, SCB_NEXT, 2; - bmov SCBPTR, WAITING_TID_TAIL, 2; - bmov SCB_NEXT2, REG0, 2; - bmov WAITING_TID_TAIL, REG0, 2; - jmp select_out_inc_tid_q; - -select_out_list_done: - /* - * The whole list made it. Just clear our TID's tail pointer - * unless we were queued independently due to our need to - * send a message. - */ - test SCB_CONTROL, MK_MESSAGE jnz select_out_inc_tid_q; - shr DINDEX, 3, SCB_SCSIID; -/* XXX When we switch to SCB_SELOID, put +1 in addition below. */ - or DINDEX, 1; /* Want only the second byte */ - mvi DINDEX[1], ((WAITING_SCB_TAILS) >> 8); - mvi DINDIR, SCB_LIST_NULL; -select_out_inc_tid_q: - bmov SCBPTR, WAITING_TID_HEAD, 2; - bmov WAITING_TID_HEAD, SCB_NEXT2, 2; - cmp WAITING_TID_HEAD[1], SCB_LIST_NULL jne . + 2; - mvi WAITING_TID_TAIL[1], SCB_LIST_NULL; - bmov SCBPTR, CURRSCB, 2; -END_CRITICAL; - - mvi CLRSINT0, CLRSELDO; - - test LQOSTAT2, LQOPHACHGOUTPKT jnz unexpected_nonpkt_phase; - test LQOSTAT1, LQOPHACHGINPKT jnz unexpected_nonpkt_phase; - - /* - * If this is a packetized connection, return to our - * idle_loop and let our interrupt handler deal with - * any connection setup/teardown issues. The only - * exception is the case of MK_MESSAGE SCBs. In the - * A, the LQO manager transitions to LQOSTOP0 even if - * we have selected out with ATN asserted and the target - * REQs in a non-packet phase. - */ - if ((ahd->bugs & AHD_LQO_ATNO_BUG) != 0) { - test SCB_CONTROL, MK_MESSAGE jz select_out_no_message; - test SCSISIGO, ATNO jnz select_out_non_packetized; -select_out_no_message: - } - test LQOSTAT2, LQOSTOP0 jnz idle_loop; - -select_out_non_packetized: - /* Non packetized request. */ - and SCSISEQ0, ~ENSELO; - mov SAVED_SCSIID, SCB_SCSIID; - mov SAVED_LUN, SCB_LUN; - or SXFRCTL0, SPIOEN; - - /* - * As soon as we get a successful selection, the target - * should go into the message out phase since we have ATN - * asserted. - */ - mvi MSG_OUT, MSG_IDENTIFYFLAG; - mvi SEQ_FLAGS, NO_CDB_SENT; - - /* - * Main loop for information transfer phases. Wait for the - * target to assert REQ before checking MSG, C/D and I/O for - * the bus phase. - */ -mesgin_phasemis: -ITloop: - call phase_lock; - - mov A, LASTPHASE; - - test A, ~P_DATAIN_DT jz p_data; - cmp A,P_COMMAND je p_command; - cmp A,P_MESGOUT je p_mesgout; - cmp A,P_STATUS je p_status; - cmp A,P_MESGIN je p_mesgin; - - mvi SEQINTCODE, BAD_PHASE; - jmp ITloop; /* Try reading the bus again. */ - -/* - * Command phase. Set up the DMA registers and let 'er rip. - */ -p_command: -SET_SRC_MODE M_DFF1; -SET_DST_MODE M_DFF1; - test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) - jnz p_command_allocate_fifo; - /* - * Command retry. Free our current FIFO and - * re-allocate a FIFO so transfer state is - * reset. - */ - mvi DFFSXFRCTL, RSTCHN|CLRSHCNT; -p_command_allocate_fifo: - call allocate_fifo; - add NONE, -17, SCB_CDB_LEN; - jnc p_command_embedded; -p_command_from_host: - bmov HADDR[0], SCB_CDB_PTR, 11; - mvi SG_CACHE_PRE, LAST_SEG; - mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN); - jmp p_command_loop; -p_command_embedded: - bmov SHCNT[0], SCB_CDB_LEN, 1; - bmov SHCNT[1], ALLZEROS, 2; - bmov DFDAT, SCB_CDB_STORE, 16; - mvi DFCNTRL, SCSIEN; -p_command_loop: - test DFCNTRL, SCSIEN jnz p_command_loop; - /* - * DMA Channel automatically disabled. - * Don't allow a data phase if the command - * was not fully transferred. Make sure that - * we clear the IDENTIFY SEEN flag if a retry - * falls short too. - */ - and SEQ_FLAGS, ~NO_CDB_SENT; - test SSTAT2, SDONE jnz ITloop; - or SEQ_FLAGS, NO_CDB_SENT; - jmp ITloop; - - -/* - * Status phase. Wait for the data byte to appear, then read it - * and store it into the SCB. - */ -SET_SRC_MODE M_SCSI; -SET_DST_MODE M_SCSI; -p_status: - test SEQ_FLAGS,NOT_IDENTIFIED jz p_status_okay; - mvi SEQINTCODE, PROTO_VIOLATION; - jmp mesgin_done; -p_status_okay: - mov SCB_SCSI_STATUS, SCSIDAT; - or SCB_CONTROL, STATUS_RCVD; - jmp ITloop; - -/* - * Message out phase. If MSG_OUT is MSG_IDENTIFYFLAG, build a full - * indentify message sequence and send it to the target. The host may - * override this behavior by setting the MK_MESSAGE bit in the SCB - * control byte. This will cause us to interrupt the host and allow - * it to handle the message phase completely on its own. If the bit - * associated with this target is set, we will also interrupt the host, - * thereby allowing it to send a message on the next selection regardless - * of the transaction being sent. - * - * If MSG_OUT is == HOST_MSG, also interrupt the host and take a message. - * This is done to allow the host to send messages outside of an identify - * sequence while protecting the seqencer from testing the MK_MESSAGE bit - * on an SCB that might not be for the current nexus. (For example, a - * BDR message in responce to a bad reselection would leave us pointed to - * an SCB that doesn't have anything to do with the current target). - * - * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag, - * bus device reset). - * - * When there are no messages to send, MSG_OUT should be set to MSG_NOOP, - * in case the target decides to put us in this phase for some strange - * reason. - */ -p_mesgout_retry: - /* Turn on ATN for the retry */ - mvi SCSISIGO, ATNO; -p_mesgout: - mov SINDEX, MSG_OUT; - cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host; - test SCB_CONTROL,MK_MESSAGE jnz host_message_loop; -p_mesgout_identify: - or SINDEX, MSG_IDENTIFYFLAG|DISCENB, SCB_LUN; - test SCB_CONTROL, DISCENB jnz . + 2; - and SINDEX, ~DISCENB; -/* - * Send a tag message if TAG_ENB is set in the SCB control block. - * Use SCB_NONPACKET_TAG as the tag value. - */ -p_mesgout_tag: - test SCB_CONTROL,TAG_ENB jz p_mesgout_onebyte; - mov SCSIDAT, SINDEX; /* Send the identify message */ - call phase_lock; - cmp LASTPHASE, P_MESGOUT jne p_mesgout_done; - and SCSIDAT,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL; - call phase_lock; - cmp LASTPHASE, P_MESGOUT jne p_mesgout_done; - mov SCB_NONPACKET_TAG jmp p_mesgout_onebyte; -/* - * Interrupt the driver, and allow it to handle this message - * phase and any required retries. - */ -p_mesgout_from_host: - cmp SINDEX, HOST_MSG jne p_mesgout_onebyte; - jmp host_message_loop; - -p_mesgout_onebyte: - mvi CLRSINT1, CLRATNO; - mov SCSIDAT, SINDEX; - -/* - * If the next bus phase after ATN drops is message out, it means - * that the target is requesting that the last message(s) be resent. - */ - call phase_lock; - cmp LASTPHASE, P_MESGOUT je p_mesgout_retry; - -p_mesgout_done: - mvi CLRSINT1,CLRATNO; /* Be sure to turn ATNO off */ - mov LAST_MSG, MSG_OUT; - mvi MSG_OUT, MSG_NOOP; /* No message left */ - jmp ITloop; - -/* - * Message in phase. Bytes are read using Automatic PIO mode. - */ -p_mesgin: - /* read the 1st message byte */ - mvi ACCUM call inb_first; - - test A,MSG_IDENTIFYFLAG jnz mesgin_identify; - cmp A,MSG_DISCONNECT je mesgin_disconnect; - cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs; - cmp ALLZEROS,A je mesgin_complete; - cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs; - cmp A,MSG_IGN_WIDE_RESIDUE je mesgin_ign_wide_residue; - cmp A,MSG_NOOP je mesgin_done; - -/* - * Pushed message loop to allow the kernel to - * run it's own message state engine. To avoid an - * extra nop instruction after signaling the kernel, - * we perform the phase_lock before checking to see - * if we should exit the loop and skip the phase_lock - * in the ITloop. Performing back to back phase_locks - * shouldn't hurt, but why do it twice... - */ -host_message_loop: - call phase_lock; /* Benign the first time through. */ - mvi SEQINTCODE, HOST_MSG_LOOP; - cmp RETURN_1, EXIT_MSG_LOOP je ITloop; - cmp RETURN_1, CONT_MSG_LOOP_WRITE jne . + 3; - mov SCSIDAT, RETURN_2; - jmp host_message_loop; - /* Must be CONT_MSG_LOOP_READ */ - mov NONE, SCSIDAT; /* ACK Byte */ - jmp host_message_loop; - -mesgin_ign_wide_residue: - shr NEGOADDR, 4, SAVED_SCSIID; - test NEGCONOPTS, WIDEXFER jz mesgin_reject; - /* Pull the residue byte */ - mvi REG0 call inb_next; - cmp REG0, 0x01 jne mesgin_reject; - test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 2; - test DATA_COUNT_ODD, 0x1 jz mesgin_done; - mvi SEQINTCODE, IGN_WIDE_RES; - jmp mesgin_done; - -mesgin_reject: - mvi MSG_MESSAGE_REJECT call mk_mesg; -mesgin_done: - mov NONE,SCSIDAT; /*dummy read from latch to ACK*/ - jmp ITloop; - -#define INDEX_DISC_LIST_SCB(target, lun) \ - mov SCBPTR, lun; \ - shr SCBPTR[1], 3, target - -#define INDEX_DISC_LIST(target, lun) \ - INDEX_DISC_LIST_SCB(target, lun); \ - and SINDEX, 0x7, target; \ - shl SINDEX, 1; \ - add SINDEX, (SCB_DISCONNECTED_LISTS & 0xFF); \ - mvi SINDEX[1], ((SCB_DISCONNECTED_LISTS >> 8) & 0xFF) - -mesgin_identify: - /* - * Determine whether a target is using tagged or non-tagged - * transactions by first looking at the transaction stored in - * the per-device, disconnected array. If there is no untagged - * transaction for this target this must be an untagged transaction. - */ - shr SINDEX, 4, SAVED_SCSIID; - and SAVED_LUN, MSG_IDENTIFY_LUNMASK, A; - INDEX_DISC_LIST(SINDEX, SAVED_LUN); - bmov DINDEX, SINDEX, 2; - bmov SCBPTR, SINDIR, 2; - cmp SCBPTR[1], SCB_LIST_NULL je snoop_tag; - test SCB_CONTROL, TAG_ENB jnz snoop_tag; - /* Untagged. Setup the SCB. */ - bmov REG1, SCB_TAG, 4; /* Save SCB_TAG and SCB_NEXT */ - jmp dequeue_first_scb; - -/* - * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message. - * If we get one, we use the tag returned to find the proper - * SCB. The disconnected list contains any outstanding tagged transactions - * where SCB_TAG != SCB_NONPACKET_TAG or SCB_NONPACKET_TAG + 256. - * After receiving the tag, look for the SCB at SCB locations tag and - * tag + 256. If those SCBs do not match, traverse the disconnected - * list until we find the correct SCB. - */ -snoop_tag: - if ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0) { - or SEQ_FLAGS, 0x80; - } - mov NONE, SCSIDAT; /* ACK Identify MSG */ - call phase_lock; - if ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0) { - or SEQ_FLAGS, 0x1; - } - cmp LASTPHASE, P_MESGIN jne not_found_ITloop; - if ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0) { - or SEQ_FLAGS, 0x2; - } - cmp SCSIBUS, MSG_SIMPLE_Q_TAG jne not_found; -get_tag: - /* Save diconnected list head. */ - bmov REG0, SCBPTR, 2; - clr SCBPTR[1]; - mvi SCBPTR call inb_next; /* tag value */ - mov REG1, SCBPTR; -verify_scb: - mov A, REG1; - cmp SCB_NONPACKET_TAG, A jne verify_other_scb; - mov A, SAVED_SCSIID; - cmp SCB_SCSIID, A jne verify_other_scb; - mov A, SAVED_LUN; - cmp SCB_LUN, A je setup_SCB; -verify_other_scb: - xor SCBPTR[1], 1; - test SCBPTR[1], 0xFF jnz verify_scb; - -search_disc_list: - /* Restore disconnected list head. */ - bmov SCBPTR, REG0, 2; - mvi REG0[1], SCB_LIST_NULL; - mov A, REG1; -search_disc_list_loop: - cmp SCB_NONPACKET_TAG, A je dequeue_scb; - bmov REG0, SCBPTR, 2; - bmov SCBPTR, SCB_NEXT, 2; - cmp SCBPTR[1], SCB_LIST_NULL jne search_disc_list_loop; - jmp not_found; - -dequeue_scb: - bmov REG1, SCB_TAG, 4; /* Save SCB_TAG and SCB_NEXT */ - cmp REG0[1], SCB_LIST_NULL jne dequeue_intermediate_SCB; -dequeue_first_scb: - shr SINDEX, 4, SAVED_SCSIID; - INDEX_DISC_LIST_SCB(SINDEX, SAVED_LUN); - /* Update list head. */ - bmov DINDIR, REG2, 2; - jmp dequeue_restore; -dequeue_intermediate_SCB: - bmov SCBPTR, REG0, 2; - bmov SCB_NEXT, REG2, 2; -dequeue_restore: - bmov SCBPTR, REG1, 2; - -/* - * Ensure that the SCB the tag points to is for - * an SCB transaction to the reconnecting target. - */ -setup_SCB: - if ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0) { - or SEQ_FLAGS, 0x10; - } - test SCB_CONTROL,DISCONNECTED jz not_found; - and SCB_CONTROL,~DISCONNECTED; - clr SEQ_FLAGS; /* make note of IDENTIFY */ - test SCB_SGPTR, SG_LIST_NULL jnz . + 2; - call allocate_fifo; -/* mvi SEQINTCODE, PRINT_RESIDUALS; */ - /* See if the host wants to send a message upon reconnection */ - test SCB_CONTROL, MK_MESSAGE jz mesgin_done; - mvi HOST_MSG call mk_mesg; - jmp mesgin_done; - -not_found: - mvi SEQINTCODE, NO_MATCH; - jmp mesgin_done; - -not_found_ITloop: - mvi SEQINTCODE, NO_MATCH; - jmp ITloop; - -/* - * We received a "command complete" message. Put the SCB on the complete - * queue and trigger a completion interrupt via the idle loop. Before doing - * so, check to see if there - * is a residual or the status byte is something other than STATUS_GOOD (0). - * In either of these conditions, we upload the SCB back to the host so it can - * process this information. In the case of a non zero status byte, we - * additionally interrupt the kernel driver synchronously, allowing it to - * decide if sense should be retrieved. If the kernel driver wishes to request - * sense, it will fill the kernel SCB with a request sense command, requeue - * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting - * RETURN_1 to SEND_SENSE. - */ -mesgin_complete: - - /* - * If ATN is raised, we still want to give the target a message. - * Perhaps there was a parity error on this last message byte. - * Either way, the target should take us to message out phase - * and then attempt to complete the command again. We should use a - * critical section here to guard against a timeout triggering - * for this command and setting ATN while we are still processing - * the completion. - test SCSISIGI, ATNI jnz mesgin_done; - */ - - /* - * If the target never sent an identify message but instead went - * to mesgin to give an invalid message, let the host abort us. - */ - test SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT jz . + 3; - mvi SEQINTCODE, PROTO_VIOLATION; - jmp mesgin_done; - - /* - * If the target never gave us status information, have - * the host abort the command. - */ - test SCB_CONTROL, STATUS_RCVD jz . - 2; - - /* - * See if we attempted to deliver a message but the target ingnored us. - */ - test SCB_CONTROL, MK_MESSAGE jz . + 2; - mvi SEQINTCODE, MKMSG_FAILED; - call queue_scb_completion; - jmp await_busfree; - -freeze_queue: - /* Cancel any pending select-out. */ - test SSTAT0, SELDO jnz . + 2; - and SCSISEQ0, ~ENSELO; - mov ACCUM_SAVE, A; - clr A; - add QFREEZE_COUNT, 1; - adc QFREEZE_COUNT[1], A; - or SEQ_FLAGS2, SELECTOUT_QFROZEN; - mov A, ACCUM_SAVE ret; - -queue_arg1_scb_completion: - SET_MODE(M_SCSI, M_SCSI); - bmov SCBPTR, ARG_1, 2; -queue_scb_completion: - test SCB_SCSI_STATUS,0xff jnz bad_status; - /* - * Check for residuals - */ - test SCB_SGPTR, SG_LIST_NULL jnz complete; /* No xfer */ - test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */ - test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb; -complete: - bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; - bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; -bad_status: - cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb; - call freeze_queue; -upload_scb: - bmov SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2; - bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2; - or SCB_SGPTR, SG_STATUS_VALID ret; - -/* - * Is it a disconnect message? Set a flag in the SCB to remind us - * and await the bus going free. If this is an untagged transaction - * store the SCB id for it in our untagged target table for lookup on - * a reselction. - */ -mesgin_disconnect: - /* - * If ATN is raised, we still want to give the target a message. - * Perhaps there was a parity error on this last message byte - * or we want to abort this command. Either way, the target - * should take us to message out phase and then attempt to - * disconnect again. - * XXX - Wait for more testing. - test SCSISIGI, ATNI jnz mesgin_done; - */ - test SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT jz disconnect_allowed; - mvi SEQINTCODE, PROTO_VIOLATION; - jmp mesgin_done; -disconnect_allowed: - or SCB_CONTROL,DISCONNECTED; - test SCB_CONTROL, TAG_ENB jz queue_disc_scb; - mov A, SCB_NONPACKET_TAG; - cmp SCBPTR, A je await_busfree; -queue_disc_scb: - bmov REG0, SCBPTR, 2; - shr SINDEX, 4, SCB_SCSIID; - INDEX_DISC_LIST(SINDEX, SCB_LUN); - bmov DINDEX, SINDEX, 2; - bmov REG1, SINDIR, 2; - bmov DINDIR, REG0, 2; - bmov SCBPTR, REG0, 2; - bmov SCB_NEXT, REG1, 2; - /* FALLTHROUGH */ -await_busfree: - and SIMODE1, ~ENBUSFREE; - mov NONE, SCSIDAT; /* Ack the last byte */ - call clear_target_state; - test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) - jnz await_busfree_not_m_dff; -SET_SRC_MODE M_DFF1; -SET_DST_MODE M_DFF1; -await_busfree_clrchn: - mvi DFFSXFRCTL, CLRCHN; -await_busfree_not_m_dff: - test SSTAT1,REQINIT|BUSFREE jz .; - test SSTAT1, BUSFREE jnz idle_loop; - mvi SEQINTCODE, MISSED_BUSFREE; - - -/* - * Save data pointers message: - * Copying RAM values back to SCB, for Save Data Pointers message, but - * only if we've actually been into a data phase to change them. This - * protects against bogus data in scratch ram and the residual counts - * since they are only initialized when we go into data_in or data_out. - * Ack the message as soon as possible. For chips without S/G pipelining, - * we can only ack the message after SHADDR has been saved. On these - * chips, SHADDR increments with every bus transaction, even PIO. - */ -SET_SRC_MODE M_DFF1; -SET_DST_MODE M_DFF1; -mesgin_sdptrs: - mov NONE,SCSIDAT; /*dummy read from latch to ACK*/ - test SEQ_FLAGS, DPHASE jz ITloop; - call save_pointers; - jmp ITloop; - -save_pointers: - /* - * If we are asked to save our position at the end of the - * transfer, just mark us at the end rather than perform a - * full save. - */ - test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz save_pointers_full; - or SCB_SGPTR, SG_LIST_NULL ret; - -save_pointers_full: - /* - * The SCB_DATAPTR becomes the current SHADDR. - * All other information comes directly from our residual - * state. - */ - bmov SCB_DATAPTR, SHADDR, 8; - bmov SCB_DATACNT, SCB_RESIDUAL_DATACNT, 8 ret; - -/* - * Restore pointers message? Data pointers are recopied from the - * SCB anytime we enter a data phase for the first time, so all - * we need to do is clear the DPHASE flag and let the data phase - * code do the rest. We also reset/reallocate the FIFO to make - * sure we have a clean start for the next data phase. - */ -mesgin_rdptrs: - and SEQ_FLAGS, ~DPHASE; - test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) jnz msgin_rdptrs_get_fifo; - mvi DFFSXFRCTL, RSTCHN|CLRSHCNT; -msgin_rdptrs_get_fifo: - call allocate_fifo; - jmp mesgin_done; - -clear_target_state: - mvi LASTPHASE, P_BUSFREE; - /* clear target specific flags */ - mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret; - -phase_lock: - test SCSIPHASE, 0xFF jz .; -phase_lock_latch_phase: - and LASTPHASE, PHASE_MASK, SCSISIGI ret; - -/* - * Functions to read data in Automatic PIO mode. - * - * An ACK is not sent on input from the target until SCSIDATL is read from. - * So we wait until SCSIDATL is latched (the usual way), then read the data - * byte directly off the bus using SCSIBUSL. When we have pulled the ATN - * line, or we just want to acknowledge the byte, then we do a dummy read - * from SCISDATL. The SCSI spec guarantees that the target will hold the - * data byte on the bus until we send our ACK. - * - * The assumption here is that these are called in a particular sequence, - * and that REQ is already set when inb_first is called. inb_{first,next} - * use the same calling convention as inb. - */ -inb_next: - mov NONE,SCSIDAT; /*dummy read from latch to ACK*/ -inb_next_wait: - /* - * If there is a parity error, wait for the kernel to - * see the interrupt and prepare our message response - * before continuing. - */ - test SCSIPHASE, 0xFF jz .; -inb_next_check_phase: - and LASTPHASE, PHASE_MASK, SCSISIGI; - cmp LASTPHASE, P_MESGIN jne mesgin_phasemis; -inb_first: - clr DINDEX[1]; - mov DINDEX,SINDEX; - mov DINDIR,SCSIBUS ret; /*read byte directly from bus*/ -inb_last: - mov NONE,SCSIDAT ret; /*dummy read from latch to ACK*/ - -mk_mesg: - mvi SCSISIGO, ATNO; - mov MSG_OUT,SINDEX ret; - -SET_SRC_MODE M_DFF1; -SET_DST_MODE M_DFF1; -disable_ccsgen: - test SG_STATE, FETCH_INPROG jz return; - clr SG_STATE; -disable_ccsgen_fetch_done: - clr CCSGCTL ret; - -toggle_dff_mode: - mvi SEQINTCTL, INTVEC1DSL; - xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); - clr SEQINTCTL ret; - -data_group_idle_loop: - mov SAVED_MODE, MODE_PTR; - test SG_STATE, LOADING_NEEDED jz . + 2; - call service_fifo; - call toggle_dff_mode; - test SG_STATE, LOADING_NEEDED jz . + 2; - call service_fifo; - call idle_loop_cchan; - mov SAVED_MODE jmp set_mode_work_around; - -service_fifo: - /* - * Do we have any prefetch left??? - */ - test SG_STATE, SEGS_AVAIL jnz idle_sg_avail; - - /* - * Can this FIFO have access to the S/G cache yet? - */ - test CCSGCTL, SG_CACHE_AVAIL jz return; - - /* Did we just finish fetching segs? */ - cmp CCSGCTL, CCSGEN|SG_CACHE_AVAIL|CCSGDONE - je idle_sgfetch_complete; - - /* Are we actively fetching segments? */ - test CCSGCTL, CCSGEN jnz return; - - /* - * We fetch a "cacheline aligned" and sized amount of data - * so we don't end up referencing a non-existant page. - * Cacheline aligned is in quotes because the kernel will - * set the prefetch amount to a reasonable level if the - * cacheline size is unknown. - */ - mvi SGHCNT, SG_PREFETCH_CNT; - and SGHADDR[0], SG_PREFETCH_ALIGN_MASK, SCB_RESIDUAL_SGPTR; - bmov SGHADDR[1], SCB_RESIDUAL_SGPTR[1], 3; - mvi CCSGCTL, CCSGEN|SG_CACHE_AVAIL|CCSGRESET; - or SG_STATE, FETCH_INPROG ret; -idle_sgfetch_complete: - /* - * Guard against SG_CACHE_AVAIL activating during sg fetch - * request in the other FIFO. - */ - test SG_STATE, FETCH_INPROG jz return; - call disable_ccsgen_fetch_done; - and CCSGADDR, SG_PREFETCH_ADDR_MASK, SCB_RESIDUAL_SGPTR; - mvi SG_STATE, SEGS_AVAIL|LOADING_NEEDED; -idle_sg_avail: - /* Does the hardware have space for another SG entry? */ - test DFSTATUS, PRELOAD_AVAIL jz return; - if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { - bmov HADDR, CCSGRAM, 8; - } else { - bmov HADDR, CCSGRAM, 4; - } - bmov HCNT, CCSGRAM, 3; - test HCNT[0], 0x1 jz . + 2; - xor DATA_COUNT_ODD, 0x1; - bmov SCB_RESIDUAL_DATACNT[3], CCSGRAM, 1; - if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) { - and HADDR[4], SG_HIGH_ADDR_BITS, SCB_RESIDUAL_DATACNT[3]; - } - if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { - /* Skip 4 bytes of pad. */ - add CCSGADDR, 4; - } -sg_advance: - clr A; /* add sizeof(struct scatter) */ - add SCB_RESIDUAL_SGPTR[0],SG_SIZEOF; - adc SCB_RESIDUAL_SGPTR[1],A; - adc SCB_RESIDUAL_SGPTR[2],A; - adc SCB_RESIDUAL_SGPTR[3],A; - mov SINDEX, SCB_RESIDUAL_SGPTR[0]; - test DATA_COUNT_ODD, 0x1 jz . + 2; - or SINDEX, ODD_SEG; - test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 3; - or SINDEX, LAST_SEG; - clr SG_STATE; - mov SG_CACHE_PRE, SINDEX; - /* - * Load the segment. Or in HDMAEN here too - * just in case HDMAENACK has not come true - * by the time this segment is loaded. If - * HDMAENACK is not true, this or will disable - * HDMAEN mid-transfer. We do not want to simply - * mvi our original settings as SCSIEN automatically - * de-asserts and we don't want to accidentally - * re-enable it. - */ - or DFCNTRL, PRELOADEN|HDMAEN; - /* - * Do we have another segment in the cache? - */ - add NONE, SG_PREFETCH_CNT_LIMIT, CCSGADDR; - jnc return; - and SG_STATE, ~SEGS_AVAIL ret; - -/* - * Initialize the DMA address and counter from the SCB. - */ -load_first_seg: - bmov HADDR, SCB_DATAPTR, 11; - and DATA_COUNT_ODD, 0x1, SCB_DATACNT[0]; - and REG0, ~SG_FULL_RESID, SCB_SGPTR[0]; - test SCB_DATACNT[3], SG_LAST_SEG jz . + 2; - or REG0, LAST_SEG; - test DATA_COUNT_ODD, 0x1 jz . + 2; - or REG0, ODD_SEG; - mov SG_CACHE_PRE, REG0; - mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN); - /* - * Since we've are entering a data phase, we will - * rely on the SCB_RESID* fields. Initialize the - * residual and clear the full residual flag. - */ - and SCB_SGPTR[0], ~SG_FULL_RESID; - bmov SCB_RESIDUAL_DATACNT[3], SCB_DATACNT[3], 5; - /* If we need more S/G elements, tell the idle loop */ - test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz . + 2; - mvi SG_STATE, LOADING_NEEDED ret; - clr SG_STATE ret; - -p_data: - test SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT jz p_data_allowed; - mvi SEQINTCODE, PROTO_VIOLATION; -p_data_allowed: - - test SEQ_FLAGS, DPHASE jz data_phase_initialize; - - /* - * If we re-enter the data phase after going through another - * phase, our transfer location has almost certainly been - * corrupted by the interveining, non-data, transfers. Ask - * the host driver to fix us up based on the transfer residual - * unless we already know that we should be bitbucketing. - */ - test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jnz p_data_bitbucket; - mvi SEQINTCODE, PDATA_REINIT; - -p_data_bitbucket: - /* - * Turn on `Bit Bucket' mode, wait until the target takes - * us to another phase, and then notify the host. - */ - test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) - jnz bitbucket_not_m_dff; - /* - * Ensure that any FIFO contents are cleared out and the - * FIFO free'd prior to starting the BITBUCKET. BITBUCKET - * doesn't discard data already in the FIFO. - */ - mvi DFFSXFRCTL, RSTCHN|CLRSHCNT; - SET_MODE(M_SCSI, M_SCSI); -bitbucket_not_m_dff: - or SXFRCTL1,BITBUCKET; - test SCSIPHASE, DATA_PHASE_MASK jnz .; - and SXFRCTL1, ~BITBUCKET; - SET_MODE(M_DFF1, M_DFF1); - mvi SEQINTCODE, DATA_OVERRUN; - jmp ITloop; - -data_phase_initialize: - test SCB_SGPTR[0], SG_LIST_NULL jnz p_data_bitbucket; - call load_first_seg; -data_phase_inbounds: - /* We have seen a data phase at least once. */ - or SEQ_FLAGS, DPHASE; -data_group_dma_loop: - /* - * The transfer is complete if either the last segment - * completes or the target changes phase. Both conditions - * will clear SCSIEN. We test SCSIEN twice during our - * "idle loop" to avoid long delays before we notice the - * SCSIEN transition. - */ - call data_group_idle_loop; - test DFCNTRL, SCSIEN jnz data_group_dma_loop; - -data_group_dmafinish: - /* - * The transfer has terminated either due to a phase - * change, and/or the completion of the last segment. - * We have two goals here. Do as much other work - * as possible while the data fifo drains on a read - * and respond as quickly as possible to the standard - * messages (save data pointers/disconnect and command - * complete) that usually follow a data phase. - */ - call calc_residual; - - /* - * Go ahead and shut down the DMA engine now. - */ - test DFCNTRL, DIRECTION jnz data_phase_finish; -data_group_fifoflush: - if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) { - or DFCNTRL, FIFOFLUSH; - } - /* - * We have enabled the auto-ack feature. This means - * that the controller may have already transferred - * some overrun bytes into the data FIFO and acked them - * on the bus. The only way to detect this situation is - * to wait for LAST_SEG_DONE to come true on a completed - * transfer and then test to see if the data FIFO is - * non-empty. We know there is more data yet to transfer - * if SG_LIST_NULL is not yet set, thus there cannot be - * an overrun. - */ - test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz data_phase_finish; - test SG_CACHE_SHADOW, LAST_SEG_DONE jz .; - test DFSTATUS, FIFOEMP jnz data_phase_finish; - /* Overrun */ - jmp p_data; -data_phase_finish: - /* - * If the target has left us in data phase, loop through - * the dma code again. We will only loop if there is a - * data overrun. - */ - if ((ahd->flags & AHD_TARGETROLE) != 0) { - test SSTAT0, TARGET jnz data_phase_done; - } - if ((ahd->flags & AHD_INITIATORROLE) != 0) { - test SSTAT1, REQINIT jz .; - test SCSIPHASE, DATA_PHASE_MASK jnz p_data; - } - -data_phase_done: - /* Kill off any pending prefetch */ - call disable_ccsgen; - - if ((ahd->flags & AHD_TARGETROLE) != 0) { - test SEQ_FLAGS, DPHASE_PENDING jz ITloop; - /* - and SEQ_FLAGS, ~DPHASE_PENDING; - * For data-in phases, wait for any pending acks from the - * initiator before changing phase. We only need to - * send Ignore Wide Residue messages for data-in phases. - test DFCNTRL, DIRECTION jz target_ITloop; - test SSTAT1, REQINIT jnz .; - test DATA_COUNT_ODD, 0x1 jz target_ITloop; - SET_MODE(M_SCSI, M_SCSI); - test NEGCONOPTS, WIDEXFER jz target_ITloop; - */ - /* - * Issue an Ignore Wide Residue Message. - mvi P_MESGIN|BSYO call change_phase; - mvi MSG_IGN_WIDE_RESIDUE call target_outb; - mvi 1 call target_outb; - jmp target_ITloop; - */ - } else { - jmp ITloop; - } - -/* - * We assume that, even though data may still be - * transferring to the host, that the SCSI side of - * the DMA engine is now in a static state. This - * allows us to update our notion of where we are - * in this transfer. - * - * If, by chance, we stopped before being able - * to fetch additional segments for this transfer, - * yet the last S/G was completely exhausted, - * call our idle loop until it is able to load - * another segment. This will allow us to immediately - * pickup on the next segment on the next data phase. - * - * If we happened to stop on the last segment, then - * our residual information is still correct from - * the idle loop and there is no need to perform - * any fixups. - */ -calc_residual: - test SG_CACHE_SHADOW, LAST_SEG jz residual_before_last_seg; - /* Record if we've consumed all S/G entries */ - test MDFFSTAT, SHVALID jz . + 2; - bmov SCB_RESIDUAL_DATACNT, SHCNT, 3 ret; - or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL ret; -residual_before_last_seg: - test MDFFSTAT, SHVALID jnz sgptr_fixup; - /* - * Can never happen from an interrupt as the packetized - * hardware will only interrupt us once SHVALID or - * LAST_SEG_DONE. - */ - call data_group_idle_loop; - jmp calc_residual; - -sgptr_fixup: - /* - * Fixup the residual next S/G pointer. The S/G preload - * feature of the chip allows us to load two elements - * in addition to the currently active element. We - * store the bottom byte of the next S/G pointer in - * the SG_CACHE_PTR register so we can restore the - * correct value when the DMA completes. If the next - * sg ptr value has advanced to the point where higher - * bytes in the address have been affected, fix them - * too. - */ - test SG_CACHE_SHADOW, 0x80 jz sgptr_fixup_done; - test SCB_RESIDUAL_SGPTR[0], 0x80 jnz sgptr_fixup_done; - add SCB_RESIDUAL_SGPTR[1], -1; - adc SCB_RESIDUAL_SGPTR[2], -1; - adc SCB_RESIDUAL_SGPTR[3], -1; -sgptr_fixup_done: - and SCB_RESIDUAL_SGPTR[0], SG_ADDR_MASK, SG_CACHE_SHADOW; - clr DATA_COUNT_ODD; - test SG_CACHE_SHADOW, ODD_SEG jz . + 2; - or DATA_COUNT_ODD, 0x1; - clr SCB_RESIDUAL_DATACNT[3]; /* We are not the last seg */ - bmov SCB_RESIDUAL_DATACNT, SHCNT, 3 ret; - -export seq_isr: - nop; /* Jumps in the first ISR instruction fail on Rev A. */ - test SEQINTSRC, SAVEPTRS jnz saveptr_intr; - test SEQINTSRC, CFG4DATA jnz cfg4data_intr; - test SEQINTSRC, CFG4ISTAT jnz cfg4istat_intr; - test SEQINTSRC, CFG4ICMD jnz cfg4icmd_intr; - mvi SEQINTCODE, INVALID_SEQINT; - -/* - * There are two types of save pointers interrupts: - * The first is a snapshot save pointers where the current FIFO is not - * active and contains a snapshot of the current poniter information. - * This happens between packets in a stream for a single L_Q. Since we - * are not performing a pointer save, we can safely clear the channel - * so it can be used for other transactions. - * - * The second case is a save pointers on an active FIFO which occurs - * if the target changes to a new L_Q or busfrees/QAS' and the transfer - * has a residual. This should occur coincident with a ctxtdone. We - * disable the interrupt and allow our active routine to handle the - * save. - */ -saveptr_intr: - test DFCNTRL, HDMAENACK jz snapshot_saveptr; - and SEQIMODE, ~ENSAVEPTRS; - or SEQINTCTL, IRET ret; -snapshot_saveptr: - mvi DFFSXFRCTL, CLRCHN; - or SEQINTCTL, IRET ret; - -cfg4data_intr: - test SCB_SGPTR[0], SG_LIST_NULL jnz pkt_handle_overrun; - call load_first_seg; - call pkt_handle_xfer; - or SEQINTCTL, IRET ret; - -cfg4istat_intr: - call freeze_queue; - add NONE, -13, SCB_CDB_LEN; - jnc cfg4istat_have_sense_addr; - test SCB_CDB_LEN, SCB_CDB_LEN_PTR jnz cfg4istat_have_sense_addr; - /* - * Host sets up address/count and enables transfer. - */ - mvi SEQINTCODE, CFG4ISTAT_INTR; - jmp cfg4istat_setup_handler; -cfg4istat_have_sense_addr: - bmov HADDR, SCB_SENSE_BUSADDR, 4; - mvi HCNT[1], (AHD_SENSE_BUFSIZE >> 8); - mvi SG_CACHE_PRE, LAST_SEG; - mvi DFCNTRL, PRELOADEN|SCSIEN|HDMAEN; -cfg4istat_setup_handler: - /* - * Status pkt is transferring to host. - * Wait in idle loop for transfer to complete. - */ - call pkt_handle_status; - or SEQINTCTL, IRET ret; - -/* - * See if the target has gone on in this context creating an - * overrun condition. For the write case, the hardware cannot - * ack bytes until data is provided. So, if the target begins - * another packet without changing contexts, implying we are - * not sitting on a packet boundary, we are in an overrun - * situation. For the read case, the hardware will continue to - * ack bytes into the FIFO, and may even ack the last overrun packet - * into the FIFO. If the FIFO should become non-empty, we are in - * a read overrun case. - */ -#define check_overrun \ - /* Not on a packet boundary. */ \ - test MDFFSTAT, DLZERO jz pkt_handle_overrun; \ - test DFSTATUS, FIFOEMP jz pkt_handle_overrun - -pkt_handle_xfer: - bmov LONGJMP_SCB, SCBPTR, 2; - test SG_STATE, LOADING_NEEDED jz pkt_last_seg; - call setjmp; - test SEQINTSRC, SAVEPTRS jnz pkt_saveptrs; - test SCSIPHASE, ~DATA_PHASE_MASK jz . + 2; - test SCSISIGO, ATNO jnz . + 2; - test SSTAT2, NONPACKREQ jz pkt_service_fifo; - /* - * Defer handling of this NONPACKREQ until we - * can be sure it pertains to this FIFO. SAVEPTRS - * will not be asserted if the NONPACKREQ is for us, - * so we must simulate it if shaddow is valid. If - * shaddow is not valid, keep running this FIFO until we - * have satisfied the transfer by loading segments and - * waiting for either shaddow valid or last_seg_done. - */ - test MDFFSTAT, SHVALID jnz pkt_saveptrs; -pkt_service_fifo: - test SG_STATE, LOADING_NEEDED jnz service_fifo; -pkt_last_seg: - call setjmp; - test SEQINTSRC, SAVEPTRS jnz pkt_saveptrs; - test SG_CACHE_SHADOW, LAST_SEG_DONE jnz last_pkt_done; - test SCSIPHASE, ~DATA_PHASE_MASK jz . + 2; - test SCSISIGO, ATNO jnz . + 2; - test SSTAT2, NONPACKREQ jz return; - test MDFFSTAT, SHVALID jnz pkt_saveptrs; - jmp return; -last_pkt_done: -BEGIN_CRITICAL; - if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) { - or DFCNTRL, FIFOFLUSH; - } - test SCB_CONTROL, STATUS_RCVD jz wait_pkt_end; - check_overrun; - or SCB_SGPTR, SG_LIST_NULL; - /* - * I think it is safe to skip the FIFO check. - * in this case as LAST_SEG_DONE implies - * the other FIFO, if ever active for this transfer, - * has completed. - */ -last_pkt_queue_scb: - or LONGJMP_ADDR[1], INVALID_ADDR; - bmov ARG_1, SCBPTR, 2; - mvi DFFSXFRCTL, CLRCHN; - jmp queue_arg1_scb_completion; - -last_pkt_complete: - bmov ARG_1, SCBPTR, 2; - mvi DFFSXFRCTL, CLRCHN; -check_other_fifo: - clc; - call toggle_dff_mode; - call check_fifo; - jnc queue_arg1_scb_completion; -return: - ret; - -wait_pkt_end: - call setjmp; -END_CRITICAL; -wait_pkt_end_loop: - test SEQINTSRC, CTXTDONE jnz pkt_end; - check_overrun; - test SSTAT2, NONPACKREQ jz return; - test SEQINTSRC, CTXTDONE jz unexpected_nonpkt_phase; -pkt_end: -BEGIN_CRITICAL; - check_overrun; - or LONGJMP_ADDR[1], INVALID_ADDR; - or SCB_SGPTR, SG_LIST_NULL; - test SCB_CONTROL, STATUS_RCVD jnz last_pkt_complete; - mvi DFFSXFRCTL, CLRCHN ret; -END_CRITICAL; - -/* - * Either a SAVEPTRS interrupt condition is pending for this FIFO - * or we have a pending nonpackreq for this FIFO. We differentiate - * between the two by capturing the state of the SAVEPTRS interrupt - * prior to clearing and handling the common code of these two cases. - */ -pkt_saveptrs: -BEGIN_CRITICAL; - if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) { - or DFCNTRL, FIFOFLUSH; - } - mov REG0, SEQINTSRC; - mvi CLRSEQINTSRC, CLRSAVEPTRS; - call calc_residual; - call save_pointers; - call disable_ccsgen; - or SEQIMODE, ENSAVEPTRS; - or LONGJMP_ADDR[1], INVALID_ADDR; -pkt_saveptrs_check_status: - test REG0, SAVEPTRS jz unexpected_nonpkt_phase; - test SCB_CONTROL, STATUS_RCVD jz pkt_saveptrs_clrchn; - jmp last_pkt_complete; -pkt_saveptrs_clrchn: - mvi DFFSXFRCTL, CLRCHN ret; -END_CRITICAL; - -check_status_overrun: - test SHCNT[2], 0xFF jz status_IU_done; - mvi SEQINTCODE, STATUS_OVERRUN; - jmp status_IU_done; -pkt_handle_status: - call setjmp_setscb; - test MDFFSTAT, LASTSDONE jnz check_status_overrun; - test SEQINTSRC, CTXTDONE jz return; -status_IU_done: -BEGIN_CRITICAL; - if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) { - or DFCNTRL, FIFOFLUSH; - } - or LONGJMP_ADDR[1], INVALID_ADDR; - mvi SCB_SCSI_STATUS, STATUS_PKT_SENSE; - or SCB_CONTROL, STATUS_RCVD; - jmp last_pkt_complete; -END_CRITICAL; - -SET_SRC_MODE M_DFF0; -SET_DST_MODE M_DFF0; -BEGIN_CRITICAL; -check_fifo: - test LONGJMP_ADDR[1], INVALID_ADDR jnz return; - mov A, ARG_2; - cmp LONGJMP_SCB[1], A jne return; - mov A, ARG_1; - cmp LONGJMP_SCB[0], A jne return; - stc ret; -END_CRITICAL; - -/* - * Nonpackreq is a polled status. It can come true in three situations: - * we have received an L_Q, we have sent one or more L_Qs, or there is no - * L_Q context associated with this REQ (REQ occurs immediately after a - * (re)selection). Routines that know that the context responsible for this - * nonpackreq call directly into unexpected_nonpkt_phase. In the case of the - * top level idle loop, we exhaust all active contexts prior to determining that - * we simply do not have the full I_T_L_Q for this phase. - */ -unexpected_nonpkt_phase_find_ctxt: - /* - * This nonpackreq is most likely associated with one of the tags - * in a FIFO or an outgoing LQ. Only treat it as an I_T only - * nonpackreq if we've cleared out the FIFOs and handled any - * pending SELDO. - */ -SET_SRC_MODE M_SCSI; -SET_DST_MODE M_SCSI; - and A, FIFO1FREE|FIFO0FREE, DFFSTAT; - cmp A, FIFO1FREE|FIFO0FREE jne return; - test SSTAT0, SELDO jnz return; - mvi SCBPTR[1], SCB_LIST_NULL; -unexpected_nonpkt_phase: - test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) jnz . + 3; -SET_SRC_MODE M_DFF0; -SET_DST_MODE M_DFF0; - or LONGJMP_ADDR[1], INVALID_ADDR; - mvi DFFSXFRCTL, CLRCHN; - mvi CLRSINT2, CLRNONPACKREQ; - test SCSIPHASE, ~(MSG_IN_PHASE|MSG_OUT_PHASE) jnz illegal_phase; - mvi SEQINTCODE, ENTERING_NONPACK; - jmp ITloop; - -illegal_phase: - mvi SEQINTCODE, ILLEGAL_PHASE; - jmp ITloop; - -/* - * We have entered an overrun situation. If we have working - * BITBUCKET, flip that on and let the hardware eat any overrun - * data. Otherwise use an overrun buffer in the host to simulate - * BITBUCKET. - */ -pkt_handle_overrun: - mvi SEQINTCODE, CFG4OVERRUN; - call freeze_queue; - if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0) { - SET_MODE(M_SCSI, M_SCSI); - or SXFRCTL1,BITBUCKET; -SET_SRC_MODE M_DFF1; -SET_DST_MODE M_DFF1; - } else { - call load_overrun_buf; - mvi DFCNTRL, (HDMAEN|SCSIEN|PRELOADEN); - } - call setjmp; - if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) { - test DFSTATUS, PKT_PRELOAD_AVAIL jz overrun_load_done; - call load_overrun_buf; - or DFCNTRL, PRELOADEN; -overrun_load_done: - } - test SEQINTSRC, CTXTDONE jnz pkt_overrun_end; - test SSTAT2, NONPACKREQ jz return; -pkt_overrun_end: - or SCB_RESIDUAL_SGPTR, SG_OVERRUN_RESID; - test SEQINTSRC, CTXTDONE jz unexpected_nonpkt_phase; - test SCB_CONTROL, STATUS_RCVD jnz last_pkt_queue_scb; - mvi DFFSXFRCTL, CLRCHN ret; - -if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) { -load_overrun_buf: - /* - * Load a dummy segment if preload space is available. - */ - mov HADDR[0], SHARED_DATA_ADDR; - add HADDR[1], PKT_OVERRUN_BUFOFFSET, SHARED_DATA_ADDR[1]; - mov ACCUM_SAVE, A; - clr A; - adc HADDR[2], A, SHARED_DATA_ADDR[2]; - adc HADDR[3], A, SHARED_DATA_ADDR[3]; - mov A, ACCUM_SAVE; - bmov HADDR[4], ALLZEROS, 4; - /* PKT_OVERRUN_BUFSIZE is a multiple of 256 */ - clr HCNT[0]; - mvi HCNT[1], ((PKT_OVERRUN_BUFSIZE >> 8) & 0xFF); - clr HCNT[2]; -} - -cfg4icmd_intr: diff --git a/xen/drivers/scsi/aic7xxx/aic79xx_core.c b/xen/drivers/scsi/aic7xxx/aic79xx_core.c deleted file mode 100644 index 92cf80df40..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic79xx_core.c +++ /dev/null @@ -1,8345 +0,0 @@ -/* - * Core routines and tables shareable across OS platforms. - * - * Copyright (c) 1994-2001 Justin T. Gibbs. - * Copyright (c) 2000-2002 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#79 $ - * - * $FreeBSD$ - */ - -#ifdef __linux__ -#include "aic79xx_osm.h" -#include "aic79xx_inline.h" -#include "aicasm/aicasm_insformat.h" -#else -#include -#include -#include -#endif - -/****************************** Softc Data ************************************/ -struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq); - -/***************************** Lookup Tables **********************************/ -char *ahd_chip_names[] = -{ - "NONE", - "aic7901", - "aic7902" -}; -static const u_int num_chip_names = NUM_ELEMENTS(ahd_chip_names); - -/* - * Hardware error codes. - */ -struct ahd_hard_error_entry { - uint8_t errno; - char *errmesg; -}; - -static struct ahd_hard_error_entry ahd_hard_errors[] = { - { DSCTMOUT, "Discard Timer has timed out" }, - { ILLOPCODE, "Illegal Opcode in sequencer program" }, - { SQPARERR, "Sequencer Parity Error" }, - { DPARERR, "Data-path Parity Error" }, - { MPARERR, "Scratch or SCB Memory Parity Error" }, - { CIOPARERR, "CIOBUS Parity Error" }, -}; -static const u_int num_errors = NUM_ELEMENTS(ahd_hard_errors); - -static struct ahd_phase_table_entry ahd_phase_table[] = -{ - { P_DATAOUT, MSG_NOOP, "in Data-out phase" }, - { P_DATAIN, MSG_INITIATOR_DET_ERR, "in Data-in phase" }, - { P_DATAOUT_DT, MSG_NOOP, "in DT Data-out phase" }, - { P_DATAIN_DT, MSG_INITIATOR_DET_ERR, "in DT Data-in phase" }, - { P_COMMAND, MSG_NOOP, "in Command phase" }, - { P_MESGOUT, MSG_NOOP, "in Message-out phase" }, - { P_STATUS, MSG_INITIATOR_DET_ERR, "in Status phase" }, - { P_MESGIN, MSG_PARITY_ERROR, "in Message-in phase" }, - { P_BUSFREE, MSG_NOOP, "while idle" }, - { 0, MSG_NOOP, "in unknown phase" } -}; - -/* - * In most cases we only wish to itterate over real phases, so - * exclude the last element from the count. - */ -static const u_int num_phases = NUM_ELEMENTS(ahd_phase_table) - 1; - -/* Our Sequencer Program */ -#include "aic79xx_seq.h" - -/**************************** Function Declarations ***************************/ -static void ahd_handle_transmission_error(struct ahd_softc *ahd); -static void ahd_handle_lqiphase_error(struct ahd_softc *ahd, - u_int lqistat1); -static int ahd_handle_pkt_busfree(struct ahd_softc *ahd, - u_int busfreetime); -static int ahd_handle_nonpkt_busfree(struct ahd_softc *ahd); -static void ahd_force_renegotiation(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo); - -static struct ahd_tmode_tstate* - ahd_alloc_tstate(struct ahd_softc *ahd, - u_int scsi_id, char channel); -#ifdef AHD_TARGET_MODE -static void ahd_free_tstate(struct ahd_softc *ahd, - u_int scsi_id, char channel, int force); -#endif -static void ahd_devlimited_syncrate(struct ahd_softc *ahd, - struct ahd_initiator_tinfo *, - u_int *period, - u_int *ppr_options, - role_t role); -static void ahd_update_neg_table(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo, - struct ahd_transinfo *tinfo); -static void ahd_update_pending_scbs(struct ahd_softc *ahd); -static void ahd_fetch_devinfo(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo); -static void ahd_scb_devinfo(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo, - struct scb *scb); -static void ahd_setup_initiator_msgout(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo, - struct scb *scb); -static void ahd_build_transfer_msg(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo); -static void ahd_construct_sdtr(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo, - u_int period, u_int offset); -static void ahd_construct_wdtr(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo, - u_int bus_width); -static void ahd_construct_ppr(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo, - u_int period, u_int offset, - u_int bus_width, u_int ppr_options); -static void ahd_clear_msg_state(struct ahd_softc *ahd); -static void ahd_handle_message_phase(struct ahd_softc *ahd); -typedef enum { - AHDMSG_1B, - AHDMSG_2B, - AHDMSG_EXT -} ahd_msgtype; -static int ahd_sent_msg(struct ahd_softc *ahd, ahd_msgtype type, - u_int msgval, int full); -static int ahd_parse_msg(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo); -static int ahd_handle_msg_reject(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo); -static void ahd_handle_ign_wide_residue(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo); -static void ahd_reinitialize_dataptrs(struct ahd_softc *ahd); -static void ahd_handle_devreset(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo, - cam_status status, char *message, - int verbose_level); -#if AHD_TARGET_MODE -static void ahd_setup_target_msgin(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo, - struct scb *scb); -#endif - -static bus_size_t ahd_sglist_size(struct ahd_softc *ahd); -static bus_size_t ahd_sglist_allocsize(struct ahd_softc *ahd); -static bus_dmamap_callback_t - ahd_dmamap_cb; -static void ahd_initialize_hscbs(struct ahd_softc *ahd); -static int ahd_init_scbdata(struct ahd_softc *ahd); -static void ahd_fini_scbdata(struct ahd_softc *ahd); -static void ahd_setup_iocell_workaround(struct ahd_softc *ahd); -static void ahd_iocell_first_selection(struct ahd_softc *ahd); -static void ahd_chip_init(struct ahd_softc *ahd); -static void ahd_qinfifo_requeue(struct ahd_softc *ahd, - struct scb *prev_scb, - struct scb *scb); -static int ahd_qinfifo_count(struct ahd_softc *ahd); -static int ahd_search_scb_list(struct ahd_softc *ahd, int target, - char channel, int lun, u_int tag, - role_t role, uint32_t status, - ahd_search_action action, - u_int *list_head, u_int tid); -static void ahd_stitch_tid_list(struct ahd_softc *ahd, - u_int tid_prev, u_int tid_cur, - u_int tid_next); -static void ahd_add_scb_to_free_list(struct ahd_softc *ahd, - u_int scbid); -static u_int ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid, - u_int prev, u_int next, u_int tid); -static void ahd_reset_current_bus(struct ahd_softc *ahd); -static ahd_callback_t ahd_reset_poll; -#ifdef AHD_DUMP_SEQ -static void ahd_dumpseq(struct ahd_softc *ahd); -#endif -static void ahd_loadseq(struct ahd_softc *ahd); -static int ahd_check_patch(struct ahd_softc *ahd, - struct patch **start_patch, - u_int start_instr, u_int *skip_addr); -static u_int ahd_resolve_seqaddr(struct ahd_softc *ahd, - u_int address); -static void ahd_download_instr(struct ahd_softc *ahd, - u_int instrptr, uint8_t *dconsts); -#ifdef AHD_TARGET_MODE -static void ahd_queue_lstate_event(struct ahd_softc *ahd, - struct ahd_tmode_lstate *lstate, - u_int initiator_id, - u_int event_type, - u_int event_arg); -static void ahd_update_scsiid(struct ahd_softc *ahd, - u_int targid_mask); -static int ahd_handle_target_cmd(struct ahd_softc *ahd, - struct target_cmd *cmd); -#endif - -/******************************** Private Inlines *****************************/ -static __inline void ahd_assert_atn(struct ahd_softc *ahd); -static __inline int ahd_currently_packetized(struct ahd_softc *ahd); -static __inline int ahd_set_active_fifo(struct ahd_softc *ahd); - -static __inline void -ahd_assert_atn(struct ahd_softc *ahd) -{ - ahd_outb(ahd, SCSISIGO, ATNO); -} - -/* - * Determine if the current connection has a packetized - * agreement. This does not necessarily mean that we - * are currently in a packetized transfer. We could - * just as easily be sending or receiving a message. - */ -static __inline int -ahd_currently_packetized(struct ahd_softc *ahd) -{ - ahd_mode_state saved_modes; - int packetized; - - saved_modes = ahd_save_modes(ahd); - if ((ahd->bugs & AHD_PKTIZED_STATUS_BUG) != 0) { - /* - * The packetized bit refers to the last - * connection, not the current one. Check - * for non-zero LQISTATE instead. - */ - ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); - packetized = ahd_inb(ahd, LQISTATE) != 0; - } else { - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - packetized = ahd_inb(ahd, LQISTAT2) & PACKETIZED; - } - ahd_restore_modes(ahd, saved_modes); - return (packetized); -} - -static __inline int -ahd_set_active_fifo(struct ahd_softc *ahd) -{ - u_int active_fifo; - - AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); - active_fifo = ahd_inb(ahd, DFFSTAT) & CURRFIFO; -/* XXX This is a three possition switch in the B. */ - switch (active_fifo) { - case 0: - case 1: - ahd_set_modes(ahd, active_fifo, active_fifo); - return (1); - default: - return (0); - } -} - -/************************* Sequencer Execution Control ************************/ -/* - * Restart the sequencer program from address zero - */ -void -ahd_restart(struct ahd_softc *ahd) -{ - - ahd_pause(ahd); - - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - - /* No more pending messages */ - ahd_clear_msg_state(ahd); - ahd_outb(ahd, SCSISIGO, 0); /* De-assert BSY */ - ahd_outb(ahd, MSG_OUT, MSG_NOOP); /* No message to send */ - ahd_outb(ahd, SXFRCTL1, ahd_inb(ahd, SXFRCTL1) & ~BITBUCKET); - ahd_outb(ahd, SEQINTCTL, 0); - ahd_outb(ahd, LASTPHASE, P_BUSFREE); - ahd_outb(ahd, SEQ_FLAGS, 0); - ahd_outb(ahd, SAVED_SCSIID, 0xFF); - ahd_outb(ahd, SAVED_LUN, 0xFF); - - /* - * Ensure that the sequencer's idea of TQINPOS - * matches our own. The sequencer increments TQINPOS - * only after it sees a DMA complete and a reset could - * occur before the increment leaving the kernel to believe - * the command arrived but the sequencer to not. - */ - ahd_outb(ahd, TQINPOS, ahd->tqinfifonext); - - /* Always allow reselection */ - ahd_outb(ahd, SCSISEQ1, - ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP)); - /* Ensure that no DMA operations are in progress */ - ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); - ahd_outb(ahd, SCBHCNT, 0); - ahd_outb(ahd, CCSCBCTL, CCSCBRESET); - - ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET); - ahd_unpause(ahd); -} - -void -ahd_clear_fifo(struct ahd_softc *ahd, u_int fifo) -{ - ahd_mode_state saved_modes; - -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_FIFOS) != 0) - printf("%s: Clearing FIFO %d\n", ahd_name(ahd), fifo); -#endif - saved_modes = ahd_save_modes(ahd); - ahd_set_modes(ahd, fifo, fifo); - ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT); - if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) - ahd_outb(ahd, CCSGCTL, CCSGRESET); - ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR); - ahd_outb(ahd, SG_STATE, 0); - ahd_restore_modes(ahd, saved_modes); -} - -/************************* Input/Output Queues ********************************/ -void -ahd_run_qoutfifo(struct ahd_softc *ahd) -{ - struct scb *scb; - u_int scb_index; - - ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD); - while (ahd->qoutfifo[ahd->qoutfifonext] != SCB_LIST_NULL_LE) { - - scb_index = ahd_le16toh(ahd->qoutfifo[ahd->qoutfifonext]); - scb = ahd_lookup_scb(ahd, scb_index); - if (scb == NULL) { - printf("%s: WARNING no command for scb %d " - "(cmdcmplt)\nQOUTPOS = %d\n", - ahd_name(ahd), scb_index, - ahd->qoutfifonext); - ahd_dump_card_state(ahd); - ahd->qoutfifonext = AHD_QOUT_WRAP(ahd->qoutfifonext+1); - continue; - } - - if ((ahd->qoutfifonext & 0x01) == 0x01) { - - /* - * Clear 32bits of QOUTFIFO at a time - * so that we don't clobber an incoming - * 16bit DMA to the array on architectures - * that only support 32bit load and store - * operations. - */ - ahd->qoutfifo[ahd->qoutfifonext - 1] = SCB_LIST_NULL_LE; - ahd->qoutfifo[ahd->qoutfifonext] = SCB_LIST_NULL_LE; - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap, - /*offset*/(ahd->qoutfifonext - 1)*2, - /*len*/4, BUS_DMASYNC_PREREAD); - } - ahd->qoutfifonext = AHD_QOUT_WRAP(ahd->qoutfifonext+1); - - ahd_complete_scb(ahd, scb); - } -} - -void -ahd_run_untagged_queues(struct ahd_softc *ahd) -{ - int i; - - for (i = 0; i < 16; i++) - ahd_run_untagged_queue(ahd, &ahd->untagged_queues[i]); -} - -void -ahd_run_untagged_queue(struct ahd_softc *ahd, struct scb_tailq *queue) -{ - struct scb *scb; - - if (ahd->untagged_queue_lock != 0) - return; - - if ((scb = TAILQ_FIRST(queue)) != NULL - && (scb->flags & SCB_ACTIVE) == 0) { - scb->flags |= SCB_ACTIVE; - ahd_queue_scb(ahd, scb); - } -} - -/************************* Interrupt Handling *********************************/ -void -ahd_handle_hwerrint(struct ahd_softc *ahd) -{ - /* - * Some catastrophic hardware error has occurred. - * Print it for the user and disable the controller. - */ - int i; - int error; - - error = ahd_inb(ahd, ERROR); - for (i = 0; i < num_errors; i++) { - if ((error & ahd_hard_errors[i].errno) != 0) - printf("%s: hwerrint, %s\n", - ahd_name(ahd), ahd_hard_errors[i].errmesg); - } - - ahd_dump_card_state(ahd); - panic("BRKADRINT"); - - /* Tell everyone that this HBA is no longer availible */ - ahd_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS, - CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_UNKNOWN, - CAM_NO_HBA); - - /* Tell the system that this controller has gone away. */ - ahd_free(ahd); -} - -void -ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) -{ - u_int seqintcode; - - /* - * Save the sequencer interrupt code and clear the SEQINT - * bit. We will unpause the sequencer, if appropriate, - * after servicing the request. - */ - seqintcode = ahd_inb(ahd, SEQINTCODE); - ahd_outb(ahd, CLRINT, CLRSEQINT); - ahd_update_modes(ahd); -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("%s: Handle Seqint Called for code %d\n", - ahd_name(ahd), seqintcode); -#endif - switch (seqintcode) { - case ENTERING_NONPACK: - { - struct scb *scb; - u_int scbid; - - AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK), - ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK)); - scbid = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scbid); - if (scb == NULL) { - /* - * Somehow need to know if this - * is from a selection or reselection. - * From that, we can termine target - * ID so we at least have an I_T nexus. - */ - } else { - ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid); - ahd_outb(ahd, SAVED_LUN, scb->hscb->lun); - ahd_outb(ahd, SEQ_FLAGS, 0x0); - } - if ((ahd_inb(ahd, LQISTAT2) & LQIPHASE_OUTPKT) != 0 - && (ahd_inb(ahd, SCSISIGO) & ATNO) != 0) { - /* - * Phase change after read stream with - * CRC error with P0 asserted on last - * packet. - */ - printf("Assuming LQIPHASE_NLQ with P0 assertion\n"); - } - printf("Entering NONPACK\n"); - break; - } - case INVALID_SEQINT: - printf("%s: Invalid Sequencer interrupt occurred.\n", - ahd_name(ahd)); - ahd_dump_card_state(ahd); - printf("invalid seqint"); - ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); - break; - case STATUS_OVERRUN: - { - printf("%s: Status Overrun", ahd_name(ahd)); - ahd_dump_card_state(ahd); - ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); - break; - } - case CFG4ISTAT_INTR: - { - struct scb *scb; - u_int scbid; - - ahd_update_modes(ahd); - scbid = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scbid); - if (scb == NULL) { - ahd_dump_card_state(ahd); - printf("CFG4ISTAT: Free SCB %d referenced", scbid); - panic("For safety"); - } - ahd_outq(ahd, HADDR, scb->sense_busaddr); - ahd_outw(ahd, HCNT, AHD_SENSE_BUFSIZE); - ahd_outb(ahd, HCNT + 2, 0); - ahd_outb(ahd, SG_CACHE_PRE, SG_LAST_SEG); - ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN); - break; - } - case ILLEGAL_PHASE: - { - u_int bus_phase; - - bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK; - printf("%s: ILLEGAL_PHASE 0x%x\n", - ahd_name(ahd), bus_phase); - - switch (bus_phase) { - case P_DATAOUT: - case P_DATAIN: - case P_DATAOUT_DT: - case P_DATAIN_DT: - case P_MESGOUT: - case P_STATUS: - case P_MESGIN: - ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); - printf("%s: Issued Bus Reset.\n", ahd_name(ahd)); - break; - case P_COMMAND: - { - struct ahd_devinfo devinfo; - struct scb *scb; - struct ahd_initiator_tinfo *targ_info; - struct ahd_tmode_tstate *tstate; - struct ahd_transinfo *tinfo; - u_int scbid; - - /* - * If a target takes us into the command phase - * assume that it has been externally reset and - * has thus lost our previous packetized negotiation - * agreement. Since we have not sent an identify - * message and may not have fully qualified the - * connection, we change our command to TUR, assert - * ATN and ABORT the task when we go to message in - * phase. The OSM will see the REQUEUE_REQUEST - * status and retry the command. - */ - scbid = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scbid); - if (scb == NULL) { - printf("Invalid phase with no valid SCB. " - "Resetting bus.\n"); - ahd_reset_channel(ahd, 'A', - /*Initiate Reset*/TRUE); - break; - } - ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb), - SCB_GET_TARGET(ahd, scb), - SCB_GET_LUN(scb), - SCB_GET_CHANNEL(ahd, scb), - ROLE_INITIATOR); - targ_info = ahd_fetch_transinfo(ahd, - devinfo.channel, - devinfo.our_scsiid, - devinfo.target, - &tstate); - tinfo = &targ_info->curr; - ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, - AHD_TRANS_ACTIVE|AHD_TRANS_GOAL, - /*paused*/TRUE); - ahd_set_syncrate(ahd, &devinfo, /*period*/0, - /*offset*/0, /*ppr_options*/0, - AHD_TRANS_ACTIVE, /*paused*/TRUE); - ahd_outb(ahd, SCB_CDB_STORE, 0); - ahd_outb(ahd, SCB_CDB_STORE+1, 0); - ahd_outb(ahd, SCB_CDB_STORE+2, 0); - ahd_outb(ahd, SCB_CDB_STORE+3, 0); - ahd_outb(ahd, SCB_CDB_STORE+4, 0); - ahd_outb(ahd, SCB_CDB_STORE+5, 0); - ahd_outb(ahd, SCB_CDB_LEN, 6); - scb->hscb->control &= ~(TAG_ENB|SCB_TAG_TYPE); - scb->hscb->control |= MK_MESSAGE; - ahd_outb(ahd, SCB_CONTROL, scb->hscb->control); - ahd_outb(ahd, MSG_OUT, HOST_MSG); - ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid); - /* - * The lun is 0, regardless of the SCB's lun - * as we have not sent an identify message. - */ - ahd_outb(ahd, SAVED_LUN, 0); - ahd_outb(ahd, SEQ_FLAGS, 0); - ahd_assert_atn(ahd); - scb->flags &= ~(SCB_PACKETIZED); - scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT; - ahd_freeze_devq(ahd, scb); - ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); - ahd_freeze_scb(scb); - - /* - * Allow the sequencer to continue with - * non-pack processing. - */ - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - ahd_outb(ahd, CLRLQOINT1, CLRLQOPHACHGINPKT); - if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) { - ahd_outb(ahd, CLRLQOINT1, 0); - } - printf("Continuing non-pack processing...\n"); - break; - } - } - break; - } - case CFG4OVERRUN: - printf("%s: CFG4OVERRUN mode = %x\n", ahd_name(ahd), - ahd_inb(ahd, MODE_PTR)); - break; - case DUMP_CARD_STATE: - { - ahd_dump_card_state(ahd); - break; - } - case PDATA_REINIT: - { - printf("%s: PDATA_REINIT - DFCNTRL = 0x%x " - "SG_CACHE_SHADOW = 0x%x\n", - ahd_name(ahd), ahd_inb(ahd, DFCNTRL), - ahd_inb(ahd, SG_CACHE_SHADOW)); - ahd_reinitialize_dataptrs(ahd); - break; - } - case HOST_MSG_LOOP: - { - struct ahd_devinfo devinfo; - - /* - * The sequencer has encountered a message phase - * that requires host assistance for completion. - * While handling the message phase(s), we will be - * notified by the sequencer after each byte is - * transfered so we can track bus phase changes. - * - * If this is the first time we've seen a HOST_MSG_LOOP - * interrupt, initialize the state of the host message - * loop. - */ - ahd_fetch_devinfo(ahd, &devinfo); - if (ahd->msg_type == MSG_TYPE_NONE) { - struct scb *scb; - u_int scb_index; - u_int bus_phase; - - bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK; - if (bus_phase != P_MESGIN - && bus_phase != P_MESGOUT) { - printf("ahd_intr: HOST_MSG_LOOP bad " - "phase 0x%x\n", - bus_phase); - /* - * Probably transitioned to bus free before - * we got here. Just punt the message. - */ - ahd_dump_card_state(ahd); - ahd_clear_intstat(ahd); - ahd_restart(ahd); - return; - } - - scb_index = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scb_index); - if (devinfo.role == ROLE_INITIATOR) { - if (bus_phase == P_MESGOUT) - ahd_setup_initiator_msgout(ahd, - &devinfo, - scb); - else { - ahd->msg_type = - MSG_TYPE_INITIATOR_MSGIN; - ahd->msgin_index = 0; - } - } -#if AHD_TARGET_MODE - else { - if (bus_phase == P_MESGOUT) { - ahd->msg_type = - MSG_TYPE_TARGET_MSGOUT; - ahd->msgin_index = 0; - } - else - ahd_setup_target_msgin(ahd, - &devinfo, - scb); - } -#endif - } - - ahd_handle_message_phase(ahd); - break; - } - case NO_MATCH: - { - /* Ensure we don't leave the selection hardware on */ - AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); - ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO); - - printf("%s:%c:%d: no active SCB for reconnecting " - "target - issuing BUS DEVICE RESET\n", - ahd_name(ahd), 'A', ahd_inb(ahd, SELID)); - printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, " - "ARG_1 == 0x%x ACCUM = 0x%x\n", - ahd_inb(ahd, SAVED_SCSIID), ahd_inb(ahd, SAVED_LUN), - ahd_inb(ahd, ARG_1), ahd_inb(ahd, ACCUM)); - printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, " - "SINDEX == 0x%x\n", - ahd_inb(ahd, SEQ_FLAGS), ahd_get_scbptr(ahd), - ahd_find_busy_tcl(ahd, - BUILD_TCL(ahd_inb(ahd, SAVED_SCSIID), - ahd_inb(ahd, SAVED_LUN))), - ahd_inb(ahd, SINDEX)); - printf("SELID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, " - "SCB_CONTROL == 0x%x\n", - ahd_inb(ahd, SELID), ahd_inb_scbram(ahd, SCB_SCSIID), - ahd_inb_scbram(ahd, SCB_LUN), - ahd_inb_scbram(ahd, SCB_CONTROL)); - printf("SCSIBUS[0] == 0x%x, SCSISIGI == 0x%x\n", - ahd_inb(ahd, SCSIBUS), ahd_inb(ahd, SCSISIGI)); - printf("SXFRCTL0 == 0x%x\n", ahd_inb(ahd, SXFRCTL0)); - printf("SEQCTL0 == 0x%x\n", ahd_inb(ahd, SEQCTL0)); - ahd_dump_card_state(ahd); - ahd->msgout_buf[0] = MSG_BUS_DEV_RESET; - ahd->msgout_len = 1; - ahd->msgout_index = 0; - ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT; - ahd_outb(ahd, MSG_OUT, HOST_MSG); - ahd_assert_atn(ahd); - break; - } - case PROTO_VIOLATION: - { - struct scb *scb; - u_int scbid; - u_int scsiid; - u_int target; - u_int seq_flags; - u_int curphase; - int found; - - scbid = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scbid); - scsiid = ahd_inb(ahd, SAVED_SCSIID); - target = SCSIID_TARGET(ahd, scsiid); - seq_flags = ahd_inb(ahd, SEQ_FLAGS); - curphase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK; - if ((seq_flags & NOT_IDENTIFIED) != 0) { - - /* - * The reconnecting target either did not send an - * identify message, or did, but we didn't find an SCB - * to match. - */ - printf("%s:%c:%d: Target did not send an " - "IDENTIFY message. LASTPHASE = 0x%x, " - "SAVED_SCSIID == 0x%x\n", ahd_name(ahd), - 'A', target, ahd_inb(ahd, LASTPHASE), - scsiid); - } else if (scb == NULL) { - /* - * We don't seem to have an SCB active for this - * transaction. Print an error and reset the bus. - */ - printf("%s:%c:%d: No SCB found during protocol " - "violation\n", ahd_name(ahd), 'A', target); - goto proto_violation_reset; - } else if ((seq_flags & NO_CDB_SENT) != 0) { - ahd_print_path(ahd, scb); - printf("No or incomplete CDB sent to device.\n"); - } else if ((ahd_inb(ahd, SCB_CONTROL) & STATUS_RCVD) == 0) { - /* - * The target never bothered to provide status to - * us prior to completing the command. Since we don't - * know the disposition of this command, we must attempt - * to abort it. Assert ATN and prepare to send an abort - * message. - */ - ahd_print_path(ahd, scb); - printf("Completed command without status.\n"); - } else { - ahd_print_path(ahd, scb); - printf("Unknown protocol violation.\n"); - ahd_dump_card_state(ahd); - } - if ((curphase & ~P_DATAIN_DT) == 0) { -proto_violation_reset: - /* - * Target either went directly to data - * phase or didn't respond to our ATN. - * The only safe thing to do is to blow - * it away with a bus reset. - */ - found = ahd_reset_channel(ahd, 'A', TRUE); - printf("%s: Issued Channel %c Bus Reset. " - "%d SCBs aborted\n", ahd_name(ahd), 'A', found); - } else { - /* - * Leave the selection hardware off in case - * this abort attempt will affect yet to - * be sent commands. - */ - ahd_outb(ahd, SCSISEQ0, - ahd_inb(ahd, SCSISEQ0) & ~ENSELO); - ahd_print_path(ahd, scb); - printf("Protocol violation %s. Attempting to abort.\n", - ahd_lookup_phase_entry(curphase)->phasemsg); - scb->flags |= SCB_ABORT; - ahd_assert_atn(ahd); - ahd_outb(ahd, MSG_OUT, HOST_MSG); - } - return; - } - case IGN_WIDE_RES: - { - struct ahd_devinfo devinfo; - - ahd_fetch_devinfo(ahd, &devinfo); - ahd_handle_ign_wide_residue(ahd, &devinfo); - break; - } - case BAD_PHASE: - { - u_int lastphase; - - lastphase = ahd_inb(ahd, LASTPHASE); - printf("%s:%c:%d: unknown scsi bus phase %x, " - "lastphase = 0x%x. Attempting to continue\n", - ahd_name(ahd), 'A', - SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)), - lastphase, ahd_inb(ahd, SCSISIGI)); - break; - } - case MISSED_BUSFREE: - { - u_int lastphase; - - lastphase = ahd_inb(ahd, LASTPHASE); - printf("%s:%c:%d: Missed busfree. " - "Lastphase = 0x%x, Curphase = 0x%x\n", - ahd_name(ahd), 'A', - SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)), - lastphase, ahd_inb(ahd, SCSISIGI)); - ahd_restart(ahd); - return; - } - case DATA_OVERRUN: - { - /* - * When the sequencer detects an overrun, it - * places the controller in "BITBUCKET" mode - * and allows the target to complete its transfer. - * Unfortunately, none of the counters get updated - * when the controller is in this mode, so we have - * no way of knowing how large the overrun was. - */ - struct scb *scb; - u_int scbindex = ahd_get_scbptr(ahd); - u_int lastphase = ahd_inb(ahd, LASTPHASE); - - scb = ahd_lookup_scb(ahd, scbindex); - ahd_print_path(ahd, scb); - printf("data overrun detected %s." - " Tag == 0x%x.\n", - ahd_lookup_phase_entry(lastphase)->phasemsg, - SCB_GET_TAG(scb)); - ahd_print_path(ahd, scb); - printf("%s seen Data Phase. Length = %ld. NumSGs = %d.\n", - ahd_inb(ahd, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't", - ahd_get_transfer_length(scb), scb->sg_count); - ahd_dump_sglist(scb); - - /* - * Set this and it will take effect when the - * target does a command complete. - */ - ahd_freeze_devq(ahd, scb); - ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR); - ahd_freeze_scb(scb); - break; - } - case MKMSG_FAILED: - { - struct ahd_devinfo devinfo; - struct scb *scb; - u_int scbid; - - ahd_fetch_devinfo(ahd, &devinfo); - printf("%s:%c:%d:%d: Attempt to issue message failed\n", - ahd_name(ahd), devinfo.channel, devinfo.target, - devinfo.lun); - scbid = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scbid); - if (scb != NULL - && (scb->flags & SCB_RECOVERY_SCB) != 0) - /* - * Ensure that we didn't put a second instance of this - * SCB into the QINFIFO. - */ - ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb), - SCB_GET_CHANNEL(ahd, scb), - SCB_GET_LUN(scb), SCB_GET_TAG(scb), - ROLE_INITIATOR, /*status*/0, - SEARCH_REMOVE); - ahd_outb(ahd, SCB_CONTROL, - ahd_inb(ahd, SCB_CONTROL) & ~MK_MESSAGE); - break; - } - } - /* - * The sequencer is paused immediately on - * a SEQINT, so we should restart it when - * we're done. - */ - ahd_unpause(ahd); -} - -void -ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) -{ - struct scb *scb; - u_int status0; - u_int status3; - u_int status; - u_int lqistat1; - u_int lqostat0; - u_int scbid; - - ahd_update_modes(ahd); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - - status3 = ahd_inb(ahd, SSTAT3) & (NTRAMPERR|OSRAMPERR); - status0 = ahd_inb(ahd, SSTAT0) & (IOERR|OVERRUN|SELDI|SELDO); - status = ahd_inb(ahd, SSTAT1) & (SELTO|SCSIRSTI|BUSFREE|SCSIPERR); - lqistat1 = ahd_inb(ahd, LQISTAT1); - lqostat0 = ahd_inb(ahd, LQOSTAT0); - if ((status0 & (SELDI|SELDO)) != 0) { - u_int simode0; - - ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); - simode0 = ahd_inb(ahd, SIMODE0); - status0 &= simode0 & (ENSELDO|ENSELDI|IOERR); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - } - scbid = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scbid); - if (scb != NULL - && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0) - scb = NULL; - - /* Make sure the sequencer is in a safe location. */ - ahd_clear_critical_section(ahd); - - if ((status0 & IOERR) != 0) { - int now_lvd; - - now_lvd = ahd_inb(ahd, SBLKCTL) & ENAB40; - printf("%s: Transceiver State Has Changed to %s mode\n", - ahd_name(ahd), now_lvd ? "LVD" : "SE"); - ahd_outb(ahd, CLRSINT0, CLRIOERR); -/* XXX Still True?? */ - /* - * When transitioning to SE mode, the reset line - * glitches, triggering an arbitration bug in some - * Ultra2 controllers. This bug is cleared when we - * assert the reset line. Since a reset glitch has - * already occurred with this transition and a - * transceiver state change is handled just like - * a bus reset anyway, asserting the reset line - * ourselves is safe. - */ - ahd_reset_channel(ahd, 'A', /*Initiate Reset*/now_lvd == 0); - - ahd_pause(ahd); - ahd_setup_iocell_workaround(ahd); - ahd_unpause(ahd); - } else if ((status0 & OVERRUN) != 0) { - printf("%s: SCSI offset overrun detected. Resetting bus.\n", - ahd_name(ahd)); - ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); - } else if ((status & SCSIRSTI) != 0) { - printf("%s: Someone reset channel A\n", ahd_name(ahd)); - ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE); - } else if ((status & SCSIPERR) != 0) { - ahd_handle_transmission_error(ahd); - } else if (lqostat0 != 0) { - printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0); - ahd_outb(ahd, CLRLQOINT0, lqostat0); - if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) { - ahd_outb(ahd, CLRLQOINT1, 0); - } - } else if ((status & SELTO) != 0) { - u_int scbid; - - /* Stop the selection */ - ahd_outb(ahd, SCSISEQ0, 0); - - /* No more pending messages */ - ahd_clear_msg_state(ahd); - - /* Clear interrupt state */ - ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) & ~ENBUSFREE); - ahd_outb(ahd, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR); - - /* - * Although the driver does not care about the - * 'Selection in Progress' status bit, the busy - * LED does. SELINGO is only cleared by a sucessfull - * selection, so we must manually clear it to insure - * the LED turns off just incase no future successful - * selections occur (e.g. no devices on the bus). - */ - ahd_outb(ahd, CLRSINT0, CLRSELINGO); - - scbid = ahd_inw(ahd, WAITING_TID_HEAD); -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_SELTO) != 0) - printf("%s: Saw Selection Timeout for SCB 0x%x\n", - ahd_name(ahd), scbid); -#endif - scb = ahd_lookup_scb(ahd, scbid); - if (scb == NULL) { - printf("%s: ahd_intr - referenced scb not " - "valid during SELTO scb(0x%x)\n", - ahd_name(ahd), scbid); - ahd_dump_card_state(ahd); - panic("For diagnostics"); - } else { - ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT); - ahd_freeze_devq(ahd, scb); - } - ahd_outb(ahd, CLRINT, CLRSCSIINT); - ahd_iocell_first_selection(ahd); - ahd_restart(ahd); - } else if ((status0 & (SELDI|SELDO)) != 0) { - ahd_iocell_first_selection(ahd); - ahd_unpause(ahd); - } else if (status3 != 0) { - printf("%s: SCSI Cell parity error SSTAT3 == 0x%x\n", - ahd_name(ahd), status3); - ahd_outb(ahd, CLRSINT3, status3); - } else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) { - ahd_handle_lqiphase_error(ahd, lqistat1); - } else if ((status & BUSFREE) != 0) { - u_int busfreetime; - u_int lqostat1; - int restart; - int clear_fifo; - int packetized; - u_int mode; - - /* - * Clear our selection hardware as soon as possible. - * We may have an entry in the waiting Q for this target, - * that is affected by this busfree and we don't want to - * go about selecting the target while we handle the event. - */ - ahd_outb(ahd, SCSISEQ0, 0); - - /* - * Determine what we were up to at the time of - * the busfree. - */ - mode = AHD_MODE_SCSI; - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME; - lqostat1 = ahd_inb(ahd, LQOSTAT1); - switch (busfreetime) { - case BUSFREE_DFF0: - case BUSFREE_DFF1: - { - u_int scbid; - struct scb *scb; - - mode = busfreetime == BUSFREE_DFF0 - ? AHD_MODE_DFF0 : AHD_MODE_DFF1; - ahd_set_modes(ahd, mode, mode); - scbid = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scbid); - if (scb == NULL) { - printf("%s: Invalid SCB in DFF%d " - "during unexpected busfree\n", - ahd_name(ahd), mode); - packetized = 0; - } else - packetized = (scb->flags & SCB_PACKETIZED) != 0; - clear_fifo = 1; - break; - } - case BUSFREE_LQO: - clear_fifo = 0; - packetized = 1; - break; - default: - clear_fifo = 0; - packetized = (lqostat1 & LQOBUSFREE) != 0; - if (!packetized - && ahd_inb(ahd, LASTPHASE) == P_BUSFREE) - packetized = 1; - break; - } - -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("Saw Busfree. Busfreetime = 0x%x.\n", - busfreetime); -#endif - /* - * Busfrees that occur in non-packetized phases are - * handled by the nonpkt_busfree handler. - */ - if (packetized && ahd_inb(ahd, LASTPHASE) == P_BUSFREE) { - restart = ahd_handle_pkt_busfree(ahd, busfreetime); - } else { - restart = ahd_handle_nonpkt_busfree(ahd); - } - /* - * Clear the busfree interrupt status. The setting of - * the interrupt is a pulse, so we do not need to muck - * with the ENBUSFREE logic. This also ensures that if - * the bus has moved on to another connection, busfree - * protection is still in force. - */ - ahd_outb(ahd, CLRSINT1, CLRBUSFREE|CLRSCSIPERR); - - if (clear_fifo) - ahd_clear_fifo(ahd, mode); - - ahd_clear_msg_state(ahd); - ahd_outb(ahd, CLRINT, CLRSCSIINT); - if (restart) - ahd_restart(ahd); - else { - ahd_unpause(ahd); - } - } else { - printf("%s: Missing case in ahd_handle_scsiint. status = %x\n", - ahd_name(ahd), status); - printf("%s: lqostat1 == 0x%x, SIMODE1 == 0x%x\n", - ahd_name(ahd), ahd_inb(ahd, LQOSTAT1), - ahd_inb(ahd, SIMODE1)); - ahd_outb(ahd, CLRINT, CLRSCSIINT); - ahd_dump_card_state(ahd); - panic("Missing SCSIINT case"); - ahd_unpause(ahd); - } -} - -static void -ahd_handle_transmission_error(struct ahd_softc *ahd) -{ - u_int lqistat1; - u_int lqistat2; - u_int msg_out; - u_int curphase; - u_int lastphase; - u_int perrdiag; - - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - lqistat1 = ahd_inb(ahd, LQISTAT1) & ~(LQIPHASE_LQ|LQIPHASE_NLQ); - lqistat2 = ahd_inb(ahd, LQISTAT2); - if ((lqistat1 & (LQICRCI_NLQ|LQICRCI_LQ)) == 0 - && (ahd->bugs & AHD_NLQICRC_DELAYED_BUG) != 0) { - u_int lqistate; - - ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); - lqistate = ahd_inb(ahd, LQISTATE); - if ((lqistate >= 0x1E && lqistate <= 0x24) - || (lqistate == 0x29)) { - printf("%s: NLQCRC found via LQISTATE\n", - ahd_name(ahd)); - lqistat1 |= LQICRCI_NLQ; - } - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - } - - ahd_outb(ahd, CLRLQIINT1, lqistat1); - lastphase = ahd_inb(ahd, LASTPHASE); - curphase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK; - perrdiag = ahd_inb(ahd, PERRDIAG); - msg_out = MSG_INITIATOR_DET_ERR; - ahd_outb(ahd, CLRSINT1, CLRSCSIPERR); - printf("%s: Transmission error detected\n", ahd_name(ahd)); - printf("%s: lqistat1 == 0x%x, LASTPHASE == 0x0%x, " - "curphase = 0x%x, perrdiag == 0x%x\n", - ahd_name(ahd), lqistat1, lastphase, curphase, perrdiag); - ahd_dump_card_state(ahd); - if ((lqistat1 & (LQIOVERI_LQ|LQIOVERI_NLQ)) != 0) { - printf("%s: Gross protocol error during incoming " - "packet. lqistat1 == 0x%x. Resetting bus.\n", - ahd_name(ahd), lqistat1); - ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); - return; - } else if ((lqistat1 & LQICRCI_LQ) != 0) { - /* - * A CRC error has been detected on an incoming LQ. - * The bus is currently hung on the last ACK. - * Hit LQIRETRY to release the last ack, and - * wait for the sequencer to determine that ATNO - * is asserted while in message out to take us - * to our host message loop. No NONPACKREQ or - * LQIPHASE type errors will occur in this - * scenario. After this first LQIRETRY, the LQI - * manager will be in ISELO where it will - * happily sit until another packet phase begins. - * Unexpected bus free detection is enabled - * through any phases that occur after we release - * this last ack until the LQI manager sees a - * packet phase. This implies we may have to - * ignore a perfectly valid "unexected busfree" - * after our "initiator detected error" message is - * sent. A busfree is the expected response after - * we tell the target that it's L_Q was corrupted. - * (SPI4R09 10.7.3.3.3) - */ - ahd_outb(ahd, LQCTL2, LQIRETRY); - printf("LQIRetry for LQICRCI_LQ to release ACK\n"); - } else if ((lqistat1 & LQICRCI_NLQ) != 0) { - u_int scbid; - struct scb *scb; - - /* - * We detected a CRC error in a NON-LQ packet. - * The hardware has varying behavior in this situation - * depending on whether this packet was part of a - * stream or not. - * - * PKT by PKT mode: - * The hardware has already acked the complete packet. - * If the target honors our outstanding ATN condition, - * we should be (or soon will be) in MSGOUT phase. - * This will trigger the LQIPHASE_LQ status bit as the - * hardware was expecting another LQ. Unexpected - * busfree detection is enabled. Once LQIPHASE_LQ is - * true (first entry into host message loop is much - * the same), we must clear LQIPHASE_LQ and hit - * LQIRETRY so the hardware is ready to handle - * a future LQ. NONPACKREQ will not be asserted again - * once we hit LQIRETRY until another packet is - * processed. The target may either go busfree - * or start another packet in response to our message. - * - * Read Streaming P0 asserted: - * If we raise ATN and the target completes the entire - * stream (P0 asserted during the last packet), the - * hardware will ack all data and return to the ISTART - * state. When the target reponds to our ATN condition, - * LQIPHASE_LQ will be asserted. We should respond to - * this with an LQIRETRY to prepare for any future - * packets. NONPACKREQ will not be asserted again - * once we hit LQIRETRY until another packet is - * processed. The target may either go busfree or - * start another packet in response to our message. - * Busfree detection is enabled. - * - * Read Streaming P0 not asserted: - * If we raise ATN and the target transitions to - * MSGOUT in or after a packet where P0 is not - * asserted, the hardware will assert LQIPHASE_NLQ. - * We should respond to the LQIPHASE_NLQ with an - * LQICONTINUE. Should the target stay in a non-pkt - * phase after we send our message, the hardware - * will assert LQIPHASE_LQ. Recovery is then just as - * listed above for the read streaming with P0 asserted. - * Busfree detection is enabled. - */ - printf("LQICRC_NLQ\n"); - ahd_set_active_fifo(ahd); - scbid = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scbid); - if (scb == NULL) { - printf("%s: No SCB valid for LQICRC_NLQ. " - "Resetting bus\n", ahd_name(ahd)); - ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); - return; - } - scb->flags |= SCB_TRANSMISSION_ERROR; - } else if ((lqistat1 & LQIBADLQI) != 0) { - printf("Need to handle BADLQI!\n"); - ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); - return; - } else if ((perrdiag & (PARITYERR|LASTPHASE)) == PARITYERR) { - if ((curphase & ~P_DATAIN_DT) != 0) { - /* Ack the byte. So we can continue. */ - printf("Acking %s to clear perror\n", - ahd_lookup_phase_entry(curphase)->phasemsg); - ahd_inb(ahd, SCSIDAT); - } - - if (curphase == P_MESGIN) - msg_out = MSG_PARITY_ERROR; - } - - /* - * We've set the hardware to assert ATN if we - * get a parity error on "in" phases, so all we - * need to do is stuff the message buffer with - * the appropriate message. "In" phases have set - * mesg_out to something other than MSG_NOP. - */ - ahd->send_msg_perror = msg_out; - ahd_outb(ahd, MSG_OUT, HOST_MSG); - ahd_outb(ahd, CLRINT, CLRSCSIINT); - ahd_unpause(ahd); -} - -static void -ahd_handle_lqiphase_error(struct ahd_softc *ahd, u_int lqistat1) -{ - /* - * Clear the sources of the interrupts. - */ - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - ahd_outb(ahd, CLRLQIINT1, lqistat1); - - /* - * If the "illegal" phase changes were in response - * to our ATN to flag a CRC error, AND we ended up - * on packet boundaries, clear the error, restart the - * LQI manager as appropriate, and go on our merry - * way toward sending the message. Otherwise, reset - * the bus to clear the error. - */ - ahd_set_active_fifo(ahd); - if ((ahd_inb(ahd, SCSISIGO) & ATNO) != 0 - && (ahd_inb(ahd, MDFFSTAT) & DLZERO) != 0) { - if ((lqistat1 & LQIPHASE_LQ) != 0) { - printf("LQIRETRY for LQIPHASE_LQ\n"); - ahd_outb(ahd, LQCTL2, LQIRETRY); - } else if ((lqistat1 & LQIPHASE_NLQ) != 0) { - printf("LQICONTINUE for LQIPHASE_NLQ\n"); - ahd_outb(ahd, LQCTL2, LQIRETRY); - } else - panic("ahd_handle_lqiphase_error: No phase errors\n"); - ahd_dump_card_state(ahd); - ahd_outb(ahd, CLRINT, CLRSCSIINT); - ahd_unpause(ahd); - } else { - printf("Reseting Channel for LQI Phase error\n"); - ahd_dump_card_state(ahd); - ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); - } -} - -/* - * Packetized unexpected or expected busfree. - * Entered in MODE_SCSI. - */ -static int -ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime) -{ - u_int lqostat1; - - AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK), - ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK)); - lqostat1 = ahd_inb(ahd, LQOSTAT1); - if ((lqostat1 & LQOBUSFREE) != 0) { - struct scb *scb; - u_int scbid; - u_int waiting_h; - u_int waiting_t; - u_int next; - - if ((busfreetime & BUSFREE_LQO) == 0) - printf("%s: Warning, BUSFREE time is 0x%x. " - "Expected BUSFREE_LQO.\n", - ahd_name(ahd), busfreetime); - - scbid = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scbid); - if (scb == NULL) - panic("SCB not valid during LQOBUSFREE"); - ahd_print_path(ahd, scb); - printf("Probable outgoing LQ CRC error. Retrying command\n"); - - /* - * Return the LQO manager to its idle loop. It will - * not do this automatically if the busfree occurs - * after the first REQ of either the LQ or command - * packet or between the LQ and command packet. - */ - ahd_outb(ahd, LQCTL2, ahd_inb(ahd, LQCTL2) | LQOTOIDLE); - - /* - * Clear the status. - */ - ahd_outb(ahd, CLRLQOINT1, CLRLQOBUSFREE); - if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) { - ahd_outb(ahd, CLRLQOINT1, 0); - } - /* - * The LQO manager detected an unexpected busfree - * either: - * - * 1) During an outgoing LQ. - * 2) After an outgoing LQ but before the first - * REQ of the command packet. - * 3) During an outgoing command packet. - * - * In all cases, CURRSCB is pointing to the - * SCB that encountered the failure. Clean - * up the queue, clear SELDO and LQOBUSFREE, - * and allow the sequencer to restart the select - * out at its lesure. - */ - ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO); - ahd_outb(ahd, CLRSINT0, CLRSELDO); - waiting_h = ahd_inw(ahd, WAITING_TID_HEAD); - if (waiting_h != scbid) { - - ahd_outw(ahd, WAITING_TID_HEAD, scbid); - waiting_t = ahd_inw(ahd, WAITING_TID_TAIL); - next = SCB_LIST_NULL; - if (waiting_t == waiting_h) { - ahd_outw(ahd, WAITING_TID_TAIL, scbid); - } else { - ahd_set_scbptr(ahd, waiting_h); - next = ahd_inw(ahd, SCB_NEXT2); - } - ahd_set_scbptr(ahd, scbid); - ahd_outw(ahd, SCB_NEXT2, next); - } - - /* Return unpausing the sequencer. */ - return (0); - } - if (ahd->src_mode != AHD_MODE_SCSI) { - u_int scbid; - struct scb *scb; - - scbid = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scbid); - ahd_print_path(ahd, scb); - printf("Unexpected PKT busfree condition\n"); - ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb), 'A', - SCB_GET_LUN(scb), SCB_GET_TAG(scb), - ROLE_INITIATOR, CAM_UNEXP_BUSFREE); - - /* Return restarting the sequencer. */ - return (1); - } - printf("%s: Unexpected PKT busfree condition\n", ahd_name(ahd)); - ahd_dump_card_state(ahd); - /* Restart the sequencer. */ - return (1); -} - -/* - * Non-packetized unexpected or expected busfree. - */ -static int -ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) -{ - struct ahd_devinfo devinfo; - struct scb *scb; - u_int lastphase; - u_int saved_scsiid; - u_int saved_lun; - u_int target; - u_int initiator_role_id; - u_int scbid; - int printerror; - - /* - * Look at what phase we were last in. If its message out, - * chances are pretty good that the busfree was in response - * to one of our abort requests. - */ - lastphase = ahd_inb(ahd, LASTPHASE); - saved_scsiid = ahd_inb(ahd, SAVED_SCSIID); - saved_lun = ahd_inb(ahd, SAVED_LUN); - target = SCSIID_TARGET(ahd, saved_scsiid); - initiator_role_id = SCSIID_OUR_ID(saved_scsiid); - ahd_compile_devinfo(&devinfo, initiator_role_id, - target, saved_lun, 'A', ROLE_INITIATOR); - printerror = 1; - - scbid = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scbid); - if (scb != NULL - && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0) - scb = NULL; - - if (lastphase == P_MESGOUT) { - u_int tag; - - tag = SCB_LIST_NULL; - if (ahd_sent_msg(ahd, AHDMSG_1B, MSG_ABORT_TAG, TRUE) - || ahd_sent_msg(ahd, AHDMSG_1B, MSG_ABORT, TRUE)) { - int found; - int sent_msg; - - sent_msg = ahd->msgout_buf[ahd->msgout_index - 1]; - ahd_print_path(ahd, scb); - printf("SCB %d - Abort%s Completed.\n", - SCB_GET_TAG(scb), - sent_msg == MSG_ABORT_TAG ? "" : " Tag"); - - if (sent_msg == MSG_ABORT_TAG) - tag = SCB_GET_TAG(scb); - - if ((scb->flags & SCB_CMDPHASE_ABORT) != 0) { - /* - * This abort is in response to an - * unexpected switch to command phase - * for a packetized connection. Since - * the identify message was never sent, - * "saved lun" is 0. We really want to - * abort only the SCB that encountered - * this error, which could have a different - * lun. The SCB will be retried so the OS - * will see the UA after renegotiating to - * packetized. - */ - tag = SCB_GET_TAG(scb); - saved_lun = scb->hscb->lun; - } - found = ahd_abort_scbs(ahd, target, 'A', saved_lun, - tag, ROLE_INITIATOR, - CAM_REQ_ABORTED); - printf("found == 0x%x\n", found); - printerror = 0; - } else if (ahd_sent_msg(ahd, AHDMSG_1B, - MSG_BUS_DEV_RESET, TRUE)) { -#ifdef __FreeBSD__ - /* - * Don't mark the user's request for this BDR - * as completing with CAM_BDR_SENT. CAM3 - * specifies CAM_REQ_CMP. - */ - if (scb != NULL - && scb->io_ctx->ccb_h.func_code== XPT_RESET_DEV - && ahd_match_scb(ahd, scb, target, 'A', - CAM_LUN_WILDCARD, SCB_LIST_NULL, - ROLE_INITIATOR)) - ahd_set_transaction_status(scb, CAM_REQ_CMP); -#endif - ahd_handle_devreset(ahd, &devinfo, CAM_BDR_SENT, - "Bus Device Reset", - /*verbose_level*/0); - printerror = 0; - } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, FALSE)) { - struct ahd_initiator_tinfo *tinfo; - struct ahd_tmode_tstate *tstate; - - /* - * PPR Rejected. Try non-ppr negotiation - * and retry command. - */ - tinfo = ahd_fetch_transinfo(ahd, devinfo.channel, - devinfo.our_scsiid, - devinfo.target, &tstate); - tinfo->curr.transport_version = 2; - tinfo->goal.transport_version = 2; - tinfo->goal.ppr_options = 0; - ahd_qinfifo_requeue_tail(ahd, scb); - printerror = 0; - } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, FALSE) - || ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, FALSE)) { - /* - * Negotiation Rejected. Go-async and - * retry command. - */ - ahd_set_width(ahd, &devinfo, - MSG_EXT_WDTR_BUS_8_BIT, - AHD_TRANS_CUR|AHD_TRANS_GOAL, - /*paused*/TRUE); - ahd_set_syncrate(ahd, &devinfo, - /*period*/0, /*offset*/0, - /*ppr_options*/0, - AHD_TRANS_CUR|AHD_TRANS_GOAL, - /*paused*/TRUE); - ahd_qinfifo_requeue_tail(ahd, scb); - printerror = 0; - } else if ((ahd->msg_flags & MSG_FLAG_EXPECT_IDE_BUSFREE) != 0 - && ahd_sent_msg(ahd, AHDMSG_1B, - MSG_INITIATOR_DET_ERR, TRUE)) { - -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("Expected IDE Busfree\n"); -#endif - printerror = 0; - } - } else if (lastphase == P_MESGIN) { - - if ((ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0) { - - ahd_freeze_devq(ahd, scb); - ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); - ahd_freeze_scb(scb); - if ((ahd->msg_flags & MSG_FLAG_IU_REQ_CHANGED) != 0) { - ahd_print_path(ahd, scb); - printf("Now %spacketized.\n", - (scb->flags & SCB_PACKETIZED) == 0 - ? "" : "non-"); - ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb), - SCB_GET_CHANNEL(ahd, scb), - SCB_GET_LUN(scb), SCB_LIST_NULL, - ROLE_INITIATOR, CAM_REQ_ABORTED); - } else { -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("PPR Negotiation Busfree.\n"); -#endif - ahd_done(ahd, scb); - } - printerror = 0; - } - } - if (printerror != 0) { - int aborted; - - aborted = 0; - if (scb != NULL) { - u_int tag; - - if ((scb->hscb->control & TAG_ENB) != 0) - tag = SCB_GET_TAG(scb); - else - tag = SCB_LIST_NULL; - ahd_print_path(ahd, scb); - aborted = ahd_abort_scbs(ahd, target, 'A', - SCB_GET_LUN(scb), tag, - ROLE_INITIATOR, - CAM_UNEXP_BUSFREE); - } else { - /* - * We had not fully identified this connection, - * so we cannot abort anything. - */ - printf("%s: ", ahd_name(ahd)); - } - if (lastphase != P_BUSFREE) - ahd_force_renegotiation(ahd, &devinfo); - printf("Unexpected busfree %s, %d SCBs aborted, " - "PRGMCNT == 0x%x\n", - ahd_lookup_phase_entry(lastphase)->phasemsg, - aborted, - ahd_inb(ahd, PRGMCNT) - | (ahd_inb(ahd, PRGMCNT+1) << 8)); - ahd_dump_card_state(ahd); - } - /* Always restart the sequencer. */ - return (1); -} - -/* - * Force renegotiation to occur the next time we initiate - * a command to the current device. - */ -static void -ahd_force_renegotiation(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) -{ - struct ahd_initiator_tinfo *targ_info; - struct ahd_tmode_tstate *tstate; - - printf("Forcing renegotiation (%d:%c:%d)\n", - devinfo->our_scsiid, devinfo->channel, - devinfo->target); - targ_info = ahd_fetch_transinfo(ahd, - devinfo->channel, - devinfo->our_scsiid, - devinfo->target, - &tstate); - ahd_update_neg_request(ahd, devinfo, tstate, - targ_info, /*force*/TRUE); -} - -#define AHD_MAX_STEPS 2000 -void -ahd_clear_critical_section(struct ahd_softc *ahd) -{ - ahd_mode_state saved_modes; - int stepping; - int steps; - u_int simode0; - u_int simode1; - u_int simode3; - u_int lqimode0; - u_int lqimode1; - u_int lqomode0; - u_int lqomode1; - - if (ahd->num_critical_sections == 0) - return; - - stepping = FALSE; - steps = 0; - simode0 = 0; - simode1 = 0; - simode3 = 0; - lqimode0 = 0; - lqimode1 = 0; - lqomode0 = 0; - lqomode1 = 0; - saved_modes = ahd_save_modes(ahd); - for (;;) { - struct cs *cs; - u_int seqaddr; - u_int i; - - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - seqaddr = ahd_inb(ahd, CURADDR) - | (ahd_inb(ahd, CURADDR+1) << 8); - - cs = ahd->critical_sections; - for (i = 0; i < ahd->num_critical_sections; i++, cs++) { - - if (cs->begin < seqaddr && cs->end >= seqaddr) - break; - } - - if (i == ahd->num_critical_sections) - break; - - if (steps > AHD_MAX_STEPS) { - printf("%s: Infinite loop in critical section\n", - ahd_name(ahd)); - ahd_dump_card_state(ahd); - panic("critical section loop"); - } - - steps++; - if (stepping == FALSE) { - - /* - * Disable all interrupt sources so that the - * sequencer will not be stuck by a pausing - * interrupt condition while we attempt to - * leave a critical section. - */ - ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); - simode0 = ahd_inb(ahd, SIMODE0); - simode3 = ahd_inb(ahd, SIMODE3); - lqimode0 = ahd_inb(ahd, LQIMODE0); - lqimode1 = ahd_inb(ahd, LQIMODE1); - lqomode0 = ahd_inb(ahd, LQOMODE0); - lqomode1 = ahd_inb(ahd, LQOMODE1); - ahd_outb(ahd, SIMODE0, 0); - ahd_outb(ahd, SIMODE3, 0); - ahd_outb(ahd, LQIMODE0, 0); - ahd_outb(ahd, LQIMODE1, 0); - ahd_outb(ahd, LQOMODE0, 0); - ahd_outb(ahd, LQOMODE1, 0); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - simode1 = ahd_inb(ahd, SIMODE1); - ahd_outb(ahd, SIMODE1, 0); - ahd_outb(ahd, CLRINT, CLRSCSIINT); - ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) | STEP); - stepping = TRUE; - } - ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode); - ahd_outb(ahd, HCNTRL, ahd->unpause); - do { - ahd_delay(200); - } while (!ahd_is_paused(ahd)); - ahd_update_modes(ahd); - } - if (stepping) { - ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); - ahd_outb(ahd, SIMODE0, simode0); - ahd_outb(ahd, SIMODE3, simode3); - ahd_outb(ahd, LQIMODE0, lqimode0); - ahd_outb(ahd, LQIMODE1, lqimode1); - ahd_outb(ahd, LQOMODE0, lqomode0); - ahd_outb(ahd, LQOMODE1, lqomode1); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - ahd_outb(ahd, SIMODE1, simode1); - ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) & ~STEP); - } - ahd_restore_modes(ahd, saved_modes); -} - -/* - * Clear any pending interrupt status. - */ -void -ahd_clear_intstat(struct ahd_softc *ahd) -{ - /* Clear any interrupt conditions this may have caused */ - ahd_outb(ahd, CLRSINT1, CLRSELTIMEO|CLRATNO|CLRSCSIRSTI - |CLRBUSFREE|CLRSCSIPERR|CLRREQINIT); - ahd_outb(ahd, CLRSINT0, CLRSELDO|CLRSELDI|CLRSELINGO|CLRIOERR); - ahd_outb(ahd, CLRINT, CLRSCSIINT); -} - -/**************************** Debugging Routines ******************************/ -#ifdef AHD_DEBUG -uint32_t ahd_debug = AHD_DEBUG; -#endif -void -ahd_print_scb(struct scb *scb) -{ - struct hardware_scb *hscb; - int i; - - hscb = scb->hscb; - printf("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n", - (void *)scb, - hscb->control, - hscb->scsiid, - hscb->lun, - hscb->cdb_len); - printf("Shared Data: "); - for (i = 0; i < sizeof(hscb->shared_data.idata.cdb); i++) - printf("%#02x", hscb->shared_data.idata.cdb[i]); - printf(" dataptr:%#x%x datacnt:%#x sgptr:%#x tag:%#x\n", - (uint32_t)((ahd_le64toh(hscb->dataptr) >> 32) & 0xFFFFFFFF), - (uint32_t)(ahd_le64toh(hscb->dataptr) & 0xFFFFFFFF), - ahd_le32toh(hscb->datacnt), - ahd_le32toh(hscb->sgptr), - SCB_GET_TAG(scb)); - ahd_dump_sglist(scb); -} - -void -ahd_dump_sglist(struct scb *scb) -{ - int i; - - if (scb->sg_count > 0) { - if ((scb->ahd_softc->flags & AHD_64BIT_ADDRESSING) != 0) { - struct ahd_dma64_seg *sg_list; - - sg_list = (struct ahd_dma64_seg*)scb->sg_list; - for (i = 0; i < scb->sg_count; i++) { - uint64_t addr; - - addr = ahd_le64toh(sg_list[i].addr); - printf("sg[%d] - Addr 0x%x%x : Length %d\n", - i, - (uint32_t)((addr >> 32) & 0xFFFFFFFF), - (uint32_t)(addr & 0xFFFFFFFF), - ahd_le32toh(sg_list[i].len)); - } - } else { - struct ahd_dma_seg *sg_list; - - sg_list = (struct ahd_dma_seg*)scb->sg_list; - for (i = 0; i < scb->sg_count; i++) { - printf("sg[%d] - Addr 0x%x%x : Length %d\n", - i, - (ahd_le32toh(sg_list[i].len) >> 24 - & SG_HIGH_ADDR_BITS), - ahd_le32toh(sg_list[i].addr), - ahd_le32toh(sg_list[i].len) - & AHD_SG_LEN_MASK); - } - } - } -} - -/************************* Transfer Negotiation *******************************/ -/* - * Allocate per target mode instance (ID we respond to as a target) - * transfer negotiation data structures. - */ -static struct ahd_tmode_tstate * -ahd_alloc_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel) -{ - struct ahd_tmode_tstate *master_tstate; - struct ahd_tmode_tstate *tstate; - int i; - - master_tstate = ahd->enabled_targets[ahd->our_id]; - if (ahd->enabled_targets[scsi_id] != NULL - && ahd->enabled_targets[scsi_id] != master_tstate) - panic("%s: ahd_alloc_tstate - Target already allocated", - ahd_name(ahd)); - tstate = malloc(sizeof(*tstate), M_DEVBUF, M_NOWAIT); - if (tstate == NULL) - return (NULL); - - /* - * If we have allocated a master tstate, copy user settings from - * the master tstate (taken from SRAM or the EEPROM) for this - * channel, but reset our current and goal settings to async/narrow - * until an initiator talks to us. - */ - if (master_tstate != NULL) { - memcpy(tstate, master_tstate, sizeof(*tstate)); - memset(tstate->enabled_luns, 0, sizeof(tstate->enabled_luns)); - for (i = 0; i < 16; i++) { - memset(&tstate->transinfo[i].curr, 0, - sizeof(tstate->transinfo[i].curr)); - memset(&tstate->transinfo[i].goal, 0, - sizeof(tstate->transinfo[i].goal)); - } - } else - memset(tstate, 0, sizeof(*tstate)); - ahd->enabled_targets[scsi_id] = tstate; - return (tstate); -} - -#ifdef AHD_TARGET_MODE -/* - * Free per target mode instance (ID we respond to as a target) - * transfer negotiation data structures. - */ -static void -ahd_free_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel, int force) -{ - struct ahd_tmode_tstate *tstate; - - /* - * Don't clean up our "master" tstate. - * It has our default user settings. - */ - if (scsi_id == ahd->our_id - && force == FALSE) - return; - - tstate = ahd->enabled_targets[scsi_id]; - if (tstate != NULL) - free(tstate, M_DEVBUF); - ahd->enabled_targets[scsi_id] = NULL; -} -#endif - -/* - * Called when we have an active connection to a target on the bus, - * this function finds the nearest period to the input period limited - * by the capabilities of the bus connectivity of and sync settings for - * the target. - */ -void -ahd_devlimited_syncrate(struct ahd_softc *ahd, - struct ahd_initiator_tinfo *tinfo, - u_int *period, u_int *ppr_options, role_t role) -{ - struct ahd_transinfo *transinfo; - u_int maxsync; - - if ((ahd_inb(ahd, SBLKCTL) & ENAB40) != 0 - && (ahd_inb(ahd, SSTAT2) & EXP_ACTIVE) == 0) { - maxsync = AHD_SYNCRATE_PACED; - } else { - maxsync = AHD_SYNCRATE_ULTRA; - /* Can't do DT related options on an SE bus */ - *ppr_options &= MSG_EXT_PPR_QAS_REQ; - } - /* - * Never allow a value higher than our current goal - * period otherwise we may allow a target initiated - * negotiation to go above the limit as set by the - * user. In the case of an initiator initiated - * sync negotiation, we limit based on the user - * setting. This allows the system to still accept - * incoming negotiations even if target initiated - * negotiation is not performed. - */ - if (role == ROLE_TARGET) - transinfo = &tinfo->user; - else - transinfo = &tinfo->goal; - *ppr_options &= (transinfo->ppr_options|MSG_EXT_PPR_PCOMP_EN); - if (transinfo->period == 0) { - *period = 0; - *ppr_options = 0; - } else { - *period = MAX(*period, transinfo->period); - ahd_find_syncrate(ahd, period, ppr_options, maxsync); - } -} - -/* - * Look up the valid period to SCSIRATE conversion in our table. - * Return the period and offset that should be sent to the target - * if this was the beginning of an SDTR. - */ -void -ahd_find_syncrate(struct ahd_softc *ahd, u_int *period, - u_int *ppr_options, u_int maxsync) -{ - /* Skip all PACED only entries if IU is not available */ - if ((*ppr_options & MSG_EXT_PPR_IU_REQ) == 0 - && maxsync < AHD_SYNCRATE_DT) - maxsync = AHD_SYNCRATE_DT; - - /* Skip all DT only entries if DT is not available */ - if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0 - && maxsync < AHD_SYNCRATE_ULTRA2) - maxsync = AHD_SYNCRATE_ULTRA2; - - if (*period < maxsync) - *period = maxsync; - - if ((*ppr_options & MSG_EXT_PPR_DT_REQ) != 0 - && *period > AHD_SYNCRATE_MIN_DT) - *ppr_options &= ~MSG_EXT_PPR_DT_REQ; - - if (*period > AHD_SYNCRATE_MIN) - *period = 0; - - /* Honor PPR option conformance rules. */ - if ((*ppr_options & MSG_EXT_PPR_IU_REQ) == 0) - *ppr_options &= (MSG_EXT_PPR_DT_REQ|MSG_EXT_PPR_QAS_REQ); - - if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0) - *ppr_options &= MSG_EXT_PPR_QAS_REQ; -} - -/* - * Truncate the given synchronous offset to a value the - * current adapter type and syncrate are capable of. - */ -void -ahd_validate_offset(struct ahd_softc *ahd, - struct ahd_initiator_tinfo *tinfo, - u_int period, u_int *offset, int wide, - role_t role) -{ - u_int maxoffset; - - /* Limit offset to what we can do */ - if (period == 0) - maxoffset = 0; - else if (period <= AHD_SYNCRATE_PACED) - maxoffset = MAX_OFFSET_PACED; - else - maxoffset = MAX_OFFSET; - *offset = MIN(*offset, maxoffset); - if (tinfo != NULL) { - if (role == ROLE_TARGET) - *offset = MIN(*offset, tinfo->user.offset); - else - *offset = MIN(*offset, tinfo->goal.offset); - } -} - -/* - * Truncate the given transfer width parameter to a value the - * current adapter type is capable of. - */ -void -ahd_validate_width(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo, - u_int *bus_width, role_t role) -{ - switch (*bus_width) { - default: - if (ahd->features & AHD_WIDE) { - /* Respond Wide */ - *bus_width = MSG_EXT_WDTR_BUS_16_BIT; - break; - } - /* FALLTHROUGH */ - case MSG_EXT_WDTR_BUS_8_BIT: - *bus_width = MSG_EXT_WDTR_BUS_8_BIT; - break; - } - if (tinfo != NULL) { - if (role == ROLE_TARGET) - *bus_width = MIN(tinfo->user.width, *bus_width); - else - *bus_width = MIN(tinfo->goal.width, *bus_width); - } -} - -/* - * Update the bitmask of targets for which the controller should - * negotiate with at the next convenient oportunity. This currently - * means the next time we send the initial identify messages for - * a new transaction. - */ -int -ahd_update_neg_request(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, - struct ahd_tmode_tstate *tstate, - struct ahd_initiator_tinfo *tinfo, int force) -{ - u_int auto_negotiate_orig; - - auto_negotiate_orig = tstate->auto_negotiate; - if (tinfo->curr.period != tinfo->goal.period - || tinfo->curr.width != tinfo->goal.width - || tinfo->curr.offset != tinfo->goal.offset - || tinfo->curr.ppr_options != tinfo->goal.ppr_options - || (force - && (tinfo->goal.period != 0 - || tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT - || tinfo->goal.ppr_options != 0))) - tstate->auto_negotiate |= devinfo->target_mask; - else - tstate->auto_negotiate &= ~devinfo->target_mask; - - return (auto_negotiate_orig != tstate->auto_negotiate); -} - -/* - * Update the user/goal/curr tables of synchronous negotiation - * parameters as well as, in the case of a current or active update, - * any data structures on the host controller. In the case of an - * active update, the specified target is currently talking to us on - * the bus, so the transfer parameter update must take effect - * immediately. - */ -void -ahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, - u_int period, u_int offset, u_int ppr_options, - u_int type, int paused) -{ - struct ahd_initiator_tinfo *tinfo; - struct ahd_tmode_tstate *tstate; - u_int old_period; - u_int old_offset; - u_int old_ppr; - int active; - int update_needed; - - active = (type & AHD_TRANS_ACTIVE) == AHD_TRANS_ACTIVE; - update_needed = 0; - - if (period == 0 || offset == 0) { - period = 0; - offset = 0; - } - - tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid, - devinfo->target, &tstate); - - if ((type & AHD_TRANS_USER) != 0) { - tinfo->user.period = period; - tinfo->user.offset = offset; - tinfo->user.ppr_options = ppr_options; - } - - if ((type & AHD_TRANS_GOAL) != 0) { - tinfo->goal.period = period; - tinfo->goal.offset = offset; - tinfo->goal.ppr_options = ppr_options; - } - - old_period = tinfo->curr.period; - old_offset = tinfo->curr.offset; - old_ppr = tinfo->curr.ppr_options; - - if ((type & AHD_TRANS_CUR) != 0 - && (old_period != period - || old_offset != offset - || old_ppr != ppr_options)) { - - update_needed++; - - tinfo->curr.period = period; - tinfo->curr.offset = offset; - tinfo->curr.ppr_options = ppr_options; - - ahd_send_async(ahd, devinfo->channel, devinfo->target, - CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL); - if (bootverbose) { - if (offset != 0) { - printf("%s: target %d synchronous with " - "period = 0x%x, offset = 0x%x%s\n", - ahd_name(ahd), devinfo->target, - period, offset, - (ppr_options & MSG_EXT_PPR_DT_REQ) - ? " (DT)" : ""); - } else { - printf("%s: target %d using " - "asynchronous transfers\n", - ahd_name(ahd), devinfo->target); - } - } - } - /* - * Always refresh the neg-table to handle the case of the - * sequencer setting the ENATNO bit for a MK_MESSAGE request. - * We will always renegotiate in that case if this is a - * packetized request. - */ - if ((type & AHD_TRANS_CUR) != 0) - ahd_update_neg_table(ahd, devinfo, &tinfo->curr); - - update_needed += ahd_update_neg_request(ahd, devinfo, tstate, - tinfo, /*force*/FALSE); - - if (update_needed) - ahd_update_pending_scbs(ahd); -} - -/* - * Update the user/goal/curr tables of wide negotiation - * parameters as well as, in the case of a current or active update, - * any data structures on the host controller. In the case of an - * active update, the specified target is currently talking to us on - * the bus, so the transfer parameter update must take effect - * immediately. - */ -void -ahd_set_width(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, - u_int width, u_int type, int paused) -{ - struct ahd_initiator_tinfo *tinfo; - struct ahd_tmode_tstate *tstate; - u_int oldwidth; - int active; - int update_needed; - - active = (type & AHD_TRANS_ACTIVE) == AHD_TRANS_ACTIVE; - update_needed = 0; - tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid, - devinfo->target, &tstate); - - if ((type & AHD_TRANS_USER) != 0) - tinfo->user.width = width; - - if ((type & AHD_TRANS_GOAL) != 0) - tinfo->goal.width = width; - - oldwidth = tinfo->curr.width; - if ((type & AHD_TRANS_CUR) != 0 && oldwidth != width) { - - update_needed++; - - tinfo->curr.width = width; - ahd_send_async(ahd, devinfo->channel, devinfo->target, - CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL); - if (bootverbose) { - printf("%s: target %d using %dbit transfers\n", - ahd_name(ahd), devinfo->target, - 8 * (0x01 << width)); - } - } - if ((type & AHD_TRANS_CUR) != 0) - ahd_update_neg_table(ahd, devinfo, &tinfo->curr); - - update_needed += ahd_update_neg_request(ahd, devinfo, tstate, - tinfo, /*force*/FALSE); - if (update_needed) - ahd_update_pending_scbs(ahd); -} - -/* - * Update the current state of tagged queuing for a given target. - */ -void -ahd_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, - ahd_queue_alg alg) -{ - ahd_platform_set_tags(ahd, devinfo, alg); - ahd_send_async(ahd, devinfo->channel, devinfo->target, - devinfo->lun, AC_TRANSFER_NEG, &alg); -} - -static void -ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, - struct ahd_transinfo *tinfo) -{ - ahd_mode_state saved_modes; - u_int period; - u_int ppr_opts; - u_int con_opts; - u_int offset; - u_int precomp; - - saved_modes = ahd_save_modes(ahd); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - - ahd_outb(ahd, NEGOADDR, devinfo->target); - period = tinfo->period; - offset = tinfo->offset; - precomp = 0; - if (period == 0) - period = AHD_SYNCRATE_ASYNC; - if (period == AHD_SYNCRATE_160) { - period = AHD_SYNCRATE_REVA_160; - precomp = 0; - if ((ahd->flags & AHD_CPQ_BOARD) == 0) - precomp |= AHD_PRECOMP_FASTSLEW; - if ((tinfo->ppr_options & MSG_EXT_PPR_PCOMP_EN) != 0) - precomp |= AHD_PRECOMP_CUTBACK_29; - } - ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP); - ahd_outb(ahd, ANNEXDAT, precomp); - - ahd_outb(ahd, NEGPERIOD, period); - ppr_opts = tinfo->ppr_options - & (MSG_EXT_PPR_QAS_REQ|MSG_EXT_PPR_DT_REQ|MSG_EXT_PPR_IU_REQ); - /* - * When the SPI4 spec was finalized, PACE transfers - * was not made a configurable option in the PPR message. - * Instead it is assumed to be enabled for any - * syncrate faster than 80MHz. Nevertheless, Harpoon - * allows this to be configurable. - * - * Harpoon also assumes at most 2 data bytes per negotiated - * REQ/ACK offset. Paced transfers take 4, so we must - * adjust our offset. - */ - if (period <= AHD_SYNCRATE_PACED) { - ppr_opts |= PPROPT_PACE; - offset *= 2; - } - ahd_outb(ahd, NEGPPROPTS, ppr_opts); - ahd_outb(ahd, NEGOFFSET, offset); - - con_opts = 0; - if (tinfo->width == MSG_EXT_WDTR_BUS_16_BIT) - con_opts |= WIDEXFER; - - /* - * During packetized transfers, the target will - * give us the oportunity to send command packets - * without us asserting attention. - */ - if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) == 0) - con_opts |= ENAUTOATNO; - ahd_outb(ahd, NEGCONOPTS, con_opts); - ahd_restore_modes(ahd, saved_modes); -} - -/* - * When the transfer settings for a connection change, update any - * in-transit SCBs to contain the new data so the hardware will - * be set correctly during future (re)selections. - */ -static void -ahd_update_pending_scbs(struct ahd_softc *ahd) -{ - struct scb *pending_scb; - int pending_scb_count; - int i; - int paused; - u_int saved_scbptr; - ahd_mode_state saved_modes; - - /* - * Traverse the pending SCB list and ensure that all of the - * SCBs there have the proper settings. - */ - pending_scb_count = 0; - LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) { - struct ahd_devinfo devinfo; - struct hardware_scb *pending_hscb; - struct ahd_initiator_tinfo *tinfo; - struct ahd_tmode_tstate *tstate; - - ahd_scb_devinfo(ahd, &devinfo, pending_scb); - tinfo = ahd_fetch_transinfo(ahd, devinfo.channel, - devinfo.our_scsiid, - devinfo.target, &tstate); - pending_hscb = pending_scb->hscb; - if ((tstate->auto_negotiate & devinfo.target_mask) == 0 - && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) { - pending_scb->flags &= ~SCB_AUTO_NEGOTIATE; - pending_hscb->control &= ~MK_MESSAGE; - } - ahd_sync_scb(ahd, pending_scb, - BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); - pending_scb_count++; - } - - if (pending_scb_count == 0) - return; - - if (ahd_is_paused(ahd)) { - paused = 1; - } else { - paused = 0; - ahd_pause(ahd); - } - - saved_modes = ahd_save_modes(ahd); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - saved_scbptr = ahd_get_scbptr(ahd); - /* Ensure that the hscbs down on the card match the new information */ - for (i = 0; i < ahd->scb_data.maxhscbs; i++) { - struct hardware_scb *pending_hscb; - u_int control; - u_int scb_tag; - - ahd_set_scbptr(ahd, i); - scb_tag = i; - pending_scb = ahd_lookup_scb(ahd, scb_tag); - if (pending_scb == NULL) - continue; - - pending_hscb = pending_scb->hscb; - control = ahd_inb_scbram(ahd, SCB_CONTROL); - control &= ~MK_MESSAGE; - control |= pending_hscb->control & MK_MESSAGE; - ahd_outb(ahd, SCB_CONTROL, control); - } - ahd_set_scbptr(ahd,saved_scbptr); - ahd_restore_modes(ahd, saved_modes); - - if (paused == 0) - ahd_unpause(ahd); -} - -/**************************** Pathing Information *****************************/ -static void -ahd_fetch_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) -{ - ahd_mode_state saved_modes; - u_int saved_scsiid; - role_t role; - int our_id; - - saved_modes = ahd_save_modes(ahd); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - - if (ahd_inb(ahd, SSTAT0) & TARGET) - role = ROLE_TARGET; - else - role = ROLE_INITIATOR; - - if (role == ROLE_TARGET - && (ahd_inb(ahd, SEQ_FLAGS) & CMDPHASE_PENDING) != 0) { - /* We were selected, so pull our id from TARGIDIN */ - our_id = ahd_inb(ahd, TARGIDIN) & OID; - } else if (role == ROLE_TARGET) - our_id = ahd_inb(ahd, TOWNID); - else - our_id = ahd_inb(ahd, IOWNID); - - saved_scsiid = ahd_inb(ahd, SAVED_SCSIID); - ahd_compile_devinfo(devinfo, - our_id, - SCSIID_TARGET(ahd, saved_scsiid), - ahd_inb(ahd, SAVED_LUN), - SCSIID_CHANNEL(ahd, saved_scsiid), - role); - ahd_restore_modes(ahd, saved_modes); -} - -struct ahd_phase_table_entry* -ahd_lookup_phase_entry(int phase) -{ - struct ahd_phase_table_entry *entry; - struct ahd_phase_table_entry *last_entry; - - /* - * num_phases doesn't include the default entry which - * will be returned if the phase doesn't match. - */ - last_entry = &ahd_phase_table[num_phases]; - for (entry = ahd_phase_table; entry < last_entry; entry++) { - if (phase == entry->phase) - break; - } - return (entry); -} - -void -ahd_compile_devinfo(struct ahd_devinfo *devinfo, u_int our_id, u_int target, - u_int lun, char channel, role_t role) -{ - devinfo->our_scsiid = our_id; - devinfo->target = target; - devinfo->lun = lun; - devinfo->target_offset = target; - devinfo->channel = channel; - devinfo->role = role; - if (channel == 'B') - devinfo->target_offset += 8; - devinfo->target_mask = (0x01 << devinfo->target_offset); -} - -static void -ahd_scb_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, - struct scb *scb) -{ - role_t role; - int our_id; - - our_id = SCSIID_OUR_ID(scb->hscb->scsiid); - role = ROLE_INITIATOR; - if ((scb->hscb->control & TARGET_SCB) != 0) - role = ROLE_TARGET; - ahd_compile_devinfo(devinfo, our_id, SCB_GET_TARGET(ahd, scb), - SCB_GET_LUN(scb), SCB_GET_CHANNEL(ahd, scb), role); -} - - -/************************ Message Phase Processing ****************************/ -/* - * When an initiator transaction with the MK_MESSAGE flag either reconnects - * or enters the initial message out phase, we are interrupted. Fill our - * outgoing message buffer with the appropriate message and beging handing - * the message phase(s) manually. - */ -static void -ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, - struct scb *scb) -{ - /* - * To facilitate adding multiple messages together, - * each routine should increment the index and len - * variables instead of setting them explicitly. - */ - ahd->msgout_index = 0; - ahd->msgout_len = 0; - - if (ahd_currently_packetized(ahd)) - ahd->msg_flags |= MSG_FLAG_PACKETIZED; - - if (ahd->send_msg_perror - && ahd_inb(ahd, MSG_OUT) == HOST_MSG) { - ahd->msgout_buf[ahd->msgout_index++] = ahd->send_msg_perror; - ahd->msgout_len++; - ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT; - printf("Setting up for Parity Error delivery\n"); - return; - } else if (scb == NULL) { - printf("%s: WARNING. No pending message for " - "I_T msgin. Issuing NO-OP\n", ahd_name(ahd)); - ahd->msgout_buf[ahd->msgout_index++] = MSG_NOOP; - ahd->msgout_len++; - ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT; - return; - } - - if ((scb->flags & SCB_DEVICE_RESET) == 0 - && (scb->flags & SCB_PACKETIZED) == 0 - && ahd_inb(ahd, MSG_OUT) == MSG_IDENTIFYFLAG) { - u_int identify_msg; - - identify_msg = MSG_IDENTIFYFLAG | SCB_GET_LUN(scb); - if ((scb->hscb->control & DISCENB) != 0) - identify_msg |= MSG_IDENTIFY_DISCFLAG; - ahd->msgout_buf[ahd->msgout_index++] = identify_msg; - ahd->msgout_len++; - - if ((scb->hscb->control & TAG_ENB) != 0) { - ahd->msgout_buf[ahd->msgout_index++] = - scb->hscb->control & (TAG_ENB|SCB_TAG_TYPE); - ahd->msgout_buf[ahd->msgout_index++] = SCB_GET_TAG(scb); - ahd->msgout_len += 2; - } - } - - if (scb->flags & SCB_DEVICE_RESET) { - ahd->msgout_buf[ahd->msgout_index++] = MSG_BUS_DEV_RESET; - ahd->msgout_len++; - ahd_print_path(ahd, scb); - printf("Bus Device Reset Message Sent\n"); - /* - * Clear our selection hardware in advance of - * the busfree. We may have an entry in the waiting - * Q for this target, and we don't want to go about - * selecting while we handle the busfree and blow it - * away. - */ - ahd_outb(ahd, SCSISEQ0, 0); - } else if ((scb->flags & SCB_ABORT) != 0) { - - if ((scb->hscb->control & TAG_ENB) != 0) { - ahd->msgout_buf[ahd->msgout_index++] = MSG_ABORT_TAG; - } else { - ahd->msgout_buf[ahd->msgout_index++] = MSG_ABORT; - } - ahd->msgout_len++; - ahd_print_path(ahd, scb); - printf("Abort%s Message Sent\n", - (scb->hscb->control & TAG_ENB) != 0 ? " Tag" : ""); - /* - * Clear our selection hardware in advance of - * the busfree. We may have an entry in the waiting - * Q for this target, and we don't want to go about - * selecting while we handle the busfree and blow it - * away. - */ - ahd_outb(ahd, SCSISEQ0, 0); - } else if ((scb->flags & (SCB_AUTO_NEGOTIATE|SCB_NEGOTIATE)) != 0) { - ahd_build_transfer_msg(ahd, devinfo); - /* - * Clear our selection hardware in advance of potential - * PPR IU status change busfree. We may have an entry in - * the waiting Q for this target, and we don't want to go - * about selecting while we handle the busfree and blow - * it away. - */ - ahd_outb(ahd, SCSISEQ0, 0); - } else { - printf("ahd_intr: AWAITING_MSG for an SCB that " - "does not have a waiting message\n"); - printf("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid, - devinfo->target_mask); - panic("SCB = %d, SCB Control = %x, MSG_OUT = %x " - "SCB flags = %x", SCB_GET_TAG(scb), scb->hscb->control, - ahd_inb(ahd, MSG_OUT), scb->flags); - } - - /* - * Clear the MK_MESSAGE flag from the SCB so we aren't - * asked to send this message again. - */ - ahd_outb(ahd, SCB_CONTROL, - ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE); - scb->hscb->control &= ~MK_MESSAGE; - ahd->msgout_index = 0; - ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT; -} - -/* - * Build an appropriate transfer negotiation message for the - * currently active target. - */ -static void -ahd_build_transfer_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) -{ - /* - * We need to initiate transfer negotiations. - * If our current and goal settings are identical, - * we want to renegotiate due to a check condition. - */ - struct ahd_initiator_tinfo *tinfo; - struct ahd_tmode_tstate *tstate; - int dowide; - int dosync; - int doppr; - int use_ppr; - u_int period; - u_int ppr_options; - u_int offset; - - tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid, - devinfo->target, &tstate); - /* - * Filter our period based on the current connection. - * If we can't perform DT transfers on this segment (not in LVD - * mode for instance), then our decision to issue a PPR message - * may change. - */ - period = tinfo->goal.period; - ppr_options = tinfo->goal.ppr_options; - /* Target initiated PPR is not allowed in the SCSI spec */ - if (devinfo->role == ROLE_TARGET) - ppr_options = 0; - ahd_devlimited_syncrate(ahd, tinfo, &period, - &ppr_options, devinfo->role); - dowide = tinfo->curr.width != tinfo->goal.width; - dosync = tinfo->curr.period != period; - doppr = tinfo->curr.ppr_options != ppr_options; - - if (!dowide && !dosync && !doppr) { - dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT; - dosync = tinfo->goal.period != 0; - doppr = tinfo->goal.ppr_options != 0; - } - - if (!dowide && !dosync && !doppr) { - panic("ahd_intr: AWAITING_MSG for negotiation, " - "but no negotiation needed\n"); - } - - use_ppr = (tinfo->curr.transport_version >= 3) || doppr; - /* Target initiated PPR is not allowed in the SCSI spec */ - if (devinfo->role == ROLE_TARGET) - use_ppr = 0; - - /* - * Both the PPR message and SDTR message require the - * goal syncrate to be limited to what the target device - * is capable of handling (based on whether an LVD->SE - * expander is on the bus), so combine these two cases. - * Regardless, guarantee that if we are using WDTR and SDTR - * messages that WDTR comes first. - */ - if (use_ppr || (dosync && !dowide)) { - - offset = tinfo->goal.offset; - ahd_validate_offset(ahd, tinfo, period, &offset, - use_ppr ? tinfo->goal.width - : tinfo->curr.width, - devinfo->role); - if (use_ppr) { - ahd_construct_ppr(ahd, devinfo, period, offset, - tinfo->goal.width, ppr_options); - } else { - ahd_construct_sdtr(ahd, devinfo, period, offset); - } - } else { - ahd_construct_wdtr(ahd, devinfo, tinfo->goal.width); - } -} - -/* - * Build a synchronous negotiation message in our message - * buffer based on the input parameters. - */ -static void -ahd_construct_sdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, - u_int period, u_int offset) -{ - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR_LEN; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR; - ahd->msgout_buf[ahd->msgout_index++] = period; - ahd->msgout_buf[ahd->msgout_index++] = offset; - ahd->msgout_len += 5; - if (bootverbose) { - printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n", - ahd_name(ahd), devinfo->channel, devinfo->target, - devinfo->lun, period, offset); - } -} - -/* - * Build a wide negotiateion message in our message - * buffer based on the input parameters. - */ -static void -ahd_construct_wdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, - u_int bus_width) -{ - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR_LEN; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR; - ahd->msgout_buf[ahd->msgout_index++] = bus_width; - ahd->msgout_len += 4; - if (bootverbose) { - printf("(%s:%c:%d:%d): Sending WDTR %x\n", - ahd_name(ahd), devinfo->channel, devinfo->target, - devinfo->lun, bus_width); - } -} - -/* - * Build a parallel protocol request message in our message - * buffer based on the input parameters. - */ -static void -ahd_construct_ppr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, - u_int period, u_int offset, u_int bus_width, - u_int ppr_options) -{ - /* - * Always request precompensation from - * the other target if we are running - * at paced syncrates. - */ - if (period <= AHD_SYNCRATE_PACED) - ppr_options |= MSG_EXT_PPR_PCOMP_EN; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR_LEN; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR; - ahd->msgout_buf[ahd->msgout_index++] = period; - ahd->msgout_buf[ahd->msgout_index++] = 0; - ahd->msgout_buf[ahd->msgout_index++] = offset; - ahd->msgout_buf[ahd->msgout_index++] = bus_width; - ahd->msgout_buf[ahd->msgout_index++] = ppr_options; - ahd->msgout_len += 8; - if (bootverbose) { - printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, " - "offset %x, ppr_options %x\n", ahd_name(ahd), - devinfo->channel, devinfo->target, devinfo->lun, - bus_width, period, offset, ppr_options); - } -} - -/* - * Clear any active message state. - */ -static void -ahd_clear_msg_state(struct ahd_softc *ahd) -{ - ahd_mode_state saved_modes; - - saved_modes = ahd_save_modes(ahd); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - ahd->send_msg_perror = 0; - ahd->msg_flags = MSG_FLAG_NONE; - ahd->msgout_len = 0; - ahd->msgin_index = 0; - ahd->msg_type = MSG_TYPE_NONE; - if ((ahd_inb(ahd, SCSISIGO) & ATNO) != 0) { - /* - * The target didn't care to respond to our - * message request, so clear ATN. - */ - ahd_outb(ahd, CLRSINT1, CLRATNO); - } - ahd_outb(ahd, MSG_OUT, MSG_NOOP); - ahd_outb(ahd, SEQ_FLAGS2, - ahd_inb(ahd, SEQ_FLAGS2) & ~TARGET_MSG_PENDING); - ahd_restore_modes(ahd, saved_modes); -} - -/* - * Manual message loop handler. - */ -static void -ahd_handle_message_phase(struct ahd_softc *ahd) -{ - struct ahd_devinfo devinfo; - u_int bus_phase; - int end_session; - - ahd_fetch_devinfo(ahd, &devinfo); - end_session = FALSE; - bus_phase = ahd_inb(ahd, LASTPHASE); - - if ((ahd_inb(ahd, LQISTAT2) & LQIPHASE_OUTPKT) != 0) { - printf("LQIRETRY for LQIPHASE_OUTPKT\n"); - ahd_outb(ahd, LQCTL2, LQIRETRY); - } -reswitch: - switch (ahd->msg_type) { - case MSG_TYPE_INITIATOR_MSGOUT: - { - int lastbyte; - int phasemis; - int msgdone; - - if (ahd->msgout_len == 0 && ahd->send_msg_perror == 0) - panic("HOST_MSG_LOOP interrupt with no active message"); - -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("%s: INITIATOR_MSG_OUT", ahd_name(ahd)); -#endif - phasemis = bus_phase != P_MESGOUT; - if (phasemis) { -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { - printf(" PHASEMIS %s - %s\n", - ahd_lookup_phase_entry(bus_phase) - ->phasemsg, - ahd_lookup_phase_entry(ahd_inb(ahd, SCSISIGI) & PHASE_MASK) - ->phasemsg); - } -#endif - if (bus_phase == P_MESGIN) { - /* - * Change gears and see if - * this messages is of interest to - * us or should be passed back to - * the sequencer. - */ - ahd_outb(ahd, CLRSINT1, CLRATNO); - ahd->send_msg_perror = 0; - ahd->msg_type = MSG_TYPE_INITIATOR_MSGIN; - ahd->msgin_index = 0; - goto reswitch; - } - end_session = TRUE; - break; - } - - if (ahd->send_msg_perror) { - ahd_outb(ahd, CLRSINT1, CLRATNO); - ahd_outb(ahd, CLRSINT1, CLRREQINIT); -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf(" byte 0x%x\n", ahd->send_msg_perror); -#endif - /* - * If we are notifying the target of a CRC error - * during packetized operations, the target is - * within its rights to acknowledge our message - * with a busfree. - */ - if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 0 - && ahd->send_msg_perror == MSG_INITIATOR_DET_ERR) - ahd->msg_flags |= MSG_FLAG_EXPECT_IDE_BUSFREE; - - ahd_outb(ahd, RETURN_2, ahd->send_msg_perror); - ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_WRITE); - break; - } - - msgdone = ahd->msgout_index == ahd->msgout_len; - if (msgdone) { - /* - * The target has requested a retry. - * Re-assert ATN, reset our message index to - * 0, and try again. - */ - ahd->msgout_index = 0; - ahd_assert_atn(ahd); - } - - lastbyte = ahd->msgout_index == (ahd->msgout_len - 1); - if (lastbyte) { - /* Last byte is signified by dropping ATN */ - ahd_outb(ahd, CLRSINT1, CLRATNO); - } - - /* - * Clear our interrupt status and present - * the next byte on the bus. - */ - ahd_outb(ahd, CLRSINT1, CLRREQINIT); -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf(" byte 0x%x\n", - ahd->msgout_buf[ahd->msgout_index]); -#endif - ahd_outb(ahd, RETURN_2, ahd->msgout_buf[ahd->msgout_index++]); - ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_WRITE); - break; - } - case MSG_TYPE_INITIATOR_MSGIN: - { - int phasemis; - int message_done; - -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("%s: INITIATOR_MSG_IN", ahd_name(ahd)); -#endif - phasemis = bus_phase != P_MESGIN; - if (phasemis) { -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { - printf(" PHASEMIS %s\n", - ahd_lookup_phase_entry(bus_phase) - ->phasemsg); - } -#endif - ahd->msgin_index = 0; - if (bus_phase == P_MESGOUT - && (ahd->send_msg_perror != 0 - || (ahd->msgout_len != 0 - && ahd->msgout_index == 0))) { - ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT; - goto reswitch; - } - end_session = TRUE; - break; - } - - /* Pull the byte in without acking it */ - ahd->msgin_buf[ahd->msgin_index] = ahd_inb(ahd, SCSIBUS); -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf(" byte 0x%x\n", - ahd->msgin_buf[ahd->msgin_index]); -#endif - - message_done = ahd_parse_msg(ahd, &devinfo); - - if (message_done) { - /* - * Clear our incoming message buffer in case there - * is another message following this one. - */ - ahd->msgin_index = 0; - - /* - * If this message illicited a response, - * assert ATN so the target takes us to the - * message out phase. - */ - if (ahd->msgout_len != 0) - ahd_assert_atn(ahd); - } else - ahd->msgin_index++; - - if (message_done == MSGLOOP_TERMINATED) { - end_session = TRUE; - } else { - /* Ack the byte */ - ahd_outb(ahd, CLRSINT1, CLRREQINIT); - ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_READ); - } - break; - } - case MSG_TYPE_TARGET_MSGIN: - { - int msgdone; - int msgout_request; - - /* - * By default, the message loop will continue. - */ - ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG); - - if (ahd->msgout_len == 0) - panic("Target MSGIN with no active message"); - - /* - * If we interrupted a mesgout session, the initiator - * will not know this until our first REQ. So, we - * only honor mesgout requests after we've sent our - * first byte. - */ - if ((ahd_inb(ahd, SCSISIGI) & ATNI) != 0 - && ahd->msgout_index > 0) - msgout_request = TRUE; - else - msgout_request = FALSE; - - if (msgout_request) { - - /* - * Change gears and see if - * this messages is of interest to - * us or should be passed back to - * the sequencer. - */ - ahd->msg_type = MSG_TYPE_TARGET_MSGOUT; - ahd_outb(ahd, SCSISIGO, P_MESGOUT | BSYO); - ahd->msgin_index = 0; - /* Dummy read to REQ for first byte */ - ahd_inb(ahd, SCSIDAT); - ahd_outb(ahd, SXFRCTL0, - ahd_inb(ahd, SXFRCTL0) | SPIOEN); - break; - } - - msgdone = ahd->msgout_index == ahd->msgout_len; - if (msgdone) { - ahd_outb(ahd, SXFRCTL0, - ahd_inb(ahd, SXFRCTL0) & ~SPIOEN); - end_session = TRUE; - break; - } - - /* - * Present the next byte on the bus. - */ - ahd_outb(ahd, SXFRCTL0, ahd_inb(ahd, SXFRCTL0) | SPIOEN); - ahd_outb(ahd, SCSIDAT, ahd->msgout_buf[ahd->msgout_index++]); - break; - } - case MSG_TYPE_TARGET_MSGOUT: - { - int lastbyte; - int msgdone; - - /* - * By default, the message loop will continue. - */ - ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG); - - /* - * The initiator signals that this is - * the last byte by dropping ATN. - */ - lastbyte = (ahd_inb(ahd, SCSISIGI) & ATNI) == 0; - - /* - * Read the latched byte, but turn off SPIOEN first - * so that we don't inadvertently cause a REQ for the - * next byte. - */ - ahd_outb(ahd, SXFRCTL0, ahd_inb(ahd, SXFRCTL0) & ~SPIOEN); - ahd->msgin_buf[ahd->msgin_index] = ahd_inb(ahd, SCSIDAT); - msgdone = ahd_parse_msg(ahd, &devinfo); - if (msgdone == MSGLOOP_TERMINATED) { - /* - * The message is *really* done in that it caused - * us to go to bus free. The sequencer has already - * been reset at this point, so pull the ejection - * handle. - */ - return; - } - - ahd->msgin_index++; - - /* - * XXX Read spec about initiator dropping ATN too soon - * and use msgdone to detect it. - */ - if (msgdone == MSGLOOP_MSGCOMPLETE) { - ahd->msgin_index = 0; - - /* - * If this message illicited a response, transition - * to the Message in phase and send it. - */ - if (ahd->msgout_len != 0) { - ahd_outb(ahd, SCSISIGO, P_MESGIN | BSYO); - ahd_outb(ahd, SXFRCTL0, - ahd_inb(ahd, SXFRCTL0) | SPIOEN); - ahd->msg_type = MSG_TYPE_TARGET_MSGIN; - ahd->msgin_index = 0; - break; - } - } - - if (lastbyte) - end_session = TRUE; - else { - /* Ask for the next byte. */ - ahd_outb(ahd, SXFRCTL0, - ahd_inb(ahd, SXFRCTL0) | SPIOEN); - } - - break; - } - default: - panic("Unknown REQINIT message type"); - } - - if (end_session) { - if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 0) { - printf("%s: Returning to Idle Loop\n", - ahd_name(ahd)); - ahd_outb(ahd, LASTPHASE, P_BUSFREE); - ahd_clear_msg_state(ahd); - ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET); - } else { - ahd_clear_msg_state(ahd); - ahd_outb(ahd, RETURN_1, EXIT_MSG_LOOP); - } - } -} - -/* - * See if we sent a particular extended message to the target. - * If "full" is true, return true only if the target saw the full - * message. If "full" is false, return true if the target saw at - * least the first byte of the message. - */ -static int -ahd_sent_msg(struct ahd_softc *ahd, ahd_msgtype type, u_int msgval, int full) -{ - int found; - u_int index; - - found = FALSE; - index = 0; - - while (index < ahd->msgout_len) { - if (ahd->msgout_buf[index] == MSG_EXTENDED) { - u_int end_index; - - end_index = index + 1 + ahd->msgout_buf[index + 1]; - if (ahd->msgout_buf[index+2] == msgval - && type == AHDMSG_EXT) { - - if (full) { - if (ahd->msgout_index > end_index) - found = TRUE; - } else if (ahd->msgout_index > index) - found = TRUE; - } - index = end_index; - } else if (ahd->msgout_buf[index] >= MSG_SIMPLE_TASK - && ahd->msgout_buf[index] <= MSG_IGN_WIDE_RESIDUE) { - - /* Skip tag type and tag id or residue param*/ - index += 2; - } else { - /* Single byte message */ - if (type == AHDMSG_1B - && ahd->msgout_buf[index] == msgval - && ahd->msgout_index > index) - found = TRUE; - index++; - } - - if (found) - break; - } - return (found); -} - -/* - * Wait for a complete incoming message, parse it, and respond accordingly. - */ -static int -ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) -{ - struct ahd_initiator_tinfo *tinfo; - struct ahd_tmode_tstate *tstate; - int reject; - int done; - int response; - - done = MSGLOOP_IN_PROG; - response = FALSE; - reject = FALSE; - tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid, - devinfo->target, &tstate); - - /* - * Parse as much of the message as is availible, - * rejecting it if we don't support it. When - * the entire message is availible and has been - * handled, return MSGLOOP_MSGCOMPLETE, indicating - * that we have parsed an entire message. - * - * In the case of extended messages, we accept the length - * byte outright and perform more checking once we know the - * extended message type. - */ - switch (ahd->msgin_buf[0]) { - case MSG_DISCONNECT: - case MSG_SAVEDATAPOINTER: - case MSG_CMDCOMPLETE: - case MSG_RESTOREPOINTERS: - case MSG_IGN_WIDE_RESIDUE: - /* - * End our message loop as these are messages - * the sequencer handles on its own. - */ - done = MSGLOOP_TERMINATED; - break; - case MSG_MESSAGE_REJECT: - response = ahd_handle_msg_reject(ahd, devinfo); - /* FALLTHROUGH */ - case MSG_NOOP: - done = MSGLOOP_MSGCOMPLETE; - break; - case MSG_EXTENDED: - { - /* Wait for enough of the message to begin validation */ - if (ahd->msgin_index < 2) - break; - switch (ahd->msgin_buf[2]) { - case MSG_EXT_SDTR: - { - u_int period; - u_int ppr_options; - u_int offset; - u_int saved_offset; - - if (ahd->msgin_buf[1] != MSG_EXT_SDTR_LEN) { - reject = TRUE; - break; - } - - /* - * Wait until we have both args before validating - * and acting on this message. - * - * Add one to MSG_EXT_SDTR_LEN to account for - * the extended message preamble. - */ - if (ahd->msgin_index < (MSG_EXT_SDTR_LEN + 1)) - break; - - period = ahd->msgin_buf[3]; - ppr_options = 0; - saved_offset = offset = ahd->msgin_buf[4]; - ahd_devlimited_syncrate(ahd, tinfo, &period, - &ppr_options, devinfo->role); - ahd_validate_offset(ahd, tinfo, period, &offset, - tinfo->curr.width, devinfo->role); - if (bootverbose) { - printf("(%s:%c:%d:%d): Received " - "SDTR period %x, offset %x\n\t" - "Filtered to period %x, offset %x\n", - ahd_name(ahd), devinfo->channel, - devinfo->target, devinfo->lun, - ahd->msgin_buf[3], saved_offset, - period, offset); - } - ahd_set_syncrate(ahd, devinfo, period, - offset, ppr_options, - AHD_TRANS_ACTIVE|AHD_TRANS_GOAL, - /*paused*/TRUE); - - /* - * See if we initiated Sync Negotiation - * and didn't have to fall down to async - * transfers. - */ - if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, TRUE)) { - /* We started it */ - if (saved_offset != offset) { - /* Went too low - force async */ - reject = TRUE; - } - } else { - /* - * Send our own SDTR in reply - */ - if (bootverbose - && devinfo->role == ROLE_INITIATOR) { - printf("(%s:%c:%d:%d): Target " - "Initiated SDTR\n", - ahd_name(ahd), devinfo->channel, - devinfo->target, devinfo->lun); - } - ahd->msgout_index = 0; - ahd->msgout_len = 0; - ahd_construct_sdtr(ahd, devinfo, - period, offset); - ahd->msgout_index = 0; - response = TRUE; - } - done = MSGLOOP_MSGCOMPLETE; - break; - } - case MSG_EXT_WDTR: - { - u_int bus_width; - u_int saved_width; - u_int sending_reply; - - sending_reply = FALSE; - if (ahd->msgin_buf[1] != MSG_EXT_WDTR_LEN) { - reject = TRUE; - break; - } - - /* - * Wait until we have our arg before validating - * and acting on this message. - * - * Add one to MSG_EXT_WDTR_LEN to account for - * the extended message preamble. - */ - if (ahd->msgin_index < (MSG_EXT_WDTR_LEN + 1)) - break; - - bus_width = ahd->msgin_buf[3]; - saved_width = bus_width; - ahd_validate_width(ahd, tinfo, &bus_width, - devinfo->role); - if (bootverbose) { - printf("(%s:%c:%d:%d): Received WDTR " - "%x filtered to %x\n", - ahd_name(ahd), devinfo->channel, - devinfo->target, devinfo->lun, - saved_width, bus_width); - } - - if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, TRUE)) { - /* - * Don't send a WDTR back to the - * target, since we asked first. - * If the width went higher than our - * request, reject it. - */ - if (saved_width > bus_width) { - reject = TRUE; - printf("(%s:%c:%d:%d): requested %dBit " - "transfers. Rejecting...\n", - ahd_name(ahd), devinfo->channel, - devinfo->target, devinfo->lun, - 8 * (0x01 << bus_width)); - bus_width = 0; - } - } else { - /* - * Send our own WDTR in reply - */ - if (bootverbose - && devinfo->role == ROLE_INITIATOR) { - printf("(%s:%c:%d:%d): Target " - "Initiated WDTR\n", - ahd_name(ahd), devinfo->channel, - devinfo->target, devinfo->lun); - } - ahd->msgout_index = 0; - ahd->msgout_len = 0; - ahd_construct_wdtr(ahd, devinfo, bus_width); - ahd->msgout_index = 0; - response = TRUE; - sending_reply = TRUE; - } - ahd_set_width(ahd, devinfo, bus_width, - AHD_TRANS_ACTIVE|AHD_TRANS_GOAL, - /*paused*/TRUE); - /* After a wide message, we are async */ - ahd_set_syncrate(ahd, devinfo, /*period*/0, - /*offset*/0, /*ppr_options*/0, - AHD_TRANS_ACTIVE, /*paused*/TRUE); - if (sending_reply == FALSE && reject == FALSE) { - - if (tinfo->goal.period) { - ahd->msgout_index = 0; - ahd->msgout_len = 0; - ahd_build_transfer_msg(ahd, devinfo); - ahd->msgout_index = 0; - response = TRUE; - } - } - done = MSGLOOP_MSGCOMPLETE; - break; - } - case MSG_EXT_PPR: - { - u_int period; - u_int offset; - u_int bus_width; - u_int ppr_options; - u_int saved_width; - u_int saved_offset; - u_int saved_ppr_options; - - if (ahd->msgin_buf[1] != MSG_EXT_PPR_LEN) { - reject = TRUE; - break; - } - - /* - * Wait until we have all args before validating - * and acting on this message. - * - * Add one to MSG_EXT_PPR_LEN to account for - * the extended message preamble. - */ - if (ahd->msgin_index < (MSG_EXT_PPR_LEN + 1)) - break; - - period = ahd->msgin_buf[3]; - offset = ahd->msgin_buf[5]; - bus_width = ahd->msgin_buf[6]; - saved_width = bus_width; - ppr_options = ahd->msgin_buf[7]; - /* - * According to the spec, a DT only - * period factor with no DT option - * set implies async. - */ - if ((ppr_options & MSG_EXT_PPR_DT_REQ) == 0 - && period <= 9) - offset = 0; - saved_ppr_options = ppr_options; - saved_offset = offset; - - /* - * Transfer options are only available if we - * are negotiating wide. - */ - if (bus_width == 0) - ppr_options &= MSG_EXT_PPR_QAS_REQ; - - ahd_validate_width(ahd, tinfo, &bus_width, - devinfo->role); - ahd_devlimited_syncrate(ahd, tinfo, &period, - &ppr_options, devinfo->role); - ahd_validate_offset(ahd, tinfo, period, &offset, - bus_width, devinfo->role); - - if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, TRUE)) { - /* - * If we are unable to do any of the - * requested options (we went too low), - * then we'll have to reject the message. - */ - if (saved_width > bus_width - || saved_offset != offset - || saved_ppr_options != ppr_options) { - reject = TRUE; - period = 0; - offset = 0; - bus_width = 0; - ppr_options = 0; - } - } else { - if (devinfo->role != ROLE_TARGET) - printf("(%s:%c:%d:%d): Target " - "Initiated PPR\n", - ahd_name(ahd), devinfo->channel, - devinfo->target, devinfo->lun); - else - printf("(%s:%c:%d:%d): Initiator " - "Initiated PPR\n", - ahd_name(ahd), devinfo->channel, - devinfo->target, devinfo->lun); - ahd->msgout_index = 0; - ahd->msgout_len = 0; - ahd_construct_ppr(ahd, devinfo, period, offset, - bus_width, ppr_options); - ahd->msgout_index = 0; - response = TRUE; - } - if (bootverbose) { - printf("(%s:%c:%d:%d): Received PPR width %x, " - "period %x, offset %x,options %x\n" - "\tFiltered to width %x, period %x, " - "offset %x, options %x\n", - ahd_name(ahd), devinfo->channel, - devinfo->target, devinfo->lun, - saved_width, ahd->msgin_buf[3], - saved_offset, saved_ppr_options, - bus_width, period, offset, ppr_options); - } - ahd_set_width(ahd, devinfo, bus_width, - AHD_TRANS_ACTIVE|AHD_TRANS_GOAL, - /*paused*/TRUE); - saved_ppr_options = tinfo->curr.ppr_options; - if ((saved_ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("PPR with IU_REQ outstanding\n"); -#endif - ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE; - } - if ((saved_ppr_options & MSG_EXT_PPR_IU_REQ) - != (ppr_options & MSG_EXT_PPR_IU_REQ)) { -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("Expecting IU Change busfree\n"); -#endif - ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE - | MSG_FLAG_IU_REQ_CHANGED; - } - - ahd_set_syncrate(ahd, devinfo, period, - offset, ppr_options, - AHD_TRANS_ACTIVE|AHD_TRANS_GOAL, - /*paused*/TRUE); - - done = MSGLOOP_MSGCOMPLETE; - break; - } - default: - /* Unknown extended message. Reject it. */ - reject = TRUE; - break; - } - break; - } -#ifdef AHD_TARGET_MODE - case MSG_BUS_DEV_RESET: - ahd_handle_devreset(ahd, devinfo, - CAM_BDR_SENT, - "Bus Device Reset Received", - /*verbose_level*/0); - ahd_restart(ahd); - done = MSGLOOP_TERMINATED; - break; - case MSG_ABORT_TAG: - case MSG_ABORT: - case MSG_CLEAR_QUEUE: - { - int tag; - - /* Target mode messages */ - if (devinfo->role != ROLE_TARGET) { - reject = TRUE; - break; - } - tag = SCB_LIST_NULL; - if (ahd->msgin_buf[0] == MSG_ABORT_TAG) - tag = ahd_inb(ahd, INITIATOR_TAG); - ahd_abort_scbs(ahd, devinfo->target, devinfo->channel, - devinfo->lun, tag, ROLE_TARGET, - CAM_REQ_ABORTED); - - tstate = ahd->enabled_targets[devinfo->our_scsiid]; - if (tstate != NULL) { - struct ahd_tmode_lstate* lstate; - - lstate = tstate->enabled_luns[devinfo->lun]; - if (lstate != NULL) { - ahd_queue_lstate_event(ahd, lstate, - devinfo->our_scsiid, - ahd->msgin_buf[0], - /*arg*/tag); - ahd_send_lstate_events(ahd, lstate); - } - } - ahd_restart(ahd); - done = MSGLOOP_TERMINATED; - break; - } -#endif - case MSG_QAS_REQUEST: - printf("%s: QAS request. SCSISIGI == 0x%x\n", - ahd_name(ahd), ahd_inb(ahd, SCSISIGI)); - /* FALLTHROUGH */ - case MSG_TERM_IO_PROC: - default: - reject = TRUE; - break; - } - - if (reject) { - /* - * Setup to reject the message. - */ - ahd->msgout_index = 0; - ahd->msgout_len = 1; - ahd->msgout_buf[0] = MSG_MESSAGE_REJECT; - done = MSGLOOP_MSGCOMPLETE; - response = TRUE; - } - - if (done != MSGLOOP_IN_PROG && !response) - /* Clear the outgoing message buffer */ - ahd->msgout_len = 0; - - return (done); -} - -/* - * Process a message reject message. - */ -static int -ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) -{ - /* - * What we care about here is if we had an - * outstanding SDTR or WDTR message for this - * target. If we did, this is a signal that - * the target is refusing negotiation. - */ - struct scb *scb; - struct ahd_initiator_tinfo *tinfo; - struct ahd_tmode_tstate *tstate; - u_int scb_index; - u_int last_msg; - int response = 0; - - scb_index = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scb_index); - tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, - devinfo->our_scsiid, - devinfo->target, &tstate); - /* Might be necessary */ - last_msg = ahd_inb(ahd, LAST_MSG); - - if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, /*full*/FALSE)) { - /* - * Target does not support the PPR message. - * Attempt to negotiate SPI-2 style. - */ - if (bootverbose) { - printf("(%s:%c:%d:%d): PPR Rejected. " - "Trying WDTR/SDTR\n", - ahd_name(ahd), devinfo->channel, - devinfo->target, devinfo->lun); - } - tinfo->goal.ppr_options = 0; - tinfo->curr.transport_version = 2; - tinfo->goal.transport_version = 2; - ahd->msgout_index = 0; - ahd->msgout_len = 0; - ahd_build_transfer_msg(ahd, devinfo); - ahd->msgout_index = 0; - response = 1; - } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, /*full*/FALSE)) { - - /* note 8bit xfers */ - printf("(%s:%c:%d:%d): refuses WIDE negotiation. Using " - "8bit transfers\n", ahd_name(ahd), - devinfo->channel, devinfo->target, devinfo->lun); - ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT, - AHD_TRANS_ACTIVE|AHD_TRANS_GOAL, - /*paused*/TRUE); - /* - * No need to clear the sync rate. If the target - * did not accept the command, our syncrate is - * unaffected. If the target started the negotiation, - * but rejected our response, we already cleared the - * sync rate before sending our WDTR. - */ - if (tinfo->goal.period) { - - /* Start the sync negotiation */ - ahd->msgout_index = 0; - ahd->msgout_len = 0; - ahd_build_transfer_msg(ahd, devinfo); - ahd->msgout_index = 0; - response = 1; - } - } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, /*full*/FALSE)) { - /* note asynch xfers and clear flag */ - ahd_set_syncrate(ahd, devinfo, /*period*/0, - /*offset*/0, /*ppr_options*/0, - AHD_TRANS_ACTIVE|AHD_TRANS_GOAL, - /*paused*/TRUE); - printf("(%s:%c:%d:%d): refuses synchronous negotiation. " - "Using asynchronous transfers\n", - ahd_name(ahd), devinfo->channel, - devinfo->target, devinfo->lun); - } else if ((scb->hscb->control & MSG_SIMPLE_TASK) != 0) { - int tag_type; - int mask; - - tag_type = (scb->hscb->control & MSG_SIMPLE_TASK); - - if (tag_type == MSG_SIMPLE_TASK) { - printf("(%s:%c:%d:%d): refuses tagged commands. " - "Performing non-tagged I/O\n", ahd_name(ahd), - devinfo->channel, devinfo->target, devinfo->lun); - ahd_set_tags(ahd, devinfo, AHD_QUEUE_NONE); - mask = ~0x23; - } else { - printf("(%s:%c:%d:%d): refuses %s tagged commands. " - "Performing simple queue tagged I/O only\n", - ahd_name(ahd), devinfo->channel, devinfo->target, - devinfo->lun, tag_type == MSG_ORDERED_TASK - ? "ordered" : "head of queue"); - ahd_set_tags(ahd, devinfo, AHD_QUEUE_BASIC); - mask = ~0x03; - } - - /* - * Resend the identify for this CCB as the target - * may believe that the selection is invalid otherwise. - */ - ahd_outb(ahd, SCB_CONTROL, - ahd_inb_scbram(ahd, SCB_CONTROL) & mask); - scb->hscb->control &= mask; - ahd_set_transaction_tag(scb, /*enabled*/FALSE, - /*type*/MSG_SIMPLE_TASK); - ahd_outb(ahd, MSG_OUT, MSG_IDENTIFYFLAG); - ahd_assert_atn(ahd); - ahd_busy_tcl(ahd, BUILD_TCL(scb->hscb->scsiid, devinfo->lun), - SCB_GET_TAG(scb)); - - /* - * Requeue all tagged commands for this target - * currently in our posession so they can be - * converted to untagged commands. - */ - ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb), - SCB_GET_CHANNEL(ahd, scb), - SCB_GET_LUN(scb), /*tag*/SCB_LIST_NULL, - ROLE_INITIATOR, CAM_REQUEUE_REQ, - SEARCH_COMPLETE); - } else { - /* - * Otherwise, we ignore it. - */ - printf("%s:%c:%d: Message reject for %x -- ignored\n", - ahd_name(ahd), devinfo->channel, devinfo->target, - last_msg); - } - return (response); -} - -/* - * Process an ingnore wide residue message. - */ -static void -ahd_handle_ign_wide_residue(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) -{ - u_int scb_index; - struct scb *scb; - - scb_index = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scb_index); - /* - * XXX Actually check data direction in the sequencer? - * Perhaps add datadir to some spare bits in the hscb? - */ - if ((ahd_inb(ahd, SEQ_FLAGS) & DPHASE) == 0 - || ahd_get_transfer_dir(scb) != CAM_DIR_IN) { - /* - * Ignore the message if we haven't - * seen an appropriate data phase yet. - */ - } else { - /* - * If the residual occurred on the last - * transfer and the transfer request was - * expected to end on an odd count, do - * nothing. Otherwise, subtract a byte - * and update the residual count accordingly. - */ - uint32_t sgptr; - - sgptr = ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR); - if ((sgptr & SG_LIST_NULL) != 0 - && ahd_inb(ahd, DATA_COUNT_ODD) == 1) { - /* - * If the residual occurred on the last - * transfer and the transfer request was - * expected to end on an odd count, do - * nothing. - */ - } else { - uint32_t data_cnt; - uint64_t data_addr; - uint32_t sglen; - - /* Pull in the rest of the sgptr */ - sgptr |= - (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 3) << 24) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 2) << 16) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 1) << 8); - sgptr &= SG_PTR_MASK; - data_cnt = - (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+2) << 16) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+1) << 8) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT)); - - data_addr = (((uint64_t)ahd_inb(ahd, SHADDR + 7)) << 56) - | (((uint64_t)ahd_inb(ahd, SHADDR + 6)) << 48) - | (((uint64_t)ahd_inb(ahd, SHADDR + 5)) << 40) - | (((uint64_t)ahd_inb(ahd, SHADDR + 4)) << 32) - | (ahd_inb(ahd, SHADDR + 3) << 24) - | (ahd_inb(ahd, SHADDR + 2) << 16) - | (ahd_inb(ahd, SHADDR + 1) << 8) - | (ahd_inb(ahd, SHADDR)); - - data_cnt += 1; - data_addr -= 1; - - if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { - struct ahd_dma64_seg *sg; - - sg = ahd_sg_bus_to_virt(ahd, scb, sgptr); - - /* - * The residual sg ptr points to the next S/G - * to load so we must go back one. - */ - sg--; - sglen = ahd_le32toh(sg->len) & AHD_SG_LEN_MASK; - if (sg != scb->sg_list - && sglen < (data_cnt & AHD_SG_LEN_MASK)) { - - sg--; - sglen = ahd_le32toh(sg->len); - /* - * Preserve High Address and SG_LIST - * bits while setting the count to 1. - */ - data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK)); - data_addr = ahd_le64toh(sg->addr) - + (sglen & AHD_SG_LEN_MASK) - - 1; - - /* - * Increment sg so it points to the - * "next" sg. - */ - sg++; - sgptr = ahd_sg_virt_to_bus(ahd, scb, - sg); - } - } else { - struct ahd_dma_seg *sg; - - sg = ahd_sg_bus_to_virt(ahd, scb, sgptr); - - /* - * The residual sg ptr points to the next S/G - * to load so we must go back one. - */ - sg--; - sglen = ahd_le32toh(sg->len) & AHD_SG_LEN_MASK; - if (sg != scb->sg_list - && sglen < (data_cnt & AHD_SG_LEN_MASK)) { - - sg--; - sglen = ahd_le32toh(sg->len); - /* - * Preserve High Address and SG_LIST - * bits while setting the count to 1. - */ - data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK)); - data_addr = ahd_le32toh(sg->addr) - + (sglen & AHD_SG_LEN_MASK) - - 1; - - /* - * Increment sg so it points to the - * "next" sg. - */ - sg++; - sgptr = ahd_sg_virt_to_bus(ahd, scb, - sg); - } - } - ahd_outb(ahd, SCB_RESIDUAL_SGPTR + 3, sgptr >> 24); - ahd_outb(ahd, SCB_RESIDUAL_SGPTR + 2, sgptr >> 16); - ahd_outb(ahd, SCB_RESIDUAL_SGPTR + 1, sgptr >> 8); - ahd_outb(ahd, SCB_RESIDUAL_SGPTR, sgptr); - - ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, data_cnt >> 24); - ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 2, data_cnt >> 16); - ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 1, data_cnt >> 8); - ahd_outb(ahd, SCB_RESIDUAL_DATACNT, data_cnt); - - /* - * The FIFO's pointers will be updated if/when the - * sequencer re-enters a data phase. - */ - } - } -} - - -/* - * Reinitialize the data pointers for the active transfer - * based on its current residual. - */ -static void -ahd_reinitialize_dataptrs(struct ahd_softc *ahd) -{ - struct scb *scb; - ahd_mode_state saved_modes; - u_int scb_index; - u_int wait; - uint32_t sgptr; - uint32_t resid; - uint64_t dataptr; - - AHD_ASSERT_MODES(ahd, AHD_MODE_DFF0_MSK|AHD_MODE_DFF1_MSK, - AHD_MODE_DFF0_MSK|AHD_MODE_DFF1_MSK); - - scb_index = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scb_index); - - /* - * Release and reacquire the FIFO so we - * have a clean slate. - */ - ahd_outb(ahd, DFFSXFRCTL, CLRCHN); - wait = 1000; - do { - ahd_delay(100); - } while (--wait && !(ahd_inb(ahd, MDFFSTAT) & FIFOFREE)); - if (wait == 0) { - ahd_print_path(ahd, scb); - printf("ahd_reinitialize_dataptrs: Forcing FIFO free.\n"); - ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT); - } - saved_modes = ahd_save_modes(ahd); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - ahd_outb(ahd, DFFSTAT, - ahd_inb(ahd, DFFSTAT) | (saved_modes == 0x11 ? CURRFIFO : 0)); - - /* - * Determine initial values for data_addr and data_cnt - * for resuming the data phase. - */ - sgptr = (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 3) << 24) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 2) << 16) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 1) << 8) - | ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR); - sgptr &= SG_PTR_MASK; - - resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 1) << 8) - | ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT); - - if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { - struct ahd_dma64_seg *sg; - - sg = ahd_sg_bus_to_virt(ahd, scb, sgptr); - - /* The residual sg_ptr always points to the next sg */ - sg--; - - dataptr = ahd_le64toh(sg->addr) - + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK) - - resid; - ahd_outb(ahd, HADDR + 7, dataptr >> 56); - ahd_outb(ahd, HADDR + 6, dataptr >> 48); - ahd_outb(ahd, HADDR + 5, dataptr >> 40); - ahd_outb(ahd, HADDR + 4, dataptr >> 32); - } else { - struct ahd_dma_seg *sg; - - sg = ahd_sg_bus_to_virt(ahd, scb, sgptr); - - /* The residual sg_ptr always points to the next sg */ - sg--; - - dataptr = ahd_le32toh(sg->addr) - + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK) - - resid; - ahd_outb(ahd, HADDR + 4, - (ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24); - } - ahd_outb(ahd, HADDR + 3, dataptr >> 24); - ahd_outb(ahd, HADDR + 2, dataptr >> 16); - ahd_outb(ahd, HADDR + 1, dataptr >> 8); - ahd_outb(ahd, HADDR, dataptr); - ahd_outb(ahd, HCNT + 2, resid >> 16); - ahd_outb(ahd, HCNT + 1, resid >> 8); - ahd_outb(ahd, HCNT, resid); -} - -/* - * Handle the effects of issuing a bus device reset message. - */ -static void -ahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, - cam_status status, char *message, int verbose_level) -{ -#ifdef AHD_TARGET_MODE - struct ahd_tmode_tstate* tstate; - u_int lun; -#endif - int found; - - found = ahd_abort_scbs(ahd, devinfo->target, devinfo->channel, - CAM_LUN_WILDCARD, SCB_LIST_NULL, devinfo->role, - status); - -#ifdef AHD_TARGET_MODE - /* - * Send an immediate notify ccb to all target mord peripheral - * drivers affected by this action. - */ - tstate = ahd->enabled_targets[devinfo->our_scsiid]; - if (tstate != NULL) { - for (lun = 0; lun < AHD_NUM_LUNS; lun++) { - struct ahd_tmode_lstate* lstate; - - lstate = tstate->enabled_luns[lun]; - if (lstate == NULL) - continue; - - ahd_queue_lstate_event(ahd, lstate, devinfo->our_scsiid, - MSG_BUS_DEV_RESET, /*arg*/0); - ahd_send_lstate_events(ahd, lstate); - } - } -#endif - - /* - * Go back to async/narrow transfers and renegotiate. - */ - ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT, - AHD_TRANS_CUR, /*paused*/TRUE); - ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0, - /*ppr_options*/0, AHD_TRANS_CUR, /*paused*/TRUE); - - ahd_send_async(ahd, devinfo->channel, devinfo->target, - CAM_LUN_WILDCARD, AC_SENT_BDR, NULL); - - if (message != NULL - && (verbose_level <= bootverbose)) - printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd), - message, devinfo->channel, devinfo->target, found); -} - -#ifdef AHD_TARGET_MODE -static void -ahd_setup_target_msgin(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, - struct scb *scb) -{ - - /* - * To facilitate adding multiple messages together, - * each routine should increment the index and len - * variables instead of setting them explicitly. - */ - ahd->msgout_index = 0; - ahd->msgout_len = 0; - - if (scb != NULL && (scb->flags & SCB_AUTO_NEGOTIATE) != 0) - ahd_build_transfer_msg(ahd, devinfo); - else - panic("ahd_intr: AWAITING target message with no message"); - - ahd->msgout_index = 0; - ahd->msg_type = MSG_TYPE_TARGET_MSGIN; -} -#endif -/**************************** Initialization **********************************/ -static bus_size_t -ahd_sglist_size(struct ahd_softc *ahd) -{ - bus_size_t list_size; - - list_size = sizeof(struct ahd_dma_seg) * AHD_NSEG; - if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) - list_size = sizeof(struct ahd_dma64_seg) * AHD_NSEG; - return (list_size); -} - -/* - * Calculate the optimum S/G List allocation size. S/G elements used - * for a given transaction must be physically contiguous. Assume the - * OS will allocate full pages to us, so it doesn't make sense to request - * less than a page. - */ -static bus_size_t -ahd_sglist_allocsize(struct ahd_softc *ahd) -{ - bus_size_t sg_list_increment; - bus_size_t sg_list_size; - bus_size_t max_list_size; - bus_size_t best_list_size; - - /* Start out with the minimum required for AHD_NSEG. */ - sg_list_increment = ahd_sglist_size(ahd); - sg_list_size = sg_list_increment; - - /* Get us as close as possible to a page in size. */ - while ((sg_list_size + sg_list_increment) <= PAGE_SIZE) - sg_list_size += sg_list_increment; - - /* - * Try to reduce the amount of wastage by allocating - * multiple pages. - */ - best_list_size = sg_list_size; - max_list_size = roundup(sg_list_increment, PAGE_SIZE); - if (max_list_size < 4 * PAGE_SIZE) - max_list_size = 4 * PAGE_SIZE; - if (max_list_size > (AHD_SCB_MAX_ALLOC * sg_list_increment)) - max_list_size = (AHD_SCB_MAX_ALLOC * sg_list_increment); - while ((sg_list_size + sg_list_increment) <= max_list_size - && (sg_list_size % PAGE_SIZE) != 0) { - bus_size_t new_mod; - bus_size_t best_mod; - - sg_list_size += sg_list_increment; - new_mod = sg_list_size % PAGE_SIZE; - best_mod = best_list_size % PAGE_SIZE; - if (new_mod > best_mod || new_mod == 0) { - best_list_size = sg_list_size; - } - } - return (best_list_size); -} - -/* - * Allocate a controller structure for a new device - * and perform initial initializion. - */ -struct ahd_softc * -ahd_alloc(void *platform_arg, char *name) -{ - struct ahd_softc *ahd; - -#ifndef __FreeBSD__ - ahd = malloc(sizeof(*ahd), M_DEVBUF, M_NOWAIT); - if (!ahd) { - printf("aic7xxx: cannot malloc softc!\n"); - free(name, M_DEVBUF); - return NULL; - } -#else - ahd = device_get_softc((device_t)platform_arg); -#endif - memset(ahd, 0, sizeof(*ahd)); - ahd->seep_config = malloc(sizeof(*ahd->seep_config), - M_DEVBUF, M_NOWAIT); - if (ahd->seep_config == NULL) { -#ifndef __FreeBSD__ - free(ahd, M_DEVBUF); -#endif - free(name, M_DEVBUF); - return (NULL); - } - LIST_INIT(&ahd->pending_scbs); - /* We don't know our unit number until the OSM sets it */ - ahd->name = name; - ahd->unit = -1; - ahd->description = NULL; - ahd->bus_description = NULL; - ahd->channel = 'A'; - ahd->chip = AHD_NONE; - ahd->features = AHD_FENONE; - ahd->bugs = AHD_BUGNONE; - ahd->flags = AHD_SPCHK_ENB_A|AHD_RESET_BUS_A|AHD_TERM_ENB_A - | AHD_EXTENDED_TRANS_A|AHD_STPWLEVEL_A; - ahd_timer_init(&ahd->reset_timer); - - if (ahd_platform_alloc(ahd, platform_arg) != 0) { - ahd_free(ahd); - ahd = NULL; - } - return (ahd); -} - -int -ahd_softc_init(struct ahd_softc *ahd) -{ - - ahd->unpause = 0; - ahd->pause = PAUSE; - return (0); -} - -void -ahd_softc_insert(struct ahd_softc *ahd) -{ - struct ahd_softc *list_ahd; - -#if AHD_PCI_CONFIG > 0 - /* - * Second Function PCI devices need to inherit some - * settings from function 0. - */ - if ((ahd->features & AHD_MULTI_FUNC) != 0) { - TAILQ_FOREACH(list_ahd, &ahd_tailq, links) { - ahd_dev_softc_t list_pci; - ahd_dev_softc_t pci; - - list_pci = list_ahd->dev_softc; - pci = ahd->dev_softc; - if (ahd_get_pci_slot(list_pci) == ahd_get_pci_slot(pci) - && ahd_get_pci_bus(list_pci) == ahd_get_pci_bus(pci)) { - struct ahd_softc *master; - struct ahd_softc *slave; - - if (ahd_get_pci_function(list_pci) == 0) { - master = list_ahd; - slave = ahd; - } else { - master = ahd; - slave = list_ahd; - } - slave->flags &= ~AHD_BIOS_ENABLED; - slave->flags |= - master->flags & AHD_BIOS_ENABLED; - slave->flags &= ~AHD_PRIMARY_CHANNEL; - slave->flags |= - master->flags & AHD_PRIMARY_CHANNEL; - break; - } - } - } -#endif - - /* - * Insertion sort into our list of softcs. - */ - list_ahd = TAILQ_FIRST(&ahd_tailq); - while (list_ahd != NULL - && ahd_softc_comp(list_ahd, ahd) <= 0) - list_ahd = TAILQ_NEXT(list_ahd, links); - if (list_ahd != NULL) - TAILQ_INSERT_BEFORE(list_ahd, ahd, links); - else - TAILQ_INSERT_TAIL(&ahd_tailq, ahd, links); - ahd->init_level++; -} - -/* - * Verify that the passed in softc pointer is for a - * controller that is still configured. - */ -struct ahd_softc * -ahd_find_softc(struct ahd_softc *ahd) -{ - struct ahd_softc *list_ahd; - - TAILQ_FOREACH(list_ahd, &ahd_tailq, links) { - if (list_ahd == ahd) - return (ahd); - } - return (NULL); -} - -void -ahd_set_unit(struct ahd_softc *ahd, int unit) -{ - ahd->unit = unit; -} - -void -ahd_set_name(struct ahd_softc *ahd, char *name) -{ - if (ahd->name != NULL) - free(ahd->name, M_DEVBUF); - ahd->name = name; -} - -void -ahd_free(struct ahd_softc *ahd) -{ - int i; - - ahd_fini_scbdata(ahd); - switch (ahd->init_level) { - default: - case 5: - ahd_shutdown(ahd); - TAILQ_REMOVE(&ahd_tailq, ahd, links); - /* FALLTHROUGH */ - case 4: - ahd_dmamap_unload(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap); - /* FALLTHROUGH */ - case 3: - ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo, - ahd->shared_data_dmamap); - ahd_dmamap_destroy(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap); - /* FALLTHROUGH */ - case 2: - ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat); - case 1: -#ifndef __linux__ - ahd_dma_tag_destroy(ahd, ahd->buffer_dmat); -#endif - break; - case 0: - break; - } - -#ifndef __linux__ - ahd_dma_tag_destroy(ahd, ahd->parent_dmat); -#endif - ahd_platform_free(ahd); - for (i = 0; i < AHD_NUM_TARGETS; i++) { - struct ahd_tmode_tstate *tstate; - - tstate = ahd->enabled_targets[i]; - if (tstate != NULL) { -#if AHD_TARGET_MODE - int j; - - for (j = 0; j < AHD_NUM_LUNS; j++) { - struct ahd_tmode_lstate *lstate; - - lstate = tstate->enabled_luns[j]; - if (lstate != NULL) { - xpt_free_path(lstate->path); - free(lstate, M_DEVBUF); - } - } -#endif - free(tstate, M_DEVBUF); - } - } -#if AHD_TARGET_MODE - if (ahd->black_hole != NULL) { - xpt_free_path(ahd->black_hole->path); - free(ahd->black_hole, M_DEVBUF); - } -#endif - if (ahd->name != NULL) - free(ahd->name, M_DEVBUF); - if (ahd->seep_config != NULL) - free(ahd->seep_config, M_DEVBUF); -#ifndef __FreeBSD__ - free(ahd, M_DEVBUF); -#endif - return; -} - -void -ahd_shutdown(void *arg) -{ - struct ahd_softc *ahd; - - ahd = (struct ahd_softc *)arg; - - /* This will reset most registers to 0, but not all */ - ahd_reset(ahd); -} - -/* - * Reset the controller and record some information about it - * that is only available just after a reset. - */ -int -ahd_reset(struct ahd_softc *ahd) -{ - u_int sxfrctl1; - int wait; - uint32_t cmd; - - /* - * Preserve the value of the SXFRCTL1 register for all channels. - * It contains settings that affect termination and we don't want - * to disturb the integrity of the bus. - */ - ahd_pause(ahd); - sxfrctl1 = ahd_inb(ahd, SXFRCTL1); - - cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); - if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) { - uint32_t mod_cmd; - - /* - * A4 Razor #632 - * During the assertion of CHIPRST, the chip - * does not disable its parity logic prior to - * the start of the reset. This may cause a - * parity error to be detected and thus a - * spurious SERR or PERR assertion. Disble - * PERR and SERR responses during the CHIPRST. - */ - mod_cmd = cmd & ~(PCIM_CMD_PERRESPEN|PCIM_CMD_SERRESPEN); - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, - mod_cmd, /*bytes*/2); - } - ahd_outb(ahd, HCNTRL, CHIPRST | ahd->pause); - - /* - * Ensure that the reset has finished. We delay 1000us - * prior to reading the register to make sure the chip - * has sufficiently completed its reset to handle register - * accesses. - */ - wait = 1000; - do { - ahd_delay(1000); - } while (--wait && !(ahd_inb(ahd, HCNTRL) & CHIPRSTACK)); - - if (wait == 0) { - printf("%s: WARNING - Failed chip reset! " - "Trying to initialize anyway.\n", ahd_name(ahd)); - } - ahd_outb(ahd, HCNTRL, ahd->pause); - - if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) { - /* - * Clear any latched PCI error status and restore - * previous SERR and PERR response enables. - */ - ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, - 0xFF, /*bytes*/1); - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, - cmd, /*bytes*/2); - } - /* After a reset, we know the state of the mode register. */ - ahd_known_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - - /* Determine chip configuration */ - ahd->features &= ~AHD_WIDE; - if ((ahd_inb(ahd, SBLKCTL) & SELWIDE) != 0) - ahd->features |= AHD_WIDE; - - /* - * Restore SXFRCTL1. - * - * We must always initialize STPWEN to 1 before we - * restore the saved values. STPWEN is initialized - * to a tri-state condition which can only be cleared - * by turning it on. - */ - ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN); - ahd_outb(ahd, SXFRCTL1, sxfrctl1); - - /* - * If a recovery action has forced a chip reset, - * re-initialize the chip to our likeing. - */ - if (ahd->init_level > 0) - ahd_chip_init(ahd); - - return (0); -} - -/* - * Determine the number of SCBs available on the controller - */ -int -ahd_probe_scbs(struct ahd_softc *ahd) { - int i; - - AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK), - ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK)); - for (i = 0; i < AHD_SCB_MAX; i++) { - int j; - - ahd_set_scbptr(ahd, i); - ahd_outw(ahd, SCB_BASE, i); - for (j = 2; j < 64; j++) - ahd_outb(ahd, SCB_BASE+j, 0); - /* Start out life as unallocated (needing an abort) */ - ahd_outb(ahd, SCB_CONTROL, MK_MESSAGE); - if (ahd_inw_scbram(ahd, SCB_BASE) != i) - break; - ahd_set_scbptr(ahd, 0); - if (ahd_inw_scbram(ahd, SCB_BASE) != 0) - break; - } - return (i); -} - -static void -ahd_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - bus_addr_t *baddr; - - baddr = (bus_addr_t *)arg; - *baddr = segs->ds_addr; -} - -static void -ahd_initialize_hscbs(struct ahd_softc *ahd) -{ - int i; - - for (i = 0; i < ahd->scb_data.maxhscbs; i++) { - ahd_set_scbptr(ahd, i); - - /* Clear the control byte. */ - ahd_outb(ahd, SCB_CONTROL, 0); - - /* Set the next pointer */ - ahd_outw(ahd, SCB_NEXT, SCB_LIST_NULL); - } -} - -static int -ahd_init_scbdata(struct ahd_softc *ahd) -{ - struct scb_data *scb_data; - - scb_data = &ahd->scb_data; - SLIST_INIT(&scb_data->free_scbs); - SLIST_INIT(&scb_data->hscb_maps); - SLIST_INIT(&scb_data->sg_maps); - SLIST_INIT(&scb_data->sense_maps); - - /* Determine the number of hardware SCBs and initialize them */ - scb_data->maxhscbs = ahd_probe_scbs(ahd); - if (scb_data->maxhscbs == 0) { - printf("%s: No SCB space found\n", ahd_name(ahd)); - return (ENXIO); - } - - ahd_initialize_hscbs(ahd); - - /* - * Create our DMA tags. These tags define the kinds of device - * accessible memory allocations and memory mappings we will - * need to perform during normal operation. - * - * Unless we need to further restrict the allocation, we rely - * on the restrictions of the parent dmat, hence the common - * use of MAXADDR and MAXSIZE. - */ - - /* DMA tag for our hardware scb structures */ - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, - /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, - /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - PAGE_SIZE, /*nsegments*/1, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/0, &scb_data->hscb_dmat) != 0) { - goto error_exit; - } - - scb_data->init_level++; - - /* DMA tag for our S/G structures. */ - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, - /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, - /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - ahd_sglist_allocsize(ahd), /*nsegments*/1, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/0, &scb_data->sg_dmat) != 0) { - goto error_exit; - } -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MEMORY) != 0) - printf("%s: ahd_sglist_allocsize = 0x%x\n", ahd_name(ahd), - ahd_sglist_allocsize(ahd)); -#endif - - scb_data->init_level++; - - /* DMA tag for our sense buffers. We allocate in page sized chunks */ - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, - /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, - /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - PAGE_SIZE, /*nsegments*/1, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/0, &scb_data->sense_dmat) != 0) { - goto error_exit; - } - - scb_data->init_level++; - - /* Perform initial CCB allocation */ - ahd_alloc_scbs(ahd); - - if (scb_data->numscbs == 0) { - printf("%s: ahd_init_scbdata - " - "Unable to allocate initial scbs\n", - ahd_name(ahd)); - goto error_exit; - } - - /* - * Reserve an SCB as the initial "next SCB" to be - * queued to the controller. - */ - ahd->next_queued_scb = ahd_get_scb(ahd); - - /* - * Note that we were successfull - */ - return (0); - -error_exit: - - return (ENOMEM); -} - -static void -ahd_fini_scbdata(struct ahd_softc *ahd) -{ - struct scb_data *scb_data; - - scb_data = &ahd->scb_data; - if (scb_data == NULL) - return; - - switch (scb_data->init_level) { - default: - case 7: - { - struct map_node *sns_map; - - while ((sns_map = SLIST_FIRST(&scb_data->sense_maps)) != NULL) { - SLIST_REMOVE_HEAD(&scb_data->sense_maps, links); - ahd_dmamap_unload(ahd, scb_data->sense_dmat, - sns_map->dmamap); - ahd_dmamem_free(ahd, scb_data->sense_dmat, - sns_map->vaddr, sns_map->dmamap); - free(sns_map, M_DEVBUF); - } - ahd_dma_tag_destroy(ahd, scb_data->sense_dmat); - /* FALLTHROUGH */ - } - case 6: - { - struct map_node *sg_map; - - while ((sg_map = SLIST_FIRST(&scb_data->sg_maps)) != NULL) { - SLIST_REMOVE_HEAD(&scb_data->sg_maps, links); - ahd_dmamap_unload(ahd, scb_data->sg_dmat, - sg_map->dmamap); - ahd_dmamem_free(ahd, scb_data->sg_dmat, - sg_map->vaddr, sg_map->dmamap); - free(sg_map, M_DEVBUF); - } - ahd_dma_tag_destroy(ahd, scb_data->sg_dmat); - /* FALLTHROUGH */ - } - case 5: - { - struct map_node *hscb_map; - - while ((hscb_map = SLIST_FIRST(&scb_data->hscb_maps)) != NULL) { - SLIST_REMOVE_HEAD(&scb_data->hscb_maps, links); - ahd_dmamap_unload(ahd, scb_data->hscb_dmat, - hscb_map->dmamap); - ahd_dmamem_free(ahd, scb_data->hscb_dmat, - hscb_map->vaddr, hscb_map->dmamap); - free(hscb_map, M_DEVBUF); - } - ahd_dma_tag_destroy(ahd, scb_data->hscb_dmat); - /* FALLTHROUGH */ - } - case 4: - case 3: - case 2: - case 1: - case 0: - break; - } -} - -/* - * DSP filter Bypass must be enabled until the first selection - * after a change in bus mode (Razor #491 and #493). - */ -static void -ahd_setup_iocell_workaround(struct ahd_softc *ahd) -{ - ahd_mode_state saved_modes; - - saved_modes = ahd_save_modes(ahd); - ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); - ahd_outb(ahd, DSPDATACTL, ahd_inb(ahd, DSPDATACTL) - | BYPASSENAB | RCVROFFSTDIS | XMITOFFSTDIS); - ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) | (ENSELDO|ENSELDI)); - ahd_restore_modes(ahd, saved_modes); -} - -static void -ahd_iocell_first_selection(struct ahd_softc *ahd) -{ - ahd_mode_state saved_modes; - u_int sblkctl; - - saved_modes = ahd_save_modes(ahd); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - sblkctl = ahd_inb(ahd, SBLKCTL); - ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); - if ((sblkctl & ENAB40) != 0) { - ahd_outb(ahd, DSPDATACTL, - ahd_inb(ahd, DSPDATACTL) & ~BYPASSENAB); - } - ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) & ~(ENSELDO|ENSELDI)); - ahd_outb(ahd, CLRINT, CLRSCSIINT); - ahd_restore_modes(ahd, saved_modes); -} - -void -ahd_alloc_scbs(struct ahd_softc *ahd) -{ - struct scb_data *scb_data; - struct scb *next_scb; - struct hardware_scb *hscb; - struct map_node *hscb_map; - struct map_node *sg_map; - struct map_node *sense_map; - uint8_t *segs; - uint8_t *sense_data; - bus_addr_t hscb_busaddr; - bus_addr_t sg_busaddr; - bus_addr_t sense_busaddr; - int newcount; - int i; - - scb_data = &ahd->scb_data; - if (scb_data->numscbs >= AHD_SCB_MAX_ALLOC) - /* Can't allocate any more */ - return; - - if (scb_data->scbs_left != 0) { - int offset; - - offset = (PAGE_SIZE / sizeof(*hscb)) - scb_data->scbs_left; - hscb_map = SLIST_FIRST(&scb_data->hscb_maps); - hscb = &((struct hardware_scb *)hscb_map->vaddr)[offset]; - hscb_busaddr = hscb_map->physaddr + (offset * sizeof(*hscb)); - } else { - hscb_map = malloc(sizeof(*hscb_map), M_DEVBUF, M_NOWAIT); - - if (hscb_map == NULL) - return; - - /* Allocate the next batch of hardware SCBs */ - if (ahd_dmamem_alloc(ahd, scb_data->hscb_dmat, - (void **)&hscb_map->vaddr, - BUS_DMA_NOWAIT, &hscb_map->dmamap) != 0) { - free(hscb_map, M_DEVBUF); - return; - } - - SLIST_INSERT_HEAD(&scb_data->hscb_maps, hscb_map, links); - - ahd_dmamap_load(ahd, scb_data->hscb_dmat, hscb_map->dmamap, - hscb_map->vaddr, PAGE_SIZE, ahd_dmamap_cb, - &hscb_map->physaddr, /*flags*/0); - - hscb = (struct hardware_scb *)hscb_map->vaddr; - hscb_busaddr = hscb_map->physaddr; - scb_data->scbs_left = PAGE_SIZE / sizeof(*hscb); - } - - if (scb_data->sgs_left != 0) { - int offset; - - offset = ahd_sglist_allocsize(ahd) - - (scb_data->sgs_left * ahd_sglist_size(ahd)); - sg_map = SLIST_FIRST(&scb_data->sg_maps); - segs = sg_map->vaddr + offset; - sg_busaddr = sg_map->physaddr + offset; - } else { - sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT); - - if (sg_map == NULL) - return; - - /* Allocate the next batch of S/G lists */ - if (ahd_dmamem_alloc(ahd, scb_data->sg_dmat, - (void **)&sg_map->vaddr, - BUS_DMA_NOWAIT, &sg_map->dmamap) != 0) { - free(sg_map, M_DEVBUF); - return; - } - - SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links); - - ahd_dmamap_load(ahd, scb_data->sg_dmat, sg_map->dmamap, - sg_map->vaddr, ahd_sglist_allocsize(ahd), - ahd_dmamap_cb, &sg_map->physaddr, /*flags*/0); - - segs = sg_map->vaddr; - sg_busaddr = sg_map->physaddr; - scb_data->sgs_left = - ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd); -#ifdef AHD_DEBUG - if (ahd_debug & AHD_SHOW_MEMORY) - printf("Mapped SG data\n"); -#endif - } - - if (scb_data->sense_left != 0) { - int offset; - - offset = PAGE_SIZE - (AHD_SENSE_BUFSIZE * scb_data->sense_left); - sense_map = SLIST_FIRST(&scb_data->sense_maps); - sense_data = sense_map->vaddr + offset; - sense_busaddr = sense_map->physaddr + offset; - } else { - sense_map = malloc(sizeof(*sense_map), M_DEVBUF, M_NOWAIT); - - if (sense_map == NULL) - return; - - /* Allocate the next batch of sense buffers */ - if (ahd_dmamem_alloc(ahd, scb_data->sense_dmat, - (void **)&sense_map->vaddr, - BUS_DMA_NOWAIT, &sense_map->dmamap) != 0) { - free(sense_map, M_DEVBUF); - return; - } - - SLIST_INSERT_HEAD(&scb_data->sense_maps, sense_map, links); - - ahd_dmamap_load(ahd, scb_data->sense_dmat, sense_map->dmamap, - sense_map->vaddr, PAGE_SIZE, ahd_dmamap_cb, - &sense_map->physaddr, /*flags*/0); - - sense_data = sense_map->vaddr; - sense_busaddr = sense_map->physaddr; - scb_data->sense_left = PAGE_SIZE / AHD_SENSE_BUFSIZE; -#ifdef AHD_DEBUG - if (ahd_debug & AHD_SHOW_MEMORY) - printf("Mapped sense data\n"); -#endif - } - - newcount = MIN(scb_data->sense_left, scb_data->scbs_left); - newcount = MIN(newcount, scb_data->sgs_left); - newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs)); - scb_data->sense_left -= newcount; - scb_data->scbs_left -= newcount; - scb_data->sgs_left -= newcount; - for (i = 0; i < newcount; i++) { - struct scb_platform_data *pdata; -#ifndef __linux__ - int error; -#endif - next_scb = (struct scb *)malloc(sizeof(*next_scb), - M_DEVBUF, M_NOWAIT); - if (next_scb == NULL) - break; - - pdata = (struct scb_platform_data *)malloc(sizeof(*pdata), - M_DEVBUF, M_NOWAIT); - if (pdata == NULL) { - free(next_scb, M_DEVBUF); - break; - } - next_scb->platform_data = pdata; - next_scb->hscb_map = hscb_map; - next_scb->sg_map = sg_map; - next_scb->sense_map = sense_map; - next_scb->sg_list = segs; - next_scb->sense_data = sense_data; - next_scb->sense_busaddr = sense_busaddr; - next_scb->hscb = hscb; - hscb->hscb_busaddr = ahd_htole32(hscb_busaddr); - - /* - * The sequencer always starts with the second entry. - * The first entry is embedded in the scb. - */ - next_scb->sg_list_busaddr = sg_busaddr; - if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) - next_scb->sg_list_busaddr - += sizeof(struct ahd_dma64_seg); - else - next_scb->sg_list_busaddr += sizeof(struct ahd_dma_seg); - next_scb->ahd_softc = ahd; - next_scb->flags = SCB_FREE; -#ifndef __linux__ - error = ahd_dmamap_create(ahd, ahd->buffer_dmat, /*flags*/0, - &next_scb->dmamap); - if (error != 0) { - free(next_scb, M_DEVBUF); - free(pdata, M_DEVBUF); - break; - } -#endif - next_scb->hscb->tag = ahd_htole16(scb_data->numscbs); - - SLIST_INSERT_HEAD(&scb_data->free_scbs, - next_scb, links.sle); - hscb++; - hscb_busaddr += sizeof(*hscb); - segs += ahd_sglist_size(ahd); - sg_busaddr += ahd_sglist_size(ahd); - sense_data += AHD_SENSE_BUFSIZE; - sense_busaddr += AHD_SENSE_BUFSIZE; - scb_data->numscbs++; - } -} - -void -ahd_controller_info(struct ahd_softc *ahd, char *buf) -{ - const char *speed; - const char *type; - int len; - - len = sprintf(buf, "%s: ", ahd_chip_names[ahd->chip & AHD_CHIPID_MASK]); - buf += len; - - speed = "Ultra320 "; - if ((ahd->features & AHD_WIDE) != 0) { - type = "Wide"; - } else { - type = "Single"; - } - len = sprintf(buf, "%s%sChannel %c, SCSI Id=%d, ", - speed, type, ahd->channel, ahd->our_id); - buf += len; - - sprintf(buf, "%s, %d SCBs", ahd->bus_description, - ahd->scb_data.maxhscbs); -} - -static const char *channel_strings[] = { - "Primary Low", - "Primary High", - "Secondary Low", - "Secondary High" -}; - -static const char *termstat_strings[] = { - "Terminated Correctly", - "Over Terminated", - "Under Terminated", - "Not Configured" -}; - -/* - * Start the board, ready for normal operation - */ -int -ahd_init(struct ahd_softc *ahd) -{ - size_t driver_data_size; - int i; - int error; - int wait; - u_int warn_user; - uint8_t current_sensing; - uint8_t fstat; - - AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); - - /* - * Verify that the compiler hasn't over-agressively - * padded important structures. - */ - if (sizeof(struct hardware_scb) != 64) - panic("Hardware SCB size is incorrect"); - -#ifdef AHD_DEBUG_SEQUENCER - ahd->flags |= AHD_SEQUENCER_DEBUG; -#endif - - /* - * Default to allowing initiator operations. - */ - ahd->flags |= AHD_INITIATORROLE; - - /* - * Only allow target mode features if this unit has them enabled. - */ - if ((AHD_TMODE_ENABLE & (0x1 << ahd->unit)) == 0) - ahd->features &= ~AHD_TARGETMODE; - -#ifndef __linux__ - /* DMA tag for mapping buffers into device visible space. */ - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, - /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, - /*lowaddr*/BUS_SPACE_MAXADDR, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - /*maxsize*/MAXBSIZE, /*nsegments*/AHD_NSEG, - /*maxsegsz*/AHD_MAXTRANSFER_SIZE, - /*flags*/BUS_DMA_ALLOCNOW, - &ahd->buffer_dmat) != 0) { - return (ENOMEM); - } -#endif - - ahd->init_level++; - - /* - * DMA tag for our command fifos and other data in system memory - * the card's sequencer must be able to access. For initiator - * roles, we need to allocate space for the qoutfifo. When providing - * for the target mode role, we must additionally provide space for - * the incoming target command fifo. - */ - driver_data_size = AHD_SCB_MAX * sizeof(uint16_t); - if ((ahd->features & AHD_TARGETMODE) != 0) - driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd); - if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) - driver_data_size += PKT_OVERRUN_BUFSIZE; - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, - /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, - /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - driver_data_size, - /*nsegments*/1, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/0, &ahd->shared_data_dmat) != 0) { - return (ENOMEM); - } - - ahd->init_level++; - - /* Allocation of driver data */ - if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat, - (void **)&ahd->qoutfifo, - BUS_DMA_NOWAIT, &ahd->shared_data_dmamap) != 0) { - return (ENOMEM); - } - - ahd->init_level++; - - /* And permanently map it in */ - ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, - ahd->qoutfifo, driver_data_size, ahd_dmamap_cb, - &ahd->shared_data_busaddr, /*flags*/0); - - if ((ahd->features & AHD_TARGETMODE) != 0) { - /* XXX sequencer assumes qoutfifo is first. */ - ahd->targetcmds = (struct target_cmd *)ahd->qoutfifo; - ahd->qoutfifo = (uint16_t *)&ahd->targetcmds[AHD_TMODE_CMDS]; - } - - if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) - ahd->overrun_buf = (uint8_t *)&ahd->qoutfifo[AHD_SCB_MAX]; - - ahd->init_level++; - - /* Allocate SCB data now that buffer_dmat is initialized */ - if (ahd_init_scbdata(ahd) != 0) - return (ENOMEM); - - if ((ahd->flags & AHD_INITIATORROLE) == 0) - ahd->flags &= ~AHD_RESET_BUS_A; - - ahd_chip_init(ahd); - - AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); - - /* - * Wait for up to 500ms for our transceivers - * to settle. If the adapter does not have - * a cable attached, the tranceivers may - * never settle, so don't complain if we - * fail here. - */ - for (wait = 10000; - (ahd_inb(ahd, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait; - wait--) - ahd_delay(100); - if ((ahd->flags & AHD_CURRENT_SENSING) == 0) - goto init_done; - - /* - * Verify termination based on current draw and - * warn user if the bus is over/under terminated. - */ - error = ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, - CURSENSE_ENB); - if (error != 0) { - printf("%s: current sensing timeout 1\n", ahd_name(ahd)); - goto init_done; - } - for (i = 20, fstat = FLX_FSTAT_BUSY; - (fstat & FLX_FSTAT_BUSY) != 0 && i; i--) { - error = ahd_read_flexport(ahd, FLXADDR_FLEXSTAT, &fstat); - if (error != 0) { - printf("%s: current sensing timeout 2\n", - ahd_name(ahd)); - goto init_done; - } - } - if (i == 0) { - printf("%s: Timedout during current-sensing test\n", - ahd_name(ahd)); - goto init_done; - } - - /* Latch Current Sensing status. */ - error = ahd_read_flexport(ahd, FLXADDR_CURRENT_STAT, ¤t_sensing); - if (error != 0) { - printf("%s: current sensing timeout 3\n", ahd_name(ahd)); - goto init_done; - } - - /* Diable current sensing. */ - ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0); - -#ifdef AHD_DEBUG - if ((ahd_debug & AHD_SHOW_TERMCTL) != 0) { - printf("%s: current_sensing == 0x%x\n", - ahd_name(ahd), current_sensing); - } -#endif - warn_user = 0; - for (i = 0; i < 4; i++, current_sensing >>= FLX_CSTAT_SHIFT) { - u_int term_stat; - - term_stat = (current_sensing & FLX_CSTAT_MASK); - switch (term_stat) { - case FLX_CSTAT_OVER: - case FLX_CSTAT_UNDER: - warn_user++; - case FLX_CSTAT_INVALID: - case FLX_CSTAT_OKAY: - if (warn_user == 0 && bootverbose == 0) - break; - printf("%s: %s Channel %s\n", ahd_name(ahd), - channel_strings[i], termstat_strings[term_stat]); - break; - } - } - if (warn_user) { - printf("%s: WARNING. Termination is not configured correctly.\n" - "%s: WARNING. SCSI bus operations may FAIL.\n", - ahd_name(ahd), ahd_name(ahd)); - } -init_done: - ahd_restart(ahd); - return (0); -} - -/* - * (Re)initialize chip state after a chip reset. - */ -static void -ahd_chip_init(struct ahd_softc *ahd) -{ - uint32_t busaddr; - u_int sxfrctl1; - u_int scsiseq_template; - u_int i; - u_int target; - - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - /* - * Take the LED out of diagnostic mode - */ - ahd_outb(ahd, SBLKCTL, ahd_inb(ahd, SBLKCTL) & ~(DIAGLEDEN|DIAGLEDON)); - - /* Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1. */ - ahd_outb(ahd, IOWNID, ahd->our_id); - ahd_outb(ahd, TOWNID, ahd->our_id); - sxfrctl1 = (ahd->flags & AHD_TERM_ENB_A) != 0 ? STPWEN : 0; - sxfrctl1 |= (ahd->flags & AHD_SPCHK_ENB_A) != 0 ? ENSPCHK : 0; - if ((ahd->bugs & AHD_LONG_SETIMO_BUG) - && (ahd->seltime != STIMESEL_MIN)) { - /* - * The selection timer duration is twice as long - * as it should be. Halve it by adding "1" to - * the user specified setting. - */ - sxfrctl1 |= ahd->seltime + STIMESEL_BUG_ADJ; - } else { - sxfrctl1 |= ahd->seltime; - } - - ahd_outb(ahd, SXFRCTL0, DFON); - ahd_outb(ahd, SXFRCTL1, sxfrctl1|ahd->seltime|ENSTIMER|ACTNEGEN); - ahd_outb(ahd, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR); - - /* Initialize mode specific S/G state. */ - for (i = 0; i < 2; i++) { - ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i); - ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR); - ahd_outw(ahd, LONGJMP_SCB, SCB_LIST_NULL); - ahd_outb(ahd, SG_STATE, 0); - ahd_outb(ahd, CLRSEQINTSRC, 0xFF); - ahd_outb(ahd, SEQIMODE, - ENSAVEPTRS|ENCFG4DATA|ENCFG4ISTAT - |ENCFG4TSTAT|ENCFG4ICMD|ENCFG4TCMD); - } - - ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); - ahd_outb(ahd, DSCOMMAND0, ahd_inb(ahd, DSCOMMAND0)|MPARCKEN|CACHETHEN); - ahd_outb(ahd, DFF_THRSH, RD_DFTHRSH_75|WR_DFTHRSH_75); - ahd_outb(ahd, SIMODE0, ENIOERR|ENOVERRUN); - ahd_outb(ahd, SIMODE3, ENNTRAMPERR|ENOSRAMPERR); - ahd_outb(ahd, OPTIONMODE, AUTOACKEN|BUSFREEREV|AUTO_MSGOUT_DE); - if ((ahd->chip & AHD_BUS_MASK) == AHD_PCIX) - /* - * Do not issue a target abort when a split completion - * error occurs. Let our PCIX interrupt handler deal - * with it instead. H2A4 Razor #625 - */ - ahd_outb(ahd, PCIXCTL, ahd_inb(ahd, PCIXCTL) | SPLTSTADIS); - - /* - * Tweak IOCELL settings. - */ - if ((ahd->flags & AHD_CPQ_BOARD) != 0) { - for (i = 0; i < NUMDSPS; i++) { - ahd_outb(ahd, DSPSELECT, i); - ahd_outb(ahd, WRTBIASCTL, WRTBIASCTL_CPQ_DEFAULT); - } - } - ahd_setup_iocell_workaround(ahd); - - /* - * Enable LQI Manager interrupts. - */ - ahd_outb(ahd, LQIMODE1, ENLQIPHASE_LQ|ENLQIPHASE_NLQ|ENLIQABORT - | ENLQICRCI_LQ|ENLQICRCI_NLQ|ENLQIBADLQI - | ENLQIOVERI_LQ|ENLQIOVERI_NLQ); - ahd_outb(ahd, LQOMODE0, ENLQOATNLQ|ENLQOATNPKT|ENLQOTCRC); - /* - * An interrupt from LQOBUSFREE is made redundant by the - * BUSFREE interrupt. We choose to have the sequencer catch - * LQOPHCHGINPKT errors manually for the command phase at the - * start of a packetized selection case. - ahd_outb(ahd, LQOMODE1, ENLQOBUSFREE|ENLQOPHACHGINPKT); - */ - ahd_outb(ahd, LQOMODE1, 0); - - /* - * Setup sequencer interrupt handler. - */ - ahd_outw(ahd, INTVEC1_ADDR, ahd_resolve_seqaddr(ahd, LABEL_seq_isr)); - - /* - * Setup SCB Offset registers. - */ - ahd_outb(ahd, LUNPTR, offsetof(struct hardware_scb, lun)); - ahd_outb(ahd, CMDLENPTR, offsetof(struct hardware_scb, cdb_len)); - ahd_outb(ahd, ATTRPTR, - offsetof(struct hardware_scb, task_attribute_nonpkt_tag)); - ahd_outb(ahd, FLAGPTR, offsetof(struct hardware_scb, task_management)); - ahd_outb(ahd, CMDPTR, offsetof(struct hardware_scb, - shared_data.idata.cdb)); - ahd_outb(ahd, QNEXTPTR, - offsetof(struct hardware_scb, next_hscb_busaddr)); - ahd_outb(ahd, ABRTBITPTR, MK_MESSAGE_BIT_OFFSET); - ahd_outb(ahd, ABRTBYTEPTR, offsetof(struct hardware_scb, control)); - ahd_outb(ahd, LUNLEN, sizeof(ahd->next_queued_scb->hscb->lun) - 1); - ahd_outb(ahd, CDBLIMIT, SCB_CDB_LEN_PTR - 1); - ahd_outb(ahd, MAXCMD, 0xFF); - ahd_outb(ahd, SCBAUTOPTR, - AUSCBPTR_EN | offsetof(struct hardware_scb, tag)); - - /* We haven't been enabled for target mode yet. */ - ahd_outb(ahd, MULTARGID, 0); - ahd_outb(ahd, MULTARGID + 1, 0); - - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - /* - * Clear the spare bytes in the neg table to avoid - * spurious parity errors. - */ - for (target = 0; target < AHD_NUM_TARGETS; target++) { - - ahd_outb(ahd, NEGOADDR, target); - ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP); - for (i = 0; i < AHD_NUM_ANNEXCOLS; i++) - ahd_outb(ahd, ANNEXDAT, 0); - } - ahd_outb(ahd, CLRSINT3, NTRAMPERR|OSRAMPERR); - - /* - * Always enable abort on incoming L_Qs if this feature is - * supported. We use this to catch invalid SCB references. - */ - if ((ahd->bugs & AHD_ABORT_LQI_BUG) == 0) - ahd_outb(ahd, LQCTL1, ABORTPENDING); - else - ahd_outb(ahd, LQCTL1, 0); - - /* All of our queues are empty */ - ahd->qoutfifonext = 0; - for (i = 0; i < AHD_QOUT_SIZE; i++) - ahd->qoutfifo[i] = SCB_LIST_NULL_LE; - ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD); - - ahd->qinfifonext = 0; - for (i = 0; i < AHD_QIN_SIZE; i++) - ahd->qinfifo[i] = SCB_LIST_NULL; - - if ((ahd->features & AHD_TARGETMODE) != 0) { - /* All target command blocks start out invalid. */ - for (i = 0; i < AHD_TMODE_CMDS; i++) - ahd->targetcmds[i].cmd_valid = 0; - ahd_sync_tqinfifo(ahd, BUS_DMASYNC_PREREAD); - ahd->tqinfifonext = 1; - ahd_outb(ahd, KERNEL_TQINPOS, ahd->tqinfifonext - 1); - ahd_outb(ahd, TQINPOS, ahd->tqinfifonext); - } - - /* Initialize Scratch Ram. */ - ahd_outb(ahd, SEQ_FLAGS, 0); - ahd_outb(ahd, SEQ_FLAGS2, 0); - - /* We don't have any waiting selections */ - ahd_outw(ahd, WAITING_TID_HEAD, SCB_LIST_NULL); - ahd_outw(ahd, WAITING_TID_TAIL, SCB_LIST_NULL); - for (i = 0; i < AHD_NUM_TARGETS; i++) - ahd_outw(ahd, WAITING_SCB_TAILS + (2 * i), SCB_LIST_NULL); - - /* - * Nobody is waiting to be DMAed into the QOUTFIFO. - */ - ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL); - ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL); - ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL); - - /* - * The Freeze Count is 0. - */ - ahd_outw(ahd, QFREEZE_COUNT, 0); - - /* - * Tell the sequencer where it can find our arrays in memory. - */ - busaddr = ahd->shared_data_busaddr; - ahd_outb(ahd, SHARED_DATA_ADDR, busaddr & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 3, (busaddr >> 24) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR, busaddr & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 3, (busaddr >> 24) & 0xFF); - - /* - * Setup the allowed SCSI Sequences based on operational mode. - * If we are a target, we'll enable select in operations once - * we've had a lun enabled. - */ - scsiseq_template = ENAUTOATNP; - if ((ahd->flags & AHD_INITIATORROLE) != 0) - scsiseq_template |= ENRSELI; - ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq_template); - - /* There are no busy SCBs yet. */ - for (target = 0; target < AHD_NUM_TARGETS; target++) { - int lun; - - for (lun = 0; lun < AHD_NUM_LUNS_NONPKT; lun++) - ahd_unbusy_tcl(ahd, BUILD_TCL_RAW(target, 'A', lun)); - } - - /* - * Always enable abort on incoming L_Qs if this feature is - * supported. We use this to catch invalid SCB references. - */ - if ((ahd->bugs & AHD_ABORT_LQI_BUG) == 0) - ahd_outb(ahd, LQCTL1, ABORTPENDING); - else - ahd_outb(ahd, LQCTL1, 0); - - /* - * Initialize the group code to command length table. - * Vendor Unique codes are set to 0 so we only capture - * the first byte of the cdb. These can be overridden - * when target mode is enabled. - */ - ahd_outb(ahd, CMDSIZE_TABLE, 5); - ahd_outb(ahd, CMDSIZE_TABLE + 1, 9); - ahd_outb(ahd, CMDSIZE_TABLE + 2, 9); - ahd_outb(ahd, CMDSIZE_TABLE + 3, 0); - ahd_outb(ahd, CMDSIZE_TABLE + 4, 15); - ahd_outb(ahd, CMDSIZE_TABLE + 5, 11); - ahd_outb(ahd, CMDSIZE_TABLE + 6, 0); - ahd_outb(ahd, CMDSIZE_TABLE + 7, 0); - - /* Tell the sequencer of our initial queue positions */ - ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); - ahd_outb(ahd, QOFF_CTLSTA, SCB_QSIZE_512); - ahd->qinfifonext = 0; - ahd_set_hnscb_qoff(ahd, ahd->qinfifonext); - ahd_set_hescb_qoff(ahd, 0); - ahd_set_snscb_qoff(ahd, 0); - ahd_set_sescb_qoff(ahd, 0); - ahd_set_sdscb_qoff(ahd, 0); - - /* - * Tell the sequencer which SCB will be the next one it receives. - */ - busaddr = ahd_le32toh(ahd->next_queued_scb->hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); - ahd_loadseq(ahd); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); -} - -/* - * Setup default device and controller settings. - * This should only be called if our probe has - * determined that no configuration data is available. - */ -int -ahd_default_config(struct ahd_softc *ahd) -{ - int targ; - - ahd->our_id = 7; - - /* - * Allocate a tstate to house information for our - * initiator presence on the bus as well as the user - * data for any target mode initiator. - */ - if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) { - printf("%s: unable to allocate ahd_tmode_tstate. " - "Failing attach\n", ahd_name(ahd)); - return (ENOMEM); - } - - for (targ = 0; targ < AHD_NUM_TARGETS; targ++) { - struct ahd_devinfo devinfo; - struct ahd_initiator_tinfo *tinfo; - struct ahd_tmode_tstate *tstate; - uint16_t target_mask; - - TAILQ_INIT(&ahd->untagged_queues[targ]); - tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, - targ, &tstate); - /* - * We support SPC2 and SPI4. - */ - tinfo->user.protocol_version = 4; - tinfo->user.transport_version = 4; - - target_mask = 0x01 << targ; - ahd->user_discenable |= target_mask; - tstate->discenable |= target_mask; - ahd->user_tagenable |= target_mask; -#ifdef AHD_FORCE_160 - tinfo->user.period = AHD_SYNCRATE_DT; -#else - tinfo->user.period = AHD_SYNCRATE_160; -#endif - tinfo->user.offset= ~0; - tinfo->user.ppr_options = MSG_EXT_PPR_RD_STRM - | MSG_EXT_PPR_WR_FLOW - | MSG_EXT_PPR_IU_REQ - | MSG_EXT_PPR_QAS_REQ - | MSG_EXT_PPR_DT_REQ; - - tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT; - - /* - * Start out Async/Narrow/Untagged and with - * conservative protocol support. - */ - tinfo->goal.protocol_version = 2; - tinfo->goal.transport_version = 2; - tinfo->curr.protocol_version = 2; - tinfo->curr.transport_version = 2; - ahd_compile_devinfo(&devinfo, ahd->our_id, - targ, CAM_LUN_WILDCARD, - 'A', ROLE_INITIATOR); - tstate->tagenable &= ~target_mask; - ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, - AHD_TRANS_CUR|AHD_TRANS_GOAL, /*paused*/TRUE); - ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0, - /*ppr_options*/0, AHD_TRANS_CUR|AHD_TRANS_GOAL, - /*paused*/TRUE); - /* - * The neg table must be initialized even if the - * new settings above are the same as those from - * when our xfer info data structures were allocated - * and initialized. - */ - ahd_update_neg_table(ahd, &devinfo, &tinfo->curr); - } - return (0); -} - -/* - * Parse device configuration information. - */ -int -ahd_parse_cfgdata(struct ahd_softc *ahd, struct seeprom_config *sc) -{ - int targ; - int max_targ; - - max_targ = sc->max_targets & CFMAXTARG; - ahd->our_id = sc->brtime_id & CFSCSIID; - - /* - * Allocate a tstate to house information for our - * initiator presence on the bus as well as the user - * data for any target mode initiator. - */ - if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) { - printf("%s: unable to allocate ahd_tmode_tstate. " - "Failing attach\n", ahd_name(ahd)); - return (ENOMEM); - } - - for (targ = 0; targ < max_targ; targ++) { - struct ahd_devinfo devinfo; - struct ahd_initiator_tinfo *tinfo; - struct ahd_transinfo *user_tinfo; - struct ahd_tmode_tstate *tstate; - uint16_t target_mask; - - tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, - targ, &tstate); - user_tinfo = &tinfo->user; - - /* - * We support SPC2 and SPI4. - */ - tinfo->user.protocol_version = 4; - tinfo->user.transport_version = 4; - - target_mask = 0x01 << targ; - ahd->user_discenable &= ~target_mask; - tstate->discenable &= ~target_mask; - ahd->user_tagenable &= ~target_mask; - if (sc->device_flags[targ] & CFDISC) { - tstate->discenable |= target_mask; - ahd->user_discenable |= target_mask; - ahd->user_tagenable |= target_mask; - } else { - /* - * Cannot be packetized without disconnection. - */ - sc->device_flags[targ] &= ~CFPACKETIZED; - } - - user_tinfo->ppr_options = 0; - user_tinfo->period = (sc->device_flags[targ] & CFXFER); - if (user_tinfo->period < CFXFER_ASYNC) { - if (user_tinfo->period <= AHD_PERIOD_10MHz) - user_tinfo->ppr_options |= MSG_EXT_PPR_DT_REQ; - user_tinfo->offset = MAX_OFFSET; - } else { - user_tinfo->offset = 0; - user_tinfo->period = AHD_PERIOD_ASYNC; - } -#ifdef AHD_FORCE_160 - if (user_tinfo->period <= AHD_SYNCRATE_160) - user_tinfo->period = AHD_SYNCRATE_DT; -#endif - - if ((sc->device_flags[targ] & CFPACKETIZED) != 0) - user_tinfo->ppr_options |= MSG_EXT_PPR_RD_STRM - | MSG_EXT_PPR_WR_FLOW - | MSG_EXT_PPR_IU_REQ; - - if ((sc->device_flags[targ] & CFQAS) != 0) - user_tinfo->ppr_options |= MSG_EXT_PPR_QAS_REQ; - - if ((sc->device_flags[targ] & CFWIDEB) != 0) - user_tinfo->width = MSG_EXT_WDTR_BUS_16_BIT; - else - user_tinfo->width = MSG_EXT_WDTR_BUS_8_BIT; -#ifdef AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("(%d): %x:%x:%x:%x\n", targ, user_tinfo->width, - user_tinfo->period, user_tinfo->offset, - user_tinfo->ppr_options); -#endif - /* - * Start out Async/Narrow/Untagged and with - * conservative protocol support. - */ - tstate->tagenable &= ~target_mask; - tinfo->goal.protocol_version = 2; - tinfo->goal.transport_version = 2; - tinfo->curr.protocol_version = 2; - tinfo->curr.transport_version = 2; - ahd_compile_devinfo(&devinfo, ahd->our_id, - targ, CAM_LUN_WILDCARD, - 'A', ROLE_INITIATOR); - ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, - AHD_TRANS_CUR|AHD_TRANS_GOAL, /*paused*/TRUE); - ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0, - /*ppr_options*/0, AHD_TRANS_CUR|AHD_TRANS_GOAL, - /*paused*/TRUE); - /* - * The neg table must be initialized even if the - * new settings above are the same as those from - * when our xfer info data structures were allocated - * and initialized. - */ - ahd_update_neg_table(ahd, &devinfo, &tinfo->curr); - } - - ahd->flags &= ~AHD_SPCHK_ENB_A; - if (sc->bios_control & CFSPARITY) - ahd->flags |= AHD_SPCHK_ENB_A; - - ahd->flags &= ~AHD_RESET_BUS_A; - if (sc->bios_control & CFRESETB) - ahd->flags |= AHD_RESET_BUS_A; - - ahd->flags &= ~AHD_EXTENDED_TRANS_A; - if (sc->bios_control & CFEXTEND) - ahd->flags |= AHD_EXTENDED_TRANS_A; - - ahd->flags &= ~AHD_BIOS_ENABLED; - if ((sc->bios_control & CFBIOSSTATE) == CFBS_ENABLED) - ahd->flags |= AHD_BIOS_ENABLED; - - ahd->flags &= ~AHD_STPWLEVEL_A; - if ((sc->adapter_control & CFSTPWLEVEL) != 0) - ahd->flags |= AHD_STPWLEVEL_A; - - return (0); -} - -void -ahd_intr_enable(struct ahd_softc *ahd, int enable) -{ - u_int hcntrl; - - hcntrl = ahd_inb(ahd, HCNTRL); - hcntrl &= ~INTEN; - ahd->pause &= ~INTEN; - ahd->unpause &= ~INTEN; - if (enable) { - hcntrl |= INTEN; - ahd->pause |= INTEN; - ahd->unpause |= INTEN; - } - ahd_outb(ahd, HCNTRL, hcntrl); -} - -/* - * Ensure that the card is paused in a location - * outside of all critical sections and that all - * pending work is completed prior to returning. - * This routine should only be called from outside - * an interrupt context. - */ -void -ahd_pause_and_flushwork(struct ahd_softc *ahd) -{ - int intstat; - int maxloops; - - maxloops = 1000; - ahd->flags |= AHD_ALL_INTERRUPTS; - intstat = 0; - do { - ahd_intr(ahd); - ahd_pause(ahd); - ahd_clear_critical_section(ahd); - if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) - break; - maxloops--; - } while (((intstat = ahd_inb(ahd, INTSTAT)) & INT_PEND) && --maxloops); - if (maxloops == 0) { - printf("Infinite interrupt loop, INTSTAT = %x", - ahd_inb(ahd, INTSTAT)); - } - ahd_platform_flushwork(ahd); - ahd->flags &= ~AHD_ALL_INTERRUPTS; -} - -int -ahd_suspend(struct ahd_softc *ahd) -{ -#if 0 - uint8_t *ptr; - int i; - - ahd_pause_and_flushwork(ahd); - - if (LIST_FIRST(&ahd->pending_scbs) != NULL) - return (EBUSY); - -#if AHD_TARGET_MODE - /* - * XXX What about ATIOs that have not yet been serviced? - * Perhaps we should just refuse to be suspended if we - * are acting in a target role. - */ - if (ahd->pending_device != NULL) - return (EBUSY); -#endif - - /* Save volatile registers */ - ahd->suspend_state.channel[0].scsiseq = ahd_inb(ahd, SCSISEQ0); - ahd->suspend_state.channel[0].sxfrctl0 = ahd_inb(ahd, SXFRCTL0); - ahd->suspend_state.channel[0].sxfrctl1 = ahd_inb(ahd, SXFRCTL1); - ahd->suspend_state.channel[0].simode0 = ahd_inb(ahd, SIMODE0); - ahd->suspend_state.channel[0].simode1 = ahd_inb(ahd, SIMODE1); - ahd->suspend_state.channel[0].seltimer = ahd_inb(ahd, SELTIMER); - ahd->suspend_state.channel[0].seqctl = ahd_inb(ahd, SEQCTL0); - ahd->suspend_state.dscommand0 = ahd_inb(ahd, DSCOMMAND0); - ahd->suspend_state.dspcistatus = ahd_inb(ahd, DSPCISTATUS); - - if ((ahd->features & AHD_DT) != 0) { - u_int sfunct; - - sfunct = ahd_inb(ahd, SFUNCT) & ~ALT_MODE; - ahd_outb(ahd, SFUNCT, sfunct | ALT_MODE); - ahd->suspend_state.optionmode = ahd_inb(ahd, OPTIONMODE); - ahd_outb(ahd, SFUNCT, sfunct); - ahd->suspend_state.crccontrol1 = ahd_inb(ahd, CRCCONTROL1); - } - - if ((ahd->features & AHD_MULTI_FUNC) != 0) - ahd->suspend_state.scbbaddr = ahd_inb(ahd, SCBBADDR); - - if ((ahd->features & AHD_ULTRA2) != 0) - ahd->suspend_state.dff_thrsh = ahd_inb(ahd, DFF_THRSH); - - ptr = ahd->suspend_state.scratch_ram; - for (i = 0; i < 64; i++) - *ptr++ = ahd_inb(ahd, SRAM_BASE + i); - - if ((ahd->features & AHD_MORE_SRAM) != 0) { - for (i = 0; i < 16; i++) - *ptr++ = ahd_inb(ahd, TARG_OFFSET + i); - } - - ptr = ahd->suspend_state.btt; - for (i = 0;i < AHD_NUM_TARGETS; i++) { - int j; - - for (j = 0;j < AHD_NUM_LUNS; j++) { - u_int tcl; - - tcl = BUILD_TCL(i << 4, j); - *ptr = ahd_find_busy_tcl(ahd, tcl); - } - } - ahd_shutdown(ahd); -#endif - return (0); -} - -int -ahd_resume(struct ahd_softc *ahd) -{ -#if 0 - uint8_t *ptr; - int i; - - ahd_reset(ahd); - - ahd_build_free_scb_list(ahd); - - /* Restore volatile registers */ - ahd_outb(ahd, SCSISEQ0, ahd->suspend_state.channel[0].scsiseq); - ahd_outb(ahd, SXFRCTL0, ahd->suspend_state.channel[0].sxfrctl0); - ahd_outb(ahd, SXFRCTL1, ahd->suspend_state.channel[0].sxfrctl1); - ahd_outb(ahd, SIMODE0, ahd->suspend_state.channel[0].simode0); - ahd_outb(ahd, SIMODE1, ahd->suspend_state.channel[0].simode1); - ahd_outb(ahd, SELTIMER, ahd->suspend_state.channel[0].seltimer); - ahd_outb(ahd, SEQCTL0, ahd->suspend_state.channel[0].seqctl); - if ((ahd->features & AHD_ULTRA2) != 0) - ahd_outb(ahd, SCSIID_ULTRA2, ahd->our_id); - else - ahd_outb(ahd, SCSIID, ahd->our_id); - - ahd_outb(ahd, DSCOMMAND0, ahd->suspend_state.dscommand0); - ahd_outb(ahd, DSPCISTATUS, ahd->suspend_state.dspcistatus); - - if ((ahd->features & AHD_DT) != 0) { - u_int sfunct; - - sfunct = ahd_inb(ahd, SFUNCT) & ~ALT_MODE; - ahd_outb(ahd, SFUNCT, sfunct | ALT_MODE); - ahd_outb(ahd, OPTIONMODE, ahd->suspend_state.optionmode); - ahd_outb(ahd, SFUNCT, sfunct); - ahd_outb(ahd, CRCCONTROL1, ahd->suspend_state.crccontrol1); - } - - if ((ahd->features & AHD_MULTI_FUNC) != 0) - ahd_outb(ahd, SCBBADDR, ahd->suspend_state.scbbaddr); - - if ((ahd->features & AHD_ULTRA2) != 0) - ahd_outb(ahd, DFF_THRSH, ahd->suspend_state.dff_thrsh); - - ptr = ahd->suspend_state.scratch_ram; - for (i = 0; i < 64; i++) - ahd_outb(ahd, SRAM_BASE + i, *ptr++); - - if ((ahd->features & AHD_MORE_SRAM) != 0) { - for (i = 0; i < 16; i++) - ahd_outb(ahd, TARG_OFFSET + i, *ptr++); - } - - ptr = ahd->suspend_state.btt; - for (i = 0;i < AHD_NUM_TARGETS; i++) { - int j; - - for (j = 0;j < AHD_NUM_LUNS; j++) { - u_int tcl; - - tcl = BUILD_TCL(i << 4, j); - ahd_busy_tcl(ahd, tcl, *ptr); - } - } -#endif - return (0); -} - -/************************** Busy Target Table *********************************/ -/* - * Set SCBPTR to the SCB that contains the busy - * table entry for TCL. Return the offset into - * the SCB that contains the entry for TCL. - * saved_scbid is dereferenced and set to the - * scbid that should be restored once manipualtion - * of the TCL entry is complete. - */ -static __inline u_int -ahd_index_busy_tcl(struct ahd_softc *ahd, u_int *saved_scbid, u_int tcl) -{ - - *saved_scbid = ahd_get_scbptr(ahd); - - /* - * Index to the SCB that contains the busy entry. - */ - ahd_set_scbptr(ahd, TCL_LUN(tcl) - | ((TCL_TARGET_OFFSET(tcl) & ~0x7) << 5)); - - /* - * And now calculate the SCB offset to the entry. - * Each entry is 2 bytes wide, hence the - * multiplication by 2. - */ - return (((TCL_TARGET_OFFSET(tcl) & 0x7) << 1) + SCB_DISCONNECTED_LISTS); -} - -/* - * Return the untagged transaction id for a given target/channel lun. - * Optionally, clear the entry. - */ -u_int -ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl) -{ - u_int scbid; - u_int scb_offset; - u_int saved_scbptr; - - scb_offset = ahd_index_busy_tcl(ahd, &saved_scbptr, tcl); - scbid = ahd_inw_scbram(ahd, scb_offset); - ahd_set_scbptr(ahd, saved_scbptr); - return (scbid); -} - -void -ahd_busy_tcl(struct ahd_softc *ahd, u_int tcl, u_int scbid) -{ - u_int scb_offset; - u_int saved_scbptr; - - scb_offset = ahd_index_busy_tcl(ahd, &saved_scbptr, tcl); - ahd_outw(ahd, scb_offset, scbid); - ahd_set_scbptr(ahd, saved_scbptr); -} - -void -ahd_set_disconnected_list(struct ahd_softc *ahd, u_int target, - u_int lun, u_int scbid) -{ - u_int saved_scbptr; - - AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK), - ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK)); - saved_scbptr = ahd_get_scbptr(ahd); - ahd_set_scbptr(ahd, lun | ((target & 0x8) << 5)); - ahd_outw(ahd, SCB_DISCONNECTED_LISTS + ((target & 0x7) << 1), scbid); - ahd_set_scbptr(ahd, saved_scbptr); -} - -/************************** SCB and SCB queue management **********************/ -int -ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, int target, - char channel, int lun, u_int tag, role_t role) -{ - int targ = SCB_GET_TARGET(ahd, scb); - char chan = SCB_GET_CHANNEL(ahd, scb); - int slun = SCB_GET_LUN(scb); - int match; - - match = ((chan == channel) || (channel == ALL_CHANNELS)); - if (match != 0) - match = ((targ == target) || (target == CAM_TARGET_WILDCARD)); - if (match != 0) - match = ((lun == slun) || (lun == CAM_LUN_WILDCARD)); - if (match != 0) { -#if AHD_TARGET_MODE - int group; - - group = XPT_FC_GROUP(scb->io_ctx->ccb_h.func_code); - if (role == ROLE_INITIATOR) { - match = (group != XPT_FC_GROUP_TMODE) - && ((tag == SCB_GET_TAG(scb)) - || (tag == SCB_LIST_NULL)); - } else if (role == ROLE_TARGET) { - match = (group == XPT_FC_GROUP_TMODE) - && ((tag == scb->io_ctx->csio.tag_id) - || (tag == SCB_LIST_NULL)); - } -#else /* !AHD_TARGET_MODE */ - match = ((tag == SCB_GET_TAG(scb)) || (tag == SCB_LIST_NULL)); -#endif /* AHD_TARGET_MODE */ - } - - return match; -} - -void -ahd_freeze_devq(struct ahd_softc *ahd, struct scb *scb) -{ - int target; - char channel; - int lun; - - target = SCB_GET_TARGET(ahd, scb); - lun = SCB_GET_LUN(scb); - channel = SCB_GET_CHANNEL(ahd, scb); - - ahd_search_qinfifo(ahd, target, channel, lun, - /*tag*/SCB_LIST_NULL, ROLE_UNKNOWN, - CAM_REQUEUE_REQ, SEARCH_COMPLETE); - - ahd_platform_freeze_devq(ahd, scb); -} - -void -ahd_qinfifo_requeue_tail(struct ahd_softc *ahd, struct scb *scb) -{ - struct scb *prev_scb; - - prev_scb = NULL; - if (ahd_qinfifo_count(ahd) != 0) { - u_int prev_tag; - u_int prev_pos; - - prev_pos = AHD_QIN_WRAP(ahd->qinfifonext - 1); - prev_tag = ahd->qinfifo[prev_pos]; - prev_scb = ahd_lookup_scb(ahd, prev_tag); - } - ahd_qinfifo_requeue(ahd, prev_scb, scb); - ahd_set_hnscb_qoff(ahd, ahd->qinfifonext); -} - -static void -ahd_qinfifo_requeue(struct ahd_softc *ahd, struct scb *prev_scb, - struct scb *scb) -{ - if (prev_scb == NULL) { - uint32_t busaddr; - - busaddr = ahd_le32toh(scb->hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); - } else { - prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr; - ahd_sync_scb(ahd, prev_scb, - BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); - } - ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb); - ahd->qinfifonext++; - scb->hscb->next_hscb_busaddr = ahd->next_queued_scb->hscb->hscb_busaddr; - ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); -} - -static int -ahd_qinfifo_count(struct ahd_softc *ahd) -{ - u_int qinpos; - u_int wrap_qinpos; - u_int wrap_qinfifonext; - - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); - qinpos = ahd_get_snscb_qoff(ahd); - wrap_qinpos = AHD_QIN_WRAP(qinpos); - wrap_qinfifonext = AHD_QIN_WRAP(ahd->qinfifonext); - if (wrap_qinfifonext > wrap_qinpos) - return (wrap_qinfifonext - wrap_qinpos); - else - return (wrap_qinfifonext - + NUM_ELEMENTS(ahd->qinfifo) - wrap_qinpos); -} - -int -ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, - int lun, u_int tag, role_t role, uint32_t status, - ahd_search_action action) -{ - struct scb *scb; - struct scb *prev_scb; - ahd_mode_state saved_modes; - u_int qinstart; - u_int qinpos; - u_int qintail; - u_int tid_next; - u_int tid_prev; - u_int scbid; - u_int savedscbptr; - uint32_t busaddr; - int found; - int targets; - - /* Must be in CCHAN mode */ - saved_modes = ahd_save_modes(ahd); - ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); - - /* - * Halt any pending SCB DMA. The sequencer will reinitiate - * this dma if the qinfifo is not empty once we unpause. - */ - if ((ahd_inb(ahd, CCSCBCTL) & (CCARREN|CCSCBEN|CCSCBDIR)) - == (CCARREN|CCSCBEN|CCSCBDIR)) { - ahd_outb(ahd, CCSCBCTL, - ahd_inb(ahd, CCSCBCTL) & ~(CCARREN|CCSCBEN)); - while ((ahd_inb(ahd, CCSCBCTL) & (CCARREN|CCSCBEN)) != 0) - ; - } - /* Determine sequencer's position in the qinfifo. */ - qintail = AHD_QIN_WRAP(ahd->qinfifonext); - qinstart = ahd_get_snscb_qoff(ahd); - qinpos = AHD_QIN_WRAP(qinstart); - found = 0; - prev_scb = NULL; - - if (action == SEARCH_COMPLETE) { - /* - * Don't attempt to run any queued untagged transactions - * until we are done with the abort process. - */ - ahd_freeze_untagged_queues(ahd); - } - - if (action == SEARCH_PRINT) { - printf("qinstart = %d qinfifonext = %d\nQINFIFO:", - qinstart, ahd->qinfifonext); - } - - /* - * Start with an empty queue. Entries that are not chosen - * for removal will be re-added to the queue as we go. - */ - ahd->qinfifonext = qinstart; - busaddr = ahd_le32toh(ahd->next_queued_scb->hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); - - while (qinpos != qintail) { - scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]); - if (scb == NULL) { - printf("qinpos = %d, SCB index = %d\n", - qinpos, ahd->qinfifo[qinpos]); - panic("Loop 1\n"); - } - - if (ahd_match_scb(ahd, scb, target, channel, lun, tag, role)) { - /* - * We found an scb that needs to be acted on. - */ - found++; - switch (action) { - case SEARCH_COMPLETE: - { - cam_status ostat; - cam_status cstat; - - ostat = ahd_get_transaction_status(scb); - if (ostat == CAM_REQ_INPROG) - ahd_set_transaction_status(scb, - status); - cstat = ahd_get_transaction_status(scb); - if (cstat != CAM_REQ_CMP) - ahd_freeze_scb(scb); - if ((scb->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB in qinfifo\n"); - ahd_done(ahd, scb); - - /* FALLTHROUGH */ - } - case SEARCH_REMOVE: - break; - case SEARCH_PRINT: - printf(" 0x%x", ahd->qinfifo[qinpos]); - /* FALLTHROUGH */ - case SEARCH_COUNT: - ahd_qinfifo_requeue(ahd, prev_scb, scb); - prev_scb = scb; - break; - } - } else { - ahd_qinfifo_requeue(ahd, prev_scb, scb); - prev_scb = scb; - } - qinpos = AHD_QIN_WRAP(qinpos+1); - } - - ahd_set_hnscb_qoff(ahd, ahd->qinfifonext); - - if (action == SEARCH_PRINT) - printf("\nWAITING_TID_QUEUES:\n"); - - /* - * Search waiting for selection lists. We traverse the - * list of "their ids" waiting for selection and, if - * appropriate, traverse the SCBs of each "their id" - * looking for matches. - */ - savedscbptr = ahd_get_scbptr(ahd); - tid_next = ahd_inw(ahd, WAITING_TID_HEAD); - tid_prev = SCB_LIST_NULL; - targets = 0; - for (scbid = tid_next; !SCBID_IS_NULL(scbid); scbid = tid_next) { - u_int tid_head; - - /* - * We limit based on the number of SCBs since - * MK_MESSAGE SCBs are not in the per-tid lists. - */ - targets++; - if (targets > AHD_SCB_MAX) { - panic("TID LIST LOOP"); - } - if (scbid >= ahd->scb_data.numscbs) { - printf("%s: Waiting TID List inconsistency. " - "SCB index == 0x%x, yet numscbs == 0x%x.", - ahd_name(ahd), scbid, ahd->scb_data.numscbs); - ahd_dump_card_state(ahd); - panic("for safety"); - } - scb = ahd_lookup_scb(ahd, scbid); - if (scb == NULL) { - printf("%s: SCB = 0x%x Not Active!\n", - ahd_name(ahd), scbid); - panic("Waiting TID List traversal\n"); - } - ahd_set_scbptr(ahd, scbid); - tid_next = ahd_inw_scbram(ahd, SCB_NEXT2); - if (ahd_match_scb(ahd, scb, target, channel, CAM_LUN_WILDCARD, - SCB_LIST_NULL, ROLE_UNKNOWN) == 0) { - tid_prev = scbid; - continue; - } - - /* - * We found a list of scbs that needs to be searched. - */ - if (action == SEARCH_PRINT) - printf(" %d ( ", SCB_GET_TARGET(ahd, scb)); - tid_head = scbid; - found += ahd_search_scb_list(ahd, target, channel, - lun, tag, role, status, - action, &tid_head, - SCB_GET_TARGET(ahd, scb)); - if (tid_head != scbid) - ahd_stitch_tid_list(ahd, tid_prev, tid_head, tid_next); - if (!SCBID_IS_NULL(tid_head)) - tid_prev = tid_head; - if (action == SEARCH_PRINT) - printf(")\n"); - } - ahd_set_scbptr(ahd, savedscbptr); - - if (action == SEARCH_COMPLETE) - ahd_release_untagged_queues(ahd); - ahd_restore_modes(ahd, saved_modes); - return (found); -} - -static int -ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, - int lun, u_int tag, role_t role, uint32_t status, - ahd_search_action action, u_int *list_head, u_int tid) -{ - struct scb *scb; - u_int scbid; - u_int next; - u_int prev; - int found; - - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); - found = 0; - prev = SCB_LIST_NULL; - next = *list_head; - for (scbid = next; !SCBID_IS_NULL(scbid); scbid = next) { - if (scbid >= ahd->scb_data.numscbs) { - printf("%s:SCB List inconsistency. " - "SCB == 0x%x, yet numscbs == 0x%x.", - ahd_name(ahd), scbid, ahd->scb_data.numscbs); - ahd_dump_card_state(ahd); - panic("for safety"); - } - scb = ahd_lookup_scb(ahd, scbid); - if (scb == NULL) { - printf("%s: SCB = %d Not Active!\n", - ahd_name(ahd), scbid); - panic("Waiting List traversal\n"); - } - ahd_set_scbptr(ahd, scbid); - next = ahd_inw_scbram(ahd, SCB_NEXT); - if (ahd_match_scb(ahd, scb, target, channel, - lun, SCB_LIST_NULL, role) == 0) { - prev = scbid; - continue; - } - found++; - switch (action) { - case SEARCH_COMPLETE: - { - cam_status ostat; - cam_status cstat; - - ostat = ahd_get_transaction_status(scb); - if (ostat == CAM_REQ_INPROG) - ahd_set_transaction_status(scb, status); - cstat = ahd_get_transaction_status(scb); - if (cstat != CAM_REQ_CMP) - ahd_freeze_scb(scb); - if ((scb->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB in Waiting List\n"); - ahd_done(ahd, scb); - /* FALLTHROUGH */ - } - case SEARCH_REMOVE: - ahd_rem_wscb(ahd, scbid, prev, next, tid); - if (prev == SCB_LIST_NULL) - *list_head = next; - break; - case SEARCH_PRINT: - printf("0x%x ", scbid); - case SEARCH_COUNT: - prev = scbid; - break; - } - if (found > AHD_SCB_MAX) - panic("SCB LIST LOOP"); - } - return (found); -} - -static void -ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev, - u_int tid_cur, u_int tid_next) -{ - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); - - if (SCBID_IS_NULL(tid_cur)) { - - /* Bypass current TID list */ - if (SCBID_IS_NULL(tid_prev)) { - ahd_outw(ahd, WAITING_TID_HEAD, tid_next); - } else { - ahd_set_scbptr(ahd, tid_prev); - ahd_outw(ahd, SCB_NEXT2, tid_next); - } - if (SCBID_IS_NULL(tid_next)) - ahd_outw(ahd, WAITING_TID_TAIL, tid_prev); - } else { - - /* Stitch through tid_cur */ - if (SCBID_IS_NULL(tid_prev)) { - ahd_outw(ahd, WAITING_TID_HEAD, tid_cur); - } else { - ahd_set_scbptr(ahd, tid_prev); - ahd_outw(ahd, SCB_NEXT2, tid_cur); - } - ahd_set_scbptr(ahd, tid_cur); - ahd_outw(ahd, SCB_NEXT2, tid_next); - - if (SCBID_IS_NULL(tid_next)) - ahd_outw(ahd, WAITING_TID_TAIL, tid_cur); - } -} - -/* - * Manipulate the waiting for selection list and return the - * scb that follows the one that we remove. - */ -static u_int -ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid, - u_int prev, u_int next, u_int tid) -{ - u_int tail_offset; - - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); - if (!SCBID_IS_NULL(prev)) { - ahd_set_scbptr(ahd, prev); - ahd_outw(ahd, SCB_NEXT, next); - } - - /* - * SCBs that had MK_MESSAGE set in them will not - * be queued to the per-target lists, so don't - * blindly clear the tail pointer. - */ - tail_offset = WAITING_SCB_TAILS + (2 * tid); - if (SCBID_IS_NULL(next) - && ahd_inw(ahd, tail_offset) == scbid) - ahd_outw(ahd, tail_offset, prev); - ahd_add_scb_to_free_list(ahd, scbid); - return (next); -} - -/* - * Add the SCB as selected by SCBPTR onto the on chip list of - * free hardware SCBs. This list is empty/unused if we are not - * performing SCB paging. - */ -static void -ahd_add_scb_to_free_list(struct ahd_softc *ahd, u_int scbid) -{ -/* XXX Need some other mechanism to designate "free". */ - /* - * Invalidate the tag so that our abort - * routines don't think it's active. - ahd_outb(ahd, SCB_TAG, SCB_LIST_NULL); - */ -} - -/******************************** Error Handling ******************************/ -/* - * Abort all SCBs that match the given description (target/channel/lun/tag), - * setting their status to the passed in status if the status has not already - * been modified from CAM_REQ_INPROG. This routine assumes that the sequencer - * is paused before it is called. - */ -int -ahd_abort_scbs(struct ahd_softc *ahd, int target, char channel, - int lun, u_int tag, role_t role, uint32_t status) -{ - struct scb *scbp; - struct scb *scbp_next; - u_int active_scb; - u_int i, j; - u_int maxtarget; - u_int minlun; - u_int maxlun; - - int found; - - /* - * Don't attempt to run any queued untagged transactions - * until we are done with the abort process. - */ - ahd_freeze_untagged_queues(ahd); - - /* restore this when we're done */ - active_scb = ahd_get_scbptr(ahd); - - found = ahd_search_qinfifo(ahd, target, channel, lun, SCB_LIST_NULL, - role, CAM_REQUEUE_REQ, SEARCH_COMPLETE); - - /* - * Clean out the busy target table for any untagged commands. - */ - i = 0; - maxtarget = 16; - if (target != CAM_TARGET_WILDCARD) { - i = target; - if (channel == 'B') - i += 8; - maxtarget = i + 1; - } - - if (lun == CAM_LUN_WILDCARD) { - minlun = 0; - maxlun = AHD_NUM_LUNS_NONPKT; - } else if (lun >= AHD_NUM_LUNS_NONPKT) { - minlun = maxlun = 0; - } else { - minlun = lun; - maxlun = lun + 1; - } - - if (role != ROLE_TARGET) { - for (;i < maxtarget; i++) { - for (j = minlun;j < maxlun; j++) { - u_int scbid; - u_int tcl; - - tcl = BUILD_TCL(i << 4, j); - scbid = ahd_find_busy_tcl(ahd, tcl); - scbp = ahd_lookup_scb(ahd, scbid); - if (scbp == NULL - || ahd_match_scb(ahd, scbp, target, channel, - lun, tag, role) == 0) - continue; - ahd_unbusy_tcl(ahd, BUILD_TCL_RAW(i, 'A', j)); - } - } - } - - /* - * Go through the pending CCB list and look for - * commands for this target that are still active. - * These are other tagged commands that were - * disconnected when the reset occurred. - */ - scbp_next = LIST_FIRST(&ahd->pending_scbs); - while (scbp_next != NULL) { - scbp = scbp_next; - scbp_next = LIST_NEXT(scbp, pending_links); - if (ahd_match_scb(ahd, scbp, target, channel, lun, tag, role)) { - cam_status ostat; - - ostat = ahd_get_transaction_status(scbp); - if (ostat == CAM_REQ_INPROG) - ahd_set_transaction_status(scbp, status); - if (ahd_get_transaction_status(scbp) != CAM_REQ_CMP) - ahd_freeze_scb(scbp); - if ((scbp->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB on pending list\n"); - ahd_done(ahd, scbp); - found++; - } - } - ahd_set_scbptr(ahd, active_scb); - ahd_platform_abort_scbs(ahd, target, channel, lun, tag, role, status); - ahd_release_untagged_queues(ahd); - return found; -} - -static void -ahd_reset_current_bus(struct ahd_softc *ahd) -{ - uint8_t scsiseq; - - AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); - ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) & ~ENSCSIRST); - scsiseq = ahd_inb(ahd, SCSISEQ0); - ahd_outb(ahd, SCSISEQ0, scsiseq | SCSIRSTO); - ahd_delay(AHD_BUSRESET_DELAY); - /* Turn off the bus reset */ - ahd_outb(ahd, SCSISEQ0, scsiseq & ~SCSIRSTO); - if ((ahd->bugs & AHD_SCSIRST_BUG) != 0) { - /* - * 2A Razor #474 - * Certain chip state is not cleared for - * SCSI bus resets that we initiate, so - * we must reset the chip. - */ - ahd_reset(ahd); - ahd_intr_enable(ahd, /*enable*/TRUE); - AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); - } - - ahd_clear_intstat(ahd); - - /* Re-enable reset interrupts */ - ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST); -} - -int -ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) -{ - struct ahd_devinfo devinfo; -#if AHD_TARGET_MODE - u_int target; - u_int max_scsiid; -#endif - int found; - - ahd->pending_device = NULL; - - ahd_compile_devinfo(&devinfo, - CAM_TARGET_WILDCARD, - CAM_TARGET_WILDCARD, - CAM_LUN_WILDCARD, - channel, ROLE_UNKNOWN); - ahd_pause(ahd); - - /* Make sure the sequencer is in a safe location. */ - ahd_clear_critical_section(ahd); - - /* - * Run our command complete fifos to ensure that we perform - * completion processing on any commands that 'completed' - * before the reset occurred. - */ - ahd_run_qoutfifo(ahd); -#if AHD_TARGET_MODE - if ((ahd->flags & AHD_TARGETROLE) != 0) { - ahd_run_tqinfifo(ahd, /*paused*/TRUE); - } -#endif - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - - /* - * Reset the bus if we are initiating this reset - */ - ahd_clear_msg_state(ahd); - ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST)); - if (initiate_reset) - ahd_reset_current_bus(ahd); - ahd_clear_intstat(ahd); - - /* - * Clean up all the state information for the - * pending transactions on this bus. - */ - found = ahd_abort_scbs(ahd, CAM_TARGET_WILDCARD, channel, - CAM_LUN_WILDCARD, SCB_LIST_NULL, - ROLE_UNKNOWN, CAM_SCSI_BUS_RESET); - -#ifdef AHD_TARGET_MODE - max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7; - - /* - * Send an immediate notify ccb to all target more peripheral - * drivers affected by this action. - */ - for (target = 0; target <= max_scsiid; target++) { - struct ahd_tmode_tstate* tstate; - u_int lun; - - tstate = ahd->enabled_targets[target]; - if (tstate == NULL) - continue; - for (lun = 0; lun < AHD_NUM_LUNS; lun++) { - struct ahd_tmode_lstate* lstate; - - lstate = tstate->enabled_luns[lun]; - if (lstate == NULL) - continue; - - ahd_queue_lstate_event(ahd, lstate, CAM_TARGET_WILDCARD, - EVENT_TYPE_BUS_RESET, /*arg*/0); - ahd_send_lstate_events(ahd, lstate); - } - } -#endif - /* Notify the XPT that a bus reset occurred */ - ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD, - CAM_LUN_WILDCARD, AC_BUS_RESET, NULL); - - /* - * Freeze the SIMQ until our poller can determine that - * the bus reset has really gone away. We set the initial - * timer to 0 to have the check performed as soon as possible - * from the timer context. - */ - ahd_freeze_simq(ahd); - ahd_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd); - return (found); -} - - -#define AHD_RESET_POLL_US 1000 -static void -ahd_reset_poll(void *arg) -{ - struct ahd_softc *ahd; - u_int scsiseq1; - u_int initiator, target, max_scsiid; - u_long l; - u_long s; - - ahd_list_lock(&l); - ahd = ahd_find_softc((struct ahd_softc *)arg); - if (ahd == NULL) { - printf("ahd_reset_poll: Instance %p no longer exists\n", arg); - ahd_list_unlock(&l); - return; - } - ahd_lock(ahd, &s); - if (ahd_is_paused(ahd) == 0) - panic("Someone unpaused the sequencer!\n"); - - ahd_clear_intstat(ahd); - if ((ahd_inb(ahd, SSTAT0) & SCSIRSTI) != 0) { - ahd_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_US, - ahd_reset_poll, ahd); - ahd_unlock(ahd, &s); - } - - /* Reset is now low. Complete chip reinitialization. */ - ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST); - scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE); - ahd_outb(ahd, SCSISEQ1, scsiseq1 & (ENSELI|ENRSELI|ENAUTOATNP)); - - /* - * Revert to async/narrow transfers until we renegotiate. - */ - max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7; - for (target = 0; target <= max_scsiid; target++) { - - if (ahd->enabled_targets[target] == NULL) - continue; - for (initiator = 0; initiator <= max_scsiid; initiator++) { - struct ahd_devinfo devinfo; - - ahd_compile_devinfo(&devinfo, target, initiator, - CAM_LUN_WILDCARD, - 'A', ROLE_UNKNOWN); - ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, - AHD_TRANS_CUR, /*paused*/TRUE); - ahd_set_syncrate(ahd, &devinfo, /*period*/0, - /*offset*/0, /*ppr_options*/0, - AHD_TRANS_CUR, /*paused*/TRUE); - } - } - - ahd_clear_fifo(ahd, 0); - ahd_clear_fifo(ahd, 1); - ahd_restart(ahd); - ahd_unlock(ahd, &s); - ahd_release_simq(ahd); - ahd_list_unlock(&l); -} - - -/****************************** Status Processing *****************************/ -void -ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb) -{ - if (scb->hscb->shared_data.istatus.scsi_status != 0) { - ahd_handle_scsi_status(ahd, scb); - } else { - ahd_calc_residual(ahd, scb); - ahd_done(ahd, scb); - } -} - -void -ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) -{ - struct hardware_scb *hscb; - u_int qfreeze_cnt; - ahd_mode_state saved_modes; - - /* - * The sequencer freezes its select-out queue - * anytime a SCSI status error occurs. We must - * handle the error and decrement the QFREEZE count - * to allow the sequencer to continue. - */ - hscb = scb->hscb; - - /* Don't want to clobber the original sense code */ - if ((scb->flags & SCB_SENSE) != 0) { - /* - * Clear the SCB_SENSE Flag and perform - * a normal command completion. - */ - scb->flags &= ~SCB_SENSE; - ahd_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); - ahd_done(ahd, scb); - return; - } - ahd_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR); - /* Freeze the queue until the client sees the error. */ - ahd_pause(ahd); - saved_modes = ahd_save_modes(ahd); - ahd_clear_critical_section(ahd); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - ahd_freeze_devq(ahd, scb); - ahd_freeze_scb(scb); - qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT); - if (qfreeze_cnt == 0) { - printf("%s: Bad status with 0 qfreeze count!\n", ahd_name(ahd)); - } else { - qfreeze_cnt--; - ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt); - } - if (qfreeze_cnt == 0) - ahd_outb(ahd, SEQ_FLAGS2, - ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN); - ahd_unpause(ahd); - ahd_set_scsi_status(scb, hscb->shared_data.istatus.scsi_status); - switch (hscb->shared_data.istatus.scsi_status) { - case STATUS_PKT_SENSE: - { - struct scsi_status_iu_header *siu; - - ahd_sync_sense(ahd, scb, BUS_DMASYNC_POSTREAD); - siu = (struct scsi_status_iu_header *)scb->sense_data; - ahd_set_scsi_status(scb, siu->status); -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_SENSE) != 0) - ahd_print_path(ahd, scb); - printf("SCB 0x%x Received PKT Status of 0x%x\n", - SCB_GET_TAG(scb), siu->status); - printf("\tflags = 0x%x, sense len = 0x%x, " - "pktfail = 0x%x\n", - siu->flags, scsi_4btoul(siu->sense_length), - scsi_4btoul(siu->pkt_failures_length)); -#endif - if ((siu->flags & SIU_RSPVALID) != 0) { - ahd_print_path(ahd, scb); - if (scsi_4btoul(siu->pkt_failures_length) < 4) { - printf("Unable to parse pkt_failures\n"); - } else { - - switch (SIU_PKTFAIL_CODE(siu)) { - case SIU_PFC_NONE: - printf("No packet failure found\n"); - break; - case SIU_PFC_CIU_FIELDS_INVALID: - printf("Invalid Command IU Field\n"); - break; - case SIU_PFC_TMF_NOT_SUPPORTED: - printf("TMF not supportd\n"); - break; - case SIU_PFC_TMF_FAILED: - printf("TMF failed\n"); - break; - case SIU_PFC_INVALID_TYPE_CODE: - printf("Invalid L_Q Type code\n"); - break; - case SIU_PFC_ILLEGAL_REQUEST: - printf("Illegal request\n"); - default: - break; - } - } - if (siu->status == SCSI_STATUS_OK) - ahd_set_transaction_status(scb, - CAM_REQ_CMP_ERR); - } - if ((siu->flags & SIU_SNSVALID) != 0) { - scb->flags |= SCB_PKT_SENSE; -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_SENSE) != 0) - printf("Sense data available\n"); -#endif - } - ahd_done(ahd, scb); - break; - } - case SCSI_STATUS_CMD_TERMINATED: - case SCSI_STATUS_CHECK_COND: - { - struct ahd_devinfo devinfo; - struct ahd_dma_seg *sg; - struct scsi_sense *sc; - struct ahd_initiator_tinfo *targ_info; - struct ahd_tmode_tstate *tstate; - struct ahd_transinfo *tinfo; -#ifdef AHD_DEBUG - if (ahd_debug & AHD_SHOW_SENSE) { - ahd_print_path(ahd, scb); - printf("SCB %d: requests Check Status\n", - SCB_GET_TAG(scb)); - } -#endif - - if (ahd_perform_autosense(scb) == 0) - break; - - ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb), - SCB_GET_TARGET(ahd, scb), - SCB_GET_LUN(scb), - SCB_GET_CHANNEL(ahd, scb), - ROLE_INITIATOR); - targ_info = ahd_fetch_transinfo(ahd, - devinfo.channel, - devinfo.our_scsiid, - devinfo.target, - &tstate); - tinfo = &targ_info->curr; - sg = scb->sg_list; - sc = (struct scsi_sense *)hscb->shared_data.idata.cdb; - /* - * Save off the residual if there is one. - */ - ahd_update_residual(ahd, scb); -#ifdef AHD_DEBUG - if (ahd_debug & AHD_SHOW_SENSE) { - ahd_print_path(ahd, scb); - printf("Sending Sense\n"); - } -#endif - scb->sg_count = 0; - sg = ahd_sg_setup(ahd, scb, sg, ahd_get_sense_bufaddr(ahd, scb), - ahd_get_sense_bufsize(ahd, scb), - /*last*/TRUE); - sc->opcode = REQUEST_SENSE; - sc->byte2 = 0; - if (tinfo->protocol_version <= SCSI_REV_2 - && SCB_GET_LUN(scb) < 8) - sc->byte2 = SCB_GET_LUN(scb) << 5; - sc->unused[0] = 0; - sc->unused[1] = 0; - sc->length = ahd_get_sense_bufsize(ahd, scb); - sc->control = 0; - - /* - * We can't allow the target to disconnect. - * This will be an untagged transaction and - * having the target disconnect will make this - * transaction indestinguishable from outstanding - * tagged transactions. - */ - hscb->control = 0; - - /* - * This request sense could be because the - * the device lost power or in some other - * way has lost our transfer negotiations. - * Renegotiate if appropriate. Unit attention - * errors will be reported before any data - * phases occur. - */ - if (ahd_get_residual(scb) == ahd_get_transfer_length(scb)) { - ahd_update_neg_request(ahd, &devinfo, - tstate, targ_info, - /*force*/TRUE); - } - if (tstate->auto_negotiate & devinfo.target_mask) { - hscb->control |= MK_MESSAGE; - scb->flags &= - ~(SCB_NEGOTIATE|SCB_ABORT|SCB_DEVICE_RESET); - scb->flags |= SCB_AUTO_NEGOTIATE; - } - hscb->cdb_len = sizeof(*sc); - ahd_setup_data_scb(ahd, scb); - scb->flags |= SCB_SENSE; - ahd_queue_scb(ahd, scb); -#ifdef __FreeBSD__ - /* - * Ensure we have enough time to actually - * retrieve the sense. - */ - untimeout(ahd_timeout, (caddr_t)scb, - scb->io_ctx->ccb_h.timeout_ch); - scb->io_ctx->ccb_h.timeout_ch = - timeout(ahd_timeout, (caddr_t)scb, 5 * hz); -#endif - break; - } - case SCSI_STATUS_OK: - printf("%s: Interrupted for staus of 0???\n", - ahd_name(ahd)); - /* FALLTHROUGH */ - default: - ahd_done(ahd, scb); - break; - } -} - -/* - * Calculate the residual for a just completed SCB. - */ -void -ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb) -{ - struct hardware_scb *hscb; - struct initiator_status *spkt; - uint32_t sgptr; - uint32_t resid_sgptr; -/* SAE */ - uint32_t resid = 0; - - /* - * 5 cases. - * 1) No residual. - * SG_STATUS_VALID clear in sgptr. - * 2) Transferless command - * 3) Never performed any transfers. - * sgptr has SG_FULL_RESID set. - * 4) No residual but target did not - * save data pointers after the - * last transfer, so sgptr was - * never updated. - * 5) We have a partial residual. - * Use residual_sgptr to determine - * where we are. - */ - - hscb = scb->hscb; - sgptr = ahd_le32toh(hscb->sgptr); - if ((sgptr & SG_STATUS_VALID) == 0) - /* Case 1 */ - return; - sgptr &= ~SG_STATUS_VALID; - - if ((sgptr & SG_LIST_NULL) != 0) - /* Case 2 */ - return; - - /* - * Residual fields are the same in both - * target and initiator status packets, - * so we can always use the initiator fields - * regardless of the role for this SCB. - */ - spkt = &hscb->shared_data.istatus; - resid_sgptr = ahd_le32toh(spkt->residual_sgptr); - if ((sgptr & SG_FULL_RESID) != 0) { - /* Case 3 */ - resid = ahd_get_transfer_length(scb); - } else if ((resid_sgptr & SG_LIST_NULL) != 0) { - /* Case 4 */ - return; - } else if ((resid_sgptr & SG_OVERRUN_RESID) != 0) { - ahd_print_path(ahd, scb); - printf("data overrun detected Tag == 0x%x.\n", - SCB_GET_TAG(scb)); - ahd_freeze_devq(ahd, scb); - ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR); - ahd_freeze_scb(scb); - return; - } else if ((resid_sgptr & ~SG_PTR_MASK) != 0) { - panic("Bogus resid sgptr value 0x%x\n", resid_sgptr); - /* NOTREACHED */ - } else { - struct ahd_dma_seg *sg; - - /* - * Remainder of the SG where the transfer - * stopped. - */ - resid = ahd_le32toh(spkt->residual_datacnt) & AHD_SG_LEN_MASK; - sg = ahd_sg_bus_to_virt(ahd, scb, resid_sgptr & SG_PTR_MASK); - - /* The residual sg_ptr always points to the next sg */ - sg--; - - /* - * Add up the contents of all residual - * SG segments that are after the SG where - * the transfer stopped. - */ - while ((ahd_le32toh(sg->len) & AHD_DMA_LAST_SEG) == 0) { - sg++; - resid += ahd_le32toh(sg->len) & AHD_SG_LEN_MASK; - } - } - if ((scb->flags & SCB_SENSE) == 0) - ahd_set_residual(scb, resid); - else - ahd_set_sense_residual(scb, resid); - -#ifdef AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MISC) != 0) { - ahd_print_path(ahd, scb); - printf("Handled Residual of %d bytes\n", resid); - } -#endif -} - -/******************************* Target Mode **********************************/ -#ifdef AHD_TARGET_MODE -/* - * Add a target mode event to this lun's queue - */ -static void -ahd_queue_lstate_event(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate, - u_int initiator_id, u_int event_type, u_int event_arg) -{ - struct ahd_tmode_event *event; - int pending; - - xpt_freeze_devq(lstate->path, /*count*/1); - if (lstate->event_w_idx >= lstate->event_r_idx) - pending = lstate->event_w_idx - lstate->event_r_idx; - else - pending = AHD_TMODE_EVENT_BUFFER_SIZE + 1 - - (lstate->event_r_idx - lstate->event_w_idx); - - if (event_type == EVENT_TYPE_BUS_RESET - || event_type == MSG_BUS_DEV_RESET) { - /* - * Any earlier events are irrelevant, so reset our buffer. - * This has the effect of allowing us to deal with reset - * floods (an external device holding down the reset line) - * without losing the event that is really interesting. - */ - lstate->event_r_idx = 0; - lstate->event_w_idx = 0; - xpt_release_devq(lstate->path, pending, /*runqueue*/FALSE); - } - - if (pending == AHD_TMODE_EVENT_BUFFER_SIZE) { - xpt_print_path(lstate->path); - printf("immediate event %x:%x lost\n", - lstate->event_buffer[lstate->event_r_idx].event_type, - lstate->event_buffer[lstate->event_r_idx].event_arg); - lstate->event_r_idx++; - if (lstate->event_r_idx == AHD_TMODE_EVENT_BUFFER_SIZE) - lstate->event_r_idx = 0; - xpt_release_devq(lstate->path, /*count*/1, /*runqueue*/FALSE); - } - - event = &lstate->event_buffer[lstate->event_w_idx]; - event->initiator_id = initiator_id; - event->event_type = event_type; - event->event_arg = event_arg; - lstate->event_w_idx++; - if (lstate->event_w_idx == AHD_TMODE_EVENT_BUFFER_SIZE) - lstate->event_w_idx = 0; -} - -/* - * Send any target mode events queued up waiting - * for immediate notify resources. - */ -void -ahd_send_lstate_events(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate) -{ - struct ccb_hdr *ccbh; - struct ccb_immed_notify *inot; - - while (lstate->event_r_idx != lstate->event_w_idx - && (ccbh = SLIST_FIRST(&lstate->immed_notifies)) != NULL) { - struct ahd_tmode_event *event; - - event = &lstate->event_buffer[lstate->event_r_idx]; - SLIST_REMOVE_HEAD(&lstate->immed_notifies, sim_links.sle); - inot = (struct ccb_immed_notify *)ccbh; - switch (event->event_type) { - case EVENT_TYPE_BUS_RESET: - ccbh->status = CAM_SCSI_BUS_RESET|CAM_DEV_QFRZN; - break; - default: - ccbh->status = CAM_MESSAGE_RECV|CAM_DEV_QFRZN; - inot->message_args[0] = event->event_type; - inot->message_args[1] = event->event_arg; - break; - } - inot->initiator_id = event->initiator_id; - inot->sense_len = 0; - xpt_done((union ccb *)inot); - lstate->event_r_idx++; - if (lstate->event_r_idx == AHD_TMODE_EVENT_BUFFER_SIZE) - lstate->event_r_idx = 0; - } -} -#endif - -/******************** Sequencer Program Patching/Download *********************/ - -#ifdef AHD_DUMP_SEQ -void -ahd_dumpseq(struct ahd_softc* ahd) -{ - int i; - int max_prog; - - max_prog = 2048; - - ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); - ahd_outb(ahd, PRGMCNT, 0); - ahd_outb(ahd, PRGMCNT+1, 0); - for (i = 0; i < max_prog; i++) { - uint8_t ins_bytes[4]; - - ahd_insb(ahd, SEQRAM, ins_bytes, 4); - printf("0x%08x\n", ins_bytes[0] << 24 - | ins_bytes[1] << 16 - | ins_bytes[2] << 8 - | ins_bytes[3]); - } -} -#endif - -static void -ahd_loadseq(struct ahd_softc *ahd) -{ - struct cs cs_table[num_critical_sections]; - u_int begin_set[num_critical_sections]; - u_int end_set[num_critical_sections]; - struct patch *cur_patch; - u_int cs_count; - u_int cur_cs; - u_int i; - int downloaded; - u_int skip_addr; - u_int sg_prefetch_cnt; - u_int sg_prefetch_cnt_limit; - u_int sg_prefetch_align; - u_int sg_size; - uint8_t download_consts[DOWNLOAD_CONST_COUNT]; - - if (bootverbose) - printf("%s: Downloading Sequencer Program...", - ahd_name(ahd)); - -#if DOWNLOAD_CONST_COUNT != 6 -#error "Download Const Mismatch" -#endif - /* - * Start out with 0 critical sections - * that apply to this firmware load. - */ - cs_count = 0; - cur_cs = 0; - memset(begin_set, 0, sizeof(begin_set)); - memset(end_set, 0, sizeof(end_set)); - - /* - * Setup downloadable constant table. - * - * The computation for the S/G prefetch variables is - * a bit complicated. We would like to always fetch - * in terms of cachelined sized increments. However, - * if the cacheline is not an even multiple of the - * SG element size or is larger than our SG RAM, using - * just the cache size might leave us with only a portion - * of an SG element at the tail of a prefetch. If the - * cacheline is larger than our S/G prefetch buffer less - * the size of an SG element, we may round down to a cacheline - * that doesn't contain any or all of the S/G of interest - * within the bounds of our S/G ram. Provide variables to - * the sequencer that will allow it to handle these edge - * cases. - */ - /* Start by aligning to the nearest cacheline. */ - sg_prefetch_align = ahd->pci_cachesize; - if (sg_prefetch_align == 0) - sg_prefetch_cnt = 8; - /* Round down to the nearest power of 2. */ - while (powerof2(sg_prefetch_align) == 0) - sg_prefetch_align--; - /* - * If the cacheline boundary is greater than half our prefetch RAM - * we risk not being able to fetch even a single complete S/G - * segment if we align to that boundary. - */ - if (sg_prefetch_align > CCSGADDR_MAX/2) - sg_prefetch_align = CCSGADDR_MAX/2; - /* Start by fetching a single cacheline. */ - sg_prefetch_cnt = sg_prefetch_align; - /* - * Increment the prefetch count by cachelines until - * at least one S/G element will fit. - */ - sg_size = sizeof(struct ahd_dma_seg); - if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) - sg_size = sizeof(struct ahd_dma64_seg); - while (sg_prefetch_cnt < sg_size) - sg_prefetch_cnt += sg_prefetch_align; - /* - * If the cacheline is not an even multiple of - * the S/G size, we may only get a partial S/G when - * we align. Add a cacheline if this is the case. - */ - if ((sg_prefetch_align % sg_size) != 0 - && (sg_prefetch_cnt < CCSGADDR_MAX)) - sg_prefetch_cnt += sg_prefetch_align; - /* - * Lastly, compute a value that the sequencer can use - * to determine if the remainder of the CCSGRAM buffer - * has a full S/G element in it. - */ - sg_prefetch_cnt_limit = -(sg_prefetch_cnt - sg_size + 1); - download_consts[SG_PREFETCH_CNT] = sg_prefetch_cnt; - download_consts[SG_PREFETCH_CNT_LIMIT] = sg_prefetch_cnt_limit; - download_consts[SG_PREFETCH_ALIGN_MASK] = ~(sg_prefetch_align - 1); - download_consts[SG_PREFETCH_ADDR_MASK] = (sg_prefetch_align - 1); - download_consts[SG_SIZEOF] = sg_size; - download_consts[PKT_OVERRUN_BUFOFFSET] = - (AHD_SCB_MAX * sizeof(uint16_t)) / 256; - if ((ahd->features & AHD_TARGETMODE) != 0) - download_consts[PKT_OVERRUN_BUFOFFSET] += - (AHD_TMODE_CMDS * sizeof(struct target_cmd)) / 256; - - cur_patch = patches; - downloaded = 0; - skip_addr = 0; - ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); - ahd_outb(ahd, PRGMCNT, 0); - ahd_outb(ahd, PRGMCNT+1, 0); - - for (i = 0; i < sizeof(seqprog)/4; i++) { - if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) { - /* - * Don't download this instruction as it - * is in a patch that was removed. - */ - continue; - } - /* - * Move through the CS table until we find a CS - * that might apply to this instruction. - */ - for (; cur_cs < num_critical_sections; cur_cs++) { - if (critical_sections[cur_cs].end <= i) { - if (begin_set[cs_count] == TRUE - && end_set[cs_count] == FALSE) { - cs_table[cs_count].end = downloaded; - end_set[cs_count] = TRUE; - cs_count++; - } - continue; - } - if (critical_sections[cur_cs].begin <= i - && begin_set[cs_count] == FALSE) { - cs_table[cs_count].begin = downloaded; - begin_set[cs_count] = TRUE; - } - break; - } - ahd_download_instr(ahd, i, download_consts); - downloaded++; - } - - ahd->num_critical_sections = cs_count; - if (cs_count != 0) { - - cs_count *= sizeof(struct cs); - ahd->critical_sections = malloc(cs_count, M_DEVBUF, M_NOWAIT); - if (ahd->critical_sections == NULL) - panic("ahd_loadseq: Could not malloc"); - memcpy(ahd->critical_sections, cs_table, cs_count); - } - ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE); - - if (bootverbose) - printf(" %d instructions downloaded\n", downloaded); -} - -static int -ahd_check_patch(struct ahd_softc *ahd, struct patch **start_patch, - u_int start_instr, u_int *skip_addr) -{ - struct patch *cur_patch; - struct patch *last_patch; - u_int num_patches; - - num_patches = sizeof(patches)/sizeof(struct patch); - last_patch = &patches[num_patches]; - cur_patch = *start_patch; - - while (cur_patch < last_patch && start_instr == cur_patch->begin) { - - if (cur_patch->patch_func(ahd) == 0) { - - /* Start rejecting code */ - *skip_addr = start_instr + cur_patch->skip_instr; - cur_patch += cur_patch->skip_patch; - } else { - /* Accepted this patch. Advance to the next - * one and wait for our intruction pointer to - * hit this point. - */ - cur_patch++; - } - } - - *start_patch = cur_patch; - if (start_instr < *skip_addr) - /* Still skipping */ - return (0); - - return (1); -} - -static u_int -ahd_resolve_seqaddr(struct ahd_softc *ahd, u_int address) -{ - struct patch *cur_patch; - int address_offset; - u_int skip_addr; - u_int i; - - address_offset = 0; - cur_patch = patches; - skip_addr = 0; - - for (i = 0; i < address;) { - - ahd_check_patch(ahd, &cur_patch, i, &skip_addr); - - if (skip_addr > i) { - int end_addr; - - end_addr = MIN(address, skip_addr); - address_offset += end_addr - i; - i = skip_addr; - } else { - i++; - } - } - return (address - address_offset); -} - -static void -ahd_download_instr(struct ahd_softc *ahd, u_int instrptr, uint8_t *dconsts) -{ - union ins_formats instr; - struct ins_format1 *fmt1_ins; - struct ins_format3 *fmt3_ins; - u_int opcode; - - /* - * The firmware is always compiled into a little endian format. - */ - instr.integer = ahd_le32toh(*(uint32_t*)&seqprog[instrptr * 4]); - - fmt1_ins = &instr.format1; - fmt3_ins = NULL; - - /* Pull the opcode */ - opcode = instr.format1.opcode; - switch (opcode) { - case AIC_OP_JMP: - case AIC_OP_JC: - case AIC_OP_JNC: - case AIC_OP_CALL: - case AIC_OP_JNE: - case AIC_OP_JNZ: - case AIC_OP_JE: - case AIC_OP_JZ: - { - fmt3_ins = &instr.format3; - fmt3_ins->address = ahd_resolve_seqaddr(ahd, fmt3_ins->address); - /* FALLTHROUGH */ - } - case AIC_OP_OR: - case AIC_OP_AND: - case AIC_OP_XOR: - case AIC_OP_ADD: - case AIC_OP_ADC: - case AIC_OP_BMOV: - if (fmt1_ins->parity != 0) { - fmt1_ins->immediate = dconsts[fmt1_ins->immediate]; - } - fmt1_ins->parity = 0; - /* FALLTHROUGH */ - case AIC_OP_ROL: - { - int i, count; - - /* Calculate odd parity for the instruction */ - for (i = 0, count = 0; i < 31; i++) { - uint32_t mask; - - mask = 0x01 << i; - if ((instr.integer & mask) != 0) - count++; - } - if ((count & 0x01) == 0) - instr.format1.parity = 1; - - /* The sequencer is a little endian cpu */ - instr.integer = ahd_htole32(instr.integer); - ahd_outsb(ahd, SEQRAM, instr.bytes, 4); - break; - } - default: - panic("Unknown opcode encountered in seq program"); - break; - } -} - -void -ahd_dump_all_cards_state() -{ - struct ahd_softc *list_ahd; - - TAILQ_FOREACH(list_ahd, &ahd_tailq, links) { - ahd_dump_card_state(list_ahd); - } -} - -void -ahd_dump_card_state(struct ahd_softc *ahd) -{ - struct scb *scb; - ahd_mode_state saved_modes; - u_int dffstat; - int paused; - u_int scb_index; - u_int i; - - if (ahd_is_paused(ahd)) { - paused = 1; - } else { - paused = 0; - ahd_pause(ahd); - } - saved_modes = ahd_save_modes(ahd); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - printf("%s: Dumping Card State at program address 0x%x Mode 0x%x\n", - ahd_name(ahd), - ahd_inb(ahd, CURADDR) | (ahd_inb(ahd, CURADDR+1) << 8), - ahd_build_mode_state(ahd, ahd->saved_src_mode, - ahd->saved_dst_mode)); - printf("Softc pointer is %p\n", ahd); - printf("IOWNID == 0x%x, TOWNID == 0x%x, SCSISEQ1 == 0x%x\n", - ahd_inb(ahd, IOWNID), ahd_inb(ahd, TOWNID), - ahd_inb(ahd, SCSISEQ1)); - printf("SCSISIGI == 0x%x\n", ahd_inb(ahd, SCSISIGI)); - printf("QFREEZE_COUNT == %d, SEQ_FLAGS2 == 0x%x\n", - ahd_inw(ahd, QFREEZE_COUNT), ahd_inb(ahd, SEQ_FLAGS2)); - if (paused) - printf("Card was paused\n"); - printf("%s: LASTSCB 0x%x CURRSCB 0x%x NEXTSCB 0x%x SEQINTCTL 0x%x\n", - ahd_name(ahd), ahd_inw(ahd, LASTSCB), ahd_inw(ahd, CURRSCB), - ahd_inw(ahd, NEXTSCB), ahd_inb(ahd, SEQINTCTL)); - printf("SCSISEQ = 0x%x\n", ahd_inb(ahd, SCSISEQ0)); - printf("SCB count = %d\n", ahd->scb_data.numscbs); - printf("Kernel NEXTQSCB = %d\n", SCB_GET_TAG(ahd->next_queued_scb)); - printf("%s: LQCTL1 = 0x%x\n", - ahd_name(ahd), ahd_inb(ahd, LQCTL1)); - printf("%s: WAITING_TID_LIST == 0x%x:0x%x\n", - ahd_name(ahd), ahd_inw(ahd, WAITING_TID_HEAD), - ahd_inw(ahd, WAITING_TID_TAIL)); - printf("%s: WAITING_SCB_TAILS: ", ahd_name(ahd)); - for (i = 0; i < AHD_NUM_TARGETS; i++) { - printf("%d(0x%x) ", i, - ahd_inw(ahd, WAITING_SCB_TAILS + (2 * i))); - } - printf("\n"); - /* QINFIFO */ - ahd_search_qinfifo(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS, - CAM_LUN_WILDCARD, SCB_LIST_NULL, - ROLE_UNKNOWN, /*status*/0, SEARCH_PRINT); - printf("Pending list:\n"); - i = 0; - LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) { - if (i++ > AHD_SCB_MAX) - break; - if (scb != LIST_FIRST(&ahd->pending_scbs)) - printf(", "); - printf("%3d", SCB_GET_TAG(scb)); - ahd_set_scbptr(ahd, SCB_GET_TAG(scb)); - printf("(CTRL 0x%x ID 0x%x N 0x%x N2 0x%x SG 0x%x," - " RSG 0x%x, KSG 0x%x)\n", - ahd_inb(ahd, SCB_CONTROL), - ahd_inb(ahd, SCB_SCSIID), ahd_inw(ahd, SCB_NEXT), - ahd_inw(ahd, SCB_NEXT2), ahd_inl(ahd, SCB_SGPTR), - ahd_inl(ahd, SCB_RESIDUAL_SGPTR), - ahd_le32toh(scb->hscb->sgptr)); - } - printf("\n"); - - printf("Kernel Free SCB list: "); - i = 0; - SLIST_FOREACH(scb, &ahd->scb_data.free_scbs, links.sle) { - if (i++ > AHD_SCB_MAX) - break; - printf("%d ", SCB_GET_TAG(scb)); - } - printf("\n"); - - printf("Sequencer Complete DMA-inprog list: "); - scb_index = ahd_inw(ahd, COMPLETE_SCB_DMAINPROG_HEAD); - i = 0; - while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { - ahd_set_scbptr(ahd, scb_index); - printf("%d ", scb_index); - scb_index = ahd_inw(ahd, SCB_NEXT_COMPLETE); - } - printf("\n"); - - printf("Sequencer Complete list: "); - scb_index = ahd_inw(ahd, COMPLETE_SCB_HEAD); - i = 0; - while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { - ahd_set_scbptr(ahd, scb_index); - printf("%d ", scb_index); - scb_index = ahd_inw(ahd, SCB_NEXT_COMPLETE); - } - printf("\n"); - - - printf("Sequencer DMA-Up and Complete list: "); - scb_index = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD); - i = 0; - while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { - ahd_set_scbptr(ahd, scb_index); - printf("%d ", scb_index); - scb_index = ahd_inw(ahd, SCB_NEXT_COMPLETE); - } - printf("\n"); - printf("%s: SIMODE1 = 0x%x\n", - ahd_name(ahd), ahd_inb(ahd, SIMODE1)); - printf("%s: LQISTAT0 = 0x%x, LQISTAT1 = 0x%x, LQISTAT2 = 0x%x\n", - ahd_name(ahd), ahd_inb(ahd, LQISTAT0), ahd_inb(ahd, LQISTAT1), - ahd_inb(ahd, LQISTAT2)); - printf("%s: LQOSTAT0 = 0x%x, LQOSTAT1 = 0x%x, LQOSTAT2 = 0x%x\n", - ahd_name(ahd), ahd_inb(ahd, LQOSTAT0), ahd_inb(ahd, LQOSTAT1), - ahd_inb(ahd, LQOSTAT2)); - dffstat = ahd_inb(ahd, DFFSTAT); - for (i = 0; i < 2; i++) { - struct scb *fifo_scb; - u_int fifo_scbptr; - - ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i); - fifo_scbptr = ahd_inb(ahd, SCBPTR); - printf("%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x, LJSCB 0x%x\n", - ahd_name(ahd), i, - (dffstat & (FIFO0FREE << i)) ? "Free" : "Active", - ahd_inw(ahd, LONGJMP_ADDR), fifo_scbptr, - ahd_inw(ahd, LONGJMP_SCB)); - printf("%s: SEQIMODE == 0x%x, SEQINTSRC == 0x%x\n", - ahd_name(ahd), ahd_inb(ahd, SEQIMODE), - ahd_inb(ahd, SEQINTSRC)); - printf("%s: DFCNTRL == 0x%x, DFSTATUS == 0x%x, " - "SG_CACHE_SHADOW = 0x%x, SG_STATE = 0x%x\n", - ahd_name(ahd), ahd_inb(ahd, DFCNTRL), - ahd_inb(ahd, DFSTATUS), ahd_inb(ahd, SG_CACHE_SHADOW), - ahd_inb(ahd, SG_STATE)); - printf("SSTAT0 = 0x%x, SSTAT1 = 0x%x, SSTAT2 = 0x%x\n", - ahd_inb(ahd, SSTAT0), ahd_inb(ahd, SSTAT1), - ahd_inb(ahd, SSTAT2)); - printf("DFFSXFRCTL = 0x%x, SOFFCNT = 0x%x\n", - ahd_inb(ahd, DFFSXFRCTL), ahd_inb(ahd, SOFFCNT)); - printf("MDFFSTAT = 0x%x, SHADDR = 0x%x, SHCNT = 0x%x\n", - ahd_inb(ahd, MDFFSTAT), ahd_inl(ahd, SHADDR), - (ahd_inb(ahd, SHCNT) - | (ahd_inb(ahd, SHCNT + 1) << 8) - | (ahd_inb(ahd, SHCNT + 2) << 16))); - printf("HADDR = 0x%x, HCNT = 0x%x\n", - ahd_inl(ahd, HADDR), - (ahd_inb(ahd, HCNT) - | (ahd_inb(ahd, HCNT + 1) << 8) - | (ahd_inb(ahd, HCNT + 2) << 16))); - printf("CCSGCTL = 0x%x\n", ahd_inb(ahd, CCSGCTL)); - fifo_scb = ahd_lookup_scb(ahd, fifo_scbptr); - if (fifo_scb != NULL) - ahd_dump_sglist(fifo_scb); - } - printf("LQIN: "); - for (i = 0; i < 20; i++) - printf("0x%x ", ahd_inb(ahd, LQIN + i)); - printf("\n"); - printf("%s: SSTAT3 == 0x%x\n", ahd_name(ahd), ahd_inb(ahd, SSTAT3)); - ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); - printf("%s: LQISTATE = 0x%x, LQOSTATE = 0x%x, OPTIONMODE = 0x%x\n", - ahd_name(ahd), ahd_inb(ahd, LQISTATE), ahd_inb(ahd, LQOSTATE), - ahd_inb(ahd, OPTIONMODE)); - printf("%s: OS_SPACE_CNT = 0x%x MAXCMDCNT = 0x%x\n", - ahd_name(ahd), ahd_inb(ahd, OS_SPACE_CNT), - ahd_inb(ahd, MAXCMDCNT)); - ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode); - printf("%s: REG0 == 0x%x, SINDEX = 0x%x, DINDEX = 0x%x\n", - ahd_name(ahd), ahd_inw(ahd, REG0), ahd_inw(ahd, SINDEX), - ahd_inw(ahd, DINDEX)); - printf("%s: SCBPTR == 0x%x, SCB_NEXT == 0x%x, SCB_NEXT2 == 0x%x\n", - ahd_name(ahd), ahd_get_scbptr(ahd), ahd_inw(ahd, SCB_NEXT), - ahd_inw(ahd, SCB_NEXT2)); - printf("CDB %x %x %x %x %x %x\n", - ahd_inb(ahd, SCB_CDB_STORE), - ahd_inb(ahd, SCB_CDB_STORE+1), - ahd_inb(ahd, SCB_CDB_STORE+2), - ahd_inb(ahd, SCB_CDB_STORE+3), - ahd_inb(ahd, SCB_CDB_STORE+4), - ahd_inb(ahd, SCB_CDB_STORE+5)); - printf("STACK:"); - for(i = 0; i < SEQ_STACK_SIZE; i++) - printf(" 0x%x", ahd_inb(ahd, STACK)|(ahd_inb(ahd, STACK) << 8)); - printf("\n"); - ahd_platform_dump_card_state(ahd); - ahd_restore_modes(ahd, saved_modes); - if (paused == 0) - ahd_unpause(ahd); -} - -void -ahd_dump_scbs(struct ahd_softc *ahd) -{ - ahd_mode_state saved_modes; - int i; - - saved_modes = ahd_save_modes(ahd); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - for (i = 0; i < AHD_SCB_MAX; i++) { - ahd_set_scbptr(ahd, i); - printf("%3d", i); - printf("(CTRL 0x%x ID 0x%x N 0x%x N2 0x%x SG 0x%x, RSG 0x%x)\n", - ahd_inb(ahd, SCB_CONTROL), - ahd_inb(ahd, SCB_SCSIID), ahd_inw(ahd, SCB_NEXT), - ahd_inw(ahd, SCB_NEXT2), ahd_inl(ahd, SCB_SGPTR), - ahd_inl(ahd, SCB_RESIDUAL_SGPTR)); - } - printf("\n"); - ahd_restore_modes(ahd, saved_modes); -} - -/**************************** Flexport Logic **********************************/ -/* - * Read count 16bit words from 16bit word address start_addr from the - * SEEPROM attached to the controller, into buf, using the controller's - * SEEPROM reading state machine. - */ -int -ahd_read_seeprom(struct ahd_softc *ahd, uint16_t *buf, - u_int start_addr, u_int count) -{ - u_int cur_addr; - u_int end_addr; - int error; - - /* - * If we never make it through the loop even once, - * we were passed invalid arguments. - */ - error = EINVAL; - AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); - end_addr = start_addr + count; - for (cur_addr = start_addr; cur_addr < end_addr; cur_addr++) { - ahd_outb(ahd, SEEADR, cur_addr); - ahd_outb(ahd, SEECTL, SEEOP_READ | SEESTART); - - error = ahd_wait_seeprom(ahd); - if (error) - break; - *buf++ = ahd_inw(ahd, SEEDAT); - } - return (error); -} - -/* - * Write count 16bit words from buf, into SEEPROM attache to the - * controller starting at 16bit word address start_addr, using the - * controller's SEEPROM writing state machine. - */ -int -ahd_write_seeprom(struct ahd_softc *ahd, uint16_t *buf, - u_int start_addr, u_int count) -{ - u_int cur_addr; - u_int end_addr; - int error; - int retval; - - AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); - error = ENOENT; - - /* Place the chip into write-enable mode */ - ahd_outb(ahd, SEEADR, SEEOP_EWEN_ADDR); - ahd_outb(ahd, SEECTL, SEEOP_EWEN | SEESTART); - error = ahd_wait_seeprom(ahd); - if (error) - return (error); - - /* - * Write the data. If we don't get throught the loop at - * least once, the arguments were invalid. - */ - retval = EINVAL; - end_addr = start_addr + count; - for (cur_addr = start_addr; cur_addr < end_addr; cur_addr++) { - ahd_outw(ahd, SEEDAT, *buf++); - ahd_outb(ahd, SEEADR, cur_addr); - ahd_outb(ahd, SEECTL, SEEOP_WRITE | SEESTART); - - retval = ahd_wait_seeprom(ahd); - if (retval) - break; - } - - /* - * Disable writes. - */ - ahd_outb(ahd, SEEADR, SEEOP_EWDS_ADDR); - ahd_outb(ahd, SEECTL, SEEOP_EWDS | SEESTART); - error = ahd_wait_seeprom(ahd); - if (error) - return (error); - return (retval); -} - -/* - * Wait ~100us for the serial eeprom to satisfy our request. - */ -int -ahd_wait_seeprom(struct ahd_softc *ahd) -{ - int cnt; - - cnt = 20; - while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt) - ahd_delay(5); - - if (cnt == 0) - return (ETIMEDOUT); - return (0); -} - -int -ahd_verify_cksum(struct seeprom_config *sc) -{ - int i; - int maxaddr; - uint32_t checksum; - uint16_t *scarray; - - maxaddr = (sizeof(*sc)/2) - 1; - checksum = 0; - scarray = (uint16_t *)sc; - - for (i = 0; i < maxaddr; i++) - checksum = checksum + scarray[i]; - if (checksum == 0 - || (checksum & 0xFFFF) != sc->checksum) { - return (0); - } else { - return (1); - } -} - -int -ahd_acquire_seeprom(struct ahd_softc *ahd) -{ - uint8_t seetype; - int error; - - error = ahd_read_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, &seetype); - if (error != 0 - || ((seetype & FLX_ROMSTAT_SEECFG) == FLX_ROMSTAT_SEE_NONE)) - return (0); - return (1); -} - -void -ahd_release_seeprom(struct ahd_softc *ahd) -{ - /* Currently a no-op */ -} - -int -ahd_write_flexport(struct ahd_softc *ahd, u_int addr, u_int value) -{ - int error; - - AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); - if (addr > 7) - panic("ahd_write_flexport: address out of range"); - ahd_outb(ahd, BRDCTL, BRDEN|(addr << 3)); - error = ahd_wait_flexport(ahd); - if (error != 0) - return (error); - ahd_outb(ahd, BRDDAT, value); - ahd_flush_device_writes(ahd); - ahd_outb(ahd, BRDCTL, BRDSTB|BRDEN|(addr << 3)); - ahd_flush_device_writes(ahd); - ahd_outb(ahd, BRDCTL, BRDEN|(addr << 3)); - ahd_flush_device_writes(ahd); - ahd_outb(ahd, BRDCTL, 0); - ahd_flush_device_writes(ahd); - return (0); -} - -int -ahd_read_flexport(struct ahd_softc *ahd, u_int addr, uint8_t *value) -{ - int error; - - AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); - if (addr > 7) - panic("ahd_read_flexport: address out of range"); - ahd_outb(ahd, BRDCTL, BRDRW|BRDEN|(addr << 3)); - error = ahd_wait_flexport(ahd); - if (error != 0) - return (error); - *value = ahd_inb(ahd, BRDDAT); - ahd_outb(ahd, BRDCTL, 0); - ahd_flush_device_writes(ahd); - return (0); -} - -/* - * Wait at most 2 seconds for flexport arbitration to succeed. - */ -int -ahd_wait_flexport(struct ahd_softc *ahd) -{ - int cnt; - - AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); - cnt = 1000000 * 2 / 5; - while ((ahd_inb(ahd, BRDCTL) & FLXARBACK) == 0 && --cnt) - ahd_delay(5); - - if (cnt == 0) - return (ETIMEDOUT); - return (0); -} - -/************************* Target Mode ****************************************/ -#ifdef AHD_TARGET_MODE -cam_status -ahd_find_tmode_devs(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb, - struct ahd_tmode_tstate **tstate, - struct ahd_tmode_lstate **lstate, - int notfound_failure) -{ - - if ((ahd->features & AHD_TARGETMODE) == 0) - return (CAM_REQ_INVALID); - - /* - * Handle the 'black hole' device that sucks up - * requests to unattached luns on enabled targets. - */ - if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD - && ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) { - *tstate = NULL; - *lstate = ahd->black_hole; - } else { - u_int max_id; - - max_id = (ahd->features & AHD_WIDE) ? 15 : 7; - if (ccb->ccb_h.target_id > max_id) - return (CAM_TID_INVALID); - - if (ccb->ccb_h.target_lun >= AHD_NUM_LUNS) - return (CAM_LUN_INVALID); - - *tstate = ahd->enabled_targets[ccb->ccb_h.target_id]; - *lstate = NULL; - if (*tstate != NULL) - *lstate = - (*tstate)->enabled_luns[ccb->ccb_h.target_lun]; - } - - if (notfound_failure != 0 && *lstate == NULL) - return (CAM_PATH_INVALID); - - return (CAM_REQ_CMP); -} - -void -ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) -{ -#if NOT_YET - struct ahd_tmode_tstate *tstate; - struct ahd_tmode_lstate *lstate; - struct ccb_en_lun *cel; - cam_status status; - u_int target; - u_int lun; - u_int target_mask; - u_long s; - char channel; - - status = ahd_find_tmode_devs(ahd, sim, ccb, &tstate, &lstate, - /*notfound_failure*/FALSE); - - if (status != CAM_REQ_CMP) { - ccb->ccb_h.status = status; - return; - } - - if ((ahd->features & AHD_MULTIROLE) != 0) { - u_int our_id; - - our_id = ahd->our_id; - if (ccb->ccb_h.target_id != our_id) { - if ((ahd->features & AHD_MULTI_TID) != 0 - && (ahd->flags & AHD_INITIATORROLE) != 0) { - /* - * Only allow additional targets if - * the initiator role is disabled. - * The hardware cannot handle a re-select-in - * on the initiator id during a re-select-out - * on a different target id. - */ - status = CAM_TID_INVALID; - } else if ((ahd->flags & AHD_INITIATORROLE) != 0 - || ahd->enabled_luns > 0) { - /* - * Only allow our target id to change - * if the initiator role is not configured - * and there are no enabled luns which - * are attached to the currently registered - * scsi id. - */ - status = CAM_TID_INVALID; - } - } - } - - if (status != CAM_REQ_CMP) { - ccb->ccb_h.status = status; - return; - } - - /* - * We now have an id that is valid. - * If we aren't in target mode, switch modes. - */ - if ((ahd->flags & AHD_TARGETROLE) == 0 - && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) { - u_long s; - - printf("Configuring Target Mode\n"); - ahd_lock(ahd, &s); - if (LIST_FIRST(&ahd->pending_scbs) != NULL) { - ccb->ccb_h.status = CAM_BUSY; - ahd_unlock(ahd, &s); - return; - } - ahd->flags |= AHD_TARGETROLE; - if ((ahd->features & AHD_MULTIROLE) == 0) - ahd->flags &= ~AHD_INITIATORROLE; - ahd_pause(ahd); - ahd_loadseq(ahd); - ahd_unlock(ahd, &s); - } - cel = &ccb->cel; - target = ccb->ccb_h.target_id; - lun = ccb->ccb_h.target_lun; - channel = SIM_CHANNEL(ahd, sim); - target_mask = 0x01 << target; - if (channel == 'B') - target_mask <<= 8; - - if (cel->enable != 0) { - u_int scsiseq1; - - /* Are we already enabled?? */ - if (lstate != NULL) { - xpt_print_path(ccb->ccb_h.path); - printf("Lun already enabled\n"); - ccb->ccb_h.status = CAM_LUN_ALRDY_ENA; - return; - } - - if (cel->grp6_len != 0 - || cel->grp7_len != 0) { - /* - * Don't (yet?) support vendor - * specific commands. - */ - ccb->ccb_h.status = CAM_REQ_INVALID; - printf("Non-zero Group Codes\n"); - return; - } - - /* - * Seems to be okay. - * Setup our data structures. - */ - if (target != CAM_TARGET_WILDCARD && tstate == NULL) { - tstate = ahd_alloc_tstate(ahd, target, channel); - if (tstate == NULL) { - xpt_print_path(ccb->ccb_h.path); - printf("Couldn't allocate tstate\n"); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; - return; - } - } - lstate = malloc(sizeof(*lstate), M_DEVBUF, M_NOWAIT); - if (lstate == NULL) { - xpt_print_path(ccb->ccb_h.path); - printf("Couldn't allocate lstate\n"); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; - return; - } - memset(lstate, 0, sizeof(*lstate)); - status = xpt_create_path(&lstate->path, /*periph*/NULL, - xpt_path_path_id(ccb->ccb_h.path), - xpt_path_target_id(ccb->ccb_h.path), - xpt_path_lun_id(ccb->ccb_h.path)); - if (status != CAM_REQ_CMP) { - free(lstate, M_DEVBUF); - xpt_print_path(ccb->ccb_h.path); - printf("Couldn't allocate path\n"); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; - return; - } - SLIST_INIT(&lstate->accept_tios); - SLIST_INIT(&lstate->immed_notifies); - ahd_lock(ahd, &s); - ahd_pause(ahd); - if (target != CAM_TARGET_WILDCARD) { - tstate->enabled_luns[lun] = lstate; - ahd->enabled_luns++; - - if ((ahd->features & AHD_MULTI_TID) != 0) { - u_int targid_mask; - - targid_mask = ahd_inb(ahd, TARGID) - | (ahd_inb(ahd, TARGID + 1) << 8); - - targid_mask |= target_mask; - ahd_outb(ahd, TARGID, targid_mask); - ahd_outb(ahd, TARGID+1, (targid_mask >> 8)); - - ahd_update_scsiid(ahd, targid_mask); - } else { - u_int our_id; - char channel; - - channel = SIM_CHANNEL(ahd, sim); - our_id = SIM_SCSI_ID(ahd, sim); - - /* - * This can only happen if selections - * are not enabled - */ - if (target != our_id) { - u_int sblkctl; - char cur_channel; - int swap; - - sblkctl = ahd_inb(ahd, SBLKCTL); - cur_channel = (sblkctl & SELBUSB) - ? 'B' : 'A'; - if ((ahd->features & AHD_TWIN) == 0) - cur_channel = 'A'; - swap = cur_channel != channel; - ahd->our_id = target; - - if (swap) - ahd_outb(ahd, SBLKCTL, - sblkctl ^ SELBUSB); - - ahd_outb(ahd, SCSIID, target); - - if (swap) - ahd_outb(ahd, SBLKCTL, sblkctl); - } - } - } else - ahd->black_hole = lstate; - /* Allow select-in operations */ - if (ahd->black_hole != NULL && ahd->enabled_luns > 0) { - scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE); - scsiseq1 |= ENSELI; - ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq1); - scsiseq1 = ahd_inb(ahd, SCSISEQ1); - scsiseq1 |= ENSELI; - ahd_outb(ahd, SCSISEQ1, scsiseq1); - } - ahd_unpause(ahd); - ahd_unlock(ahd, &s); - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_print_path(ccb->ccb_h.path); - printf("Lun now enabled for target mode\n"); - } else { - struct scb *scb; - int i, empty; - - if (lstate == NULL) { - ccb->ccb_h.status = CAM_LUN_INVALID; - return; - } - - ahd_lock(ahd, &s); - - ccb->ccb_h.status = CAM_REQ_CMP; - LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) { - struct ccb_hdr *ccbh; - - ccbh = &scb->io_ctx->ccb_h; - if (ccbh->func_code == XPT_CONT_TARGET_IO - && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){ - printf("CTIO pending\n"); - ccb->ccb_h.status = CAM_REQ_INVALID; - ahd_unlock(ahd, &s); - return; - } - } - - if (SLIST_FIRST(&lstate->accept_tios) != NULL) { - printf("ATIOs pending\n"); - ccb->ccb_h.status = CAM_REQ_INVALID; - } - - if (SLIST_FIRST(&lstate->immed_notifies) != NULL) { - printf("INOTs pending\n"); - ccb->ccb_h.status = CAM_REQ_INVALID; - } - - if (ccb->ccb_h.status != CAM_REQ_CMP) { - ahd_unlock(ahd, &s); - return; - } - - xpt_print_path(ccb->ccb_h.path); - printf("Target mode disabled\n"); - xpt_free_path(lstate->path); - free(lstate, M_DEVBUF); - - ahd_pause(ahd); - /* Can we clean up the target too? */ - if (target != CAM_TARGET_WILDCARD) { - tstate->enabled_luns[lun] = NULL; - ahd->enabled_luns--; - for (empty = 1, i = 0; i < 8; i++) - if (tstate->enabled_luns[i] != NULL) { - empty = 0; - break; - } - - if (empty) { - ahd_free_tstate(ahd, target, channel, - /*force*/FALSE); - if (ahd->features & AHD_MULTI_TID) { - u_int targid_mask; - - targid_mask = ahd_inb(ahd, TARGID) - | (ahd_inb(ahd, TARGID + 1) - << 8); - - targid_mask &= ~target_mask; - ahd_outb(ahd, TARGID, targid_mask); - ahd_outb(ahd, TARGID+1, - (targid_mask >> 8)); - ahd_update_scsiid(ahd, targid_mask); - } - } - } else { - - ahd->black_hole = NULL; - - /* - * We can't allow selections without - * our black hole device. - */ - empty = TRUE; - } - if (ahd->enabled_luns == 0) { - /* Disallow select-in */ - u_int scsiseq1; - - scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE); - scsiseq1 &= ~ENSELI; - ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq1); - scsiseq1 = ahd_inb(ahd, SCSISEQ1); - scsiseq1 &= ~ENSELI; - ahd_outb(ahd, SCSISEQ1, scsiseq1); - - if ((ahd->features & AHD_MULTIROLE) == 0) { - printf("Configuring Initiator Mode\n"); - ahd->flags &= ~AHD_TARGETROLE; - ahd->flags |= AHD_INITIATORROLE; - ahd_pause(ahd); - ahd_loadseq(ahd); - } - } - ahd_unpause(ahd); - ahd_unlock(ahd, &s); - } -#endif -} - -static void -ahd_update_scsiid(struct ahd_softc *ahd, u_int targid_mask) -{ -#if NOT_YET - u_int scsiid_mask; - u_int scsiid; - - if ((ahd->features & AHD_MULTI_TID) == 0) - panic("ahd_update_scsiid called on non-multitid unit\n"); - - /* - * Since we will rely on the the TARGID mask - * for selection enables, ensure that OID - * in SCSIID is not set to some other ID - * that we don't want to allow selections on. - */ - if ((ahd->features & AHD_ULTRA2) != 0) - scsiid = ahd_inb(ahd, SCSIID_ULTRA2); - else - scsiid = ahd_inb(ahd, SCSIID); - scsiid_mask = 0x1 << (scsiid & OID); - if ((targid_mask & scsiid_mask) == 0) { - u_int our_id; - - /* ffs counts from 1 */ - our_id = ffs(targid_mask); - if (our_id == 0) - our_id = ahd->our_id; - else - our_id--; - scsiid &= TID; - scsiid |= our_id; - } - if ((ahd->features & AHD_ULTRA2) != 0) - ahd_outb(ahd, SCSIID_ULTRA2, scsiid); - else - ahd_outb(ahd, SCSIID, scsiid); -#endif -} - -void -ahd_run_tqinfifo(struct ahd_softc *ahd, int paused) -{ - struct target_cmd *cmd; - - ahd_sync_tqinfifo(ahd, BUS_DMASYNC_POSTREAD); - while ((cmd = &ahd->targetcmds[ahd->tqinfifonext])->cmd_valid != 0) { - - /* - * Only advance through the queue if we - * have the resources to process the command. - */ - if (ahd_handle_target_cmd(ahd, cmd) != 0) - break; - - cmd->cmd_valid = 0; - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap, - ahd_targetcmd_offset(ahd, ahd->tqinfifonext), - sizeof(struct target_cmd), - BUS_DMASYNC_PREREAD); - ahd->tqinfifonext++; - - /* - * Lazily update our position in the target mode incoming - * command queue as seen by the sequencer. - */ - if ((ahd->tqinfifonext & (HOST_TQINPOS - 1)) == 1) { - u_int hs_mailbox; - - hs_mailbox = ahd_inb(ahd, HS_MAILBOX); - hs_mailbox &= ~HOST_TQINPOS; - hs_mailbox |= ahd->tqinfifonext & HOST_TQINPOS; - ahd_outb(ahd, HS_MAILBOX, hs_mailbox); - } - } -} - -static int -ahd_handle_target_cmd(struct ahd_softc *ahd, struct target_cmd *cmd) -{ - struct ahd_tmode_tstate *tstate; - struct ahd_tmode_lstate *lstate; - struct ccb_accept_tio *atio; - uint8_t *byte; - int initiator; - int target; - int lun; - - initiator = SCSIID_TARGET(ahd, cmd->scsiid); - target = SCSIID_OUR_ID(cmd->scsiid); - lun = (cmd->identify & MSG_IDENTIFY_LUNMASK); - - byte = cmd->bytes; - tstate = ahd->enabled_targets[target]; - lstate = NULL; - if (tstate != NULL) - lstate = tstate->enabled_luns[lun]; - - /* - * Commands for disabled luns go to the black hole driver. - */ - if (lstate == NULL) - lstate = ahd->black_hole; - - atio = (struct ccb_accept_tio*)SLIST_FIRST(&lstate->accept_tios); - if (atio == NULL) { - ahd->flags |= AHD_TQINFIFO_BLOCKED; - /* - * Wait for more ATIOs from the peripheral driver for this lun. - */ - return (1); - } else - ahd->flags &= ~AHD_TQINFIFO_BLOCKED; -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_TQIN) != 0) - printf("Incoming command from %d for %d:%d%s\n", - initiator, target, lun, - lstate == ahd->black_hole ? "(Black Holed)" : ""); -#endif - SLIST_REMOVE_HEAD(&lstate->accept_tios, sim_links.sle); - - if (lstate == ahd->black_hole) { - /* Fill in the wildcards */ - atio->ccb_h.target_id = target; - atio->ccb_h.target_lun = lun; - } - - /* - * Package it up and send it off to - * whomever has this lun enabled. - */ - atio->sense_len = 0; - atio->init_id = initiator; - if (byte[0] != 0xFF) { - /* Tag was included */ - atio->tag_action = *byte++; - atio->tag_id = *byte++; - atio->ccb_h.flags = CAM_TAG_ACTION_VALID; - } else { - atio->ccb_h.flags = 0; - } - byte++; - - /* Okay. Now determine the cdb size based on the command code */ - switch (*byte >> CMD_GROUP_CODE_SHIFT) { - case 0: - atio->cdb_len = 6; - break; - case 1: - case 2: - atio->cdb_len = 10; - break; - case 4: - atio->cdb_len = 16; - break; - case 5: - atio->cdb_len = 12; - break; - case 3: - default: - /* Only copy the opcode. */ - atio->cdb_len = 1; - printf("Reserved or VU command code type encountered\n"); - break; - } - - memcpy(atio->cdb_io.cdb_bytes, byte, atio->cdb_len); - - atio->ccb_h.status |= CAM_CDB_RECVD; - - if ((cmd->identify & MSG_IDENTIFY_DISCFLAG) == 0) { - /* - * We weren't allowed to disconnect. - * We're hanging on the bus until a - * continue target I/O comes in response - * to this accept tio. - */ -#if AHD_DEBUG - if ((ahd_debug & AHD_SHOW_TQIN) != 0) - printf("Received Immediate Command %d:%d:%d - %p\n", - initiator, target, lun, ahd->pending_device); -#endif - ahd->pending_device = lstate; - ahd_freeze_ccb((union ccb *)atio); - atio->ccb_h.flags |= CAM_DIS_DISCONNECT; - } - xpt_done((union ccb*)atio); - return (0); -} - -#endif diff --git a/xen/drivers/scsi/aic7xxx/aic79xx_host.h b/xen/drivers/scsi/aic7xxx/aic79xx_host.h deleted file mode 100644 index e8d1ce47a1..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic79xx_host.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Adaptec AIC79xx device driver host template for Linux. - * - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_host.h#6 $ - */ - -#ifndef _AIC79XX_LINUX_HOST_H_ -#define _AIC79XX_LINUX_HOST_H_ - -int ahd_linux_proc_info(char *, char **, off_t, int, int, int); -int ahd_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); -int ahd_linux_detect(Scsi_Host_Template *); -int ahd_linux_release(struct Scsi_Host *); -const char *ahd_linux_info(struct Scsi_Host *); -int ahd_linux_biosparam(Disk *, kdev_t, int[]); -int ahd_linux_bus_reset(Scsi_Cmnd *); -int ahd_linux_dev_reset(Scsi_Cmnd *); -int ahd_linux_abort(Scsi_Cmnd *); - -#if defined(__i386__) -# define AIC79XX_BIOSPARAM ahd_linux_biosparam -#else -# define AIC79XX_BIOSPARAM NULL -#endif - -/* - * Scsi_Host_Template (see hosts.h) for AIC-79xx - some fields - * to do with card config are filled in after the card is detected. - */ -/* SAE: - proc_dir: NULL, \ - proc_info: ahd_linux_proc_info, \ -*/ -#define AIC79XX { \ - next: NULL, \ - module: NULL, \ - name: NULL, \ - detect: ahd_linux_detect, \ - release: ahd_linux_release, \ - info: ahd_linux_info, \ - command: NULL, \ - queuecommand: ahd_linux_queue, \ - eh_strategy_handler: NULL, \ - eh_abort_handler: ahd_linux_abort, \ - eh_device_reset_handler: ahd_linux_dev_reset, \ - eh_bus_reset_handler: ahd_linux_bus_reset, \ - eh_host_reset_handler: NULL, \ - abort: NULL, \ - reset: NULL, \ - slave_attach: NULL, \ - bios_param: AIC79XX_BIOSPARAM, \ - can_queue: AHD_MAX_QUEUE,/* max simultaneous cmds */\ - this_id: -1, /* scsi id of host adapter */\ - sg_tablesize: AHD_NSEG, /* max scatter-gather cmds */\ - cmd_per_lun: 2, /* cmds per lun */\ - present: 0, /* number of 7xxx's present */\ - unchecked_isa_dma: 0, /* no memory DMA restrictions*/\ - use_clustering: ENABLE_CLUSTERING, \ - use_new_eh_code: 1 \ -} - -#endif /* _AIC79XX_LINUX_HOST_H_ */ diff --git a/xen/drivers/scsi/aic7xxx/aic79xx_inline.h b/xen/drivers/scsi/aic7xxx/aic79xx_inline.h deleted file mode 100644 index 72750fc18a..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic79xx_inline.h +++ /dev/null @@ -1,997 +0,0 @@ -/* - * Inline routines shareable across OS platforms. - * - * Copyright (c) 1994-2001 Justin T. Gibbs. - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#28 $ - * - * $FreeBSD$ - */ - -#ifndef _AIC79XX_INLINE_H_ -#define _AIC79XX_INLINE_H_ - -/******************************** Debugging ***********************************/ -static __inline char *ahd_name(struct ahd_softc *ahd); - -static __inline char * -ahd_name(struct ahd_softc *ahd) -{ - return (ahd->name); -} - -/************************ Sequencer Execution Control *************************/ -static __inline void ahd_known_modes(struct ahd_softc *ahd, - ahd_mode src, ahd_mode dst); -static __inline ahd_mode_state ahd_build_mode_state(struct ahd_softc *ahd, - ahd_mode src, - ahd_mode dst); -static __inline void ahd_extract_mode_state(struct ahd_softc *ahd, - ahd_mode_state state, - ahd_mode *src, ahd_mode *dst); -static __inline void ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, - ahd_mode dst); -static __inline void ahd_update_modes(struct ahd_softc *ahd); -static __inline void ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode, - ahd_mode dstmode, const char *file, - int line); -static __inline ahd_mode_state ahd_save_modes(struct ahd_softc *ahd); -static __inline void ahd_restore_modes(struct ahd_softc *ahd, - ahd_mode_state state); -static __inline int ahd_is_paused(struct ahd_softc *ahd); -static __inline void ahd_pause(struct ahd_softc *ahd); -static __inline void ahd_unpause(struct ahd_softc *ahd); - -static __inline void -ahd_known_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst) -{ - ahd->src_mode = src; - ahd->dst_mode = dst; - ahd->saved_src_mode = src; - ahd->saved_dst_mode = dst; -} - -static __inline ahd_mode_state -ahd_build_mode_state(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst) -{ - return ((src << SRC_MODE_SHIFT) | (dst << DST_MODE_SHIFT)); -} - -static __inline void -ahd_extract_mode_state(struct ahd_softc *ahd, ahd_mode_state state, - ahd_mode *src, ahd_mode *dst) -{ - *src = (state & SRC_MODE) >> SRC_MODE_SHIFT; - *dst = (state & DST_MODE) >> DST_MODE_SHIFT; -} - -static __inline void -ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst) -{ - if (ahd->src_mode == src && ahd->dst_mode == dst) - return; -#ifdef AHD_DEBUG - if (ahd->src_mode == AHD_MODE_UNKNOWN - || ahd->dst_mode == AHD_MODE_UNKNOWN) - panic("Setting mode prior to saving it.\n"); - if ((ahd_debug & AHD_SHOW_MODEPTR) != 0) - printf("Setting mode 0x%x\n", - ahd_build_mode_state(ahd, src, dst)); -#endif - ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst)); - ahd->src_mode = src; - ahd->dst_mode = dst; -} - -static __inline void -ahd_update_modes(struct ahd_softc *ahd) -{ - ahd_mode_state mode_ptr; - ahd_mode src; - ahd_mode dst; - - mode_ptr = ahd_inb(ahd, MODE_PTR); -#ifdef AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MODEPTR) != 0) - printf("Reading mode 0x%x\n", mode_ptr); -#endif - ahd_extract_mode_state(ahd, mode_ptr, &src, &dst); - ahd_known_modes(ahd, src, dst); -} - -static __inline void -ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode, - ahd_mode dstmode, const char *file, int line) -{ -#ifdef AHD_DEBUG - if ((srcmode & AHD_MK_MSK(ahd->src_mode)) == 0 - || (dstmode & AHD_MK_MSK(ahd->dst_mode)) == 0) { - panic("%s:%s:%d: Mode assertion failed.\n", - ahd_name(ahd), file, line); - } -#endif -} - -static __inline ahd_mode_state -ahd_save_modes(struct ahd_softc *ahd) -{ - if (ahd->src_mode == AHD_MODE_UNKNOWN - || ahd->dst_mode == AHD_MODE_UNKNOWN) - ahd_update_modes(ahd); - - return (ahd_build_mode_state(ahd, ahd->src_mode, ahd->dst_mode)); -} - -static __inline void -ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state) -{ - ahd_mode src; - ahd_mode dst; - - ahd_extract_mode_state(ahd, state, &src, &dst); - ahd_set_modes(ahd, src, dst); -} - -#define AHD_ASSERT_MODES(ahd, source, dest) \ - ahd_assert_modes(ahd, source, dest, __FILE__, __LINE__); - -/* - * Determine whether the sequencer has halted code execution. - * Returns non-zero status if the sequencer is stopped. - */ -static __inline int -ahd_is_paused(struct ahd_softc *ahd) -{ - return ((ahd_inb(ahd, HCNTRL) & PAUSE) != 0); -} - -/* - * Request that the sequencer stop and wait, indefinitely, for it - * to stop. The sequencer will only acknowledge that it is paused - * once it has reached an instruction boundary and PAUSEDIS is - * cleared in the SEQCTL register. The sequencer may use PAUSEDIS - * for critical sections. - */ -static __inline void -ahd_pause(struct ahd_softc *ahd) -{ - ahd_outb(ahd, HCNTRL, ahd->pause); - - /* - * Since the sequencer can disable pausing in a critical section, we - * must loop until it actually stops. - */ - while (ahd_is_paused(ahd) == 0) - ; -} - -/* - * Allow the sequencer to continue program execution. - * We check here to ensure that no additional interrupt - * sources that would cause the sequencer to halt have been - * asserted. If, for example, a SCSI bus reset is detected - * while we are fielding a different, pausing, interrupt type, - * we don't want to release the sequencer before going back - * into our interrupt handler and dealing with this new - * condition. - */ -static __inline void -ahd_unpause(struct ahd_softc *ahd) -{ - /* - * Automatically restore our modes to those saved - * prior to the first change of the mode. - */ - if (ahd->saved_src_mode != AHD_MODE_UNKNOWN - && ahd->saved_dst_mode != AHD_MODE_UNKNOWN) - ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode); - - if ((ahd_inb(ahd, INTSTAT) & ~(SWTMINT | CMDCMPLT)) == 0) - ahd_outb(ahd, HCNTRL, ahd->unpause); - - ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN); -} - -/*********************** Untagged Transaction Routines ************************/ -static __inline void ahd_freeze_untagged_queues(struct ahd_softc *ahd); -static __inline void ahd_release_untagged_queues(struct ahd_softc *ahd); - -/* - * Block our completion routine from starting the next untagged - * transaction for this target or target lun. - */ -static __inline void -ahd_freeze_untagged_queues(struct ahd_softc *ahd) -{ - /* - * Assume we have enough space in the card's SCB - * to obviate the need for a per target untagged - * transaction limit. - */ -#if 0 - ahd->untagged_queue_lock++; -#endif -} - -/* - * Allow the next untagged transaction for this target or target lun - * to be executed. We use a counting semaphore to allow the lock - * to be acquired recursively. Once the count drops to zero, the - * transaction queues will be run. - */ -static __inline void -ahd_release_untagged_queues(struct ahd_softc *ahd) -{ - /* - * Assume we have enough space in the card's SCB - * to obviate the need for a per target untagged - * transaction limit. - */ -#if 0 - ahd->untagged_queue_lock--; - if (ahd->untagged_queue_lock == 0) - ahd_run_untagged_queues(ahd); -#endif -} - -/*********************** Scatter Gather List Handling *************************/ -static __inline void *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb, - void *sgptr, bus_addr_t addr, - bus_size_t len, int last); -static __inline void ahd_setup_scb_common(struct ahd_softc *ahd, - struct scb *scb); -static __inline void ahd_setup_data_scb(struct ahd_softc *ahd, - struct scb *scb); -static __inline void ahd_setup_noxfer_scb(struct ahd_softc *ahd, - struct scb *scb); - -static __inline void * -ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb, - void *sgptr, bus_addr_t addr, bus_size_t len, int last) -{ - scb->sg_count++; - if (sizeof(bus_addr_t) > 4 - && (ahd->flags & AHD_64BIT_ADDRESSING) != 0) { - struct ahd_dma64_seg *sg; - - sg = (struct ahd_dma64_seg *)sgptr; - sg->addr = ahd_htole64(addr); - sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0)); - return (sg + 1); - } else { - struct ahd_dma_seg *sg; - - sg = (struct ahd_dma_seg *)sgptr; - sg->addr = ahd_htole64(addr); - sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000) - | (last ? AHD_DMA_LAST_SEG : 0)); - return (sg + 1); - } -} - -static __inline void -ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb) -{ - /* XXX Handle target mode SCBs. */ - if ((scb->flags & SCB_PACKETIZED) != 0) { - /* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */ - scb->hscb->task_attribute_nonpkt_tag = - scb->hscb->control & SCB_TAG_TYPE; - scb->hscb->task_management = 0; - } else { - scb->hscb->task_attribute_nonpkt_tag = SCB_GET_TAG(scb); - } - - if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR - || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0) - scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr = - ahd_htole32(scb->sense_busaddr); -} - -static __inline void -ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb) -{ - /* - * Copy the first SG into the "current" data ponter area. - */ - if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { - struct ahd_dma64_seg *sg; - - sg = (struct ahd_dma64_seg *)scb->sg_list; - scb->hscb->dataptr = sg->addr; - scb->hscb->datacnt = sg->len; - } else { - struct ahd_dma_seg *sg; - - sg = (struct ahd_dma_seg *)scb->sg_list; - scb->hscb->dataptr = sg->addr; - if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) { - uint64_t high_addr; - - high_addr = ahd_le32toh(sg->len) & 0x7F000000; - scb->hscb->dataptr |= ahd_htole64(high_addr << 8); - } - scb->hscb->datacnt = sg->len; - } - /* - * Note where to find the SG entries in bus space. - * We also set the full residual flag which the - * sequencer will clear as soon as a data transfer - * occurs. - */ - scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID); -} - -static __inline void -ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb) -{ - scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL); - scb->hscb->dataptr = 0; - scb->hscb->datacnt = 0; -} - -/************************** Memory mapping routines ***************************/ -static __inline size_t ahd_sg_size(struct ahd_softc *ahd); -static __inline void * - ahd_sg_bus_to_virt(struct ahd_softc *ahd, - struct scb *scb, - uint32_t sg_busaddr); -static __inline uint32_t - ahd_sg_virt_to_bus(struct ahd_softc *ahd, - struct scb *scb, - void *sg); -static __inline void ahd_sync_scb(struct ahd_softc *ahd, - struct scb *scb, int op); -static __inline void ahd_sync_sglist(struct ahd_softc *ahd, - struct scb *scb, int op); -static __inline void ahd_sync_sense(struct ahd_softc *ahd, - struct scb *scb, int op); -static __inline uint32_t - ahd_targetcmd_offset(struct ahd_softc *ahd, - u_int index); - -static __inline size_t -ahd_sg_size(struct ahd_softc *ahd) -{ - if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) - return (sizeof(struct ahd_dma64_seg)); - return (sizeof(struct ahd_dma_seg)); -} - -static __inline void * -ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr) -{ - bus_addr_t sg_offset; - - /* sg_list_phys points to entry 1, not 0 */ - sg_offset = sg_busaddr - (scb->sg_list_busaddr - ahd_sg_size(ahd)); - return ((uint8_t *)scb->sg_list + sg_offset); -} - -static __inline uint32_t -ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg) -{ - bus_addr_t sg_offset; - - /* sg_list_phys points to entry 1, not 0 */ - sg_offset = ((uint8_t *)sg - (uint8_t *)scb->sg_list) - - ahd_sg_size(ahd); - - return (scb->sg_list_busaddr + sg_offset); -} - -static __inline void -ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op) -{ - ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat, - scb->hscb_map->dmamap, - /*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr, - /*len*/sizeof(*scb->hscb), op); -} - -static __inline void -ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op) -{ - if (scb->sg_count == 0) - return; - - ahd_dmamap_sync(ahd, ahd->scb_data.sg_dmat, - scb->sg_map->dmamap, - /*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd), - /*len*/ahd_sg_size(ahd) * scb->sg_count, op); -} - -static __inline void -ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op) -{ - ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat, - scb->sense_map->dmamap, - /*offset*/scb->sense_busaddr, - /*len*/AHD_SENSE_BUFSIZE, op); -} - -static __inline uint32_t -ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index) -{ - return (((uint8_t *)&ahd->targetcmds[index]) - - (uint8_t *)ahd->qoutfifo); -} - -/*********************** Miscelaneous Support Functions ***********************/ -static __inline void ahd_complete_scb(struct ahd_softc *ahd, - struct scb *scb); -static __inline void ahd_update_residual(struct ahd_softc *ahd, - struct scb *scb); -static __inline struct ahd_initiator_tinfo * - ahd_fetch_transinfo(struct ahd_softc *ahd, - char channel, u_int our_id, - u_int remote_id, - struct ahd_tmode_tstate **tstate); -static __inline struct scb* - ahd_get_scb(struct ahd_softc *ahd); -static __inline void ahd_free_scb(struct ahd_softc *ahd, struct scb *scb); -static __inline uint16_t - ahd_inw(struct ahd_softc *ahd, u_int port); -static __inline void ahd_outw(struct ahd_softc *ahd, u_int port, - u_int value); -static __inline uint32_t - ahd_inl(struct ahd_softc *ahd, u_int port); -static __inline void ahd_outl(struct ahd_softc *ahd, u_int port, - uint32_t value); -static __inline uint64_t - ahd_inq(struct ahd_softc *ahd, u_int port); -static __inline void ahd_outq(struct ahd_softc *ahd, u_int port, - uint64_t value); -static __inline u_int ahd_get_scbptr(struct ahd_softc *ahd); -static __inline void ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr); -static __inline u_int ahd_get_hnscb_qoff(struct ahd_softc *ahd); -static __inline void ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value); -static __inline u_int ahd_get_hescb_qoff(struct ahd_softc *ahd); -static __inline void ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value); -static __inline u_int ahd_get_snscb_qoff(struct ahd_softc *ahd); -static __inline void ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value); -static __inline u_int ahd_get_sescb_qoff(struct ahd_softc *ahd); -static __inline void ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value); -static __inline u_int ahd_get_sdscb_qoff(struct ahd_softc *ahd); -static __inline void ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value); -static __inline u_int ahd_inb_scbram(struct ahd_softc *ahd, u_int offset); -static __inline u_int ahd_inw_scbram(struct ahd_softc *ahd, u_int offset); -static __inline uint32_t - ahd_inl_scbram(struct ahd_softc *ahd, u_int offset); -static __inline void ahd_swap_with_next_hscb(struct ahd_softc *ahd, - struct scb *scb); -static __inline void ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb); -static __inline uint8_t * - ahd_get_sense_buf(struct ahd_softc *ahd, - struct scb *scb); -static __inline uint32_t - ahd_get_sense_bufaddr(struct ahd_softc *ahd, - struct scb *scb); - -static __inline void -ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb) -{ - uint32_t sgptr; - - sgptr = ahd_le32toh(scb->hscb->sgptr); - if ((sgptr & SG_STATUS_VALID) != 0) - ahd_handle_scb_status(ahd, scb); - else - ahd_done(ahd, scb); -} - -/* - * Determine whether the sequencer reported a residual - * for this SCB/transaction. - */ -static __inline void -ahd_update_residual(struct ahd_softc *ahd, struct scb *scb) -{ - uint32_t sgptr; - - sgptr = ahd_le32toh(scb->hscb->sgptr); - if ((sgptr & SG_STATUS_VALID) != 0) - ahd_calc_residual(ahd, scb); -} - -/* - * Return pointers to the transfer negotiation information - * for the specified our_id/remote_id pair. - */ -static __inline struct ahd_initiator_tinfo * -ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id, - u_int remote_id, struct ahd_tmode_tstate **tstate) -{ - /* - * Transfer data structures are stored from the perspective - * of the target role. Since the parameters for a connection - * in the initiator role to a given target are the same as - * when the roles are reversed, we pretend we are the target. - */ - if (channel == 'B') - our_id += 8; - *tstate = ahd->enabled_targets[our_id]; - return (&(*tstate)->transinfo[remote_id]); -} - -/* - * Get a free scb. If there are none, see if we can allocate a new SCB. - */ -static __inline struct scb * -ahd_get_scb(struct ahd_softc *ahd) -{ - struct scb *scb; - - if ((scb = SLIST_FIRST(&ahd->scb_data.free_scbs)) == NULL) { - ahd_alloc_scbs(ahd); - scb = SLIST_FIRST(&ahd->scb_data.free_scbs); - if (scb == NULL) - return (NULL); - } - SLIST_REMOVE_HEAD(&ahd->scb_data.free_scbs, links.sle); - return (scb); -} - -/* - * Return an SCB resource to the free list. - */ -static __inline void -ahd_free_scb(struct ahd_softc *ahd, struct scb *scb) -{ - - /* Clean up for the next user */ - ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = NULL; - scb->flags = SCB_FREE; - scb->hscb->control = 0; - - SLIST_INSERT_HEAD(&ahd->scb_data.free_scbs, scb, links.sle); - - /* Notify the OSM that a resource is now available. */ - ahd_platform_scb_free(ahd, scb); -} - -static __inline uint16_t -ahd_inw(struct ahd_softc *ahd, u_int port) -{ - return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port)); -} - -static __inline void -ahd_outw(struct ahd_softc *ahd, u_int port, u_int value) -{ - ahd_outb(ahd, port, value & 0xFF); - ahd_outb(ahd, port+1, (value >> 8) & 0xFF); -} - -static __inline uint32_t -ahd_inl(struct ahd_softc *ahd, u_int port) -{ - return ((ahd_inb(ahd, port)) - | (ahd_inb(ahd, port+1) << 8) - | (ahd_inb(ahd, port+2) << 16) - | (ahd_inb(ahd, port+3) << 24)); -} - -static __inline void -ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value) -{ - ahd_outb(ahd, port, (value) & 0xFF); - ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF); - ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF); - ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF); -} - -static __inline uint64_t -ahd_inq(struct ahd_softc *ahd, u_int port) -{ - return ((ahd_inb(ahd, port)) - | (ahd_inb(ahd, port+1) << 8) - | (ahd_inb(ahd, port+2) << 16) - | (ahd_inb(ahd, port+3) << 24) - | (((uint64_t)ahd_inb(ahd, port+4)) << 32) - | (((uint64_t)ahd_inb(ahd, port+5)) << 40) - | (((uint64_t)ahd_inb(ahd, port+6)) << 48) - | (((uint64_t)ahd_inb(ahd, port+7)) << 56)); -} - -static __inline void -ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value) -{ - ahd_outb(ahd, port, value & 0xFF); - ahd_outb(ahd, port+1, (value >> 8) & 0xFF); - ahd_outb(ahd, port+2, (value >> 16) & 0xFF); - ahd_outb(ahd, port+3, (value >> 24) & 0xFF); - ahd_outb(ahd, port+4, (value >> 32) & 0xFF); - ahd_outb(ahd, port+5, (value >> 40) & 0xFF); - ahd_outb(ahd, port+6, (value >> 48) & 0xFF); - ahd_outb(ahd, port+7, (value >> 56) & 0xFF); -} - -static __inline u_int -ahd_get_scbptr(struct ahd_softc *ahd) -{ - AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK), - ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK)); - return (ahd_inb(ahd, SCBPTR) | (ahd_inb(ahd, SCBPTR + 1) << 8)); -} - -static __inline void -ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr) -{ - AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK), - ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK)); - ahd_outb(ahd, SCBPTR, scbptr & 0xFF); - ahd_outb(ahd, SCBPTR+1, (scbptr >> 8) & 0xFF); -} - -static __inline u_int -ahd_get_hnscb_qoff(struct ahd_softc *ahd) -{ - return (ahd_inw_atomic(ahd, HNSCB_QOFF)); -} - -static __inline void -ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value) -{ - ahd_outw_atomic(ahd, HNSCB_QOFF, value); -} - -static __inline u_int -ahd_get_hescb_qoff(struct ahd_softc *ahd) -{ - return (ahd_inb(ahd, HESCB_QOFF)); -} - -static __inline void -ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value) -{ - ahd_outb(ahd, HESCB_QOFF, value); -} - -static __inline u_int -ahd_get_snscb_qoff(struct ahd_softc *ahd) -{ - u_int oldvalue; - - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); - oldvalue = ahd_inw(ahd, SNSCB_QOFF); - ahd_outw(ahd, SNSCB_QOFF, oldvalue); - return (oldvalue); -} - -static __inline void -ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value) -{ - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); - ahd_outw(ahd, SNSCB_QOFF, value); -} - -static __inline u_int -ahd_get_sescb_qoff(struct ahd_softc *ahd) -{ - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); - return (ahd_inb(ahd, SESCB_QOFF)); -} - -static __inline void -ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value) -{ - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); - ahd_outb(ahd, SESCB_QOFF, value); -} - -static __inline u_int -ahd_get_sdscb_qoff(struct ahd_softc *ahd) -{ - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); - return (ahd_inb(ahd, SDSCB_QOFF) | (ahd_inb(ahd, SDSCB_QOFF + 1) << 8)); -} - -static __inline void -ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value) -{ - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); - ahd_outb(ahd, SDSCB_QOFF, value & 0xFF); - ahd_outb(ahd, SDSCB_QOFF+1, (value >> 8) & 0xFF); -} - -static __inline u_int -ahd_inb_scbram(struct ahd_softc *ahd, u_int offset) -{ - u_int value; - - /* - * Workaround PCI-X Rev A. hardware bug. - * After a host read of SCB memory, the chip - * may become confused into thinking prefetch - * was required. This starts the discard timer - * running and can cause an unexpected discard - * timer interrupt. The work around is to read - * a normal register prior to the exhaustion of - * the discard timer. The mode pointer register - * has no side effects and so serves well for - * this purpose. - * - * Razor #528 - */ - value = ahd_inb(ahd, offset); - ahd_inb(ahd, MODE_PTR); - return (value); -} - -static __inline u_int -ahd_inw_scbram(struct ahd_softc *ahd, u_int offset) -{ - return (ahd_inb_scbram(ahd, offset) - | (ahd_inb_scbram(ahd, offset+1) << 8)); -} - -static __inline uint32_t -ahd_inl_scbram(struct ahd_softc *ahd, u_int offset) -{ - return (ahd_inb_scbram(ahd, offset) - | (ahd_inb_scbram(ahd, offset+1) << 8) - | (ahd_inb_scbram(ahd, offset+2) << 16) - | (ahd_inb_scbram(ahd, offset+3) << 24)); -} - -static __inline struct scb * -ahd_lookup_scb(struct ahd_softc *ahd, u_int tag) -{ - struct scb* scb; - - if (tag >= AHD_SCB_MAX) - return (NULL); - scb = ahd->scb_data.scbindex[tag]; - if (scb != NULL) - ahd_sync_scb(ahd, scb, - BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); - return (scb); -} - -static __inline void -ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) -{ - struct hardware_scb *q_hscb; - uint32_t saved_hscb_busaddr; - - /* - * Our queuing method is a bit tricky. The card - * knows in advance which HSCB (by address) to download, - * and we can't disappoint it. To achieve this, the next - * SCB to download is saved off in ahd->next_queued_scb. - * When we are called to queue "an arbitrary scb", - * we copy the contents of the incoming HSCB to the one - * the sequencer knows about, swap HSCB pointers and - * finally assign the SCB to the tag indexed location - * in the scb_array. This makes sure that we can still - * locate the correct SCB by SCB_TAG. - */ - q_hscb = ahd->next_queued_scb->hscb; - saved_hscb_busaddr = q_hscb->hscb_busaddr; - memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); - q_hscb->hscb_busaddr = saved_hscb_busaddr; - q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr; - - /* Now swap HSCB pointers. */ - ahd->next_queued_scb->hscb = scb->hscb; - scb->hscb = q_hscb; - - /* Now define the mapping from tag to SCB in the scbindex */ -/* XXX This should be constant now. Can we avoid the mapping? */ - ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb; -} - -/* - * Tell the sequencer about a new transaction to execute. - */ -static __inline void -ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb) -{ - ahd_swap_with_next_hscb(ahd, scb); - - if (SCBID_IS_NULL(SCB_GET_TAG(scb))) - panic("Attempt to queue invalid SCB tag %x\n", - SCB_GET_TAG(scb)); - - /* - * Keep a history of SCBs we've downloaded in the qinfifo. - */ - ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb); - ahd->qinfifonext++; - - if (scb->sg_count != 0) - ahd_setup_data_scb(ahd, scb); - else - ahd_setup_noxfer_scb(ahd, scb); - ahd_setup_scb_common(ahd, scb); - - /* - * Make sure our data is consistant from the - * perspective of the adapter. - */ - ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); - -#ifdef AHD_DEBUG - if ((ahd_debug & AHD_SHOW_QUEUE) != 0) { - printf("%s: Queueing SCB 0x%x bus addr 0x%x - 0x%x%x/0x%x\n", - ahd_name(ahd), - SCB_GET_TAG(scb), scb->hscb->hscb_busaddr, - (u_int)((scb->hscb->dataptr >> 32) & 0xFFFFFFFF), - (u_int)(scb->hscb->dataptr & 0xFFFFFFFF), - scb->hscb->datacnt); - } -#endif - /* Tell the adapter about the newly queued SCB */ - ahd_set_hnscb_qoff(ahd, ahd->qinfifonext); -} - -static __inline uint8_t * -ahd_get_sense_buf(struct ahd_softc *ahd, struct scb *scb) -{ - return (scb->sense_data); -} - -static __inline uint32_t -ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb) -{ - return (scb->sense_busaddr); -} - -/************************** Interrupt Processing ******************************/ -static __inline void ahd_sync_qoutfifo(struct ahd_softc *ahd, int op); -static __inline void ahd_sync_tqinfifo(struct ahd_softc *ahd, int op); -static __inline u_int ahd_check_cmdcmpltqueues(struct ahd_softc *ahd); -static __inline void ahd_intr(struct ahd_softc *ahd); - -static __inline void -ahd_sync_qoutfifo(struct ahd_softc *ahd, int op) -{ - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, - /*offset*/0, /*len*/AHC_SCB_MAX * sizeof(uint16_t), op); -} - -static __inline void -ahd_sync_tqinfifo(struct ahd_softc *ahd, int op) -{ -#ifdef AHD_TARGET_MODE - if ((ahd->flags & AHD_TARGETROLE) != 0) { - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap, - ahd_targetcmd_offset(ahd, 0), - sizeof(struct target_cmd) * AHD_TMODE_CMDS, - op); - } -#endif -} - -/* - * See if the firmware has posted any completed commands - * into our in-core command complete fifos. - */ -#define AHD_RUN_QOUTFIFO 0x1 -#define AHD_RUN_TQINFIFO 0x2 -static __inline u_int -ahd_check_cmdcmpltqueues(struct ahd_softc *ahd) -{ - u_int retval; - - retval = 0; - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, - /*offset*/ahd->qoutfifonext, /*len*/2, - BUS_DMASYNC_POSTREAD); - if (ahd->qoutfifo[ahd->qoutfifonext] != SCB_LIST_NULL_LE) - retval |= AHD_RUN_QOUTFIFO; -#ifdef AHD_TARGET_MODE - if ((ahd->flags & AHD_TARGETROLE) != 0 - && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) { - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap, - ahd_targetcmd_offset(ahd, ahd->tqinfifofnext), - /*len*/sizeof(struct target_cmd), - BUS_DMASYNC_POSTREAD); - if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0) - retval |= AHD_RUN_TQINFIFO; - } -#endif - return (retval); -} - -/* - * Catch an interrupt from the adapter - */ -static __inline void -ahd_intr(struct ahd_softc *ahd) -{ - u_int intstat; - - /* - * Instead of directly reading the interrupt status register, - * infer the cause of the interrupt by checking our in-core - * completion queues. This avoids a costly PCI bus read in - * most cases. - */ - if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0 - && (ahd_check_cmdcmpltqueues(ahd) != 0)) - intstat = CMDCMPLT; - else - intstat = ahd_inb(ahd, INTSTAT); - - if (intstat & CMDCMPLT) { - ahd_outb(ahd, CLRINT, CLRCMDINT); - - /* - * Ensure that the chip sees that we've cleared - * this interrupt before we walk the output fifo. - * Otherwise, we may, due to posted bus writes, - * clear the interrupt after we finish the scan, - * and after the sequencer has added new entries - * and asserted the interrupt again. - */ - ahd_flush_device_writes(ahd); - ahd_run_qoutfifo(ahd); -#ifdef AHD_TARGET_MODE - if ((ahd->flags & AHD_TARGETROLE) != 0) - ahd_run_tqinfifo(ahd, /*paused*/FALSE); -#endif - } - - if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) - /* Hot eject */ - return; - - if ((intstat & INT_PEND) == 0) - return; - - if (intstat & HWERRINT) { - ahd_handle_hwerrint(ahd); - return; - } - - if ((intstat & (PCIINT|SPLTINT)) != 0) { - ahd->bus_intr(ahd); - return; - } - - if ((intstat & SEQINT) != 0) - ahd_handle_seqint(ahd, intstat); - - if ((intstat & SCSIINT) != 0) - ahd_handle_scsiint(ahd, intstat); -} - -#endif /* _AIC79XX_INLINE_H_ */ diff --git a/xen/drivers/scsi/aic7xxx/aic79xx_osm.c b/xen/drivers/scsi/aic7xxx/aic79xx_osm.c deleted file mode 100644 index 85f3f76828..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic79xx_osm.c +++ /dev/null @@ -1,2968 +0,0 @@ -/* - * Adaptec AIC79xx device driver for Linux. - * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#36 $ - * - * -------------------------------------------------------------------------- - * Copyright (c) 1994-2000 Justin T. Gibbs. - * Copyright (c) 1997-1999 Doug Ledford - * Copyright (c) 2000-2002 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -/* - * This is the only file where module.h should - * embed module global version info. - */ -#define AHD_MODVERSION_FILE - -#include "aic79xx_osm.h" -#include "aic79xx_inline.h" - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) -#include /* __setup */ -#endif - -#include "../sd.h" /* For geometry detection */ - -#include /* For fetching system memory size */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) -/* - * Lock protecting manipulation of the ahd softc list. - */ -spinlock_t ahd_list_spinlock; -#endif - -/* SAE: */ -/* -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -struct proc_dir_entry proc_scsi_aic79xx = { - PROC_SCSI_AIC79XX, 7, "aic79xx", - S_IFDIR | S_IRUGO | S_IXUGO, 2, - 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; -#endif -*/ - -/* - * Set this to the delay in seconds after SCSI bus reset. - * Note, we honor this only for the initial bus reset. - * The scsi error recovery code performs its own bus settle - * delay handling for error recovery actions. - */ -#ifdef CONFIG_AIC79XX_RESET_DELAY_MS -#define AIC79XX_RESET_DELAY CONFIG_AIC79XX_RESET_DELAY_MS -#else -#define AIC79XX_RESET_DELAY 500 -#endif - -/* - * To change the default number of tagged transactions allowed per-device, - * add a line to the lilo.conf file like: - * append="aic79xx=verbose,tag_info:{{32,32,32,32},{32,32,32,32}}" - * which will result in the first four devices on the first two - * controllers being set to a tagged queue depth of 32. - * - * The tag_commands is an array of 16 to allow for wide and twin adapters. - * Twin adapters will use indexes 0-7 for channel 0, and indexes 8-15 - * for channel 1. - */ -typedef struct { - uint16_t tag_commands[16]; /* Allow for wide/twin adapters. */ -} adapter_tag_info_t; - -/* - * Modify this as you see fit for your system. - * - * 0 tagged queuing disabled - * 1 <= n <= 253 n == max tags ever dispatched. - * - * The driver will throttle the number of commands dispatched to a - * device if it returns queue full. For devices with a fixed maximum - * queue depth, the driver will eventually determine this depth and - * lock it in (a console message is printed to indicate that a lock - * has occurred). On some devices, queue full is returned for a temporary - * resource shortage. These devices will return queue full at varying - * depths. The driver will throttle back when the queue fulls occur and - * attempt to slowly increase the depth over time as the device recovers - * from the resource shortage. - * - * In this example, the first line will disable tagged queueing for all - * the devices on the first probed aic79xx adapter. - * - * The second line enables tagged queueing with 4 commands/LUN for IDs - * (0, 2-11, 13-15), disables tagged queueing for ID 12, and tells the - * driver to attempt to use up to 64 tags for ID 1. - * - * The third line is the same as the first line. - * - * The fourth line disables tagged queueing for devices 0 and 3. It - * enables tagged queueing for the other IDs, with 16 commands/LUN - * for IDs 1 and 4, 127 commands/LUN for ID 8, and 4 commands/LUN for - * IDs 2, 5-7, and 9-15. - */ - -/* - * NOTE: The below structure is for reference only, the actual structure - * to modify in order to change things is just below this comment block. -adapter_tag_info_t aic79xx_tag_info[] = -{ - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{4, 64, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4}}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0, 16, 4, 0, 16, 4, 4, 4, 127, 4, 4, 4, 4, 4, 4, 4}} -}; -*/ - -#ifdef CONFIG_AIC79XX_CMDS_PER_DEVICE -#define AIC79XX_CMDS_PER_DEVICE CONFIG_AIC79XX_CMDS_PER_DEVICE -#else -#define AIC79XX_CMDS_PER_DEVICE AHD_MAX_QUEUE -#endif - -#define AIC79XX_CONFIGED_TAG_COMMANDS { \ - AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \ - AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \ - AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \ - AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \ - AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \ - AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \ - AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \ - AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE \ -} - -/* - * By default, use the number of commands specified by - * the users kernel configuration. - */ -static adapter_tag_info_t aic79xx_tag_info[] = -{ - {AIC79XX_CONFIGED_TAG_COMMANDS}, - {AIC79XX_CONFIGED_TAG_COMMANDS}, - {AIC79XX_CONFIGED_TAG_COMMANDS}, - {AIC79XX_CONFIGED_TAG_COMMANDS}, - {AIC79XX_CONFIGED_TAG_COMMANDS}, - {AIC79XX_CONFIGED_TAG_COMMANDS}, - {AIC79XX_CONFIGED_TAG_COMMANDS}, - {AIC79XX_CONFIGED_TAG_COMMANDS}, - {AIC79XX_CONFIGED_TAG_COMMANDS}, - {AIC79XX_CONFIGED_TAG_COMMANDS}, - {AIC79XX_CONFIGED_TAG_COMMANDS}, - {AIC79XX_CONFIGED_TAG_COMMANDS}, - {AIC79XX_CONFIGED_TAG_COMMANDS}, - {AIC79XX_CONFIGED_TAG_COMMANDS}, - {AIC79XX_CONFIGED_TAG_COMMANDS}, - {AIC79XX_CONFIGED_TAG_COMMANDS} -}; - -/* - * By default, read streaming is disabled. In theory, - * read streaming should enhance performance, but early - * U320 drive firmware actually performs slower with - * read streaming enabled. - */ -#ifdef CONFIG_AIC79XX_ENABLE_RD_STRM -#define AIC79XX_CONFIGED_RD_STRM 0xFFFF -#else -#define AIC79XX_CONFIGED_RD_STRM 0 -#endif - -static uint16_t aic79xx_rd_strm_info[] = -{ - AIC79XX_CONFIGED_RD_STRM, - AIC79XX_CONFIGED_RD_STRM, - AIC79XX_CONFIGED_RD_STRM, - AIC79XX_CONFIGED_RD_STRM, - AIC79XX_CONFIGED_RD_STRM, - AIC79XX_CONFIGED_RD_STRM, - AIC79XX_CONFIGED_RD_STRM, - AIC79XX_CONFIGED_RD_STRM, - AIC79XX_CONFIGED_RD_STRM, - AIC79XX_CONFIGED_RD_STRM, - AIC79XX_CONFIGED_RD_STRM, - AIC79XX_CONFIGED_RD_STRM, - AIC79XX_CONFIGED_RD_STRM, - AIC79XX_CONFIGED_RD_STRM, - AIC79XX_CONFIGED_RD_STRM, - AIC79XX_CONFIGED_RD_STRM -}; - -/* - * There should be a specific return value for this in scsi.h, but - * it seems that most drivers ignore it. - */ -#define DID_UNDERFLOW DID_ERROR - -void -ahd_print_path(struct ahd_softc *ahd, struct scb *scb) -{ -/* SAE: */ - printf("(scsi%d:%c:%d:%d): ", - ahd->platform_data->host->host_no, - scb != NULL ? SCB_GET_CHANNEL(ahd, scb) : 'X', - scb != NULL ? SCB_GET_TARGET(ahd, scb) : -1, - scb != NULL ? SCB_GET_LUN(scb) : -1); - -} - -/* - * XXX - these options apply unilaterally to _all_ adapters - * cards in the system. This should be fixed. Exceptions to this - * rule are noted in the comments. - */ - -/* - * Skip the scsi bus reset. Non 0 make us skip the reset at startup. This - * has no effect on any later resets that might occur due to things like - * SCSI bus timeouts. - */ -static uint32_t aic79xx_no_reset; - -/* - * Certain PCI motherboards will scan PCI devices from highest to lowest, - * others scan from lowest to highest, and they tend to do all kinds of - * strange things when they come into contact with PCI bridge chips. The - * net result of all this is that the PCI card that is actually used to boot - * the machine is very hard to detect. Most motherboards go from lowest - * PCI slot number to highest, and the first SCSI controller found is the - * one you boot from. The only exceptions to this are when a controller - * has its BIOS disabled. So, we by default sort all of our SCSI controllers - * from lowest PCI slot number to highest PCI slot number. We also force - * all controllers with their BIOS disabled to the end of the list. This - * works on *almost* all computers. Where it doesn't work, we have this - * option. Setting this option to non-0 will reverse the order of the sort - * to highest first, then lowest, but will still leave cards with their BIOS - * disabled at the very end. That should fix everyone up unless there are - * really strange cirumstances. - */ -static int aic79xx_reverse_scan = 0; - -/* - * Should we force EXTENDED translation on a controller. - * 0 == Use whatever is in the SEEPROM or default to off - * 1 == Use whatever is in the SEEPROM or default to on - */ -static uint32_t aic79xx_extended = 0; - -/* - * PCI bus parity checking of the Adaptec controllers. This is somewhat - * dubious at best. To my knowledge, this option has never actually - * solved a PCI parity problem, but on certain machines with broken PCI - * chipset configurations, it can generate tons of false error messages. - * It's included in the driver for completeness. - * 0 = Shut off PCI parity check - * -1 = Normal polarity pci parity checking - * 1 = reverse polarity pci parity checking - * - * NOTE: you can't actually pass -1 on the lilo prompt. So, to set this - * variable to -1 you would actually want to simply pass the variable - * name without a number. That will invert the 0 which will result in - * -1. - */ -static int aic79xx_pci_parity = 0; - -/* - * aic79xx_detect() has been run, so register all device arrivals - * immediately with the system rather than deferring to the sorted - * attachment performed by aic79xx_detect(). - */ -int aic79xx_detect_complete; - -/* - * So that we can set how long each device is given as a selection timeout. - * The table of values goes like this: - * 0 - 256ms - * 1 - 128ms - * 2 - 64ms - * 3 - 32ms - * We default to 256ms because some older devices need a longer time - * to respond to initial selection. - */ -static int aic79xx_seltime = 0x00; - -/* - * Certain devices do not perform any aging on commands. Should the - * device be saturated by commands in one portion of the disk, it is - * possible for transactions on far away sectors to never be serviced. - * To handle these devices, we can periodically send an ordered tag to - * force all outstanding transactions to be serviced prior to a new - * transaction. - */ -int aic79xx_periodic_otag; - -/* - * Module information and settable options. - */ -#ifdef MODULE -static char *aic79xx = NULL; -/* - * Just in case someone uses commas to separate items on the insmod - * command line, we define a dummy buffer here to avoid having insmod - * write wild stuff into our code segment - */ -static char dummy_buffer[60] = "Please don't trounce on me insmod!!\n"; - -MODULE_AUTHOR("Maintainer: Justin T. Gibbs "); -MODULE_DESCRIPTION("Adaptec Aic77XX/78XX SCSI Host Bus Adapter driver"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10) -MODULE_LICENSE("Dual BSD/GPL"); -#endif -MODULE_PARM(aic79xx, "s"); -MODULE_PARM_DESC(aic79xx, "period delimited, options string.\n" - "verbose Enable verbose/diagnostic logging\n" - "debug Bitmask of debug values to enable\n" - "no_reset Supress initial bus resets\n" - "extended Enable extended geometry on all controllers\n" - "periodic_otag Send an ordered tagged transaction periodically\n" - "to prevent tag starvation. This may be\n" - "required by some older disk drives/RAID arrays. \n" - "reverse_scan Sort PCI devices highest Bus/Slot to lowest\n" - "tag_info: Set per-target tag depth\n" - "rd_strm: Set per-target read streaming setting.\n" - "seltime: Selection Timeout(0/256ms,1/128ms,2/64ms,3/32ms)\n" -"\n" - "Sample /etc/modules.conf line:\n" - "Enable verbose logging\n" - "Set tag depth on Controller 2/Target 2 to 10 tags\n" - "Shorten the selection timeout to 128ms from its default of 256\n" -"\n" - "options aic79xx='\"verbose.tag_info:{{}.{}.{..10}}.seltime:1\"'\n" -"\n" - "Sample /etc/modules.conf line:\n" - "Change Read Streaming for Controller's 2 and 3\n" -"\n" - "options aic79xx='\"rd_strm:{..0xFFF0.0xC0F0}\"'\n"); -#endif - -static void ahd_linux_handle_scsi_status(struct ahd_softc *, - struct ahd_linux_device *, - struct scb *); -static void ahd_linux_filter_command(struct ahd_softc*, Scsi_Cmnd*, - struct scb*); -static void ahd_linux_dev_timed_unfreeze(u_long arg); -/* SAE */ -#if XEN_KILLED -static void ahd_linux_sem_timeout(u_long arg); -static int ahd_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag); -#endif - -static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd); -static void ahd_linux_select_queue_depth(struct Scsi_Host *host, - Scsi_Device *scsi_devs); -static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo); -static void ahd_linux_device_queue_depth(struct ahd_softc *ahd, - Scsi_Device *device); -static struct ahd_linux_target* ahd_linux_alloc_target(struct ahd_softc*, - u_int, u_int); -static void ahd_linux_free_target(struct ahd_softc*, - struct ahd_linux_target*); -static struct ahd_linux_device* ahd_linux_alloc_device(struct ahd_softc*, - struct ahd_linux_target*, - u_int); -static void ahd_linux_free_device(struct ahd_softc*, - struct ahd_linux_device*); -static void ahd_linux_run_device_queue(struct ahd_softc*, - struct ahd_linux_device*); -static void ahd_linux_setup_tag_info(char *p, char *end); -static void ahd_linux_setup_rd_strm_info(char *p, char *end); -static int ahd_linux_next_unit(void); -static void ahd_runq_tasklet(unsigned long data); -/* SAE: .... */ -struct notifier_block; -/*static int ahd_linux_halt(struct notifier_block *nb, u_long event, void *buf);*/ - -static __inline struct ahd_linux_device* - ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, - u_int target, u_int lun, int alloc); -static __inline void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, - Scsi_Cmnd *cmd); -static __inline void ahd_linux_run_complete_queue(struct ahd_softc *ahd, - struct ahd_cmd *acmd); -static __inline void ahd_linux_check_device_queue(struct ahd_softc *ahd, - struct ahd_linux_device *dev); -static __inline struct ahd_linux_device * - ahd_linux_next_device_to_run(struct ahd_softc *ahd); -static __inline void ahd_linux_run_device_queues(struct ahd_softc *ahd); -static __inline void ahd_linux_sniff_command(struct ahd_softc*, Scsi_Cmnd*, - struct scb*); -static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*); - -static __inline int ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb, - struct ahd_dma_seg *sg, - bus_addr_t addr, bus_size_t len); - -static __inline struct ahd_linux_device* -ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, u_int target, - u_int lun, int alloc) -{ - struct ahd_linux_target *targ; - struct ahd_linux_device *dev; - u_int target_offset; - - target_offset = target; - if (channel != 0) - target_offset += 8; - targ = ahd->platform_data->targets[target_offset]; - if (targ == NULL) { - if (alloc != 0) { - targ = ahd_linux_alloc_target(ahd, channel, target); - if (targ == NULL) - return (NULL); - } else - return (NULL); - } - dev = targ->devices[lun]; - if (dev == NULL && alloc != 0) - dev = ahd_linux_alloc_device(ahd, targ, lun); - return (dev); -} - -static __inline void -ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, Scsi_Cmnd *cmd) -{ - /* - * Typically, the complete queue has very few entries - * queued to it before the queue is emptied by - * ahd_linux_run_complete_queue, so sorting the entries - * by generation number should be inexpensive. - * We perform the sort so that commands that complete - * with an error are retuned in the order origionally - * queued to the controller so that any subsequent retries - * are performed in order. The underlying ahd routines do - * not guarantee the order that aborted commands will be - * returned to us. - */ - struct ahd_completeq *completeq; - struct ahd_cmd *list_cmd; - struct ahd_cmd *acmd; - - /* - * If we want the request requeued, make sure there - * are sufficent retries. In the old scsi error code, - * we used to be able to specify a result code that - * bypassed the retry count. Now we must use this - * hack. - */ - if (cmd->result == (CAM_REQUEUE_REQ << 16)) - cmd->retries--; - completeq = &ahd->platform_data->completeq; - list_cmd = TAILQ_FIRST(completeq); - acmd = (struct ahd_cmd *)cmd; - while (list_cmd != NULL - && acmd_scsi_cmd(list_cmd).serial_number - < acmd_scsi_cmd(acmd).serial_number) - list_cmd = TAILQ_NEXT(list_cmd, acmd_links.tqe); - if (list_cmd != NULL) - TAILQ_INSERT_BEFORE(list_cmd, acmd, acmd_links.tqe); - else - TAILQ_INSERT_TAIL(completeq, acmd, acmd_links.tqe); -} - -static __inline void -ahd_linux_run_complete_queue(struct ahd_softc *ahd, struct ahd_cmd *acmd) -{ - u_long done_flags; - - ahd_done_lock(ahd, &done_flags); - while (acmd != NULL) { - Scsi_Cmnd *cmd; - - cmd = &acmd_scsi_cmd(acmd); - acmd = TAILQ_NEXT(acmd, acmd_links.tqe); - cmd->host_scribble = NULL; - cmd->scsi_done(cmd); - } - ahd_done_unlock(ahd, &done_flags); -} - -static __inline void -ahd_linux_check_device_queue(struct ahd_softc *ahd, - struct ahd_linux_device *dev) -{ - if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) != 0 - && dev->active == 0) { - dev->flags &= ~AHD_DEV_FREEZE_TIL_EMPTY; - dev->qfrozen--; - } - - if (TAILQ_FIRST(&dev->busyq) == NULL - || dev->openings == 0 || dev->qfrozen != 0) - return; - - ahd_linux_run_device_queue(ahd, dev); -} - -static __inline struct ahd_linux_device * -ahd_linux_next_device_to_run(struct ahd_softc *ahd) -{ - - if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0 - || ahd->platform_data->qfrozen != 0) - return (NULL); - return (TAILQ_FIRST(&ahd->platform_data->device_runq)); -} - -static __inline void -ahd_linux_run_device_queues(struct ahd_softc *ahd) -{ - struct ahd_linux_device *dev; - - while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) { - TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links); - dev->flags &= ~AHD_DEV_ON_RUN_LIST; - ahd_linux_check_device_queue(ahd, dev); - } -} - -static __inline void -ahd_linux_sniff_command(struct ahd_softc *ahd, Scsi_Cmnd *cmd, struct scb *scb) -{ - /* - * Determine whether we care to filter - * information out of this command. If so, - * pass it on to ahd_linux_filter_command() for more - * heavy weight processing. - */ - if (cmd->cmnd[0] == INQUIRY) - ahd_linux_filter_command(ahd, cmd, scb); -} - -static __inline void -ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) -{ - Scsi_Cmnd *cmd; - int direction; - - cmd = scb->io_ctx; - direction = scsi_to_pci_dma_dir(cmd->sc_data_direction); - ahd_sync_sglist(ahd, scb, BUS_DMASYNC_POSTWRITE); - if (cmd->use_sg != 0) { - struct scatterlist *sg; - - sg = (struct scatterlist *)cmd->request_buffer; - pci_unmap_sg(ahd->dev_softc, sg, cmd->use_sg, direction); - } else if (cmd->request_bufflen != 0) { - pci_unmap_single(ahd->dev_softc, - scb->platform_data->buf_busaddr, - cmd->request_bufflen, direction); - } -} - -static __inline int -ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb, - struct ahd_dma_seg *sg, bus_addr_t addr, bus_size_t len) -{ - int consumed; - - if ((scb->sg_count + 1) > AHD_NSEG) - panic("Too few segs for dma mapping. " - "Increase AHD_NSEG\n"); - - consumed = 1; - sg->addr = ahd_htole32(addr & 0xFFFFFFFF); - scb->platform_data->xfer_len += len; - if (sizeof(bus_addr_t) > 4 - && (ahd->flags & AHD_39BIT_ADDRESSING) != 0) { - /* - * Due to DAC restrictions, we can't - * cross a 4GB boundary. - */ - if ((addr ^ (addr + len - 1)) & ~0xFFFFFFFF) { - struct ahd_dma_seg *next_sg; - uint32_t next_len; - - printf("Crossed Seg\n"); - if ((scb->sg_count + 2) > AHD_NSEG) - panic("Too few segs for dma mapping. " - "Increase AHD_NSEG\n"); - - consumed++; - next_sg = sg + 1; - next_sg->addr = 0; - next_len = (uint32_t)((-addr) & 0xFFFFFFFF); - len -= next_len; - next_len |= ((addr >> 8) + 0x1000000) & 0x7F000000; - next_sg->len = ahd_htole32(next_len); - } - len |= (addr >> 8) & 0x7F000000; - } - sg->len = ahd_htole32(len); - return (consumed); -} - -/**************************** Tasklet Handler *********************************/ - -static void -ahd_runq_tasklet(unsigned long data) -{ - struct ahd_softc* ahd; - struct ahd_linux_device *dev; - u_long flags; - - ahd = (struct ahd_softc *)data; - ahd_lock(ahd, &flags); - while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) { - - TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links); - dev->flags &= ~AHD_DEV_ON_RUN_LIST; - ahd_linux_check_device_queue(ahd, dev); - /* Yeild to our interrupt handler */ - ahd_unlock(ahd, &flags); - ahd_lock(ahd, &flags); - } - ahd_unlock(ahd, &flags); -} - -/************************ Shutdown/halt/reboot hook ***************************/ -#include -#include -/* SAE: */ -/* -static struct notifier_block ahd_linux_notifier = { - ahd_linux_halt, NULL, 0 -}; - -static int ahd_linux_halt(struct notifier_block *nb, u_long event, void *buf) -{ - struct ahd_softc *ahd; - - if (event == SYS_DOWN || event == SYS_HALT) { - TAILQ_FOREACH(ahd, &ahd_tailq, links) { - ahd_shutdown(ahd); - } - } - return (NOTIFY_OK); -} -*/ - -/******************************** Macros **************************************/ -#define BUILD_SCSIID(ahd, cmd) \ - ((((cmd)->target << TID_SHIFT) & TID) | (ahd)->our_id) - -/******************************** Bus DMA *************************************/ -int -ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent, - bus_size_t alignment, bus_size_t boundary, - bus_addr_t lowaddr, bus_addr_t highaddr, - bus_dma_filter_t *filter, void *filterarg, - bus_size_t maxsize, int nsegments, - bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag) -{ - bus_dma_tag_t dmat; - - dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT); - if (dmat == NULL) - return (ENOMEM); - - /* - * Linux is very simplistic about DMA memory. For now don't - * maintain all specification information. Once Linux supplies - * better facilities for doing these operations, or the - * needs of this particular driver change, we might need to do - * more here. - */ - dmat->alignment = alignment; - dmat->boundary = boundary; - dmat->maxsize = maxsize; - *ret_tag = dmat; - return (0); -} - -void -ahd_dma_tag_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat) -{ - free(dmat, M_DEVBUF); -} - -int -ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr, - int flags, bus_dmamap_t *mapp) -{ - bus_dmamap_t map; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT); - if (map == NULL) - return (ENOMEM); - /* - * Although we can dma data above 4GB, our - * "consistent" memory is below 4GB for - * space efficiency reasons (only need a 4byte - * address). For this reason, we have to reset - * our dma mask when doing allocations. - */ - if (ahd->dev_softc != NULL) - ahd_pci_set_dma_mask(ahd->dev_softc, 0xFFFFFFFF); - *vaddr = pci_alloc_consistent(ahd->dev_softc, - dmat->maxsize, &map->bus_addr); - if (ahd->dev_softc != NULL) - ahd_pci_set_dma_mask(ahd->dev_softc, - ahd->platform_data->hw_dma_mask); -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) */ - /* - * At least in 2.2.14, malloc is a slab allocator so all - * allocations are aligned. We assume for these kernel versions - * that all allocations will be bellow 4Gig, physically contiguous, - * and accessable via DMA by the controller. - */ - map = NULL; /* No additional information to store */ - *vaddr = malloc(dmat->maxsize, M_DEVBUF, M_NOWAIT); -#endif - if (*vaddr == NULL) - return (ENOMEM); - *mapp = map; - return(0); -} - -void -ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat, - void* vaddr, bus_dmamap_t map) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - pci_free_consistent(ahd->dev_softc, dmat->maxsize, - vaddr, map->bus_addr); -#else - free(vaddr, M_DEVBUF); -#endif -} - -int -ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map, - void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb, - void *cb_arg, int flags) -{ - /* - * Assume for now that this will only be used during - * initialization and not for per-transaction buffer mapping. - */ - bus_dma_segment_t stack_sg; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - stack_sg.ds_addr = map->bus_addr; -#else -#define VIRT_TO_BUS(a) (uint32_t)virt_to_bus((void *)(a)) - stack_sg.ds_addr = VIRT_TO_BUS(buf); -#endif - stack_sg.ds_len = dmat->maxsize; - cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); - return (0); -} - -void -ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map) -{ - /* - * The map may is NULL in our < 2.3.X implementation. - */ - if (map != NULL) - free(map, M_DEVBUF); -} - -int -ahd_dmamap_unload(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map) -{ - /* Nothing to do */ - return (0); -} - -/********************* Platform Dependent Functions ***************************/ -int -ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd) -{ - int value; - char primary_channel; - - /* - * Under Linux, cards are ordered as follows: - * 1) PCI devices with BIOS enabled sorted by bus/slot/func. - * 2) All remaining PCI devices sorted by bus/slot/func. - */ - value = (lahd->flags & AHD_BIOS_ENABLED) - - (rahd->flags & AHD_BIOS_ENABLED); - if (value != 0) - /* Controllers with BIOS enabled have a *higher* priority */ - return (-value); - - /* Still equal. Sort by bus/slot/func. */ - if (aic79xx_reverse_scan != 0) - value = ahd_get_pci_bus(rahd->dev_softc) - - ahd_get_pci_bus(lahd->dev_softc); - else - value = ahd_get_pci_bus(lahd->dev_softc) - - ahd_get_pci_bus(rahd->dev_softc); - if (value != 0) - return (value); - if (aic79xx_reverse_scan != 0) - value = ahd_get_pci_slot(rahd->dev_softc) - - ahd_get_pci_slot(lahd->dev_softc); - else - value = ahd_get_pci_slot(lahd->dev_softc) - - ahd_get_pci_slot(rahd->dev_softc); - if (value != 0) - return (value); - - /* - * On multi-function devices, the user can choose - * to have function 1 probed before function 0. - * Give whichever channel is the primary channel - * the lowest priority. - */ - primary_channel = (lahd->flags & AHD_PRIMARY_CHANNEL) + 'A'; - value = 1; - if (lahd->channel == primary_channel) - value = -1; - return (value); -} - -static void -ahd_linux_setup_tag_info(char *p, char *end) -{ - char *base; - char *tok; - char *tok_end; - char *tok_end2; - int i; - int instance; - int targ; - int done; - char tok_list[] = {'.', ',', '{', '}', '\0'}; - - if (*p != ':') - return; - - instance = -1; - targ = -1; - done = FALSE; - base = p; - /* Forward us just past the ':' */ - tok = base + 1; - tok_end = strchr(tok, '\0'); - if (tok_end < end) - *tok_end = ','; - while (!done) { - switch (*tok) { - case '{': - if (instance == -1) - instance = 0; - else if (targ == -1) - targ = 0; - tok++; - break; - case '}': - if (targ != -1) - targ = -1; - else if (instance != -1) - instance = -1; - tok++; - break; - case ',': - case '.': - if (instance == -1) - done = TRUE; - else if (targ >= 0) - targ++; - else if (instance >= 0) - instance++; - if ((targ >= AHD_NUM_TARGETS) || - (instance >= NUM_ELEMENTS(aic79xx_tag_info))) - done = TRUE; - tok++; - if (!done) { - base = tok; - } - break; - case '\0': - done = TRUE; - break; - default: - done = TRUE; - tok_end = strchr(tok, '\0'); - for (i = 0; tok_list[i]; i++) { - tok_end2 = strchr(tok, tok_list[i]); - if ((tok_end2) && (tok_end2 < tok_end)) { - tok_end = tok_end2; - done = FALSE; - } - } - if ((instance >= 0) && (targ >= 0) - && (instance < NUM_ELEMENTS(aic79xx_tag_info)) - && (targ < AHD_NUM_TARGETS)) { - aic79xx_tag_info[instance].tag_commands[targ] = - simple_strtoul(tok, NULL, 0) & 0xff; - } - tok = tok_end; - break; - } - } - while ((p != base) && (p != NULL)) - p = strtok(NULL, ",."); -} - -static void -ahd_linux_setup_rd_strm_info(char *p, char *end) -{ - char *base; - char *tok; - char *tok_end; - char *tok_end2; - int i; - int instance; - int targ; - int done; - char tok_list[] = {'.', ',', '{', '}', '\0'}; - - if (*p != ':') - return; - - instance = -1; - targ = -1; - done = FALSE; - base = p; - /* Forward us just past the ':' */ - tok = base + 1; - tok_end = strchr(tok, '\0'); - if (tok_end < end) - *tok_end = ','; - while (!done) { - switch (*tok) { - case '{': - if (instance == -1) - instance = 0; - tok++; - break; - case '}': - if (instance != -1) - instance = -1; - tok++; - break; - case ',': - case '.': - if (instance == -1) - done = TRUE; - else if (instance >= 0) - instance++; - if (instance >= NUM_ELEMENTS(aic79xx_rd_strm_info)) - done = TRUE; - tok++; - if (!done) { - base = tok; - } - break; - case '\0': - done = TRUE; - break; - default: - done = TRUE; - tok_end = strchr(tok, '\0'); - for (i = 0; tok_list[i]; i++) { - tok_end2 = strchr(tok, tok_list[i]); - if ((tok_end2) && (tok_end2 < tok_end)) { - tok_end = tok_end2; - done = FALSE; - } - } - if ((instance >= 0) - && (instance < NUM_ELEMENTS(aic79xx_tag_info))) { - aic79xx_rd_strm_info[instance] = - simple_strtoul(tok, NULL, 0) & 0xffff; - } - tok = tok_end; - break; - } - } - while ((p != base) && (p != NULL)) - p = strtok(NULL, ",."); -} - -/* - * Handle Linux boot parameters. This routine allows for assigning a value - * to a parameter with a ':' between the parameter and the value. - * ie. aic79xx=stpwlev:1,extended - */ -int -aic79xx_setup(char *s) -{ - int i, n; - char *p; - char *end; - - static struct { - const char *name; - uint32_t *flag; - } options[] = { - { "extended", &aic79xx_extended }, - { "no_reset", &aic79xx_no_reset }, - { "verbose", &aic79xx_verbose }, -#ifdef AHD_DEBUG - { "debug", &ahd_debug }, -#endif - { "reverse_scan", &aic79xx_reverse_scan }, - { "periodic_otag", &aic79xx_periodic_otag }, - { "pci_parity", &aic79xx_pci_parity }, - { "seltime", &aic79xx_seltime }, - { "tag_info", NULL }, - { "rd_strm", NULL } - }; - - end = strchr(s, '\0'); - - for (p = strtok(s, ",."); p; p = strtok(NULL, ",.")) { - for (i = 0; i < NUM_ELEMENTS(options); i++) { - n = strlen(options[i].name); - - if (strncmp(options[i].name, p, n) != 0) - continue; - - if (strncmp(p, "tag_info", n) == 0) { - ahd_linux_setup_tag_info(p + n, end); - } else if (strncmp(p, "rd_strm", n) == 0) { - ahd_linux_setup_rd_strm_info(p + n, end); - } else if (p[n] == ':') { - *(options[i].flag) = - simple_strtoul(p + n + 1, NULL, 0); - } else if (!strncmp(p, "verbose", n)) { - *(options[i].flag) = 1; - } else { - *(options[i].flag) = ~(*(options[i].flag)); - } - break; - } - } - return 1; -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) -__setup("aic79xx=", aic79xx_setup); -#endif - -int aic79xx_verbose; - -/* - * Try to detect an Adaptec 79XX controller. - */ -int -ahd_linux_detect(Scsi_Host_Template *template) -{ - struct ahd_softc *ahd; - int found; - - /* - * It is a bug that the upper layer takes - * this lock just prior to calling us. - */ - spin_unlock_irq(&io_request_lock); - - /* - * Sanity checking of Linux SCSI data structures so - * that some of our hacks^H^H^H^H^Hassumptions aren't - * violated. - */ - if (offsetof(struct ahd_cmd_internal, end) - > offsetof(struct scsi_cmnd, host_scribble)) { - printf("ahd_linux_detect: SCSI data structures changed.\n"); - printf("ahd_linux_detect: Unable to attach\n"); - return (0); - } -#ifdef MODULE - /* - * If we've been passed any parameters, process them now. - */ - if (aic79xx) - aic79xx_setup(aic79xx); - if (dummy_buffer[0] != 'P') - printk(KERN_WARNING -"aic79xx: Please read the file /usr/src/linux/drivers/scsi/README.aic79xx\n" -"aic79xx: to see the proper way to specify options to the aic79xx module\n" -"aic79xx: Specifically, don't use any commas when passing arguments to\n" -"aic79xx: insmod or else it might trash certain memory areas.\n"); -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) - template->proc_name = "aic79xx"; -#else - template->proc_dir = &proc_scsi_aic79xx; -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) - /* - * We can only map 16MB per-SG - * so create a sector limit of - * "16MB" in 2K sectors. - */ - template->max_sectors = 8192; -#endif - - /* - * Initialize our softc list lock prior to - * probing for any adapters. - */ - ahd_list_lockinit(); - -#ifdef CONFIG_PCI - ahd_linux_pci_probe(template); -#endif - - /* - * Register with the SCSI layer all - * controllers we've found. - */ - spin_lock_irq(&io_request_lock); - found = 0; - TAILQ_FOREACH(ahd, &ahd_tailq, links) { - - if (ahd_linux_register_host(ahd, template) == 0) - found++; - } - aic79xx_detect_complete++; - return (found); -} - -int -ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template) -{ - char buf[80]; - struct Scsi_Host *host; - char *new_name; - u_long s; - - template->name = ahd->description; - host = scsi_register(template, sizeof(struct ahd_softc *)); - if (host == NULL) - return (ENOMEM); - - ahd_lock(ahd, &s); - *((struct ahd_softc **)host->hostdata) = ahd; - ahd->platform_data->host = host; - host->can_queue = AHD_MAX_QUEUE; - host->cmd_per_lun = 2; - host->sg_tablesize = AHD_NSEG; - host->select_queue_depths = ahd_linux_select_queue_depth; - host->this_id = ahd->our_id; - host->irq = ahd->platform_data->irq; - host->max_id = (ahd->features & AHD_WIDE) ? 16 : 8; - host->max_lun = AHD_NUM_LUNS; - host->max_channel = 0; - ahd_set_unit(ahd, ahd_linux_next_unit()); - sprintf(buf, "scsi%d", host->host_no); - new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); - if (new_name != NULL) { - strcpy(new_name, buf); - ahd_set_name(ahd, new_name); - } - host->unique_id = ahd->unit; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) - scsi_set_pci_device(host, ahd->dev_softc); -#endif - ahd_linux_initialize_scsi_bus(ahd); - ahd_unlock(ahd, &s); - return (0); -} - -uint64_t -ahd_linux_get_memsize() -{/* - struct sysinfo si; - - si_meminfo(&si); - return (si.totalram << PAGE_SHIFT); -*/ - printf("SAE: aic79xx_osm: get_memsize\n"); - return 0; -} - -/* - * Find the smallest available unit number to use - * for a new device. We don't just use a static - * count to handle the "repeated hot-(un)plug" - * scenario. - */ -static int -ahd_linux_next_unit() -{ - struct ahd_softc *ahd; - int unit; - - unit = 0; -retry: - TAILQ_FOREACH(ahd, &ahd_tailq, links) { - if (ahd->unit == unit) { - unit++; - goto retry; - } - } - return (unit); -} - -/* - * Place the SCSI bus into a known state by either resetting it, - * or forcing transfer negotiations on the next command to any - * target. - */ -void -ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd) -{ - int i; - int numtarg; - - i = 0; - numtarg = 0; - - if (aic79xx_no_reset != 0) - ahd->flags &= ~AHD_RESET_BUS_A; - - if ((ahd->flags & AHD_RESET_BUS_A) != 0) - ahd_reset_channel(ahd, 'A', /*initiate_reset*/TRUE); - else - numtarg = (ahd->features & AHD_WIDE) ? 16 : 8; - - for (; i < numtarg; i++) { - struct ahd_devinfo devinfo; - struct ahd_initiator_tinfo *tinfo; - struct ahd_tmode_tstate *tstate; - u_int our_id; - u_int target_id; - char channel; - - channel = 'A'; - our_id = ahd->our_id; - target_id = i; - tinfo = ahd_fetch_transinfo(ahd, channel, our_id, - target_id, &tstate); - tinfo->goal = tinfo->user; - /* - * Don't try negotiations that require PPR messages - * until we successfully retrieve Inquiry data. - */ - tinfo->goal.ppr_options = 0; - if (tinfo->goal.transport_version > SCSI_REV_2) - tinfo->goal.transport_version = SCSI_REV_2; - ahd_compile_devinfo(&devinfo, our_id, target_id, - CAM_LUN_WILDCARD, channel, ROLE_INITIATOR); - ahd_update_neg_request(ahd, &devinfo, tstate, - tinfo, /*force*/FALSE); - } - /* Give the bus some time to recover */ - if ((ahd->flags & AHD_RESET_BUS_A) != 0) { -/* SAE: No timers - ahd_freeze_simq(ahd); - init_timer(&ahd->platform_data->reset_timer); - ahd->platform_data->reset_timer.data = (u_long)ahd; - ahd->platform_data->reset_timer.expires = - jiffies + (AIC79XX_RESET_DELAY * HZ)/1000; - ahd->platform_data->reset_timer.function = - (ahd_linux_callback_t *)ahd_release_simq; - add_timer(&ahd->platform_data->reset_timer); -*/ - mdelay(AIC79XX_RESET_DELAY); - } -} - -int -ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg) -{ - ahd->platform_data = - malloc(sizeof(struct ahd_platform_data), M_DEVBUF, M_NOWAIT); - if (ahd->platform_data == NULL) - return (ENOMEM); - memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data)); - TAILQ_INIT(&ahd->platform_data->completeq); - TAILQ_INIT(&ahd->platform_data->device_runq); - ahd->platform_data->irq = AHD_LINUX_NOIRQ; - ahd->platform_data->hw_dma_mask = 0xFFFFFFFF; - ahd_lockinit(ahd); - ahd_done_lockinit(ahd); -/* SAE */ -#if XEN_KILLED -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - init_MUTEX_LOCKED(&ahd->platform_data->eh_sem); -#else - ahd->platform_data->eh_sem = MUTEX_LOCKED; -#endif -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_init(&ahd->platform_data->runq_tasklet, ahd_runq_tasklet, - (unsigned long)ahd); -#endif - ahd->seltime = (aic79xx_seltime & 0x3) << 4; -/* SAE */ -#if XEN_KILLED - if (TAILQ_EMPTY(&ahd_tailq)) - register_reboot_notifier(&ahd_linux_notifier); -#endif - return (0); -} - -void -ahd_platform_free(struct ahd_softc *ahd) -{ - if (ahd->platform_data != NULL) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_kill(&ahd->platform_data->runq_tasklet); -#endif - if (ahd->platform_data->host != NULL) - scsi_unregister(ahd->platform_data->host); - if (ahd->platform_data->irq != AHD_LINUX_NOIRQ) - free_irq(ahd->platform_data->irq, ahd); - if (ahd->tags[0] == BUS_SPACE_PIO - && ahd->bshs[0].ioport != 0) - release_region(ahd->bshs[0].ioport, 256); - if (ahd->tags[1] == BUS_SPACE_PIO - && ahd->bshs[1].ioport != 0) - release_region(ahd->bshs[1].ioport, 256); - if (ahd->tags[0] == BUS_SPACE_MEMIO - && ahd->bshs[0].maddr != NULL) { - u_long base_addr; - - base_addr = (u_long)ahd->bshs[0].maddr; - base_addr &= PAGE_MASK; - iounmap((void *)base_addr); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - release_mem_region(ahd->platform_data->mem_busaddr, - 0x1000); -#endif - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - /* XXX Need an instance detach in the PCI code */ - if (ahd->dev_softc != NULL) - ahd->dev_softc->driver = NULL; -#endif - free(ahd->platform_data, M_DEVBUF); - } - if (TAILQ_EMPTY(&ahd_tailq)) { -/* SAE: - unregister_reboot_notifier(&ahd_linux_notifier); -*/ -#ifdef CONFIG_PCI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pci_unregister_driver(&aic79xx_pci_driver); -#endif -#endif - } -} - -void -ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb) -{ - ahd_platform_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb), - SCB_GET_CHANNEL(ahd, scb), - SCB_GET_LUN(scb), SCB_LIST_NULL, - ROLE_UNKNOWN, CAM_REQUEUE_REQ); -} - -void -ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, - ahd_queue_alg alg) -{ - struct ahd_linux_device *dev; - int was_queuing; - int now_queuing; - - dev = ahd_linux_get_device(ahd, devinfo->channel - 'A', - devinfo->target, - devinfo->lun, /*alloc*/FALSE); - if (dev == NULL) - return; - was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED); - now_queuing = alg != AHD_QUEUE_NONE; - if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) == 0 - && (was_queuing != now_queuing) - && (dev->active != 0)) { - dev->flags |= AHD_DEV_FREEZE_TIL_EMPTY; - dev->qfrozen++; - } - - dev->flags &= ~(AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED|AHD_DEV_PERIODIC_OTAG); - if (now_queuing) { - u_int usertags; - - usertags = ahd_linux_user_tagdepth(ahd, devinfo); - if (!was_queuing) { - /* - * Start out agressively and allow our - * dynamic queue depth algorithm to take - * care of the rest. - */ - dev->maxtags = usertags; - dev->openings = dev->maxtags - dev->active; - } - if (alg == AHD_QUEUE_TAGGED) { - dev->flags |= AHD_DEV_Q_TAGGED; - if (aic79xx_periodic_otag != 0) - dev->flags |= AHD_DEV_PERIODIC_OTAG; - } else - dev->flags |= AHD_DEV_Q_BASIC; - } else { - /* We can only have one opening. */ - dev->maxtags = 0; - dev->openings = 1 - dev->active; - } -} - -int -ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel, - int lun, u_int tag, role_t role, uint32_t status) -{ - int targ; - int maxtarg; - int maxlun; - int clun; - int count; - - if (tag != SCB_LIST_NULL) - return (0); - - targ = 0; - if (target != CAM_TARGET_WILDCARD) { - targ = target; - maxtarg = targ + 1; - } else { - maxtarg = (ahd->features & AHD_WIDE) ? 16 : 8; - } - clun = 0; - if (lun != CAM_LUN_WILDCARD) { - clun = lun; - maxlun = clun + 1; - } else { - maxlun = AHD_NUM_LUNS; - } - - count = 0; - for (; targ < maxtarg; targ++) { - - for (; clun < maxlun; clun++) { - struct ahd_linux_device *dev; - struct ahd_busyq *busyq; - struct ahd_cmd *acmd; - - dev = ahd_linux_get_device(ahd, /*chan*/0, targ, - clun, /*alloc*/FALSE); - if (dev == NULL) - continue; - - busyq = &dev->busyq; - while ((acmd = TAILQ_FIRST(busyq)) != NULL) { - Scsi_Cmnd *cmd; - - cmd = &acmd_scsi_cmd(acmd); - TAILQ_REMOVE(busyq, acmd, - acmd_links.tqe); - count++; - cmd->result = status << 16; - ahd_linux_queue_cmd_complete(ahd, cmd); - } - } - } - - return (count); -} - -/* - * Sets the queue depth for each SCSI device hanging - * off the input host adapter. - */ -static void -ahd_linux_select_queue_depth(struct Scsi_Host * host, - Scsi_Device * scsi_devs) -{ - Scsi_Device *device; - struct ahd_softc *ahd; - u_long flags; - int scbnum; - - ahd = *((struct ahd_softc **)host->hostdata); - ahd_lock(ahd, &flags); - scbnum = 0; - for (device = scsi_devs; device != NULL; device = device->next) { - if (device->host == host) { - ahd_linux_device_queue_depth(ahd, device); - scbnum += device->queue_depth; - } - } - ahd_unlock(ahd, &flags); -} - -static u_int -ahd_linux_user_tagdepth(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) -{ - static int warned_user; - u_int tags; - - tags = 0; - if ((ahd->user_discenable & devinfo->target_mask) != 0) { - if (warned_user == 0 - && ahd->unit >= NUM_ELEMENTS(aic79xx_tag_info)) { - - printf("aic79xx: WARNING, insufficient " - "tag_info instances for installed " - "controllers. Using defaults\n"); - printf("aic79xx: Please update the " - "aic79xx_tag_info array in the " - "aic79xx.c source file.\n"); - tags = AHD_MAX_QUEUE; - warned_user++; - } else { - adapter_tag_info_t *tag_info; - - tag_info = &aic79xx_tag_info[ahd->unit]; - tags = tag_info->tag_commands[devinfo->target_offset]; - if (tags > AHD_MAX_QUEUE) - tags = AHD_MAX_QUEUE; - } - } - return (tags); -} - -/* - * Determines the queue depth for a given device. - */ -static void -ahd_linux_device_queue_depth(struct ahd_softc *ahd, Scsi_Device * device) -{ - struct ahd_devinfo devinfo; - u_int tags; - - ahd_compile_devinfo(&devinfo, - ahd->our_id, - device->id, device->lun, - device->channel == 0 ? 'A' : 'B', - ROLE_INITIATOR); - tags = ahd_linux_user_tagdepth(ahd, &devinfo); - if (tags != 0 - && device->tagged_supported != 0) { - - device->queue_depth = tags; - ahd_set_tags(ahd, &devinfo, AHD_QUEUE_TAGGED); - printf("scsi%d:%c:%d:%d: Tagged Queuing enabled. Depth %d\n", - ahd->platform_data->host->host_no, devinfo.channel, - devinfo.target, devinfo.lun, tags); - } else { - /* - * We allow the OS to queue 2 untagged transactions to - * us at any time even though we can only execute them - * serially on the controller/device. This should remove - * some latency. - */ - device->queue_depth = 2; - } -} - -/* - * Queue an SCB to the controller. - */ -int -ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) -{ - struct ahd_softc *ahd; - struct ahd_linux_device *dev; - u_long flags; - - ahd = *(struct ahd_softc **)cmd->host->hostdata; - - /* - * Save the callback on completion function. - */ - cmd->scsi_done = scsi_done; - - ahd_lock(ahd, &flags); - dev = ahd_linux_get_device(ahd, cmd->channel, cmd->target, - cmd->lun, /*alloc*/TRUE); - if (dev == NULL) { - ahd_unlock(ahd, &flags); - printf("aic79xx_linux_queue: Unable to allocate device!\n"); - return (-ENOMEM); - } - if (cmd->cmd_len > MAX_CDB_LEN) - return (-EINVAL); - cmd->result = CAM_REQ_INPROG << 16; - TAILQ_INSERT_TAIL(&dev->busyq, (struct ahd_cmd *)cmd, acmd_links.tqe); - if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) { - TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links); - dev->flags |= AHD_DEV_ON_RUN_LIST; - ahd_linux_run_device_queues(ahd); - } - ahd_unlock(ahd, &flags); - return (0); -} - -static void -ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev) -{ - struct ahd_cmd *acmd; - struct scsi_cmnd *cmd; - struct scb *scb; - struct hardware_scb *hscb; - struct ahd_initiator_tinfo *tinfo; - struct ahd_tmode_tstate *tstate; - uint16_t mask; - - if ((dev->flags & AHD_DEV_ON_RUN_LIST) != 0) - panic("running device on run list"); - - while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL - && dev->openings > 0 && dev->qfrozen == 0) { - - /* - * Schedule us to run later. The only reason we are not - * running is because the whole controller Q is frozen. - */ - if (ahd->platform_data->qfrozen != 0) { - - TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, - dev, links); - dev->flags |= AHD_DEV_ON_RUN_LIST; - return; - } - /* - * Get an scb to use. - */ - if ((scb = ahd_get_scb(ahd)) == NULL) { - TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, - dev, links); - dev->flags |= AHD_DEV_ON_RUN_LIST; - ahd->flags |= AHD_RESOURCE_SHORTAGE; - return; - } - TAILQ_REMOVE(&dev->busyq, acmd, acmd_links.tqe); - cmd = &acmd_scsi_cmd(acmd); - scb->io_ctx = cmd; - scb->platform_data->dev = dev; - hscb = scb->hscb; - cmd->host_scribble = (char *)scb; - - /* - * Fill out basics of the HSCB. - */ - hscb->control = 0; - hscb->scsiid = BUILD_SCSIID(ahd, cmd); - hscb->lun = cmd->lun; - mask = SCB_GET_TARGET_MASK(ahd, scb); - tinfo = ahd_fetch_transinfo(ahd, SCB_GET_CHANNEL(ahd, scb), - SCB_GET_OUR_ID(scb), - SCB_GET_TARGET(ahd, scb), &tstate); - - if ((ahd->user_discenable & mask) != 0) - hscb->control |= DISCENB; - - if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) - scb->flags |= SCB_PACKETIZED; - - if ((tstate->auto_negotiate & mask) != 0) { - scb->flags |= SCB_AUTO_NEGOTIATE; - scb->hscb->control |= MK_MESSAGE; - } - - if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) { - if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH - && (dev->flags & AHD_DEV_Q_TAGGED) != 0) { - hscb->control |= MSG_ORDERED_TASK; - dev->commands_since_idle_or_otag = 0; - } else { - hscb->control |= MSG_SIMPLE_TASK; - } - } - - hscb->cdb_len = cmd->cmd_len; - memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len); - - scb->sg_count = 0; - ahd_set_residual(scb, 0); - ahd_set_sense_residual(scb, 0); - if (cmd->use_sg != 0) { - void *sg; - struct scatterlist *cur_seg; - u_int nseg; - int dir; - - cur_seg = (struct scatterlist *)cmd->request_buffer; - dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); - nseg = pci_map_sg(ahd->dev_softc, cur_seg, - cmd->use_sg, dir); - scb->platform_data->xfer_len = 0; - for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) { - bus_addr_t addr; - bus_size_t len; - - addr = sg_dma_address(cur_seg); - len = sg_dma_len(cur_seg); - scb->platform_data->xfer_len += len; - sg = ahd_sg_setup(ahd, scb, sg, addr, len, - /*last*/nseg == 1); - } - } else if (cmd->request_bufflen != 0) { - void *sg; - bus_addr_t addr; - int dir; - - sg = scb->sg_list; - dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); - addr = pci_map_single(ahd->dev_softc, - cmd->request_buffer, - cmd->request_bufflen, dir); - scb->platform_data->xfer_len = cmd->request_bufflen; - scb->platform_data->buf_busaddr = addr; - sg = ahd_sg_setup(ahd, scb, sg, addr, - cmd->request_bufflen, /*last*/TRUE); - } - - LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links); - dev->openings--; - dev->active++; - dev->commands_issued++; - if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0) - dev->commands_since_idle_or_otag++; - scb->flags |= SCB_ACTIVE; - ahd_queue_scb(ahd, scb); - } -} - -/* - * SCSI controller interrupt handler. - */ -void -ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs) -{ - struct ahd_softc *ahd; - struct ahd_cmd *acmd; - u_long flags; - struct ahd_linux_device *next_dev; - - ahd = (struct ahd_softc *) dev_id; - ahd_lock(ahd, &flags); - ahd_intr(ahd); - acmd = TAILQ_FIRST(&ahd->platform_data->completeq); - TAILQ_INIT(&ahd->platform_data->completeq); - next_dev = ahd_linux_next_device_to_run(ahd); - ahd_unlock(ahd, &flags); - if (next_dev) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_schedule(&ahd->platform_data->runq_tasklet); -#else - ahd_runq_tasklet((unsigned long)ahd); -#endif - } - if (acmd != NULL) - ahd_linux_run_complete_queue(ahd, acmd); -} - -void -ahd_platform_flushwork(struct ahd_softc *ahd) -{ - struct ahd_cmd *acmd; - - acmd = TAILQ_FIRST(&ahd->platform_data->completeq); - TAILQ_INIT(&ahd->platform_data->completeq); - if (acmd != NULL) - ahd_linux_run_complete_queue(ahd, acmd); -} - -static struct ahd_linux_target* -ahd_linux_alloc_target(struct ahd_softc *ahd, u_int channel, u_int target) -{ - struct ahd_linux_target *targ; - u_int target_offset; - - targ = malloc(sizeof(*targ), M_DEVBUG, M_NOWAIT); - if (targ == NULL) - return (NULL); - memset(targ, 0, sizeof(*targ)); - targ->channel = channel; - targ->target = target; - targ->ahd = ahd; - target_offset = target; - if (channel != 0) - target_offset += 8; - ahd->platform_data->targets[target_offset] = targ; - return (targ); -} - -static void -ahd_linux_free_target(struct ahd_softc *ahd, struct ahd_linux_target *targ) -{ - u_int target_offset; - - target_offset = targ->target; - if (targ->channel != 0) - target_offset += 8; - ahd->platform_data->targets[target_offset] = NULL; - free(targ, M_DEVBUF); -} - -static struct ahd_linux_device* -ahd_linux_alloc_device(struct ahd_softc *ahd, - struct ahd_linux_target *targ, u_int lun) -{ - struct ahd_linux_device *dev; - - dev = malloc(sizeof(*dev), M_DEVBUG, M_NOWAIT); - if (dev == NULL) - return (NULL); - memset(dev, 0, sizeof(*dev)); - init_timer(&dev->timer); - TAILQ_INIT(&dev->busyq); - dev->flags = AHD_DEV_UNCONFIGURED; - dev->lun = lun; - dev->target = targ; - - /* - * We start out life using untagged - * transactions of which we allow one. - */ - dev->openings = 1; - - /* - * Set maxtags to 0. This will be changed if we - * later determine that we are dealing with - * a tagged queuing capable device. - */ - dev->maxtags = 0; - - targ->refcount++; - targ->devices[lun] = dev; - return (dev); -} - -static void -ahd_linux_free_device(struct ahd_softc *ahd, struct ahd_linux_device *dev) -{ - struct ahd_linux_target *targ; - - del_timer(&dev->timer); - targ = dev->target; - targ->devices[dev->lun] = NULL; - free(dev, M_DEVBUF); - targ->refcount--; - if (targ->refcount == 0) - ahd_linux_free_target(ahd, targ); -} - -/* - * Return a string describing the driver. - */ -const char * -ahd_linux_info(struct Scsi_Host *host) -{ - static char buffer[512]; - char ahd_info[256]; - char *bp; - struct ahd_softc *ahd; - - bp = &buffer[0]; - ahd = *(struct ahd_softc **)host->hostdata; - memset(bp, 0, sizeof(buffer)); - strcpy(bp, "Adaptec AIC79XX PCI-X SCSI HBA DRIVER, Rev "); - strcat(bp, AIC79XX_DRIVER_VERSION); - strcat(bp, "\n"); - strcat(bp, " <"); - strcat(bp, ahd->description); - strcat(bp, ">\n"); - strcat(bp, " "); - ahd_controller_info(ahd, ahd_info); - strcat(bp, ahd_info); - strcat(bp, "\n"); - - return (bp); -} - -void -ahd_send_async(struct ahd_softc *ahd, char channel, - u_int target, u_int lun, ac_code code, void *arg) -{ - switch (code) { - case AC_TRANSFER_NEG: - { - char buf[80]; - struct ahd_linux_target *targ; - struct info_str info; - struct ahd_initiator_tinfo *tinfo; - struct ahd_tmode_tstate *tstate; - - info.buffer = buf; - info.length = sizeof(buf); - info.offset = 0; - info.pos = 0; - tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id, - target, &tstate); - - /* - * Don't bother reporting results while - * negotiations are still pending. - */ - if (tinfo->curr.period != tinfo->goal.period - || tinfo->curr.width != tinfo->goal.width - || tinfo->curr.offset != tinfo->goal.offset - || tinfo->curr.ppr_options != tinfo->goal.ppr_options) - if (bootverbose == 0) - break; - - /* - * Don't bother reporting results that - * are identical to those last reported. - */ - targ = ahd->platform_data->targets[target]; - if (targ == NULL) - break; - if (tinfo->curr.period == targ->last_tinfo.period - && tinfo->curr.width == targ->last_tinfo.width - && tinfo->curr.offset == targ->last_tinfo.offset - && tinfo->curr.ppr_options == targ->last_tinfo.ppr_options) - if (bootverbose == 0) - break; - - targ->last_tinfo.period = tinfo->curr.period; - targ->last_tinfo.width = tinfo->curr.width; - targ->last_tinfo.offset = tinfo->curr.offset; - targ->last_tinfo.ppr_options = tinfo->curr.ppr_options; - - printf("(%s:%c:", ahd_name(ahd), channel); - if (target == CAM_TARGET_WILDCARD) - printf("*): "); - else - printf("%d): ", target); - ahd_format_transinfo(&info, &tinfo->curr); - if (info.pos < info.length) - *info.buffer = '\0'; - else - buf[info.length - 1] = '\0'; - printf("%s", buf); - break; - } - case AC_SENT_BDR: - break; - case AC_BUS_RESET: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - if (ahd->platform_data->host != NULL) { - scsi_report_bus_reset(ahd->platform_data->host, - channel - 'A'); - } -#endif - break; - default: - panic("ahd_send_async: Unexpected async event"); - } -} - -/* - * Calls the higher level scsi done function and frees the scb. - */ -void -ahd_done(struct ahd_softc *ahd, struct scb * scb) -{ - Scsi_Cmnd *cmd; - struct ahd_linux_device *dev; - - LIST_REMOVE(scb, pending_links); - if ((scb->flags & SCB_UNTAGGEDQ) != 0) { - struct scb_tailq *untagged_q; - int target_offset; - - target_offset = SCB_GET_TARGET_OFFSET(ahd, scb); - untagged_q = &(ahd->untagged_queues[target_offset]); - TAILQ_REMOVE(untagged_q, scb, links.tqe); - ahd_run_untagged_queue(ahd, untagged_q); - } - - if ((scb->flags & SCB_ACTIVE) == 0) { - printf("SCB %d done'd twice\n", scb->hscb->tag); - ahd_dump_card_state(ahd); - panic("Stopping for safety"); - } - cmd = scb->io_ctx; - dev = scb->platform_data->dev; - dev->active--; - dev->openings++; - ahd_linux_unmap_scb(ahd, scb); - if (scb->flags & SCB_SENSE) { - memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); - memcpy(cmd->sense_buffer, ahd_get_sense_buf(ahd, scb), - MIN(sizeof(struct scsi_sense_data), - sizeof(cmd->sense_buffer))); - cmd->result |= (DRIVER_SENSE << 24); - } else if (scb->flags & SCB_PKT_SENSE) { - struct scsi_status_iu_header *siu; - u_int sense_len; - - /* - * Copy only the sense data into the provided buffer. - */ - siu = (struct scsi_status_iu_header *)scb->sense_data; - sense_len = MIN(scsi_4btoul(siu->sense_length), - sizeof(cmd->sense_buffer)); - memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); - memcpy(cmd->sense_buffer, - ahd_get_sense_buf(ahd, scb) + SIU_SENSE_OFFSET(siu), - sense_len); - -#ifdef AHD_DEBUG - if (ahd_debug & AHD_SHOW_SENSE) { - int i; - - printf("Copied %d bytes of sense data offset %d:", - sense_len, SIU_SENSE_OFFSET(siu)); - for (i = 0; i < sense_len; i++) - printf(" 0x%x", cmd->sense_buffer[i]); - printf("\n"); - } -#endif - cmd->result |= (DRIVER_SENSE << 24); - } else { - /* - * Guard against stale sense data. - * The Linux mid-layer assumes that sense - * was retrieved anytime the first byte of - * the sense buffer looks "sane". - */ - cmd->sense_buffer[0] = 0; - } - if (ahd_get_transaction_status(scb) == CAM_REQ_INPROG) { - uint32_t amount_xferred; - - amount_xferred = - ahd_get_transfer_length(scb) - ahd_get_residual(scb); - if (amount_xferred < scb->io_ctx->underflow) { - printf("Saw underflow (%ld of %ld bytes). " - "Treated as error\n", - ahd_get_residual(scb), - ahd_get_transfer_length(scb)); - ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR); - } else { - ahd_set_transaction_status(scb, CAM_REQ_CMP); - ahd_linux_sniff_command(ahd, cmd, scb); - } - } else if (ahd_get_transaction_status(scb) == DID_OK) { - ahd_linux_handle_scsi_status(ahd, dev, scb); - } else if (ahd_get_transaction_status(scb) == DID_NO_CONNECT) { - /* - * Should a selection timeout kill the device? - * That depends on whether the selection timeout - * is persistent. Since we have no guarantee that - * the mid-layer will issue an inquiry for this device - * again, we can't just kill it off. - dev->flags |= AHD_DEV_UNCONFIGURED; - */ - } - - if (dev->openings == 1 - && ahd_get_transaction_status(scb) == CAM_REQ_CMP - && ahd_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL) - dev->tag_success_count++; - /* - * Some devices deal with temporary internal resource - * shortages by returning queue full. When the queue - * full occurrs, we throttle back. Slowly try to get - * back to our previous queue depth. - */ - if ((dev->openings + dev->active) < dev->maxtags - && dev->tag_success_count > AHD_TAG_SUCCESS_INTERVAL) { - dev->tag_success_count = 0; - dev->openings++; - } - - if (dev->active == 0) - dev->commands_since_idle_or_otag = 0; - - if (TAILQ_EMPTY(&dev->busyq)) { - if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0 - && dev->active == 0) - ahd_linux_free_device(ahd, dev); - } else if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) { - TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links); - dev->flags |= AHD_DEV_ON_RUN_LIST; - } - - if ((scb->flags & SCB_RECOVERY_SCB) != 0) { - printf("Recovery SCB completes\n"); -/* SAE: */ -#if XEN_KILLED - up(&ahd->platform_data->eh_sem); -#endif - } - - ahd_free_scb(ahd, scb); - ahd_linux_queue_cmd_complete(ahd, cmd); -} - -static void -ahd_linux_handle_scsi_status(struct ahd_softc *ahd, - struct ahd_linux_device *dev, struct scb *scb) -{ - /* - * We don't currently trust the mid-layer to - * properly deal with queue full or busy. So, - * when one occurs, we tell the mid-layer to - * unconditionally requeue the command to us - * so that we can retry it ourselves. We also - * implement our own throttling mechanism so - * we don't clobber the device with too many - * commands. - */ - switch (ahd_get_scsi_status(scb)) { - default: - break; - case SCSI_STATUS_QUEUE_FULL: - { - /* - * By the time the core driver has returned this - * command, all other commands that were queued - * to us but not the device have been returned. - * This ensures that dev->active is equal to - * the number of commands actually queued to - * the device. - */ - dev->tag_success_count = 0; - if (dev->active != 0) { - /* - * Drop our opening count to the number - * of commands currently outstanding. - */ - dev->openings = 0; -#ifdef AHD_DEBUG - if (ahd_debug & AHD_SHOW_QFULL) { - ahd_print_path(ahd, scb); - printf("Dropping tag count to %d\n", - dev->active); - } -#endif - if (dev->active == dev->tags_on_last_queuefull) { - - dev->last_queuefull_same_count++; - /* - * If we repeatedly see a queue full - * at the same queue depth, this - * device has a fixed number of tag - * slots. Lock in this tag depth - * so we stop seeing queue fulls from - * this device. - */ - if (dev->last_queuefull_same_count - == AHD_LOCK_TAGS_COUNT) { - dev->maxtags = dev->active; - ahd_print_path(ahd, scb); - printf("Locking max tag count at %d\n", - dev->active); - } - } else { - dev->tags_on_last_queuefull = dev->active; - dev->last_queuefull_same_count = 0; - } - ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); - ahd_set_scsi_status(scb, SCSI_STATUS_OK); - break; - } - /* - * Drop down to a single opening, and treat this - * as if the target return BUSY SCSI status. - */ - dev->openings = 1; - /* FALLTHROUGH */ - } - case SCSI_STATUS_BUSY: - /* - * Set a short timer to defer sending commands for - * a bit since Linux will not delay in this case. - */ - if ((dev->flags & AHD_DEV_TIMER_ACTIVE) != 0) { - printf("%s:%c:%d: Device Timer still active during " - "busy processing\n", ahd_name(ahd), - dev->target->channel, dev->target->target); - break; - } - dev->flags |= AHD_DEV_TIMER_ACTIVE; - dev->qfrozen++; - init_timer(&dev->timer); - dev->timer.data = (u_long)dev; - dev->timer.expires = jiffies + (HZ/2); - dev->timer.function = ahd_linux_dev_timed_unfreeze; - add_timer(&dev->timer); - break; - } -} - -static void -ahd_linux_filter_command(struct ahd_softc *ahd, Scsi_Cmnd *cmd, struct scb *scb) -{ - switch (cmd->cmnd[0]) { - case INQUIRY: - { - struct ahd_devinfo devinfo; - struct scsi_inquiry *inq; - struct scsi_inquiry_data *sid; - struct ahd_initiator_tinfo *tinfo; - struct ahd_transinfo *user; - struct ahd_transinfo *goal; - struct ahd_transinfo *curr; - struct ahd_tmode_tstate *tstate; - struct ahd_linux_device *dev; - u_int scsiid; - int transferred_len; - int minlen; - int was_configured; - u_int width; - u_int period; - u_int offset; - u_int ppr_options; - u_int trans_version; - u_int prot_version; - static int warned_user; - - /* - * Validate the command. We only want to filter - * standard inquiry commands, not those querying - * Vital Product Data. - */ - inq = (struct scsi_inquiry *)cmd->cmnd; - if ((inq->byte2 & SI_EVPD) != 0 - || inq->page_code != 0) - break; - - if (cmd->use_sg != 0) { - printf("%s: SG Inquiry response ignored\n", - ahd_name(ahd)); - break; - } - transferred_len = ahd_get_transfer_length(scb) - - ahd_get_residual(scb); - sid = (struct scsi_inquiry_data *)cmd->request_buffer; - - /* - * Determine if this lun actually exists. If so, - * hold on to its corresponding device structure. - * If not, make sure we release the device and - * don't bother processing the rest of this inquiry - * command. - */ - dev = ahd_linux_get_device(ahd, cmd->channel, - cmd->target, cmd->lun, - /*alloc*/FALSE); - was_configured = dev->flags & AHD_DEV_UNCONFIGURED; - if (transferred_len >= 1 - && SID_QUAL(sid) == SID_QUAL_LU_CONNECTED) { - - dev->flags &= ~AHD_DEV_UNCONFIGURED; - } else { - dev->flags |= AHD_DEV_UNCONFIGURED; - break; - } - - /* - * Update our notion of this device's transfer - * negotiation capabilities. - */ - scsiid = BUILD_SCSIID(ahd, cmd); - ahd_compile_devinfo(&devinfo, SCSIID_OUR_ID(scsiid), - cmd->target, cmd->lun, - SCSIID_CHANNEL(ahd, scsiid), - ROLE_INITIATOR); - tinfo = ahd_fetch_transinfo(ahd, devinfo.channel, - devinfo.our_scsiid, - devinfo.target, &tstate); - user = &tinfo->user; - goal = &tinfo->goal; - curr = &tinfo->curr; - width = user->width; - period = user->period; - offset = user->offset; - ppr_options = user->ppr_options; - trans_version = user->transport_version; - prot_version = user->protocol_version; - /* - * If we have read streaming info for this controller, - * apply it to this target. - */ - if (warned_user == 0 - && ahd->unit >= NUM_ELEMENTS(aic79xx_rd_strm_info)) { - - printf("aic79xx: WARNING, insufficient " - "rd_strm instances for installed " - "controllers. Using defaults\n"); - printf("aic79xx: Please update the " - "aic79xx_rd_strm_info array in the " - "aic79xx.c source file.\n"); - warned_user++; - } else { - uint16_t rd_strm_mask; - - rd_strm_mask = aic79xx_rd_strm_info[ahd->unit]; - if ((rd_strm_mask & devinfo.target_mask) == 0) - ppr_options &= ~MSG_EXT_PPR_RD_STRM; - } - - minlen = offsetof(struct scsi_inquiry_data, version) + 1; - if (transferred_len >= minlen) { - prot_version = SID_ANSI_REV(sid); - - /* - * Only attempt SPI3 once we've verified that - * the device claims to support SPI3 features. - */ - if (prot_version < SCSI_REV_2) - trans_version = SID_ANSI_REV(sid); - else - trans_version = SCSI_REV_2; - } - - minlen = offsetof(struct scsi_inquiry_data, flags) + 1; - if (transferred_len >= minlen - && (sid->additional_length + 4) >= minlen) { - if ((sid->flags & SID_WBus16) == 0) - width = MSG_EXT_WDTR_BUS_8_BIT; - if ((sid->flags & SID_Sync) == 0) { - period = 0; - offset = 0; - ppr_options = 0; - } - } else { - /* Keep current settings */ - break; - } - minlen = offsetof(struct scsi_inquiry_data, spi3data) + 1; - /* - * This is a kludge to deal with inquiry requests that - * are not large enough for us to pull the spi3/4 bits. - * In this case, we assume that a device that tells us - * they can provide inquiry data that spans the SPI3 - * bits and says its SCSI3 can handle a PPR request. - * If the inquiry request has sufficient buffer space to - * cover SPI3 bits, we honor them regardless of reported - * SCSI REV. We also allow any device that has had its - * goal ppr_options set to allow DT speeds to keep that - * option if a short inquiry occurs that would fail the - * normal tests outlined above. - */ - if ((sid->additional_length + 4) >= minlen) { - if (transferred_len >= minlen) { - if ((sid->spi3data & SID_SPI_CLOCK_DT) == 0) - ppr_options = 0; - if ((sid->spi3data & SID_SPI_IUS) == 0) - ppr_options &= (MSG_EXT_PPR_DT_REQ - | MSG_EXT_PPR_QAS_REQ); - } else if (was_configured - && (curr->transport_version - == user->transport_version)) { - - /* Keep already existant settings. */ - break; - } else if ((goal->ppr_options & MSG_EXT_PPR_DT_REQ)== 0) - ppr_options = 0; - - if (curr->protocol_version > SCSI_REV_2) - trans_version = user->transport_version; - } else { - ppr_options = 0; - } - ahd_validate_width(ahd, /*tinfo limit*/NULL, &width, - ROLE_UNKNOWN); - - ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_MAX); - ahd_validate_offset(ahd, /*tinfo limit*/NULL, period, - &offset, width, ROLE_UNKNOWN); - if (offset == 0 || period == 0) { - period = 0; - offset = 0; - ppr_options = 0; - } - /* Apply our filtered user settings. */ - curr->transport_version = trans_version; - curr->protocol_version = prot_version; - ahd_set_width(ahd, &devinfo, width, - AHD_TRANS_GOAL, /*paused*/FALSE); - ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options, - AHD_TRANS_GOAL, /*paused*/FALSE); - break; - } - default: - panic("ahd_linux_filter_command: Unexpected Command type %x\n", - cmd->cmnd[0]); - break; - } -} - -void -ahd_freeze_simq(struct ahd_softc *ahd) -{ - ahd->platform_data->qfrozen++; - if (ahd->platform_data->qfrozen == 1) - scsi_block_requests(ahd->platform_data->host); -} - -void -ahd_release_simq(struct ahd_softc *ahd) -{ - u_long s; - int unblock_reqs; - - unblock_reqs = 0; - ahd_lock(ahd, &s); - if (ahd->platform_data->qfrozen > 0) - ahd->platform_data->qfrozen--; - if (ahd->platform_data->qfrozen == 0) { - unblock_reqs = 1; - } - ahd_unlock(ahd, &s); - /* - * There is still a race here. The mid-layer - * should keep its own freeze count and use - * a bottom half handler to run the queues - * so we can unblock with our own lock held. - */ - if (unblock_reqs) { - scsi_unblock_requests(ahd->platform_data->host); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_schedule(&ahd->platform_data->runq_tasklet); -#else - ahd_runq_tasklet((unsigned long)ahd); -#endif - } -} - -/* SAE */ -#if XEN_KILLED -static void -ahd_linux_sem_timeout(u_long arg) -{ - struct semaphore *sem; - - sem = (struct semaphore *)arg; - up(sem); -} - -static int -ahd_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag) -{ - struct ahd_softc *ahd; - struct ahd_cmd *acmd; - struct ahd_cmd *list_acmd; - struct ahd_linux_device *dev; - struct scb *pending_scb; - u_long s; - u_int saved_scbptr; - u_int active_scb_index; - u_int last_phase; - int retval; - int paused; - int wait; - int disconnected; - - paused = FALSE; - wait = FALSE; - ahd = *(struct ahd_softc **)cmd->host->hostdata; - acmd = (struct ahd_cmd *)cmd; - - printf("%s:%d:%d:%d: Attempting to queue a%s message\n", - ahd_name(ahd), cmd->channel, cmd->target, cmd->lun, - flag == SCB_ABORT ? "n ABORT" : " TARGET RESET"); - - /* - * It is a bug that the upper layer takes - * this lock just prior to calling us. - */ - spin_unlock_irq(&io_request_lock); - - ahd_lock(ahd, &s); - - /* - * First determine if we currently own this command. - * Start by searching the device queue. If not found - * there, check the pending_scb list. If not found - * at all, and the system wanted us to just abort the - * command return success. - */ - dev = ahd_linux_get_device(ahd, cmd->channel, cmd->target, - cmd->lun, /*alloc*/FALSE); - - if (dev == NULL) { - /* - * No target device for this command exists, - * so we must not still own the command. - */ - printf("%s:%d:%d:%d: Is not an active device\n", - ahd_name(ahd), cmd->channel, cmd->target, cmd->lun); - retval = SUCCESS; - goto no_cmd; - } - - TAILQ_FOREACH(list_acmd, &dev->busyq, acmd_links.tqe) { - if (list_acmd == acmd) - break; - } - - if (list_acmd != NULL) { - printf("%s:%d:%d:%d: Command found on device queue\n", - ahd_name(ahd), cmd->channel, cmd->target, cmd->lun); - if (flag == SCB_ABORT) { - TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe); - cmd->result = DID_ABORT << 16; - ahd_linux_queue_cmd_complete(ahd, cmd); - retval = SUCCESS; - goto done; - } - } - - /* - * See if we can find a matching cmd in the pending list. - */ - LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) { - if (pending_scb->io_ctx == cmd) - break; - } - - if (pending_scb == NULL && flag == SCB_DEVICE_RESET) { - - /* Any SCB for this device will do for a target reset */ - LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) { - if (ahd_match_scb(ahd, pending_scb, cmd->target, - cmd->channel, CAM_LUN_WILDCARD, - SCB_LIST_NULL, ROLE_INITIATOR) == 0) - break; - } - } - - if (pending_scb == NULL) { - printf("%s:%d:%d:%d: Command not found\n", - ahd_name(ahd), cmd->channel, cmd->target, cmd->lun); - goto no_cmd; - } - - if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) { - /* - * We can't queue two recovery actions using the same SCB - */ - retval = FAILED; - goto done; - } - - /* - * Ensure that the card doesn't do anything - * behind our back. Also make sure that we - * didn't "just" miss an interrupt that would - * affect this cmd. - */ - ahd->flags |= AHD_ALL_INTERRUPTS; - do { - ahd_intr(ahd); - ahd_pause(ahd); - ahd_clear_critical_section(ahd); - } while (ahd_inb(ahd, INTSTAT) & INT_PEND); - ahd->flags &= ~AHD_ALL_INTERRUPTS; - paused = TRUE; - - ahd_dump_card_state(ahd); - - if ((pending_scb->flags & SCB_ACTIVE) == 0) { - printf("%s:%d:%d:%d: Command already completed\n", - ahd_name(ahd), cmd->channel, cmd->target, cmd->lun); - goto no_cmd; - } - - disconnected = TRUE; - if (flag == SCB_ABORT) { - if (ahd_search_qinfifo(ahd, cmd->target, cmd->channel + 'A', - cmd->lun, pending_scb->hscb->tag, - ROLE_INITIATOR, CAM_REQ_ABORTED, - SEARCH_COMPLETE) > 0) { - printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", - ahd_name(ahd), cmd->channel, cmd->target, - cmd->lun); - retval = SUCCESS; - goto done; - } - } else if (ahd_search_qinfifo(ahd, cmd->target, cmd->channel + 'A', - cmd->lun, pending_scb->hscb->tag, - ROLE_INITIATOR, /*status*/0, - SEARCH_COUNT) > 0) { - disconnected = FALSE; - } - - /* - * At this point, pending_scb is the scb associated with the - * passed in command. That command is currently active on the - * bus, is in the disconnected state, or we're hoping to find - * a command for the same target active on the bus to abuse to - * send a BDR. Queue the appropriate message based on which of - * these states we are in. - */ - last_phase = ahd_inb(ahd, LASTPHASE); - saved_scbptr = ahd_inb(ahd, SCBPTR); - active_scb_index = ahd_inb(ahd, SCB_TAG); - if (last_phase != P_BUSFREE - && (pending_scb->hscb->tag == active_scb_index - || (flag == SCB_DEVICE_RESET - && SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)) == cmd->target))) { - - /* - * We're active on the bus, so assert ATN - * and hope that the target responds. - */ - pending_scb = ahd_lookup_scb(ahd, active_scb_index); - pending_scb->flags |= SCB_RECOVERY_SCB|flag; - ahd_outb(ahd, MSG_OUT, HOST_MSG); - ahd_outb(ahd, SCSISIGO, last_phase|ATNO); - printf("%s:%d:%d:%d: Device is active, asserting ATN\n", - ahd_name(ahd), cmd->channel, cmd->target, cmd->lun); - wait = TRUE; - } else if (disconnected) { - - /* - * Actually re-queue this SCB in an attempt - * to select the device before it reconnects. - * In either case (selection or reselection), - * we will now issue the approprate message - * to the timed-out device. - * - * Set the MK_MESSAGE control bit indicating - * that we desire to send a message. We - * also set the disconnected flag since - * in the paging case there is no guarantee - * that our SCB control byte matches the - * version on the card. We don't want the - * sequencer to abort the command thinking - * an unsolicited reselection occurred. - */ - pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED; - pending_scb->flags |= SCB_RECOVERY_SCB|flag; - - /* - * In the non-paging case, the sequencer will - * never re-reference the in-core SCB. - * To make sure we are notified during - * reslection, set the MK_MESSAGE flag in - * the card's copy of the SCB. - */ - ahd_outb(ahd, SCBPTR, pending_scb->hscb->tag); - ahd_outb(ahd, SCB_CONTROL, - ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE); - - /* - * Clear out any entries in the QINFIFO first - * so we are the next SCB for this target - * to run. - */ - ahd_search_qinfifo(ahd, cmd->target, cmd->channel + 'A', - cmd->lun, SCB_LIST_NULL, ROLE_INITIATOR, - CAM_REQUEUE_REQ, SEARCH_COMPLETE); - ahd_print_path(ahd, pending_scb); - printf("Queuing a recovery SCB\n"); - ahd_qinfifo_requeue_tail(ahd, pending_scb); - ahd_outb(ahd, SCBPTR, saved_scbptr); - printf("%s:%d:%d:%d: Device is disconnected, re-queuing SCB\n", - ahd_name(ahd), cmd->channel, cmd->target, cmd->lun); - wait = TRUE; - } else { - printf("%s:%d:%d:%d: Unable to deliver message\n", - ahd_name(ahd), cmd->channel, cmd->target, cmd->lun); - retval = FAILED; - goto done; - } - -no_cmd: - /* - * Our assumption is that if we don't have the command, no - * recovery action was required, so we return success. Again, - * the semantics of the mid-layer recovery engine are not - * well defined, so this may change in time. - */ - retval = SUCCESS; -done: - if (paused) - ahd_unpause(ahd); - if (wait) { -/* SAE */ - printf("SAE: aic79xxx: recovery failed\n"); - retval=FAILED; -#if XEN_KILLED - struct timer_list timer; - int ret; - - ahd_unlock(ahd, &s); - init_timer(&timer); - timer.data = (u_long)&ahd->platform_data->eh_sem; - timer.expires = jiffies + (5 * HZ); - timer.function = ahd_linux_sem_timeout; - add_timer(&timer); - printf("Recovery code sleeping\n"); - down(&ahd->platform_data->eh_sem); - printf("Recovery code awake\n"); - ret = del_timer(&timer); - if (ret == 0) { - printf("Timer Expired\n"); - retval = FAILED; - } - ahd_lock(ahd, &s); -#endif - } - acmd = TAILQ_FIRST(&ahd->platform_data->completeq); - TAILQ_INIT(&ahd->platform_data->completeq); - ahd_unlock(ahd, &s); - if (acmd != NULL) - ahd_linux_run_complete_queue(ahd, acmd); - ahd_runq_tasklet((unsigned long)ahd); - spin_lock_irq(&io_request_lock); - return (retval); -} -#endif /* XEN_KILLED */ - -static void -ahd_linux_dev_timed_unfreeze(u_long arg) -{ - struct ahd_linux_device *dev; - struct ahd_softc *ahd; - u_long s; - - dev = (struct ahd_linux_device *)arg; - ahd = dev->target->ahd; - ahd_lock(ahd, &s); - dev->flags &= ~AHD_DEV_TIMER_ACTIVE; - if (dev->qfrozen > 0) - dev->qfrozen--; - if (dev->qfrozen == 0 - && (dev->flags & AHD_DEV_ON_RUN_LIST) == 0) - ahd_linux_run_device_queue(ahd, dev); - ahd_unlock(ahd, &s); -} - -/* - * Abort the current SCSI command(s). - */ -int -ahd_linux_abort(Scsi_Cmnd *cmd) -{ - struct ahd_softc *ahd; - u_long s; -#if NOTYET - struct ahd_cmd *acmd; - int found; -#endif - - ahd = *(struct ahd_softc **)cmd->host->hostdata; -#if NOTYET - int error; - - error = ahd_linux_queue_recovery_cmd(cmd, SCB_ABORT); - if (error != 0) - printf("aic79xx_abort returns 0x%x\n", error); - return (error); -#else - printf("Abort called for cmd %p\n", cmd); - ahd_lock(ahd, &s); - ahd_dump_card_state(ahd); - ahd_unlock(ahd, &s); - return (FAILED); -#endif -} - -/* - * Attempt to send a target reset message to the device that timed out. - */ -int -ahd_linux_dev_reset(Scsi_Cmnd *cmd) -{ - struct ahd_softc *ahd; -#if NOTYET - struct ahd_cmd *acmd; - u_long s; - int found; -#endif - - printf("dev reset called for cmd %p\n", cmd); - ahd = *(struct ahd_softc **)cmd->host->hostdata; -#if NOTYET - int error; - - error = ahd_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET); - if (error != 0) - printf("aic79xx_dev_reset returns 0x%x\n", error); - return (error); -#else - return (FAILED); -#endif -} - -/* - * Reset the SCSI bus. - */ -int -ahd_linux_bus_reset(Scsi_Cmnd *cmd) -{ - struct ahd_softc *ahd; - struct ahd_cmd *acmd; - u_long s; - int found; - - printf("bus reset called for cmd %p\n", cmd); - /* - * It is a bug that the upper layer takes - * this lock just prior to calling us. - */ - spin_unlock_irq(&io_request_lock); - - ahd = *(struct ahd_softc **)cmd->host->hostdata; - ahd_lock(ahd, &s); - found = ahd_reset_channel(ahd, cmd->channel + 'A', - /*initiate reset*/TRUE); - acmd = TAILQ_FIRST(&ahd->platform_data->completeq); - TAILQ_INIT(&ahd->platform_data->completeq); - ahd_unlock(ahd, &s); - if (bootverbose) - printf("%s: SCSI bus reset delivered. " - "%d SCBs aborted.\n", ahd_name(ahd), found); - - if (acmd != NULL) - ahd_linux_run_complete_queue(ahd, acmd); - - spin_lock_irq(&io_request_lock); - return (SUCCESS); -} - -/* - * Return the disk geometry for the given SCSI device. - */ -int -ahd_linux_biosparam(Disk *disk, kdev_t dev, int geom[]) -{ - int heads; - int sectors; - int cylinders; -/* SAE */ -#if XEN_KILLED - int ret; -#endif - int extended; - struct ahd_softc *ahd; -/* SAE */ -#if XEN_KILLED - struct buffer_head *bh; -#endif - - ahd = *((struct ahd_softc **)disk->device->host->hostdata); -/* SAE: */ -#if XEN_KILLED - bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, 1024); - - if (bh) { - ret = scsi_partsize(bh, disk->capacity, - &geom[2], &geom[0], &geom[1]); - brelse(bh); - if (ret != -1) - return (ret); - } -#endif - heads = 64; - sectors = 32; - cylinders = disk->capacity / (heads * sectors); - - if (aic79xx_extended != 0) - extended = 1; - else - extended = (ahd->flags & AHD_EXTENDED_TRANS_A) != 0; - if (extended && cylinders >= 1024) { - heads = 255; - sectors = 63; - cylinders = disk->capacity / (heads * sectors); - } - geom[0] = heads; - geom[1] = sectors; - geom[2] = cylinders; - return (0); -} - -/* - * Free the passed in Scsi_Host memory structures prior to unloading the - * module. - */ -int -ahd_linux_release(struct Scsi_Host * host) -{ - struct ahd_softc *ahd; - u_long l; - - ahd_list_lock(&l); - if (host != NULL) { - - /* - * We should be able to just perform - * the free directly, but check our - * list for extra sanity. - */ - ahd = ahd_find_softc(*(struct ahd_softc **)host->hostdata); - if (ahd != NULL) { - u_long s; - - ahd_lock(ahd, &s); - ahd_intr_enable(ahd, FALSE); - ahd_unlock(ahd, &s); - ahd_free(ahd); - } - } - ahd_list_unlock(&l); - return (0); -} - -void -ahd_platform_dump_card_state(struct ahd_softc *ahd) -{ - struct ahd_linux_device *dev; - int target; - int maxtarget; - int lun; - int i; - - maxtarget = (ahd->features & AHD_WIDE) ? 15 : 7; - for (target = 0; target <=maxtarget; target++) { - - for (lun = 0; lun < AHD_NUM_LUNS; lun++) { - struct ahd_cmd *acmd; - - dev = ahd_linux_get_device(ahd, 0, target, - lun, /*alloc*/FALSE); - if (dev == NULL) - continue; - - printf("DevQ(%d:%d:%d): ", 0, target, lun); - i = 0; - TAILQ_FOREACH(acmd, &dev->busyq, acmd_links.tqe) { - if (i++ > AHD_SCB_MAX) - break; - } - printf("%d waiting\n", i); - } - } -} - -#if defined(MODULE) || LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -static Scsi_Host_Template driver_template = AIC79XX; -Scsi_Host_Template *aic79xx_driver_template = &driver_template; -#include "../scsi_module.c.inc" -#endif diff --git a/xen/drivers/scsi/aic7xxx/aic79xx_osm.h b/xen/drivers/scsi/aic7xxx/aic79xx_osm.h deleted file mode 100644 index c17001d25b..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic79xx_osm.h +++ /dev/null @@ -1,1303 +0,0 @@ -/* - * Adaptec AIC79xx device driver for Linux. - * - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#35 $ - * - */ -#ifndef _AIC79XX_LINUX_H_ -#define _AIC79XX_LINUX_H_ - -#include -#include -#include -#include -#include -#include -#include -/* SAE */ -#if XEN_KILLED -#include -#endif -#ifndef AHD_MODVERSION_FILE -#define __NO_VERSION__ -#endif -#include -#include - -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) -#endif - -/* SAE */ -#define LINUX_VERSION_CODE KERNEL_VERSION(2,4,0) - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -#include /* For tasklet support. */ -#include -#include -#else -#include -#endif - -/* Core SCSI definitions */ -#include "../scsi.h" -#include "../hosts.h" - -/* Name space conflict with BSD queue macros */ -#ifdef LIST_HEAD -#undef LIST_HEAD -#endif - -#include "cam.h" -#include "queue.h" -#include "scsi_message.h" -#include "scsi_iu.h" - -/*********************************** Debugging ********************************/ -#ifdef CONFIG_AIC79XX_DEBUG_ENABLE -#ifdef CONFIG_AIC79XX_DEBUG_MASK -#define AHD_DEBUG CONFIG_AIC79XX_DEBUG_MASK -#else -/* - * Compile in debugging code, but do not enable any printfs. - */ -#define AHD_DEBUG 0 -#endif -#endif - -/********************************** Misc Macros *******************************/ -#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) -#define powerof2(x) ((((x)-1)&(x))==0) - -/************************* Forward Declarations *******************************/ -struct ahd_softc; -typedef struct pci_dev *ahd_dev_softc_t; -typedef Scsi_Cmnd *ahd_io_ctx_t; - -/******************************* Byte Order ***********************************/ -#define ahd_htobe16(x) cpu_to_be16(x) -#define ahd_htobe32(x) cpu_to_be32(x) -#define ahd_htobe64(x) cpu_to_be64(x) -#define ahd_htole16(x) cpu_to_le16(x) -#define ahd_htole32(x) cpu_to_le32(x) -#define ahd_htole64(x) cpu_to_le64(x) - -#define ahd_be16toh(x) be16_to_cpu(x) -#define ahd_be32toh(x) be32_to_cpu(x) -#define ahd_be64toh(x) be64_to_cpu(x) -#define ahd_le16toh(x) le16_to_cpu(x) -#define ahd_le32toh(x) le32_to_cpu(x) -#define ahd_le64toh(x) le64_to_cpu(x) - -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN 1234 -#endif - -#ifndef BIG_ENDIAN -#define BIG_ENDIAN 4321 -#endif - -#ifndef BYTE_ORDER -#if defined(__BIG_ENDIAN) -#define BYTE_ORDER BIG_ENDIAN -#endif -#if defined(__LITTLE_ENDIAN) -#define BYTE_ORDER LITTLE_ENDIAN -#endif -#endif /* BYTE_ORDER */ - -/* SAE: */ -#define off_t int - -/************************* Configuration Data *********************************/ -extern int aic79xx_detect_complete; -extern Scsi_Host_Template* aic79xx_driver_template; - -/***************************** Bus Space/DMA **********************************/ -/* SAE */ -typedef dma_addr_t bus_addr_t; -#if XEN_KILLED -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,17) -typedef dma_addr_t bus_addr_t; -#else -typedef uint32_t bus_addr_t; -#endif -#endif -typedef uint32_t bus_size_t; - -typedef enum { - BUS_SPACE_MEMIO, - BUS_SPACE_PIO -} bus_space_tag_t; - -typedef union { - u_long ioport; - volatile uint8_t *maddr; -} bus_space_handle_t; - -typedef struct bus_dma_segment -{ - bus_addr_t ds_addr; - bus_size_t ds_len; -} bus_dma_segment_t; - -struct ahd_linux_dma_tag -{ - bus_size_t alignment; - bus_size_t boundary; - bus_size_t maxsize; -}; -typedef struct ahd_linux_dma_tag* bus_dma_tag_t; - -struct ahd_linux_dmamap -{ - bus_addr_t bus_addr; -}; -typedef struct ahd_linux_dmamap* bus_dmamap_t; - -typedef int bus_dma_filter_t(void*, bus_addr_t); -typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); - -#define BUS_DMA_WAITOK 0x0 -#define BUS_DMA_NOWAIT 0x1 -#define BUS_DMA_ALLOCNOW 0x2 -#define BUS_DMA_LOAD_SEGS 0x4 /* - * Argument is an S/G list not - * a single buffer. - */ - -#define BUS_SPACE_MAXADDR 0xFFFFFFFF -#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF -#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF - -int ahd_dma_tag_create(struct ahd_softc *, bus_dma_tag_t /*parent*/, - bus_size_t /*alignment*/, bus_size_t /*boundary*/, - bus_addr_t /*lowaddr*/, bus_addr_t /*highaddr*/, - bus_dma_filter_t*/*filter*/, void */*filterarg*/, - bus_size_t /*maxsize*/, int /*nsegments*/, - bus_size_t /*maxsegsz*/, int /*flags*/, - bus_dma_tag_t */*dma_tagp*/); - -void ahd_dma_tag_destroy(struct ahd_softc *, bus_dma_tag_t /*tag*/); - -int ahd_dmamem_alloc(struct ahd_softc *, bus_dma_tag_t /*dmat*/, - void** /*vaddr*/, int /*flags*/, - bus_dmamap_t* /*mapp*/); - -void ahd_dmamem_free(struct ahd_softc *, bus_dma_tag_t /*dmat*/, - void* /*vaddr*/, bus_dmamap_t /*map*/); - -void ahd_dmamap_destroy(struct ahd_softc *, bus_dma_tag_t /*tag*/, - bus_dmamap_t /*map*/); - -int ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t /*dmat*/, - bus_dmamap_t /*map*/, void * /*buf*/, - bus_size_t /*buflen*/, bus_dmamap_callback_t *, - void */*callback_arg*/, int /*flags*/); - -int ahd_dmamap_unload(struct ahd_softc *, bus_dma_tag_t, bus_dmamap_t); - -/* - * Operations performed by ahd_dmamap_sync(). - */ -#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ -#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ -#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ -#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ - -/* - * XXX - * ahd_dmamap_sync is only used on buffers allocated with - * the pci_alloc_consistent() API. Although I'm not sure how - * this works on architectures with a write buffer, Linux does - * not have an API to sync "coherent" memory. Perhaps we need - * to do an mb()? - */ -#define ahd_dmamap_sync(ahd, dma_tag, dmamap, offset, len, op) - -/************************** SCSI Constants/Structures *************************/ -#define SCSI_REV_2 2 -#define SCSI_STATUS_OK 0x00 -#define SCSI_STATUS_CHECK_COND 0x02 -#define SCSI_STATUS_COND_MET 0x04 -#define SCSI_STATUS_BUSY 0x08 -#define SCSI_STATUS_INTERMED 0x10 -#define SCSI_STATUS_INTERMED_COND_MET 0x14 -#define SCSI_STATUS_RESERV_CONFLICT 0x18 -#define SCSI_STATUS_CMD_TERMINATED 0x22 -#define SCSI_STATUS_QUEUE_FULL 0x28 - -/* - * 6 byte request sense CDB format. - */ -struct scsi_sense -{ - uint8_t opcode; - uint8_t byte2; - uint8_t unused[2]; - uint8_t length; - uint8_t control; -}; - -struct scsi_sense_data -{ - uint8_t error_code; - uint8_t segment; - uint8_t flags; - uint8_t info[4]; - uint8_t extra_len; - uint8_t cmd_spec_info[4]; - uint8_t add_sense_code; - uint8_t add_sense_code_qual; - uint8_t fru; - uint8_t sense_key_spec[3]; - uint8_t extra_bytes[14]; -}; - -struct scsi_inquiry -{ - u_int8_t opcode; - u_int8_t byte2; -#define SI_EVPD 0x01 - u_int8_t page_code; - u_int8_t reserved; - u_int8_t length; - u_int8_t control; -}; - -struct scsi_inquiry_data -{ - uint8_t device; -#define SID_TYPE(inq_data) ((inq_data)->device & 0x1f) -#define SID_QUAL(inq_data) (((inq_data)->device & 0xE0) >> 5) -#define SID_QUAL_LU_CONNECTED 0x00 /* - * The specified peripheral device - * type is currently connected to - * logical unit. If the target cannot - * determine whether or not a physical - * device is currently connected, it - * shall also use this peripheral - * qualifier when returning the INQUIRY - * data. This peripheral qualifier - * does not mean that the device is - * ready for access by the initiator. - */ -#define SID_QUAL_LU_OFFLINE 0x01 /* - * The target is capable of supporting - * the specified peripheral device type - * on this logical unit; however, the - * physical device is not currently - * connected to this logical unit. - */ -#define SID_QUAL_RSVD 0x02 -#define SID_QUAL_BAD_LU 0x03 /* - * The target is not capable of - * supporting a physical device on - * this logical unit. For this - * peripheral qualifier the peripheral - * device type shall be set to 1Fh to - * provide compatibility with previous - * versions of SCSI. All other - * peripheral device type values are - * reserved for this peripheral - * qualifier. - */ -#define SID_QUAL_IS_VENDOR_UNIQUE(inq_data) ((SID_QUAL(inq_data) & 0x08) != 0) - uint8_t dev_qual2; -#define SID_QUAL2 0x7F -#define SID_IS_REMOVABLE(inq_data) (((inq_data)->dev_qual2 & 0x80) != 0) - uint8_t version; -#define SID_ANSI_REV(inq_data) ((inq_data)->version & 0x07) -#define SCSI_REV_0 0 -#define SCSI_REV_CCS 1 -#define SCSI_REV_2 2 -#define SCSI_REV_SPC 3 -#define SCSI_REV_SPC2 4 - -#define SID_ECMA 0x38 -#define SID_ISO 0xC0 - uint8_t response_format; -#define SID_AENC 0x80 -#define SID_TrmIOP 0x40 - uint8_t additional_length; - uint8_t reserved[2]; - uint8_t flags; -#define SID_SftRe 0x01 -#define SID_CmdQue 0x02 -#define SID_Linked 0x08 -#define SID_Sync 0x10 -#define SID_WBus16 0x20 -#define SID_WBus32 0x40 -#define SID_RelAdr 0x80 -#define SID_VENDOR_SIZE 8 - char vendor[SID_VENDOR_SIZE]; -#define SID_PRODUCT_SIZE 16 - char product[SID_PRODUCT_SIZE]; -#define SID_REVISION_SIZE 4 - char revision[SID_REVISION_SIZE]; - /* - * The following fields were taken from SCSI Primary Commands - 2 - * (SPC-2) Revision 14, Dated 11 November 1999 - */ -#define SID_VENDOR_SPECIFIC_0_SIZE 20 - u_int8_t vendor_specific0[SID_VENDOR_SPECIFIC_0_SIZE]; - /* - * An extension of SCSI Parallel Specific Values - */ -#define SID_SPI_IUS 0x01 -#define SID_SPI_QAS 0x02 -#define SID_SPI_CLOCK_ST 0x00 -#define SID_SPI_CLOCK_DT 0x04 -#define SID_SPI_CLOCK_DT_ST 0x0C -#define SID_SPI_MASK 0x0F - uint8_t spi3data; - uint8_t reserved2; - /* - * Version Descriptors, stored 2 byte values. - */ - uint8_t version1[2]; - uint8_t version2[2]; - uint8_t version3[2]; - uint8_t version4[2]; - uint8_t version5[2]; - uint8_t version6[2]; - uint8_t version7[2]; - uint8_t version8[2]; - - uint8_t reserved3[22]; - -#define SID_VENDOR_SPECIFIC_1_SIZE 160 - uint8_t vendor_specific1[SID_VENDOR_SPECIFIC_1_SIZE]; -}; - -static __inline uint32_t scsi_4btoul(uint8_t *bytes); -static __inline uint32_t -scsi_4btoul(uint8_t *bytes) -{ - return ((bytes[0] << 24)|(bytes[1] << 16)|(bytes[2] << 8)|bytes[3]); -} -/************************** Timer DataStructures ******************************/ -typedef struct timer_list ahd_timer_t; - -/********************************** Includes **********************************/ -/* Host template and function declarations referenced by the template. */ -#include "aic79xx_host.h" - -/* Core driver definitions */ -#include "aic79xx.h" - -/***************************** Timer Facilities *******************************/ -#define ahd_timer_init init_timer -#define ahd_timer_stop del_timer -typedef void ahd_linux_callback_t (u_long); -static __inline void -ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg) -{ - struct ahd_softc *ahd; - - ahd = (struct ahd_softc *)arg; - del_timer(timer); - timer->data = (u_long)arg; - timer->expires = jiffies + (usec * HZ)/1000000; - timer->function = (ahd_linux_callback_t*)func; - add_timer(timer); -} - -/***************************** SMP support ************************************/ -/* SAE */ -#include -/* -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,17) -#include -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93) -#include -#endif -*/ - -#define AIC79XX_DRIVER_VERSION "1.0.0" - -/**************************** Front End Queues ********************************/ -/* - * Data structure used to cast the Linux struct scsi_cmnd to something - * that allows us to use the queue macros. The linux structure has - * plenty of space to hold the links fields as required by the queue - * macros, but the queue macors require them to have the correct type. - */ -struct ahd_cmd_internal { - /* Area owned by the Linux scsi layer. */ - uint8_t private[offsetof(struct scsi_cmnd, SCp.Status)]; - union { - STAILQ_ENTRY(ahd_cmd) ste; - LIST_ENTRY(ahd_cmd) le; - TAILQ_ENTRY(ahd_cmd) tqe; - } links; - uint32_t end; -}; - -struct ahd_cmd { - union { - struct ahd_cmd_internal icmd; - struct scsi_cmnd scsi_cmd; - } un; -}; - -#define acmd_icmd(cmd) ((cmd)->un.icmd) -#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd) -#define acmd_links un.icmd.links - -/*************************** Device Data Structures ***************************/ -/* - * A per probed device structure used to deal with some error recovery - * scenarios that the Linux mid-layer code just doesn't know how to - * handle. The structure allocated for a device only becomes persistant - * after a successfully completed inquiry command to the target when - * that inquiry data indicates a lun is present. - */ -TAILQ_HEAD(ahd_busyq, ahd_cmd); -typedef enum { - AHD_DEV_UNCONFIGURED = 0x01, - AHD_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */ - AHD_DEV_TIMER_ACTIVE = 0x04, /* Our timer is active */ - AHD_DEV_ON_RUN_LIST = 0x08, /* Queued to be run later */ - AHD_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */ - AHD_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */ - AHD_DEV_PERIODIC_OTAG = 0x40 /* Send OTAG to prevent starvation */ -} ahd_dev_flags; - -struct ahd_linux_target; -struct ahd_linux_device { - TAILQ_ENTRY(ahd_linux_device) links; - struct ahd_busyq busyq; - - /* - * The number of transactions currently - * queued to the device. - */ - int active; - - /* - * The currently allowed number of - * transactions that can be queued to - * the device. Must be signed for - * conversion from tagged to untagged - * mode where the device may have more - * than one outstanding active transaction. - */ - int openings; - - /* - * A positive count indicates that this - * device's queue is halted. - */ - u_int qfrozen; - - /* - * Cumulative command counter. - */ - u_long commands_issued; - - /* - * The number of tagged transactions when - * running at our current opening level - * that have been successfully received by - * this device since the last QUEUE FULL. - */ - u_int tag_success_count; -#define AHD_TAG_SUCCESS_INTERVAL 50 - - ahd_dev_flags flags; - - /* - * Per device timer. - */ - struct timer_list timer; - - /* - * The high limit for the tags variable. - */ - u_int maxtags; - - /* - * The computed number of tags outstanding - * at the time of the last QUEUE FULL event. - */ - u_int tags_on_last_queuefull; - - /* - * How many times we have seen a queue full - * with the same number of tags. This is used - * to stop our adaptive queue depth algorithm - * on devices with a fixed number of tags. - */ - u_int last_queuefull_same_count; -#define AHD_LOCK_TAGS_COUNT 50 - - /* - * How many transactions have been queued - * without the device going idle. We use - * this statistic to determine when to issue - * an ordered tag to prevent transaction - * starvation. This statistic is only updated - * if the AHD_DEV_PERIODIC_OTAG flag is set - * on this device. - */ - u_int commands_since_idle_or_otag; -#define AHD_OTAG_THRESH 500 - - int lun; - struct ahd_linux_target *target; -}; - -struct ahd_linux_target { - struct ahd_linux_device *devices[AHD_NUM_LUNS]; - int channel; - int target; - int refcount; - struct ahd_transinfo last_tinfo; - struct ahd_softc *ahd; -}; - -/********************* Definitions Required by the Core ***********************/ -/* - * Number of SG segments we require. So long as the S/G segments for - * a particular transaction are allocated in a physically contiguous - * manner and are allocated below 4GB, the number of S/G segments is - * unrestricted. - */ -#define AHD_NSEG 128 - -/* - * Per-SCB OSM storage. - */ -struct scb_platform_data { - struct ahd_linux_device *dev; - bus_addr_t buf_busaddr; - uint32_t xfer_len; -/* SAE */ - uint32_t resid; /* Transfer residual */ -#if XEN_KILLED -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - uint32_t resid; /* Transfer residual */ -#endif -#endif -}; - -/* - * Define a structure used for each host adapter. All members are - * aligned on a boundary >= the size of the member to honor the - * alignment restrictions of the various platforms supported by - * this driver. - */ -TAILQ_HEAD(ahd_completeq, ahd_cmd); -struct ahd_platform_data { - /* - * Fields accessed from interrupt context. - */ - struct ahd_linux_target *targets[AHD_NUM_TARGETS]; - TAILQ_HEAD(, ahd_linux_device) device_runq; - struct ahd_completeq completeq; -/* SAE */ - spinlock_t spin_lock; - struct tasklet_struct runq_tasklet; -#if XEN_KILLED -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) - spinlock_t spin_lock; -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - struct tasklet_struct runq_tasklet; -#endif -#endif - u_int qfrozen; - struct timer_list reset_timer; -/* SAE: No semaphores */ -#if XEN_KILLED - struct semaphore eh_sem; -#endif - struct Scsi_Host *host; /* pointer to scsi host */ -#define AHD_LINUX_NOIRQ ((uint32_t)~0) - uint32_t irq; /* IRQ for this adapter */ - uint32_t bios_address; - uint32_t mem_busaddr; /* Mem Base Addr */ - bus_addr_t hw_dma_mask; -}; - -/************************** OS Utility Wrappers *******************************/ -#define printf printk -#define M_NOWAIT GFP_ATOMIC -#define M_WAITOK 0 -#define malloc(size, type, flags) kmalloc(size, flags) -#define free(ptr, type) kfree(ptr) - -static __inline void ahd_delay(long); -static __inline void -ahd_delay(long usec) -{ - /* - * udelay on Linux can have problems for - * multi-millisecond waits. Wait at most - * 1024us per call. - */ - while (usec > 0) { - udelay(usec % 1024); - usec -= 1024; - } -} - - -/***************************** Low Level I/O **********************************/ -#if defined(__powerpc__) || defined(__i386__) || defined(__ia64__) -#define MMAPIO -#endif - -static __inline uint8_t ahd_inb(struct ahd_softc * ahd, long port); -static __inline uint16_t ahd_inw_atomic(struct ahd_softc * ahd, long port); -static __inline void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val); -static __inline void ahd_outw_atomic(struct ahd_softc * ahd, - long port, uint16_t val); -static __inline void ahd_outsb(struct ahd_softc * ahd, long port, - uint8_t *, int count); -static __inline void ahd_insb(struct ahd_softc * ahd, long port, - uint8_t *, int count); - -static __inline uint8_t -ahd_inb(struct ahd_softc * ahd, long port) -{ - uint8_t x; -#ifdef MMAPIO - - if (ahd->tags[0] == BUS_SPACE_MEMIO) { - x = readb(ahd->bshs[0].maddr + port); - } else { - x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); - } -#else - x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); -#endif - mb(); - return (x); -} - -static __inline uint16_t -ahd_inw_atomic(struct ahd_softc * ahd, long port) -{ - uint8_t x; -#ifdef MMAPIO - - if (ahd->tags[0] == BUS_SPACE_MEMIO) { - x = readw(ahd->bshs[0].maddr + port); - } else { - x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); - } -#else - x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); -#endif - mb(); - return (x); -} - -static __inline void -ahd_outb(struct ahd_softc * ahd, long port, uint8_t val) -{ -#ifdef MMAPIO - if (ahd->tags[0] == BUS_SPACE_MEMIO) { - writeb(val, ahd->bshs[0].maddr + port); - } else { - outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF)); - } -#else - outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF)); -#endif - mb(); -} - -static __inline void -ahd_outw_atomic(struct ahd_softc * ahd, long port, uint16_t val) -{ -#ifdef MMAPIO - if (ahd->tags[0] == BUS_SPACE_MEMIO) { - writew(val, ahd->bshs[0].maddr + port); - } else { - outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF)); - } -#else - outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF)); -#endif - mb(); -} - -static __inline void -ahd_outsb(struct ahd_softc * ahd, long port, uint8_t *array, int count) -{ - int i; - - /* - * There is probably a more efficient way to do this on Linux - * but we don't use this for anything speed critical and this - * should work. - */ - for (i = 0; i < count; i++) - ahd_outb(ahd, port, *array++); -} - -static __inline void -ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count) -{ - int i; - - /* - * There is probably a more efficient way to do this on Linux - * but we don't use this for anything speed critical and this - * should work. - */ - for (i = 0; i < count; i++) - *array++ = ahd_inb(ahd, port); -} - -/**************************** Initialization **********************************/ -int ahd_linux_register_host(struct ahd_softc *, - Scsi_Host_Template *); - -uint64_t ahd_linux_get_memsize(void); - -/*************************** Pretty Printing **********************************/ -struct info_str { - char *buffer; - int length; - off_t offset; - int pos; -}; - -void ahd_format_transinfo(struct info_str *info, - struct ahd_transinfo *tinfo); - -/******************************** Locking *************************************/ -/* Lock protecting internal data structures */ -static __inline void ahd_lockinit(struct ahd_softc *); -static __inline void ahd_lock(struct ahd_softc *, unsigned long *flags); -static __inline void ahd_unlock(struct ahd_softc *, unsigned long *flags); - -/* Lock held during command compeletion to the upper layer */ -static __inline void ahd_done_lockinit(struct ahd_softc *); -static __inline void ahd_done_lock(struct ahd_softc *, unsigned long *flags); -static __inline void ahd_done_unlock(struct ahd_softc *, unsigned long *flags); - -/* Lock held during ahd_list manipulation and ahd softc frees */ -extern spinlock_t ahd_list_spinlock; -static __inline void ahd_list_lockinit(void); -static __inline void ahd_list_lock(unsigned long *flags); -static __inline void ahd_list_unlock(unsigned long *flags); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93) -static __inline void -ahd_lockinit(struct ahd_softc *ahd) -{ - spin_lock_init(&ahd->platform_data->spin_lock); -} - -static __inline void -ahd_lock(struct ahd_softc *ahd, unsigned long *flags) -{ - *flags = 0; - spin_lock_irqsave(&ahd->platform_data->spin_lock, *flags); -} - -static __inline void -ahd_unlock(struct ahd_softc *ahd, unsigned long *flags) -{ - spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags); -} - -static __inline void -ahd_done_lockinit(struct ahd_softc *ahd) -{ - /* We don't own the iorequest lock, so we don't initialize it. */ -} - -static __inline void -ahd_done_lock(struct ahd_softc *ahd, unsigned long *flags) -{ - *flags = 0; - spin_lock_irqsave(&io_request_lock, *flags); -} - -static __inline void -ahd_done_unlock(struct ahd_softc *ahd, unsigned long *flags) -{ - spin_unlock_irqrestore(&io_request_lock, *flags); -} - -static __inline void -ahd_list_lockinit() -{ - spin_lock_init(&ahd_list_spinlock); -} - -static __inline void -ahd_list_lock(unsigned long *flags) -{ - *flags = 0; - spin_lock_irqsave(&ahd_list_spinlock, *flags); -} - -static __inline void -ahd_list_unlock(unsigned long *flags) -{ - spin_unlock_irqrestore(&ahd_list_spinlock, *flags); -} - -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) */ - -ahd_lockinit(struct ahd_softc *ahd) -{ -} - -static __inline void -ahd_lock(struct ahd_softc *ahd, unsigned long *flags) -{ - *flags = 0; - save_flags(*flags); - cli(); -} - -static __inline void -ahd_unlock(struct ahd_softc *ahd, unsigned long *flags) -{ - restore_flags(*flags); -} - -ahd_done_lockinit(struct ahd_softc *ahd) -{ -} - -static __inline void -ahd_done_lock(struct ahd_softc *ahd, unsigned long *flags) -{ - /* - * The done lock is always held while - * the ahd lock is held so blocking - * interrupts again would have no effect. - */ -} - -static __inline void -ahd_done_unlock(struct ahd_softc *ahd, unsigned long *flags) -{ -} - -static __inline void -ahd_list_lockinit() -{ -} - -static __inline void -ahd_list_lock(unsigned long *flags) -{ - *flags = 0; - save_flags(*flags); - cli(); -} - -static __inline void -ahd_list_unlock(unsigned long *flags) -{ - restore_flags(*flags); -} -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) */ - -/******************************* PCI Definitions ******************************/ -/* - * PCIM_xxx: mask to locate subfield in register - * PCIR_xxx: config register offset - * PCIC_xxx: device class - * PCIS_xxx: device subclass - * PCIP_xxx: device programming interface - * PCIV_xxx: PCI vendor ID (only required to fixup ancient devices) - * PCID_xxx: device ID - */ -#define PCIR_DEVVENDOR 0x00 -#define PCIR_VENDOR 0x00 -#define PCIR_DEVICE 0x02 -#define PCIR_COMMAND 0x04 -#define PCIM_CMD_PORTEN 0x0001 -#define PCIM_CMD_MEMEN 0x0002 -#define PCIM_CMD_BUSMASTEREN 0x0004 -#define PCIM_CMD_MWRICEN 0x0010 -#define PCIM_CMD_PERRESPEN 0x0040 -#define PCIM_CMD_SERRESPEN 0x0100 -#define PCIR_STATUS 0x06 -#define PCIR_REVID 0x08 -#define PCIR_PROGIF 0x09 -#define PCIR_SUBCLASS 0x0a -#define PCIR_CLASS 0x0b -#define PCIR_CACHELNSZ 0x0c -#define PCIR_LATTIMER 0x0d -#define PCIR_HEADERTYPE 0x0e -#define PCIM_MFDEV 0x80 -#define PCIR_BIST 0x0f -#define PCIR_CAP_PTR 0x34 - -/* config registers for header type 0 devices */ -#define PCIR_MAPS 0x10 -#define PCIR_SUBVEND_0 0x2c -#define PCIR_SUBDEV_0 0x2e - -/****************************** PCI-X definitions *****************************/ -#define PCIXR_COMMAND 0x96 -#define PCIXR_DEVADDR 0x98 -#define PCIXM_DEVADDR_FNUM 0x0003 /* Function Number */ -#define PCIXM_DEVADDR_DNUM 0x00F8 /* Device Number */ -#define PCIXM_DEVADDR_BNUM 0xFF00 /* Bus Number */ -#define PCIXR_STATUS 0x9A -#define PCIXM_STATUS_64BIT 0x0001 /* Active 64bit connection to device. */ -#define PCIXM_STATUS_133CAP 0x0002 /* Device is 133MHz capable */ -#define PCIXM_STATUS_SCDISC 0x0004 /* Split Completion Discarded */ -#define PCIXM_STATUS_UNEXPSC 0x0008 /* Unexpected Split Completion */ -#define PCIXM_STATUS_CMPLEXDEV 0x0010 /* Device Complexity (set == bridge) */ -#define PCIXM_STATUS_MAXMRDBC 0x0060 /* Maximum Burst Read Count */ -#define PCIXM_STATUS_MAXSPLITS 0x0380 /* Maximum Split Transactions */ -#define PCIXM_STATUS_MAXCRDS 0x1C00 /* Maximum Cumulative Read Size */ -#define PCIXM_STATUS_RCVDSCEM 0x2000 /* Received a Split Comp w/Error msg */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -extern struct pci_driver aic79xx_pci_driver; -#endif - -typedef enum -{ - AHD_POWER_STATE_D0, - AHD_POWER_STATE_D1, - AHD_POWER_STATE_D2, - AHD_POWER_STATE_D3 -} ahd_power_state; - -void ahd_power_state_change(struct ahd_softc *ahd, - ahd_power_state new_state); - -/******************************* PCI Routines *********************************/ -/* - * We need to use the bios32.h routines if we are kernel version 2.1.92 or less. - */ -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,92) -#if defined(__sparc_v9__) || defined(__powerpc__) -#error "PPC and Sparc platforms are only support under 2.1.92 and above" -#endif -#include -#endif - -int ahd_linux_pci_probe(Scsi_Host_Template *); -int ahd_pci_map_registers(struct ahd_softc *ahd); -int ahd_pci_map_int(struct ahd_softc *ahd); - -static __inline uint32_t ahd_pci_read_config(ahd_dev_softc_t pci, - int reg, int width); - -static __inline uint32_t -ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width) -{ - switch (width) { - case 1: - { - uint8_t retval; - - pci_read_config_byte(pci, reg, &retval); - return (retval); - } - case 2: - { - uint16_t retval; - pci_read_config_word(pci, reg, &retval); - return (retval); - } - case 4: - { - uint32_t retval; - pci_read_config_dword(pci, reg, &retval); - return (retval); - } - default: - panic("ahd_pci_read_config: Read size too big"); - /* NOTREACHED */ - return (0); - } -} - -static __inline void ahd_pci_write_config(ahd_dev_softc_t pci, - int reg, uint32_t value, - int width); - -static __inline void -ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width) -{ - switch (width) { - case 1: - pci_write_config_byte(pci, reg, value); - break; - case 2: - pci_write_config_word(pci, reg, value); - break; - case 4: - pci_write_config_dword(pci, reg, value); - break; - default: - panic("ahd_pci_write_config: Write size too big"); - /* NOTREACHED */ - } -} - -static __inline int ahd_get_pci_function(ahd_dev_softc_t); -static __inline int -ahd_get_pci_function(ahd_dev_softc_t pci) -{ - return (PCI_FUNC(pci->devfn)); -} - -static __inline int ahd_get_pci_slot(ahd_dev_softc_t); -static __inline int -ahd_get_pci_slot(ahd_dev_softc_t pci) -{ - return (PCI_SLOT(pci->devfn)); -} - -static __inline int ahd_get_pci_bus(ahd_dev_softc_t); -static __inline int -ahd_get_pci_bus(ahd_dev_softc_t pci) -{ - return (pci->bus->number); -} - -static __inline void ahd_flush_device_writes(struct ahd_softc *); -static __inline void -ahd_flush_device_writes(struct ahd_softc *ahd) -{ - /* XXX Is this sufficient for all architectures??? */ - ahd_inb(ahd, INTSTAT); -} - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0) -#define pci_map_sg(pdev, sg_list, nseg, direction) (nseg) -#define pci_unmap_sg(pdev, sg_list, nseg, direction) -#define sg_dma_address(sg) (VIRT_TO_BUS((sg)->address)) -#define sg_dma_len(sg) ((sg)->length) -#define pci_map_single(pdev, buffer, bufflen, direction) \ - (VIRT_TO_BUS(buffer)) -#define pci_unmap_single(pdev, buffer, buflen, direction) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3) -#define ahd_pci_set_dma_mask pci_set_dma_mask -#else -/* - * Always "return" 0 for success. - */ -static inline int ahd_pci_set_dma_mask(struct pci_dev *dev_softc, u64 mask) -{ - dev_softc->dma_mask = mask; - return 0; -} -#endif -/*********************** Transaction Access Wrappers **************************/ -static __inline void ahd_set_transaction_status(struct scb *, uint32_t); -static __inline -void ahd_set_transaction_status(struct scb *scb, uint32_t status) -{ - scb->io_ctx->result &= ~(CAM_STATUS_MASK << 16); - scb->io_ctx->result |= status << 16; -} - -static __inline void ahd_set_scsi_status(struct scb *, uint32_t); -static __inline -void ahd_set_scsi_status(struct scb *scb, uint32_t status) -{ - scb->io_ctx->result &= ~0xFFFF; - scb->io_ctx->result |= status; -} - -static __inline uint32_t ahd_get_transaction_status(struct scb *); -static __inline -uint32_t ahd_get_transaction_status(struct scb *scb) -{ - return ((scb->io_ctx->result >> 16) & CAM_STATUS_MASK); -} - -static __inline uint32_t ahd_get_scsi_status(struct scb *); -static __inline -uint32_t ahd_get_scsi_status(struct scb *scb) -{ - return (scb->io_ctx->result & 0xFFFF); -} - -static __inline void ahd_set_transaction_tag(struct scb *, int, u_int); -static __inline -void ahd_set_transaction_tag(struct scb *scb, int enabled, u_int type) -{ - /* - * Nothing to do for linux as the incoming transaction - * has no concept of tag/non tagged, etc. - */ -} - -static __inline u_long ahd_get_transfer_length(struct scb *); -static __inline -u_long ahd_get_transfer_length(struct scb *scb) -{ - return (scb->platform_data->xfer_len); -} - -static __inline int ahd_get_transfer_dir(struct scb *); -static __inline -int ahd_get_transfer_dir(struct scb *scb) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,40) - return (scb->io_ctx->sc_data_direction); -#else - if (scb->io_ctx->bufflen == 0) - return (CAM_DIR_NONE); - - switch(scb->io_ctx->cmnd[0]) { - case 0x08: /* READ(6) */ - case 0x28: /* READ(10) */ - case 0xA8: /* READ(12) */ - return (CAM_DIR_IN); - case 0x0A: /* WRITE(6) */ - case 0x2A: /* WRITE(10) */ - case 0xAA: /* WRITE(12) */ - return (CAM_DIR_OUT); - default: - return (CAM_DIR_NONE); - } -#endif -} - -static __inline void ahd_set_residual(struct scb *, u_long); -static __inline -void ahd_set_residual(struct scb *scb, u_long resid) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - scb->io_ctx->resid = resid; -#else - scb->platform_data->resid = resid; -#endif -} - -static __inline void ahd_set_sense_residual(struct scb *, u_long); -static __inline -void ahd_set_sense_residual(struct scb *scb, u_long resid) -{ - /* This can't be reported in Linux */ -} - -static __inline u_long ahd_get_residual(struct scb *); -static __inline -u_long ahd_get_residual(struct scb *scb) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - return (scb->io_ctx->resid); -#else - return (scb->platform_data->resid); -#endif -} - -static __inline int ahd_perform_autosense(struct scb *); -static __inline -int ahd_perform_autosense(struct scb *scb) -{ - /* - * We always perform autosense in Linux. - * On other platforms this is set on a - * per-transaction basis. - */ - return (1); -} - -static __inline uint32_t -ahd_get_sense_bufsize(struct ahd_softc *ahd, struct scb *scb) -{ - return (sizeof(struct scsi_sense_data)); -} - -static __inline void ahd_notify_xfer_settings_change(struct ahd_softc *, - struct ahd_devinfo *); -static __inline void -ahd_notify_xfer_settings_change(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo) -{ - /* Nothing to do here for linux */ -} - -static __inline void ahd_platform_scb_free(struct ahd_softc *ahd, - struct scb *scb); -static __inline void -ahd_platform_scb_free(struct ahd_softc *ahd, struct scb *scb) -{ - ahd->flags &= ~AHD_RESOURCE_SHORTAGE; -} - -int ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg); -void ahd_platform_free(struct ahd_softc *ahd); -void ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb); -void ahd_freeze_simq(struct ahd_softc *ahd); -void ahd_release_simq(struct ahd_softc *ahd); -static __inline void ahd_freeze_scb(struct scb *scb); -static __inline void -ahd_freeze_scb(struct scb *scb) -{ - /* Noting to do here for linux */ -} - -void ahd_platform_set_tags(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo, ahd_queue_alg); -int ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, - char channel, int lun, u_int tag, - role_t role, uint32_t status); -void ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs); -void ahd_platform_flushwork(struct ahd_softc *ahd); -int ahd_softc_comp(struct ahd_softc *, struct ahd_softc *); -void ahd_done(struct ahd_softc*, struct scb*); -void ahd_send_async(struct ahd_softc *, char channel, - u_int target, u_int lun, ac_code, void *); -void ahd_print_path(struct ahd_softc *, struct scb *); -void ahd_platform_dump_card_state(struct ahd_softc *ahd); - -#ifdef CONFIG_PCI -#define AHD_PCI_CONFIG 1 -#else -#define AHD_PCI_CONFIG 0 -#endif -#define bootverbose aic79xx_verbose -extern int aic79xx_verbose; -#endif /* _AIC79XX_LINUX_H_ */ diff --git a/xen/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/xen/drivers/scsi/aic7xxx/aic79xx_osm_pci.c deleted file mode 100644 index 9381627f07..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Linux driver attachment glue for PCI based U320 controllers. - * - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm_pci.c#11 $ - */ - -#include "aic79xx_osm.h" -#include "aic79xx_inline.h" - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -struct pci_device_id -{ -}; -#endif - -static int ahd_linux_pci_dev_probe(struct pci_dev *pdev, - const struct pci_device_id *ent); -static int ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, - u_long *base, u_long *base2); -static int ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, - u_long *bus_addr, - uint8_t **maddr); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -static void ahd_linux_pci_dev_remove(struct pci_dev *pdev); - -/* We do our own ID filtering. So, grab all SCSI storage class devices. */ -static struct pci_device_id ahd_linux_pci_id_table[] = { - { - 0x9005, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_STORAGE_SCSI << 8, 0xFFFF00, 0 - }, - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table); - -struct pci_driver aic79xx_pci_driver = { - name: "aic79xx", - probe: ahd_linux_pci_dev_probe, - remove: ahd_linux_pci_dev_remove, - id_table: ahd_linux_pci_id_table -}; - -static void -ahd_linux_pci_dev_remove(struct pci_dev *pdev) -{ - struct ahd_softc *ahd; - u_long l; - - /* - * We should be able to just perform - * the free directly, but check our - * list for extra sanity. - */ - ahd_list_lock(&l); - ahd = ahd_find_softc((struct ahd_softc *)pdev->driver_data); - if (ahd != NULL) { - u_long s; - - ahd_lock(ahd, &s); - ahd_intr_enable(ahd, FALSE); - ahd_unlock(ahd, &s); - ahd_free(ahd); - } - ahd_list_unlock(&l); -} -#endif /* !LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) */ - -static int -ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - char buf[80]; - struct ahd_softc *ahd; - ahd_dev_softc_t pci; - struct ahd_pci_identity *entry; - char *name; - int error; - - /* - * Some BIOSen report the same device multiple times. - */ - TAILQ_FOREACH(ahd, &ahd_tailq, links) { - struct pci_dev *probed_pdev; - - probed_pdev = ahd->dev_softc; - if (probed_pdev->bus->number == pdev->bus->number - && probed_pdev->devfn == pdev->devfn) - break; - } - if (ahd != NULL) { - /* Skip duplicate. */ - return (-ENODEV); - } - - pci = pdev; - entry = ahd_find_pci_device(pci); - if (entry == NULL) - return (-ENODEV); - - /* - * Allocate a softc for this card and - * set it up for attachment by our - * common detect routine. - */ - sprintf(buf, "ahd_pci:%d:%d:%d", - ahd_get_pci_bus(pci), - ahd_get_pci_slot(pci), - ahd_get_pci_function(pci)); - name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); - if (name == NULL) - return (-ENOMEM); - strcpy(name, buf); - ahd = ahd_alloc(NULL, name); - if (ahd == NULL) - return (-ENOMEM); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - if (pci_enable_device(pdev)) { - ahd_free(ahd); - return (-ENODEV); - } - pci_set_master(pdev); - - if (sizeof(bus_addr_t) > 4) { - uint64_t memsize; - - memsize = ahd_linux_get_memsize(); - if (memsize >= 0x8000000000ULL - && ahd_pci_set_dma_mask(pdev, 0xFFFFFFFFFFFFFFFFULL) == 0) { - ahd->flags |= AHD_64BIT_ADDRESSING; - ahd->platform_data->hw_dma_mask = - (bus_addr_t)(0xFFFFFFFFFFFFFFFFULL&(bus_addr_t)~0); - } else if (memsize > 0x80000000ULL - && ahd_pci_set_dma_mask(pdev, 0x7FFFFFFFFFULL) == 0) { - ahd->flags |= AHD_39BIT_ADDRESSING; - ahd->platform_data->hw_dma_mask = - (bus_addr_t)(0x7FFFFFFFFFULL & (bus_addr_t)~0); - } - } -#endif - ahd->dev_softc = pci; - error = ahd_pci_config(ahd, entry); - if (error != 0) { - ahd_free(ahd); - return (-error); - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pdev->driver_data = ahd; - if (aic79xx_detect_complete) - ahd_linux_register_host(ahd, aic79xx_driver_template); -#endif - return (0); -} - -int -ahd_linux_pci_probe(Scsi_Host_Template *template) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - return (pci_module_init(&aic79xx_pci_driver)); -#else - struct pci_dev *pdev; - u_int class; - int found; - - /* If we don't have a PCI bus, we can't find any adapters. */ - if (pci_present() == 0) - return (0); - - found = 0; - pdev = NULL; - class = PCI_CLASS_STORAGE_SCSI << 8; - while ((pdev = pci_find_class(class, pdev)) != NULL) { - ahd_dev_softc_t pci; - int error; - - pci = pdev; - error = ahd_linux_pci_dev_probe(pdev, /*pci_devid*/NULL); - if (error == 0) - found++; - } - return (found); -#endif -} - -static int -ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base, - u_long *base2) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - *base = pci_resource_start(ahd->dev_softc, 0); - /* - * This is really the 3rd bar and should be at index 2, - * but the Linux PCI code doesn't know how to "count" 64bit - * bars. - */ - *base2 = pci_resource_start(ahd->dev_softc, 3); -#else - *base = ahd_pci_read_config(ahd->dev_softc, AHD_PCI_IOADDR0, 4); - *base2 = ahd_pci_read_config(ahd->dev_softc, AHD_PCI_IOADDR1, 4); - *base &= PCI_BASE_ADDRESS_IO_MASK; - *base2 &= PCI_BASE_ADDRESS_IO_MASK; -#endif - if (*base == 0 || *base2 == 0) - return (ENOMEM); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - if (check_region(*base, 256) != 0 - || check_region(*base2, 256) != 0) - return (ENOMEM); - else { - request_region(*base, 256, "aic79xx"); - request_region(*base2, 256, "aic79xx"); - } -#else - if (request_region(*base, 256, "aic79xx") == 0) - return (ENOMEM); - if (request_region(*base2, 256, "aic79xx") == 0) { - release_region(*base2, 256); - return (ENOMEM); - } -#endif - return (0); -} - -static int -ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, - u_long *bus_addr, - uint8_t **maddr) -{ - u_long start; - u_long base_page; - u_long base_offset; - int error; - - if ((ahd->chip & AHD_BUS_MASK) == AHD_PCIX - && (ahd->bugs & AHD_PCIX_MMAPIO_BUG) != 0) - return (ENOMEM); - - error = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - start = pci_resource_start(ahd->dev_softc, 1); - base_page = start & PAGE_MASK; - base_offset = start - base_page; -#else - start = ahd_pci_read_config(ahd->dev_softc, PCIR_MAPS+4, 4); - base_offset = start & PCI_BASE_ADDRESS_MEM_MASK; - base_page = base_offset & PAGE_MASK; - base_offset -= base_page; -#endif - if (start != 0) { - *bus_addr = start; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - if (request_mem_region(start, 0x1000, "aic79xx") == 0) - error = ENOMEM; -#endif - if (error == 0) { - *maddr = ioremap_nocache(base_page, base_offset + 256); - if (*maddr == NULL) { - error = ENOMEM; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - release_mem_region(start, 0x1000); -#endif - } else - *maddr += base_offset; - } - } else - error = ENOMEM; - return (error); -} - -int -ahd_pci_map_registers(struct ahd_softc *ahd) -{ - uint32_t command; - u_long base; - uint8_t *maddr; - int error; - - /* - * If its allowed, we prefer memory mapped access. - */ - command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, 4); - command &= ~(PCIM_CMD_PORTEN|PCIM_CMD_MEMEN); - base = 0; - maddr = NULL; -#ifdef MMAPIO - error = ahd_linux_pci_reserve_mem_region(ahd, &base, &maddr); - if (error == 0) { - ahd->platform_data->mem_busaddr = base; - ahd->tags[0] = BUS_SPACE_MEMIO; - ahd->bshs[0].maddr = maddr; - ahd->tags[1] = BUS_SPACE_MEMIO; - ahd->bshs[1].maddr = maddr + 0x100; - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, - command | PCIM_CMD_MEMEN, 4); - - /* - * Do a quick test to see if memory mapped - * I/O is functioning correctly. - */ - if (ahd_inb(ahd, HCNTRL) == 0xFF) { - - printf("aic79xx: PCI Device %d:%d:%d " - "failed memory mapped test\n", - ahd_get_pci_bus(ahd->dev_softc), - ahd_get_pci_slot(ahd->dev_softc), - ahd_get_pci_function(ahd->dev_softc)); - ahd->bshs[0].maddr = NULL; - maddr = NULL; - } else - command |= PCIM_CMD_MEMEN; - } else { - printf("aic79xx: PCI%d:%d:%d MEM region 0x%lx " - "unavailable. Cannot memory map device.\n", - ahd_get_pci_bus(ahd->dev_softc), - ahd_get_pci_slot(ahd->dev_softc), - ahd_get_pci_function(ahd->dev_softc), - base); - } -#endif - - if (maddr == NULL) { - u_long base2; - - error = ahd_linux_pci_reserve_io_regions(ahd, &base, &base2); - if (error == 0) { - ahd->tags[0] = BUS_SPACE_PIO; - ahd->tags[1] = BUS_SPACE_PIO; - ahd->bshs[0].ioport = base; - ahd->bshs[1].ioport = base2; - command |= PCIM_CMD_PORTEN; - } else { - printf("aic79xx: PCI%d:%d:%d IO regions 0x%lx and 0x%lx" - "unavailable. Cannot map device.\n", - ahd_get_pci_bus(ahd->dev_softc), - ahd_get_pci_slot(ahd->dev_softc), - ahd_get_pci_function(ahd->dev_softc), - base, base2); - } - } - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, 4); - return (error); -} - -int -ahd_pci_map_int(struct ahd_softc *ahd) -{ - int error; - - error = request_irq(ahd->dev_softc->irq, ahd_linux_isr, - SA_SHIRQ, "aic79xx", ahd); - if (error == 0) - ahd->platform_data->irq = ahd->dev_softc->irq; - - return (-error); -} - -void -ahd_power_state_change(struct ahd_softc *ahd, ahd_power_state new_state) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pci_set_power_state(ahd->dev_softc, new_state); -#else - uint32_t cap; - u_int cap_offset; - - /* - * Traverse the capability list looking for - * the power management capability. - */ - cap = 0; - cap_offset = ahd_pci_read_config(ahd->dev_softc, - PCIR_CAP_PTR, /*bytes*/1); - while (cap_offset != 0) { - - cap = ahd_pci_read_config(ahd->dev_softc, - cap_offset, /*bytes*/4); - if ((cap & 0xFF) == 1 - && ((cap >> 16) & 0x3) > 0) { - uint32_t pm_control; - - pm_control = ahd_pci_read_config(ahd->dev_softc, - cap_offset + 4, - /*bytes*/4); - pm_control &= ~0x3; - pm_control |= new_state; - ahd_pci_write_config(ahd->dev_softc, - cap_offset + 4, - pm_control, /*bytes*/2); - break; - } - cap_offset = (cap >> 8) & 0xFF; - } -#endif -} diff --git a/xen/drivers/scsi/aic7xxx/aic79xx_pci.c b/xen/drivers/scsi/aic7xxx/aic79xx_pci.c deleted file mode 100644 index b7bd3cc73d..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic79xx_pci.c +++ /dev/null @@ -1,792 +0,0 @@ -/* - * Product specific probe and attach routines for: - * aic7901 and aic7902 SCSI controllers - * - * Copyright (c) 1994-2001 Justin T. Gibbs. - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#32 $ - * - * $FreeBSD$ - */ - -#ifdef __linux__ -#include "aic79xx_osm.h" -#include "aic79xx_inline.h" -#else -#include -#include -#endif - -static __inline uint64_t -ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) -{ - uint64_t id; - - id = subvendor - | (subdevice << 16) - | ((uint64_t)vendor << 32) - | ((uint64_t)device << 48); - - return (id); -} - -#define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull -#define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull -#define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull - -#define ID_AIC7901 0x800F9005FFFF9005ull -#define ID_AIC7901_IROC 0x80089005FFFF9005ull -#define ID_AHA_29320 0x8000900500609005ull -#define ID_AHA_29320LP 0x8000900500409005ull - -#define ID_AIC7902 0x801F9005FFFF9005ull -#define ID_AIC7902_IROC 0x80189005FFFF9005ull -#define ID_AHA_39320 0x8010900500409005ull -#define ID_AHA_39320D 0x8011900500419005ull -#define ID_AHA_39320D_CPQ 0x8011900500AC0E11ull -#define ID_AIC7902_PCI_REV_A3 0x2 -#define ID_AIC7902_PCI_REV_A4 0x3 -#define ID_AIC7902_PCI_REV_B0 0xFF /* Rev Id not yet known. */ -#define SUBID_CPQ 0x0E11 - -#define DEVID_9005_TYPE(id) ((id) & 0xF) -#define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */ -#define DEVID_9005_TYPE_HBA_2EXT 0x1 /* 2 External Ports */ -#define DEVID_9005_TYPE_IROC 0x8 /* Raid(0,1,10) Card */ -#define DEVID_9005_TYPE_MB 0xF /* On Motherboard */ - -#define DEVID_9005_MFUNC(id) ((id) & 0x10) - -#define DEVID_9005_PACKETIZED(id) ((id) & 0x8000) - -#define SUBID_9005_TYPE(id) ((id) & 0xF) -#define SUBID_9005_TYPE_HBA 0x0 /* Standard Card */ -#define SUBID_9005_TYPE_MB 0xF /* On Motherboard */ - -#define SUBID_9005_AUTOTERM(id) (((id) & 0x10) == 0) - -#define SUBID_9005_LEGACYCONN_FUNC(id) ((id) & 0x20) - -#define SUBID_9005_SEEPTYPE(id) ((id) & 0x0C0) >> 6) -#define SUBID_9005_SEEPTYPE_NONE 0x0 -#define SUBID_9005_SEEPTYPE_4K 0x1 - -static ahd_device_setup_t ahd_aic7901_setup; -static ahd_device_setup_t ahd_aic7902_setup; - -struct ahd_pci_identity ahd_pci_ident_table [] = -{ - /* aic7901 based controllers */ - { - ID_AHA_29320, - ID_ALL_MASK, - "Adaptec 29320 Ultra320 SCSI adapter", - ahd_aic7901_setup - }, - { - ID_AHA_29320LP, - ID_ALL_MASK, - "Adaptec 29320LP Ultra320 SCSI adapter", - ahd_aic7901_setup - }, - /* aic7902 based controllers */ - { - ID_AHA_39320, - ID_ALL_MASK, - "Adaptec 39320 Ultra320 SCSI adapter", - ahd_aic7902_setup - }, - { - ID_AHA_39320D, - ID_ALL_MASK, - "Adaptec 39320D Ultra320 SCSI adapter", - ahd_aic7902_setup - }, - { - ID_AHA_39320D_CPQ, - ID_ALL_MASK, - "Adaptec (Compaq OEM) 39320D Ultra320 SCSI adapter", - ahd_aic7902_setup - }, - /* Generic chip probes for devices we don't know 'exactly' */ - { - ID_AIC7901 & ID_9005_GENERIC_MASK, - ID_9005_GENERIC_MASK, - "Adaptec aic7901 Ultra320 SCSI adapter", - ahd_aic7901_setup - }, - { - ID_AIC7902 & ID_9005_GENERIC_MASK, - ID_9005_GENERIC_MASK, - "Adaptec aic7902 Ultra320 SCSI adapter", - ahd_aic7902_setup - } -}; - -const u_int ahd_num_pci_devs = NUM_ELEMENTS(ahd_pci_ident_table); - -#define DEVCONFIG 0x40 -#define PCIXINITPAT 0x0000E000ul -#define PCIXINIT_PCI33_66 0x0000E000ul -#define PCIXINIT_PCIX50_66 0x0000C000ul -#define PCIXINIT_PCIX66_100 0x0000A000ul -#define PCIXINIT_PCIX100_133 0x00008000ul -#define PCI_BUS_MODES_INDEX(devconfig) \ - (((devconfig) & PCIXINITPAT) >> 13) -static const char *pci_bus_modes[] = -{ - "PCI bus mode unknown", - "PCI bus mode unknown", - "PCI bus mode unknown", - "PCI bus mode unknown", - "PCI-X 101-133Mhz", - "PCI-X 67-100Mhz", - "PCI-X 50-66Mhz", - "PCI 33 or 66Mhz" -}; - -#define TESTMODE 0x00000800ul -#define IRDY_RST 0x00000200ul -#define FRAME_RST 0x00000100ul -#define PCI64BIT 0x00000080ul -#define MRDCEN 0x00000040ul -#define ENDIANSEL 0x00000020ul -#define MIXQWENDIANEN 0x00000008ul -#define DACEN 0x00000004ul -#define STPWLEVEL 0x00000002ul -#define QWENDIANSEL 0x00000001ul - -#define DEVCONFIG1 0x44 -#define PREQDIS 0x01 - -#define CSIZE_LATTIME 0x0c -#define CACHESIZE 0x000000fful -#define LATTIME 0x0000ff00ul - -static int ahd_check_extport(struct ahd_softc *ahd); -static void ahd_configure_termination(struct ahd_softc *ahd, - u_int adapter_control); -static void ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat); - -struct ahd_pci_identity * -ahd_find_pci_device(ahd_dev_softc_t pci) -{ - uint64_t full_id; - uint16_t device; - uint16_t vendor; - uint16_t subdevice; - uint16_t subvendor; - struct ahd_pci_identity *entry; - u_int i; - - vendor = ahd_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); - device = ahd_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); - subvendor = ahd_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); - subdevice = ahd_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); - full_id = ahd_compose_id(device, - vendor, - subdevice, - subvendor); - - for (i = 0; i < ahd_num_pci_devs; i++) { - entry = &ahd_pci_ident_table[i]; - if (entry->full_id == (full_id & entry->id_mask)) { - /* Honor exclusion entries. */ - if (entry->name == NULL) - return (NULL); - return (entry); - } - } - return (NULL); -} - -int -ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) -{ - struct scb_data *shared_scb_data; - u_long l; - u_long s; - u_int command; - uint32_t devconfig; - uint16_t subvendor; - int error; - - shared_scb_data = NULL; - error = entry->setup(ahd); - if (error != 0) - return (error); - - ahd->description = entry->name; - devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); - if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) { - ahd->chip |= AHD_PCI; - /* Disable PCIX workarounds when running in PCI mode. */ - ahd->bugs &= ~AHD_PCIX_BUG_MASK; - } else { - ahd->chip |= AHD_PCIX; - } - ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)]; - - /* - * Record if this is a Compaq board. - */ - subvendor = ahd_pci_read_config(ahd->dev_softc, - PCIR_SUBVEND_0, /*bytes*/2); - if (subvendor == SUBID_CPQ) - ahd->flags |= AHD_CPQ_BOARD; - - ahd_power_state_change(ahd, AHD_POWER_STATE_D0); - - error = ahd_pci_map_registers(ahd); - if (error != 0) - return (error); - - /* - * If we need to support high memory, enable dual - * address cycles. This bit must be set to enable - * high address bit generation even if we are on a - * 64bit bus (PCI64BIT set in devconfig). - */ - if ((ahd->flags & (AHD_39BIT_ADDRESSING|AHD_64BIT_ADDRESSING)) != 0) { - uint32_t devconfig; - - if (bootverbose) - printf("%s: Enabling 39Bit Addressing\n", - ahd_name(ahd)); - devconfig = ahd_pci_read_config(ahd->dev_softc, - DEVCONFIG, /*bytes*/4); - devconfig |= DACEN; - ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, - devconfig, /*bytes*/4); - } - - /* Ensure busmastering is enabled */ - command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1); - command |= PCIM_CMD_BUSMASTEREN; - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/1); - - error = ahd_softc_init(ahd); - if (error != 0) - return (error); - - ahd->bus_intr = ahd_pci_intr; - - error = ahd_reset(ahd); - if (error != 0) - return (ENXIO); - - ahd->pci_cachesize = - ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, - /*bytes*/1) & CACHESIZE; - ahd->pci_cachesize *= 4; - - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - /* See if we have a SEEPROM and perform auto-term */ - error = ahd_check_extport(ahd); - if (error != 0) - return (error); - - /* Core initialization */ - error = ahd_init(ahd); - if (error != 0) - return (error); - - /* - * Allow interrupts now that we are completely setup. - */ - error = ahd_pci_map_int(ahd); - if (error != 0) - return (error); - - ahd_list_lock(&l); - /* - * Link this softc in with all other ahd instances. - */ - ahd_softc_insert(ahd); - - ahd_lock(ahd, &s); - ahd_intr_enable(ahd, TRUE); - ahd_unlock(ahd, &s); - - ahd_list_unlock(&l); - return (0); -} - -/* - * Check the external port logic for a serial eeprom - * and termination/cable detection contrls. - */ -static int -ahd_check_extport(struct ahd_softc *ahd) -{ - struct seeprom_config *sc; - u_int adapter_control; - int have_seeprom; - int error; - - sc = ahd->seep_config; - have_seeprom = ahd_acquire_seeprom(ahd); - if (have_seeprom) { - u_int start_addr; - - if (bootverbose) - printf("%s: Reading SEEPROM...", ahd_name(ahd)); - - /* Address is always in units of 16bit words */ - start_addr = (sizeof(*sc) / 2) * (ahd->channel - 'A'); - - error = ahd_read_seeprom(ahd, (uint16_t *)sc, - start_addr, sizeof(*sc)/2); - - if (error != 0) { - printf("Unable to read SEEPROM\n"); - have_seeprom = 0; - } else { - have_seeprom = ahd_verify_cksum(sc); - - if (bootverbose) { - if (have_seeprom == 0) - printf ("checksum error\n"); - else - printf ("done.\n"); - } - } - ahd_release_seeprom(ahd); - } - - if (!have_seeprom) { - u_int nvram_scb; - - /* - * Pull scratch ram settings and treat them as - * if they are the contents of an seeprom if - * the 'ADPT', 'BIOS', or 'ASPI' signature is found - * in SCB 0xFF. We manually compose the data as 16bit - * values to avoid endian issues. - */ - ahd_set_scbptr(ahd, 0xFF); - nvram_scb = ahd_inb_scbram(ahd, SCB_BASE + NVRAM_SCB_OFFSET); - printf("nvram_scb == 0x%x\n", nvram_scb); - printf("SCBPTR == 0x%x\n", ahd_get_scbptr(ahd)); - printf("Signature = %c%c%c%c\n", - ahd_inb_scbram(ahd, SCB_BASE + 0), - ahd_inb_scbram(ahd, SCB_BASE + 1), - ahd_inb_scbram(ahd, SCB_BASE + 2), - ahd_inb_scbram(ahd, SCB_BASE + 3)); - if (nvram_scb != 0xFF - && ((ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A' - && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'D' - && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P' - && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'T') - || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'B' - && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'I' - && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'O' - && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'S') - || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A' - && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'S' - && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P' - && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'I'))) { - uint16_t *sc_data; - int i; - - ahd_set_scbptr(ahd, nvram_scb); - sc_data = (uint16_t *)sc; - for (i = 0; i < 64; i += 2) - *sc_data++ = ahd_inw_scbram(ahd, SCB_BASE+i); - have_seeprom = ahd_verify_cksum(sc); - if (have_seeprom) - ahd->flags |= AHD_SCB_CONFIG_USED; - } - } - -#ifdef AHD_DEBUG - if (have_seeprom != 0 - && (ahd_debug & AHD_DUMP_SEEPROM) != 0) { - uint8_t *sc_data; - int i; - - printf("%s: Seeprom Contents:", ahd_name(ahd)); - sc_data = (uint8_t *)sc; - for (i = 0; i < (sizeof(*sc)); i += 2) - printf("\n\t0x%.4x", - sc_data[i] | (sc_data[i+1] << 8)); - printf("\n"); - } -#endif - - if (!have_seeprom) { - if (bootverbose) - printf("%s: No SEEPROM available.\n", ahd_name(ahd)); - ahd->flags |= AHD_USEDEFAULTS; - error = ahd_default_config(ahd); - adapter_control = CFAUTOTERM|CFSEAUTOTERM; - free(ahd->seep_config, M_DEVBUF); - ahd->seep_config = NULL; - } else { - error = ahd_parse_cfgdata(ahd, sc); - adapter_control = sc->adapter_control; - } - if (error != 0) - return (error); - - ahd_configure_termination(ahd, adapter_control); - - return (0); -} - -static void -ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control) -{ - int error; - u_int sxfrctl1; - uint8_t termctl; - uint32_t devconfig; - - devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); - devconfig &= ~STPWLEVEL; - if ((ahd->flags & AHD_STPWLEVEL_A) != 0) { - devconfig |= STPWLEVEL; - } - ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); - - /* Make sure current sensing is off. */ - if ((ahd->flags & AHD_CURRENT_SENSING) != 0) { - (void)ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0); - } - - /* - * Read to sense. Write to set. - */ - error = ahd_read_flexport(ahd, FLXADDR_TERMCTL, &termctl); - if ((adapter_control & CFAUTOTERM) == 0) { - if (bootverbose) - printf("%s: Manual Primary Termination\n", - ahd_name(ahd)); - termctl &= ~(FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH); - if ((adapter_control & CFSTERM) != 0) - termctl |= FLX_TERMCTL_ENPRILOW; - if ((adapter_control & CFWSTERM) != 0) - termctl |= FLX_TERMCTL_ENPRIHIGH; - } else if (error != 0) { - printf("%s: Primary Auto-Term Sensing failed! " - "Using Defaults.\n", ahd_name(ahd)); - termctl = FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH; - } - - if ((adapter_control & CFSEAUTOTERM) == 0) { - if (bootverbose) - printf("%s: Manual Secondary Termination\n", - ahd_name(ahd)); - termctl &= ~(FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH); - if ((adapter_control & CFSELOWTERM) != 0) - termctl |= FLX_TERMCTL_ENSECLOW; - if ((adapter_control & CFSEHIGHTERM) != 0) - termctl |= FLX_TERMCTL_ENSECHIGH; - } else if (error != 0) { - printf("%s: Secondary Auto-Term Sensing failed! " - "Using Defaults.\n", ahd_name(ahd)); - termctl |= FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH; - } - - /* - * Now set the termination based on what we found. - */ - sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN; - if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) { - ahd->flags |= AHD_TERM_ENB_A; - sxfrctl1 |= STPWEN; - } - /* Must set the latch once in order to be effective. */ - ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN); - ahd_outb(ahd, SXFRCTL1, sxfrctl1); - - error = ahd_write_flexport(ahd, FLXADDR_TERMCTL, termctl); - if (error != 0) { - printf("%s: Unable to set termination settings!\n", - ahd_name(ahd)); - } else if (bootverbose) { - printf("%s: Primary High byte termination %sabled\n", - ahd_name(ahd), - (termctl & FLX_TERMCTL_ENPRIHIGH) ? "En" : "Dis"); - - printf("%s: Primary Low byte termination %sabled\n", - ahd_name(ahd), - (termctl & FLX_TERMCTL_ENPRILOW) ? "En" : "Dis"); - - printf("%s: Secondary High byte termination %sabled\n", - ahd_name(ahd), - (termctl & FLX_TERMCTL_ENSECHIGH) ? "En" : "Dis"); - - printf("%s: Secondary Low byte termination %sabled\n", - ahd_name(ahd), - (termctl & FLX_TERMCTL_ENSECLOW) ? "En" : "Dis"); - } - return; -} - -#define DPE 0x80 -#define SSE 0x40 -#define RMA 0x20 -#define RTA 0x10 -#define STA 0x08 -#define DPR 0x01 - -static const char *split_status_source[] = -{ - "DFF0", - "DFF1", - "OVLY", - "CMC", -}; - -static const char *pci_status_source[] = -{ - "DFF0", - "DFF1", - "SG", - "CMC", - "OVLY", - "NONE", - "MSI", - "TARG" -}; - -static const char *split_status_strings[] = -{ - "%s: Received split response in %s.\n" - "%s: Received split completion error message in %s\n", - "%s: Receive overrun in %s\n", - "%s: Count not complete in %s\n", - "%s: Split completion data bucket in %s\n", - "%s: Split completion address error in %s\n", - "%s: Split completion byte count error in %s\n", - "%s: Signaled Target-abort to early terminate a split in %s\n", -}; - -static const char *pci_status_strings[] = -{ - "%s: Data Parity Error has been reported via PERR# in %s\n", - "%s: Target initial wait state error in %s\n", - "%s: Split completion read data parity error in %s\n", - "%s: Split completion address attribute parity error in %s\n", - "%s: Received a Target Abort in %s\n", - "%s: Received a Master Abort in %s\n", - "%s: Signal System Error Detected in %s\n", - "%s: Address or Write Phase Parity Error Detected in %s.\n" -}; - -void -ahd_pci_intr(struct ahd_softc *ahd) -{ - uint8_t pci_status[8]; - ahd_mode_state saved_modes; - u_int pci_status1; - u_int intstat; - u_int i; - u_int reg; - - intstat = ahd_inb(ahd, INTSTAT); - - if ((intstat & SPLTINT) != 0) - ahd_pci_split_intr(ahd, intstat); - - if ((intstat & PCIINT) == 0) - return; - - printf("%s: PCI error Interrupt\n", ahd_name(ahd)); - saved_modes = ahd_save_modes(ahd); - ahd_dump_card_state(ahd); - ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); - for (i = 0, reg = DF0PCISTAT; i < 8; i++, reg++) { - - if (i == 5) - continue; - pci_status[i] = ahd_inb(ahd, reg); - /* Clear latched errors. So our interupt deasserts. */ - ahd_outb(ahd, reg, pci_status[i]); - } - - for (i = 0; i < 8; i++) { - u_int bit; - - if (i == 5) - continue; - - for (bit = 0; bit < 8; bit++) { - - if ((pci_status[i] & (0x1 << bit)) != 0) { - static const char *s; - - s = pci_status_strings[bit]; - if (i == 7/*TARG*/ && bit == 3) - s = "%s: Signal Target Abort\n"; - printf(s, ahd_name(ahd), pci_status_source[i]); - } - } - } - pci_status1 = ahd_pci_read_config(ahd->dev_softc, - PCIR_STATUS + 1, /*bytes*/1); - ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, - pci_status1, /*bytes*/1); - ahd_restore_modes(ahd, saved_modes); - ahd_unpause(ahd); -} - -static void -ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat) -{ - uint8_t split_status[4]; - uint8_t split_status1[4]; - uint8_t sg_split_status[2]; - uint8_t sg_split_status1[2]; - ahd_mode_state saved_modes; - u_int i; - uint16_t pcix_status; - - /* - * Check for splits in all modes. Modes 0 and 1 - * additionally have SG engine splits to look at. - */ - pcix_status = ahd_pci_read_config(ahd->dev_softc, PCIXR_STATUS, - /*bytes*/2); - printf("%s: PCI Split Interrupt - PCI-X status = 0x%x\n", - ahd_name(ahd), pcix_status); - saved_modes = ahd_save_modes(ahd); - for (i = 0; i < 4; i++) { - ahd_set_modes(ahd, i, i); - - split_status[i] = ahd_inb(ahd, DCHSPLTSTAT0); - split_status1[i] = ahd_inb(ahd, DCHSPLTSTAT1); - /* Clear latched errors. So our interupt deasserts. */ - ahd_outb(ahd, DCHSPLTSTAT0, split_status[i]); - ahd_outb(ahd, DCHSPLTSTAT1, split_status1[i]); - if (i != 0) - continue; - sg_split_status[i] = ahd_inb(ahd, SGSPLTSTAT0); - sg_split_status1[i] = ahd_inb(ahd, SGSPLTSTAT1); - /* Clear latched errors. So our interupt deasserts. */ - ahd_outb(ahd, SGSPLTSTAT0, sg_split_status[i]); - ahd_outb(ahd, SGSPLTSTAT1, sg_split_status1[i]); - } - - for (i = 0; i < 4; i++) { - u_int bit; - - for (bit = 0; bit < 8; bit++) { - - if ((split_status[i] & (0x1 << bit)) != 0) { - static const char *s; - - s = split_status_strings[bit]; - printf(s, ahd_name(ahd), - split_status_source[i]); - } - - if (i != 0) - continue; - - if ((sg_split_status[i] & (0x1 << bit)) != 0) { - static const char *s; - - s = split_status_strings[bit]; - printf(s, ahd_name(ahd), "SG"); - } - } - } - /* - * Clear PCI-X status bits. - */ - ahd_pci_write_config(ahd->dev_softc, PCIXR_STATUS, - pcix_status, /*bytes*/2); - ahd_restore_modes(ahd, saved_modes); -} - -static int -ahd_aic7901_setup(struct ahd_softc *ahd) -{ - ahd_dev_softc_t pci; - - pci = ahd->dev_softc; - ahd->channel = 'A'; - ahd->chip = AHD_AIC7901; - ahd->features = AHD_AIC7901_FE; - return (0); -} - -static int -ahd_aic7902_setup(struct ahd_softc *ahd) -{ - ahd_dev_softc_t pci; - u_int rev; - u_int devconfig1; - - pci = ahd->dev_softc; - rev = ahd_pci_read_config(pci, PCIR_REVID, /*bytes*/1); - if (rev < ID_AIC7902_PCI_REV_A3) { - printf("%s: Unable to attach to unsupported chip revision %d\n", - ahd_name(ahd), rev); - ahd_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/1); - return (ENXIO); - } - if (rev < ID_AIC7902_PCI_REV_B0) { - /* - * Pending request assertion does not work on the A if we have - * DMA requests outstanding on both channels. See H2A3 Razors - * #327 and #365. - */ - devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); - ahd_pci_write_config(pci, DEVCONFIG1, - devconfig1|PREQDIS, /*bytes*/1); - devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); - /* - * Enable A series workarounds. - */ - ahd->bugs |= AHD_SENT_SCB_UPDATE_BUG|AHD_ABORT_LQI_BUG - | AHD_PKT_BITBUCKET_BUG|AHD_LONG_SETIMO_BUG - | AHD_NLQICRC_DELAYED_BUG|AHD_SCSIRST_BUG - | AHD_LQO_ATNO_BUG|AHD_AUTOFLUSH_BUG - | AHD_CLRLQO_AUTOCLR_BUG|AHD_PCIX_MMAPIO_BUG - | AHD_PCIX_CHIPRST_BUG|AHD_PKTIZED_STATUS_BUG; - if (rev < ID_AIC7902_PCI_REV_A4) - ahd->bugs |= AHD_PCIX_ARBITER_BUG|AHD_PCIX_SPLIT_BUG; - } - - ahd->channel = ahd_get_pci_function(pci) + 'A'; - ahd->chip = AHD_AIC7902; - ahd->features = AHD_AIC7902_FE; - return (0); -} diff --git a/xen/drivers/scsi/aic7xxx/aic79xx_proc.c b/xen/drivers/scsi/aic7xxx/aic79xx_proc.c deleted file mode 100644 index a9b05d4fe6..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic79xx_proc.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * String handling code courtesy of Gerard Roudier's - * sym driver. - * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#7 $ - */ -#include "aic79xx_osm.h" -#include "aic79xx_inline.h" - -static void copy_mem_info(struct info_str *info, char *data, int len); -static int copy_info(struct info_str *info, char *fmt, ...); -static u_int scsi_calc_syncsrate(u_int period_factor); -static void ahd_dump_target_state(struct ahd_softc *ahd, - struct info_str *info, - u_int our_id, char channel, - u_int target_id, u_int target_offset); -static void ahd_dump_device_state(struct info_str *info, - struct ahd_linux_device *dev); -static int ahd_proc_write_seeprom(struct ahd_softc *ahd, - char *buffer, int length); - -static void -copy_mem_info(struct info_str *info, char *data, int len) -{ - if (info->pos + len > info->offset + info->length) - len = info->offset + info->length - info->pos; - - if (info->pos + len < info->offset) { - info->pos += len; - return; - } - - if (info->pos < info->offset) { - off_t partial; - - partial = info->offset - info->pos; - data += partial; - info->pos += partial; - len -= partial; - } - - if (len > 0) { - memcpy(info->buffer, data, len); - info->pos += len; - info->buffer += len; - } -} - -static int -copy_info(struct info_str *info, char *fmt, ...) -{ - va_list args; - char buf[256]; - int len; - - va_start(args, fmt); - len = vsprintf(buf, fmt, args); - va_end(args); - - copy_mem_info(info, buf, len); - return (len); -} - -/* - * Table of syncrates that don't follow the "divisible by 4" - * rule. This table will be expanded in future SCSI specs. - */ -static struct { - u_int period_factor; - u_int period; /* in 100ths of ns */ -} scsi_syncrates[] = { - { 0x08, 625 }, /* FAST-160 */ - { 0x09, 1250 }, /* FAST-80 */ - { 0x0a, 2500 }, /* FAST-40 40MHz */ - { 0x0b, 3030 }, /* FAST-40 33MHz */ - { 0x0c, 5000 } /* FAST-20 */ -}; - -/* - * Return the frequency in kHz corresponding to the given - * sync period factor. - */ -static u_int -scsi_calc_syncsrate(u_int period_factor) -{ - int i; - int num_syncrates; - - num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]); - /* See if the period is in the "exception" table */ - for (i = 0; i < num_syncrates; i++) { - - if (period_factor == scsi_syncrates[i].period_factor) { - /* Period in kHz */ - return (100000000 / scsi_syncrates[i].period); - } - } - - /* - * Wasn't in the table, so use the standard - * 4 times conversion. - */ - return (10000000 / (period_factor * 4 * 10)); -} - -void -ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo) -{ - u_int speed; - u_int freq; - u_int mb; - - speed = 3300; - freq = 0; - if (tinfo->offset != 0) { - freq = scsi_calc_syncsrate(tinfo->period); - speed = freq; - } - speed *= (0x01 << tinfo->width); - mb = speed / 1000; - if (mb > 0) - copy_info(info, "%d.%03dMB/s transfers", mb, speed % 1000); - else - copy_info(info, "%dKB/s transfers", speed); - - if (freq != 0) { - copy_info(info, " (%d.%03dMHz%s, offset %d", - freq / 1000, freq % 1000, - (tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0 - ? " DT" : "", tinfo->offset); - } - - if (tinfo->width > 0) { - if (freq != 0) { - copy_info(info, ", "); - } else { - copy_info(info, " ("); - } - copy_info(info, "%dbit)", 8 * (0x01 << tinfo->width)); - } else if (freq != 0) { - copy_info(info, ")"); - } - copy_info(info, "\n"); -} - -static void -ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info, - u_int our_id, char channel, u_int target_id, - u_int target_offset) -{ - struct ahd_linux_target *targ; - struct ahd_initiator_tinfo *tinfo; - struct ahd_tmode_tstate *tstate; - int lun; - - tinfo = ahd_fetch_transinfo(ahd, channel, our_id, - target_id, &tstate); - copy_info(info, "Channel %c Target %d Negotiation Settings\n", - channel, target_id); - copy_info(info, "\tUser: "); - ahd_format_transinfo(info, &tinfo->user); - targ = ahd->platform_data->targets[target_offset]; - if (targ == NULL) - return; - - copy_info(info, "\tGoal: "); - ahd_format_transinfo(info, &tinfo->goal); - copy_info(info, "\tCurr: "); - ahd_format_transinfo(info, &tinfo->curr); - - for (lun = 0; lun < AHD_NUM_LUNS; lun++) { - struct ahd_linux_device *dev; - - dev = targ->devices[lun]; - - if (dev == NULL) - continue; - - ahd_dump_device_state(info, dev); - } -} - -static void -ahd_dump_device_state(struct info_str *info, struct ahd_linux_device *dev) -{ - copy_info(info, "\tChannel %c Target %d Lun %d Settings\n", - dev->target->channel + 'A', dev->target->target, dev->lun); - - copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued); - copy_info(info, "\t\tCommands Active %d\n", dev->active); - copy_info(info, "\t\tCommand Openings %d\n", dev->openings); - copy_info(info, "\t\tMax Tagged Openings %d\n", dev->maxtags); - copy_info(info, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen); -} - -static int -ahd_proc_write_seeprom(struct ahd_softc *ahd, char *buffer, int length) -{ - ahd_mode_state saved_modes; - int have_seeprom; - u_long s; - int paused; - int written; - - /* Default to failure. */ - written = -EINVAL; - ahd_lock(ahd, &s); - paused = ahd_is_paused(ahd); - if (!paused) - ahd_pause(ahd); - - saved_modes = ahd_save_modes(ahd); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - if (length != sizeof(struct seeprom_config)) { - printf("ahd_proc_write_seeprom: incorrect buffer size\n"); - goto done; - } - - have_seeprom = ahd_verify_cksum((struct seeprom_config*)buffer); - if (have_seeprom == 0) { - printf("ahd_proc_write_seeprom: cksum verification failed\n"); - goto done; - } - - have_seeprom = ahd_acquire_seeprom(ahd); - if (!have_seeprom) { - printf("ahd_proc_write_seeprom: No Serial EEPROM\n"); - goto done; - } else { - u_int start_addr; - - if (ahd->seep_config == NULL) { - ahd->seep_config = malloc(sizeof(*ahd->seep_config), - M_DEVBUF, M_NOWAIT); - if (ahd->seep_config == NULL) { - printf("aic79xx: Unable to allocate serial " - "eeprom buffer. Write failing\n"); - goto done; - } - } - printf("aic79xx: Writing Serial EEPROM\n"); - start_addr = 32 * (ahd->channel - 'A'); - ahd_write_seeprom(ahd, (u_int16_t *)buffer, start_addr, - sizeof(struct seeprom_config)/2); - ahd_read_seeprom(ahd, (uint16_t *)ahd->seep_config, - start_addr, sizeof(struct seeprom_config)/2); - ahd_release_seeprom(ahd); - written = length; - } - -done: - ahd_restore_modes(ahd, saved_modes); - if (!paused) - ahd_unpause(ahd); - ahd_unlock(ahd, &s); - return (written); -} -/* - * Return information to handle /proc support for the driver. - */ -int -ahd_linux_proc_info(char *buffer, char **start, off_t offset, - int length, int hostno, int inout) -{ - struct ahd_softc *ahd; - struct info_str info; - char ahd_info[256]; - u_long l; - u_int max_targ; - u_int i; - int retval; - - retval = -EINVAL; - ahd_list_lock(&l); - TAILQ_FOREACH(ahd, &ahd_tailq, links) { - if (ahd->platform_data->host->host_no == hostno) - break; - } - - if (ahd == NULL) - goto done; - - /* Has data been written to the file? */ - if (inout == TRUE) { - retval = ahd_proc_write_seeprom(ahd, buffer, length); - goto done; - } - - if (start) - *start = buffer; - - info.buffer = buffer; - info.length = length; - info.offset = offset; - info.pos = 0; - - copy_info(&info, "Adaptec AIC79xx driver version: %s\n", - AIC79XX_DRIVER_VERSION); - ahd_controller_info(ahd, ahd_info); - copy_info(&info, "%s\n\n", ahd_info); - - if (ahd->seep_config == NULL) - copy_info(&info, "No Serial EEPROM\n"); - else { - copy_info(&info, "Serial EEPROM:\n"); - for (i = 0; i < sizeof(*ahd->seep_config)/2; i++) { - if (((i % 8) == 0) && (i != 0)) { - copy_info(&info, "\n"); - } - copy_info(&info, "0x%.4x ", - ((uint16_t*)ahd->seep_config)[i]); - } - copy_info(&info, "\n"); - } - copy_info(&info, "\n"); - - max_targ = 15; - if ((ahd->features & AHD_WIDE) == 0) - max_targ = 7; - - for (i = 0; i <= max_targ; i++) { - - ahd_dump_target_state(ahd, &info, ahd->our_id, 'A', - /*target_id*/i, /*target_offset*/i); - } - retval = info.pos > info.offset ? info.pos - info.offset : 0; -done: - ahd_list_unlock(&l); - return (retval); -} diff --git a/xen/drivers/scsi/aic7xxx/aic79xx_reg.h b/xen/drivers/scsi/aic7xxx/aic79xx_reg.h deleted file mode 100644 index 45852b5221..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic79xx_reg.h +++ /dev/null @@ -1,1357 +0,0 @@ -/* - * DO NOT EDIT - This file is automatically generated - * from the following source files: - * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#42 $ - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#34 $ - */ - -#define MODE_PTR 0x00 -#define DST_MODE 0x70 -#define SRC_MODE 0x07 - -#define INTSTAT 0x01 -#define INT_PEND 0xff -#define HWERRINT 0x80 -#define BRKADRINT 0x40 -#define SWTMINT 0x20 -#define PCIINT 0x10 -#define SCSIINT 0x08 -#define SEQINT 0x04 -#define CMDCMPLT 0x02 -#define SPLTINT 0x01 - -#define SEQINTCODE 0x02 -#define PCIX_ARBITOR_WW 0x19 -#define ENTERING_NONPACK 0x18 -#define MONITORDRAIN 0x17 -#define SNAPSHOTCLRCHN 0x16 -#define CFG4OVERRUN 0x15 -#define STATUS_OVERRUN 0x14 -#define CFG4ISTAT_INTR 0x13 -#define INVALID_SEQINT 0x12 -#define ILLEGAL_PHASE 0x11 -#define DUMP_CARD_STATE 0x10 -#define NO_FREE_FIFO 0x0f -#define OUT_OF_RANGE 0x0e -#define NO_FREE_SCB 0x0d -#define SCB_MISMATCH 0x0c -#define MISSED_BUSFREE 0x0b -#define MKMSG_FAILED 0x0a -#define DATA_OVERRUN 0x09 -#define BAD_STATUS 0x08 -#define HOST_MSG_LOOP 0x07 -#define PDATA_REINIT 0x06 -#define IGN_WIDE_RES 0x05 -#define NO_MATCH 0x04 -#define PROTO_VIOLATION 0x03 -#define SEND_REJECT 0x02 -#define BAD_PHASE 0x01 - -#define CLRINT 0x03 -#define CLRBRKADRINT 0x40 -#define CLRSWTMINT 0x20 -#define CLRSCSIINT 0x08 -#define CLRSEQINT 0x04 -#define CLRCMDINT 0x02 -#define CLRSPLTINT 0x01 - -#define ERROR 0x04 -#define CIOPARERR 0x80 -#define MPARERR 0x20 -#define DPARERR 0x10 -#define SQPARERR 0x08 -#define ILLOPCODE 0x04 -#define DSCTMOUT 0x02 - -#define CLRERR 0x04 -#define CLRCIOPARERR 0x80 -#define CLRMPARERR 0x20 -#define CLRDPARERR 0x10 -#define CLRSQPARERR 0x08 -#define CLRILLOPCODE 0x04 -#define CLRDSCTMOUT 0x02 - -#define HCNTRL 0x05 -#define POWRDN 0x40 -#define SWINT 0x10 -#define HCNTRL3 0x08 -#define PAUSE 0x04 -#define INTEN 0x02 -#define CHIPRST 0x01 -#define CHIPRSTACK 0x01 - -#define HNSCB_QOFF 0x06 - -#define HESCB_QOFF 0x08 - -#define HS_MAILBOX 0x0b -#define HOST_TQINPOS 0x80 - -#define SEQINTSTAT 0x0c -#define SEQ_SWTMRTO 0x10 -#define SEQ_SEQINT 0x08 -#define SEQ_SCSIINT 0x04 -#define SEQ_PCIINT 0x02 -#define SEQ_SPLTINT 0x01 - -#define SNSCB_QOFF 0x10 - -#define SESCB_QOFF 0x12 - -#define SDSCB_QOFF 0x14 - -#define QOFF_CTLSTA 0x16 -#define EMPTY_SCB_AVAIL 0x80 -#define NEW_SCB_AVAIL 0x40 -#define SDSCB_ROLLOVR 0x20 -#define HS_MAILBOX_ACT 0x10 -#define SCB_QSIZE 0x0f -#define SCB_QSIZE_16384 0x0c -#define SCB_QSIZE_8192 0x0b -#define SCB_QSIZE_4096 0x0a -#define SCB_QSIZE_2048 0x09 -#define SCB_QSIZE_1024 0x08 -#define SCB_QSIZE_512 0x07 -#define SCB_QSIZE_256 0x06 -#define SCB_QSIZE_128 0x05 -#define SCB_QSIZE_64 0x04 -#define SCB_QSIZE_32 0x03 -#define SCB_QSIZE_16 0x02 -#define SCB_QSIZE_8 0x01 -#define SCB_QSIZE_4 0x00 - -#define INTCTL 0x18 -#define SWTMINTMASK 0x80 -#define SWTMINTEN 0x40 -#define SWTIMER_START 0x20 -#define AUTOCLRCMDINT 0x10 -#define PCIINTEN 0x08 -#define SCSIINTEN 0x04 -#define SEQINTEN 0x02 -#define SPLTINTEN 0x01 - -#define DFCNTRL 0x19 -#define SCSIENACK 0x20 -#define DIRECTIONACK 0x04 -#define FIFOFLUSHACK 0x02 -#define DIRECTIONEN 0x01 - -#define DSCOMMAND0 0x19 -#define CACHETHEN 0x80 -#define DPARCKEN 0x40 -#define MPARCKEN 0x20 -#define EXTREQLCK 0x10 -#define CIOPARCKEN 0x01 - -#define DFSTATUS 0x1a -#define PRELOAD_AVAIL 0x80 -#define PKT_PRELOAD_AVAIL 0x40 -#define MREQPEND 0x10 -#define HDONE 0x08 -#define DFTHRESH 0x04 -#define FIFOFULL 0x02 -#define FIFOEMP 0x01 - -#define SG_CACHE_SHADOW 0x1b -#define ODD_SEG 0x04 -#define LAST_SEG 0x02 -#define LAST_SEG_DONE 0x01 - -#define ARBCTL 0x1b -#define RESET_HARB 0x80 -#define RETRY_SWEN 0x08 -#define USE_TIME 0x07 - -#define SG_CACHE_PRE 0x1b - -#define LQIN 0x20 - -#define TYPEPTR 0x20 - -#define TAGPTR 0x21 - -#define LUNPTR 0x22 - -#define DATALENPTR 0x23 - -#define STATLENPTR 0x24 - -#define CMDLENPTR 0x25 - -#define ATTRPTR 0x26 - -#define FLAGPTR 0x27 - -#define CMDPTR 0x28 - -#define QNEXTPTR 0x29 - -#define IDPTR 0x2a - -#define ABRTBYTEPTR 0x2b - -#define ABRTBITPTR 0x2c - -#define LUNLEN 0x30 - -#define CDBLIMIT 0x31 - -#define MAXCMD 0x32 - -#define MAXCMDCNT 0x33 - -#define LQRSVD01 0x34 - -#define LQRSVD16 0x35 - -#define LQRSVD17 0x36 - -#define CMDRSVD0 0x37 - -#define LQCTL0 0x38 -#define LQITARGCLT 0xc0 -#define LQIINITGCLT 0x30 -#define LQ0TARGCLT 0x0c -#define LQ0INITGCLT 0x03 - -#define LQCTL1 0x38 -#define PCI2PCI 0x04 -#define SINGLECMD 0x02 -#define ABORTPENDING 0x01 - -#define SCSBIST0 0x39 -#define GSBISTERR 0x40 -#define GSBISTDONE 0x20 -#define GSBISTRUN 0x10 -#define OSBISTERR 0x04 -#define OSBISTDONE 0x02 -#define OSBISTRUN 0x01 - -#define LQCTL2 0x39 -#define LQIRETRY 0x80 -#define LQICONTINUE 0x40 -#define LQITOIDLE 0x20 -#define LQIPAUSE 0x10 -#define LQORETRY 0x08 -#define LQOCONTINUE 0x04 -#define LQOTOIDLE 0x02 -#define LQOPAUSE 0x01 - -#define SCSBIST1 0x3a -#define NTBISTERR 0x04 -#define NTBISTDONE 0x02 -#define NTBISTRUN 0x01 - -#define SCSISEQ0 0x3a -#define TEMODEO 0x80 -#define ENSELO 0x40 -#define ENARBO 0x20 -#define FORCEBUSFREE 0x10 -#define SCSIRSTO 0x01 - -#define SCSISEQ1 0x3b - -#define SXFRCTL0 0x3c -#define DFON 0x80 -#define DFPEXP 0x40 -#define BIOSCANCELEN 0x10 -#define SPIOEN 0x08 - -#define BUSINITID 0x3c - -#define DLCOUNT 0x3c - -#define SXFRCTL1 0x3d -#define BITBUCKET 0x80 -#define ENSACHK 0x40 -#define ENSPCHK 0x20 -#define STIMESEL 0x18 -#define ENSTIMER 0x04 -#define ACTNEGEN 0x02 -#define STPWEN 0x01 - -#define BUSTARGID 0x3e - -#define SXFRCTL2 0x3e -#define AUTORSTDIS 0x10 -#define CMDDMAEN 0x08 -#define ASU 0x07 - -#define DFFSTAT 0x3f -#define FIFO1FREE 0x20 -#define FIFO0FREE 0x10 -#define CURRFIFO 0x01 - -#define SCSISIGO 0x40 -#define CDO 0x80 -#define IOO 0x40 -#define MSGO 0x20 -#define ATNO 0x10 -#define SELO 0x08 -#define BSYO 0x04 -#define REQO 0x02 -#define ACKO 0x01 - -#define MULTARGID 0x40 - -#define SCSISIGI 0x41 -#define ATNI 0x10 -#define SELI 0x08 -#define BSYI 0x04 -#define REQI 0x02 -#define ACKI 0x01 - -#define SCSIPHASE 0x42 -#define STATUS_PHASE 0x20 -#define COMMAND_PHASE 0x10 -#define MSG_IN_PHASE 0x08 -#define MSG_OUT_PHASE 0x04 -#define DATA_PHASE_MASK 0x03 -#define DATA_IN_PHASE 0x02 -#define DATA_OUT_PHASE 0x01 - -#define SCSIDAT0_IMG 0x43 - -#define SCSIDAT 0x44 - -#define SCSIBUS 0x46 - -#define TARGIDIN 0x48 -#define CLKOUT 0x80 -#define TARGID 0x0f - -#define SELID 0x49 -#define SELID_MASK 0xf0 -#define ONEBIT 0x08 - -#define SBLKCTL 0x4a -#define DIAGLEDEN 0x80 -#define DIAGLEDON 0x40 -#define ENAB40 0x08 -#define ENAB20 0x04 -#define SELWIDE 0x02 - -#define OPTIONMODE 0x4a -#define BIOSCANCTL 0x80 -#define AUTOACKEN 0x40 -#define BIASCANCTL 0x20 -#define BUSFREEREV 0x10 -#define ENDGFORMCHK 0x04 -#define OPTIONMODE_DEFAULTS 0x02 -#define AUTO_MSGOUT_DE 0x02 - -#define SSTAT0 0x4b -#define TARGET 0x80 -#define SELDO 0x40 -#define SELDI 0x20 -#define SELINGO 0x10 -#define IOERR 0x08 -#define OVERRUN 0x04 -#define SPIORDY 0x02 -#define ARBDO 0x01 - -#define CLRSINT0 0x4b -#define CLRSELDO 0x40 -#define CLRSELDI 0x20 -#define CLRSELINGO 0x10 -#define CLRIOERR 0x08 -#define CLROVERRUN 0x04 -#define CLRSPIORDY 0x02 -#define CLRARBDO 0x01 - -#define SIMODE0 0x4b -#define ENSELDO 0x40 -#define ENSELDI 0x20 -#define ENSELINGO 0x10 -#define ENIOERR 0x08 -#define ENOVERRUN 0x04 -#define ENSPIORDY 0x02 -#define ENARBDO 0x01 - -#define CLRSINT1 0x4c -#define CLRSELTIMEO 0x80 -#define CLRATNO 0x40 -#define CLRSCSIRSTI 0x20 -#define CLRBUSFREE 0x08 -#define CLRSCSIPERR 0x04 -#define CLRSTRB2FAST 0x02 -#define CLRREQINIT 0x01 - -#define SSTAT1 0x4c -#define SELTO 0x80 -#define ATNTARG 0x40 -#define SCSIRSTI 0x20 -#define PHASEMIS 0x10 -#define BUSFREE 0x08 -#define SCSIPERR 0x04 -#define STRB2FAST 0x02 -#define REQINIT 0x01 - -#define SSTAT2 0x4d -#define BUSFREE_DFF1 0xc0 -#define BUSFREETIME 0xc0 -#define BUSFREE_DFF0 0x80 -#define BUSFREE_LQO 0x40 -#define NONPACKREQ 0x20 -#define EXP_ACTIVE 0x10 -#define BSYX 0x08 -#define WIDE_RES 0x04 -#define SDONE 0x02 -#define DMADONE 0x01 - -#define CLRSINT2 0x4d -#define CLRNONPACKREQ 0x20 -#define CLRWIDE_RES 0x04 -#define CLRSDONE 0x02 -#define CLRDMADONE 0x01 - -#define SIMODE2 0x4d -#define ENWIDE_RES 0x04 -#define ENSDONE 0x02 -#define ENDMADONE 0x01 - -#define PERRDIAG 0x4e -#define HIZERO 0x80 -#define HIPERR 0x40 -#define PREVPHASE 0x20 -#define PARITYERR 0x10 -#define AIPERR 0x08 -#define CRCERR 0x04 -#define DGFORMERR 0x02 -#define DTERR 0x01 - -#define LQISTATE 0x4e - -#define SOFFCNT 0x4f - -#define LQOSTATE 0x4f - -#define LQISTAT0 0x50 -#define LQIATNQAS 0x20 -#define LQICRCT1 0x10 -#define LQICRCT2 0x08 -#define LQIBADLQT 0x04 -#define LQIATNLQ 0x02 -#define LQIATNCMD 0x01 - -#define CLRLQIINTO 0x50 -#define CLRLQIATNQAS 0x20 -#define CLRLQICRCT1 0x10 -#define CLRLQICRCT2 0x08 -#define CLRLQIBADLQT 0x04 -#define CLRLQIATNLQ 0x02 -#define CLRLQIATNCMD 0x01 - -#define LQIMODE0 0x50 -#define ENLQIATNQASK 0x20 -#define ENLQICRCT1 0x10 -#define ENLQICRCT2 0x08 -#define ENLQIBADLQT 0x04 -#define ENLQIATNLQ 0x02 -#define ENLQIATNCMD 0x01 - -#define LQIMODE1 0x51 -#define ENLQIPHASE_LQ 0x80 -#define ENLQIPHASE_NLQ 0x40 -#define ENLIQABORT 0x20 -#define ENLQICRCI_LQ 0x10 -#define ENLQICRCI_NLQ 0x08 -#define ENLQIBADLQI 0x04 -#define ENLQIOVERI_LQ 0x02 -#define ENLQIOVERI_NLQ 0x01 - -#define LQISTAT1 0x51 -#define LQIPHASE_LQ 0x80 -#define LQIPHASE_NLQ 0x40 -#define LQIABORT 0x20 -#define LQICRCI_LQ 0x10 -#define LQICRCI_NLQ 0x08 -#define LQIBADLQI 0x04 -#define LQIOVERI_LQ 0x02 -#define LQIOVERI_NLQ 0x01 - -#define CLRLQIINT1 0x51 -#define CLRLQIPHASE_LQ 0x80 -#define CLRLQIPHASE_NLQ 0x40 -#define CLRLIQABORT 0x20 -#define CLRLQICRCI_LQ 0x10 -#define CLRLQICRCI_NLQ 0x08 -#define CLRLQIBADLQI 0x04 -#define CLRLQIOVERI_LQ 0x02 -#define CLRLQIOVERI_NLQ 0x01 - -#define LQISTAT2 0x52 -#define PACKETIZED 0x80 -#define LQIPHASE_OUTPKT 0x40 -#define LQIWORKONLQ 0x20 -#define LQIWAITFIFO 0x10 -#define LQISTOPPKT 0x08 -#define LQISTOPLQ 0x04 -#define LQISTOPCMD 0x02 -#define LQIGSAVAIL 0x01 - -#define SSTAT3 0x53 -#define NTRAMPERR 0x02 -#define OSRAMPERR 0x01 - -#define SIMODE3 0x53 -#define ENNTRAMPERR 0x02 -#define ENOSRAMPERR 0x01 - -#define CLRSINT3 0x53 -#define CLRNTRAMPERR 0x02 -#define CLROSRAMPERR 0x01 - -#define LQOMODE0 0x54 -#define ENLQOTARGSCBPERR 0x10 -#define ENLQOSTOPT2 0x08 -#define ENLQOATNLQ 0x04 -#define ENLQOATNPKT 0x02 -#define ENLQOTCRC 0x01 - -#define LQOSTAT0 0x54 -#define LQOTARGSCBPERR 0x10 -#define LQOSTOPT2 0x08 -#define LQOATNLQ 0x04 -#define LQOATNPKT 0x02 -#define LQOTCRC 0x01 - -#define CLRLQOINT0 0x54 -#define CLRLQOTARGSCBPERR 0x10 -#define CLRLQOSTOPT2 0x08 -#define CLRLQOATNLQ 0x04 -#define CLRLQOATNPKT 0x02 -#define CLRLQOTCRC 0x01 - -#define LQOSTAT1 0x55 -#define LQOINITSCBPERR 0x10 -#define LQOSTOPI2 0x08 -#define LQOBADQAS 0x04 -#define LQOBUSFREE 0x02 -#define LQOPHACHGINPKT 0x01 - -#define CLRLQOINT1 0x55 -#define CLRLQOINITSCBPERR 0x10 -#define CLRLQOSTOPI2 0x08 -#define CLRLQOBADQAS 0x04 -#define CLRLQOBUSFREE 0x02 -#define CLRLQOPHACHGINPKT 0x01 - -#define LQOMODE1 0x55 -#define ENLQOINITSCBPERR 0x10 -#define ENLQOSTOPI2 0x08 -#define ENLQOBADQAS 0x04 -#define ENLQOBUSFREE 0x02 -#define ENLQOPHACHGINPKT 0x01 - -#define LQOSTAT2 0x56 -#define LQOPKT 0xe0 -#define LQOWAITFIFO 0x10 -#define LQOPHACHGOUTPKT 0x02 -#define LQOSTOP0 0x01 - -#define OS_SPACE_CNT 0x56 - -#define SIMODE1 0x57 -#define ENSELTIMO 0x80 -#define ENATNTARG 0x40 -#define ENSCSIRST 0x20 -#define ENPHASEMIS 0x10 -#define ENBUSFREE 0x08 -#define ENSCSIPERR 0x04 -#define ENSTRB2FAST 0x02 -#define ENREQINIT 0x01 - -#define GSFIFO 0x58 - -#define DFFSXFRCTL 0x5a -#define CLRSHCNT 0x04 -#define CLRCHN 0x02 -#define RSTCHN 0x01 - -#define NEXTSCB 0x5a - -#define CLRSEQINTSRC 0x5b -#define CLRCTXTDONE 0x40 -#define CLRSAVEPTRS 0x20 -#define CLRCFG4DATA 0x10 -#define CLRCFG4ISTAT 0x08 -#define CLRCFG4TSTAT 0x04 -#define CLRCFG4ICMD 0x02 -#define CLRCFG4TCMD 0x01 - -#define SEQINTSRC 0x5b -#define CTXTDONE 0x40 -#define SAVEPTRS 0x20 -#define CFG4DATA 0x10 -#define CFG4ISTAT 0x08 -#define CFG4TSTAT 0x04 -#define CFG4ICMD 0x02 -#define CFG4TCMD 0x01 - -#define CURRSCB 0x5c - -#define SEQIMODE 0x5c -#define ENCTXTDONE 0x40 -#define ENSAVEPTRS 0x20 -#define ENCFG4DATA 0x10 -#define ENCFG4ISTAT 0x08 -#define ENCFG4TSTAT 0x04 -#define ENCFG4ICMD 0x02 -#define ENCFG4TCMD 0x01 - -#define MDFFSTAT 0x5d -#define LASTSDONE 0x10 -#define SHVALID 0x08 -#define DLZERO 0x04 -#define DATAINFIFO 0x02 -#define FIFOFREE 0x01 - -#define CRCCONTROL 0x5d -#define CRCVALCHKEN 0x40 - -#define DFFTAG 0x5e - -#define LASTSCB 0x5e - -#define SCSITEST 0x5e -#define CNTRTEST 0x08 -#define SEL_TXPLL_DEBUG 0x04 - -#define IOPDNCTL 0x5f -#define DISABLE_OE 0x80 -#define PDN_IDIST 0x04 -#define PDN_DIFFSENSE 0x01 - -#define SHADDR 0x60 - -#define NEGOADDR 0x60 - -#define DGRPCRCI 0x60 - -#define NEGPERIOD 0x61 - -#define PACKCRCI 0x62 - -#define NEGOFFSET 0x62 - -#define NEGPPROPTS 0x63 -#define PPROPT_PACE 0x08 -#define PPROPT_QAS 0x04 -#define PPROPT_DT 0x02 -#define PPROPT_IUT 0x01 - -#define NEGCONOPTS 0x64 -#define ENAIP 0x08 -#define ENAUTOATNI 0x04 -#define ENAUTOATNO 0x02 -#define WIDEXFER 0x01 - -#define ANNEXCOL 0x65 - -#define ANNEXDAT 0x66 - -#define IOWNID 0x67 - -#define PLL960CTL0 0x68 - -#define SHCNT 0x68 - -#define TOWNID 0x69 - -#define PLL960CTL1 0x69 - -#define PLL960CNT0 0x6a - -#define XSIG 0x6a - -#define SELOID 0x6b - -#define PLL400CTL0 0x6c -#define PLL_VCOSEL 0x80 -#define PLL_PWDN 0x40 -#define PLL_NS 0x30 -#define PLL_ENLUD 0x08 -#define PLL_ENLPF 0x04 -#define PLL_DLPF 0x02 -#define PLL_ENFBM 0x01 - -#define FAIRNESS 0x6c - -#define PLL400CTL1 0x6d -#define PLL_CNTEN 0x80 -#define PLL_CNTCLR 0x40 -#define PLL_RST 0x01 - -#define PLL400CNT0 0x6e - -#define UNFAIRNESS 0x6e - -#define HADDR 0x70 - -#define HODMAADR 0x70 - -#define HODMACNT 0x78 - -#define HCNT 0x78 - -#define HODMAEN 0x7a - -#define SGHADDR 0x7c - -#define SCBHADDR 0x7c - -#define SGHCNT 0x84 - -#define SCBHCNT 0x84 - -#define DFF_THRSH 0x88 -#define WR_DFTHRSH 0x70 -#define WR_DFTHRSH_MAX 0x70 -#define WR_DFTHRSH_90 0x60 -#define WR_DFTHRSH_85 0x50 -#define WR_DFTHRSH_75 0x40 -#define WR_DFTHRSH_63 0x30 -#define WR_DFTHRSH_50 0x20 -#define WR_DFTHRSH_25 0x10 -#define RD_DFTHRSH 0x07 -#define RD_DFTHRSH_MAX 0x07 -#define RD_DFTHRSH_90 0x06 -#define RD_DFTHRSH_85 0x05 -#define RD_DFTHRSH_75 0x04 -#define RD_DFTHRSH_63 0x03 -#define RD_DFTHRSH_50 0x02 -#define RD_DFTHRSH_25 0x01 -#define WR_DFTHRSH_MIN 0x00 -#define RD_DFTHRSH_MIN 0x00 - -#define ROMADDR 0x8a - -#define ROMCNTRL 0x8d -#define ROMOP 0xe0 -#define ROMSPD 0x18 -#define REPEAT 0x02 -#define RDY 0x01 - -#define ROMDATA 0x8e - -#define CMCRXMSG0 0x90 - -#define ROENABLE 0x90 -#define MSIROEN 0x20 -#define OVLYROEN 0x10 -#define CMCROEN 0x08 -#define SGROEN 0x04 -#define DCH1ROEN 0x02 -#define DCH0ROEN 0x01 - -#define OVLYRXMSG0 0x90 - -#define DCHRXMSG0 0x90 - -#define OVLYRXMSG1 0x91 - -#define NSENABLE 0x91 -#define MSINSEN 0x20 -#define OVLYNSEN 0x10 -#define CMCNSEN 0x08 -#define SGNSEN 0x04 -#define DCH1NSEN 0x02 -#define DCH0NSEN 0x01 - -#define DCHRXMSG1 0x91 - -#define CMCRXMSG1 0x91 - -#define DCHRXMSG2 0x92 - -#define OVLYRXMSG2 0x92 - -#define CMCRXMSG2 0x92 - -#define OST 0x92 - -#define DCHRXMSG3 0x93 - -#define CMCRXMSG3 0x93 - -#define PCIXCTL 0x93 -#define SERRPULSE 0x80 -#define UNEXPSCIEN 0x20 -#define SPLTSMADIS 0x10 -#define SPLTSTADIS 0x08 -#define SRSPDPEEN 0x04 -#define TSCSERREN 0x02 -#define CMPABCDIS 0x01 - -#define OVLYRXMSG3 0x93 - -#define OVLYSEQBCNT 0x94 - -#define CMCSEQBCNT 0x94 - -#define DCHSEQBCNT 0x94 - -#define CMCSPLTSTAT0 0x96 - -#define OVLYSPLTSTAT0 0x96 - -#define DCHSPLTSTAT0 0x96 - -#define DCHSPLTSTAT1 0x97 - -#define CMCSPLTSTAT1 0x97 - -#define OVLYSPLTSTAT1 0x97 - -#define SGRXMSG0 0x98 -#define CDNUM 0xf8 -#define CFNUM 0x07 - -#define SLVSPLTOUTADR0 0x98 -#define LOWER_ADDR 0x7f - -#define SGRXMSG1 0x99 -#define CBNUM 0xff - -#define SLVSPLTOUTADR1 0x99 -#define REQ_DNUM 0xf8 -#define REQ_FNUM 0x07 - -#define SGRXMSG2 0x9a -#define MINDEX 0xff - -#define SLVSPLTOUTADR2 0x9a -#define REQ_BNUM 0xff - -#define SGRXMSG3 0x9b -#define MCLASS 0x0f - -#define SLVSPLTOUTADR3 0x9b -#define TAG_NUM 0x1f -#define RLXORD 0x10 - -#define SGSEQBCNT 0x9c - -#define SLVSPLTOUTATTR0 0x9c -#define LOWER_BCNT 0xff - -#define SLVSPLTOUTATTR1 0x9d -#define CMPLT_DNUM 0xf8 -#define CMPLT_FNUM 0x07 - -#define SLVSPLTOUTATTR2 0x9e -#define CMPLT_BNUM 0xff - -#define SGSPLTSTAT0 0x9e -#define STAETERM 0x80 -#define SCBCERR 0x40 -#define SCADERR 0x20 -#define SCDATBUCKET 0x10 -#define CNTNOTCMPLT 0x08 -#define RXOVRUN 0x04 -#define RXSCEMSG 0x02 -#define RXSPLTRSP 0x01 - -#define SFUNCT 0x9f -#define TEST_GROUP 0xf0 -#define TEST_NUM 0x0f - -#define SGSPLTSTAT1 0x9f -#define RXDATABUCKET 0x01 - -#define DF0PCISTAT 0xa0 - -#define REG0 0xa0 - -#define DF1PCISTAT 0xa1 - -#define SGPCISTAT 0xa2 - -#define REG1 0xa2 - -#define CMCPCISTAT 0xa3 - -#define OVLYPCISTAT 0xa4 -#define SCAAPERR 0x08 -#define RDPERR 0x04 - -#define REG2 0xa4 - -#define SG_STATE 0xa6 -#define FETCH_INPROG 0x04 -#define LOADING_NEEDED 0x02 -#define SEGS_AVAIL 0x01 - -#define MSIPCISTAT 0xa6 -#define RMA 0x20 -#define RTA 0x10 -#define CLRPENDMSI 0x08 -#define DPR 0x01 - -#define TARGPCISTAT 0xa6 -#define DPE 0x80 -#define SSE 0x40 -#define STA 0x08 -#define TWATERR 0x02 - -#define DATA_COUNT_ODD 0xa7 - -#define SCBPTR 0xa8 - -#define CCSCBACNT 0xab - -#define SCBAUTOPTR 0xab -#define AUSCBPTR_EN 0x80 -#define SCBPTR_ADDR 0x38 -#define SCBPTR_OFF 0x07 - -#define CCSGADDR 0xac - -#define CCSCBADDR 0xac - -#define CCSCBADR_BK 0xac - -#define CMC_RAMBIST 0xad -#define SG_ELEMENT_SIZE 0x80 -#define SCBRAMBIST_FAIL 0x40 -#define SG_BIST_FAIL 0x20 -#define SG_BIST_EN 0x10 -#define CMC_BUFFER_BIST_FAIL 0x02 -#define CMC_BUFFER_BIST_EN 0x01 - -#define CCSGCTL 0xad -#define CCSGDONE 0x80 -#define SG_CACHE_AVAIL 0x10 -#define CCSGEN 0x08 -#define SG_FETCH_REQ 0x02 -#define CCSGRESET 0x01 - -#define CCSCBCTL 0xad -#define CCSCBDONE 0x80 -#define ARRDONE 0x40 -#define CCARREN 0x10 -#define CCSCBEN 0x08 -#define CCSCBDIR 0x04 -#define CCSCBRESET 0x01 - -#define CCSGRAM 0xb0 - -#define FLEXADR 0xb0 - -#define CCSCBRAM 0xb0 - -#define FLEXCNT 0xb3 - -#define FLEXDMASTAT 0xb5 -#define FLEXDMAERR 0x02 -#define FLEXDMADONE 0x01 - -#define FLEXDATA 0xb6 - -#define BRDDAT 0xb8 - -#define BRDCTL 0xb9 -#define FLXARBACK 0x80 -#define FLXARBREQ 0x40 -#define BRDADDR 0x38 -#define BRDEN 0x04 -#define BRDRW 0x02 -#define BRDSTB 0x01 - -#define SEEADR 0xba - -#define SEEDAT 0xbc - -#define SEECTL 0xbe -#define SEEOP_ERASE 0x70 -#define SEEOPCODE 0x70 -#define SEEOP_READ 0x60 -#define SEEOP_WRITE 0x50 -#define SEEOP_EWEN 0x40 -#define SEEOP_WALL 0x40 -#define SEEOP_ERAL 0x40 -#define SEEOP_EWDS 0x40 -#define SEERST 0x02 -#define SEESTART 0x01 - -#define SEESTAT 0xbe -#define INIT_DONE 0x80 -#define LDALTID_L 0x08 -#define SEEARBACK 0x04 -#define SEEBUSY 0x02 - -#define SCBCNT 0xbf - -#define DFWADDR 0xc0 - -#define DSPFLTRCTL 0xc0 -#define FLTRDISABLE 0x20 -#define EDGESENSE 0x10 -#define DSPFCNTSEL 0x0f - -#define CLRSEQINTSTAT 0xc0 -#define CLRSEQ_SWTMRTO 0x10 -#define CLRSEQ_SEQINT 0x08 -#define CLRSEQ_SCSIINT 0x04 -#define CLRSEQ_PCIINT 0x02 -#define CLRSEQ_SPLTINT 0x01 - -#define DSPDATACTL 0xc1 -#define BYPASSENAB 0x80 -#define DESQDIS 0x10 -#define RCVROFFSTDIS 0x04 -#define XMITOFFSTDIS 0x02 - -#define DFRADDR 0xc2 - -#define DSPREQCTL 0xc2 -#define MANREQCTL 0xc0 -#define MANREQDLY 0x3f - -#define DSPACKCTL 0xc3 -#define MANACKCTL 0xc0 -#define MANACKDLY 0x3f - -#define DFDAT 0xc4 - -#define DSPSELECT 0xc4 -#define AUTOINCEN 0x80 -#define DSPSEL 0x1f - -#define WRTBIASCTL 0xc5 -#define AUTOXBCDIS 0x80 -#define XMITMANVAL 0x3f - -#define RCVRBIOSCTL 0xc6 -#define AUTORBCDIS 0x80 -#define RCVRMANVAL 0x3f - -#define WRTBIASCALC 0xc7 - -#define DFPTRS 0xc8 - -#define RCVRBIASCALC 0xc8 - -#define DFDBCTL 0xc8 -#define DFF_CIO_WR_RDY 0x20 -#define DFF_CIO_RD_RDY 0x10 -#define DFF_DIR_ERR 0x08 -#define DFF_RAMBIST_FAIL 0x04 -#define DFF_RAMBIST_DONE 0x02 -#define DFF_RAMBIST_EN 0x01 - -#define DFBKPTR 0xc9 - -#define SKEWCALC 0xc9 - -#define DFSCNT 0xcc - -#define DFBCNT 0xce - -#define OVLYADDR 0xd4 - -#define SEQCTL0 0xd6 -#define PERRORDIS 0x80 -#define PAUSEDIS 0x40 -#define FAILDIS 0x20 -#define FASTMODE 0x10 -#define BRKADRINTEN 0x08 -#define STEP 0x04 -#define SEQRESET 0x02 -#define LOADRAM 0x01 - -#define SEQCTL1 0xd7 -#define OVRLAY_DATA_CHK 0x08 -#define RAMBIST_DONE 0x04 -#define RAMBIST_FAIL 0x02 -#define RAMBIST_EN 0x01 - -#define FLAGS 0xd8 -#define ZERO 0x02 -#define CARRY 0x01 - -#define SEQINTCTL 0xd9 -#define INTVEC1DSL 0x80 -#define INT1_CONTEXT 0x20 -#define SCS_SEQ_INT1M1 0x10 -#define SCS_SEQ_INT1M0 0x08 -#define INTMASK 0x06 -#define IRET 0x01 - -#define SEQRAM 0xda - -#define PRGMCNT 0xde - -#define SWTIMER 0xe0 - -#define ACCUM 0xe0 - -#define SINDEX 0xe2 - -#define DINDEX 0xe4 - -#define BRKADDR1 0xe6 -#define BRKDIS 0x80 - -#define BRKADDR0 0xe6 - -#define ALLONES 0xe8 - -#define ALLZEROS 0xea - -#define NONE 0xea - -#define SINDIR 0xec - -#define DINDIR 0xed - -#define FUNCTION1 0xf0 - -#define STACK 0xf2 - -#define CURADDR 0xf4 - -#define INTVEC1_ADDR 0xf4 - -#define INTVEC2_ADDR 0xf6 - -#define LASTADDR 0xf6 - -#define LONGJMP_ADDR 0xf8 - -#define LONGJMP_SCB 0xfa - -#define ACCUM_SAVE 0xfc - -#define WAITING_SCB_TAILS 0x100 - -#define AHD_PCI_CONFIG_BASE 0x100 - -#define SRAM_BASE 0x100 - -#define WAITING_TID_HEAD 0x120 - -#define WAITING_TID_TAIL 0x122 - -#define NEXT_QUEUED_SCB_ADDR 0x124 - -#define COMPLETE_SCB_HEAD 0x128 - -#define COMPLETE_SCB_DMAINPROG_HEAD 0x12a - -#define COMPLETE_DMA_SCB_HEAD 0x12c - -#define QFREEZE_COUNT 0x12e - -#define SAVED_MODE 0x130 - -#define MSG_OUT 0x131 - -#define DMAPARAMS 0x132 -#define PRELOADEN 0x80 -#define WIDEODD 0x40 -#define SCSIEN 0x20 -#define SDMAEN 0x10 -#define SDMAENACK 0x10 -#define HDMAENACK 0x08 -#define HDMAEN 0x08 -#define DIRECTION 0x04 -#define FIFOFLUSH 0x02 -#define FIFORESET 0x01 - -#define SEQ_FLAGS 0x133 -#define NOT_IDENTIFIED 0x80 -#define NO_CDB_SENT 0x40 -#define TARGET_CMD_IS_TAGGED 0x40 -#define DPHASE 0x20 -#define TARG_CMD_PENDING 0x10 -#define CMDPHASE_PENDING 0x08 -#define DPHASE_PENDING 0x04 -#define SPHASE_PENDING 0x02 -#define NO_DISCONNECT 0x01 - -#define SAVED_SCSIID 0x134 - -#define SAVED_LUN 0x135 - -#define LASTPHASE 0x136 -#define P_MESGIN 0xe0 -#define PHASE_MASK 0xe0 -#define P_STATUS 0xc0 -#define P_MESGOUT 0xa0 -#define CDI 0x80 -#define P_COMMAND 0x80 -#define P_DATAIN_DT 0x60 -#define P_DATAIN 0x40 -#define IOI 0x40 -#define MSGI 0x20 -#define P_DATAOUT_DT 0x20 -#define P_BUSFREE 0x01 -#define P_DATAOUT 0x00 - -#define SHARED_DATA_ADDR 0x137 - -#define QOUTFIFO_NEXT_ADDR 0x13b - -#define KERNEL_TQINPOS 0x13f - -#define TQINPOS 0x140 - -#define ARG_1 0x141 -#define RETURN_1 0x141 -#define SEND_MSG 0x80 -#define SEND_SENSE 0x40 -#define SEND_REJ 0x20 -#define MSGOUT_PHASEMIS 0x10 -#define EXIT_MSG_LOOP 0x08 -#define CONT_MSG_LOOP_WRITE 0x04 -#define CONT_MSG_LOOP_READ 0x03 -#define CONT_MSG_LOOP_TARG 0x02 - -#define ARG_2 0x142 -#define RETURN_2 0x142 - -#define LAST_MSG 0x143 - -#define SCSISEQ_TEMPLATE 0x144 -#define MANUALCTL 0x40 -#define ENSELI 0x20 -#define ENRSELI 0x10 -#define MANUALP 0x0c -#define ENAUTOATNP 0x02 -#define ALTSTIM 0x01 - -#define INITIATOR_TAG 0x145 - -#define SEQ_FLAGS2 0x146 -#define SELECTOUT_QFROZEN 0x04 -#define TARGET_MSG_PENDING 0x02 -#define SCB_DMA 0x01 - -#define CMDSIZE_TABLE 0x147 - -#define SCB_BASE 0x180 - -#define SCB_RESIDUAL_DATACNT 0x180 -#define SCB_CDB_STORE 0x180 - -#define SCB_RESIDUAL_SGPTR 0x184 -#define SCB_CDB_PTR 0x184 -#define SG_ADDR_MASK 0xf8 -#define SG_OVERRUN_RESID 0x02 - -#define SCB_SCSI_STATUS 0x188 - -#define SCB_TARGET_PHASES 0x189 - -#define SCB_TARGET_DATA_DIR 0x18a - -#define SCB_TARGET_ITAG 0x18b - -#define SCB_SENSE_BUSADDR 0x18c -#define SCB_NEXT_COMPLETE 0x18c - -#define SCB_CDB_LEN 0x190 -#define SCB_CDB_LEN_PTR 0x80 - -#define SCB_TASK_MANAGEMENT 0x191 - -#define SCB_TAG 0x192 - -#define SCB_NEXT 0x194 -#define SCB_NEXT_SCB_BUSADDR 0x194 - -#define SCB_NEXT2 0x196 - -#define SCB_DATAPTR 0x198 - -#define SCB_DATACNT 0x1a0 -#define SG_LAST_SEG 0x80 -#define SG_HIGH_ADDR_BITS 0x7f - -#define SCB_SGPTR 0x1a4 -#define SG_STATUS_VALID 0x04 -#define SG_FULL_RESID 0x02 -#define SG_LIST_NULL 0x01 - -#define SCB_CONTROL 0x1a8 -#define TARGET_SCB 0x80 -#define DISCENB 0x40 -#define TAG_ENB 0x20 -#define MK_MESSAGE 0x10 -#define STATUS_RCVD 0x08 -#define DISCONNECTED 0x04 -#define SCB_TAG_TYPE 0x03 - -#define SCB_SCSIID 0x1a9 -#define TID 0xf0 -#define OID 0x0f - -#define SCB_LUN 0x1aa -#define LID 0xff - -#define SCB_TASK_ATTRIBUTE 0x1ab -#define SCB_NONPACKET_TAG 0x1ab - -#define SCB_BUSADDR 0x1ac - -#define SCB_DISCONNECTED_LISTS 0x1b0 - - -#define SCB_TRANSFER_SIZE 0x30 -#define STATUS_QUEUE_FULL 0x28 -#define STATUS_BUSY 0x08 -#define MAX_OFFSET_PACED 0x7f -#define BUS_32_BIT 0x02 -#define CCSGADDR_MAX 0x80 -#define TID_SHIFT 0x04 -#define MK_MESSAGE_BIT_OFFSET 0x04 -#define SEEOP_EWDS_ADDR 0x00 -#define AHD_NUM_ANNEXCOLS 0x04 -#define AHD_PRECOMP_FASTSLEW 0x40 -#define AHD_PRECOMP_CUTBACK_29 0x06 -#define NVRAM_SCB_OFFSET 0x2c -#define STATUS_PKT_SENSE 0xff -#define CMD_GROUP_CODE_SHIFT 0x05 -#define AHD_SENSE_BUFSIZE 0x100 -#define BUS_8_BIT 0x00 -#define STIMESEL_BUG_ADJ 0x08 -#define STIMESEL_MIN 0x18 -#define STIMESEL_SHIFT 0x03 -#define CCSGRAM_MAXSEGS 0x10 -#define INVALID_ADDR 0x80 -#define TARGET_CMD_CMPLT 0xfe -#define SEEOP_WRAL_ADDR 0x40 -#define SEEOP_ERAL_ADDR 0x80 -#define AHD_PRECOMP_CUTBACK_37 0x07 -#define AHD_PRECOMP_CUTBACK_17 0x04 -#define AHD_PRECOMP_MASK 0x07 -#define AHD_ANNEXCOL_PRECOMP 0x04 -#define SRC_MODE_SHIFT 0x00 -#define PKT_OVERRUN_BUFSIZE 0x200 -#define TARGET_DATA_IN 0x01 -#define HOST_MSG 0xff -#define MAX_OFFSET 0xfe -#define BUS_16_BIT 0x01 -#define CCSCBADDR_MAX 0x80 -#define SEQ_STACK_SIZE 0x08 -#define WRTBIASCTL_CPQ_DEFAULT 0x97 -#define NUMDSPS 0x14 -#define SEEOP_EWEN_ADDR 0xc0 -#define DST_MODE_SHIFT 0x04 - - -/* Downloaded Constant Definitions */ -#define PKT_OVERRUN_BUFOFFSET 0x05 -#define SG_SIZEOF 0x04 -#define SG_PREFETCH_ADDR_MASK 0x03 -#define SG_PREFETCH_ALIGN_MASK 0x02 -#define SG_PREFETCH_CNT_LIMIT 0x01 -#define SG_PREFETCH_CNT 0x00 -#define DOWNLOAD_CONST_COUNT 0x06 - - -/* Exported Labels */ -#define LABEL_seq_isr 0x215 diff --git a/xen/drivers/scsi/aic7xxx/aic79xx_seq.h b/xen/drivers/scsi/aic7xxx/aic79xx_seq.h deleted file mode 100644 index eafb47e585..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic79xx_seq.h +++ /dev/null @@ -1,824 +0,0 @@ -/* - * DO NOT EDIT - This file is automatically generated - * from the following source files: - * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#42 $ - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#34 $ - */ -static uint8_t seqprog[] = { - 0x33, 0xea, 0xda, 0x58, - 0x60, 0x3a, 0x0c, 0x68, - 0x04, 0x46, 0x0d, 0x68, - 0xff, 0x21, 0x0d, 0x70, - 0x40, 0x4b, 0x16, 0x69, - 0x00, 0xe2, 0xe0, 0x58, - 0x40, 0x4b, 0x16, 0x69, - 0x20, 0x4b, 0x0a, 0x69, - 0xfc, 0x42, 0x16, 0x78, - 0x10, 0x40, 0x16, 0x78, - 0x00, 0xe2, 0xf4, 0x5c, - 0x20, 0x4d, 0x1a, 0x78, - 0x00, 0xe2, 0xf4, 0x5c, - 0x01, 0x52, 0x3c, 0x78, - 0x02, 0x58, 0x50, 0x31, - 0xff, 0xea, 0x10, 0x0b, - 0x08, 0xa8, 0x51, 0x03, - 0x01, 0xa4, 0x29, 0x78, - 0x00, 0xe2, 0xc6, 0x5a, - 0x00, 0xe2, 0x1a, 0x40, - 0xff, 0xea, 0xd4, 0x19, - 0x02, 0xa8, 0x82, 0x32, - 0x00, 0xea, 0xda, 0x58, - 0x00, 0xe2, 0xe8, 0x5c, - 0x00, 0xe2, 0x3c, 0x48, - 0x11, 0xea, 0xda, 0x58, - 0x00, 0xe2, 0xe8, 0x5c, - 0x00, 0xe2, 0x3c, 0x48, - 0x33, 0xea, 0xda, 0x58, - 0x00, 0xe2, 0xbe, 0x5a, - 0x00, 0xea, 0xda, 0x58, - 0x80, 0xf9, 0x42, 0x68, - 0x00, 0xe2, 0xd8, 0x58, - 0x11, 0xea, 0xda, 0x58, - 0x80, 0xf9, 0x48, 0x68, - 0x00, 0xe2, 0xd8, 0x58, - 0x00, 0xe2, 0x4c, 0x58, - 0x00, 0xe2, 0x00, 0x40, - 0x22, 0xea, 0xda, 0x58, - 0x18, 0xad, 0x94, 0x78, - 0x04, 0xad, 0x64, 0x68, - 0x80, 0xad, 0xa0, 0x7c, - 0x10, 0xad, 0x58, 0x78, - 0xe7, 0xad, 0x5a, 0x0d, - 0xe7, 0xad, 0x5a, 0x09, - 0x02, 0xea, 0x02, 0x00, - 0xff, 0xea, 0x56, 0x02, - 0x04, 0x7c, 0x76, 0x32, - 0x20, 0x16, 0xa0, 0x7c, - 0x04, 0x37, 0x77, 0x36, - 0x40, 0xad, 0xa0, 0x7c, - 0xe7, 0xad, 0x5a, 0x09, - 0x02, 0xa8, 0x40, 0x31, - 0x04, 0x94, 0x49, 0x32, - 0xff, 0xea, 0x2a, 0x03, - 0xff, 0xea, 0x2e, 0x03, - 0x10, 0xa8, 0x85, 0x68, - 0x3d, 0xa9, 0xc5, 0x29, - 0xfe, 0xe2, 0xc4, 0x09, - 0x01, 0xea, 0xc6, 0x01, - 0x02, 0xe2, 0xc8, 0x31, - 0x02, 0xec, 0x50, 0x31, - 0x02, 0xa0, 0xda, 0x31, - 0xff, 0xa9, 0x84, 0x70, - 0x02, 0xa0, 0x28, 0x33, - 0x01, 0x10, 0xd4, 0x35, - 0xff, 0x21, 0x8f, 0x70, - 0x02, 0x22, 0x51, 0x31, - 0x02, 0xa0, 0x2c, 0x33, - 0x02, 0xa0, 0x44, 0x32, - 0x01, 0x10, 0xd4, 0x35, - 0x02, 0xa0, 0x40, 0x32, - 0x02, 0xa0, 0x44, 0x32, - 0x01, 0x10, 0xd4, 0x35, - 0x04, 0x46, 0x99, 0x68, - 0x40, 0x16, 0xbc, 0x68, - 0xff, 0x2d, 0xc1, 0x60, - 0xff, 0x29, 0xa1, 0x74, - 0x02, 0x28, 0x55, 0x32, - 0x01, 0xea, 0x5a, 0x01, - 0x04, 0x3b, 0xf9, 0x30, - 0x02, 0x28, 0x61, 0x31, - 0x02, 0x28, 0x51, 0x31, - 0x00, 0xe2, 0xac, 0x40, - 0x02, 0x8c, 0x61, 0x31, - 0x02, 0x8c, 0x51, 0x31, - 0x01, 0x14, 0xd4, 0x31, - 0xff, 0x8d, 0xb5, 0x70, - 0x80, 0xac, 0xb4, 0x70, - 0x20, 0x16, 0xa8, 0x78, - 0x01, 0xac, 0x08, 0x31, - 0x09, 0xea, 0x5a, 0x01, - 0x02, 0x8c, 0x51, 0x32, - 0xff, 0xea, 0x1a, 0x07, - 0x04, 0x24, 0xf9, 0x30, - 0x1d, 0xea, 0xcc, 0x40, - 0x02, 0x2c, 0x51, 0x31, - 0x04, 0xac, 0xf9, 0x30, - 0x19, 0xea, 0xcc, 0x58, - 0x02, 0x8c, 0x59, 0x32, - 0x02, 0x28, 0x19, 0x33, - 0x02, 0xa8, 0x50, 0x36, - 0x30, 0xea, 0x08, 0x01, - 0x01, 0xe2, 0x5a, 0x31, - 0x01, 0x46, 0x8d, 0x06, - 0x02, 0xa8, 0xf4, 0x31, - 0x02, 0xf2, 0xf0, 0x35, - 0x02, 0xf2, 0xf0, 0x31, - 0x02, 0xf8, 0xe4, 0x35, - 0x80, 0xea, 0xb2, 0x01, - 0x01, 0xe2, 0x00, 0x30, - 0xff, 0xea, 0xb2, 0x0d, - 0x02, 0x20, 0xbd, 0x30, - 0x02, 0x20, 0xb9, 0x30, - 0x02, 0x20, 0x51, 0x31, - 0x4c, 0xa9, 0xd7, 0x28, - 0x10, 0xa8, 0xef, 0x78, - 0x01, 0x6b, 0xc0, 0x30, - 0x02, 0x64, 0xc8, 0x00, - 0x40, 0x3a, 0x74, 0x04, - 0x00, 0xea, 0xda, 0x58, - 0x80, 0xf9, 0xf6, 0x68, - 0x00, 0xe2, 0xd8, 0x58, - 0x11, 0xea, 0xda, 0x58, - 0x80, 0xf9, 0xfc, 0x68, - 0x00, 0xe2, 0xd8, 0x58, - 0x33, 0xea, 0xda, 0x58, - 0x30, 0x3f, 0xc0, 0x09, - 0x30, 0xe0, 0xf0, 0x60, - 0x02, 0xa8, 0x82, 0x32, - 0x01, 0x3f, 0x7e, 0x00, - 0x11, 0xea, 0xda, 0x58, - 0x02, 0x41, 0x51, 0x35, - 0x08, 0x3c, 0x78, 0x00, - 0xf0, 0x49, 0x68, 0x0a, - 0x0f, 0x67, 0xc0, 0x09, - 0x00, 0x34, 0x69, 0x02, - 0x20, 0xea, 0x96, 0x00, - 0x00, 0xe2, 0x70, 0x41, - 0x40, 0x3a, 0x32, 0x69, - 0x02, 0x55, 0x00, 0x68, - 0x02, 0x56, 0x32, 0x69, - 0xff, 0x5b, 0x32, 0x61, - 0x02, 0x20, 0x51, 0x31, - 0x80, 0xea, 0xb2, 0x01, - 0x44, 0xea, 0x00, 0x00, - 0x01, 0x33, 0xc0, 0x31, - 0x33, 0xea, 0x00, 0x00, - 0xff, 0xea, 0xb2, 0x09, - 0xff, 0xe0, 0xc0, 0x19, - 0xff, 0xe0, 0x34, 0x79, - 0x02, 0x94, 0x51, 0x31, - 0x00, 0xe2, 0x2a, 0x41, - 0x02, 0x5e, 0x50, 0x31, - 0x02, 0xa8, 0xb8, 0x30, - 0x02, 0x5c, 0x50, 0x31, - 0xff, 0x95, 0x45, 0x71, - 0x02, 0x94, 0x41, 0x31, - 0x02, 0x22, 0x51, 0x31, - 0x02, 0xa0, 0x2c, 0x33, - 0x02, 0xa0, 0x44, 0x32, - 0x00, 0xe2, 0x4e, 0x41, - 0x10, 0xa8, 0x4f, 0x69, - 0x3d, 0xa9, 0xc9, 0x29, - 0x01, 0xe4, 0xc8, 0x01, - 0x01, 0xea, 0xca, 0x01, - 0xff, 0xea, 0xda, 0x01, - 0x02, 0x20, 0x51, 0x31, - 0x02, 0x96, 0x41, 0x32, - 0xff, 0x21, 0x57, 0x61, - 0xff, 0xea, 0x46, 0x02, - 0x02, 0x5c, 0x50, 0x31, - 0x40, 0xea, 0x96, 0x00, - 0x02, 0x56, 0xfc, 0x6c, - 0x01, 0x55, 0xfc, 0x6c, - 0x10, 0xa8, 0x63, 0x79, - 0x10, 0x40, 0x64, 0x69, - 0x01, 0x56, 0x00, 0x68, - 0xbf, 0x3a, 0x74, 0x08, - 0x01, 0xa9, 0x69, 0x32, - 0x01, 0xaa, 0x6b, 0x32, - 0x08, 0x3c, 0x78, 0x00, - 0x80, 0xea, 0x62, 0x02, - 0x40, 0xea, 0x66, 0x02, - 0x00, 0xe2, 0x2a, 0x5b, - 0x01, 0x36, 0xc1, 0x31, - 0x9f, 0xe0, 0xc6, 0x7b, - 0x80, 0xe0, 0x82, 0x71, - 0xa0, 0xe0, 0xb4, 0x71, - 0xc0, 0xe0, 0xa6, 0x71, - 0xe0, 0xe0, 0xe4, 0x71, - 0x01, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x70, 0x41, - 0xee, 0x00, 0x86, 0x69, - 0x05, 0xea, 0xb4, 0x00, - 0x00, 0xe2, 0xfe, 0x58, - 0xef, 0x90, 0xd5, 0x19, - 0x00, 0xe2, 0x94, 0x51, - 0x0b, 0x84, 0xe1, 0x30, - 0x02, 0xea, 0x36, 0x00, - 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0x9c, 0x41, - 0x01, 0x90, 0xd1, 0x30, - 0x02, 0xea, 0xd2, 0x30, - 0x10, 0x80, 0x89, 0x31, - 0x20, 0xea, 0x32, 0x00, - 0x20, 0x19, 0x9c, 0x69, - 0xbf, 0x33, 0x67, 0x0a, - 0x02, 0x4d, 0x70, 0x69, - 0x40, 0x33, 0x67, 0x02, - 0x00, 0xe2, 0x70, 0x41, - 0x80, 0x33, 0xad, 0x79, - 0x03, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x16, 0x42, - 0x01, 0x44, 0x10, 0x33, - 0x08, 0xa8, 0x51, 0x03, - 0x00, 0xe2, 0x70, 0x41, - 0x10, 0xea, 0x80, 0x00, - 0x01, 0x31, 0xc5, 0x31, - 0x80, 0xe2, 0xd0, 0x61, - 0x10, 0xa8, 0xf5, 0x69, - 0xc0, 0xaa, 0xc5, 0x01, - 0x40, 0xa8, 0xc1, 0x69, - 0xbf, 0xe2, 0xc4, 0x09, - 0x20, 0xa8, 0xd5, 0x79, - 0x01, 0xe2, 0x88, 0x30, - 0x00, 0xe2, 0x2a, 0x5b, - 0xa0, 0x36, 0xdd, 0x61, - 0x23, 0xa8, 0x89, 0x08, - 0x00, 0xe2, 0x2a, 0x5b, - 0xa0, 0x36, 0xdd, 0x61, - 0x00, 0xab, 0xd5, 0x41, - 0xff, 0xe2, 0xd4, 0x61, - 0x00, 0xe2, 0xf4, 0x41, - 0x40, 0xea, 0x98, 0x00, - 0x01, 0xe2, 0x88, 0x30, - 0x00, 0xe2, 0x2a, 0x5b, - 0xa0, 0x36, 0xb3, 0x71, - 0x40, 0xea, 0x98, 0x00, - 0x01, 0x31, 0x87, 0x32, - 0x08, 0xea, 0x62, 0x02, - 0x00, 0xe2, 0x70, 0x41, - 0xe0, 0xea, 0x36, 0x5b, - 0x80, 0xe0, 0x1a, 0x6a, - 0x04, 0xe0, 0xd4, 0x72, - 0x02, 0xe0, 0x0c, 0x73, - 0x00, 0xea, 0x9a, 0x72, - 0x03, 0xe0, 0x1c, 0x73, - 0x23, 0xe0, 0x04, 0x72, - 0x08, 0xe0, 0x16, 0x72, - 0x00, 0xe2, 0x2a, 0x5b, - 0x07, 0xea, 0x04, 0x00, - 0x08, 0x41, 0x71, 0x71, - 0x04, 0x41, 0x01, 0x62, - 0x01, 0x42, 0x89, 0x30, - 0x00, 0xe2, 0xf4, 0x41, - 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0xf4, 0x41, - 0x4c, 0x34, 0xc1, 0x28, - 0x01, 0x64, 0x14, 0x7a, - 0xa0, 0xea, 0x2e, 0x5b, - 0x01, 0xa0, 0x14, 0x62, - 0x01, 0x84, 0x11, 0x7a, - 0x01, 0xa7, 0x16, 0x7a, - 0x05, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x16, 0x42, - 0x07, 0xea, 0x3e, 0x5b, - 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0x70, 0x41, - 0x4c, 0x34, 0xc5, 0x29, - 0x3f, 0xe0, 0x6a, 0x0a, - 0x01, 0x35, 0x51, 0x31, - 0x3d, 0xe2, 0x52, 0x29, - 0x07, 0xe2, 0xc4, 0x09, - 0x11, 0xe2, 0xc4, 0x29, - 0xb0, 0xe2, 0xc4, 0x19, - 0x01, 0xea, 0xc6, 0x01, - 0x02, 0xe2, 0xc8, 0x31, - 0x02, 0xec, 0x50, 0x31, - 0xff, 0xa9, 0x36, 0x72, - 0x20, 0xa8, 0x37, 0x6a, - 0x04, 0x92, 0x45, 0x31, - 0x00, 0xe2, 0x70, 0x42, - 0x80, 0x33, 0x67, 0x02, - 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0x2a, 0x5b, - 0x01, 0x33, 0x67, 0x02, - 0xe0, 0x36, 0x97, 0x62, - 0x02, 0x33, 0x67, 0x02, - 0x20, 0x46, 0x92, 0x62, - 0x02, 0xa8, 0x40, 0x31, - 0xff, 0xea, 0x52, 0x09, - 0xa8, 0xea, 0x2e, 0x5b, - 0x01, 0xa8, 0x44, 0x31, - 0x01, 0xa2, 0xc0, 0x31, - 0x00, 0xab, 0x59, 0x62, - 0x01, 0x34, 0xc1, 0x31, - 0x00, 0xa9, 0x59, 0x62, - 0x01, 0x35, 0xc1, 0x31, - 0x00, 0xaa, 0x81, 0x72, - 0x01, 0xa9, 0x52, 0x11, - 0xff, 0xa9, 0x4c, 0x6a, - 0x02, 0xa0, 0x50, 0x31, - 0xff, 0xea, 0x42, 0x01, - 0x01, 0xa2, 0xc0, 0x31, - 0x00, 0xab, 0x6d, 0x72, - 0x02, 0xa8, 0x40, 0x31, - 0x02, 0x94, 0x51, 0x31, - 0xff, 0xa9, 0x62, 0x62, - 0x00, 0xe2, 0x92, 0x42, - 0x04, 0x92, 0x45, 0x31, - 0xff, 0xa1, 0x7a, 0x62, - 0x4c, 0x34, 0xc5, 0x29, - 0x01, 0x35, 0x51, 0x31, - 0x3d, 0xe2, 0x52, 0x29, - 0x02, 0xa4, 0xda, 0x31, - 0x00, 0xe2, 0x7e, 0x42, - 0x02, 0xa0, 0x50, 0x31, - 0x02, 0xa4, 0x28, 0x33, - 0x02, 0xa2, 0x50, 0x31, - 0x10, 0x33, 0x67, 0x02, - 0x04, 0xa8, 0x93, 0x7a, - 0xfb, 0xa8, 0x51, 0x0b, - 0xff, 0xea, 0x66, 0x0a, - 0x01, 0xa4, 0x8d, 0x6a, - 0x00, 0xe2, 0xfe, 0x58, - 0x10, 0xa8, 0x17, 0x7a, - 0xff, 0xea, 0x3e, 0x5b, - 0x00, 0xe2, 0x16, 0x42, - 0x04, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x16, 0x42, - 0x04, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x70, 0x41, - 0xc0, 0x33, 0xa1, 0x7a, - 0x03, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x16, 0x42, - 0x08, 0xa8, 0x9d, 0x7a, - 0x10, 0xa8, 0xa7, 0x7a, - 0x0a, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xbe, 0x5a, - 0x00, 0xe2, 0xfc, 0x42, - 0x40, 0x4b, 0xae, 0x6a, - 0xbf, 0x3a, 0x74, 0x08, - 0x01, 0xe0, 0xf8, 0x31, - 0xff, 0xea, 0xc0, 0x09, - 0x01, 0x2e, 0x5d, 0x1a, - 0x00, 0x2f, 0x5f, 0x22, - 0x04, 0x46, 0x8d, 0x02, - 0x01, 0xfc, 0xc0, 0x35, - 0x33, 0xea, 0xda, 0x58, - 0x02, 0x41, 0x51, 0x31, - 0xff, 0x88, 0xcb, 0x6a, - 0x01, 0xa4, 0xc7, 0x6a, - 0x02, 0xa4, 0xcf, 0x6a, - 0x01, 0x84, 0xcf, 0x7a, - 0x02, 0x28, 0x19, 0x33, - 0x02, 0xa8, 0x50, 0x36, - 0xff, 0x88, 0xcf, 0x72, - 0x00, 0xe2, 0xaa, 0x5a, - 0x02, 0x2c, 0x19, 0x33, - 0x02, 0xa8, 0x58, 0x32, - 0x04, 0xa4, 0x49, 0x07, - 0xc0, 0x33, 0xdb, 0x7a, - 0x03, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x16, 0x42, - 0x04, 0xa8, 0x51, 0x03, - 0x20, 0xa8, 0xe3, 0x7a, - 0x01, 0xab, 0xc1, 0x31, - 0x00, 0xa8, 0xfc, 0x72, - 0x02, 0xa8, 0x40, 0x31, - 0x4c, 0xa9, 0xc5, 0x29, - 0x01, 0xaa, 0x51, 0x31, - 0x3d, 0xe2, 0x52, 0x29, - 0x07, 0xe2, 0xc4, 0x09, - 0x11, 0xe2, 0xc4, 0x29, - 0xb0, 0xe2, 0xc4, 0x19, - 0x01, 0xea, 0xc6, 0x01, - 0x02, 0xe2, 0xc8, 0x31, - 0x02, 0xec, 0x44, 0x31, - 0x02, 0xa0, 0xda, 0x31, - 0x02, 0xa0, 0x50, 0x31, - 0x02, 0xa2, 0x28, 0x33, - 0xf7, 0x57, 0xae, 0x08, - 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0x26, 0x5b, - 0xee, 0x00, 0x06, 0x6b, - 0x02, 0xea, 0xb4, 0x00, - 0x09, 0x4c, 0x06, 0x7b, - 0x08, 0x4c, 0x00, 0x68, - 0x0b, 0xea, 0x04, 0x00, - 0x01, 0x44, 0xd4, 0x31, - 0x20, 0x33, 0x71, 0x79, - 0x00, 0xe2, 0x14, 0x5b, - 0x00, 0xe2, 0x70, 0x41, - 0x01, 0x84, 0x19, 0x7b, - 0x01, 0xa4, 0x49, 0x07, - 0x08, 0x60, 0x30, 0x33, - 0x08, 0x80, 0x41, 0x37, - 0xdf, 0x33, 0x67, 0x0a, - 0xee, 0x00, 0x22, 0x6b, - 0x05, 0xea, 0xb4, 0x00, - 0x00, 0xe2, 0xfe, 0x58, - 0x00, 0xe2, 0x16, 0x42, - 0x01, 0xea, 0x6c, 0x02, - 0xc0, 0xea, 0x66, 0x06, - 0xff, 0x42, 0x2a, 0x7b, - 0xe0, 0x41, 0x6c, 0x0e, - 0x01, 0x44, 0xd4, 0x31, - 0xff, 0x42, 0x30, 0x7b, - 0xe0, 0x41, 0x6c, 0x0a, - 0xe0, 0x36, 0x71, 0x61, - 0xff, 0xea, 0xca, 0x09, - 0x01, 0xe2, 0xc8, 0x31, - 0x01, 0x46, 0xda, 0x35, - 0x01, 0x44, 0xd4, 0x35, - 0x10, 0xea, 0x80, 0x00, - 0x01, 0xe2, 0x62, 0x36, - 0x04, 0xa6, 0xa0, 0x7c, - 0xff, 0xea, 0x4c, 0x09, - 0xff, 0xea, 0x5a, 0x0d, - 0x80, 0xea, 0xb2, 0x01, - 0x11, 0x00, 0x00, 0x10, - 0xff, 0xea, 0xb2, 0x0d, - 0x01, 0x00, 0x60, 0x32, - 0x02, 0xa6, 0x54, 0x7b, - 0x00, 0xe2, 0x5e, 0x5b, - 0x00, 0xe2, 0x48, 0x5b, - 0x02, 0xa6, 0x5a, 0x7b, - 0x00, 0xe2, 0x5e, 0x5b, - 0x00, 0xe2, 0x4c, 0x58, - 0x00, 0x30, 0xdb, 0x40, - 0x01, 0xa6, 0x78, 0x6b, - 0x10, 0xad, 0xa0, 0x7c, - 0x98, 0xad, 0x70, 0x73, - 0x08, 0xad, 0xa0, 0x6c, - 0x00, 0xea, 0x08, 0x81, - 0x02, 0x84, 0xf9, 0x88, - 0x03, 0x85, 0xfb, 0x30, - 0x19, 0xea, 0x5a, 0x01, - 0x04, 0xa6, 0x4c, 0x05, - 0x04, 0xa6, 0xa0, 0x7c, - 0x00, 0xe2, 0x46, 0x5b, - 0x03, 0x84, 0x59, 0x89, - 0x03, 0xea, 0x4c, 0x01, - 0x80, 0x1a, 0xa0, 0x7c, - 0x08, 0xb0, 0xe0, 0x30, - 0x04, 0xb0, 0xe0, 0x30, - 0x03, 0xb0, 0xf0, 0x30, - 0x01, 0x78, 0x84, 0x7b, - 0x01, 0xa7, 0x4e, 0x11, - 0x01, 0xb0, 0x06, 0x33, - 0x7f, 0x83, 0xe9, 0x08, - 0x04, 0xac, 0x58, 0x19, - 0xff, 0xea, 0xc0, 0x09, - 0x04, 0x84, 0x09, 0x9b, - 0x00, 0x85, 0x0b, 0x23, - 0x00, 0x86, 0x0d, 0x23, - 0x00, 0x87, 0x0f, 0x23, - 0x01, 0x84, 0xc5, 0x31, - 0x01, 0xa7, 0x9a, 0x7b, - 0x04, 0xe2, 0xc4, 0x01, - 0x80, 0x83, 0xa1, 0x7b, - 0x02, 0xe2, 0xc4, 0x01, - 0xff, 0xea, 0x4c, 0x09, - 0x01, 0xe2, 0x36, 0x30, - 0x88, 0x19, 0x32, 0x00, - 0x01, 0xac, 0xd4, 0x99, - 0x00, 0xe2, 0xa0, 0x54, - 0xfe, 0xa6, 0x4c, 0x0d, - 0x0b, 0x98, 0xe1, 0x30, - 0x01, 0xa0, 0x4f, 0x09, - 0xfd, 0xa4, 0x41, 0x09, - 0x80, 0xa3, 0xb5, 0x7b, - 0x02, 0xa0, 0x40, 0x01, - 0x01, 0xa7, 0xb8, 0x7b, - 0x04, 0xa0, 0x40, 0x01, - 0x01, 0xa0, 0x36, 0x30, - 0xa8, 0xea, 0x32, 0x00, - 0xfd, 0xa4, 0x49, 0x0b, - 0x05, 0xa3, 0x07, 0x33, - 0x80, 0x83, 0xc5, 0x6b, - 0x02, 0xea, 0x4c, 0x05, - 0xff, 0xea, 0x4c, 0x0d, - 0xc0, 0x33, 0xcb, 0x7b, - 0x03, 0xea, 0x04, 0x00, - 0x20, 0x33, 0xe3, 0x7b, - 0x01, 0x84, 0xd1, 0x6b, - 0x06, 0xea, 0x04, 0x00, - 0xee, 0x00, 0xd6, 0x6b, - 0x05, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0xda, 0x58, - 0x80, 0x3d, 0x7a, 0x00, - 0x03, 0x42, 0xd8, 0x6b, - 0x7f, 0x3d, 0x7a, 0x08, - 0x11, 0xea, 0xda, 0x58, - 0x09, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x70, 0x41, - 0x01, 0xa4, 0xd1, 0x6b, - 0x00, 0xe2, 0xaa, 0x5b, - 0x20, 0x33, 0x67, 0x02, - 0x00, 0xe2, 0x4e, 0x5b, - 0x20, 0x19, 0xe8, 0x6b, - 0x00, 0xe2, 0x06, 0x5c, - 0x04, 0x19, 0xfa, 0x6b, - 0x02, 0x19, 0x32, 0x00, - 0x01, 0x84, 0xfb, 0x7b, - 0x01, 0x1b, 0xf4, 0x7b, - 0x01, 0x1a, 0xfa, 0x6b, - 0x00, 0xe2, 0xc6, 0x43, - 0x80, 0x4b, 0x00, 0x6c, - 0x01, 0x4c, 0xfc, 0x7b, - 0x03, 0x42, 0xc6, 0x6b, - 0x00, 0xe2, 0x42, 0x5b, - 0x04, 0x33, 0x71, 0x79, - 0x00, 0xe2, 0x70, 0x41, - 0x02, 0x1b, 0x0e, 0x7c, - 0x08, 0x5d, 0x0c, 0x7c, - 0x03, 0x68, 0x00, 0x37, - 0x01, 0x84, 0x09, 0x07, - 0x08, 0x5d, 0x14, 0x6c, - 0x00, 0xe2, 0x4e, 0x5b, - 0x00, 0xe2, 0x06, 0x44, - 0x80, 0x1b, 0x1e, 0x7c, - 0x80, 0x84, 0x1f, 0x6c, - 0xff, 0x85, 0x0b, 0x1b, - 0xff, 0x86, 0x0d, 0x23, - 0xff, 0x87, 0x0f, 0x23, - 0xf8, 0x1b, 0x08, 0x0b, - 0xff, 0xea, 0x4e, 0x09, - 0x04, 0x1b, 0x26, 0x7c, - 0x01, 0xa7, 0x4e, 0x01, - 0xff, 0xea, 0x06, 0x0b, - 0x03, 0x68, 0x00, 0x37, - 0xff, 0xea, 0xd4, 0x09, - 0x20, 0x5b, 0x36, 0x6c, - 0x10, 0x5b, 0x40, 0x6c, - 0x08, 0x5b, 0x48, 0x6c, - 0x02, 0x5b, 0x44, 0x6d, - 0x12, 0xea, 0x04, 0x00, - 0x08, 0x19, 0x3c, 0x7c, - 0xdf, 0x5c, 0xb8, 0x08, - 0x01, 0xd9, 0xb2, 0x05, - 0x02, 0xea, 0xb4, 0x00, - 0x01, 0xd9, 0xb2, 0x05, - 0x01, 0xa4, 0x0f, 0x6d, - 0x00, 0xe2, 0xaa, 0x5b, - 0x00, 0xe2, 0x60, 0x5c, - 0x01, 0xd9, 0xb2, 0x05, - 0x00, 0xe2, 0xaa, 0x5a, - 0xf3, 0x90, 0xd5, 0x19, - 0x00, 0xe2, 0x54, 0x54, - 0x80, 0x90, 0x55, 0x6c, - 0x13, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x5c, 0x44, - 0x04, 0x8c, 0xe1, 0x30, - 0x01, 0xea, 0xf2, 0x00, - 0x02, 0xea, 0x36, 0x00, - 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0xd8, 0x5c, - 0x01, 0xd9, 0xb2, 0x05, - 0x02, 0xa8, 0xf4, 0x31, - 0x02, 0xa6, 0x72, 0x7c, - 0x00, 0xe2, 0xd4, 0x58, - 0x20, 0x5b, 0xba, 0x6c, - 0xfc, 0x42, 0x6c, 0x7c, - 0x10, 0x40, 0x6e, 0x6c, - 0x20, 0x4d, 0x70, 0x7c, - 0x08, 0x5d, 0xba, 0x6c, - 0x02, 0xa6, 0x5e, 0x6b, - 0x00, 0xe2, 0xd4, 0x58, - 0x20, 0x5b, 0xba, 0x6c, - 0x01, 0x1b, 0x82, 0x6c, - 0xfc, 0x42, 0x7c, 0x7c, - 0x10, 0x40, 0x7e, 0x6c, - 0x20, 0x4d, 0xa0, 0x7c, - 0x08, 0x5d, 0xba, 0x6c, - 0x00, 0xe2, 0xa0, 0x44, - 0x02, 0x19, 0x32, 0x00, - 0x08, 0xa8, 0xa3, 0x7c, - 0x04, 0x5d, 0x0e, 0x7d, - 0x01, 0x1a, 0x0e, 0x7d, - 0x01, 0xa4, 0x49, 0x03, - 0x80, 0xf9, 0xf2, 0x01, - 0x02, 0xa8, 0x82, 0x32, - 0x02, 0xea, 0xb4, 0x00, - 0x00, 0xe2, 0xba, 0x42, - 0x02, 0xa8, 0x82, 0x32, - 0x02, 0xea, 0xb4, 0x00, - 0xff, 0xea, 0xd4, 0x19, - 0x00, 0xe2, 0x48, 0x5b, - 0x00, 0xe2, 0xe8, 0x5c, - 0x00, 0xe2, 0xba, 0x52, - 0xff, 0xea, 0xd4, 0x0d, - 0x00, 0xe2, 0xd4, 0x58, - 0x40, 0x5b, 0xae, 0x6c, - 0x04, 0x5d, 0x0e, 0x7d, - 0x01, 0x1a, 0x0e, 0x7d, - 0x20, 0x4d, 0xa0, 0x7c, - 0x40, 0x5b, 0xfc, 0x7c, - 0x04, 0x5d, 0x0e, 0x7d, - 0x01, 0x1a, 0x0e, 0x7d, - 0x80, 0xf9, 0xf2, 0x01, - 0x01, 0xa4, 0x49, 0x03, - 0x08, 0xa8, 0x95, 0x6c, - 0x02, 0xea, 0xb4, 0x04, - 0x02, 0x19, 0x32, 0x00, - 0x01, 0x5b, 0x40, 0x31, - 0x20, 0xea, 0xb6, 0x00, - 0x00, 0xe2, 0x06, 0x5c, - 0x00, 0xe2, 0x14, 0x5b, - 0x00, 0xe2, 0x42, 0x5b, - 0x20, 0x5c, 0xb8, 0x00, - 0x80, 0xf9, 0xf2, 0x01, - 0x20, 0xa0, 0xfc, 0x7c, - 0x08, 0xa8, 0xd1, 0x7c, - 0x00, 0xe2, 0x94, 0x44, - 0x02, 0xea, 0xb4, 0x04, - 0xff, 0x6a, 0xde, 0x7c, - 0x14, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xde, 0x44, - 0x00, 0xe2, 0xd2, 0x58, - 0x10, 0x5d, 0xd2, 0x6c, - 0x40, 0x5b, 0xa0, 0x7c, - 0x02, 0x19, 0x32, 0x00, - 0x80, 0xf9, 0xf2, 0x01, - 0xff, 0xea, 0x10, 0x03, - 0x08, 0xa8, 0x51, 0x03, - 0x00, 0xe2, 0x94, 0x44, - 0x80, 0xf9, 0xa0, 0x6c, - 0x01, 0x42, 0xc1, 0x31, - 0x00, 0xfb, 0xa0, 0x64, - 0x01, 0x41, 0xc1, 0x31, - 0x00, 0xfa, 0xa0, 0x64, - 0x01, 0xe8, 0xd4, 0x1d, - 0x30, 0x3f, 0xc0, 0x09, - 0x30, 0xe0, 0xa0, 0x64, - 0x40, 0x4b, 0xa0, 0x6c, - 0xff, 0xea, 0x52, 0x01, - 0xee, 0x00, 0x02, 0x6d, - 0x80, 0xf9, 0xf2, 0x01, - 0x02, 0xea, 0xb4, 0x00, - 0x20, 0xea, 0x9a, 0x00, - 0xf3, 0x42, 0x0a, 0x6d, - 0x18, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x70, 0x41, - 0x11, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x70, 0x41, - 0x15, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xaa, 0x5a, - 0x33, 0xea, 0xda, 0x58, - 0x80, 0x3d, 0x7a, 0x00, - 0x00, 0xe2, 0x2e, 0x5d, - 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0xd4, 0x58, - 0x40, 0x1a, 0x22, 0x7d, - 0x00, 0xe2, 0x2e, 0x5d, - 0x80, 0x19, 0x32, 0x00, - 0x40, 0x5b, 0x26, 0x6d, - 0x20, 0x4d, 0xa0, 0x7c, - 0x02, 0x84, 0x09, 0x03, - 0x40, 0x5b, 0xfc, 0x7c, - 0x08, 0xa8, 0x8d, 0x6c, - 0x02, 0xea, 0xb4, 0x04, - 0x01, 0x37, 0xe1, 0x30, - 0x05, 0x38, 0xe3, 0x98, - 0x01, 0xe0, 0xf8, 0x31, - 0xff, 0xea, 0xc0, 0x09, - 0x00, 0x39, 0xe5, 0x20, - 0x00, 0x3a, 0xe7, 0x20, - 0x01, 0xfc, 0xc0, 0x31, - 0x04, 0xea, 0xe8, 0x30, - 0xff, 0xea, 0xf0, 0x08, - 0x02, 0xea, 0xf2, 0x00, - 0xff, 0xea, 0xf4, 0x08 -}; - -static int aic_patch10_func(struct ahd_softc *ahd); - -static int -aic_patch10_func(struct ahd_softc *ahd) -{ - return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0); -} - -static int aic_patch9_func(struct ahd_softc *ahd); - -static int -aic_patch9_func(struct ahd_softc *ahd) -{ - return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0); -} - -static int aic_patch8_func(struct ahd_softc *ahd); - -static int -aic_patch8_func(struct ahd_softc *ahd) -{ - return ((ahd->flags & AHD_INITIATORROLE) != 0); -} - -static int aic_patch7_func(struct ahd_softc *ahd); - -static int -aic_patch7_func(struct ahd_softc *ahd) -{ - return ((ahd->flags & AHD_TARGETROLE) != 0); -} - -static int aic_patch6_func(struct ahd_softc *ahd); - -static int -aic_patch6_func(struct ahd_softc *ahd) -{ - return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0); -} - -static int aic_patch5_func(struct ahd_softc *ahd); - -static int -aic_patch5_func(struct ahd_softc *ahd) -{ - return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0); -} - -static int aic_patch4_func(struct ahd_softc *ahd); - -static int -aic_patch4_func(struct ahd_softc *ahd) -{ - return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0); -} - -static int aic_patch3_func(struct ahd_softc *ahd); - -static int -aic_patch3_func(struct ahd_softc *ahd) -{ - return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0); -} - -static int aic_patch2_func(struct ahd_softc *ahd); - -static int -aic_patch2_func(struct ahd_softc *ahd) -{ - return ((ahd->bugs & AHD_LQO_ATNO_BUG) != 0); -} - -static int aic_patch1_func(struct ahd_softc *ahd); - -static int -aic_patch1_func(struct ahd_softc *ahd) -{ - return ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0); -} - -static int aic_patch0_func(struct ahd_softc *ahd); - -static int -aic_patch0_func(struct ahd_softc *ahd) -{ - return (0); -} - -typedef int patch_func_t (struct ahd_softc *ahd); -static struct patch { - patch_func_t *patch_func; - uint32_t begin :10, - skip_instr :10, - skip_patch :12; -} patches[] = { - { aic_patch1_func, 112, 1, 1 }, - { aic_patch1_func, 139, 16, 2 }, - { aic_patch0_func, 155, 1, 1 }, - { aic_patch2_func, 175, 2, 1 }, - { aic_patch3_func, 283, 1, 1 }, - { aic_patch3_func, 286, 1, 1 }, - { aic_patch3_func, 288, 1, 1 }, - { aic_patch3_func, 320, 1, 1 }, - { aic_patch4_func, 445, 1, 2 }, - { aic_patch0_func, 446, 1, 1 }, - { aic_patch5_func, 451, 1, 1 }, - { aic_patch4_func, 452, 1, 1 }, - { aic_patch6_func, 504, 1, 1 }, - { aic_patch7_func, 509, 1, 1 }, - { aic_patch8_func, 510, 2, 1 }, - { aic_patch7_func, 513, 1, 2 }, - { aic_patch0_func, 514, 1, 1 }, - { aic_patch6_func, 577, 1, 1 }, - { aic_patch6_func, 605, 1, 1 }, - { aic_patch6_func, 623, 1, 1 }, - { aic_patch9_func, 649, 2, 2 }, - { aic_patch0_func, 651, 2, 1 }, - { aic_patch10_func, 654, 3, 1 }, - { aic_patch10_func, 663, 11, 1 } -}; -static struct cs { - u_int16_t begin; - u_int16_t end; -} critical_sections[] = { - { 4, 5 }, - { 6, 7 }, - { 13, 19 }, - { 20, 30 }, - { 75, 102 }, - { 105, 109 }, - { 112, 120 }, - { 139, 172 }, - { 577, 594 }, - { 599, 605 }, - { 605, 617 }, - { 623, 628 }, - { 628, 634 } -}; -static const int num_critical_sections = sizeof(critical_sections) - / sizeof(*critical_sections); diff --git a/xen/drivers/scsi/aic7xxx/aic7xxx.h b/xen/drivers/scsi/aic7xxx/aic7xxx.h deleted file mode 100644 index 289e0bf44e..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic7xxx.h +++ /dev/null @@ -1,1245 +0,0 @@ -/* - * Core definitions and data structures shareable across OS platforms. - * - * Copyright (c) 1994-2001 Justin T. Gibbs. - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#45 $ - * - * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.h,v 1.16.2.13 2002/04/29 19:36:29 gibbs Exp $ - */ - -#ifndef _AIC7XXX_H_ -#define _AIC7XXX_H_ - -/* Register Definitions */ -#include "aic7xxx_reg.h" - -/************************* Forward Declarations *******************************/ -struct ahc_platform_data; -struct scb_platform_data; -struct seeprom_descriptor; - -/****************************** Useful Macros *********************************/ -#ifndef MAX -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -#ifndef MIN -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(*array)) - -#define ALL_CHANNELS '\0' -#define ALL_TARGETS_MASK 0xFFFF -#define INITIATOR_WILDCARD (~0) - -#define SCSIID_TARGET(ahc, scsiid) \ - (((scsiid) & ((((ahc)->features & AHC_TWIN) != 0) ? TWIN_TID : TID)) \ - >> TID_SHIFT) -#define SCSIID_OUR_ID(scsiid) \ - ((scsiid) & OID) -#define SCSIID_CHANNEL(ahc, scsiid) \ - ((((ahc)->features & AHC_TWIN) != 0) \ - ? ((((scsiid) & TWIN_CHNLB) != 0) ? 'B' : 'A') \ - : 'A') -#define SCB_IS_SCSIBUS_B(ahc, scb) \ - (SCSIID_CHANNEL(ahc, (scb)->hscb->scsiid) == 'B') -#define SCB_GET_OUR_ID(scb) \ - SCSIID_OUR_ID((scb)->hscb->scsiid) -#define SCB_GET_TARGET(ahc, scb) \ - SCSIID_TARGET((ahc), (scb)->hscb->scsiid) -#define SCB_GET_CHANNEL(ahc, scb) \ - SCSIID_CHANNEL(ahc, (scb)->hscb->scsiid) -#define SCB_GET_LUN(scb) \ - ((scb)->hscb->lun) -#define SCB_GET_TARGET_OFFSET(ahc, scb) \ - (SCB_GET_TARGET(ahc, scb) + (SCB_IS_SCSIBUS_B(ahc, scb) ? 8 : 0)) -#define SCB_GET_TARGET_MASK(ahc, scb) \ - (0x01 << (SCB_GET_TARGET_OFFSET(ahc, scb))) -#define TCL_TARGET_OFFSET(tcl) \ - ((((tcl) >> 4) & TID) >> 4) -#define TCL_LUN(tcl) \ - (tcl & (AHC_NUM_LUNS - 1)) -#define BUILD_TCL(scsiid, lun) \ - ((lun) | (((scsiid) & TID) << 4)) - -#ifndef AHC_TARGET_MODE -#undef AHC_TMODE_ENABLE -#define AHC_TMODE_ENABLE 0 -#endif - -/**************************** Driver Constants ********************************/ -/* - * The maximum number of supported targets. - */ -#define AHC_NUM_TARGETS 16 - -/* - * The maximum number of supported luns. - * The identify message only supports 64 luns in SPI3. - * You can have 2^64 luns when information unit transfers are enabled, - * but it is doubtful this driver will ever support IUTs. - */ -#define AHC_NUM_LUNS 64 - -/* - * The maximum transfer per S/G segment. - */ -#define AHC_MAXTRANSFER_SIZE 0x00ffffff /* limited by 24bit counter */ - -/* - * The maximum amount of SCB storage in hardware on a controller. - * This value represents an upper bound. Controllers vary in the number - * they actually support. - */ -#define AHC_SCB_MAX 255 - -/* - * The maximum number of concurrent transactions supported per driver instance. - * Sequencer Control Blocks (SCBs) store per-transaction information. Although - * the space for SCBs on the host adapter varies by model, the driver will - * page the SCBs between host and controller memory as needed. We are limited - * to 253 because: - * 1) The 8bit nature of the RISC engine holds us to an 8bit value. - * 2) We reserve one value, 255, to represent the invalid element. - * 3) Our input queue scheme requires one SCB to always be reserved - * in advance of queuing any SCBs. This takes us down to 254. - * 4) To handle our output queue correctly on machines that only - * support 32bit stores, we must clear the array 4 bytes at a - * time. To avoid colliding with a DMA write from the sequencer, - * we must be sure that 4 slots are empty when we write to clear - * the queue. This reduces us to 253 SCBs: 1 that just completed - * and the known three additional empty slots in the queue that - * precede it. - */ -#define AHC_MAX_QUEUE 253 - -/* - * The maximum amount of SCB storage we allocate in host memory. This - * number should reflect the 1 additional SCB we require to handle our - * qinfifo mechanism. - */ -#define AHC_SCB_MAX_ALLOC (AHC_MAX_QUEUE+1) - -/* - * Ring Buffer of incoming target commands. - * We allocate 256 to simplify the logic in the sequencer - * by using the natural wrap point of an 8bit counter. - */ -#define AHC_TMODE_CMDS 256 - -/* Reset line assertion time in us */ -#define AHC_BUSRESET_DELAY 250 - -/******************* Chip Characteristics/Operating Settings *****************/ -/* - * Chip Type - * The chip order is from least sophisticated to most sophisticated. - */ -typedef enum { - AHC_NONE = 0x0000, - AHC_CHIPID_MASK = 0x00FF, - AHC_AIC7770 = 0x0001, - AHC_AIC7850 = 0x0002, - AHC_AIC7855 = 0x0003, - AHC_AIC7859 = 0x0004, - AHC_AIC7860 = 0x0005, - AHC_AIC7870 = 0x0006, - AHC_AIC7880 = 0x0007, - AHC_AIC7895 = 0x0008, - AHC_AIC7895C = 0x0009, - AHC_AIC7890 = 0x000a, - AHC_AIC7896 = 0x000b, - AHC_AIC7892 = 0x000c, - AHC_AIC7899 = 0x000d, - AHC_VL = 0x0100, /* Bus type VL */ - AHC_EISA = 0x0200, /* Bus type EISA */ - AHC_PCI = 0x0400, /* Bus type PCI */ - AHC_BUS_MASK = 0x0F00 -} ahc_chip; - -/* - * Features available in each chip type. - */ -typedef enum { - AHC_FENONE = 0x00000, - AHC_ULTRA = 0x00001, /* Supports 20MHz Transfers */ - AHC_ULTRA2 = 0x00002, /* Supports 40MHz Transfers */ - AHC_WIDE = 0x00004, /* Wide Channel */ - AHC_TWIN = 0x00008, /* Twin Channel */ - AHC_MORE_SRAM = 0x00010, /* 80 bytes instead of 64 */ - AHC_CMD_CHAN = 0x00020, /* Has a Command DMA Channel */ - AHC_QUEUE_REGS = 0x00040, /* Has Queue management registers */ - AHC_SG_PRELOAD = 0x00080, /* Can perform auto-SG preload */ - AHC_SPIOCAP = 0x00100, /* Has a Serial Port I/O Cap Register */ - AHC_MULTI_TID = 0x00200, /* Has bitmask of TIDs for select-in */ - AHC_HS_MAILBOX = 0x00400, /* Has HS_MAILBOX register */ - AHC_DT = 0x00800, /* Double Transition transfers */ - AHC_NEW_TERMCTL = 0x01000, /* Newer termination scheme */ - AHC_MULTI_FUNC = 0x02000, /* Multi-Function Twin Channel Device */ - AHC_LARGE_SCBS = 0x04000, /* 64byte SCBs */ - AHC_AUTORATE = 0x08000, /* Automatic update of SCSIRATE/OFFSET*/ - AHC_AUTOPAUSE = 0x10000, /* Automatic pause on register access */ - AHC_TARGETMODE = 0x20000, /* Has tested target mode support */ - AHC_MULTIROLE = 0x40000, /* Space for two roles at a time */ - AHC_REMOVABLE = 0x80000, /* Hot-Swap supported */ - AHC_AIC7770_FE = AHC_FENONE, - /* - * The real 7850 does not support Ultra modes, but there are - * several cards that use the generic 7850 PCI ID even though - * they are using an Ultra capable chip (7859/7860). We start - * out with the AHC_ULTRA feature set and then check the DEVSTATUS - * register to determine if the capability is really present. - */ - AHC_AIC7850_FE = AHC_SPIOCAP|AHC_AUTOPAUSE|AHC_TARGETMODE|AHC_ULTRA, - AHC_AIC7860_FE = AHC_AIC7850_FE, - AHC_AIC7870_FE = AHC_TARGETMODE, - AHC_AIC7880_FE = AHC_AIC7870_FE|AHC_ULTRA, - /* - * Although we have space for both the initiator and - * target roles on ULTRA2 chips, we currently disable - * the initiator role to allow multi-scsi-id target mode - * configurations. We can only respond on the same SCSI - * ID as our initiator role if we allow initiator operation. - * At some point, we should add a configuration knob to - * allow both roles to be loaded. - */ - AHC_AIC7890_FE = AHC_MORE_SRAM|AHC_CMD_CHAN|AHC_ULTRA2 - |AHC_QUEUE_REGS|AHC_SG_PRELOAD|AHC_MULTI_TID - |AHC_HS_MAILBOX|AHC_NEW_TERMCTL|AHC_LARGE_SCBS - |AHC_TARGETMODE, - AHC_AIC7892_FE = AHC_AIC7890_FE|AHC_DT|AHC_AUTORATE|AHC_AUTOPAUSE, - AHC_AIC7895_FE = AHC_AIC7880_FE|AHC_MORE_SRAM|AHC_AUTOPAUSE - |AHC_CMD_CHAN|AHC_MULTI_FUNC|AHC_LARGE_SCBS, - AHC_AIC7895C_FE = AHC_AIC7895_FE|AHC_MULTI_TID, - AHC_AIC7896_FE = AHC_AIC7890_FE|AHC_MULTI_FUNC, - AHC_AIC7899_FE = AHC_AIC7892_FE|AHC_MULTI_FUNC -} ahc_feature; - -/* - * Bugs in the silicon that we work around in software. - */ -typedef enum { - AHC_BUGNONE = 0x00, - /* - * On all chips prior to the U2 product line, - * the WIDEODD S/G segment feature does not - * work during scsi->HostBus transfers. - */ - AHC_TMODE_WIDEODD_BUG = 0x01, - /* - * On the aic7890/91 Rev 0 chips, the autoflush - * feature does not work. A manual flush of - * the DMA FIFO is required. - */ - AHC_AUTOFLUSH_BUG = 0x02, - /* - * On many chips, cacheline streaming does not work. - */ - AHC_CACHETHEN_BUG = 0x04, - /* - * On the aic7896/97 chips, cacheline - * streaming must be enabled. - */ - AHC_CACHETHEN_DIS_BUG = 0x08, - /* - * PCI 2.1 Retry failure on non-empty data fifo. - */ - AHC_PCI_2_1_RETRY_BUG = 0x10, - /* - * Controller does not handle cacheline residuals - * properly on S/G segments if PCI MWI instructions - * are allowed. - */ - AHC_PCI_MWI_BUG = 0x20, - /* - * An SCB upload using the SCB channel's - * auto array entry copy feature may - * corrupt data. This appears to only - * occur on 66MHz systems. - */ - AHC_SCBCHAN_UPLOAD_BUG = 0x40 -} ahc_bug; - -/* - * Configuration specific settings. - * The driver determines these settings by probing the - * chip/controller's configuration. - */ -typedef enum { - AHC_FNONE = 0x000, - AHC_PRIMARY_CHANNEL = 0x003,/* - * The channel that should - * be probed first. - */ - AHC_USEDEFAULTS = 0x004,/* - * For cards without an seeprom - * or a BIOS to initialize the chip's - * SRAM, we use the default target - * settings. - */ - AHC_SEQUENCER_DEBUG = 0x008, - AHC_SHARED_SRAM = 0x010, - AHC_LARGE_SEEPROM = 0x020,/* Uses C56_66 not C46 */ - AHC_RESET_BUS_A = 0x040, - AHC_RESET_BUS_B = 0x080, - AHC_EXTENDED_TRANS_A = 0x100, - AHC_EXTENDED_TRANS_B = 0x200, - AHC_TERM_ENB_A = 0x400, - AHC_TERM_ENB_B = 0x800, - AHC_INITIATORROLE = 0x1000,/* - * Allow initiator operations on - * this controller. - */ - AHC_TARGETROLE = 0x2000,/* - * Allow target operations on this - * controller. - */ - AHC_NEWEEPROM_FMT = 0x4000, - AHC_RESOURCE_SHORTAGE = 0x8000, - AHC_TQINFIFO_BLOCKED = 0x10000,/* Blocked waiting for ATIOs */ - AHC_INT50_SPEEDFLEX = 0x20000,/* - * Internal 50pin connector - * sits behind an aic3860 - */ - AHC_SCB_BTT = 0x40000,/* - * The busy targets table is - * stored in SCB space rather - * than SRAM. - */ - AHC_BIOS_ENABLED = 0x80000, - AHC_ALL_INTERRUPTS = 0x100000, - AHC_PAGESCBS = 0x400000, /* Enable SCB paging */ - AHC_EDGE_INTERRUPT = 0x800000, /* Device uses edge triggered ints */ - AHC_39BIT_ADDRESSING = 0x1000000, /* Use 39 bit addressing scheme. */ - AHC_LSCBS_ENABLED = 0x2000000, /* 64Byte SCBs enabled */ - AHC_SCB_CONFIG_USED = 0x4000000 /* No SEEPROM but SCB2 had info. */ -} ahc_flag; - -/************************* Hardware SCB Definition ***************************/ - -/* - * The driver keeps up to MAX_SCB scb structures per card in memory. The SCB - * consists of a "hardware SCB" mirroring the fields availible on the card - * and additional information the kernel stores for each transaction. - * - * To minimize space utilization, a portion of the hardware scb stores - * different data during different portions of a SCSI transaction. - * As initialized by the host driver for the initiator role, this area - * contains the SCSI cdb (or a pointer to the cdb) to be executed. After - * the cdb has been presented to the target, this area serves to store - * residual transfer information and the SCSI status byte. - * For the target role, the contents of this area do not change, but - * still serve a different purpose than for the initiator role. See - * struct target_data for details. - */ - -/* - * Status information embedded in the shared poriton of - * an SCB after passing the cdb to the target. The kernel - * driver will only read this data for transactions that - * complete abnormally (non-zero status byte). - */ -struct status_pkt { - uint32_t residual_datacnt; /* Residual in the current S/G seg */ - uint32_t residual_sg_ptr; /* The next S/G for this transfer */ - uint8_t scsi_status; /* Standard SCSI status byte */ -}; - -/* - * Target mode version of the shared data SCB segment. - */ -struct target_data { - uint32_t residual_datacnt; /* Residual in the current S/G seg */ - uint32_t residual_sg_ptr; /* The next S/G for this transfer */ - uint8_t scsi_status; /* SCSI status to give to initiator */ - uint8_t target_phases; /* Bitmap of phases to execute */ - uint8_t data_phase; /* Data-In or Data-Out */ - uint8_t initiator_tag; /* Initiator's transaction tag */ -}; - -struct hardware_scb { -/*0*/ union { - /* - * If the cdb is 12 bytes or less, we embed it directly - * in the SCB. For longer cdbs, we embed the address - * of the cdb payload as seen by the chip and a DMA - * is used to pull it in. - */ - uint8_t cdb[12]; - uint32_t cdb_ptr; - struct status_pkt status; - struct target_data tdata; - } shared_data; -/* - * A word about residuals. - * The scb is presented to the sequencer with the dataptr and datacnt - * fields initialized to the contents of the first S/G element to - * transfer. The sgptr field is initialized to the bus address for - * the S/G element that follows the first in the in core S/G array - * or'ed with the SG_FULL_RESID flag. Sgptr may point to an invalid - * S/G entry for this transfer (single S/G element transfer with the - * first elements address and length preloaded in the dataptr/datacnt - * fields). If no transfer is to occur, sgptr is set to SG_LIST_NULL. - * The SG_FULL_RESID flag ensures that the residual will be correctly - * noted even if no data transfers occur. Once the data phase is entered, - * the residual sgptr and datacnt are loaded from the sgptr and the - * datacnt fields. After each S/G element's dataptr and length are - * loaded into the hardware, the residual sgptr is advanced. After - * each S/G element is expired, its datacnt field is checked to see - * if the LAST_SEG flag is set. If so, SG_LIST_NULL is set in the - * residual sg ptr and the transfer is considered complete. If the - * sequencer determines that there is a residual in the tranfer, it - * will set the SG_RESID_VALID flag in sgptr and dma the scb back into - * host memory. To sumarize: - * - * Sequencer: - * o A residual has occurred if SG_FULL_RESID is set in sgptr, - * or residual_sgptr does not have SG_LIST_NULL set. - * - * o We are transfering the last segment if residual_datacnt has - * the SG_LAST_SEG flag set. - * - * Host: - * o A residual has occurred if a completed scb has the - * SG_RESID_VALID flag set. - * - * o residual_sgptr and sgptr refer to the "next" sg entry - * and so may point beyond the last valid sg entry for the - * transfer. - */ -/*12*/ uint32_t dataptr; -/*16*/ uint32_t datacnt; /* - * Byte 3 (numbered from 0) of - * the datacnt is really the - * 4th byte in that data address. - */ -/*20*/ uint32_t sgptr; -#define SG_PTR_MASK 0xFFFFFFF8 -/*24*/ uint8_t control; /* See SCB_CONTROL in aic7xxx.reg for details */ -/*25*/ uint8_t scsiid; /* what to load in the SCSIID register */ -/*26*/ uint8_t lun; -/*27*/ uint8_t tag; /* - * Index into our kernel SCB array. - * Also used as the tag for tagged I/O - */ -/*28*/ uint8_t cdb_len; -/*29*/ uint8_t scsirate; /* Value for SCSIRATE register */ -/*30*/ uint8_t scsioffset; /* Value for SCSIOFFSET register */ -/*31*/ uint8_t next; /* - * Used for threading SCBs in the - * "Waiting for Selection" and - * "Disconnected SCB" lists down - * in the sequencer. - */ -/*32*/ uint8_t cdb32[32]; /* - * CDB storage for cdbs of size - * 13->32. We store them here - * because hardware scbs are - * allocated from DMA safe - * memory so we are guaranteed - * the controller can access - * this data. - */ -}; - -/************************ Kernel SCB Definitions ******************************/ -/* - * Some fields of the SCB are OS dependent. Here we collect the - * definitions for elements that all OS platforms need to include - * in there SCB definition. - */ - -/* - * Definition of a scatter/gather element as transfered to the controller. - * The aic7xxx chips only support a 24bit length. We use the top byte of - * the length to store additional address bits and a flag to indicate - * that a given segment terminates the transfer. This gives us an - * addressable range of 512GB on machines with 64bit PCI or with chips - * that can support dual address cycles on 32bit PCI busses. - */ -struct ahc_dma_seg { - uint32_t addr; - uint32_t len; -#define AHC_DMA_LAST_SEG 0x80000000 -#define AHC_SG_HIGH_ADDR_MASK 0x7F000000 -#define AHC_SG_LEN_MASK 0x00FFFFFF -}; - -struct sg_map_node { - bus_dmamap_t sg_dmamap; - bus_addr_t sg_physaddr; - struct ahc_dma_seg* sg_vaddr; - SLIST_ENTRY(sg_map_node) links; -}; - -/* - * The current state of this SCB. - */ -typedef enum { - SCB_FREE = 0x0000, - SCB_OTHERTCL_TIMEOUT = 0x0002,/* - * Another device was active - * during the first timeout for - * this SCB so we gave ourselves - * an additional timeout period - * in case it was hogging the - * bus. - */ - SCB_DEVICE_RESET = 0x0004, - SCB_SENSE = 0x0008, - SCB_CDB32_PTR = 0x0010, - SCB_RECOVERY_SCB = 0x0020, - SCB_AUTO_NEGOTIATE = 0x0040,/* Negotiate to achieve goal. */ - SCB_NEGOTIATE = 0x0080,/* Negotiation forced for command. */ - SCB_ABORT = 0x1000, - SCB_UNTAGGEDQ = 0x2000, - SCB_ACTIVE = 0x4000, - SCB_TARGET_IMMEDIATE = 0x8000 -} scb_flag; - -struct scb { - struct hardware_scb *hscb; - union { - SLIST_ENTRY(scb) sle; - TAILQ_ENTRY(scb) tqe; - } links; - LIST_ENTRY(scb) pending_links; - ahc_io_ctx_t io_ctx; - struct ahc_softc *ahc_softc; - scb_flag flags; -#ifndef __linux__ - bus_dmamap_t dmamap; -#endif - struct scb_platform_data *platform_data; - struct sg_map_node *sg_map; - struct ahc_dma_seg *sg_list; - bus_addr_t sg_list_phys; - u_int sg_count;/* How full ahc_dma_seg is */ -}; - -struct scb_data { - SLIST_HEAD(, scb) free_scbs; /* - * Pool of SCBs ready to be assigned - * commands to execute. - */ - struct scb *scbindex[256]; /* - * Mapping from tag to SCB. - * As tag identifiers are an - * 8bit value, we provide space - * for all possible tag values. - * Any lookups to entries at or - * above AHC_SCB_MAX_ALLOC will - * always fail. - */ - struct hardware_scb *hscbs; /* Array of hardware SCBs */ - struct scb *scbarray; /* Array of kernel SCBs */ - struct scsi_sense_data *sense; /* Per SCB sense data */ - - /* - * "Bus" addresses of our data structures. - */ - bus_dma_tag_t hscb_dmat; /* dmat for our hardware SCB array */ - bus_dmamap_t hscb_dmamap; - bus_addr_t hscb_busaddr; - bus_dma_tag_t sense_dmat; - bus_dmamap_t sense_dmamap; - bus_addr_t sense_busaddr; - bus_dma_tag_t sg_dmat; /* dmat for our sg segments */ - SLIST_HEAD(, sg_map_node) sg_maps; - uint8_t numscbs; - uint8_t maxhscbs; /* Number of SCBs on the card */ - uint8_t init_level; /* - * How far we've initialized - * this structure. - */ -}; - -/************************ Target Mode Definitions *****************************/ - -/* - * Connection desciptor for select-in requests in target mode. - */ -struct target_cmd { - uint8_t scsiid; /* Our ID and the initiator's ID */ - uint8_t identify; /* Identify message */ - uint8_t bytes[22]; /* - * Bytes contains any additional message - * bytes terminated by 0xFF. The remainder - * is the cdb to execute. - */ - uint8_t cmd_valid; /* - * When a command is complete, the firmware - * will set cmd_valid to all bits set. - * After the host has seen the command, - * the bits are cleared. This allows us - * to just peek at host memory to determine - * if more work is complete. cmd_valid is on - * an 8 byte boundary to simplify setting - * it on aic7880 hardware which only has - * limited direct access to the DMA FIFO. - */ - uint8_t pad[7]; -}; - -/* - * Number of events we can buffer up if we run out - * of immediate notify ccbs. - */ -#define AHC_TMODE_EVENT_BUFFER_SIZE 8 -struct ahc_tmode_event { - uint8_t initiator_id; - uint8_t event_type; /* MSG type or EVENT_TYPE_BUS_RESET */ -#define EVENT_TYPE_BUS_RESET 0xFF - uint8_t event_arg; -}; - -/* - * Per enabled lun target mode state. - * As this state is directly influenced by the host OS'es target mode - * environment, we let the OS module define it. Forward declare the - * structure here so we can store arrays of them, etc. in OS neutral - * data structures. - */ -#ifdef AHC_TARGET_MODE -struct ahc_tmode_lstate { - struct cam_path *path; - struct ccb_hdr_slist accept_tios; - struct ccb_hdr_slist immed_notifies; - struct ahc_tmode_event event_buffer[AHC_TMODE_EVENT_BUFFER_SIZE]; - uint8_t event_r_idx; - uint8_t event_w_idx; -}; -#else -struct ahc_tmode_lstate; -#endif - -/******************** Transfer Negotiation Datastructures *********************/ -#define AHC_TRANS_CUR 0x01 /* Modify current neogtiation status */ -#define AHC_TRANS_ACTIVE 0x03 /* Assume this target is on the bus */ -#define AHC_TRANS_GOAL 0x04 /* Modify negotiation goal */ -#define AHC_TRANS_USER 0x08 /* Modify user negotiation settings */ - -/* - * Transfer Negotiation Information. - */ -struct ahc_transinfo { - uint8_t protocol_version; /* SCSI Revision level */ - uint8_t transport_version; /* SPI Revision level */ - uint8_t width; /* Bus width */ - uint8_t period; /* Sync rate factor */ - uint8_t offset; /* Sync offset */ - uint8_t ppr_options; /* Parallel Protocol Request options */ -}; - -/* - * Per-initiator current, goal and user transfer negotiation information. */ -struct ahc_initiator_tinfo { - uint8_t scsirate; /* Computed value for SCSIRATE reg */ - struct ahc_transinfo curr; - struct ahc_transinfo goal; - struct ahc_transinfo user; -}; - -/* - * Per enabled target ID state. - * Pointers to lun target state as well as sync/wide negotiation information - * for each initiator<->target mapping. For the initiator role we pretend - * that we are the target and the targets are the initiators since the - * negotiation is the same regardless of role. - */ -struct ahc_tmode_tstate { - struct ahc_tmode_lstate* enabled_luns[AHC_NUM_LUNS]; - struct ahc_initiator_tinfo transinfo[AHC_NUM_TARGETS]; - - /* - * Per initiator state bitmasks. - */ - uint16_t auto_negotiate;/* Auto Negotiation Required */ - uint16_t ultraenb; /* Using ultra sync rate */ - uint16_t discenable; /* Disconnection allowed */ - uint16_t tagenable; /* Tagged Queuing allowed */ -}; - -/* - * Data structure for our table of allowed synchronous transfer rates. - */ -struct ahc_syncrate { - u_int sxfr_u2; /* Value of the SXFR parameter for Ultra2+ Chips */ - u_int sxfr; /* Value of the SXFR parameter for <= Ultra Chips */ -#define ULTRA_SXFR 0x100 /* Rate Requires Ultra Mode set */ -#define ST_SXFR 0x010 /* Rate Single Transition Only */ -#define DT_SXFR 0x040 /* Rate Double Transition Only */ - uint8_t period; /* Period to send to SCSI target */ - char *rate; -}; - -/* - * The synchronouse transfer rate table. - */ -extern struct ahc_syncrate ahc_syncrates[]; - -/* - * Indexes into our table of syncronous transfer rates. - */ -#define AHC_SYNCRATE_DT 0 -#define AHC_SYNCRATE_ULTRA2 1 -#define AHC_SYNCRATE_ULTRA 3 -#define AHC_SYNCRATE_FAST 6 - -/***************************** Lookup Tables **********************************/ -/* - * Phase -> name and message out response - * to parity errors in each phase table. - */ -struct ahc_phase_table_entry { - uint8_t phase; - uint8_t mesg_out; /* Message response to parity errors */ - char *phasemsg; -}; - -/************************** Serial EEPROM Format ******************************/ - -struct seeprom_config { -/* - * Per SCSI ID Configuration Flags - */ - uint16_t device_flags[16]; /* words 0-15 */ -#define CFXFER 0x0007 /* synchronous transfer rate */ -#define CFSYNCH 0x0008 /* enable synchronous transfer */ -#define CFDISC 0x0010 /* enable disconnection */ -#define CFWIDEB 0x0020 /* wide bus device */ -#define CFSYNCHISULTRA 0x0040 /* CFSYNCH is an ultra offset (2940AU)*/ -#define CFSYNCSINGLE 0x0080 /* Single-Transition signalling */ -#define CFSTART 0x0100 /* send start unit SCSI command */ -#define CFINCBIOS 0x0200 /* include in BIOS scan */ -#define CFRNFOUND 0x0400 /* report even if not found */ -#define CFMULTILUNDEV 0x0800 /* Probe multiple luns in BIOS scan */ -#define CFWBCACHEENB 0x4000 /* Enable W-Behind Cache on disks */ -#define CFWBCACHENOP 0xc000 /* Don't touch W-Behind Cache */ - -/* - * BIOS Control Bits - */ - uint16_t bios_control; /* word 16 */ -#define CFSUPREM 0x0001 /* support all removeable drives */ -#define CFSUPREMB 0x0002 /* support removeable boot drives */ -#define CFBIOSEN 0x0004 /* BIOS enabled */ -#define CFBIOS_BUSSCAN 0x0008 /* Have the BIOS Scan the Bus */ -#define CFSM2DRV 0x0010 /* support more than two drives */ -#define CFSTPWLEVEL 0x0010 /* Termination level control */ -#define CF284XEXTEND 0x0020 /* extended translation (284x cards) */ -#define CFCTRL_A 0x0020 /* BIOS displays Ctrl-A message */ -#define CFTERM_MENU 0x0040 /* BIOS displays termination menu */ -#define CFEXTEND 0x0080 /* extended translation enabled */ -#define CFSCAMEN 0x0100 /* SCAM enable */ -#define CFMSG_LEVEL 0x0600 /* BIOS Message Level */ -#define CFMSG_VERBOSE 0x0000 -#define CFMSG_SILENT 0x0200 -#define CFMSG_DIAG 0x0400 -#define CFBOOTCD 0x0800 /* Support Bootable CD-ROM */ -/* UNUSED 0xff00 */ - -/* - * Host Adapter Control Bits - */ - uint16_t adapter_control; /* word 17 */ -#define CFAUTOTERM 0x0001 /* Perform Auto termination */ -#define CFULTRAEN 0x0002 /* Ultra SCSI speed enable */ -#define CF284XSELTO 0x0003 /* Selection timeout (284x cards) */ -#define CF284XFIFO 0x000C /* FIFO Threshold (284x cards) */ -#define CFSTERM 0x0004 /* SCSI low byte termination */ -#define CFWSTERM 0x0008 /* SCSI high byte termination */ -#define CFSPARITY 0x0010 /* SCSI parity */ -#define CF284XSTERM 0x0020 /* SCSI low byte term (284x cards) */ -#define CFMULTILUN 0x0020 -#define CFRESETB 0x0040 /* reset SCSI bus at boot */ -#define CFCLUSTERENB 0x0080 /* Cluster Enable */ -#define CFBOOTCHAN 0x0300 /* probe this channel first */ -#define CFBOOTCHANSHIFT 8 -#define CFSEAUTOTERM 0x0400 /* Ultra2 Perform secondary Auto Term*/ -#define CFSELOWTERM 0x0800 /* Ultra2 secondary low term */ -#define CFSEHIGHTERM 0x1000 /* Ultra2 secondary high term */ -#define CFDOMAINVAL 0x4000 /* Perform Domain Validation*/ - -/* - * Bus Release Time, Host Adapter ID - */ - uint16_t brtime_id; /* word 18 */ -#define CFSCSIID 0x000f /* host adapter SCSI ID */ -/* UNUSED 0x00f0 */ -#define CFBRTIME 0xff00 /* bus release time */ - -/* - * Maximum targets - */ - uint16_t max_targets; /* word 19 */ -#define CFMAXTARG 0x00ff /* maximum targets */ -#define CFBOOTLUN 0x0f00 /* Lun to boot from */ -#define CFBOOTID 0xf000 /* Target to boot from */ - uint16_t res_1[10]; /* words 20-29 */ - uint16_t signature; /* Signature == 0x250 */ -#define CFSIGNATURE 0x250 -#define CFSIGNATURE2 0x300 - uint16_t checksum; /* word 31 */ -}; - -/**************************** Message Buffer *********************************/ -typedef enum { - MSG_TYPE_NONE = 0x00, - MSG_TYPE_INITIATOR_MSGOUT = 0x01, - MSG_TYPE_INITIATOR_MSGIN = 0x02, - MSG_TYPE_TARGET_MSGOUT = 0x03, - MSG_TYPE_TARGET_MSGIN = 0x04 -} ahc_msg_type; - -typedef enum { - MSGLOOP_IN_PROG, - MSGLOOP_MSGCOMPLETE, - MSGLOOP_TERMINATED -} msg_loop_stat; - -/*********************** Software Configuration Structure *********************/ -TAILQ_HEAD(scb_tailq, scb); - -struct ahc_suspend_channel_state { - uint8_t scsiseq; - uint8_t sxfrctl0; - uint8_t sxfrctl1; - uint8_t simode0; - uint8_t simode1; - uint8_t seltimer; - uint8_t seqctl; -}; - -struct ahc_suspend_state { - struct ahc_suspend_channel_state channel[2]; - uint8_t optionmode; - uint8_t dscommand0; - uint8_t dspcistatus; - /* hsmailbox */ - uint8_t crccontrol1; - uint8_t scbbaddr; - /* Host and sequencer SCB counts */ - uint8_t dff_thrsh; - uint8_t *scratch_ram; - uint8_t *btt; -}; - -typedef void (*ahc_bus_intr_t)(struct ahc_softc *); - -struct ahc_softc { - bus_space_tag_t tag; - bus_space_handle_t bsh; -#ifndef __linux__ - bus_dma_tag_t buffer_dmat; /* dmat for buffer I/O */ -#endif - struct scb_data *scb_data; - - struct scb *next_queued_scb; - - /* - * SCBs that have been sent to the controller - */ - LIST_HEAD(, scb) pending_scbs; - - /* - * Counting lock for deferring the release of additional - * untagged transactions from the untagged_queues. When - * the lock is decremented to 0, all queues in the - * untagged_queues array are run. - */ - u_int untagged_queue_lock; - - /* - * Per-target queue of untagged-transactions. The - * transaction at the head of the queue is the - * currently pending untagged transaction for the - * target. The driver only allows a single untagged - * transaction per target. - */ - struct scb_tailq untagged_queues[AHC_NUM_TARGETS]; - - /* - * Platform specific data. - */ - struct ahc_platform_data *platform_data; - - /* - * Platform specific device information. - */ - ahc_dev_softc_t dev_softc; - - /* - * Bus specific device information. - */ - ahc_bus_intr_t bus_intr; - - /* - * Target mode related state kept on a per enabled lun basis. - * Targets that are not enabled will have null entries. - * As an initiator, we keep one target entry for our initiator - * ID to store our sync/wide transfer settings. - */ - struct ahc_tmode_tstate *enabled_targets[AHC_NUM_TARGETS]; - - /* - * The black hole device responsible for handling requests for - * disabled luns on enabled targets. - */ - struct ahc_tmode_lstate *black_hole; - - /* - * Device instance currently on the bus awaiting a continue TIO - * for a command that was not given the disconnect priveledge. - */ - struct ahc_tmode_lstate *pending_device; - - /* - * Card characteristics - */ - ahc_chip chip; - ahc_feature features; - ahc_bug bugs; - ahc_flag flags; - struct seeprom_config *seep_config; - - /* Values to store in the SEQCTL register for pause and unpause */ - uint8_t unpause; - uint8_t pause; - - /* Command Queues */ - uint8_t qoutfifonext; - uint8_t qinfifonext; - uint8_t *qoutfifo; - uint8_t *qinfifo; - - /* Critical Section Data */ - struct cs *critical_sections; - u_int num_critical_sections; - - /* Links for chaining softcs */ - TAILQ_ENTRY(ahc_softc) links; - - /* Channel Names ('A', 'B', etc.) */ - char channel; - char channel_b; - - /* Initiator Bus ID */ - uint8_t our_id; - uint8_t our_id_b; - - /* - * PCI error detection. - */ - int unsolicited_ints; - - /* - * Target incoming command FIFO. - */ - struct target_cmd *targetcmds; - uint8_t tqinfifonext; - - /* - * Incoming and outgoing message handling. - */ - uint8_t send_msg_perror; - ahc_msg_type msg_type; - uint8_t msgout_buf[12];/* Message we are sending */ - uint8_t msgin_buf[12];/* Message we are receiving */ - u_int msgout_len; /* Length of message to send */ - u_int msgout_index; /* Current index in msgout */ - u_int msgin_index; /* Current index in msgin */ - - /* - * Mapping information for data structures shared - * between the sequencer and kernel. - */ - bus_dma_tag_t parent_dmat; - bus_dma_tag_t shared_data_dmat; - bus_dmamap_t shared_data_dmamap; - bus_addr_t shared_data_busaddr; - - /* - * Bus address of the one byte buffer used to - * work-around a DMA bug for chips <= aic7880 - * in target mode. - */ - bus_addr_t dma_bug_buf; - - /* Information saved through suspend/resume cycles */ - struct ahc_suspend_state suspend_state; - - /* Number of enabled target mode device on this card */ - u_int enabled_luns; - - /* Initialization level of this data structure */ - u_int init_level; - - /* PCI cacheline size. */ - u_int pci_cachesize; - - /* Per-Unit descriptive information */ - const char *description; - char *name; - int unit; - - /* Selection Timer settings */ - int seltime; - int seltime_b; - - uint16_t user_discenable;/* Disconnection allowed */ - uint16_t user_tagenable;/* Tagged Queuing allowed */ -}; - -TAILQ_HEAD(ahc_softc_tailq, ahc_softc); -extern struct ahc_softc_tailq ahc_tailq; - -/************************ Active Device Information ***************************/ -typedef enum { - ROLE_UNKNOWN, - ROLE_INITIATOR, - ROLE_TARGET -} role_t; - -struct ahc_devinfo { - int our_scsiid; - int target_offset; - uint16_t target_mask; - u_int target; - u_int lun; - char channel; - role_t role; /* - * Only guaranteed to be correct if not - * in the busfree state. - */ -}; - -/****************************** PCI Structures ********************************/ -typedef int (ahc_device_setup_t)(struct ahc_softc *); - -struct ahc_pci_identity { - uint64_t full_id; - uint64_t id_mask; - char *name; - ahc_device_setup_t *setup; -}; -extern struct ahc_pci_identity ahc_pci_ident_table []; -extern const u_int ahc_num_pci_devs; - -/***************************** VL/EISA Declarations ***************************/ -struct aic7770_identity { - uint32_t full_id; - uint32_t id_mask; - char *name; - ahc_device_setup_t *setup; -}; -extern struct aic7770_identity aic7770_ident_table []; -extern const int ahc_num_aic7770_devs; - -#define AHC_EISA_SLOT_OFFSET 0xc00 -#define AHC_EISA_IOSIZE 0x100 - -/*************************** Function Declarations ****************************/ -/******************************************************************************/ -u_int ahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl); -void ahc_unbusy_tcl(struct ahc_softc *ahc, u_int tcl); -void ahc_busy_tcl(struct ahc_softc *ahc, - u_int tcl, u_int busyid); - -/***************************** PCI Front End *********************************/ -struct ahc_pci_identity *ahc_find_pci_device(ahc_dev_softc_t); -int ahc_pci_config(struct ahc_softc *, - struct ahc_pci_identity *); - -/*************************** EISA/VL Front End ********************************/ -struct aic7770_identity *aic7770_find_device(uint32_t); -int aic7770_config(struct ahc_softc *ahc, - struct aic7770_identity *, - u_int port); - -/************************** SCB and SCB queue management **********************/ -int ahc_probe_scbs(struct ahc_softc *); -void ahc_run_untagged_queues(struct ahc_softc *ahc); -void ahc_run_untagged_queue(struct ahc_softc *ahc, - struct scb_tailq *queue); -void ahc_qinfifo_requeue_tail(struct ahc_softc *ahc, - struct scb *scb); -int ahc_match_scb(struct ahc_softc *ahc, struct scb *scb, - int target, char channel, int lun, - u_int tag, role_t role); - -/****************************** Initialization ********************************/ -struct ahc_softc *ahc_alloc(void *platform_arg, char *name); -int ahc_softc_init(struct ahc_softc *); -void ahc_controller_info(struct ahc_softc *ahc, char *buf); -int ahc_init(struct ahc_softc *ahc); -void ahc_intr_enable(struct ahc_softc *ahc, int enable); -void ahc_pause_and_flushwork(struct ahc_softc *ahc); -int ahc_suspend(struct ahc_softc *ahc); -int ahc_resume(struct ahc_softc *ahc); -void ahc_softc_insert(struct ahc_softc *); -struct ahc_softc *ahc_find_softc(struct ahc_softc *ahc); -void ahc_set_unit(struct ahc_softc *, int); -void ahc_set_name(struct ahc_softc *, char *); -void ahc_alloc_scbs(struct ahc_softc *ahc); -void ahc_free(struct ahc_softc *ahc); -int ahc_reset(struct ahc_softc *ahc); -void ahc_shutdown(void *arg); - -/*************************** Interrupt Services *******************************/ -void ahc_pci_intr(struct ahc_softc *ahc); -void ahc_clear_intstat(struct ahc_softc *ahc); -void ahc_run_qoutfifo(struct ahc_softc *ahc); -#ifdef AHC_TARGET_MODE -void ahc_run_tqinfifo(struct ahc_softc *ahc, int paused); -#endif -void ahc_handle_brkadrint(struct ahc_softc *ahc); -void ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat); -void ahc_handle_scsiint(struct ahc_softc *ahc, - u_int intstat); -void ahc_clear_critical_section(struct ahc_softc *ahc); - -/***************************** Error Recovery *********************************/ -typedef enum { - SEARCH_COMPLETE, - SEARCH_COUNT, - SEARCH_REMOVE -} ahc_search_action; -int ahc_search_qinfifo(struct ahc_softc *ahc, int target, - char channel, int lun, u_int tag, - role_t role, uint32_t status, - ahc_search_action action); -int ahc_search_untagged_queues(struct ahc_softc *ahc, - ahc_io_ctx_t ctx, - int target, char channel, - int lun, uint32_t status, - ahc_search_action action); -int ahc_search_disc_list(struct ahc_softc *ahc, int target, - char channel, int lun, u_int tag, - int stop_on_first, int remove, - int save_state); -void ahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb); -int ahc_reset_channel(struct ahc_softc *ahc, char channel, - int initiate_reset); -int ahc_abort_scbs(struct ahc_softc *ahc, int target, - char channel, int lun, u_int tag, - role_t role, uint32_t status); -void ahc_restart(struct ahc_softc *ahc); -void ahc_calc_residual(struct ahc_softc *ahc, - struct scb *scb); -/*************************** Utility Functions ********************************/ -struct ahc_phase_table_entry* - ahc_lookup_phase_entry(int phase); -void ahc_compile_devinfo(struct ahc_devinfo *devinfo, - u_int our_id, u_int target, - u_int lun, char channel, - role_t role); -/************************** Transfer Negotiation ******************************/ -struct ahc_syncrate* ahc_find_syncrate(struct ahc_softc *ahc, u_int *period, - u_int *ppr_options, u_int maxsync); -u_int ahc_find_period(struct ahc_softc *ahc, - u_int scsirate, u_int maxsync); -void ahc_validate_offset(struct ahc_softc *ahc, - struct ahc_initiator_tinfo *tinfo, - struct ahc_syncrate *syncrate, - u_int *offset, int wide, - role_t role); -void ahc_validate_width(struct ahc_softc *ahc, - struct ahc_initiator_tinfo *tinfo, - u_int *bus_width, - role_t role); -int ahc_update_neg_request(struct ahc_softc*, - struct ahc_devinfo*, - struct ahc_tmode_tstate*, - struct ahc_initiator_tinfo*, - int /*force*/); -void ahc_set_width(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo, - u_int width, u_int type, int paused); -void ahc_set_syncrate(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo, - struct ahc_syncrate *syncrate, - u_int period, u_int offset, - u_int ppr_options, - u_int type, int paused); -typedef enum { - AHC_QUEUE_NONE, - AHC_QUEUE_BASIC, - AHC_QUEUE_TAGGED -} ahc_queue_alg; - -void ahc_set_tags(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo, - ahc_queue_alg alg); - -/**************************** Target Mode *************************************/ -#ifdef AHC_TARGET_MODE -void ahc_send_lstate_events(struct ahc_softc *, - struct ahc_tmode_lstate *); -void ahc_handle_en_lun(struct ahc_softc *ahc, - struct cam_sim *sim, union ccb *ccb); -cam_status ahc_find_tmode_devs(struct ahc_softc *ahc, - struct cam_sim *sim, union ccb *ccb, - struct ahc_tmode_tstate **tstate, - struct ahc_tmode_lstate **lstate, - int notfound_failure); -#ifndef AHC_TMODE_ENABLE -#define AHC_TMODE_ENABLE 0 -#endif -#endif -/******************************* Debug ***************************************/ -#ifdef AHC_DEBUG -extern int ahc_debug; -#define AHC_SHOWMISC 0x1 -#define AHC_SHOWSENSE 0x2 -#endif -void ahc_print_scb(struct scb *scb); -void ahc_dump_card_state(struct ahc_softc *ahc); -/******************************* SEEPROM *************************************/ -int ahc_acquire_seeprom(struct ahc_softc *ahc, - struct seeprom_descriptor *sd); -void ahc_release_seeprom(struct seeprom_descriptor *sd); -#endif /* _AIC7XXX_H_ */ diff --git a/xen/drivers/scsi/aic7xxx/aic7xxx.reg b/xen/drivers/scsi/aic7xxx/aic7xxx.reg deleted file mode 100644 index 954038bd34..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic7xxx.reg +++ /dev/null @@ -1,1588 +0,0 @@ -/* - * Aic7xxx register and scratch ram definitions. - * - * Copyright (c) 1994-2001 Justin T. Gibbs. - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.reg,v 1.20.2.11 2002/04/29 19:36:30 gibbs Exp $ - */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#30 $" - -/* - * This file is processed by the aic7xxx_asm utility for use in assembling - * firmware for the aic7xxx family of SCSI host adapters as well as to generate - * a C header file for use in the kernel portion of the Aic7xxx driver. - * - * All page numbers refer to the Adaptec AIC-7770 Data Book available from - * Adaptec's Technical Documents Department 1-800-934-2766 - */ - -/* - * SCSI Sequence Control (p. 3-11). - * Each bit, when set starts a specific SCSI sequence on the bus - */ -register SCSISEQ { - address 0x000 - access_mode RW - bit TEMODE 0x80 - bit ENSELO 0x40 - bit ENSELI 0x20 - bit ENRSELI 0x10 - bit ENAUTOATNO 0x08 - bit ENAUTOATNI 0x04 - bit ENAUTOATNP 0x02 - bit SCSIRSTO 0x01 -} - -/* - * SCSI Transfer Control 0 Register (pp. 3-13). - * Controls the SCSI module data path. - */ -register SXFRCTL0 { - address 0x001 - access_mode RW - bit DFON 0x80 - bit DFPEXP 0x40 - bit FAST20 0x20 - bit CLRSTCNT 0x10 - bit SPIOEN 0x08 - bit SCAMEN 0x04 - bit CLRCHN 0x02 -} - -/* - * SCSI Transfer Control 1 Register (pp. 3-14,15). - * Controls the SCSI module data path. - */ -register SXFRCTL1 { - address 0x002 - access_mode RW - bit BITBUCKET 0x80 - bit SWRAPEN 0x40 - bit ENSPCHK 0x20 - mask STIMESEL 0x18 - bit ENSTIMER 0x04 - bit ACTNEGEN 0x02 - bit STPWEN 0x01 /* Powered Termination */ -} - -/* - * SCSI Control Signal Read Register (p. 3-15). - * Reads the actual state of the SCSI bus pins - */ -register SCSISIGI { - address 0x003 - access_mode RO - bit CDI 0x80 - bit IOI 0x40 - bit MSGI 0x20 - bit ATNI 0x10 - bit SELI 0x08 - bit BSYI 0x04 - bit REQI 0x02 - bit ACKI 0x01 -/* - * Possible phases in SCSISIGI - */ - mask PHASE_MASK CDI|IOI|MSGI - mask P_DATAOUT 0x00 - mask P_DATAIN IOI - mask P_DATAOUT_DT P_DATAOUT|MSGI - mask P_DATAIN_DT P_DATAIN|MSGI - mask P_COMMAND CDI - mask P_MESGOUT CDI|MSGI - mask P_STATUS CDI|IOI - mask P_MESGIN CDI|IOI|MSGI -} - -/* - * SCSI Control Signal Write Register (p. 3-16). - * Writing to this register modifies the control signals on the bus. Only - * those signals that are allowed in the current mode (Initiator/Target) are - * asserted. - */ -register SCSISIGO { - address 0x003 - access_mode WO - bit CDO 0x80 - bit IOO 0x40 - bit MSGO 0x20 - bit ATNO 0x10 - bit SELO 0x08 - bit BSYO 0x04 - bit REQO 0x02 - bit ACKO 0x01 -/* - * Possible phases to write into SCSISIG0 - */ - mask PHASE_MASK CDI|IOI|MSGI - mask P_DATAOUT 0x00 - mask P_DATAIN IOI - mask P_COMMAND CDI - mask P_MESGOUT CDI|MSGI - mask P_STATUS CDI|IOI - mask P_MESGIN CDI|IOI|MSGI -} - -/* - * SCSI Rate Control (p. 3-17). - * Contents of this register determine the Synchronous SCSI data transfer - * rate and the maximum synchronous Req/Ack offset. An offset of 0 in the - * SOFS (3:0) bits disables synchronous data transfers. Any offset value - * greater than 0 enables synchronous transfers. - */ -register SCSIRATE { - address 0x004 - access_mode RW - bit WIDEXFER 0x80 /* Wide transfer control */ - bit ENABLE_CRC 0x40 /* CRC for D-Phases */ - bit SINGLE_EDGE 0x10 /* Disable DT Transfers */ - mask SXFR 0x70 /* Sync transfer rate */ - mask SXFR_ULTRA2 0x0f /* Sync transfer rate */ - mask SOFS 0x0f /* Sync offset */ -} - -/* - * SCSI ID (p. 3-18). - * Contains the ID of the board and the current target on the - * selected channel. - */ -register SCSIID { - address 0x005 - access_mode RW - mask TID 0xf0 /* Target ID mask */ - mask TWIN_TID 0x70 - bit TWIN_CHNLB 0x80 - mask OID 0x0f /* Our ID mask */ - /* - * SCSI Maximum Offset (p. 4-61 aic7890/91 Data Book) - * The aic7890/91 allow an offset of up to 127 transfers in both wide - * and narrow mode. - */ - alias SCSIOFFSET - mask SOFS_ULTRA2 0x7f /* Sync offset U2 chips */ -} - -/* - * SCSI Latched Data (p. 3-19). - * Read/Write latches used to transfer data on the SCSI bus during - * Automatic or Manual PIO mode. SCSIDATH can be used for the - * upper byte of a 16bit wide asynchronouse data phase transfer. - */ -register SCSIDATL { - address 0x006 - access_mode RW -} - -register SCSIDATH { - address 0x007 - access_mode RW -} - -/* - * SCSI Transfer Count (pp. 3-19,20) - * These registers count down the number of bytes transferred - * across the SCSI bus. The counter is decremented only once - * the data has been safely transferred. SDONE in SSTAT0 is - * set when STCNT goes to 0 - */ -register STCNT { - address 0x008 - size 3 - access_mode RW -} - -/* ALT_MODE register on Ultra160 chips */ -register OPTIONMODE { - address 0x008 - access_mode RW - bit AUTORATEEN 0x80 - bit AUTOACKEN 0x40 - bit ATNMGMNTEN 0x20 - bit BUSFREEREV 0x10 - bit EXPPHASEDIS 0x08 - bit SCSIDATL_IMGEN 0x04 - bit AUTO_MSGOUT_DE 0x02 - bit DIS_MSGIN_DUALEDGE 0x01 - mask OPTIONMODE_DEFAULTS AUTO_MSGOUT_DE|DIS_MSGIN_DUALEDGE -} - -/* ALT_MODE register on Ultra160 chips */ -register TARGCRCCNT { - address 0x00a - size 2 - access_mode RW -} - -/* - * Clear SCSI Interrupt 0 (p. 3-20) - * Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT0. - */ -register CLRSINT0 { - address 0x00b - access_mode WO - bit CLRSELDO 0x40 - bit CLRSELDI 0x20 - bit CLRSELINGO 0x10 - bit CLRSWRAP 0x08 - bit CLRIOERR 0x08 /* Ultra2 Only */ - bit CLRSPIORDY 0x02 -} - -/* - * SCSI Status 0 (p. 3-21) - * Contains one set of SCSI Interrupt codes - * These are most likely of interest to the sequencer - */ -register SSTAT0 { - address 0x00b - access_mode RO - bit TARGET 0x80 /* Board acting as target */ - bit SELDO 0x40 /* Selection Done */ - bit SELDI 0x20 /* Board has been selected */ - bit SELINGO 0x10 /* Selection In Progress */ - bit SWRAP 0x08 /* 24bit counter wrap */ - bit IOERR 0x08 /* LVD Tranceiver mode changed */ - bit SDONE 0x04 /* STCNT = 0x000000 */ - bit SPIORDY 0x02 /* SCSI PIO Ready */ - bit DMADONE 0x01 /* DMA transfer completed */ -} - -/* - * Clear SCSI Interrupt 1 (p. 3-23) - * Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT1. - */ -register CLRSINT1 { - address 0x00c - access_mode WO - bit CLRSELTIMEO 0x80 - bit CLRATNO 0x40 - bit CLRSCSIRSTI 0x20 - bit CLRBUSFREE 0x08 - bit CLRSCSIPERR 0x04 - bit CLRPHASECHG 0x02 - bit CLRREQINIT 0x01 -} - -/* - * SCSI Status 1 (p. 3-24) - */ -register SSTAT1 { - address 0x00c - access_mode RO - bit SELTO 0x80 - bit ATNTARG 0x40 - bit SCSIRSTI 0x20 - bit PHASEMIS 0x10 - bit BUSFREE 0x08 - bit SCSIPERR 0x04 - bit PHASECHG 0x02 - bit REQINIT 0x01 -} - -/* - * SCSI Status 2 (pp. 3-25,26) - */ -register SSTAT2 { - address 0x00d - access_mode RO - bit OVERRUN 0x80 - bit SHVALID 0x40 /* Shaddow Layer non-zero */ - bit EXP_ACTIVE 0x10 /* SCSI Expander Active */ - bit CRCVALERR 0x08 /* CRC doesn't match (U3 only) */ - bit CRCENDERR 0x04 /* No terminal CRC packet (U3 only) */ - bit CRCREQERR 0x02 /* Illegal CRC packet req (U3 only) */ - bit DUAL_EDGE_ERR 0x01 /* Incorrect data phase (U3 only) */ - mask SFCNT 0x1f -} - -/* - * SCSI Status 3 (p. 3-26) - */ -register SSTAT3 { - address 0x00e - access_mode RO - mask SCSICNT 0xf0 - mask OFFCNT 0x0f - mask U2OFFCNT 0x7f -} - -/* - * SCSI ID for the aic7890/91 chips - */ -register SCSIID_ULTRA2 { - address 0x00f - access_mode RW - mask TID 0xf0 /* Target ID mask */ - mask OID 0x0f /* Our ID mask */ -} - -/* - * SCSI Interrupt Mode 1 (p. 3-28) - * Setting any bit will enable the corresponding function - * in SIMODE0 to interrupt via the IRQ pin. - */ -register SIMODE0 { - address 0x010 - access_mode RW - bit ENSELDO 0x40 - bit ENSELDI 0x20 - bit ENSELINGO 0x10 - bit ENSWRAP 0x08 - bit ENIOERR 0x08 /* LVD Tranceiver mode changes */ - bit ENSDONE 0x04 - bit ENSPIORDY 0x02 - bit ENDMADONE 0x01 -} - -/* - * SCSI Interrupt Mode 1 (pp. 3-28,29) - * Setting any bit will enable the corresponding function - * in SIMODE1 to interrupt via the IRQ pin. - */ -register SIMODE1 { - address 0x011 - access_mode RW - bit ENSELTIMO 0x80 - bit ENATNTARG 0x40 - bit ENSCSIRST 0x20 - bit ENPHASEMIS 0x10 - bit ENBUSFREE 0x08 - bit ENSCSIPERR 0x04 - bit ENPHASECHG 0x02 - bit ENREQINIT 0x01 -} - -/* - * SCSI Data Bus (High) (p. 3-29) - * This register reads data on the SCSI Data bus directly. - */ -register SCSIBUSL { - address 0x012 - access_mode RW -} - -register SCSIBUSH { - address 0x013 - access_mode RW -} - -/* - * SCSI/Host Address (p. 3-30) - * These registers hold the host address for the byte about to be - * transferred on the SCSI bus. They are counted up in the same - * manner as STCNT is counted down. SHADDR should always be used - * to determine the address of the last byte transferred since HADDR - * can be skewed by write ahead. - */ -register SHADDR { - address 0x014 - size 4 - access_mode RO -} - -/* - * Selection Timeout Timer (p. 3-30) - */ -register SELTIMER { - address 0x018 - access_mode RW - bit STAGE6 0x20 - bit STAGE5 0x10 - bit STAGE4 0x08 - bit STAGE3 0x04 - bit STAGE2 0x02 - bit STAGE1 0x01 - alias TARGIDIN -} - -/* - * Selection/Reselection ID (p. 3-31) - * Upper four bits are the device id. The ONEBIT is set when the re/selecting - * device did not set its own ID. - */ -register SELID { - address 0x019 - access_mode RW - mask SELID_MASK 0xf0 - bit ONEBIT 0x08 -} - -register SCAMCTL { - address 0x01a - access_mode RW - bit ENSCAMSELO 0x80 - bit CLRSCAMSELID 0x40 - bit ALTSTIM 0x20 - bit DFLTTID 0x10 - mask SCAMLVL 0x03 -} - -/* - * Target Mode Selecting in ID bitmask (aic7890/91/96/97) - */ -register TARGID { - address 0x01b - size 2 - access_mode RW -} - -/* - * Serial Port I/O Cabability register (p. 4-95 aic7860 Data Book) - * Indicates if external logic has been attached to the chip to - * perform the tasks of accessing a serial eeprom, testing termination - * strength, and performing cable detection. On the aic7860, most of - * these features are handled on chip, but on the aic7855 an attached - * aic3800 does the grunt work. - */ -register SPIOCAP { - address 0x01b - access_mode RW - bit SOFT1 0x80 - bit SOFT0 0x40 - bit SOFTCMDEN 0x20 - bit EXT_BRDCTL 0x10 /* External Board control */ - bit SEEPROM 0x08 /* External serial eeprom logic */ - bit EEPROM 0x04 /* Writable external BIOS ROM */ - bit ROM 0x02 /* Logic for accessing external ROM */ - bit SSPIOCPS 0x01 /* Termination and cable detection */ -} - -register BRDCTL { - address 0x01d - bit BRDDAT7 0x80 - bit BRDDAT6 0x40 - bit BRDDAT5 0x20 - bit BRDSTB 0x10 - bit BRDCS 0x08 - bit BRDRW 0x04 - bit BRDCTL1 0x02 - bit BRDCTL0 0x01 - /* 7890 Definitions */ - bit BRDDAT4 0x10 - bit BRDDAT3 0x08 - bit BRDDAT2 0x04 - bit BRDRW_ULTRA2 0x02 - bit BRDSTB_ULTRA2 0x01 -} - -/* - * Serial EEPROM Control (p. 4-92 in 7870 Databook) - * Controls the reading and writing of an external serial 1-bit - * EEPROM Device. In order to access the serial EEPROM, you must - * first set the SEEMS bit that generates a request to the memory - * port for access to the serial EEPROM device. When the memory - * port is not busy servicing another request, it reconfigures - * to allow access to the serial EEPROM. When this happens, SEERDY - * gets set high to verify that the memory port access has been - * granted. - * - * After successful arbitration for the memory port, the SEECS bit of - * the SEECTL register is connected to the chip select. The SEECK, - * SEEDO, and SEEDI are connected to the clock, data out, and data in - * lines respectively. The SEERDY bit of SEECTL is useful in that it - * gives us an 800 nsec timer. After a write to the SEECTL register, - * the SEERDY goes high 800 nsec later. The one exception to this is - * when we first request access to the memory port. The SEERDY goes - * high to signify that access has been granted and, for this case, has - * no implied timing. - * - * See 93cx6.c for detailed information on the protocol necessary to - * read the serial EEPROM. - */ -register SEECTL { - address 0x01e - bit EXTARBACK 0x80 - bit EXTARBREQ 0x40 - bit SEEMS 0x20 - bit SEERDY 0x10 - bit SEECS 0x08 - bit SEECK 0x04 - bit SEEDO 0x02 - bit SEEDI 0x01 -} -/* - * SCSI Block Control (p. 3-32) - * Controls Bus type and channel selection. In a twin channel configuration - * addresses 0x00-0x1e are gated to the appropriate channel based on this - * register. SELWIDE allows for the coexistence of 8bit and 16bit devices - * on a wide bus. - */ -register SBLKCTL { - address 0x01f - access_mode RW - bit DIAGLEDEN 0x80 /* Aic78X0 only */ - bit DIAGLEDON 0x40 /* Aic78X0 only */ - bit AUTOFLUSHDIS 0x20 - bit SELBUSB 0x08 - bit ENAB40 0x08 /* LVD transceiver active */ - bit ENAB20 0x04 /* SE/HVD transceiver active */ - bit SELWIDE 0x02 - bit XCVR 0x01 /* External transceiver active */ -} - -/* - * Sequencer Control (p. 3-33) - * Error detection mode and speed configuration - */ -register SEQCTL { - address 0x060 - access_mode RW - bit PERRORDIS 0x80 - bit PAUSEDIS 0x40 - bit FAILDIS 0x20 - bit FASTMODE 0x10 - bit BRKADRINTEN 0x08 - bit STEP 0x04 - bit SEQRESET 0x02 - bit LOADRAM 0x01 -} - -/* - * Sequencer RAM Data (p. 3-34) - * Single byte window into the Scratch Ram area starting at the address - * specified by SEQADDR0 and SEQADDR1. To write a full word, simply write - * four bytes in succession. The SEQADDRs will increment after the most - * significant byte is written - */ -register SEQRAM { - address 0x061 - access_mode RW -} - -/* - * Sequencer Address Registers (p. 3-35) - * Only the first bit of SEQADDR1 holds addressing information - */ -register SEQADDR0 { - address 0x062 - access_mode RW -} - -register SEQADDR1 { - address 0x063 - access_mode RW - mask SEQADDR1_MASK 0x01 -} - -/* - * Accumulator - * We cheat by passing arguments in the Accumulator up to the kernel driver - */ -register ACCUM { - address 0x064 - access_mode RW - accumulator -} - -register SINDEX { - address 0x065 - access_mode RW - sindex -} - -register DINDEX { - address 0x066 - access_mode RW -} - -register ALLONES { - address 0x069 - access_mode RO - allones -} - -register ALLZEROS { - address 0x06a - access_mode RO - allzeros -} - -register NONE { - address 0x06a - access_mode WO - none -} - -register FLAGS { - address 0x06b - access_mode RO - bit ZERO 0x02 - bit CARRY 0x01 -} - -register SINDIR { - address 0x06c - access_mode RO -} - -register DINDIR { - address 0x06d - access_mode WO -} - -register FUNCTION1 { - address 0x06e - access_mode RW -} - -register STACK { - address 0x06f - access_mode RO -} - -/* - * Board Control (p. 3-43) - */ -register BCTL { - address 0x084 - access_mode RW - bit ACE 0x08 - bit ENABLE 0x01 -} - -/* - * On the aic78X0 chips, Board Control is replaced by the DSCommand - * register (p. 4-64) - */ -register DSCOMMAND0 { - address 0x084 - access_mode RW - bit CACHETHEN 0x80 /* Cache Threshold enable */ - bit DPARCKEN 0x40 /* Data Parity Check Enable */ - bit MPARCKEN 0x20 /* Memory Parity Check Enable */ - bit EXTREQLCK 0x10 /* External Request Lock */ - /* aic7890/91/96/97 only */ - bit INTSCBRAMSEL 0x08 /* Internal SCB RAM Select */ - bit RAMPS 0x04 /* External SCB RAM Present */ - bit USCBSIZE32 0x02 /* Use 32byte SCB Page Size */ - bit CIOPARCKEN 0x01 /* Internal bus parity error enable */ -} - -register DSCOMMAND1 { - address 0x085 - access_mode RW - mask DSLATT 0xfc /* PCI latency timer (non-ultra2) */ - bit HADDLDSEL1 0x02 /* Host Address Load Select Bits */ - bit HADDLDSEL0 0x01 -} - -/* - * Bus On/Off Time (p. 3-44) aic7770 only - */ -register BUSTIME { - address 0x085 - access_mode RW - mask BOFF 0xf0 - mask BON 0x0f -} - -/* - * Bus Speed (p. 3-45) aic7770 only - */ -register BUSSPD { - address 0x086 - access_mode RW - mask DFTHRSH 0xc0 - mask STBOFF 0x38 - mask STBON 0x07 - mask DFTHRSH_100 0xc0 - mask DFTHRSH_75 0x80 -} - -/* aic7850/55/60/70/80/95 only */ -register DSPCISTATUS { - address 0x086 - mask DFTHRSH_100 0xc0 -} - -/* aic7890/91/96/97 only */ -register HS_MAILBOX { - address 0x086 - mask HOST_MAILBOX 0xF0 - mask SEQ_MAILBOX 0x0F - mask HOST_TQINPOS 0x80 /* Boundary at either 0 or 128 */ -} - -const HOST_MAILBOX_SHIFT 4 -const SEQ_MAILBOX_SHIFT 0 - -/* - * Host Control (p. 3-47) R/W - * Overall host control of the device. - */ -register HCNTRL { - address 0x087 - access_mode RW - bit POWRDN 0x40 - bit SWINT 0x10 - bit IRQMS 0x08 - bit PAUSE 0x04 - bit INTEN 0x02 - bit CHIPRST 0x01 - bit CHIPRSTACK 0x01 -} - -/* - * Host Address (p. 3-48) - * This register contains the address of the byte about - * to be transferred across the host bus. - */ -register HADDR { - address 0x088 - size 4 - access_mode RW -} - -register HCNT { - address 0x08c - size 3 - access_mode RW -} - -/* - * SCB Pointer (p. 3-49) - * Gate one of the SCBs into the SCBARRAY window. - */ -register SCBPTR { - address 0x090 - access_mode RW -} - -/* - * Interrupt Status (p. 3-50) - * Status for system interrupts - */ -register INTSTAT { - address 0x091 - access_mode RW - bit BRKADRINT 0x08 - bit SCSIINT 0x04 - bit CMDCMPLT 0x02 - bit SEQINT 0x01 - mask BAD_PHASE SEQINT /* unknown scsi bus phase */ - mask SEND_REJECT 0x10|SEQINT /* sending a message reject */ - mask NO_IDENT 0x20|SEQINT /* no IDENTIFY after reconnect*/ - mask NO_MATCH 0x30|SEQINT /* no cmd match for reconnect */ - mask IGN_WIDE_RES 0x40|SEQINT /* Complex IGN Wide Res Msg */ - mask PDATA_REINIT 0x50|SEQINT /* - * Returned to data phase - * that requires data - * transfer pointers to be - * recalculated from the - * transfer residual. - */ - mask HOST_MSG_LOOP 0x60|SEQINT /* - * The bus is ready for the - * host to perform another - * message transaction. This - * mechanism is used for things - * like sync/wide negotiation - * that require a kernel based - * message state engine. - */ - mask BAD_STATUS 0x70|SEQINT /* Bad status from target */ - mask PERR_DETECTED 0x80|SEQINT /* - * Either the phase_lock - * or inb_next routine has - * noticed a parity error. - */ - mask DATA_OVERRUN 0x90|SEQINT /* - * Target attempted to write - * beyond the bounds of its - * command. - */ - mask MKMSG_FAILED 0xa0|SEQINT /* - * Target completed command - * without honoring our ATN - * request to issue a message. - */ - mask MISSED_BUSFREE 0xb0|SEQINT /* - * The sequencer never saw - * the bus go free after - * either a command complete - * or disconnect message. - */ - mask SCB_MISMATCH 0xc0|SEQINT /* - * Downloaded SCB's tag does - * not match the entry we - * intended to download. - */ - mask NO_FREE_SCB 0xd0|SEQINT /* - * get_free_or_disc_scb failed. - */ - mask OUT_OF_RANGE 0xe0|SEQINT - - mask SEQINT_MASK 0xf0|SEQINT /* SEQINT Status Codes */ - mask INT_PEND (BRKADRINT|SEQINT|SCSIINT|CMDCMPLT) -} - -/* - * Hard Error (p. 3-53) - * Reporting of catastrophic errors. You usually cannot recover from - * these without a full board reset. - */ -register ERROR { - address 0x092 - access_mode RO - bit CIOPARERR 0x80 /* Ultra2 only */ - bit PCIERRSTAT 0x40 /* PCI only */ - bit MPARERR 0x20 /* PCI only */ - bit DPARERR 0x10 /* PCI only */ - bit SQPARERR 0x08 - bit ILLOPCODE 0x04 - bit ILLSADDR 0x02 - bit ILLHADDR 0x01 -} - -/* - * Clear Interrupt Status (p. 3-52) - */ -register CLRINT { - address 0x092 - access_mode WO - bit CLRPARERR 0x10 /* PCI only */ - bit CLRBRKADRINT 0x08 - bit CLRSCSIINT 0x04 - bit CLRCMDINT 0x02 - bit CLRSEQINT 0x01 -} - -register DFCNTRL { - address 0x093 - access_mode RW - bit PRELOADEN 0x80 /* aic7890 only */ - bit WIDEODD 0x40 - bit SCSIEN 0x20 - bit SDMAEN 0x10 - bit SDMAENACK 0x10 - bit HDMAEN 0x08 - bit HDMAENACK 0x08 - bit DIRECTION 0x04 - bit FIFOFLUSH 0x02 - bit FIFORESET 0x01 -} - -register DFSTATUS { - address 0x094 - access_mode RO - bit PRELOAD_AVAIL 0x80 - bit DFCACHETH 0x40 - bit FIFOQWDEMP 0x20 - bit MREQPEND 0x10 - bit HDONE 0x08 - bit DFTHRESH 0x04 - bit FIFOFULL 0x02 - bit FIFOEMP 0x01 -} - -register DFWADDR { - address 0x95 - access_mode RW -} - -register DFRADDR { - address 0x97 - access_mode RW -} - -register DFDAT { - address 0x099 - access_mode RW -} - -/* - * SCB Auto Increment (p. 3-59) - * Byte offset into the SCB Array and an optional bit to allow auto - * incrementing of the address during download and upload operations - */ -register SCBCNT { - address 0x09a - access_mode RW - bit SCBAUTO 0x80 - mask SCBCNT_MASK 0x1f -} - -/* - * Queue In FIFO (p. 3-60) - * Input queue for queued SCBs (commands that the seqencer has yet to start) - */ -register QINFIFO { - address 0x09b - access_mode RW -} - -/* - * Queue In Count (p. 3-60) - * Number of queued SCBs - */ -register QINCNT { - address 0x09c - access_mode RO -} - -/* - * Queue Out FIFO (p. 3-61) - * Queue of SCBs that have completed and await the host - */ -register QOUTFIFO { - address 0x09d - access_mode WO -} - -register CRCCONTROL1 { - address 0x09d - access_mode RW - bit CRCONSEEN 0x80 - bit CRCVALCHKEN 0x40 - bit CRCENDCHKEN 0x20 - bit CRCREQCHKEN 0x10 - bit TARGCRCENDEN 0x08 - bit TARGCRCCNTEN 0x04 -} - - -/* - * Queue Out Count (p. 3-61) - * Number of queued SCBs in the Out FIFO - */ -register QOUTCNT { - address 0x09e - access_mode RO -} - -register SCSIPHASE { - address 0x09e - access_mode RO - bit STATUS_PHASE 0x20 - bit COMMAND_PHASE 0x10 - bit MSG_IN_PHASE 0x08 - bit MSG_OUT_PHASE 0x04 - bit DATA_IN_PHASE 0x02 - bit DATA_OUT_PHASE 0x01 - mask DATA_PHASE_MASK 0x03 -} - -/* - * Special Function - */ -register SFUNCT { - address 0x09f - access_mode RW - bit ALT_MODE 0x80 -} - -/* - * SCB Definition (p. 5-4) - */ -scb { - address 0x0a0 - size 64 - - SCB_CDB_PTR { - size 4 - alias SCB_RESIDUAL_DATACNT - alias SCB_CDB_STORE - } - SCB_RESIDUAL_SGPTR { - size 4 - } - SCB_SCSI_STATUS { - size 1 - } - SCB_TARGET_PHASES { - size 1 - } - SCB_TARGET_DATA_DIR { - size 1 - } - SCB_TARGET_ITAG { - size 1 - } - SCB_DATAPTR { - size 4 - } - SCB_DATACNT { - /* - * The last byte is really the high address bits for - * the data address. - */ - size 4 - bit SG_LAST_SEG 0x80 /* In the fourth byte */ - mask SG_HIGH_ADDR_BITS 0x7F /* In the fourth byte */ - } - SCB_SGPTR { - size 4 - bit SG_RESID_VALID 0x04 /* In the first byte */ - bit SG_FULL_RESID 0x02 /* In the first byte */ - bit SG_LIST_NULL 0x01 /* In the first byte */ - } - SCB_CONTROL { - size 1 - bit TARGET_SCB 0x80 - bit DISCENB 0x40 - bit TAG_ENB 0x20 - bit MK_MESSAGE 0x10 - bit ULTRAENB 0x08 - bit DISCONNECTED 0x04 - mask SCB_TAG_TYPE 0x03 - } - SCB_SCSIID { - size 1 - bit TWIN_CHNLB 0x80 - mask TWIN_TID 0x70 - mask TID 0xf0 - mask OID 0x0f - } - SCB_LUN { - mask LID 0xff - size 1 - } - SCB_TAG { - size 1 - } - SCB_CDB_LEN { - size 1 - } - SCB_SCSIRATE { - size 1 - } - SCB_SCSIOFFSET { - size 1 - } - SCB_NEXT { - size 1 - } - SCB_64_SPARE { - size 16 - } - SCB_64_BTT { - size 16 - } -} - -const SCB_UPLOAD_SIZE 32 -const SCB_DOWNLOAD_SIZE 32 -const SCB_DOWNLOAD_SIZE_64 48 - -const SG_SIZEOF 0x08 /* sizeof(struct ahc_dma) */ - -/* --------------------- AHA-2840-only definitions -------------------- */ - -register SEECTL_2840 { - address 0x0c0 - access_mode RW - bit CS_2840 0x04 - bit CK_2840 0x02 - bit DO_2840 0x01 -} - -register STATUS_2840 { - address 0x0c1 - access_mode RW - bit EEPROM_TF 0x80 - mask BIOS_SEL 0x60 - mask ADSEL 0x1e - bit DI_2840 0x01 -} - -/* --------------------- AIC-7870-only definitions -------------------- */ - -register CCHADDR { - address 0x0E0 - size 8 -} - -register CCHCNT { - address 0x0E8 -} - -register CCSGRAM { - address 0x0E9 -} - -register CCSGADDR { - address 0x0EA -} - -register CCSGCTL { - address 0x0EB - bit CCSGDONE 0x80 - bit CCSGEN 0x08 - bit SG_FETCH_NEEDED 0x02 /* Bit used for software state */ - bit CCSGRESET 0x01 -} - -register CCSCBCNT { - address 0xEF -} - -register CCSCBCTL { - address 0x0EE - bit CCSCBDONE 0x80 - bit ARRDONE 0x40 /* SCB Array prefetch done */ - bit CCARREN 0x10 - bit CCSCBEN 0x08 - bit CCSCBDIR 0x04 - bit CCSCBRESET 0x01 -} - -register CCSCBADDR { - address 0x0ED -} - -register CCSCBRAM { - address 0xEC -} - -/* - * SCB bank address (7895/7896/97 only) - */ -register SCBBADDR { - address 0x0F0 - access_mode RW -} - -register CCSCBPTR { - address 0x0F1 -} - -register HNSCB_QOFF { - address 0x0F4 -} - -register SNSCB_QOFF { - address 0x0F6 -} - -register SDSCB_QOFF { - address 0x0F8 -} - -register QOFF_CTLSTA { - address 0x0FA - bit SCB_AVAIL 0x40 - bit SNSCB_ROLLOVER 0x20 - bit SDSCB_ROLLOVER 0x10 - mask SCB_QSIZE 0x07 - mask SCB_QSIZE_256 0x06 -} - -register DFF_THRSH { - address 0x0FB - mask WR_DFTHRSH 0x70 - mask RD_DFTHRSH 0x07 - mask RD_DFTHRSH_MIN 0x00 - mask RD_DFTHRSH_25 0x01 - mask RD_DFTHRSH_50 0x02 - mask RD_DFTHRSH_63 0x03 - mask RD_DFTHRSH_75 0x04 - mask RD_DFTHRSH_85 0x05 - mask RD_DFTHRSH_90 0x06 - mask RD_DFTHRSH_MAX 0x07 - mask WR_DFTHRSH_MIN 0x00 - mask WR_DFTHRSH_25 0x10 - mask WR_DFTHRSH_50 0x20 - mask WR_DFTHRSH_63 0x30 - mask WR_DFTHRSH_75 0x40 - mask WR_DFTHRSH_85 0x50 - mask WR_DFTHRSH_90 0x60 - mask WR_DFTHRSH_MAX 0x70 -} - -register SG_CACHE_PRE { - access_mode WO - address 0x0fc - mask SG_ADDR_MASK 0xf8 - bit ODD_SEG 0x04 - bit LAST_SEG 0x02 - bit LAST_SEG_DONE 0x01 -} - -register SG_CACHE_SHADOW { - access_mode RO - address 0x0fc - mask SG_ADDR_MASK 0xf8 - bit ODD_SEG 0x04 - bit LAST_SEG 0x02 - bit LAST_SEG_DONE 0x01 -} -/* ---------------------- Scratch RAM Offsets ------------------------- */ -/* These offsets are either to values that are initialized by the board's - * BIOS or are specified by the sequencer code. - * - * The host adapter card (at least the BIOS) uses 20-2f for SCSI - * device information, 32-33 and 5a-5f as well. As it turns out, the - * BIOS trashes 20-2f, writing the synchronous negotiation results - * on top of the BIOS values, so we re-use those for our per-target - * scratchspace (actually a value that can be copied directly into - * SCSIRATE). The kernel driver will enable synchronous negotiation - * for all targets that have a value other than 0 in the lower four - * bits of the target scratch space. This should work regardless of - * whether the bios has been installed. - */ - -scratch_ram { - address 0x020 - size 58 - - /* - * 1 byte per target starting at this address for configuration values - */ - BUSY_TARGETS { - alias TARG_SCSIRATE - size 16 - } - /* - * Bit vector of targets that have ULTRA enabled as set by - * the BIOS. The Sequencer relies on a per-SCB field to - * control whether to enable Ultra transfers or not. During - * initialization, we read this field and reuse it for 2 - * entries in the busy target table. - */ - ULTRA_ENB { - alias CMDSIZE_TABLE - size 2 - } - /* - * Bit vector of targets that have disconnection disabled as set by - * the BIOS. The Sequencer relies in a per-SCB field to control the - * disconnect priveldge. During initialization, we read this field - * and reuse it for 2 entries in the busy target table. - */ - DISC_DSB { - size 2 - } - CMDSIZE_TABLE_TAIL { - size 4 - } - /* - * Partial transfer past cacheline end to be - * transferred using an extra S/G. - */ - MWI_RESIDUAL { - size 1 - } - /* - * SCBID of the next SCB to be started by the controller. - */ - NEXT_QUEUED_SCB { - size 1 - } - /* - * Single byte buffer used to designate the type or message - * to send to a target. - */ - MSG_OUT { - size 1 - } - /* Parameters for DMA Logic */ - DMAPARAMS { - size 1 - bit PRELOADEN 0x80 - bit WIDEODD 0x40 - bit SCSIEN 0x20 - bit SDMAEN 0x10 - bit SDMAENACK 0x10 - bit HDMAEN 0x08 - bit HDMAENACK 0x08 - bit DIRECTION 0x04 /* Set indicates PCI->SCSI */ - bit FIFOFLUSH 0x02 - bit FIFORESET 0x01 - } - SEQ_FLAGS { - size 1 - bit IDENTIFY_SEEN 0x80 - bit TARGET_CMD_IS_TAGGED 0x40 - bit DPHASE 0x20 - /* Target flags */ - bit TARG_CMD_PENDING 0x10 - bit CMDPHASE_PENDING 0x08 - bit DPHASE_PENDING 0x04 - bit SPHASE_PENDING 0x02 - bit NO_DISCONNECT 0x01 - } - /* - * Temporary storage for the - * target/channel/lun of a - * reconnecting target - */ - SAVED_SCSIID { - size 1 - } - SAVED_LUN { - size 1 - } - /* - * The last bus phase as seen by the sequencer. - */ - LASTPHASE { - size 1 - bit CDI 0x80 - bit IOI 0x40 - bit MSGI 0x20 - mask PHASE_MASK CDI|IOI|MSGI - mask P_DATAOUT 0x00 - mask P_DATAIN IOI - mask P_COMMAND CDI - mask P_MESGOUT CDI|MSGI - mask P_STATUS CDI|IOI - mask P_MESGIN CDI|IOI|MSGI - mask P_BUSFREE 0x01 - } - /* - * head of list of SCBs awaiting - * selection - */ - WAITING_SCBH { - size 1 - } - /* - * head of list of SCBs that are - * disconnected. Used for SCB - * paging. - */ - DISCONNECTED_SCBH { - size 1 - } - /* - * head of list of SCBs that are - * not in use. Used for SCB paging. - */ - FREE_SCBH { - size 1 - } - /* - * head of list of SCBs that have - * completed but have not been - * put into the qoutfifo. - */ - COMPLETE_SCBH { - size 1 - } - /* - * Address of the hardware scb array in the host. - */ - HSCB_ADDR { - size 4 - } - /* - * Base address of our shared data with the kernel driver in host - * memory. This includes the qoutfifo and target mode - * incoming command queue. - */ - SHARED_DATA_ADDR { - size 4 - } - KERNEL_QINPOS { - size 1 - } - QINPOS { - size 1 - } - QOUTPOS { - size 1 - } - /* - * Kernel and sequencer offsets into the queue of - * incoming target mode command descriptors. The - * queue is full when the KERNEL_TQINPOS == TQINPOS. - */ - KERNEL_TQINPOS { - size 1 - } - TQINPOS { - size 1 - } - ARG_1 { - size 1 - mask SEND_MSG 0x80 - mask SEND_SENSE 0x40 - mask SEND_REJ 0x20 - mask MSGOUT_PHASEMIS 0x10 - mask EXIT_MSG_LOOP 0x08 - mask CONT_MSG_LOOP 0x04 - mask CONT_TARG_SESSION 0x02 - alias RETURN_1 - } - ARG_2 { - size 1 - alias RETURN_2 - } - - /* - * Snapshot of MSG_OUT taken after each message is sent. - */ - LAST_MSG { - size 1 - } - - /* - * Sequences the kernel driver has okayed for us. This allows - * the driver to do things like prevent initiator or target - * operations. - */ - SCSISEQ_TEMPLATE { - size 1 - bit ENSELO 0x40 - bit ENSELI 0x20 - bit ENRSELI 0x10 - bit ENAUTOATNO 0x08 - bit ENAUTOATNI 0x04 - bit ENAUTOATNP 0x02 - } - - /* - * Track whether the transfer byte count for - * the current data phase is odd. - */ - DATA_COUNT_ODD { - size 1 - } -} - -scratch_ram { - address 0x056 - size 4 - /* - * These scratch ram locations are initialized by the 274X BIOS. - * We reuse them after capturing the BIOS settings during - * initialization. - */ - - /* - * The initiator specified tag for this target mode transaction. - */ - HA_274_BIOSGLOBAL { - size 1 - bit HA_274_EXTENDED_TRANS 0x01 - alias INITIATOR_TAG - } - - SEQ_FLAGS2 { - size 1 - bit SCB_DMA 0x01 - bit TARGET_MSG_PENDING 0x02 - } -} - -scratch_ram { - address 0x05a - size 6 - /* - * These are reserved registers in the card's scratch ram on the 2742. - * The EISA configuraiton chip is mapped here. On Rev E. of the - * aic7770, the sequencer can use this area for scratch, but the - * host cannot directly access these registers. On later chips, this - * area can be read and written by both the host and the sequencer. - * Even on later chips, many of these locations are initialized by - * the BIOS. - */ - SCSICONF { - size 1 - bit TERM_ENB 0x80 - bit RESET_SCSI 0x40 - bit ENSPCHK 0x20 - mask HSCSIID 0x07 /* our SCSI ID */ - mask HWSCSIID 0x0f /* our SCSI ID if Wide Bus */ - } - INTDEF { - address 0x05c - size 1 - bit EDGE_TRIG 0x80 - mask VECTOR 0x0f - } - HOSTCONF { - address 0x05d - size 1 - } - HA_274_BIOSCTRL { - address 0x05f - size 1 - mask BIOSMODE 0x30 - mask BIOSDISABLED 0x30 - bit CHANNEL_B_PRIMARY 0x08 - } -} - -scratch_ram { - address 0x070 - size 16 - - /* - * Per target SCSI offset values for Ultra2 controllers. - */ - TARG_OFFSET { - size 16 - } -} - -const TID_SHIFT 4 -const SCB_LIST_NULL 0xff -const TARGET_CMD_CMPLT 0xfe - -const CCSGADDR_MAX 0x80 -const CCSGRAM_MAXSEGS 16 - -/* WDTR Message values */ -const BUS_8_BIT 0x00 -const BUS_16_BIT 0x01 -const BUS_32_BIT 0x02 - -/* Offset maximums */ -const MAX_OFFSET_8BIT 0x0f -const MAX_OFFSET_16BIT 0x08 -const MAX_OFFSET_ULTRA2 0x7f -const HOST_MSG 0xff - -/* Target mode command processing constants */ -const CMD_GROUP_CODE_SHIFT 0x05 - -const STATUS_BUSY 0x08 -const STATUS_QUEUE_FULL 0x28 -const TARGET_DATA_IN 1 - -/* - * Downloaded (kernel inserted) constants - */ -/* Offsets into the SCBID array where different data is stored */ -const QOUTFIFO_OFFSET download -const QINFIFO_OFFSET download -const CACHESIZE_MASK download -const INVERTED_CACHESIZE_MASK download -const SG_PREFETCH_CNT download -const SG_PREFETCH_ALIGN_MASK download -const SG_PREFETCH_ADDR_MASK download diff --git a/xen/drivers/scsi/aic7xxx/aic7xxx.seq b/xen/drivers/scsi/aic7xxx/aic7xxx.seq deleted file mode 100644 index db64c6fa56..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic7xxx.seq +++ /dev/null @@ -1,2365 +0,0 @@ -/* - * Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD. - * - * Copyright (c) 1994-2001 Justin T. Gibbs. - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.seq,v 1.94.2.16 2002/04/29 19:36:30 gibbs Exp $ - */ - -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#43 $" -PATCH_ARG_LIST = "struct ahc_softc *ahc" - -#include "aic7xxx.reg" -#include "scsi_message.h" - -/* - * A few words on the waiting SCB list: - * After starting the selection hardware, we check for reconnecting targets - * as well as for our selection to complete just in case the reselection wins - * bus arbitration. The problem with this is that we must keep track of the - * SCB that we've already pulled from the QINFIFO and started the selection - * on just in case the reselection wins so that we can retry the selection at - * a later time. This problem cannot be resolved by holding a single entry - * in scratch ram since a reconnecting target can request sense and this will - * create yet another SCB waiting for selection. The solution used here is to - * use byte 27 of the SCB as a psuedo-next pointer and to thread a list - * of SCBs that are awaiting selection. Since 0-0xfe are valid SCB indexes, - * SCB_LIST_NULL is 0xff which is out of range. An entry is also added to - * this list everytime a request sense occurs or after completing a non-tagged - * command for which a second SCB has been queued. The sequencer will - * automatically consume the entries. - */ - -bus_free_sel: - /* - * Turn off the selection hardware. We need to reset the - * selection request in order to perform a new selection. - */ - and SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ; - and SIMODE1, ~ENBUSFREE; -poll_for_work: - call clear_target_state; - and SXFRCTL0, ~SPIOEN; - if ((ahc->features & AHC_ULTRA2) != 0) { - clr SCSIBUSL; - } - test SCSISEQ, ENSELO jnz poll_for_selection; - if ((ahc->features & AHC_TWIN) != 0) { - xor SBLKCTL,SELBUSB; /* Toggle to the other bus */ - test SCSISEQ, ENSELO jnz poll_for_selection; - } - cmp WAITING_SCBH,SCB_LIST_NULL jne start_waiting; -poll_for_work_loop: - if ((ahc->features & AHC_TWIN) != 0) { - xor SBLKCTL,SELBUSB; /* Toggle to the other bus */ - } - test SSTAT0, SELDO|SELDI jnz selection; -test_queue: - /* Has the driver posted any work for us? */ -BEGIN_CRITICAL; - if ((ahc->features & AHC_QUEUE_REGS) != 0) { - test QOFF_CTLSTA, SCB_AVAIL jz poll_for_work_loop; - } else { - mov A, QINPOS; - cmp KERNEL_QINPOS, A je poll_for_work_loop; - } - mov ARG_1, NEXT_QUEUED_SCB; - - /* - * We have at least one queued SCB now and we don't have any - * SCBs in the list of SCBs awaiting selection. Allocate a - * card SCB for the host's SCB and get to work on it. - */ - if ((ahc->flags & AHC_PAGESCBS) != 0) { - mov ALLZEROS call get_free_or_disc_scb; - } else { - /* In the non-paging case, the SCBID == hardware SCB index */ - mov SCBPTR, ARG_1; - } - or SEQ_FLAGS2, SCB_DMA; -END_CRITICAL; -dma_queued_scb: - /* - * DMA the SCB from host ram into the current SCB location. - */ - mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET; - mov ARG_1 call dma_scb; - /* - * Check one last time to see if this SCB was canceled - * before we completed the DMA operation. If it was, - * the QINFIFO next pointer will not match our saved - * value. - */ - mov A, ARG_1; -BEGIN_CRITICAL; - cmp NEXT_QUEUED_SCB, A jne abort_qinscb; - if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { - cmp SCB_TAG, A je . + 2; - mvi SCB_MISMATCH call set_seqint; - } - mov NEXT_QUEUED_SCB, SCB_NEXT; - mov SCB_NEXT,WAITING_SCBH; - mov WAITING_SCBH, SCBPTR; - if ((ahc->features & AHC_QUEUE_REGS) != 0) { - mov NONE, SNSCB_QOFF; - } else { - inc QINPOS; - } - and SEQ_FLAGS2, ~SCB_DMA; -END_CRITICAL; -start_waiting: - /* - * Start the first entry on the waiting SCB list. - */ - mov SCBPTR, WAITING_SCBH; - call start_selection; - -poll_for_selection: - /* - * Twin channel devices cannot handle things like SELTO - * interrupts on the "background" channel. So, while - * selecting, keep polling the current channel until - * either a selection or reselection occurs. - */ - test SSTAT0, SELDO|SELDI jz poll_for_selection; - -selection: - /* - * We aren't expecting a bus free, so interrupt - * the kernel driver if it happens. - */ - mvi CLRSINT1,CLRBUSFREE; - if ((ahc->features & AHC_DT) == 0) { - or SIMODE1, ENBUSFREE; - } - - /* - * Guard against a bus free after (re)selection - * but prior to enabling the busfree interrupt. SELDI - * and SELDO will be cleared in that case. - */ - test SSTAT0, SELDI|SELDO jz bus_free_sel; - test SSTAT0,SELDO jnz select_out; -select_in: - if ((ahc->flags & AHC_TARGETROLE) != 0) { - if ((ahc->flags & AHC_INITIATORROLE) != 0) { - test SSTAT0, TARGET jz initiator_reselect; - } - mvi CLRSINT0, CLRSELDI; - - /* - * We've just been selected. Assert BSY and - * setup the phase for receiving messages - * from the target. - */ - mvi SCSISIGO, P_MESGOUT|BSYO; - - /* - * Setup the DMA for sending the identify and - * command information. - */ - or SEQ_FLAGS, CMDPHASE_PENDING; - - mov A, TQINPOS; - if ((ahc->features & AHC_CMD_CHAN) != 0) { - mvi DINDEX, CCHADDR; - mvi SHARED_DATA_ADDR call set_32byte_addr; - mvi CCSCBCTL, CCSCBRESET; - } else { - mvi DINDEX, HADDR; - mvi SHARED_DATA_ADDR call set_32byte_addr; - mvi DFCNTRL, FIFORESET; - } - - /* Initiator that selected us */ - and SAVED_SCSIID, SELID_MASK, SELID; - /* The Target ID we were selected at */ - if ((ahc->features & AHC_MULTI_TID) != 0) { - and A, OID, TARGIDIN; - } else if ((ahc->features & AHC_ULTRA2) != 0) { - and A, OID, SCSIID_ULTRA2; - } else { - and A, OID, SCSIID; - } - or SAVED_SCSIID, A; - if ((ahc->features & AHC_TWIN) != 0) { - test SBLKCTL, SELBUSB jz . + 2; - or SAVED_SCSIID, TWIN_CHNLB; - } - if ((ahc->features & AHC_CMD_CHAN) != 0) { - mov CCSCBRAM, SAVED_SCSIID; - } else { - mov DFDAT, SAVED_SCSIID; - } - - /* - * If ATN isn't asserted, the target isn't interested - * in talking to us. Go directly to bus free. - * XXX SCSI-1 may require us to assume lun 0 if - * ATN is false. - */ - test SCSISIGI, ATNI jz target_busfree; - - /* - * Watch ATN closely now as we pull in messages from the - * initiator. We follow the guidlines from section 6.5 - * of the SCSI-2 spec for what messages are allowed when. - */ - call target_inb; - - /* - * Our first message must be one of IDENTIFY, ABORT, or - * BUS_DEVICE_RESET. - */ - test DINDEX, MSG_IDENTIFYFLAG jz host_target_message_loop; - /* Store for host */ - if ((ahc->features & AHC_CMD_CHAN) != 0) { - mov CCSCBRAM, DINDEX; - } else { - mov DFDAT, DINDEX; - } - and SAVED_LUN, MSG_IDENTIFY_LUNMASK, DINDEX; - - /* Remember for disconnection decision */ - test DINDEX, MSG_IDENTIFY_DISCFLAG jnz . + 2; - /* XXX Honor per target settings too */ - or SEQ_FLAGS, NO_DISCONNECT; - - test SCSISIGI, ATNI jz ident_messages_done; - call target_inb; - /* - * If this is a tagged request, the tagged message must - * immediately follow the identify. We test for a valid - * tag message by seeing if it is >= MSG_SIMPLE_Q_TAG and - * < MSG_IGN_WIDE_RESIDUE. - */ - add A, -MSG_SIMPLE_Q_TAG, DINDEX; - jnc ident_messages_done_msg_pending; - add A, -MSG_IGN_WIDE_RESIDUE, DINDEX; - jc ident_messages_done_msg_pending; - - /* Store for host */ - if ((ahc->features & AHC_CMD_CHAN) != 0) { - mov CCSCBRAM, DINDEX; - } else { - mov DFDAT, DINDEX; - } - - /* - * If the initiator doesn't feel like providing a tag number, - * we've got a failed selection and must transition to bus - * free. - */ - test SCSISIGI, ATNI jz target_busfree; - - /* - * Store the tag for the host. - */ - call target_inb; - if ((ahc->features & AHC_CMD_CHAN) != 0) { - mov CCSCBRAM, DINDEX; - } else { - mov DFDAT, DINDEX; - } - mov INITIATOR_TAG, DINDEX; - or SEQ_FLAGS, TARGET_CMD_IS_TAGGED; - -ident_messages_done: - /* Terminate the ident list */ - if ((ahc->features & AHC_CMD_CHAN) != 0) { - mvi CCSCBRAM, SCB_LIST_NULL; - } else { - mvi DFDAT, SCB_LIST_NULL; - } - or SEQ_FLAGS, TARG_CMD_PENDING|IDENTIFY_SEEN; - test SEQ_FLAGS2, TARGET_MSG_PENDING - jnz target_mesgout_pending; - test SCSISIGI, ATNI jnz target_mesgout_continue; - jmp target_ITloop; - - -ident_messages_done_msg_pending: - or SEQ_FLAGS2, TARGET_MSG_PENDING; - jmp ident_messages_done; - - /* - * Pushed message loop to allow the kernel to - * run it's own target mode message state engine. - */ -host_target_message_loop: - mvi HOST_MSG_LOOP call set_seqint; - cmp RETURN_1, EXIT_MSG_LOOP je target_ITloop; - test SSTAT0, SPIORDY jz .; - jmp host_target_message_loop; - } - -if ((ahc->flags & AHC_INITIATORROLE) != 0) { -/* - * Reselection has been initiated by a target. Make a note that we've been - * reselected, but haven't seen an IDENTIFY message from the target yet. - */ -initiator_reselect: - /* XXX test for and handle ONE BIT condition */ - or SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN; - and SAVED_SCSIID, SELID_MASK, SELID; - if ((ahc->features & AHC_ULTRA2) != 0) { - and A, OID, SCSIID_ULTRA2; - } else { - and A, OID, SCSIID; - } - or SAVED_SCSIID, A; - if ((ahc->features & AHC_TWIN) != 0) { - test SBLKCTL, SELBUSB jz . + 2; - or SAVED_SCSIID, TWIN_CHNLB; - } - mvi CLRSINT0, CLRSELDI; - jmp ITloop; -} - -abort_qinscb: - call add_scb_to_free_list; - jmp poll_for_work_loop; - -start_selection: - /* - * If bus reset interrupts have been disabled (from a previous - * reset), re-enable them now. Resets are only of interest - * when we have outstanding transactions, so we can safely - * defer re-enabling the interrupt until, as an initiator, - * we start sending out transactions again. - */ - test SIMODE1, ENSCSIRST jnz . + 3; - mvi CLRSINT1, CLRSCSIRSTI; - or SIMODE1, ENSCSIRST; - if ((ahc->features & AHC_TWIN) != 0) { - and SINDEX,~SELBUSB,SBLKCTL;/* Clear channel select bit */ - test SCB_SCSIID, TWIN_CHNLB jz . + 2; - or SINDEX, SELBUSB; - mov SBLKCTL,SINDEX; /* select channel */ - } -initialize_scsiid: - if ((ahc->features & AHC_ULTRA2) != 0) { - mov SCSIID_ULTRA2, SCB_SCSIID; - } else if ((ahc->features & AHC_TWIN) != 0) { - and SCSIID, TWIN_TID|OID, SCB_SCSIID; - } else { - mov SCSIID, SCB_SCSIID; - } - if ((ahc->flags & AHC_TARGETROLE) != 0) { - mov SINDEX, SCSISEQ_TEMPLATE; - test SCB_CONTROL, TARGET_SCB jz . + 2; - or SINDEX, TEMODE; - mov SCSISEQ, SINDEX ret; - } else { - mov SCSISEQ, SCSISEQ_TEMPLATE ret; - } - -/* - * Initialize transfer settings and clear the SCSI channel. - * SINDEX should contain any additional bit's the client wants - * set in SXFRCTL0. We also assume that the current SCB is - * a valid SCB for the target we wish to talk to. - */ -initialize_channel: - or SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN; -set_transfer_settings: - if ((ahc->features & AHC_ULTRA) != 0) { - test SCB_CONTROL, ULTRAENB jz . + 2; - or SXFRCTL0, FAST20; - } - /* - * Initialize SCSIRATE with the appropriate value for this target. - */ - if ((ahc->features & AHC_ULTRA2) != 0) { - bmov SCSIRATE, SCB_SCSIRATE, 2 ret; - } else { - mov SCSIRATE, SCB_SCSIRATE ret; - } - -if ((ahc->flags & AHC_TARGETROLE) != 0) { -/* - * We carefully toggle SPIOEN to allow us to return the - * message byte we receive so it can be checked prior to - * driving REQ on the bus for the next byte. - */ -target_inb: - /* - * Drive REQ on the bus by enabling SCSI PIO. - */ - or SXFRCTL0, SPIOEN; - /* Wait for the byte */ - test SSTAT0, SPIORDY jz .; - /* Prevent our read from triggering another REQ */ - and SXFRCTL0, ~SPIOEN; - /* Save latched contents */ - mov DINDEX, SCSIDATL ret; -} - -/* - * After the selection, remove this SCB from the "waiting SCB" - * list. This is achieved by simply moving our "next" pointer into - * WAITING_SCBH. Our next pointer will be set to null the next time this - * SCB is used, so don't bother with it now. - */ -select_out: - /* Turn off the selection hardware */ - and SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ; - mov SCBPTR, WAITING_SCBH; - mov WAITING_SCBH,SCB_NEXT; - mov SAVED_SCSIID, SCB_SCSIID; - mov SAVED_LUN, SCB_LUN; - call initialize_channel; - if ((ahc->flags & AHC_TARGETROLE) != 0) { - test SSTAT0, TARGET jz initiator_select; - - /* - * We've just re-selected an initiator. - * Assert BSY and setup the phase for - * sending our identify messages. - */ - mvi P_MESGIN|BSYO call change_phase; - mvi CLRSINT0, CLRSELDO; - - /* - * Start out with a simple identify message. - */ - or SCB_LUN, MSG_IDENTIFYFLAG call target_outb; - - /* - * If we are the result of a tagged command, send - * a simple Q tag and the tag id. - */ - test SCB_CONTROL, TAG_ENB jz . + 3; - mvi MSG_SIMPLE_Q_TAG call target_outb; - mov SCB_TARGET_ITAG call target_outb; -target_synccmd: - /* - * Now determine what phases the host wants us - * to go through. - */ - mov SEQ_FLAGS, SCB_TARGET_PHASES; - - test SCB_CONTROL, MK_MESSAGE jz target_ITloop; - mvi P_MESGIN|BSYO call change_phase; - jmp host_target_message_loop; -target_ITloop: - /* - * Start honoring ATN signals now that - * we properly identified ourselves. - */ - test SCSISIGI, ATNI jnz target_mesgout; - test SEQ_FLAGS, CMDPHASE_PENDING jnz target_cmdphase; - test SEQ_FLAGS, DPHASE_PENDING jnz target_dphase; - test SEQ_FLAGS, SPHASE_PENDING jnz target_sphase; - - /* - * No more work to do. Either disconnect or not depending - * on the state of NO_DISCONNECT. - */ - test SEQ_FLAGS, NO_DISCONNECT jz target_disconnect; - mov RETURN_1, ALLZEROS; - call complete_target_cmd; - cmp RETURN_1, CONT_MSG_LOOP jne .; - if ((ahc->flags & AHC_PAGESCBS) != 0) { - mov ALLZEROS call get_free_or_disc_scb; - } - mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET; - mov SCB_TAG call dma_scb; - call set_transfer_settings; - jmp target_synccmd; - -target_mesgout: - mvi SCSISIGO, P_MESGOUT|BSYO; -target_mesgout_continue: - call target_inb; -target_mesgout_pending: - /* Local Processing goes here... */ - jmp host_target_message_loop; - -target_disconnect: - mvi P_MESGIN|BSYO call change_phase; - test SEQ_FLAGS, DPHASE jz . + 2; - mvi MSG_SAVEDATAPOINTER call target_outb; - mvi MSG_DISCONNECT call target_outb; - -target_busfree_wait: - /* Wait for preceding I/O session to complete. */ - test SCSISIGI, ACKI jnz .; -target_busfree: - and SIMODE1, ~ENBUSFREE; - if ((ahc->features & AHC_ULTRA2) != 0) { - clr SCSIBUSL; - } - clr SCSISIGO; - mvi LASTPHASE, P_BUSFREE; - call complete_target_cmd; - jmp poll_for_work; - -target_cmdphase: - /* - * The target has dropped ATN (doesn't want to abort or BDR) - * and we believe this selection to be valid. If the ring - * buffer for new commands is full, return busy or queue full. - */ - if ((ahc->features & AHC_HS_MAILBOX) != 0) { - and A, HOST_TQINPOS, HS_MAILBOX; - } else { - mov A, KERNEL_TQINPOS; - } - cmp TQINPOS, A jne tqinfifo_has_space; - mvi P_STATUS|BSYO call change_phase; - test SEQ_FLAGS, TARGET_CMD_IS_TAGGED jz . + 3; - mvi STATUS_QUEUE_FULL call target_outb; - jmp target_busfree_wait; - mvi STATUS_BUSY call target_outb; - jmp target_busfree_wait; -tqinfifo_has_space: - mvi P_COMMAND|BSYO call change_phase; - call target_inb; - mov A, DINDEX; - /* Store for host */ - if ((ahc->features & AHC_CMD_CHAN) != 0) { - mov CCSCBRAM, A; - } else { - mov DFDAT, A; - } - - /* - * Determine the number of bytes to read - * based on the command group code via table lookup. - * We reuse the first 8 bytes of the TARG_SCSIRATE - * BIOS array for this table. Count is one less than - * the total for the command since we've already fetched - * the first byte. - */ - shr A, CMD_GROUP_CODE_SHIFT; - add SINDEX, CMDSIZE_TABLE, A; - mov A, SINDIR; - - test A, 0xFF jz command_phase_done; - or SXFRCTL0, SPIOEN; -command_loop: - test SSTAT0, SPIORDY jz .; - cmp A, 1 jne . + 2; - and SXFRCTL0, ~SPIOEN; /* Last Byte */ - if ((ahc->features & AHC_CMD_CHAN) != 0) { - mov CCSCBRAM, SCSIDATL; - } else { - mov DFDAT, SCSIDATL; - } - dec A; - test A, 0xFF jnz command_loop; - -command_phase_done: - and SEQ_FLAGS, ~CMDPHASE_PENDING; - jmp target_ITloop; - -target_dphase: - /* - * Data phases on the bus are from the - * perspective of the initiator. The dma - * code looks at LASTPHASE to determine the - * data direction of the DMA. Toggle it for - * target transfers. - */ - xor LASTPHASE, IOI, SCB_TARGET_DATA_DIR; - or SCB_TARGET_DATA_DIR, BSYO call change_phase; - jmp p_data; - -target_sphase: - mvi P_STATUS|BSYO call change_phase; - mvi LASTPHASE, P_STATUS; - mov SCB_SCSI_STATUS call target_outb; - /* XXX Watch for ATN or parity errors??? */ - mvi SCSISIGO, P_MESGIN|BSYO; - /* MSG_CMDCMPLT is 0, but we can't do an immediate of 0 */ - mov ALLZEROS call target_outb; - jmp target_busfree_wait; - -complete_target_cmd: - test SEQ_FLAGS, TARG_CMD_PENDING jnz . + 2; - mov SCB_TAG jmp complete_post; - if ((ahc->features & AHC_CMD_CHAN) != 0) { - /* Set the valid byte */ - mvi CCSCBADDR, 24; - mov CCSCBRAM, ALLONES; - mvi CCHCNT, 28; - or CCSCBCTL, CCSCBEN|CCSCBRESET; - test CCSCBCTL, CCSCBDONE jz .; - clr CCSCBCTL; - } else { - /* Set the valid byte */ - or DFCNTRL, FIFORESET; - mvi DFWADDR, 3; /* Third 64bit word or byte 24 */ - mov DFDAT, ALLONES; - mvi 28 call set_hcnt; - or DFCNTRL, HDMAEN|FIFOFLUSH; - call dma_finish; - } - inc TQINPOS; - mvi INTSTAT,CMDCMPLT ret; - } - -if ((ahc->flags & AHC_INITIATORROLE) != 0) { -initiator_select: - /* - * As soon as we get a successful selection, the target - * should go into the message out phase since we have ATN - * asserted. - */ - mvi MSG_OUT, MSG_IDENTIFYFLAG; - or SEQ_FLAGS, IDENTIFY_SEEN; - mvi CLRSINT0, CLRSELDO; - - /* - * Main loop for information transfer phases. Wait for the - * target to assert REQ before checking MSG, C/D and I/O for - * the bus phase. - */ -mesgin_phasemis: -ITloop: - call phase_lock; - - mov A, LASTPHASE; - - test A, ~P_DATAIN jz p_data; - cmp A,P_COMMAND je p_command; - cmp A,P_MESGOUT je p_mesgout; - cmp A,P_STATUS je p_status; - cmp A,P_MESGIN je p_mesgin; - - mvi BAD_PHASE call set_seqint; - jmp ITloop; /* Try reading the bus again. */ - -await_busfree: - and SIMODE1, ~ENBUSFREE; - mov NONE, SCSIDATL; /* Ack the last byte */ - if ((ahc->features & AHC_ULTRA2) != 0) { - clr SCSIBUSL; /* Prevent bit leakage durint SELTO */ - } - and SXFRCTL0, ~SPIOEN; - test SSTAT1,REQINIT|BUSFREE jz .; - test SSTAT1, BUSFREE jnz poll_for_work; - mvi MISSED_BUSFREE call set_seqint; -} - -clear_target_state: - /* - * We assume that the kernel driver may reset us - * at any time, even in the middle of a DMA, so - * clear DFCNTRL too. - */ - clr DFCNTRL; - or SXFRCTL0, CLRSTCNT|CLRCHN; - - /* - * We don't know the target we will connect to, - * so default to narrow transfers to avoid - * parity problems. - */ - if ((ahc->features & AHC_ULTRA2) != 0) { - bmov SCSIRATE, ALLZEROS, 2; - } else { - clr SCSIRATE; - if ((ahc->features & AHC_ULTRA) != 0) { - and SXFRCTL0, ~(FAST20); - } - } - mvi LASTPHASE, P_BUSFREE; - /* clear target specific flags */ - clr SEQ_FLAGS ret; - -sg_advance: - clr A; /* add sizeof(struct scatter) */ - add SCB_RESIDUAL_SGPTR[0],SG_SIZEOF; - adc SCB_RESIDUAL_SGPTR[1],A; - adc SCB_RESIDUAL_SGPTR[2],A; - adc SCB_RESIDUAL_SGPTR[3],A ret; - -if ((ahc->features & AHC_CMD_CHAN) != 0) { -disable_ccsgen: - test CCSGCTL, CCSGEN jz return; - test CCSGCTL, CCSGDONE jz .; -disable_ccsgen_fetch_done: - clr CCSGCTL; - test CCSGCTL, CCSGEN jnz .; - ret; -idle_loop: - /* - * Do we need any more segments for this transfer? - */ - test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz return; - - /* Did we just finish fetching segs? */ - cmp CCSGCTL, CCSGEN|CCSGDONE je idle_sgfetch_complete; - - /* Are we actively fetching segments? */ - test CCSGCTL, CCSGEN jnz return; - - /* - * Do we have any prefetch left??? - */ - cmp CCSGADDR, SG_PREFETCH_CNT jne idle_sg_avail; - - /* - * Need to fetch segments, but we can only do that - * if the command channel is completely idle. Make - * sure we don't have an SCB prefetch going on. - */ - test CCSCBCTL, CCSCBEN jnz return; - - /* - * We fetch a "cacheline aligned" and sized amount of data - * so we don't end up referencing a non-existant page. - * Cacheline aligned is in quotes because the kernel will - * set the prefetch amount to a reasonable level if the - * cacheline size is unknown. - */ - mvi CCHCNT, SG_PREFETCH_CNT; - and CCHADDR[0], SG_PREFETCH_ALIGN_MASK, SCB_RESIDUAL_SGPTR; - bmov CCHADDR[1], SCB_RESIDUAL_SGPTR[1], 3; - mvi CCSGCTL, CCSGEN|CCSGRESET ret; -idle_sgfetch_complete: - call disable_ccsgen_fetch_done; - and CCSGADDR, SG_PREFETCH_ADDR_MASK, SCB_RESIDUAL_SGPTR; -idle_sg_avail: - if ((ahc->features & AHC_ULTRA2) != 0) { - /* Does the hardware have space for another SG entry? */ - test DFSTATUS, PRELOAD_AVAIL jz return; - bmov HADDR, CCSGRAM, 7; - test HCNT[0], 0x1 jz . + 2; - xor DATA_COUNT_ODD, 0x1; - bmov SCB_RESIDUAL_DATACNT[3], CCSGRAM, 1; - if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { - mov SCB_RESIDUAL_DATACNT[3] call set_hhaddr; - } - call sg_advance; - mov SINDEX, SCB_RESIDUAL_SGPTR[0]; - test DATA_COUNT_ODD, 0x1 jz . + 2; - or SINDEX, ODD_SEG; - test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2; - or SINDEX, LAST_SEG; - mov SG_CACHE_PRE, SINDEX; - /* Load the segment */ - or DFCNTRL, PRELOADEN; - } - ret; -} - -if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0) { -/* - * Calculate the trailing portion of this S/G segment that cannot - * be transferred using memory write and invalidate PCI transactions. - * XXX Can we optimize this for PCI writes only??? - */ -calc_mwi_residual: - /* - * If the ending address is on a cacheline boundary, - * there is no need for an extra segment. - */ - mov A, HCNT[0]; - add A, A, HADDR[0]; - and A, CACHESIZE_MASK; - test A, 0xFF jz return; - - /* - * If the transfer is less than a cachline, - * there is no need for an extra segment. - */ - test HCNT[1], 0xFF jnz calc_mwi_residual_final; - test HCNT[2], 0xFF jnz calc_mwi_residual_final; - add NONE, INVERTED_CACHESIZE_MASK, HCNT[0]; - jnc return; - -calc_mwi_residual_final: - mov MWI_RESIDUAL, A; - not A; - inc A; - add HCNT[0], A; - adc HCNT[1], -1; - adc HCNT[2], -1 ret; -} - -p_data: - test SEQ_FLAGS,IDENTIFY_SEEN jnz p_data_okay; - mvi NO_IDENT jmp set_seqint; -p_data_okay: - if ((ahc->features & AHC_ULTRA2) != 0) { - mvi DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN; - } else { - mvi DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET; - } - test LASTPHASE, IOI jnz . + 2; - or DMAPARAMS, DIRECTION; - if ((ahc->features & AHC_CMD_CHAN) != 0) { - /* We don't have any valid S/G elements */ - mvi CCSGADDR, SG_PREFETCH_CNT; - } - test SEQ_FLAGS, DPHASE jz data_phase_initialize; - - /* - * If we re-enter the data phase after going through another - * phase, our transfer location has almost certainly been - * corrupted by the interveining, non-data, transfers. Ask - * the host driver to fix us up based on the transfer residual. - */ - mvi PDATA_REINIT call set_seqint; - jmp data_phase_loop; - -data_phase_initialize: - /* We have seen a data phase for the first time */ - or SEQ_FLAGS, DPHASE; - - /* - * Initialize the DMA address and counter from the SCB. - * Also set SCB_RESIDUAL_SGPTR, including the LAST_SEG - * flag in the highest byte of the data count. We cannot - * modify the saved values in the SCB until we see a save - * data pointers message. - */ - if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { - /* The lowest address byte must be loaded last. */ - mov SCB_DATACNT[3] call set_hhaddr; - } - if ((ahc->features & AHC_CMD_CHAN) != 0) { - bmov HADDR, SCB_DATAPTR, 7; - bmov SCB_RESIDUAL_DATACNT[3], SCB_DATACNT[3], 5; - } else { - mvi DINDEX, HADDR; - mvi SCB_DATAPTR call bcopy_7; - mvi DINDEX, SCB_RESIDUAL_DATACNT + 3; - mvi SCB_DATACNT + 3 call bcopy_5; - } - if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0) { - call calc_mwi_residual; - } - and SCB_RESIDUAL_SGPTR[0], ~SG_FULL_RESID; - and DATA_COUNT_ODD, 0x1, HCNT[0]; - - if ((ahc->features & AHC_ULTRA2) == 0) { - if ((ahc->features & AHC_CMD_CHAN) != 0) { - bmov STCNT, HCNT, 3; - } else { - call set_stcnt_from_hcnt; - } - } - -data_phase_loop: - /* Guard against overruns */ - test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz data_phase_inbounds; - - /* - * Turn on `Bit Bucket' mode, wait until the target takes - * us to another phase, and then notify the host. - */ - and DMAPARAMS, DIRECTION; - mov DFCNTRL, DMAPARAMS; - or SXFRCTL1,BITBUCKET; - if ((ahc->features & AHC_DT) == 0) { - test SSTAT1,PHASEMIS jz .; - } else { - test SCSIPHASE, DATA_PHASE_MASK jnz .; - } - and SXFRCTL1, ~BITBUCKET; - mvi DATA_OVERRUN call set_seqint; - jmp ITloop; - -data_phase_inbounds: - if ((ahc->features & AHC_ULTRA2) != 0) { - mov SINDEX, SCB_RESIDUAL_SGPTR[0]; - test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2; - or SINDEX, LAST_SEG; - test DATA_COUNT_ODD, 0x1 jz . + 2; - or SINDEX, ODD_SEG; - mov SG_CACHE_PRE, SINDEX; - mov DFCNTRL, DMAPARAMS; -ultra2_dma_loop: - call idle_loop; - /* - * The transfer is complete if either the last segment - * completes or the target changes phase. - */ - test SG_CACHE_SHADOW, LAST_SEG_DONE jnz ultra2_dmafinish; - if ((ahc->features & AHC_DT) == 0) { - if ((ahc->flags & AHC_TARGETROLE) != 0) { - /* - * As a target, we control the phases, - * so ignore PHASEMIS. - */ - test SSTAT0, TARGET jnz ultra2_dma_loop; - } - if ((ahc->flags & AHC_INITIATORROLE) != 0) { - test SSTAT1,PHASEMIS jz ultra2_dma_loop; - } - } else { - test DFCNTRL, SCSIEN jnz ultra2_dma_loop; - } - -ultra2_dmafinish: - /* - * The transfer has terminated either due to a phase - * change, and/or the completion of the last segment. - * We have two goals here. Do as much other work - * as possible while the data fifo drains on a read - * and respond as quickly as possible to the standard - * messages (save data pointers/disconnect and command - * complete) that usually follow a data phase. - */ - if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) { - /* - * On chips with broken auto-flush, start - * the flushing process now. We'll poke - * the chip from time to time to keep the - * flush process going as we complete the - * data phase. - */ - or DFCNTRL, FIFOFLUSH; - } - /* - * We assume that, even though data may still be - * transferring to the host, that the SCSI side of - * the DMA engine is now in a static state. This - * allows us to update our notion of where we are - * in this transfer. - * - * If, by chance, we stopped before being able - * to fetch additional segments for this transfer, - * yet the last S/G was completely exhausted, - * call our idle loop until it is able to load - * another segment. This will allow us to immediately - * pickup on the next segment on the next data phase. - * - * If we happened to stop on the last segment, then - * our residual information is still correct from - * the idle loop and there is no need to perform - * any fixups. - */ -ultra2_ensure_sg: - test SG_CACHE_SHADOW, LAST_SEG jz ultra2_shvalid; - /* Record if we've consumed all S/G entries */ - test SSTAT2, SHVALID jnz residuals_correct; - or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL; - jmp residuals_correct; - -ultra2_shvalid: - test SSTAT2, SHVALID jnz sgptr_fixup; - call idle_loop; - jmp ultra2_ensure_sg; - -sgptr_fixup: - /* - * Fixup the residual next S/G pointer. The S/G preload - * feature of the chip allows us to load two elements - * in addition to the currently active element. We - * store the bottom byte of the next S/G pointer in - * the SG_CACEPTR register so we can restore the - * correct value when the DMA completes. If the next - * sg ptr value has advanced to the point where higher - * bytes in the address have been affected, fix them - * too. - */ - test SG_CACHE_SHADOW, 0x80 jz sgptr_fixup_done; - test SCB_RESIDUAL_SGPTR[0], 0x80 jnz sgptr_fixup_done; - add SCB_RESIDUAL_SGPTR[1], -1; - adc SCB_RESIDUAL_SGPTR[2], -1; - adc SCB_RESIDUAL_SGPTR[3], -1; -sgptr_fixup_done: - and SCB_RESIDUAL_SGPTR[0], SG_ADDR_MASK, SG_CACHE_SHADOW; - clr DATA_COUNT_ODD; - test SG_CACHE_SHADOW, ODD_SEG jz . + 2; - or DATA_COUNT_ODD, 0x1; - clr SCB_RESIDUAL_DATACNT[3]; /* We are not the last seg */ -residuals_correct: - /* - * Go ahead and shut down the DMA engine now. - * In the future, we'll want to handle end of - * transfer messages prior to doing this, but this - * requires similar restructuring for pre-ULTRA2 - * controllers. - */ - test DMAPARAMS, DIRECTION jnz ultra2_fifoempty; -ultra2_fifoflush: - if ((ahc->features & AHC_DT) == 0) { - if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) { - /* - * On Rev A of the aic7890, the autoflush - * feature doesn't function correctly. - * Perform an explicit manual flush. During - * a manual flush, the FIFOEMP bit becomes - * true every time the PCI FIFO empties - * regardless of the state of the SCSI FIFO. - * It can take up to 4 clock cycles for the - * SCSI FIFO to get data into the PCI FIFO - * and for FIFOEMP to de-assert. Here we - * guard against this condition by making - * sure the FIFOEMP bit stays on for 5 full - * clock cycles. - */ - or DFCNTRL, FIFOFLUSH; - test DFSTATUS, FIFOEMP jz ultra2_fifoflush; - test DFSTATUS, FIFOEMP jz ultra2_fifoflush; - test DFSTATUS, FIFOEMP jz ultra2_fifoflush; - test DFSTATUS, FIFOEMP jz ultra2_fifoflush; - } - test DFSTATUS, FIFOEMP jz ultra2_fifoflush; - } else { - /* - * We enable the auto-ack feature on DT capable - * controllers. This means that the controller may - * have already transferred some overrun bytes into - * the data FIFO and acked them on the bus. The only - * way to detect this situation is to wait for - * LAST_SEG_DONE to come true on a completed transfer - * and then test to see if the data FIFO is non-empty. - */ - test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 4; - test SG_CACHE_SHADOW, LAST_SEG_DONE jz .; - test DFSTATUS, FIFOEMP jnz ultra2_fifoempty; - /* Overrun */ - jmp data_phase_loop; - test DFSTATUS, FIFOEMP jz .; - } -ultra2_fifoempty: - /* Don't clobber an inprogress host data transfer */ - test DFSTATUS, MREQPEND jnz ultra2_fifoempty; -ultra2_dmahalt: - and DFCNTRL, ~(SCSIEN|HDMAEN); - test DFCNTRL, SCSIEN|HDMAEN jnz .; - if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { - /* - * Keep HHADDR cleared for future, 32bit addressed - * only, DMA operations. - * - * Due to bayonette style S/G handling, our residual - * data must be "fixed up" once the transfer is halted. - * Here we fixup the HSHADDR stored in the high byte - * of the residual data cnt. By postponing the fixup, - * we can batch the clearing of HADDR with the fixup. - * If we halted on the last segment, the residual is - * already correct. If we are not on the last - * segment, copy the high address directly from HSHADDR. - * We don't need to worry about maintaining the - * SG_LAST_SEG flag as it will always be false in the - * case where an update is required. - */ - or DSCOMMAND1, HADDLDSEL0; - test SG_CACHE_SHADOW, LAST_SEG jnz . + 2; - mov SCB_RESIDUAL_DATACNT[3], SHADDR; - clr HADDR; - and DSCOMMAND1, ~HADDLDSEL0; - } - } else { - /* If we are the last SG block, tell the hardware. */ - if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 - && ahc->pci_cachesize != 0) { - test MWI_RESIDUAL, 0xFF jnz dma_mid_sg; - } - test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg; - if ((ahc->flags & AHC_TARGETROLE) != 0) { - test SSTAT0, TARGET jz dma_last_sg; - if ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0) { - test DMAPARAMS, DIRECTION jz dma_mid_sg; - } - } -dma_last_sg: - and DMAPARAMS, ~WIDEODD; -dma_mid_sg: - /* Start DMA data transfer. */ - mov DFCNTRL, DMAPARAMS; -dma_loop: - if ((ahc->features & AHC_CMD_CHAN) != 0) { - call idle_loop; - } - test SSTAT0,DMADONE jnz dma_dmadone; - test SSTAT1,PHASEMIS jz dma_loop; /* ie. underrun */ -dma_phasemis: - /* - * We will be "done" DMAing when the transfer count goes to - * zero, or the target changes the phase (in light of this, - * it makes sense that the DMA circuitry doesn't ACK when - * PHASEMIS is active). If we are doing a SCSI->Host transfer, - * the data FIFO should be flushed auto-magically on STCNT=0 - * or a phase change, so just wait for FIFO empty status. - */ -dma_checkfifo: - test DFCNTRL,DIRECTION jnz dma_fifoempty; -dma_fifoflush: - test DFSTATUS,FIFOEMP jz dma_fifoflush; -dma_fifoempty: - /* Don't clobber an inprogress host data transfer */ - test DFSTATUS, MREQPEND jnz dma_fifoempty; - - /* - * Now shut off the DMA and make sure that the DMA - * hardware has actually stopped. Touching the DMA - * counters, etc. while a DMA is active will result - * in an ILLSADDR exception. - */ -dma_dmadone: - and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN); -dma_halt: - /* - * Some revisions of the aic78XX have a problem where, if the - * data fifo is full, but the PCI input latch is not empty, - * HDMAEN cannot be cleared. The fix used here is to drain - * the prefetched but unused data from the data fifo until - * there is space for the input latch to drain. - */ - if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0) { - mov NONE, DFDAT; - } - test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz dma_halt; - - /* See if we have completed this last segment */ - test STCNT[0], 0xff jnz data_phase_finish; - test STCNT[1], 0xff jnz data_phase_finish; - test STCNT[2], 0xff jnz data_phase_finish; - - /* - * Advance the scatter-gather pointers if needed - */ - if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 - && ahc->pci_cachesize != 0) { - test MWI_RESIDUAL, 0xFF jz no_mwi_resid; - /* - * Reload HADDR from SHADDR and setup the - * count to be the size of our residual. - */ - if ((ahc->features & AHC_CMD_CHAN) != 0) { - bmov HADDR, SHADDR, 4; - mov HCNT, MWI_RESIDUAL; - bmov HCNT[1], ALLZEROS, 2; - } else { - mvi DINDEX, HADDR; - mvi SHADDR call bcopy_4; - mov MWI_RESIDUAL call set_hcnt; - } - clr MWI_RESIDUAL; - jmp sg_load_done; -no_mwi_resid: - } - test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz sg_load; - or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL; - jmp data_phase_finish; -sg_load: - /* - * Load the next SG element's data address and length - * into the DMA engine. If we don't have hardware - * to perform a prefetch, we'll have to fetch the - * segment from host memory first. - */ - if ((ahc->features & AHC_CMD_CHAN) != 0) { - /* Wait for the idle loop to complete */ - test CCSGCTL, CCSGEN jz . + 3; - call idle_loop; - test CCSGCTL, CCSGEN jnz . - 1; - bmov HADDR, CCSGRAM, 7; - /* - * Workaround for flaky external SCB RAM - * on certain aic7895 setups. It seems - * unable to handle direct transfers from - * S/G ram to certain SCB locations. - */ - mov SINDEX, CCSGRAM; - mov SCB_RESIDUAL_DATACNT[3], SINDEX; - } else { - if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { - mov ALLZEROS call set_hhaddr; - } - mvi DINDEX, HADDR; - mvi SCB_RESIDUAL_SGPTR call bcopy_4; - - mvi SG_SIZEOF call set_hcnt; - - or DFCNTRL, HDMAEN|DIRECTION|FIFORESET; - - call dma_finish; - - mvi DINDEX, HADDR; - call dfdat_in_7; - mov SCB_RESIDUAL_DATACNT[3], DFDAT; - } - - if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { - mov SCB_RESIDUAL_DATACNT[3] call set_hhaddr; - - /* - * The lowest address byte must be loaded - * last as it triggers the computation of - * some items in the PCI block. The ULTRA2 - * chips do this on PRELOAD. - */ - mov HADDR, HADDR; - } - if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 - && ahc->pci_cachesize != 0) { - call calc_mwi_residual; - } - - /* Point to the new next sg in memory */ - call sg_advance; - -sg_load_done: - if ((ahc->features & AHC_CMD_CHAN) != 0) { - bmov STCNT, HCNT, 3; - } else { - call set_stcnt_from_hcnt; - } - /* Track odd'ness */ - test HCNT[0], 0x1 jz . + 2; - xor DATA_COUNT_ODD, 0x1; - - if ((ahc->flags & AHC_TARGETROLE) != 0) { - test SSTAT0, TARGET jnz data_phase_loop; - } - } -data_phase_finish: - /* - * If the target has left us in data phase, loop through - * the dma code again. In the case of ULTRA2 adapters, - * we should only loop if there is a data overrun. For - * all other adapters, we'll loop after each S/G element - * is loaded as well as if there is an overrun. - */ - if ((ahc->flags & AHC_TARGETROLE) != 0) { - test SSTAT0, TARGET jnz data_phase_done; - } - if ((ahc->flags & AHC_INITIATORROLE) != 0) { - test SSTAT1, REQINIT jz .; - if ((ahc->features & AHC_DT) == 0) { - test SSTAT1,PHASEMIS jz data_phase_loop; - } else { - test SCSIPHASE, DATA_PHASE_MASK jnz data_phase_loop; - } - } - -data_phase_done: - /* - * After a DMA finishes, save the SG and STCNT residuals back into - * the SCB. We use STCNT instead of HCNT, since it's a reflection - * of how many bytes were transferred on the SCSI (as opposed to the - * host) bus. - */ - if ((ahc->features & AHC_CMD_CHAN) != 0) { - /* Kill off any pending prefetch */ - call disable_ccsgen; - } - - if ((ahc->features & AHC_ULTRA2) == 0) { - /* - * Clear the high address byte so that all other DMA - * operations, which use 32bit addressing, can assume - * HHADDR is 0. - */ - if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { - mov ALLZEROS call set_hhaddr; - } - } - - /* - * Update our residual information before the information is - * lost by some other type of SCSI I/O (e.g. PIO). If we have - * transferred all data, no update is needed. - * - */ - test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jnz residual_update_done; - if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 - && ahc->pci_cachesize != 0) { - if ((ahc->features & AHC_CMD_CHAN) != 0) { - test MWI_RESIDUAL, 0xFF jz bmov_resid; - } - mov A, MWI_RESIDUAL; - add SCB_RESIDUAL_DATACNT[0], A, STCNT[0]; - clr A; - adc SCB_RESIDUAL_DATACNT[1], A, STCNT[1]; - adc SCB_RESIDUAL_DATACNT[2], A, STCNT[2]; - clr MWI_RESIDUAL; - if ((ahc->features & AHC_CMD_CHAN) != 0) { - jmp . + 2; -bmov_resid: - bmov SCB_RESIDUAL_DATACNT, STCNT, 3; - } - } else if ((ahc->features & AHC_CMD_CHAN) != 0) { - bmov SCB_RESIDUAL_DATACNT, STCNT, 3; - } else { - mov SCB_RESIDUAL_DATACNT[0], STCNT[0]; - mov SCB_RESIDUAL_DATACNT[1], STCNT[1]; - mov SCB_RESIDUAL_DATACNT[2], STCNT[2]; - } -residual_update_done: - /* - * Since we've been through a data phase, the SCB_RESID* fields - * are now initialized. Clear the full residual flag. - */ - and SCB_SGPTR[0], ~SG_FULL_RESID; - - if ((ahc->features & AHC_ULTRA2) != 0) { - /* Clear the channel in case we return to data phase later */ - or SXFRCTL0, CLRSTCNT|CLRCHN; - or SXFRCTL0, CLRSTCNT|CLRCHN; - } - - if ((ahc->flags & AHC_TARGETROLE) != 0) { - test SEQ_FLAGS, DPHASE_PENDING jz ITloop; - and SEQ_FLAGS, ~DPHASE_PENDING; - /* - * For data-in phases, wait for any pending acks from the - * initiator before changing phase. We only need to - * send Ignore Wide Residue messages for data-in phases. - */ - test DFCNTRL, DIRECTION jz target_ITloop; - test SSTAT1, REQINIT jnz .; - test DATA_COUNT_ODD, 0x1 jz target_ITloop; - test SCSIRATE, WIDEXFER jz target_ITloop; - /* - * Issue an Ignore Wide Residue Message. - */ - mvi P_MESGIN|BSYO call change_phase; - mvi MSG_IGN_WIDE_RESIDUE call target_outb; - mvi 1 call target_outb; - jmp target_ITloop; - } else { - jmp ITloop; - } - -if ((ahc->flags & AHC_INITIATORROLE) != 0) { -/* - * Command phase. Set up the DMA registers and let 'er rip. - */ -p_command: - test SEQ_FLAGS,IDENTIFY_SEEN jnz p_command_okay; - mvi NO_IDENT jmp set_seqint; -p_command_okay: - - if ((ahc->features & AHC_ULTRA2) != 0) { - bmov HCNT[0], SCB_CDB_LEN, 1; - bmov HCNT[1], ALLZEROS, 2; - mvi SG_CACHE_PRE, LAST_SEG; - } else if ((ahc->features & AHC_CMD_CHAN) != 0) { - bmov STCNT[0], SCB_CDB_LEN, 1; - bmov STCNT[1], ALLZEROS, 2; - } else { - mov STCNT[0], SCB_CDB_LEN; - clr STCNT[1]; - clr STCNT[2]; - } - add NONE, -13, SCB_CDB_LEN; - mvi SCB_CDB_STORE jnc p_command_embedded; -p_command_from_host: - if ((ahc->features & AHC_ULTRA2) != 0) { - bmov HADDR[0], SCB_CDB_PTR, 4; - mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION); - } else { - if ((ahc->features & AHC_CMD_CHAN) != 0) { - bmov HADDR[0], SCB_CDB_PTR, 4; - bmov HCNT, STCNT, 3; - } else { - mvi DINDEX, HADDR; - mvi SCB_CDB_PTR call bcopy_4; - mov SCB_CDB_LEN call set_hcnt; - } - mvi DFCNTRL, (SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET); - } - jmp p_command_loop; -p_command_embedded: - /* - * The data fifo seems to require 4 byte aligned - * transfers from the sequencer. Force this to - * be the case by clearing HADDR[0] even though - * we aren't going to touch host memory. - */ - clr HADDR[0]; - if ((ahc->features & AHC_ULTRA2) != 0) { - mvi DFCNTRL, (PRELOADEN|SCSIEN|DIRECTION); - bmov DFDAT, SCB_CDB_STORE, 12; - } else if ((ahc->features & AHC_CMD_CHAN) != 0) { - if ((ahc->flags & AHC_SCB_BTT) != 0) { - /* - * On the 7895 the data FIFO will - * get corrupted if you try to dump - * data from external SCB memory into - * the FIFO while it is enabled. So, - * fill the fifo and then enable SCSI - * transfers. - */ - mvi DFCNTRL, (DIRECTION|FIFORESET); - } else { - mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFORESET); - } - bmov DFDAT, SCB_CDB_STORE, 12; - if ((ahc->flags & AHC_SCB_BTT) != 0) { - mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFOFLUSH); - } else { - or DFCNTRL, FIFOFLUSH; - } - } else { - mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFORESET); - call copy_to_fifo_6; - call copy_to_fifo_6; - or DFCNTRL, FIFOFLUSH; - } -p_command_loop: - if ((ahc->features & AHC_DT) == 0) { - test SSTAT0, SDONE jnz . + 2; - test SSTAT1, PHASEMIS jz p_command_loop; - /* - * Wait for our ACK to go-away on it's own - * instead of being killed by SCSIEN getting cleared. - */ - test SCSISIGI, ACKI jnz .; - } else { - test DFCNTRL, SCSIEN jnz p_command_loop; - } - and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN); - test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz .; - if ((ahc->features & AHC_ULTRA2) != 0) { - /* Drop any residual from the S/G Preload queue */ - or SXFRCTL0, CLRSTCNT; - } - jmp ITloop; - -/* - * Status phase. Wait for the data byte to appear, then read it - * and store it into the SCB. - */ -p_status: - test SEQ_FLAGS,IDENTIFY_SEEN jnz p_status_okay; - mvi NO_IDENT jmp set_seqint; -p_status_okay: - mov SCB_SCSI_STATUS, SCSIDATL; - jmp ITloop; - -/* - * Message out phase. If MSG_OUT is MSG_IDENTIFYFLAG, build a full - * indentify message sequence and send it to the target. The host may - * override this behavior by setting the MK_MESSAGE bit in the SCB - * control byte. This will cause us to interrupt the host and allow - * it to handle the message phase completely on its own. If the bit - * associated with this target is set, we will also interrupt the host, - * thereby allowing it to send a message on the next selection regardless - * of the transaction being sent. - * - * If MSG_OUT is == HOST_MSG, also interrupt the host and take a message. - * This is done to allow the host to send messages outside of an identify - * sequence while protecting the seqencer from testing the MK_MESSAGE bit - * on an SCB that might not be for the current nexus. (For example, a - * BDR message in responce to a bad reselection would leave us pointed to - * an SCB that doesn't have anything to do with the current target). - * - * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag, - * bus device reset). - * - * When there are no messages to send, MSG_OUT should be set to MSG_NOOP, - * in case the target decides to put us in this phase for some strange - * reason. - */ -p_mesgout_retry: - /* Turn on ATN for the retry */ - if ((ahc->features & AHC_DT) == 0) { - or SCSISIGO, ATNO, LASTPHASE; - } else { - mvi SCSISIGO, ATNO; - } -p_mesgout: - mov SINDEX, MSG_OUT; - cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host; - test SCB_CONTROL,MK_MESSAGE jnz host_message_loop; -p_mesgout_identify: - or SINDEX, MSG_IDENTIFYFLAG|DISCENB, SCB_LUN; - test SCB_CONTROL, DISCENB jnz . + 2; - and SINDEX, ~DISCENB; -/* - * Send a tag message if TAG_ENB is set in the SCB control block. - * Use SCB_TAG (the position in the kernel's SCB array) as the tag value. - */ -p_mesgout_tag: - test SCB_CONTROL,TAG_ENB jz p_mesgout_onebyte; - mov SCSIDATL, SINDEX; /* Send the identify message */ - call phase_lock; - cmp LASTPHASE, P_MESGOUT jne p_mesgout_done; - and SCSIDATL,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL; - call phase_lock; - cmp LASTPHASE, P_MESGOUT jne p_mesgout_done; - mov SCB_TAG jmp p_mesgout_onebyte; -/* - * Interrupt the driver, and allow it to handle this message - * phase and any required retries. - */ -p_mesgout_from_host: - cmp SINDEX, HOST_MSG jne p_mesgout_onebyte; - jmp host_message_loop; - -p_mesgout_onebyte: - mvi CLRSINT1, CLRATNO; - mov SCSIDATL, SINDEX; - -/* - * If the next bus phase after ATN drops is message out, it means - * that the target is requesting that the last message(s) be resent. - */ - call phase_lock; - cmp LASTPHASE, P_MESGOUT je p_mesgout_retry; - -p_mesgout_done: - mvi CLRSINT1,CLRATNO; /* Be sure to turn ATNO off */ - mov LAST_MSG, MSG_OUT; - mvi MSG_OUT, MSG_NOOP; /* No message left */ - jmp ITloop; - -/* - * Message in phase. Bytes are read using Automatic PIO mode. - */ -p_mesgin: - mvi ACCUM call inb_first; /* read the 1st message byte */ - - test A,MSG_IDENTIFYFLAG jnz mesgin_identify; - cmp A,MSG_DISCONNECT je mesgin_disconnect; - cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs; - cmp ALLZEROS,A je mesgin_complete; - cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs; - cmp A,MSG_IGN_WIDE_RESIDUE je mesgin_ign_wide_residue; - cmp A,MSG_NOOP je mesgin_done; - -/* - * Pushed message loop to allow the kernel to - * run it's own message state engine. To avoid an - * extra nop instruction after signaling the kernel, - * we perform the phase_lock before checking to see - * if we should exit the loop and skip the phase_lock - * in the ITloop. Performing back to back phase_locks - * shouldn't hurt, but why do it twice... - */ -host_message_loop: - mvi HOST_MSG_LOOP call set_seqint; - call phase_lock; - cmp RETURN_1, EXIT_MSG_LOOP je ITloop + 1; - jmp host_message_loop; - -mesgin_ign_wide_residue: -if ((ahc->features & AHC_WIDE) != 0) { - test SCSIRATE, WIDEXFER jz mesgin_reject; - /* Pull the residue byte */ - mvi ARG_1 call inb_next; - cmp ARG_1, 0x01 jne mesgin_reject; - test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 2; - test DATA_COUNT_ODD, 0x1 jz mesgin_done; - mvi IGN_WIDE_RES call set_seqint; - jmp mesgin_done; -} - -mesgin_reject: - mvi MSG_MESSAGE_REJECT call mk_mesg; -mesgin_done: - mov NONE,SCSIDATL; /*dummy read from latch to ACK*/ - jmp ITloop; - -mesgin_complete: -/* - * We received a "command complete" message. Put the SCB_TAG into the QOUTFIFO, - * and trigger a completion interrupt. Before doing so, check to see if there - * is a residual or the status byte is something other than STATUS_GOOD (0). - * In either of these conditions, we upload the SCB back to the host so it can - * process this information. In the case of a non zero status byte, we - * additionally interrupt the kernel driver synchronously, allowing it to - * decide if sense should be retrieved. If the kernel driver wishes to request - * sense, it will fill the kernel SCB with a request sense command, requeue - * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting - * RETURN_1 to SEND_SENSE. - */ - -/* - * If ATN is raised, we still want to give the target a message. - * Perhaps there was a parity error on this last message byte. - * Either way, the target should take us to message out phase - * and then attempt to complete the command again. We should use a - * critical section here to guard against a timeout triggering - * for this command and setting ATN while we are still processing - * the completion. - test SCSISIGI, ATNI jnz mesgin_done; - */ - -/* - * See if we attempted to deliver a message but the target ingnored us. - */ - test SCB_CONTROL, MK_MESSAGE jz . + 2; - mvi MKMSG_FAILED call set_seqint; - -/* - * Check for residuals - */ - test SCB_SGPTR, SG_LIST_NULL jnz check_status;/* No xfer */ - test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */ - test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb; -check_status: - test SCB_SCSI_STATUS,0xff jz complete; /* Good Status? */ -upload_scb: - or SCB_SGPTR, SG_RESID_VALID; - mvi DMAPARAMS, FIFORESET; - mov SCB_TAG call dma_scb; - test SCB_SCSI_STATUS, 0xff jz complete; /* Just a residual? */ - mvi BAD_STATUS call set_seqint; /* let driver know */ - cmp RETURN_1, SEND_SENSE jne complete; - call add_scb_to_free_list; - jmp await_busfree; -complete: - mov SCB_TAG call complete_post; - jmp await_busfree; -} - -complete_post: - /* Post the SCBID in SINDEX and issue an interrupt */ - call add_scb_to_free_list; - mov ARG_1, SINDEX; - if ((ahc->features & AHC_QUEUE_REGS) != 0) { - mov A, SDSCB_QOFF; - } else { - mov A, QOUTPOS; - } - mvi QOUTFIFO_OFFSET call post_byte_setup; - mov ARG_1 call post_byte; - if ((ahc->features & AHC_QUEUE_REGS) == 0) { - inc QOUTPOS; - } - mvi INTSTAT,CMDCMPLT ret; - -if ((ahc->flags & AHC_INITIATORROLE) != 0) { -/* - * Is it a disconnect message? Set a flag in the SCB to remind us - * and await the bus going free. If this is an untagged transaction - * store the SCB id for it in our untagged target table for lookup on - * a reselction. - */ -mesgin_disconnect: - /* - * If ATN is raised, we still want to give the target a message. - * Perhaps there was a parity error on this last message byte - * or we want to abort this command. Either way, the target - * should take us to message out phase and then attempt to - * disconnect again. - * XXX - Wait for more testing. - test SCSISIGI, ATNI jnz mesgin_done; - */ - - or SCB_CONTROL,DISCONNECTED; - if ((ahc->flags & AHC_PAGESCBS) != 0) { - call add_scb_to_disc_list; - } - test SCB_CONTROL, TAG_ENB jnz await_busfree; - mov ARG_1, SCB_TAG; - mov SAVED_LUN, SCB_LUN; - mov SCB_SCSIID call set_busy_target; - jmp await_busfree; - -/* - * Save data pointers message: - * Copying RAM values back to SCB, for Save Data Pointers message, but - * only if we've actually been into a data phase to change them. This - * protects against bogus data in scratch ram and the residual counts - * since they are only initialized when we go into data_in or data_out. - * Ack the message as soon as possible. For chips without S/G pipelining, - * we can only ack the message after SHADDR has been saved. On these - * chips, SHADDR increments with every bus transaction, even PIO. - */ -mesgin_sdptrs: - if ((ahc->features & AHC_ULTRA2) != 0) { - mov NONE,SCSIDATL; /*dummy read from latch to ACK*/ - test SEQ_FLAGS, DPHASE jz ITloop; - } else { - test SEQ_FLAGS, DPHASE jz mesgin_done; - } - - /* - * If we are asked to save our position at the end of the - * transfer, just mark us at the end rather than perform a - * full save. - */ - test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz mesgin_sdptrs_full; - or SCB_SGPTR, SG_LIST_NULL; - if ((ahc->features & AHC_ULTRA2) != 0) { - jmp ITloop; - } else { - jmp mesgin_done; - } - -mesgin_sdptrs_full: - - /* - * The SCB_SGPTR becomes the next one we'll download, - * and the SCB_DATAPTR becomes the current SHADDR. - * Use the residual number since STCNT is corrupted by - * any message transfer. - */ - if ((ahc->features & AHC_CMD_CHAN) != 0) { - bmov SCB_DATAPTR, SHADDR, 4; - if ((ahc->features & AHC_ULTRA2) == 0) { - mov NONE,SCSIDATL; /*dummy read from latch to ACK*/ - } - bmov SCB_DATACNT, SCB_RESIDUAL_DATACNT, 8; - } else { - mvi DINDEX, SCB_DATAPTR; - mvi SHADDR call bcopy_4; - mov NONE,SCSIDATL; /*dummy read from latch to ACK*/ - mvi SCB_RESIDUAL_DATACNT call bcopy_8; - } - jmp ITloop; - -/* - * Restore pointers message? Data pointers are recopied from the - * SCB anytime we enter a data phase for the first time, so all - * we need to do is clear the DPHASE flag and let the data phase - * code do the rest. - */ -mesgin_rdptrs: - and SEQ_FLAGS, ~DPHASE; /* - * We'll reload them - * the next time through - * the dataphase. - */ - jmp mesgin_done; - -/* - * Index into our Busy Target table. SINDEX and DINDEX are modified - * upon return. SCBPTR may be modified by this action. - */ -set_busy_target: - shr DINDEX, 4, SINDEX; - if ((ahc->flags & AHC_SCB_BTT) != 0) { - mov SCBPTR, SAVED_LUN; - add DINDEX, SCB_64_BTT; - } else { - add DINDEX, BUSY_TARGETS; - } - mov DINDIR, ARG_1 ret; - -/* - * Identify message? For a reconnecting target, this tells us the lun - * that the reconnection is for - find the correct SCB and switch to it, - * clearing the "disconnected" bit so we don't "find" it by accident later. - */ -mesgin_identify: - /* - * Determine whether a target is using tagged or non-tagged - * transactions by first looking at the transaction stored in - * the busy target array. If there is no untagged transaction - * for this target or the transaction is for a different lun, then - * this must be an untagged transaction. - */ - shr SINDEX, 4, SAVED_SCSIID; - and SAVED_LUN, MSG_IDENTIFY_LUNMASK, A; - if ((ahc->flags & AHC_SCB_BTT) != 0) { - add SINDEX, SCB_64_BTT; - mov SCBPTR, SAVED_LUN; - if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { - add NONE, -SCB_64_BTT, SINDEX; - jc . + 2; - mvi INTSTAT, OUT_OF_RANGE; - nop; - add NONE, -(SCB_64_BTT + 16), SINDEX; - jnc . + 2; - mvi INTSTAT, OUT_OF_RANGE; - nop; - } - } else { - add SINDEX, BUSY_TARGETS; - if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { - add NONE, -BUSY_TARGETS, SINDEX; - jc . + 2; - mvi INTSTAT, OUT_OF_RANGE; - nop; - add NONE, -(BUSY_TARGETS + 16), SINDEX; - jnc . + 2; - mvi INTSTAT, OUT_OF_RANGE; - nop; - } - } - mov ARG_1, SINDIR; - cmp ARG_1, SCB_LIST_NULL je snoop_tag; - if ((ahc->flags & AHC_PAGESCBS) != 0) { - mov ARG_1 call findSCB; - } else { - mov SCBPTR, ARG_1; - } - if ((ahc->flags & AHC_SCB_BTT) != 0) { - jmp setup_SCB_id_lun_okay; - } else { - /* - * We only allow one untagged command per-target - * at a time. So, if the lun doesn't match, look - * for a tag message. - */ - mov A, SCB_LUN; - cmp SAVED_LUN, A je setup_SCB_id_lun_okay; - if ((ahc->flags & AHC_PAGESCBS) != 0) { - /* - * findSCB removes the SCB from the - * disconnected list, so we must replace - * it there should this SCB be for another - * lun. - */ - call cleanup_scb; - } - } - -/* - * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message. - * If we get one, we use the tag returned to find the proper - * SCB. With SCB paging, we must search for non-tagged - * transactions since the SCB may exist in any slot. If we're not - * using SCB paging, we can use the tag as the direct index to the - * SCB. - */ -snoop_tag: - if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { - or SEQ_FLAGS, 0x80; - } - mov NONE,SCSIDATL; /* ACK Identify MSG */ - call phase_lock; - if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { - or SEQ_FLAGS, 0x1; - } - cmp LASTPHASE, P_MESGIN jne not_found; - if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { - or SEQ_FLAGS, 0x2; - } - cmp SCSIBUSL,MSG_SIMPLE_Q_TAG jne not_found; -get_tag: - if ((ahc->flags & AHC_PAGESCBS) != 0) { - mvi ARG_1 call inb_next; /* tag value */ - mov ARG_1 call findSCB; - } else { - mvi ARG_1 call inb_next; /* tag value */ - mov SCBPTR, ARG_1; - } - -/* - * Ensure that the SCB the tag points to is for - * an SCB transaction to the reconnecting target. - */ -setup_SCB: - if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { - or SEQ_FLAGS, 0x4; - } - mov A, SCB_SCSIID; - cmp SAVED_SCSIID, A jne not_found_cleanup_scb; - if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { - or SEQ_FLAGS, 0x8; - } -setup_SCB_id_okay: - mov A, SCB_LUN; - cmp SAVED_LUN, A jne not_found_cleanup_scb; -setup_SCB_id_lun_okay: - if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { - or SEQ_FLAGS, 0x10; - } - test SCB_CONTROL,DISCONNECTED jz not_found_cleanup_scb; - and SCB_CONTROL,~DISCONNECTED; - test SCB_CONTROL, TAG_ENB jnz setup_SCB_tagged; - if ((ahc->flags & AHC_SCB_BTT) != 0) { - mov A, SCBPTR; - } - mvi ARG_1, SCB_LIST_NULL; - mov SAVED_SCSIID call set_busy_target; - if ((ahc->flags & AHC_SCB_BTT) != 0) { - mov SCBPTR, A; - } -setup_SCB_tagged: - mvi SEQ_FLAGS,IDENTIFY_SEEN; /* make note of IDENTIFY */ - call set_transfer_settings; - /* See if the host wants to send a message upon reconnection */ - test SCB_CONTROL, MK_MESSAGE jz mesgin_done; - mvi HOST_MSG call mk_mesg; - jmp mesgin_done; - -not_found_cleanup_scb: - if ((ahc->flags & AHC_PAGESCBS) != 0) { - call cleanup_scb; - } -not_found: - mvi NO_MATCH call set_seqint; - jmp mesgin_done; - -mk_mesg: - if ((ahc->features & AHC_DT) == 0) { - or SCSISIGO, ATNO, LASTPHASE; - } else { - mvi SCSISIGO, ATNO; - } - mov MSG_OUT,SINDEX ret; - -/* - * Functions to read data in Automatic PIO mode. - * - * According to Adaptec's documentation, an ACK is not sent on input from - * the target until SCSIDATL is read from. So we wait until SCSIDATL is - * latched (the usual way), then read the data byte directly off the bus - * using SCSIBUSL. When we have pulled the ATN line, or we just want to - * acknowledge the byte, then we do a dummy read from SCISDATL. The SCSI - * spec guarantees that the target will hold the data byte on the bus until - * we send our ACK. - * - * The assumption here is that these are called in a particular sequence, - * and that REQ is already set when inb_first is called. inb_{first,next} - * use the same calling convention as inb. - */ -inb_next_wait_perr: - mvi PERR_DETECTED call set_seqint; - jmp inb_next_wait; -inb_next: - mov NONE,SCSIDATL; /*dummy read from latch to ACK*/ -inb_next_wait: - /* - * If there is a parity error, wait for the kernel to - * see the interrupt and prepare our message response - * before continuing. - */ - test SSTAT1, REQINIT jz inb_next_wait; - test SSTAT1, SCSIPERR jnz inb_next_wait_perr; -inb_next_check_phase: - and LASTPHASE, PHASE_MASK, SCSISIGI; - cmp LASTPHASE, P_MESGIN jne mesgin_phasemis; -inb_first: - mov DINDEX,SINDEX; - mov DINDIR,SCSIBUSL ret; /*read byte directly from bus*/ -inb_last: - mov NONE,SCSIDATL ret; /*dummy read from latch to ACK*/ -} - -if ((ahc->flags & AHC_TARGETROLE) != 0) { -/* - * Change to a new phase. If we are changing the state of the I/O signal, - * from out to in, wait an additional data release delay before continuing. - */ -change_phase: - /* Wait for preceeding I/O session to complete. */ - test SCSISIGI, ACKI jnz .; - - /* Change the phase */ - and DINDEX, IOI, SCSISIGI; - mov SCSISIGO, SINDEX; - and A, IOI, SINDEX; - - /* - * If the data direction has changed, from - * out (initiator driving) to in (target driving), - * we must wait at least a data release delay plus - * the normal bus settle delay. [SCSI III SPI 10.11.0] - */ - cmp DINDEX, A je change_phase_wait; - test SINDEX, IOI jz change_phase_wait; - call change_phase_wait; -change_phase_wait: - nop; - nop; - nop; - nop ret; - -/* - * Send a byte to an initiator in Automatic PIO mode. - */ -target_outb: - or SXFRCTL0, SPIOEN; - test SSTAT0, SPIORDY jz .; - mov SCSIDATL, SINDEX; - test SSTAT0, SPIORDY jz .; - and SXFRCTL0, ~SPIOEN ret; -} - -/* - * Locate a disconnected SCB by SCBID. Upon return, SCBPTR and SINDEX will - * be set to the position of the SCB. If the SCB cannot be found locally, - * it will be paged in from host memory. RETURN_2 stores the address of the - * preceding SCB in the disconnected list which can be used to speed up - * removal of the found SCB from the disconnected list. - */ -if ((ahc->flags & AHC_PAGESCBS) != 0) { -BEGIN_CRITICAL; -findSCB: - mov A, SINDEX; /* Tag passed in SINDEX */ - cmp DISCONNECTED_SCBH, SCB_LIST_NULL je findSCB_notFound; - mov SCBPTR, DISCONNECTED_SCBH; /* Initialize SCBPTR */ - mvi ARG_2, SCB_LIST_NULL; /* Head of list */ - jmp findSCB_loop; -findSCB_next: - cmp SCB_NEXT, SCB_LIST_NULL je findSCB_notFound; - mov ARG_2, SCBPTR; - mov SCBPTR,SCB_NEXT; -findSCB_loop: - cmp SCB_TAG, A jne findSCB_next; -rem_scb_from_disc_list: - cmp ARG_2, SCB_LIST_NULL je rHead; - mov DINDEX, SCB_NEXT; - mov SINDEX, SCBPTR; - mov SCBPTR, ARG_2; - mov SCB_NEXT, DINDEX; - mov SCBPTR, SINDEX ret; -rHead: - mov DISCONNECTED_SCBH,SCB_NEXT ret; -END_CRITICAL; -findSCB_notFound: - /* - * We didn't find it. Page in the SCB. - */ - mov ARG_1, A; /* Save tag */ - mov ALLZEROS call get_free_or_disc_scb; - mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET; - mov ARG_1 jmp dma_scb; -} - -/* - * Prepare the hardware to post a byte to host memory given an - * index of (A + (256 * SINDEX)) and a base address of SHARED_DATA_ADDR. - */ -post_byte_setup: - mov ARG_2, SINDEX; - if ((ahc->features & AHC_CMD_CHAN) != 0) { - mvi DINDEX, CCHADDR; - mvi SHARED_DATA_ADDR call set_1byte_addr; - mvi CCHCNT, 1; - mvi CCSCBCTL, CCSCBRESET ret; - } else { - mvi DINDEX, HADDR; - mvi SHARED_DATA_ADDR call set_1byte_addr; - mvi 1 call set_hcnt; - mvi DFCNTRL, FIFORESET ret; - } - -post_byte: - if ((ahc->features & AHC_CMD_CHAN) != 0) { - bmov CCSCBRAM, SINDEX, 1; - or CCSCBCTL, CCSCBEN|CCSCBRESET; - test CCSCBCTL, CCSCBDONE jz .; - clr CCSCBCTL ret; - } else { - mov DFDAT, SINDEX; - or DFCNTRL, HDMAEN|FIFOFLUSH; - jmp dma_finish; - } - -phase_lock_perr: - mvi PERR_DETECTED call set_seqint; -phase_lock: - /* - * If there is a parity error, wait for the kernel to - * see the interrupt and prepare our message response - * before continuing. - */ - test SSTAT1, REQINIT jz phase_lock; - test SSTAT1, SCSIPERR jnz phase_lock_perr; -phase_lock_latch_phase: - if ((ahc->features & AHC_DT) == 0) { - and SCSISIGO, PHASE_MASK, SCSISIGI; - } - and LASTPHASE, PHASE_MASK, SCSISIGI ret; - -if ((ahc->features & AHC_CMD_CHAN) == 0) { -set_hcnt: - mov HCNT[0], SINDEX; -clear_hcnt: - clr HCNT[1]; - clr HCNT[2] ret; - -set_stcnt_from_hcnt: - mov STCNT[0], HCNT[0]; - mov STCNT[1], HCNT[1]; - mov STCNT[2], HCNT[2] ret; - -bcopy_8: - mov DINDIR, SINDIR; -bcopy_7: - mov DINDIR, SINDIR; - mov DINDIR, SINDIR; -bcopy_5: - mov DINDIR, SINDIR; -bcopy_4: - mov DINDIR, SINDIR; -bcopy_3: - mov DINDIR, SINDIR; - mov DINDIR, SINDIR; - mov DINDIR, SINDIR ret; -} - -if ((ahc->flags & AHC_TARGETROLE) != 0) { -/* - * Setup addr assuming that A is an index into - * an array of 32byte objects, SINDEX contains - * the base address of that array, and DINDEX - * contains the base address of the location - * to store the indexed address. - */ -set_32byte_addr: - shr ARG_2, 3, A; - shl A, 5; - jmp set_1byte_addr; -} - -/* - * Setup addr assuming that A is an index into - * an array of 64byte objects, SINDEX contains - * the base address of that array, and DINDEX - * contains the base address of the location - * to store the indexed address. - */ -set_64byte_addr: - shr ARG_2, 2, A; - shl A, 6; - -/* - * Setup addr assuming that A + (ARG_2 * 256) is an - * index into an array of 1byte objects, SINDEX contains - * the base address of that array, and DINDEX contains - * the base address of the location to store the computed - * address. - */ -set_1byte_addr: - add DINDIR, A, SINDIR; - mov A, ARG_2; - adc DINDIR, A, SINDIR; - clr A; - adc DINDIR, A, SINDIR; - adc DINDIR, A, SINDIR ret; - -/* - * Either post or fetch an SCB from host memory based on the - * DIRECTION bit in DMAPARAMS. The host SCB index is in SINDEX. - */ -dma_scb: - mov A, SINDEX; - if ((ahc->features & AHC_CMD_CHAN) != 0) { - mvi DINDEX, CCHADDR; - mvi HSCB_ADDR call set_64byte_addr; - mov CCSCBPTR, SCBPTR; - test DMAPARAMS, DIRECTION jz dma_scb_tohost; - if ((ahc->flags & AHC_SCB_BTT) != 0) { - mvi CCHCNT, SCB_DOWNLOAD_SIZE_64; - } else { - mvi CCHCNT, SCB_DOWNLOAD_SIZE; - } - mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET; - cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .; - jmp dma_scb_finish; -dma_scb_tohost: - mvi CCHCNT, SCB_UPLOAD_SIZE; - if ((ahc->features & AHC_ULTRA2) == 0) { - mvi CCSCBCTL, CCSCBRESET; - bmov CCSCBRAM, SCB_BASE, SCB_UPLOAD_SIZE; - or CCSCBCTL, CCSCBEN|CCSCBRESET; - test CCSCBCTL, CCSCBDONE jz .; - } else if ((ahc->bugs & AHC_SCBCHAN_UPLOAD_BUG) != 0) { - mvi CCSCBCTL, CCARREN|CCSCBRESET; - cmp CCSCBCTL, ARRDONE|CCARREN jne .; - mvi CCHCNT, SCB_UPLOAD_SIZE; - mvi CCSCBCTL, CCSCBEN|CCSCBRESET; - cmp CCSCBCTL, CCSCBDONE|CCSCBEN jne .; - } else { - mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBRESET; - cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN jne .; - } -dma_scb_finish: - clr CCSCBCTL; - test CCSCBCTL, CCARREN|CCSCBEN jnz .; - ret; - } else { - mvi DINDEX, HADDR; - mvi HSCB_ADDR call set_64byte_addr; - mvi SCB_DOWNLOAD_SIZE call set_hcnt; - mov DFCNTRL, DMAPARAMS; - test DMAPARAMS, DIRECTION jnz dma_scb_fromhost; - /* Fill it with the SCB data */ -copy_scb_tofifo: - mvi SINDEX, SCB_BASE; - add A, SCB_DOWNLOAD_SIZE, SINDEX; -copy_scb_tofifo_loop: - call copy_to_fifo_8; - cmp SINDEX, A jne copy_scb_tofifo_loop; - or DFCNTRL, HDMAEN|FIFOFLUSH; - jmp dma_finish; -dma_scb_fromhost: - mvi DINDEX, SCB_BASE; - if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0) { - /* - * The PCI module will only issue a PCI - * retry if the data FIFO is empty. If the - * host disconnects in the middle of a - * transfer, we must empty the fifo of all - * available data to force the chip to - * continue the transfer. This does not - * happen for SCSI transfers as the SCSI module - * will drain the FIFO as data is made available. - * When the hang occurs, we know that a multiple - * of 8 bytes are in the FIFO because the PCI - * module has an 8 byte input latch that only - * dumps to the FIFO when HCNT == 0 or the - * latch is full. - */ - clr A; - /* Wait for at least 8 bytes of data to arrive. */ -dma_scb_hang_fifo: - test DFSTATUS, FIFOQWDEMP jnz dma_scb_hang_fifo; -dma_scb_hang_wait: - test DFSTATUS, MREQPEND jnz dma_scb_hang_wait; - test DFSTATUS, HDONE jnz dma_scb_hang_dma_done; - test DFSTATUS, HDONE jnz dma_scb_hang_dma_done; - test DFSTATUS, HDONE jnz dma_scb_hang_dma_done; - /* - * The PCI module no longer intends to perform - * a PCI transaction. Drain the fifo. - */ -dma_scb_hang_dma_drain_fifo: - not A, HCNT; - add A, SCB_DOWNLOAD_SIZE+SCB_BASE+1; - and A, ~0x7; - mov DINDIR,DFDAT; - cmp DINDEX, A jne . - 1; - cmp DINDEX, SCB_DOWNLOAD_SIZE+SCB_BASE - je dma_finish_nowait; - /* Restore A as the lines left to transfer. */ - add A, -SCB_BASE, DINDEX; - shr A, 3; - jmp dma_scb_hang_fifo; -dma_scb_hang_dma_done: - and DFCNTRL, ~HDMAEN; - test DFCNTRL, HDMAEN jnz .; - add SEQADDR0, A; - } else { - call dma_finish; - } - /* If we were putting the SCB, we are done */ - call dfdat_in_8; - call dfdat_in_8; - call dfdat_in_8; -dfdat_in_8: - mov DINDIR,DFDAT; -dfdat_in_7: - mov DINDIR,DFDAT; - mov DINDIR,DFDAT; - mov DINDIR,DFDAT; - mov DINDIR,DFDAT; - mov DINDIR,DFDAT; -dfdat_in_2: - mov DINDIR,DFDAT; - mov DINDIR,DFDAT ret; - } - -copy_to_fifo_8: - mov DFDAT,SINDIR; - mov DFDAT,SINDIR; -copy_to_fifo_6: - mov DFDAT,SINDIR; -copy_to_fifo_5: - mov DFDAT,SINDIR; -copy_to_fifo_4: - mov DFDAT,SINDIR; - mov DFDAT,SINDIR; - mov DFDAT,SINDIR; - mov DFDAT,SINDIR ret; - -/* - * Wait for DMA from host memory to data FIFO to complete, then disable - * DMA and wait for it to acknowledge that it's off. - */ -dma_finish: - test DFSTATUS,HDONE jz dma_finish; -dma_finish_nowait: - /* Turn off DMA */ - and DFCNTRL, ~HDMAEN; - test DFCNTRL, HDMAEN jnz .; - ret; - -/* - * Restore an SCB that failed to match an incoming reselection - * to the correct/safe state. If the SCB is for a disconnected - * transaction, it must be returned to the disconnected list. - * If it is not in the disconnected state, it must be free. - */ -cleanup_scb: - if ((ahc->flags & AHC_PAGESCBS) != 0) { - test SCB_CONTROL,DISCONNECTED jnz add_scb_to_disc_list; - } -add_scb_to_free_list: - if ((ahc->flags & AHC_PAGESCBS) != 0) { -BEGIN_CRITICAL; - mov SCB_NEXT, FREE_SCBH; - mvi SCB_TAG, SCB_LIST_NULL; - mov FREE_SCBH, SCBPTR ret; -END_CRITICAL; - } else { - mvi SCB_TAG, SCB_LIST_NULL ret; - } - -if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { -set_hhaddr: - or DSCOMMAND1, HADDLDSEL0; - and HADDR, SG_HIGH_ADDR_BITS, SINDEX; - and DSCOMMAND1, ~HADDLDSEL0 ret; -} - -if ((ahc->flags & AHC_PAGESCBS) != 0) { -get_free_or_disc_scb: -BEGIN_CRITICAL; - cmp FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb; - cmp DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb; -return_error: - mvi NO_FREE_SCB call set_seqint; - mvi SINDEX, SCB_LIST_NULL ret; -dequeue_disc_scb: - mov SCBPTR, DISCONNECTED_SCBH; - mov DISCONNECTED_SCBH, SCB_NEXT; -END_CRITICAL; - mvi DMAPARAMS, FIFORESET; - mov SCB_TAG jmp dma_scb; -BEGIN_CRITICAL; -dequeue_free_scb: - mov SCBPTR, FREE_SCBH; - mov FREE_SCBH, SCB_NEXT ret; -END_CRITICAL; - -add_scb_to_disc_list: -/* - * Link this SCB into the DISCONNECTED list. This list holds the - * candidates for paging out an SCB if one is needed for a new command. - * Modifying the disconnected list is a critical(pause dissabled) section. - */ -BEGIN_CRITICAL; - mov SCB_NEXT, DISCONNECTED_SCBH; - mov DISCONNECTED_SCBH, SCBPTR ret; -END_CRITICAL; -} -set_seqint: - mov INTSTAT, SINDEX; - nop; -return: - ret; diff --git a/xen/drivers/scsi/aic7xxx/aic7xxx_93cx6.c b/xen/drivers/scsi/aic7xxx/aic7xxx_93cx6.c deleted file mode 100644 index 0ae6bdebef..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic7xxx_93cx6.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Interface for the 93C66/56/46/26/06 serial eeprom parts. - * - * Copyright (c) 1995, 1996 Daniel M. Eischen - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL"). - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#15 $ - * - * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx_93cx6.c,v 1.8.2.5 2002/04/29 19:36:31 gibbs Exp $ - */ - -/* - * The instruction set of the 93C66/56/46/26/06 chips are as follows: - * - * Start OP * - * Function Bit Code Address** Data Description - * ------------------------------------------------------------------- - * READ 1 10 A5 - A0 Reads data stored in memory, - * starting at specified address - * EWEN 1 00 11XXXX Write enable must precede - * all programming modes - * ERASE 1 11 A5 - A0 Erase register A5A4A3A2A1A0 - * WRITE 1 01 A5 - A0 D15 - D0 Writes register - * ERAL 1 00 10XXXX Erase all registers - * WRAL 1 00 01XXXX D15 - D0 Writes to all registers - * EWDS 1 00 00XXXX Disables all programming - * instructions - * *Note: A value of X for address is a don't care condition. - * **Note: There are 8 address bits for the 93C56/66 chips unlike - * the 93C46/26/06 chips which have 6 address bits. - * - * The 93C46 has a four wire interface: clock, chip select, data in, and - * data out. In order to perform one of the above functions, you need - * to enable the chip select for a clock period (typically a minimum of - * 1 usec, with the clock high and low a minimum of 750 and 250 nsec - * respectively). While the chip select remains high, you can clock in - * the instructions (above) starting with the start bit, followed by the - * OP code, Address, and Data (if needed). For the READ instruction, the - * requested 16-bit register contents is read from the data out line but - * is preceded by an initial zero (leading 0, followed by 16-bits, MSB - * first). The clock cycling from low to high initiates the next data - * bit to be sent from the chip. - * - */ - -#ifdef __linux__ -#include "aic7xxx_osm.h" -#include "aic7xxx_inline.h" -#include "aic7xxx_93cx6.h" -#else -#include -#include -#include -#endif - -/* - * Right now, we only have to read the SEEPROM. But we make it easier to - * add other 93Cx6 functions. - */ -static struct seeprom_cmd { - uint8_t len; - uint8_t bits[9]; -} seeprom_read = {3, {1, 1, 0}}; - -static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}}; -static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}}; -static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}}; - -/* - * Wait for the SEERDY to go high; about 800 ns. - */ -#define CLOCK_PULSE(sd, rdy) \ - while ((SEEPROM_STATUS_INB(sd) & rdy) == 0) { \ - ; /* Do nothing */ \ - } \ - (void)SEEPROM_INB(sd); /* Clear clock */ - -/* - * Send a START condition and the given command - */ -static void -send_seeprom_cmd(struct seeprom_descriptor *sd, struct seeprom_cmd *cmd) -{ - uint8_t temp; - int i = 0; - - /* Send chip select for one clock cycle. */ - temp = sd->sd_MS ^ sd->sd_CS; - SEEPROM_OUTB(sd, temp ^ sd->sd_CK); - CLOCK_PULSE(sd, sd->sd_RDY); - - for (i = 0; i < cmd->len; i++) { - if (cmd->bits[i] != 0) - temp ^= sd->sd_DO; - SEEPROM_OUTB(sd, temp); - CLOCK_PULSE(sd, sd->sd_RDY); - SEEPROM_OUTB(sd, temp ^ sd->sd_CK); - CLOCK_PULSE(sd, sd->sd_RDY); - if (cmd->bits[i] != 0) - temp ^= sd->sd_DO; - } -} - -/* - * Clear CS put the chip in the reset state, where it can wait for new commands. - */ -static void -reset_seeprom(struct seeprom_descriptor *sd) -{ - uint8_t temp; - - temp = sd->sd_MS; - SEEPROM_OUTB(sd, temp); - CLOCK_PULSE(sd, sd->sd_RDY); - SEEPROM_OUTB(sd, temp ^ sd->sd_CK); - CLOCK_PULSE(sd, sd->sd_RDY); - SEEPROM_OUTB(sd, temp); - CLOCK_PULSE(sd, sd->sd_RDY); -} - -/* - * Read the serial EEPROM and returns 1 if successful and 0 if - * not successful. - */ -int -ahc_read_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, - u_int start_addr, u_int count) -{ - int i = 0; - u_int k = 0; - uint16_t v; - uint8_t temp; - - /* - * Read the requested registers of the seeprom. The loop - * will range from 0 to count-1. - */ - for (k = start_addr; k < count + start_addr; k++) { - /* - * Now we're ready to send the read command followed by the - * address of the 16-bit register we want to read. - */ - send_seeprom_cmd(sd, &seeprom_read); - - /* Send the 6 or 8 bit address (MSB first, LSB last). */ - temp = sd->sd_MS ^ sd->sd_CS; - for (i = (sd->sd_chip - 1); i >= 0; i--) { - if ((k & (1 << i)) != 0) - temp ^= sd->sd_DO; - SEEPROM_OUTB(sd, temp); - CLOCK_PULSE(sd, sd->sd_RDY); - SEEPROM_OUTB(sd, temp ^ sd->sd_CK); - CLOCK_PULSE(sd, sd->sd_RDY); - if ((k & (1 << i)) != 0) - temp ^= sd->sd_DO; - } - - /* - * Now read the 16 bit register. An initial 0 precedes the - * register contents which begins with bit 15 (MSB) and ends - * with bit 0 (LSB). The initial 0 will be shifted off the - * top of our word as we let the loop run from 0 to 16. - */ - v = 0; - for (i = 16; i >= 0; i--) { - SEEPROM_OUTB(sd, temp); - CLOCK_PULSE(sd, sd->sd_RDY); - v <<= 1; - if (SEEPROM_DATA_INB(sd) & sd->sd_DI) - v |= 1; - SEEPROM_OUTB(sd, temp ^ sd->sd_CK); - CLOCK_PULSE(sd, sd->sd_RDY); - } - - buf[k - start_addr] = v; - - /* Reset the chip select for the next command cycle. */ - reset_seeprom(sd); - } -#ifdef AHC_DUMP_EEPROM - printf("\nSerial EEPROM:\n\t"); - for (k = 0; k < count; k = k + 1) { - if (((k % 8) == 0) && (k != 0)) { - printf ("\n\t"); - } - printf (" 0x%x", buf[k]); - } - printf ("\n"); -#endif - return (1); -} - -/* - * Write the serial EEPROM and return 1 if successful and 0 if - * not successful. - */ -int -ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, - u_int start_addr, u_int count) -{ - uint16_t v; - uint8_t temp; - int i, k; - - /* Place the chip into write-enable mode */ - send_seeprom_cmd(sd, &seeprom_ewen); - reset_seeprom(sd); - - /* Write all requested data out to the seeprom. */ - temp = sd->sd_MS ^ sd->sd_CS; - for (k = start_addr; k < count + start_addr; k++) { - /* Send the write command */ - send_seeprom_cmd(sd, &seeprom_write); - - /* Send the 6 or 8 bit address (MSB first). */ - for (i = (sd->sd_chip - 1); i >= 0; i--) { - if ((k & (1 << i)) != 0) - temp ^= sd->sd_DO; - SEEPROM_OUTB(sd, temp); - CLOCK_PULSE(sd, sd->sd_RDY); - SEEPROM_OUTB(sd, temp ^ sd->sd_CK); - CLOCK_PULSE(sd, sd->sd_RDY); - if ((k & (1 << i)) != 0) - temp ^= sd->sd_DO; - } - - /* Write the 16 bit value, MSB first */ - v = buf[k - start_addr]; - for (i = 15; i >= 0; i--) { - if ((v & (1 << i)) != 0) - temp ^= sd->sd_DO; - SEEPROM_OUTB(sd, temp); - CLOCK_PULSE(sd, sd->sd_RDY); - SEEPROM_OUTB(sd, temp ^ sd->sd_CK); - CLOCK_PULSE(sd, sd->sd_RDY); - if ((v & (1 << i)) != 0) - temp ^= sd->sd_DO; - } - - /* Wait for the chip to complete the write */ - temp = sd->sd_MS; - SEEPROM_OUTB(sd, temp); - CLOCK_PULSE(sd, sd->sd_RDY); - temp = sd->sd_MS ^ sd->sd_CS; - do { - SEEPROM_OUTB(sd, temp); - CLOCK_PULSE(sd, sd->sd_RDY); - SEEPROM_OUTB(sd, temp ^ sd->sd_CK); - CLOCK_PULSE(sd, sd->sd_RDY); - } while ((SEEPROM_DATA_INB(sd) & sd->sd_DI) == 0); - - reset_seeprom(sd); - } - - /* Put the chip back into write-protect mode */ - send_seeprom_cmd(sd, &seeprom_ewds); - reset_seeprom(sd); - - return (1); -} - -int -ahc_verify_cksum(struct seeprom_config *sc) -{ - int i; - int maxaddr; - uint32_t checksum; - uint16_t *scarray; - - maxaddr = (sizeof(*sc)/2) - 1; - checksum = 0; - scarray = (uint16_t *)sc; - - for (i = 0; i < maxaddr; i++) - checksum = checksum + scarray[i]; - if (checksum == 0 - || (checksum & 0xFFFF) != sc->checksum) { - return (0); - } else { - return(1); - } -} diff --git a/xen/drivers/scsi/aic7xxx/aic7xxx_93cx6.h b/xen/drivers/scsi/aic7xxx/aic7xxx_93cx6.h deleted file mode 100644 index 9535c7283f..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic7xxx_93cx6.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Interface to the 93C46/56 serial EEPROM that is used to store BIOS - * settings for the aic7xxx based adaptec SCSI controllers. It can - * also be used for 93C26 and 93C06 serial EEPROMS. - * - * Copyright (c) 1994, 1995, 2000 Justin T. Gibbs. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.h#10 $ - * - * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx_93cx6.h,v 1.7.2.3 2002/04/29 19:36:31 gibbs Exp $ - */ -#ifndef _AIC7XXX_93CX6_H_ -#define _AIC7XXX_93CX6_H_ - -typedef enum { - C46 = 6, - C56_66 = 8 -} seeprom_chip_t; - -struct seeprom_descriptor { - struct ahc_softc *sd_ahc; - u_int sd_control_offset; - u_int sd_status_offset; - u_int sd_dataout_offset; - seeprom_chip_t sd_chip; - uint16_t sd_MS; - uint16_t sd_RDY; - uint16_t sd_CS; - uint16_t sd_CK; - uint16_t sd_DO; - uint16_t sd_DI; -}; - -/* - * This function will read count 16-bit words from the serial EEPROM and - * return their value in buf. The port address of the aic7xxx serial EEPROM - * control register is passed in as offset. The following parameters are - * also passed in: - * - * CS - Chip select - * CK - Clock - * DO - Data out - * DI - Data in - * RDY - SEEPROM ready - * MS - Memory port mode select - * - * A failed read attempt returns 0, and a successful read returns 1. - */ - -#define SEEPROM_INB(sd) \ - ahc_inb(sd->sd_ahc, sd->sd_control_offset) -#define SEEPROM_OUTB(sd, value) \ -do { \ - ahc_outb(sd->sd_ahc, sd->sd_control_offset, value); \ - ahc_flush_device_writes(sd->sd_ahc); \ -} while(0) - -#define SEEPROM_STATUS_INB(sd) \ - ahc_inb(sd->sd_ahc, sd->sd_status_offset) -#define SEEPROM_DATA_INB(sd) \ - ahc_inb(sd->sd_ahc, sd->sd_dataout_offset) - -int ahc_read_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, - u_int start_addr, u_int count); -int ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, - u_int start_addr, u_int count); -int ahc_verify_cksum(struct seeprom_config *sc); - -#endif /* _AIC7XXX_93CX6_H_ */ diff --git a/xen/drivers/scsi/aic7xxx/aic7xxx_core.c b/xen/drivers/scsi/aic7xxx/aic7xxx_core.c deleted file mode 100644 index ebbf161d08..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic7xxx_core.c +++ /dev/null @@ -1,7127 +0,0 @@ -/* - * Core routines and tables shareable across OS platforms. - * - * Copyright (c) 1994-2001 Justin T. Gibbs. - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#69 $ - * - * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.c,v 1.41.2.22 2002/04/29 19:36:26 gibbs Exp $ - */ - -#ifdef __linux__ -#include "aic7xxx_osm.h" -#include "aic7xxx_inline.h" -#include "aicasm/aicasm_insformat.h" -#else -#include -#include -#include -#endif - -/****************************** Softc Data ************************************/ -struct ahc_softc_tailq ahc_tailq = TAILQ_HEAD_INITIALIZER(ahc_tailq); - -/***************************** Lookup Tables **********************************/ -char *ahc_chip_names[] = -{ - "NONE", - "aic7770", - "aic7850", - "aic7855", - "aic7859", - "aic7860", - "aic7870", - "aic7880", - "aic7895", - "aic7895C", - "aic7890/91", - "aic7896/97", - "aic7892", - "aic7899" -}; -static const u_int num_chip_names = NUM_ELEMENTS(ahc_chip_names); - -/* - * Hardware error codes. - */ -struct ahc_hard_error_entry { - uint8_t errno; - char *errmesg; -}; - -static struct ahc_hard_error_entry ahc_hard_errors[] = { - { ILLHADDR, "Illegal Host Access" }, - { ILLSADDR, "Illegal Sequencer Address referrenced" }, - { ILLOPCODE, "Illegal Opcode in sequencer program" }, - { SQPARERR, "Sequencer Parity Error" }, - { DPARERR, "Data-path Parity Error" }, - { MPARERR, "Scratch or SCB Memory Parity Error" }, - { PCIERRSTAT, "PCI Error detected" }, - { CIOPARERR, "CIOBUS Parity Error" }, -}; -static const u_int num_errors = NUM_ELEMENTS(ahc_hard_errors); - -static struct ahc_phase_table_entry ahc_phase_table[] = -{ - { P_DATAOUT, MSG_NOOP, "in Data-out phase" }, - { P_DATAIN, MSG_INITIATOR_DET_ERR, "in Data-in phase" }, - { P_DATAOUT_DT, MSG_NOOP, "in DT Data-out phase" }, - { P_DATAIN_DT, MSG_INITIATOR_DET_ERR, "in DT Data-in phase" }, - { P_COMMAND, MSG_NOOP, "in Command phase" }, - { P_MESGOUT, MSG_NOOP, "in Message-out phase" }, - { P_STATUS, MSG_INITIATOR_DET_ERR, "in Status phase" }, - { P_MESGIN, MSG_PARITY_ERROR, "in Message-in phase" }, - { P_BUSFREE, MSG_NOOP, "while idle" }, - { 0, MSG_NOOP, "in unknown phase" } -}; - -/* - * In most cases we only wish to itterate over real phases, so - * exclude the last element from the count. - */ -static const u_int num_phases = NUM_ELEMENTS(ahc_phase_table) - 1; - -/* - * Valid SCSIRATE values. (p. 3-17) - * Provides a mapping of tranfer periods in ns to the proper value to - * stick in the scsixfer reg. - */ -static struct ahc_syncrate ahc_syncrates[] = -{ - /* ultra2 fast/ultra period rate */ - { 0x42, 0x000, 9, "80.0" }, - { 0x03, 0x000, 10, "40.0" }, - { 0x04, 0x000, 11, "33.0" }, - { 0x05, 0x100, 12, "20.0" }, - { 0x06, 0x110, 15, "16.0" }, - { 0x07, 0x120, 18, "13.4" }, - { 0x08, 0x000, 25, "10.0" }, - { 0x19, 0x010, 31, "8.0" }, - { 0x1a, 0x020, 37, "6.67" }, - { 0x1b, 0x030, 43, "5.7" }, - { 0x1c, 0x040, 50, "5.0" }, - { 0x00, 0x050, 56, "4.4" }, - { 0x00, 0x060, 62, "4.0" }, - { 0x00, 0x070, 68, "3.6" }, - { 0x00, 0x000, 0, NULL } -}; - -/* Our Sequencer Program */ -#include "aic7xxx_seq.h" - -/**************************** Function Declarations ***************************/ -static void ahc_force_renegotiation(struct ahc_softc *ahc); -static struct ahc_tmode_tstate* - ahc_alloc_tstate(struct ahc_softc *ahc, - u_int scsi_id, char channel); -#ifdef AHC_TARGET_MODE -static void ahc_free_tstate(struct ahc_softc *ahc, - u_int scsi_id, char channel, int force); -#endif -static struct ahc_syncrate* - ahc_devlimited_syncrate(struct ahc_softc *ahc, - struct ahc_initiator_tinfo *, - u_int *period, - u_int *ppr_options, - role_t role); -static void ahc_update_pending_scbs(struct ahc_softc *ahc); -static void ahc_fetch_devinfo(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo); -static void ahc_scb_devinfo(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo, - struct scb *scb); -static void ahc_assert_atn(struct ahc_softc *ahc); -static void ahc_setup_initiator_msgout(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo, - struct scb *scb); -static void ahc_build_transfer_msg(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo); -static void ahc_construct_sdtr(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo, - u_int period, u_int offset); -static void ahc_construct_wdtr(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo, - u_int bus_width); -static void ahc_construct_ppr(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo, - u_int period, u_int offset, - u_int bus_width, u_int ppr_options); -static void ahc_clear_msg_state(struct ahc_softc *ahc); -static void ahc_handle_message_phase(struct ahc_softc *ahc); -typedef enum { - AHCMSG_1B, - AHCMSG_2B, - AHCMSG_EXT -} ahc_msgtype; -static int ahc_sent_msg(struct ahc_softc *ahc, ahc_msgtype type, - u_int msgval, int full); -static int ahc_parse_msg(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo); -static int ahc_handle_msg_reject(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo); -static void ahc_handle_ign_wide_residue(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo); -static void ahc_reinitialize_dataptrs(struct ahc_softc *ahc); -static void ahc_handle_devreset(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo, - cam_status status, char *message, - int verbose_level); -#if AHC_TARGET_MODE -static void ahc_setup_target_msgin(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo, - struct scb *scb); -#endif - -static bus_dmamap_callback_t ahc_dmamap_cb; -static void ahc_build_free_scb_list(struct ahc_softc *ahc); -static int ahc_init_scbdata(struct ahc_softc *ahc); -static void ahc_fini_scbdata(struct ahc_softc *ahc); -static void ahc_qinfifo_requeue(struct ahc_softc *ahc, - struct scb *prev_scb, - struct scb *scb); -static int ahc_qinfifo_count(struct ahc_softc *ahc); -static u_int ahc_rem_scb_from_disc_list(struct ahc_softc *ahc, - u_int prev, u_int scbptr); -static void ahc_add_curscb_to_free_list(struct ahc_softc *ahc); -static u_int ahc_rem_wscb(struct ahc_softc *ahc, - u_int scbpos, u_int prev); -static void ahc_reset_current_bus(struct ahc_softc *ahc); -#ifdef AHC_DUMP_SEQ -static void ahc_dumpseq(struct ahc_softc *ahc); -#endif -static void ahc_loadseq(struct ahc_softc *ahc); -static int ahc_check_patch(struct ahc_softc *ahc, - struct patch **start_patch, - u_int start_instr, u_int *skip_addr); -static void ahc_download_instr(struct ahc_softc *ahc, - u_int instrptr, uint8_t *dconsts); -#ifdef AHC_TARGET_MODE -static void ahc_queue_lstate_event(struct ahc_softc *ahc, - struct ahc_tmode_lstate *lstate, - u_int initiator_id, - u_int event_type, - u_int event_arg); -static void ahc_update_scsiid(struct ahc_softc *ahc, - u_int targid_mask); -static int ahc_handle_target_cmd(struct ahc_softc *ahc, - struct target_cmd *cmd); -#endif -/************************* Sequencer Execution Control ************************/ -/* - * Restart the sequencer program from address zero - */ -void -ahc_restart(struct ahc_softc *ahc) -{ - - ahc_pause(ahc); - - /* No more pending messages. */ - ahc_clear_msg_state(ahc); - - ahc_outb(ahc, SCSISIGO, 0); /* De-assert BSY */ - ahc_outb(ahc, MSG_OUT, MSG_NOOP); /* No message to send */ - ahc_outb(ahc, SXFRCTL1, ahc_inb(ahc, SXFRCTL1) & ~BITBUCKET); - ahc_outb(ahc, LASTPHASE, P_BUSFREE); - ahc_outb(ahc, SAVED_SCSIID, 0xFF); - ahc_outb(ahc, SAVED_LUN, 0xFF); - - /* - * Ensure that the sequencer's idea of TQINPOS - * matches our own. The sequencer increments TQINPOS - * only after it sees a DMA complete and a reset could - * occur before the increment leaving the kernel to believe - * the command arrived but the sequencer to not. - */ - ahc_outb(ahc, TQINPOS, ahc->tqinfifonext); - - /* Always allow reselection */ - ahc_outb(ahc, SCSISEQ, - ahc_inb(ahc, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP)); - if ((ahc->features & AHC_CMD_CHAN) != 0) { - /* Ensure that no DMA operations are in progress */ - ahc_outb(ahc, CCSCBCNT, 0); - ahc_outb(ahc, CCSGCTL, 0); - ahc_outb(ahc, CCSCBCTL, 0); - } - /* - * If we were in the process of DMA'ing SCB data into - * an SCB, replace that SCB on the free list. This prevents - * an SCB leak. - */ - if ((ahc_inb(ahc, SEQ_FLAGS2) & SCB_DMA) != 0) { - ahc_add_curscb_to_free_list(ahc); - ahc_outb(ahc, SEQ_FLAGS2, - ahc_inb(ahc, SEQ_FLAGS2) & ~SCB_DMA); - } - ahc_outb(ahc, MWI_RESIDUAL, 0); - ahc_outb(ahc, SEQCTL, FASTMODE); - ahc_outb(ahc, SEQADDR0, 0); - ahc_outb(ahc, SEQADDR1, 0); - ahc_unpause(ahc); -} - -/************************* Input/Output Queues ********************************/ -void -ahc_run_qoutfifo(struct ahc_softc *ahc) -{ - struct scb *scb; - u_int scb_index; - - ahc_sync_qoutfifo(ahc, BUS_DMASYNC_POSTREAD); - while (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL) { - - scb_index = ahc->qoutfifo[ahc->qoutfifonext]; - if ((ahc->qoutfifonext & 0x03) == 0x03) { - u_int modnext; - - /* - * Clear 32bits of QOUTFIFO at a time - * so that we don't clobber an incoming - * byte DMA to the array on architectures - * that only support 32bit load and store - * operations. - */ - modnext = ahc->qoutfifonext & ~0x3; - *((uint32_t *)(&ahc->qoutfifo[modnext])) = 0xFFFFFFFFUL; - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, - ahc->shared_data_dmamap, - /*offset*/modnext, /*len*/4, - BUS_DMASYNC_PREREAD); - } - ahc->qoutfifonext++; - - scb = ahc_lookup_scb(ahc, scb_index); - if (scb == NULL) { - printf("%s: WARNING no command for scb %d " - "(cmdcmplt)\nQOUTPOS = %d\n", - ahc_name(ahc), scb_index, - ahc->qoutfifonext - 1); - continue; - } - - /* - * Save off the residual - * if there is one. - */ - ahc_update_residual(ahc, scb); - ahc_done(ahc, scb); - } -} - -void -ahc_run_untagged_queues(struct ahc_softc *ahc) -{ - int i; - - for (i = 0; i < 16; i++) - ahc_run_untagged_queue(ahc, &ahc->untagged_queues[i]); -} - -void -ahc_run_untagged_queue(struct ahc_softc *ahc, struct scb_tailq *queue) -{ - struct scb *scb; - - if (ahc->untagged_queue_lock != 0) - return; - - if ((scb = TAILQ_FIRST(queue)) != NULL - && (scb->flags & SCB_ACTIVE) == 0) { - scb->flags |= SCB_ACTIVE; - ahc_queue_scb(ahc, scb); - } -} - -/************************* Interrupt Handling *********************************/ -void -ahc_handle_brkadrint(struct ahc_softc *ahc) -{ - /* - * We upset the sequencer :-( - * Lookup the error message - */ - int i; - int error; - - error = ahc_inb(ahc, ERROR); - for (i = 0; error != 1 && i < num_errors; i++) - error >>= 1; - printf("%s: brkadrint, %s at seqaddr = 0x%x\n", - ahc_name(ahc), ahc_hard_errors[i].errmesg, - ahc_inb(ahc, SEQADDR0) | - (ahc_inb(ahc, SEQADDR1) << 8)); - - ahc_dump_card_state(ahc); - - /* Tell everyone that this HBA is no longer availible */ - ahc_abort_scbs(ahc, CAM_TARGET_WILDCARD, ALL_CHANNELS, - CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_UNKNOWN, - CAM_NO_HBA); - - /* Disable all interrupt sources by resetting the controller */ - ahc_shutdown(ahc); -} - -void -ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) -{ - struct scb *scb; - struct ahc_devinfo devinfo; - - ahc_fetch_devinfo(ahc, &devinfo); - - /* - * Clear the upper byte that holds SEQINT status - * codes and clear the SEQINT bit. We will unpause - * the sequencer, if appropriate, after servicing - * the request. - */ - ahc_outb(ahc, CLRINT, CLRSEQINT); - switch (intstat & SEQINT_MASK) { - case BAD_STATUS: - { - u_int scb_index; - struct hardware_scb *hscb; - - /* - * Set the default return value to 0 (don't - * send sense). The sense code will change - * this if needed. - */ - ahc_outb(ahc, RETURN_1, 0); - - /* - * The sequencer will notify us when a command - * has an error that would be of interest to - * the kernel. This allows us to leave the sequencer - * running in the common case of command completes - * without error. The sequencer will already have - * dma'd the SCB back up to us, so we can reference - * the in kernel copy directly. - */ - scb_index = ahc_inb(ahc, SCB_TAG); - scb = ahc_lookup_scb(ahc, scb_index); - if (scb == NULL) { - printf("%s:%c:%d: ahc_intr - referenced scb " - "not valid during seqint 0x%x scb(%d)\n", - ahc_name(ahc), devinfo.channel, - devinfo.target, intstat, scb_index); - ahc_dump_card_state(ahc); - panic("for safety"); - goto unpause; - } - - hscb = scb->hscb; - - /* Don't want to clobber the original sense code */ - if ((scb->flags & SCB_SENSE) != 0) { - /* - * Clear the SCB_SENSE Flag and have - * the sequencer do a normal command - * complete. - */ - scb->flags &= ~SCB_SENSE; - ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); - break; - } - ahc_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR); - /* Freeze the queue until the client sees the error. */ - ahc_freeze_devq(ahc, scb); - ahc_freeze_scb(scb); - ahc_set_scsi_status(scb, hscb->shared_data.status.scsi_status); - switch (hscb->shared_data.status.scsi_status) { - case SCSI_STATUS_OK: - printf("%s: Interrupted for staus of 0???\n", - ahc_name(ahc)); - break; - case SCSI_STATUS_CMD_TERMINATED: - case SCSI_STATUS_CHECK_COND: - { - struct ahc_dma_seg *sg; - struct scsi_sense *sc; - struct ahc_initiator_tinfo *targ_info; - struct ahc_tmode_tstate *tstate; - struct ahc_transinfo *tinfo; -#ifdef AHC_DEBUG - if (ahc_debug & AHC_SHOWSENSE) { - ahc_print_path(ahc, scb); - printf("SCB %d: requests Check Status\n", - scb->hscb->tag); - } -#endif - - if (ahc_perform_autosense(scb) == 0) - break; - - targ_info = ahc_fetch_transinfo(ahc, - devinfo.channel, - devinfo.our_scsiid, - devinfo.target, - &tstate); - tinfo = &targ_info->curr; - sg = scb->sg_list; - sc = (struct scsi_sense *)(&hscb->shared_data.cdb); - /* - * Save off the residual if there is one. - */ - ahc_update_residual(ahc, scb); -#ifdef AHC_DEBUG - if (ahc_debug & AHC_SHOWSENSE) { - ahc_print_path(ahc, scb); - printf("Sending Sense\n"); - } -#endif - sg->addr = ahc_get_sense_bufaddr(ahc, scb); - sg->len = ahc_get_sense_bufsize(ahc, scb); - sg->len |= AHC_DMA_LAST_SEG; - - /* Fixup byte order */ - sg->addr = ahc_htole32(sg->addr); - sg->len = ahc_htole32(sg->len); - - sc->opcode = REQUEST_SENSE; - sc->byte2 = 0; - if (tinfo->protocol_version <= SCSI_REV_2 - && SCB_GET_LUN(scb) < 8) - sc->byte2 = SCB_GET_LUN(scb) << 5; - sc->unused[0] = 0; - sc->unused[1] = 0; - sc->length = sg->len; - sc->control = 0; - - /* - * We can't allow the target to disconnect. - * This will be an untagged transaction and - * having the target disconnect will make this - * transaction indestinguishable from outstanding - * tagged transactions. - */ - hscb->control = 0; - - /* - * This request sense could be because the - * the device lost power or in some other - * way has lost our transfer negotiations. - * Renegotiate if appropriate. Unit attention - * errors will be reported before any data - * phases occur. - */ - if (ahc_get_residual(scb) - == ahc_get_transfer_length(scb)) { - ahc_update_neg_request(ahc, &devinfo, - tstate, targ_info, - /*force*/TRUE); - } - if (tstate->auto_negotiate & devinfo.target_mask) { - hscb->control |= MK_MESSAGE; - scb->flags &= ~SCB_NEGOTIATE; - scb->flags |= SCB_AUTO_NEGOTIATE; - } - hscb->cdb_len = sizeof(*sc); - hscb->dataptr = sg->addr; - hscb->datacnt = sg->len; - hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID; - hscb->sgptr = ahc_htole32(hscb->sgptr); - scb->sg_count = 1; - scb->flags |= SCB_SENSE; - ahc_qinfifo_requeue_tail(ahc, scb); - ahc_outb(ahc, RETURN_1, SEND_SENSE); -#ifdef __FreeBSD__ - /* - * Ensure we have enough time to actually - * retrieve the sense. - */ - untimeout(ahc_timeout, (caddr_t)scb, - scb->io_ctx->ccb_h.timeout_ch); - scb->io_ctx->ccb_h.timeout_ch = - timeout(ahc_timeout, (caddr_t)scb, 5 * hz); -#endif - break; - } - default: - break; - } - break; - } - case NO_MATCH: - { - /* Ensure we don't leave the selection hardware on */ - ahc_outb(ahc, SCSISEQ, - ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP)); - - printf("%s:%c:%d: no active SCB for reconnecting " - "target - issuing BUS DEVICE RESET\n", - ahc_name(ahc), devinfo.channel, devinfo.target); - printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, " - "ARG_1 == 0x%x ACCUM = 0x%x\n", - ahc_inb(ahc, SAVED_SCSIID), ahc_inb(ahc, SAVED_LUN), - ahc_inb(ahc, ARG_1), ahc_inb(ahc, ACCUM)); - printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, " - "SINDEX == 0x%x\n", - ahc_inb(ahc, SEQ_FLAGS), ahc_inb(ahc, SCBPTR), - ahc_index_busy_tcl(ahc, - BUILD_TCL(ahc_inb(ahc, SAVED_SCSIID), - ahc_inb(ahc, SAVED_LUN))), - ahc_inb(ahc, SINDEX)); - printf("SCSIID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, " - "SCB_TAG == 0x%x, SCB_CONTROL == 0x%x\n", - ahc_inb(ahc, SCSIID), ahc_inb(ahc, SCB_SCSIID), - ahc_inb(ahc, SCB_LUN), ahc_inb(ahc, SCB_TAG), - ahc_inb(ahc, SCB_CONTROL)); - printf("SCSIBUSL == 0x%x, SCSISIGI == 0x%x\n", - ahc_inb(ahc, SCSIBUSL), ahc_inb(ahc, SCSISIGI)); - printf("SXFRCTL0 == 0x%x\n", ahc_inb(ahc, SXFRCTL0)); - printf("SEQCTL == 0x%x\n", ahc_inb(ahc, SEQCTL)); - ahc_dump_card_state(ahc); - ahc->msgout_buf[0] = MSG_BUS_DEV_RESET; - ahc->msgout_len = 1; - ahc->msgout_index = 0; - ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT; - ahc_outb(ahc, MSG_OUT, HOST_MSG); - ahc_assert_atn(ahc); - break; - } - case SEND_REJECT: - { - u_int rejbyte = ahc_inb(ahc, ACCUM); - printf("%s:%c:%d: Warning - unknown message received from " - "target (0x%x). Rejecting\n", - ahc_name(ahc), devinfo.channel, devinfo.target, rejbyte); - break; - } - case NO_IDENT: - { - /* - * The reconnecting target either did not send an identify - * message, or did, but we didn't find an SCB to match and - * before it could respond to our ATN/abort, it hit a dataphase. - * The only safe thing to do is to blow it away with a bus - * reset. - */ - int found; - - printf("%s:%c:%d: Target did not send an IDENTIFY message. " - "LASTPHASE = 0x%x, SAVED_SCSIID == 0x%x\n", - ahc_name(ahc), devinfo.channel, devinfo.target, - ahc_inb(ahc, LASTPHASE), ahc_inb(ahc, SAVED_SCSIID)); - found = ahc_reset_channel(ahc, devinfo.channel, - /*initiate reset*/TRUE); - printf("%s: Issued Channel %c Bus Reset. " - "%d SCBs aborted\n", ahc_name(ahc), devinfo.channel, - found); - return; - } - case IGN_WIDE_RES: - ahc_handle_ign_wide_residue(ahc, &devinfo); - break; - case PDATA_REINIT: - ahc_reinitialize_dataptrs(ahc); - break; - case BAD_PHASE: - { - u_int lastphase; - - lastphase = ahc_inb(ahc, LASTPHASE); - printf("%s:%c:%d: unknown scsi bus phase %x, " - "lastphase = 0x%x. Attempting to continue\n", - ahc_name(ahc), devinfo.channel, devinfo.target, - lastphase, ahc_inb(ahc, SCSISIGI)); - break; - } - case MISSED_BUSFREE: - { - u_int lastphase; - - lastphase = ahc_inb(ahc, LASTPHASE); - printf("%s:%c:%d: Missed busfree. " - "Lastphase = 0x%x, Curphase = 0x%x\n", - ahc_name(ahc), devinfo.channel, devinfo.target, - lastphase, ahc_inb(ahc, SCSISIGI)); - ahc_restart(ahc); - return; - } - case HOST_MSG_LOOP: - { - /* - * The sequencer has encountered a message phase - * that requires host assistance for completion. - * While handling the message phase(s), we will be - * notified by the sequencer after each byte is - * transfered so we can track bus phase changes. - * - * If this is the first time we've seen a HOST_MSG_LOOP - * interrupt, initialize the state of the host message - * loop. - */ - if (ahc->msg_type == MSG_TYPE_NONE) { - struct scb *scb; - u_int scb_index; - u_int bus_phase; - - bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; - if (bus_phase != P_MESGIN - && bus_phase != P_MESGOUT) { - printf("ahc_intr: HOST_MSG_LOOP bad " - "phase 0x%x\n", - bus_phase); - /* - * Probably transitioned to bus free before - * we got here. Just punt the message. - */ - ahc_clear_intstat(ahc); - ahc_restart(ahc); - return; - } - - scb_index = ahc_inb(ahc, SCB_TAG); - scb = ahc_lookup_scb(ahc, scb_index); - if (devinfo.role == ROLE_INITIATOR) { - if (scb == NULL) - panic("HOST_MSG_LOOP with " - "invalid SCB %x\n", scb_index); - - if (bus_phase == P_MESGOUT) - ahc_setup_initiator_msgout(ahc, - &devinfo, - scb); - else { - ahc->msg_type = - MSG_TYPE_INITIATOR_MSGIN; - ahc->msgin_index = 0; - } - } -#if AHC_TARGET_MODE - else { - if (bus_phase == P_MESGOUT) { - ahc->msg_type = - MSG_TYPE_TARGET_MSGOUT; - ahc->msgin_index = 0; - } - else - ahc_setup_target_msgin(ahc, - &devinfo, - scb); - } -#endif - } - - ahc_handle_message_phase(ahc); - break; - } - case PERR_DETECTED: - { - /* - * If we've cleared the parity error interrupt - * but the sequencer still believes that SCSIPERR - * is true, it must be that the parity error is - * for the currently presented byte on the bus, - * and we are not in a phase (data-in) where we will - * eventually ack this byte. Ack the byte and - * throw it away in the hope that the target will - * take us to message out to deliver the appropriate - * error message. - */ - if ((intstat & SCSIINT) == 0 - && (ahc_inb(ahc, SSTAT1) & SCSIPERR) != 0) { - - if ((ahc->features & AHC_DT) == 0) { - u_int curphase; - - /* - * The hardware will only let you ack bytes - * if the expected phase in SCSISIGO matches - * the current phase. Make sure this is - * currently the case. - */ - curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; - ahc_outb(ahc, LASTPHASE, curphase); - ahc_outb(ahc, SCSISIGO, curphase); - } - ahc_inb(ahc, SCSIDATL); - } - break; - } - case DATA_OVERRUN: - { - /* - * When the sequencer detects an overrun, it - * places the controller in "BITBUCKET" mode - * and allows the target to complete its transfer. - * Unfortunately, none of the counters get updated - * when the controller is in this mode, so we have - * no way of knowing how large the overrun was. - */ - u_int scbindex = ahc_inb(ahc, SCB_TAG); - u_int lastphase = ahc_inb(ahc, LASTPHASE); - u_int i; - - scb = ahc_lookup_scb(ahc, scbindex); - for (i = 0; i < num_phases; i++) { - if (lastphase == ahc_phase_table[i].phase) - break; - } - ahc_print_path(ahc, scb); - printf("data overrun detected %s." - " Tag == 0x%x.\n", - ahc_phase_table[i].phasemsg, - scb->hscb->tag); - ahc_print_path(ahc, scb); - printf("%s seen Data Phase. Length = %ld. NumSGs = %d.\n", - ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't", - ahc_get_transfer_length(scb), scb->sg_count); - if (scb->sg_count > 0) { - for (i = 0; i < scb->sg_count; i++) { - - printf("sg[%d] - Addr 0x%x%x : Length %d\n", - i, - (ahc_le32toh(scb->sg_list[i].len) >> 24 - & SG_HIGH_ADDR_BITS), - ahc_le32toh(scb->sg_list[i].addr), - ahc_le32toh(scb->sg_list[i].len) - & AHC_SG_LEN_MASK); - } - } - /* - * Set this and it will take effect when the - * target does a command complete. - */ - ahc_freeze_devq(ahc, scb); - if ((scb->flags & SCB_SENSE) == 0) { - ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR); - } else { - scb->flags &= ~SCB_SENSE; - ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); - } - ahc_freeze_scb(scb); - - if ((ahc->features & AHC_ULTRA2) != 0) { - /* - * Clear the channel in case we return - * to data phase later. - */ - ahc_outb(ahc, SXFRCTL0, - ahc_inb(ahc, SXFRCTL0) | CLRSTCNT|CLRCHN); - ahc_outb(ahc, SXFRCTL0, - ahc_inb(ahc, SXFRCTL0) | CLRSTCNT|CLRCHN); - } - if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { - u_int dscommand1; - - /* Ensure HHADDR is 0 for future DMA operations. */ - dscommand1 = ahc_inb(ahc, DSCOMMAND1); - ahc_outb(ahc, DSCOMMAND1, dscommand1 | HADDLDSEL0); - ahc_outb(ahc, HADDR, 0); - ahc_outb(ahc, DSCOMMAND1, dscommand1); - } - break; - } - case MKMSG_FAILED: - { - u_int scbindex; - - printf("%s:%c:%d:%d: Attempt to issue message failed\n", - ahc_name(ahc), devinfo.channel, devinfo.target, - devinfo.lun); - scbindex = ahc_inb(ahc, SCB_TAG); - scb = ahc_lookup_scb(ahc, scbindex); - if (scb != NULL - && (scb->flags & SCB_RECOVERY_SCB) != 0) - /* - * Ensure that we didn't put a second instance of this - * SCB into the QINFIFO. - */ - ahc_search_qinfifo(ahc, SCB_GET_TARGET(ahc, scb), - SCB_GET_CHANNEL(ahc, scb), - SCB_GET_LUN(scb), scb->hscb->tag, - ROLE_INITIATOR, /*status*/0, - SEARCH_REMOVE); - break; - } - case NO_FREE_SCB: - { - printf("%s: No free or disconnected SCBs\n", ahc_name(ahc)); - ahc_dump_card_state(ahc); - panic("for safety"); - break; - } - case SCB_MISMATCH: - { - u_int scbptr; - - scbptr = ahc_inb(ahc, SCBPTR); - printf("Bogus TAG after DMA. SCBPTR %d, tag %d, our tag %d\n", - scbptr, ahc_inb(ahc, ARG_1), - ahc->scb_data->hscbs[scbptr].tag); - ahc_dump_card_state(ahc); - panic("for saftey"); - break; - } - case OUT_OF_RANGE: - { - printf("%s: BTT calculation out of range\n", ahc_name(ahc)); - printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, " - "ARG_1 == 0x%x ACCUM = 0x%x\n", - ahc_inb(ahc, SAVED_SCSIID), ahc_inb(ahc, SAVED_LUN), - ahc_inb(ahc, ARG_1), ahc_inb(ahc, ACCUM)); - printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, " - "SINDEX == 0x%x\n, A == 0x%x\n", - ahc_inb(ahc, SEQ_FLAGS), ahc_inb(ahc, SCBPTR), - ahc_index_busy_tcl(ahc, - BUILD_TCL(ahc_inb(ahc, SAVED_SCSIID), - ahc_inb(ahc, SAVED_LUN))), - ahc_inb(ahc, SINDEX), - ahc_inb(ahc, ACCUM)); - printf("SCSIID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, " - "SCB_TAG == 0x%x, SCB_CONTROL == 0x%x\n", - ahc_inb(ahc, SCSIID), ahc_inb(ahc, SCB_SCSIID), - ahc_inb(ahc, SCB_LUN), ahc_inb(ahc, SCB_TAG), - ahc_inb(ahc, SCB_CONTROL)); - printf("SCSIBUSL == 0x%x, SCSISIGI == 0x%x\n", - ahc_inb(ahc, SCSIBUSL), ahc_inb(ahc, SCSISIGI)); - ahc_dump_card_state(ahc); - panic("for safety"); - break; - } - default: - printf("ahc_intr: seqint, " - "intstat == 0x%x, scsisigi = 0x%x\n", - intstat, ahc_inb(ahc, SCSISIGI)); - break; - } -unpause: - /* - * The sequencer is paused immediately on - * a SEQINT, so we should restart it when - * we're done. - */ - ahc_unpause(ahc); -} - -void -ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) -{ - u_int scb_index; - u_int status0; - u_int status; - struct scb *scb; - char cur_channel; - char intr_channel; - - /* Make sure the sequencer is in a safe location. */ - ahc_clear_critical_section(ahc); - - if ((ahc->features & AHC_TWIN) != 0 - && ((ahc_inb(ahc, SBLKCTL) & SELBUSB) != 0)) - cur_channel = 'B'; - else - cur_channel = 'A'; - intr_channel = cur_channel; - - if ((ahc->features & AHC_ULTRA2) != 0) - status0 = ahc_inb(ahc, SSTAT0) & IOERR; - else - status0 = 0; - status = ahc_inb(ahc, SSTAT1) & (SELTO|SCSIRSTI|BUSFREE|SCSIPERR); - if (status == 0 && status0 == 0) { - if ((ahc->features & AHC_TWIN) != 0) { - /* Try the other channel */ - ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) ^ SELBUSB); - status = ahc_inb(ahc, SSTAT1) - & (SELTO|SCSIRSTI|BUSFREE|SCSIPERR); - intr_channel = (cur_channel == 'A') ? 'B' : 'A'; - } - if (status == 0) { - printf("%s: Spurious SCSI interrupt\n", ahc_name(ahc)); - ahc_outb(ahc, CLRINT, CLRSCSIINT); - ahc_unpause(ahc); - return; - } - } - - scb_index = ahc_inb(ahc, SCB_TAG); - scb = ahc_lookup_scb(ahc, scb_index); - if (scb != NULL - && (ahc_inb(ahc, SEQ_FLAGS) & IDENTIFY_SEEN) == 0) - scb = NULL; - - if ((ahc->features & AHC_ULTRA2) != 0 - && (status0 & IOERR) != 0) { - int now_lvd; - - now_lvd = ahc_inb(ahc, SBLKCTL) & ENAB40; - printf("%s: Transceiver State Has Changed to %s mode\n", - ahc_name(ahc), now_lvd ? "LVD" : "SE"); - ahc_outb(ahc, CLRSINT0, CLRIOERR); - /* - * When transitioning to SE mode, the reset line - * glitches, triggering an arbitration bug in some - * Ultra2 controllers. This bug is cleared when we - * assert the reset line. Since a reset glitch has - * already occurred with this transition and a - * transceiver state change is handled just like - * a bus reset anyway, asserting the reset line - * ourselves is safe. - */ - ahc_reset_channel(ahc, intr_channel, - /*Initiate Reset*/now_lvd == 0); - } else if ((status & SCSIRSTI) != 0) { - printf("%s: Someone reset channel %c\n", - ahc_name(ahc), intr_channel); - if (intr_channel != cur_channel) - ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) ^ SELBUSB); - ahc_reset_channel(ahc, intr_channel, /*Initiate Reset*/FALSE); - } else if ((status & SCSIPERR) != 0) { - /* - * Determine the bus phase and queue an appropriate message. - * SCSIPERR is latched true as soon as a parity error - * occurs. If the sequencer acked the transfer that - * caused the parity error and the currently presented - * transfer on the bus has correct parity, SCSIPERR will - * be cleared by CLRSCSIPERR. Use this to determine if - * we should look at the last phase the sequencer recorded, - * or the current phase presented on the bus. - */ - u_int mesg_out; - u_int curphase; - u_int errorphase; - u_int lastphase; - u_int scsirate; - u_int i; - u_int sstat2; - - lastphase = ahc_inb(ahc, LASTPHASE); - curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; - sstat2 = ahc_inb(ahc, SSTAT2); - ahc_outb(ahc, CLRSINT1, CLRSCSIPERR); - /* - * For all phases save DATA, the sequencer won't - * automatically ack a byte that has a parity error - * in it. So the only way that the current phase - * could be 'data-in' is if the parity error is for - * an already acked byte in the data phase. During - * synchronous data-in transfers, we may actually - * ack bytes before latching the current phase in - * LASTPHASE, leading to the discrepancy between - * curphase and lastphase. - */ - if ((ahc_inb(ahc, SSTAT1) & SCSIPERR) != 0 - || curphase == P_DATAIN || curphase == P_DATAIN_DT) - errorphase = curphase; - else - errorphase = lastphase; - - for (i = 0; i < num_phases; i++) { - if (errorphase == ahc_phase_table[i].phase) - break; - } - mesg_out = ahc_phase_table[i].mesg_out; - if (scb != NULL) - ahc_print_path(ahc, scb); - else - printf("%s:%c:%d: ", ahc_name(ahc), intr_channel, - SCSIID_TARGET(ahc, ahc_inb(ahc, SAVED_SCSIID))); - scsirate = ahc_inb(ahc, SCSIRATE); - printf("parity error detected %s. " - "SEQADDR(0x%x) SCSIRATE(0x%x)\n", - ahc_phase_table[i].phasemsg, - ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8), - scsirate); - - if ((ahc->features & AHC_DT) != 0) { - - if ((sstat2 & CRCVALERR) != 0) - printf("\tCRC Value Mismatch\n"); - if ((sstat2 & CRCENDERR) != 0) - printf("\tNo terminal CRC packet recevied\n"); - if ((sstat2 & CRCREQERR) != 0) - printf("\tIllegal CRC packet request\n"); - if ((sstat2 & DUAL_EDGE_ERR) != 0) - printf("\tUnexpected %sDT Data Phase\n", - (scsirate & SINGLE_EDGE) ? "" : "non-"); - } - - /* - * We've set the hardware to assert ATN if we - * get a parity error on "in" phases, so all we - * need to do is stuff the message buffer with - * the appropriate message. "In" phases have set - * mesg_out to something other than MSG_NOP. - */ - if (mesg_out != MSG_NOOP) { - if (ahc->msg_type != MSG_TYPE_NONE) - ahc->send_msg_perror = TRUE; - else - ahc_outb(ahc, MSG_OUT, mesg_out); - } - /* - * Force a renegotiation with this target just in - * case we are out of sync for some external reason - * unknown (or unreported) by the target. - */ - ahc_force_renegotiation(ahc); - ahc_outb(ahc, CLRINT, CLRSCSIINT); - ahc_unpause(ahc); - } else if ((status & SELTO) != 0) { - u_int scbptr; - - /* Stop the selection */ - ahc_outb(ahc, SCSISEQ, 0); - - /* No more pending messages */ - ahc_clear_msg_state(ahc); - - /* Clear interrupt state */ - ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE); - ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR); - - /* - * Although the driver does not care about the - * 'Selection in Progress' status bit, the busy - * LED does. SELINGO is only cleared by a sucessfull - * selection, so we must manually clear it to insure - * the LED turns off just incase no future successful - * selections occur (e.g. no devices on the bus). - */ - ahc_outb(ahc, CLRSINT0, CLRSELINGO); - - scbptr = ahc_inb(ahc, WAITING_SCBH); - ahc_outb(ahc, SCBPTR, scbptr); - scb_index = ahc_inb(ahc, SCB_TAG); - - scb = ahc_lookup_scb(ahc, scb_index); - if (scb == NULL) { - printf("%s: ahc_intr - referenced scb not " - "valid during SELTO scb(%d, %d)\n", - ahc_name(ahc), scbptr, scb_index); - } else { - ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT); - ahc_freeze_devq(ahc, scb); - } - ahc_outb(ahc, CLRINT, CLRSCSIINT); - /* - * Force a renegotiation with this target just in - * case the cable was pulled and will later be - * re-attached. The target may forget its negotiation - * settings with us should it attempt to reselect - * during the interruption. The target will not issue - * a unit attention in this case, so we must always - * renegotiate. - */ - ahc_force_renegotiation(ahc); - ahc_restart(ahc); - } else if ((status & BUSFREE) != 0 - && (ahc_inb(ahc, SIMODE1) & ENBUSFREE) != 0) { - u_int lastphase; - u_int saved_scsiid; - u_int saved_lun; - u_int target; - u_int initiator_role_id; - char channel; - int printerror; - - /* - * Clear our selection hardware as soon as possible. - * We may have an entry in the waiting Q for this target, - * that is affected by this busfree and we don't want to - * go about selecting the target while we handle the event. - */ - ahc_outb(ahc, SCSISEQ, - ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP)); - - /* - * Disable busfree interrupts and clear the busfree - * interrupt status. We do this here so that several - * bus transactions occur prior to clearing the SCSIINT - * latch. It can take a bit for the clearing to take effect. - */ - ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE); - ahc_outb(ahc, CLRSINT1, CLRBUSFREE|CLRSCSIPERR); - - /* - * Look at what phase we were last in. - * If its message out, chances are pretty good - * that the busfree was in response to one of - * our abort requests. - */ - lastphase = ahc_inb(ahc, LASTPHASE); - saved_scsiid = ahc_inb(ahc, SAVED_SCSIID); - saved_lun = ahc_inb(ahc, SAVED_LUN); - target = SCSIID_TARGET(ahc, saved_scsiid); - initiator_role_id = SCSIID_OUR_ID(saved_scsiid); - channel = SCSIID_CHANNEL(ahc, saved_scsiid); - printerror = 1; - - if (lastphase == P_MESGOUT) { - struct ahc_devinfo devinfo; - u_int tag; - - ahc_fetch_devinfo(ahc, &devinfo); - tag = SCB_LIST_NULL; - if (ahc_sent_msg(ahc, AHCMSG_1B, MSG_ABORT_TAG, TRUE) - || ahc_sent_msg(ahc, AHCMSG_1B, MSG_ABORT, TRUE)) { - if (ahc->msgout_buf[ahc->msgout_index - 1] - == MSG_ABORT_TAG) - tag = scb->hscb->tag; - ahc_print_path(ahc, scb); - printf("SCB %d - Abort%s Completed.\n", - scb->hscb->tag, tag == SCB_LIST_NULL ? - "" : " Tag"); - ahc_abort_scbs(ahc, target, channel, - saved_lun, tag, - ROLE_INITIATOR, - CAM_REQ_ABORTED); - printerror = 0; - } else if (ahc_sent_msg(ahc, AHCMSG_1B, - MSG_BUS_DEV_RESET, TRUE)) { -#ifdef __FreeBSD__ - /* - * Don't mark the user's request for this BDR - * as completing with CAM_BDR_SENT. CAM3 - * specifies CAM_REQ_CMP. - */ - if (scb != NULL - && scb->io_ctx->ccb_h.func_code== XPT_RESET_DEV - && ahc_match_scb(ahc, scb, target, channel, - CAM_LUN_WILDCARD, - SCB_LIST_NULL, - ROLE_INITIATOR)) { - ahc_set_transaction_status(scb, CAM_REQ_CMP); - } -#endif - ahc_compile_devinfo(&devinfo, - initiator_role_id, - target, - CAM_LUN_WILDCARD, - channel, - ROLE_INITIATOR); - ahc_handle_devreset(ahc, &devinfo, - CAM_BDR_SENT, - "Bus Device Reset", - /*verbose_level*/0); - printerror = 0; - } else if (ahc_sent_msg(ahc, AHCMSG_EXT, - MSG_EXT_PPR, FALSE)) { - struct ahc_initiator_tinfo *tinfo; - struct ahc_tmode_tstate *tstate; - - /* - * PPR Rejected. Try non-ppr negotiation - * and retry command. - */ - tinfo = ahc_fetch_transinfo(ahc, - devinfo.channel, - devinfo.our_scsiid, - devinfo.target, - &tstate); - tinfo->curr.transport_version = 2; - tinfo->goal.transport_version = 2; - tinfo->goal.ppr_options = 0; - ahc_qinfifo_requeue_tail(ahc, scb); - printerror = 0; - } else if (ahc_sent_msg(ahc, AHCMSG_EXT, - MSG_EXT_WDTR, FALSE) - || ahc_sent_msg(ahc, AHCMSG_EXT, - MSG_EXT_SDTR, FALSE)) { - /* - * Negotiation Rejected. Go-async and - * retry command. - */ - ahc_set_width(ahc, &devinfo, - MSG_EXT_WDTR_BUS_8_BIT, - AHC_TRANS_CUR|AHC_TRANS_GOAL, - /*paused*/TRUE); - ahc_set_syncrate(ahc, &devinfo, - /*syncrate*/NULL, - /*period*/0, /*offset*/0, - /*ppr_options*/0, - AHC_TRANS_CUR|AHC_TRANS_GOAL, - /*paused*/TRUE); - ahc_qinfifo_requeue_tail(ahc, scb); - printerror = 0; - } - } - if (printerror != 0) { - u_int i; - - if (scb != NULL) { - u_int tag; - - if ((scb->hscb->control & TAG_ENB) != 0) - tag = scb->hscb->tag; - else - tag = SCB_LIST_NULL; - ahc_print_path(ahc, scb); - ahc_abort_scbs(ahc, target, channel, - SCB_GET_LUN(scb), tag, - ROLE_INITIATOR, - CAM_UNEXP_BUSFREE); - } else { - /* - * We had not fully identified this connection, - * so we cannot abort anything. - */ - printf("%s: ", ahc_name(ahc)); - } - for (i = 0; i < num_phases; i++) { - if (lastphase == ahc_phase_table[i].phase) - break; - } - /* - * Renegotiate with this device at the - * next oportunity just in case this busfree - * is due to a negotiation mismatch with the - * device. - */ - ahc_force_renegotiation(ahc); - printf("Unexpected busfree %s\n" - "SEQADDR == 0x%x\n", - ahc_phase_table[i].phasemsg, - ahc_inb(ahc, SEQADDR0) - | (ahc_inb(ahc, SEQADDR1) << 8)); - } - ahc_outb(ahc, CLRINT, CLRSCSIINT); - ahc_restart(ahc); - } else { - printf("%s: Missing case in ahc_handle_scsiint. status = %x\n", - ahc_name(ahc), status); - ahc_outb(ahc, CLRINT, CLRSCSIINT); - } -} - -/* - * Force renegotiation to occur the next time we initiate - * a command to the current device. - */ -static void -ahc_force_renegotiation(struct ahc_softc *ahc) -{ - struct ahc_devinfo devinfo; - struct ahc_initiator_tinfo *targ_info; - struct ahc_tmode_tstate *tstate; - - ahc_fetch_devinfo(ahc, &devinfo); - targ_info = ahc_fetch_transinfo(ahc, - devinfo.channel, - devinfo.our_scsiid, - devinfo.target, - &tstate); - ahc_update_neg_request(ahc, &devinfo, tstate, - targ_info, /*force*/TRUE); -} - -#define AHC_MAX_STEPS 2000 -void -ahc_clear_critical_section(struct ahc_softc *ahc) -{ - int stepping; - int steps; - u_int simode0; - u_int simode1; - - if (ahc->num_critical_sections == 0) - return; - - stepping = FALSE; - steps = 0; - simode0 = 0; - simode1 = 0; - for (;;) { - struct cs *cs; - u_int seqaddr; - u_int i; - - seqaddr = ahc_inb(ahc, SEQADDR0) - | (ahc_inb(ahc, SEQADDR1) << 8); - - /* - * Seqaddr represents the next instruction to execute, - * so we are really executing the instruction just - * before it. - */ - if (seqaddr != 0) - seqaddr -= 1; - cs = ahc->critical_sections; - for (i = 0; i < ahc->num_critical_sections; i++, cs++) { - - if (cs->begin < seqaddr && cs->end >= seqaddr) - break; - } - - if (i == ahc->num_critical_sections) - break; - - if (steps > AHC_MAX_STEPS) { - printf("%s: Infinite loop in critical section\n", - ahc_name(ahc)); - ahc_dump_card_state(ahc); - panic("critical section loop"); - } - - steps++; - if (stepping == FALSE) { - - /* - * Disable all interrupt sources so that the - * sequencer will not be stuck by a pausing - * interrupt condition while we attempt to - * leave a critical section. - */ - simode0 = ahc_inb(ahc, SIMODE0); - ahc_outb(ahc, SIMODE0, 0); - simode1 = ahc_inb(ahc, SIMODE1); - ahc_outb(ahc, SIMODE1, 0); - ahc_outb(ahc, CLRINT, CLRSCSIINT); - ahc_outb(ahc, SEQCTL, ahc_inb(ahc, SEQCTL) | STEP); - stepping = TRUE; - } - ahc_outb(ahc, HCNTRL, ahc->unpause); - while (!ahc_is_paused(ahc)) - ahc_delay(200); - } - if (stepping) { - ahc_outb(ahc, SIMODE0, simode0); - ahc_outb(ahc, SIMODE1, simode1); - ahc_outb(ahc, SEQCTL, ahc_inb(ahc, SEQCTL) & ~STEP); - } -} - -/* - * Clear any pending interrupt status. - */ -void -ahc_clear_intstat(struct ahc_softc *ahc) -{ - /* Clear any interrupt conditions this may have caused */ - ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRATNO|CLRSCSIRSTI - |CLRBUSFREE|CLRSCSIPERR|CLRPHASECHG| - CLRREQINIT); - ahc_flush_device_writes(ahc); - ahc_outb(ahc, CLRSINT0, CLRSELDO|CLRSELDI|CLRSELINGO); - ahc_flush_device_writes(ahc); - ahc_outb(ahc, CLRINT, CLRSCSIINT); - ahc_flush_device_writes(ahc); -} - -/**************************** Debugging Routines ******************************/ -#ifdef AHC_DEBUG -int ahc_debug = AHC_DEBUG; -#endif - -void -ahc_print_scb(struct scb *scb) -{ - int i; - - struct hardware_scb *hscb = scb->hscb; - - printf("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n", - (void *)scb, - hscb->control, - hscb->scsiid, - hscb->lun, - hscb->cdb_len); - printf("Shared Data: "); - for (i = 0; i < sizeof(hscb->shared_data.cdb); i++) - printf("%#02x", hscb->shared_data.cdb[i]); - printf(" dataptr:%#x datacnt:%#x sgptr:%#x tag:%#x\n", - ahc_le32toh(hscb->dataptr), - ahc_le32toh(hscb->datacnt), - ahc_le32toh(hscb->sgptr), - hscb->tag); - if (scb->sg_count > 0) { - for (i = 0; i < scb->sg_count; i++) { - printf("sg[%d] - Addr 0x%x%x : Length %d\n", - i, - (ahc_le32toh(scb->sg_list[i].len) >> 24 - & SG_HIGH_ADDR_BITS), - ahc_le32toh(scb->sg_list[i].addr), - ahc_le32toh(scb->sg_list[i].len)); - } - } -} - -/************************* Transfer Negotiation *******************************/ -/* - * Allocate per target mode instance (ID we respond to as a target) - * transfer negotiation data structures. - */ -static struct ahc_tmode_tstate * -ahc_alloc_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel) -{ - struct ahc_tmode_tstate *master_tstate; - struct ahc_tmode_tstate *tstate; - int i; - - master_tstate = ahc->enabled_targets[ahc->our_id]; - if (channel == 'B') { - scsi_id += 8; - master_tstate = ahc->enabled_targets[ahc->our_id_b + 8]; - } - if (ahc->enabled_targets[scsi_id] != NULL - && ahc->enabled_targets[scsi_id] != master_tstate) - panic("%s: ahc_alloc_tstate - Target already allocated", - ahc_name(ahc)); - tstate = malloc(sizeof(*tstate), M_DEVBUF, M_NOWAIT); - if (tstate == NULL) - return (NULL); - - /* - * If we have allocated a master tstate, copy user settings from - * the master tstate (taken from SRAM or the EEPROM) for this - * channel, but reset our current and goal settings to async/narrow - * until an initiator talks to us. - */ - if (master_tstate != NULL) { - memcpy(tstate, master_tstate, sizeof(*tstate)); - memset(tstate->enabled_luns, 0, sizeof(tstate->enabled_luns)); - tstate->ultraenb = 0; - for (i = 0; i < AHC_NUM_TARGETS; i++) { - memset(&tstate->transinfo[i].curr, 0, - sizeof(tstate->transinfo[i].curr)); - memset(&tstate->transinfo[i].goal, 0, - sizeof(tstate->transinfo[i].goal)); - } - } else - memset(tstate, 0, sizeof(*tstate)); - ahc->enabled_targets[scsi_id] = tstate; - return (tstate); -} - -#ifdef AHC_TARGET_MODE -/* - * Free per target mode instance (ID we respond to as a target) - * transfer negotiation data structures. - */ -static void -ahc_free_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel, int force) -{ - struct ahc_tmode_tstate *tstate; - - /* - * Don't clean up our "master" tstate. - * It has our default user settings. - */ - if (((channel == 'B' && scsi_id == ahc->our_id_b) - || (channel == 'A' && scsi_id == ahc->our_id)) - && force == FALSE) - return; - - if (channel == 'B') - scsi_id += 8; - tstate = ahc->enabled_targets[scsi_id]; - if (tstate != NULL) - free(tstate, M_DEVBUF); - ahc->enabled_targets[scsi_id] = NULL; -} -#endif - -/* - * Called when we have an active connection to a target on the bus, - * this function finds the nearest syncrate to the input period limited - * by the capabilities of the bus connectivity of and sync settings for - * the target. - */ -struct ahc_syncrate * -ahc_devlimited_syncrate(struct ahc_softc *ahc, - struct ahc_initiator_tinfo *tinfo, - u_int *period, u_int *ppr_options, role_t role) -{ - struct ahc_transinfo *transinfo; - u_int maxsync; - - if ((ahc->features & AHC_ULTRA2) != 0) { - if ((ahc_inb(ahc, SBLKCTL) & ENAB40) != 0 - && (ahc_inb(ahc, SSTAT2) & EXP_ACTIVE) == 0) { - maxsync = AHC_SYNCRATE_DT; - } else { - maxsync = AHC_SYNCRATE_ULTRA; - /* Can't do DT on an SE bus */ - *ppr_options &= ~MSG_EXT_PPR_DT_REQ; - } - } else if ((ahc->features & AHC_ULTRA) != 0) { - maxsync = AHC_SYNCRATE_ULTRA; - } else { - maxsync = AHC_SYNCRATE_FAST; - } - /* - * Never allow a value higher than our current goal - * period otherwise we may allow a target initiated - * negotiation to go above the limit as set by the - * user. In the case of an initiator initiated - * sync negotiation, we limit based on the user - * setting. This allows the system to still accept - * incoming negotiations even if target initiated - * negotiation is not performed. - */ - if (role == ROLE_TARGET) - transinfo = &tinfo->user; - else - transinfo = &tinfo->goal; - *ppr_options &= transinfo->ppr_options; - if (transinfo->period == 0) { - *period = 0; - *ppr_options = 0; - return (NULL); - } - *period = MAX(*period, transinfo->period); - return (ahc_find_syncrate(ahc, period, ppr_options, maxsync)); -} - -/* - * Look up the valid period to SCSIRATE conversion in our table. - * Return the period and offset that should be sent to the target - * if this was the beginning of an SDTR. - */ -struct ahc_syncrate * -ahc_find_syncrate(struct ahc_softc *ahc, u_int *period, - u_int *ppr_options, u_int maxsync) -{ - struct ahc_syncrate *syncrate; - - if ((ahc->features & AHC_DT) == 0) - *ppr_options &= ~MSG_EXT_PPR_DT_REQ; - - /* Skip all DT only entries if DT is not available */ - if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0 - && maxsync < AHC_SYNCRATE_ULTRA2) - maxsync = AHC_SYNCRATE_ULTRA2; - - for (syncrate = &ahc_syncrates[maxsync]; - syncrate->rate != NULL; - syncrate++) { - - /* - * The Ultra2 table doesn't go as low - * as for the Fast/Ultra cards. - */ - if ((ahc->features & AHC_ULTRA2) != 0 - && (syncrate->sxfr_u2 == 0)) - break; - - if (*period <= syncrate->period) { - /* - * When responding to a target that requests - * sync, the requested rate may fall between - * two rates that we can output, but still be - * a rate that we can receive. Because of this, - * we want to respond to the target with - * the same rate that it sent to us even - * if the period we use to send data to it - * is lower. Only lower the response period - * if we must. - */ - if (syncrate == &ahc_syncrates[maxsync]) - *period = syncrate->period; - - /* - * At some speeds, we only support - * ST transfers. - */ - if ((syncrate->sxfr_u2 & ST_SXFR) != 0) - *ppr_options &= ~MSG_EXT_PPR_DT_REQ; - break; - } - } - - if ((*period == 0) - || (syncrate->rate == NULL) - || ((ahc->features & AHC_ULTRA2) != 0 - && (syncrate->sxfr_u2 == 0))) { - /* Use asynchronous transfers. */ - *period = 0; - syncrate = NULL; - *ppr_options &= ~MSG_EXT_PPR_DT_REQ; - } - return (syncrate); -} - -/* - * Convert from an entry in our syncrate table to the SCSI equivalent - * sync "period" factor. - */ -u_int -ahc_find_period(struct ahc_softc *ahc, u_int scsirate, u_int maxsync) -{ - struct ahc_syncrate *syncrate; - - if ((ahc->features & AHC_ULTRA2) != 0) - scsirate &= SXFR_ULTRA2; - else - scsirate &= SXFR; - - syncrate = &ahc_syncrates[maxsync]; - while (syncrate->rate != NULL) { - - if ((ahc->features & AHC_ULTRA2) != 0) { - if (syncrate->sxfr_u2 == 0) - break; - else if (scsirate == (syncrate->sxfr_u2 & SXFR_ULTRA2)) - return (syncrate->period); - } else if (scsirate == (syncrate->sxfr & SXFR)) { - return (syncrate->period); - } - syncrate++; - } - return (0); /* async */ -} - -/* - * Truncate the given synchronous offset to a value the - * current adapter type and syncrate are capable of. - */ -void -ahc_validate_offset(struct ahc_softc *ahc, - struct ahc_initiator_tinfo *tinfo, - struct ahc_syncrate *syncrate, - u_int *offset, int wide, role_t role) -{ - u_int maxoffset; - - /* Limit offset to what we can do */ - if (syncrate == NULL) { - maxoffset = 0; - } else if ((ahc->features & AHC_ULTRA2) != 0) { - maxoffset = MAX_OFFSET_ULTRA2; - } else { - if (wide) - maxoffset = MAX_OFFSET_16BIT; - else - maxoffset = MAX_OFFSET_8BIT; - } - *offset = MIN(*offset, maxoffset); - if (tinfo != NULL) { - if (role == ROLE_TARGET) - *offset = MIN(*offset, tinfo->user.offset); - else - *offset = MIN(*offset, tinfo->goal.offset); - } -} - -/* - * Truncate the given transfer width parameter to a value the - * current adapter type is capable of. - */ -void -ahc_validate_width(struct ahc_softc *ahc, struct ahc_initiator_tinfo *tinfo, - u_int *bus_width, role_t role) -{ - switch (*bus_width) { - default: - if (ahc->features & AHC_WIDE) { - /* Respond Wide */ - *bus_width = MSG_EXT_WDTR_BUS_16_BIT; - break; - } - /* FALLTHROUGH */ - case MSG_EXT_WDTR_BUS_8_BIT: - *bus_width = MSG_EXT_WDTR_BUS_8_BIT; - break; - } - if (tinfo != NULL) { - if (role == ROLE_TARGET) - *bus_width = MIN(tinfo->user.width, *bus_width); - else - *bus_width = MIN(tinfo->goal.width, *bus_width); - } -} - -/* - * Update the bitmask of targets for which the controller should - * negotiate with at the next convenient oportunity. This currently - * means the next time we send the initial identify messages for - * a new transaction. - */ -int -ahc_update_neg_request(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, - struct ahc_tmode_tstate *tstate, - struct ahc_initiator_tinfo *tinfo, int force) -{ - u_int auto_negotiate_orig; - - auto_negotiate_orig = tstate->auto_negotiate; - if (tinfo->curr.period != tinfo->goal.period - || tinfo->curr.width != tinfo->goal.width - || tinfo->curr.offset != tinfo->goal.offset - || tinfo->curr.ppr_options != tinfo->goal.ppr_options - || (force - && (tinfo->goal.period != 0 - || tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT - || tinfo->goal.ppr_options != 0))) - tstate->auto_negotiate |= devinfo->target_mask; - else - tstate->auto_negotiate &= ~devinfo->target_mask; - - return (auto_negotiate_orig != tstate->auto_negotiate); -} - -/* - * Update the user/goal/curr tables of synchronous negotiation - * parameters as well as, in the case of a current or active update, - * any data structures on the host controller. In the case of an - * active update, the specified target is currently talking to us on - * the bus, so the transfer parameter update must take effect - * immediately. - */ -void -ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, - struct ahc_syncrate *syncrate, u_int period, - u_int offset, u_int ppr_options, u_int type, int paused) -{ - struct ahc_initiator_tinfo *tinfo; - struct ahc_tmode_tstate *tstate; - u_int old_period; - u_int old_offset; - u_int old_ppr; - int active; - int update_needed; - - active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE; - update_needed = 0; - - if (syncrate == NULL) { - period = 0; - offset = 0; - } - - tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, - devinfo->target, &tstate); - - if ((type & AHC_TRANS_USER) != 0) { - tinfo->user.period = period; - tinfo->user.offset = offset; - tinfo->user.ppr_options = ppr_options; - } - - if ((type & AHC_TRANS_GOAL) != 0) { - tinfo->goal.period = period; - tinfo->goal.offset = offset; - tinfo->goal.ppr_options = ppr_options; - } - - old_period = tinfo->curr.period; - old_offset = tinfo->curr.offset; - old_ppr = tinfo->curr.ppr_options; - - if ((type & AHC_TRANS_CUR) != 0 - && (old_period != period - || old_offset != offset - || old_ppr != ppr_options)) { - u_int scsirate; - - update_needed++; - scsirate = tinfo->scsirate; - if ((ahc->features & AHC_ULTRA2) != 0) { - - scsirate &= ~(SXFR_ULTRA2|SINGLE_EDGE|ENABLE_CRC); - if (syncrate != NULL) { - scsirate |= syncrate->sxfr_u2; - if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) - scsirate |= ENABLE_CRC; - else - scsirate |= SINGLE_EDGE; - } - } else { - - scsirate &= ~(SXFR|SOFS); - /* - * Ensure Ultra mode is set properly for - * this target. - */ - tstate->ultraenb &= ~devinfo->target_mask; - if (syncrate != NULL) { - if (syncrate->sxfr & ULTRA_SXFR) { - tstate->ultraenb |= - devinfo->target_mask; - } - scsirate |= syncrate->sxfr & SXFR; - scsirate |= offset & SOFS; - } - if (active) { - u_int sxfrctl0; - - sxfrctl0 = ahc_inb(ahc, SXFRCTL0); - sxfrctl0 &= ~FAST20; - if (tstate->ultraenb & devinfo->target_mask) - sxfrctl0 |= FAST20; - ahc_outb(ahc, SXFRCTL0, sxfrctl0); - } - } - if (active) { - ahc_outb(ahc, SCSIRATE, scsirate); - if ((ahc->features & AHC_ULTRA2) != 0) - ahc_outb(ahc, SCSIOFFSET, offset); - } - - tinfo->scsirate = scsirate; - tinfo->curr.period = period; - tinfo->curr.offset = offset; - tinfo->curr.ppr_options = ppr_options; - - ahc_send_async(ahc, devinfo->channel, devinfo->target, - CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL); - if (bootverbose) { - if (offset != 0) { - printf("%s: target %d synchronous at %sMHz%s, " - "offset = 0x%x\n", ahc_name(ahc), - devinfo->target, syncrate->rate, - (ppr_options & MSG_EXT_PPR_DT_REQ) - ? " DT" : "", offset); - } else { - printf("%s: target %d using " - "asynchronous transfers\n", - ahc_name(ahc), devinfo->target); - } - } - } - - update_needed += ahc_update_neg_request(ahc, devinfo, tstate, - tinfo, /*force*/FALSE); - - if (update_needed) - ahc_update_pending_scbs(ahc); -} - -/* - * Update the user/goal/curr tables of wide negotiation - * parameters as well as, in the case of a current or active update, - * any data structures on the host controller. In the case of an - * active update, the specified target is currently talking to us on - * the bus, so the transfer parameter update must take effect - * immediately. - */ -void -ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, - u_int width, u_int type, int paused) -{ - struct ahc_initiator_tinfo *tinfo; - struct ahc_tmode_tstate *tstate; - u_int oldwidth; - int active; - int update_needed; - - active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE; - update_needed = 0; - tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, - devinfo->target, &tstate); - - if ((type & AHC_TRANS_USER) != 0) - tinfo->user.width = width; - - if ((type & AHC_TRANS_GOAL) != 0) - tinfo->goal.width = width; - - oldwidth = tinfo->curr.width; - if ((type & AHC_TRANS_CUR) != 0 && oldwidth != width) { - u_int scsirate; - - update_needed++; - scsirate = tinfo->scsirate; - scsirate &= ~WIDEXFER; - if (width == MSG_EXT_WDTR_BUS_16_BIT) - scsirate |= WIDEXFER; - - tinfo->scsirate = scsirate; - - if (active) - ahc_outb(ahc, SCSIRATE, scsirate); - - tinfo->curr.width = width; - - ahc_send_async(ahc, devinfo->channel, devinfo->target, - CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL); - if (bootverbose) { - printf("%s: target %d using %dbit transfers\n", - ahc_name(ahc), devinfo->target, - 8 * (0x01 << width)); - } - } - - update_needed += ahc_update_neg_request(ahc, devinfo, tstate, - tinfo, /*force*/FALSE); - if (update_needed) - ahc_update_pending_scbs(ahc); -} - -/* - * Update the current state of tagged queuing for a given target. - */ -void -ahc_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, - ahc_queue_alg alg) -{ - ahc_platform_set_tags(ahc, devinfo, alg); - ahc_send_async(ahc, devinfo->channel, devinfo->target, - devinfo->lun, AC_TRANSFER_NEG, &alg); -} - -/* - * When the transfer settings for a connection change, update any - * in-transit SCBs to contain the new data so the hardware will - * be set correctly during future (re)selections. - */ -static void -ahc_update_pending_scbs(struct ahc_softc *ahc) -{ - struct scb *pending_scb; - int pending_scb_count; - int i; - int paused; - u_int saved_scbptr; - - /* - * Traverse the pending SCB list and ensure that all of the - * SCBs there have the proper settings. - */ - pending_scb_count = 0; - LIST_FOREACH(pending_scb, &ahc->pending_scbs, pending_links) { - struct ahc_devinfo devinfo; - struct hardware_scb *pending_hscb; - struct ahc_initiator_tinfo *tinfo; - struct ahc_tmode_tstate *tstate; - - ahc_scb_devinfo(ahc, &devinfo, pending_scb); - tinfo = ahc_fetch_transinfo(ahc, devinfo.channel, - devinfo.our_scsiid, - devinfo.target, &tstate); - pending_hscb = pending_scb->hscb; - pending_hscb->control &= ~ULTRAENB; - if ((tstate->ultraenb & devinfo.target_mask) != 0) - pending_hscb->control |= ULTRAENB; - pending_hscb->scsirate = tinfo->scsirate; - pending_hscb->scsioffset = tinfo->curr.offset; - if ((tstate->auto_negotiate & devinfo.target_mask) == 0 - && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) { - pending_scb->flags &= ~SCB_AUTO_NEGOTIATE; - pending_hscb->control &= ~MK_MESSAGE; - } - ahc_sync_scb(ahc, pending_scb, - BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); - pending_scb_count++; - } - - if (pending_scb_count == 0) - return; - - if (ahc_is_paused(ahc)) { - paused = 1; - } else { - paused = 0; - ahc_pause(ahc); - } - - saved_scbptr = ahc_inb(ahc, SCBPTR); - /* Ensure that the hscbs down on the card match the new information */ - for (i = 0; i < ahc->scb_data->maxhscbs; i++) { - struct hardware_scb *pending_hscb; - u_int control; - u_int scb_tag; - - ahc_outb(ahc, SCBPTR, i); - scb_tag = ahc_inb(ahc, SCB_TAG); - pending_scb = ahc_lookup_scb(ahc, scb_tag); - if (pending_scb == NULL) - continue; - - pending_hscb = pending_scb->hscb; - control = ahc_inb(ahc, SCB_CONTROL); - control &= ~(ULTRAENB|MK_MESSAGE); - control |= pending_hscb->control & (ULTRAENB|MK_MESSAGE); - ahc_outb(ahc, SCB_CONTROL, control); - ahc_outb(ahc, SCB_SCSIRATE, pending_hscb->scsirate); - ahc_outb(ahc, SCB_SCSIOFFSET, pending_hscb->scsioffset); - } - ahc_outb(ahc, SCBPTR, saved_scbptr); - - if (paused == 0) - ahc_unpause(ahc); -} - -/**************************** Pathing Information *****************************/ -static void -ahc_fetch_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) -{ - u_int saved_scsiid; - role_t role; - int our_id; - - if (ahc_inb(ahc, SSTAT0) & TARGET) - role = ROLE_TARGET; - else - role = ROLE_INITIATOR; - - if (role == ROLE_TARGET - && (ahc->features & AHC_MULTI_TID) != 0 - && (ahc_inb(ahc, SEQ_FLAGS) & CMDPHASE_PENDING) != 0) { - /* We were selected, so pull our id from TARGIDIN */ - our_id = ahc_inb(ahc, TARGIDIN) & OID; - } else if ((ahc->features & AHC_ULTRA2) != 0) - our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID; - else - our_id = ahc_inb(ahc, SCSIID) & OID; - - saved_scsiid = ahc_inb(ahc, SAVED_SCSIID); - ahc_compile_devinfo(devinfo, - our_id, - SCSIID_TARGET(ahc, saved_scsiid), - ahc_inb(ahc, SAVED_LUN), - SCSIID_CHANNEL(ahc, saved_scsiid), - role); -} - -struct ahc_phase_table_entry* -ahc_lookup_phase_entry(int phase) -{ - struct ahc_phase_table_entry *entry; - struct ahc_phase_table_entry *last_entry; - - /* - * num_phases doesn't include the default entry which - * will be returned if the phase doesn't match. - */ - last_entry = &ahc_phase_table[num_phases]; - for (entry = ahc_phase_table; entry < last_entry; entry++) { - if (phase == entry->phase) - break; - } - return (entry); -} - -void -ahc_compile_devinfo(struct ahc_devinfo *devinfo, u_int our_id, u_int target, - u_int lun, char channel, role_t role) -{ - devinfo->our_scsiid = our_id; - devinfo->target = target; - devinfo->lun = lun; - devinfo->target_offset = target; - devinfo->channel = channel; - devinfo->role = role; - if (channel == 'B') - devinfo->target_offset += 8; - devinfo->target_mask = (0x01 << devinfo->target_offset); -} - -static void -ahc_scb_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, - struct scb *scb) -{ - role_t role; - int our_id; - - our_id = SCSIID_OUR_ID(scb->hscb->scsiid); - role = ROLE_INITIATOR; - if ((scb->hscb->control & TARGET_SCB) != 0) - role = ROLE_TARGET; - ahc_compile_devinfo(devinfo, our_id, SCB_GET_TARGET(ahc, scb), - SCB_GET_LUN(scb), SCB_GET_CHANNEL(ahc, scb), role); -} - - -/************************ Message Phase Processing ****************************/ -static void -ahc_assert_atn(struct ahc_softc *ahc) -{ - u_int scsisigo; - - scsisigo = ATNO; - if ((ahc->features & AHC_DT) == 0) - scsisigo |= ahc_inb(ahc, SCSISIGI); - ahc_outb(ahc, SCSISIGO, scsisigo); -} - -/* - * When an initiator transaction with the MK_MESSAGE flag either reconnects - * or enters the initial message out phase, we are interrupted. Fill our - * outgoing message buffer with the appropriate message and beging handing - * the message phase(s) manually. - */ -static void -ahc_setup_initiator_msgout(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, - struct scb *scb) -{ - /* - * To facilitate adding multiple messages together, - * each routine should increment the index and len - * variables instead of setting them explicitly. - */ - ahc->msgout_index = 0; - ahc->msgout_len = 0; - - if ((scb->flags & SCB_DEVICE_RESET) == 0 - && ahc_inb(ahc, MSG_OUT) == MSG_IDENTIFYFLAG) { - u_int identify_msg; - - identify_msg = MSG_IDENTIFYFLAG | SCB_GET_LUN(scb); - if ((scb->hscb->control & DISCENB) != 0) - identify_msg |= MSG_IDENTIFY_DISCFLAG; - ahc->msgout_buf[ahc->msgout_index++] = identify_msg; - ahc->msgout_len++; - - if ((scb->hscb->control & TAG_ENB) != 0) { - ahc->msgout_buf[ahc->msgout_index++] = - scb->hscb->control & (TAG_ENB|SCB_TAG_TYPE); - ahc->msgout_buf[ahc->msgout_index++] = scb->hscb->tag; - ahc->msgout_len += 2; - } - } - - if (scb->flags & SCB_DEVICE_RESET) { - ahc->msgout_buf[ahc->msgout_index++] = MSG_BUS_DEV_RESET; - ahc->msgout_len++; - ahc_print_path(ahc, scb); - printf("Bus Device Reset Message Sent\n"); - /* - * Clear our selection hardware in advance of - * the busfree. We may have an entry in the waiting - * Q for this target, and we don't want to go about - * selecting while we handle the busfree and blow it - * away. - */ - ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO)); - } else if ((scb->flags & SCB_ABORT) != 0) { - if ((scb->hscb->control & TAG_ENB) != 0) - ahc->msgout_buf[ahc->msgout_index++] = MSG_ABORT_TAG; - else - ahc->msgout_buf[ahc->msgout_index++] = MSG_ABORT; - ahc->msgout_len++; - ahc_print_path(ahc, scb); - printf("Abort%s Message Sent\n", - (scb->hscb->control & TAG_ENB) != 0 ? " Tag" : ""); - /* - * Clear our selection hardware in advance of - * the busfree. We may have an entry in the waiting - * Q for this target, and we don't want to go about - * selecting while we handle the busfree and blow it - * away. - */ - ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO)); - } else if ((scb->flags & (SCB_AUTO_NEGOTIATE|SCB_NEGOTIATE)) != 0) { - ahc_build_transfer_msg(ahc, devinfo); - } else { - printf("ahc_intr: AWAITING_MSG for an SCB that " - "does not have a waiting message\n"); - printf("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid, - devinfo->target_mask); - panic("SCB = %d, SCB Control = %x, MSG_OUT = %x " - "SCB flags = %x", scb->hscb->tag, scb->hscb->control, - ahc_inb(ahc, MSG_OUT), scb->flags); - } - - /* - * Clear the MK_MESSAGE flag from the SCB so we aren't - * asked to send this message again. - */ - ahc_outb(ahc, SCB_CONTROL, ahc_inb(ahc, SCB_CONTROL) & ~MK_MESSAGE); - scb->hscb->control &= ~MK_MESSAGE; - ahc->msgout_index = 0; - ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT; -} - -/* - * Build an appropriate transfer negotiation message for the - * currently active target. - */ -static void -ahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) -{ - /* - * We need to initiate transfer negotiations. - * If our current and goal settings are identical, - * we want to renegotiate due to a check condition. - */ - struct ahc_initiator_tinfo *tinfo; - struct ahc_tmode_tstate *tstate; - struct ahc_syncrate *rate; - int dowide; - int dosync; - int doppr; - int use_ppr; - u_int period; - u_int ppr_options; - u_int offset; - - tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, - devinfo->target, &tstate); - /* - * Filter our period based on the current connection. - * If we can't perform DT transfers on this segment (not in LVD - * mode for instance), then our decision to issue a PPR message - * may change. - */ - period = tinfo->goal.period; - ppr_options = tinfo->goal.ppr_options; - /* Target initiated PPR is not allowed in the SCSI spec */ - if (devinfo->role == ROLE_TARGET) - ppr_options = 0; - rate = ahc_devlimited_syncrate(ahc, tinfo, &period, - &ppr_options, devinfo->role); - dowide = tinfo->curr.width != tinfo->goal.width; - dosync = tinfo->curr.period != period; - doppr = tinfo->curr.ppr_options != ppr_options; - - if (!dowide && !dosync && !doppr) { - dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT; - dosync = tinfo->goal.period != 0; - doppr = tinfo->goal.ppr_options != 0; - } - - if (!dowide && !dosync && !doppr) { - panic("ahc_intr: AWAITING_MSG for negotiation, " - "but no negotiation needed\n"); - } - - use_ppr = (tinfo->curr.transport_version >= 3) || doppr; - /* Target initiated PPR is not allowed in the SCSI spec */ - if (devinfo->role == ROLE_TARGET) - use_ppr = 0; - - /* - * Both the PPR message and SDTR message require the - * goal syncrate to be limited to what the target device - * is capable of handling (based on whether an LVD->SE - * expander is on the bus), so combine these two cases. - * Regardless, guarantee that if we are using WDTR and SDTR - * messages that WDTR comes first. - */ - if (use_ppr || (dosync && !dowide)) { - - offset = tinfo->goal.offset; - ahc_validate_offset(ahc, tinfo, rate, &offset, - use_ppr ? tinfo->goal.width - : tinfo->curr.width, - devinfo->role); - if (use_ppr) { - ahc_construct_ppr(ahc, devinfo, period, offset, - tinfo->goal.width, ppr_options); - } else { - ahc_construct_sdtr(ahc, devinfo, period, offset); - } - } else { - ahc_construct_wdtr(ahc, devinfo, tinfo->goal.width); - } -} - -/* - * Build a synchronous negotiation message in our message - * buffer based on the input parameters. - */ -static void -ahc_construct_sdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, - u_int period, u_int offset) -{ - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_SDTR_LEN; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_SDTR; - ahc->msgout_buf[ahc->msgout_index++] = period; - ahc->msgout_buf[ahc->msgout_index++] = offset; - ahc->msgout_len += 5; - if (bootverbose) { - printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n", - ahc_name(ahc), devinfo->channel, devinfo->target, - devinfo->lun, period, offset); - } -} - -/* - * Build a wide negotiation message in our message - * buffer based on the input parameters. - */ -static void -ahc_construct_wdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, - u_int bus_width) -{ - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR_LEN; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR; - ahc->msgout_buf[ahc->msgout_index++] = bus_width; - ahc->msgout_len += 4; - if (bootverbose) { - printf("(%s:%c:%d:%d): Sending WDTR %x\n", - ahc_name(ahc), devinfo->channel, devinfo->target, - devinfo->lun, bus_width); - } -} - -/* - * Build a parallel protocol request message in our message - * buffer based on the input parameters. - */ -static void -ahc_construct_ppr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, - u_int period, u_int offset, u_int bus_width, - u_int ppr_options) -{ - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_PPR_LEN; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_PPR; - ahc->msgout_buf[ahc->msgout_index++] = period; - ahc->msgout_buf[ahc->msgout_index++] = 0; - ahc->msgout_buf[ahc->msgout_index++] = offset; - ahc->msgout_buf[ahc->msgout_index++] = bus_width; - ahc->msgout_buf[ahc->msgout_index++] = ppr_options; - ahc->msgout_len += 8; - if (bootverbose) { - printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, " - "offset %x, ppr_options %x\n", ahc_name(ahc), - devinfo->channel, devinfo->target, devinfo->lun, - bus_width, period, offset, ppr_options); - } -} - -/* - * Clear any active message state. - */ -static void -ahc_clear_msg_state(struct ahc_softc *ahc) -{ - ahc->msgout_len = 0; - ahc->msgin_index = 0; - ahc->msg_type = MSG_TYPE_NONE; - if ((ahc_inb(ahc, SCSISIGI) & ATNI) != 0) { - /* - * The target didn't care to respond to our - * message request, so clear ATN. - */ - ahc_outb(ahc, CLRSINT1, CLRATNO); - } - ahc_outb(ahc, MSG_OUT, MSG_NOOP); - ahc_outb(ahc, SEQ_FLAGS2, - ahc_inb(ahc, SEQ_FLAGS2) & ~TARGET_MSG_PENDING); -} - -/* - * Manual message loop handler. - */ -static void -ahc_handle_message_phase(struct ahc_softc *ahc) -{ - struct ahc_devinfo devinfo; - u_int bus_phase; - int end_session; - - ahc_fetch_devinfo(ahc, &devinfo); - end_session = FALSE; - bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; - -reswitch: - switch (ahc->msg_type) { - case MSG_TYPE_INITIATOR_MSGOUT: - { - int lastbyte; - int phasemis; - int msgdone; - - if (ahc->msgout_len == 0) - panic("HOST_MSG_LOOP interrupt with no active message"); - - phasemis = bus_phase != P_MESGOUT; - if (phasemis) { - if (bus_phase == P_MESGIN) { - /* - * Change gears and see if - * this messages is of interest to - * us or should be passed back to - * the sequencer. - */ - ahc_outb(ahc, CLRSINT1, CLRATNO); - ahc->send_msg_perror = FALSE; - ahc->msg_type = MSG_TYPE_INITIATOR_MSGIN; - ahc->msgin_index = 0; - goto reswitch; - } - end_session = TRUE; - break; - } - - if (ahc->send_msg_perror) { - ahc_outb(ahc, CLRSINT1, CLRATNO); - ahc_outb(ahc, CLRSINT1, CLRREQINIT); - ahc_outb(ahc, SCSIDATL, MSG_PARITY_ERROR); - break; - } - - msgdone = ahc->msgout_index == ahc->msgout_len; - if (msgdone) { - /* - * The target has requested a retry. - * Re-assert ATN, reset our message index to - * 0, and try again. - */ - ahc->msgout_index = 0; - ahc_assert_atn(ahc); - } - - lastbyte = ahc->msgout_index == (ahc->msgout_len - 1); - if (lastbyte) { - /* Last byte is signified by dropping ATN */ - ahc_outb(ahc, CLRSINT1, CLRATNO); - } - - /* - * Clear our interrupt status and present - * the next byte on the bus. - */ - ahc_outb(ahc, CLRSINT1, CLRREQINIT); - ahc_outb(ahc, SCSIDATL, ahc->msgout_buf[ahc->msgout_index++]); - break; - } - case MSG_TYPE_INITIATOR_MSGIN: - { - int phasemis; - int message_done; - - phasemis = bus_phase != P_MESGIN; - - if (phasemis) { - ahc->msgin_index = 0; - if (bus_phase == P_MESGOUT - && (ahc->send_msg_perror == TRUE - || (ahc->msgout_len != 0 - && ahc->msgout_index == 0))) { - ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT; - goto reswitch; - } - end_session = TRUE; - break; - } - - /* Pull the byte in without acking it */ - ahc->msgin_buf[ahc->msgin_index] = ahc_inb(ahc, SCSIBUSL); - - message_done = ahc_parse_msg(ahc, &devinfo); - - if (message_done) { - /* - * Clear our incoming message buffer in case there - * is another message following this one. - */ - ahc->msgin_index = 0; - - /* - * If this message illicited a response, - * assert ATN so the target takes us to the - * message out phase. - */ - if (ahc->msgout_len != 0) - ahc_assert_atn(ahc); - } else - ahc->msgin_index++; - - if (message_done == MSGLOOP_TERMINATED) { - end_session = TRUE; - } else { - /* Ack the byte */ - ahc_outb(ahc, CLRSINT1, CLRREQINIT); - ahc_inb(ahc, SCSIDATL); - } - break; - } - case MSG_TYPE_TARGET_MSGIN: - { - int msgdone; - int msgout_request; - - if (ahc->msgout_len == 0) - panic("Target MSGIN with no active message"); - - /* - * If we interrupted a mesgout session, the initiator - * will not know this until our first REQ. So, we - * only honor mesgout requests after we've sent our - * first byte. - */ - if ((ahc_inb(ahc, SCSISIGI) & ATNI) != 0 - && ahc->msgout_index > 0) - msgout_request = TRUE; - else - msgout_request = FALSE; - - if (msgout_request) { - - /* - * Change gears and see if - * this messages is of interest to - * us or should be passed back to - * the sequencer. - */ - ahc->msg_type = MSG_TYPE_TARGET_MSGOUT; - ahc_outb(ahc, SCSISIGO, P_MESGOUT | BSYO); - ahc->msgin_index = 0; - /* Dummy read to REQ for first byte */ - ahc_inb(ahc, SCSIDATL); - ahc_outb(ahc, SXFRCTL0, - ahc_inb(ahc, SXFRCTL0) | SPIOEN); - break; - } - - msgdone = ahc->msgout_index == ahc->msgout_len; - if (msgdone) { - ahc_outb(ahc, SXFRCTL0, - ahc_inb(ahc, SXFRCTL0) & ~SPIOEN); - end_session = TRUE; - break; - } - - /* - * Present the next byte on the bus. - */ - ahc_outb(ahc, SXFRCTL0, ahc_inb(ahc, SXFRCTL0) | SPIOEN); - ahc_outb(ahc, SCSIDATL, ahc->msgout_buf[ahc->msgout_index++]); - break; - } - case MSG_TYPE_TARGET_MSGOUT: - { - int lastbyte; - int msgdone; - - /* - * The initiator signals that this is - * the last byte by dropping ATN. - */ - lastbyte = (ahc_inb(ahc, SCSISIGI) & ATNI) == 0; - - /* - * Read the latched byte, but turn off SPIOEN first - * so that we don't inadvertently cause a REQ for the - * next byte. - */ - ahc_outb(ahc, SXFRCTL0, ahc_inb(ahc, SXFRCTL0) & ~SPIOEN); - ahc->msgin_buf[ahc->msgin_index] = ahc_inb(ahc, SCSIDATL); - msgdone = ahc_parse_msg(ahc, &devinfo); - if (msgdone == MSGLOOP_TERMINATED) { - /* - * The message is *really* done in that it caused - * us to go to bus free. The sequencer has already - * been reset at this point, so pull the ejection - * handle. - */ - return; - } - - ahc->msgin_index++; - - /* - * XXX Read spec about initiator dropping ATN too soon - * and use msgdone to detect it. - */ - if (msgdone == MSGLOOP_MSGCOMPLETE) { - ahc->msgin_index = 0; - - /* - * If this message illicited a response, transition - * to the Message in phase and send it. - */ - if (ahc->msgout_len != 0) { - ahc_outb(ahc, SCSISIGO, P_MESGIN | BSYO); - ahc_outb(ahc, SXFRCTL0, - ahc_inb(ahc, SXFRCTL0) | SPIOEN); - ahc->msg_type = MSG_TYPE_TARGET_MSGIN; - ahc->msgin_index = 0; - break; - } - } - - if (lastbyte) - end_session = TRUE; - else { - /* Ask for the next byte. */ - ahc_outb(ahc, SXFRCTL0, - ahc_inb(ahc, SXFRCTL0) | SPIOEN); - } - - break; - } - default: - panic("Unknown REQINIT message type"); - } - - if (end_session) { - ahc_clear_msg_state(ahc); - ahc_outb(ahc, RETURN_1, EXIT_MSG_LOOP); - } else - ahc_outb(ahc, RETURN_1, CONT_MSG_LOOP); -} - -/* - * See if we sent a particular extended message to the target. - * If "full" is true, return true only if the target saw the full - * message. If "full" is false, return true if the target saw at - * least the first byte of the message. - */ -static int -ahc_sent_msg(struct ahc_softc *ahc, ahc_msgtype type, u_int msgval, int full) -{ - int found; - u_int index; - - found = FALSE; - index = 0; - - while (index < ahc->msgout_len) { - if (ahc->msgout_buf[index] == MSG_EXTENDED) { - u_int end_index; - - end_index = index + 1 + ahc->msgout_buf[index + 1]; - if (ahc->msgout_buf[index+2] == msgval - && type == AHCMSG_EXT) { - - if (full) { - if (ahc->msgout_index > end_index) - found = TRUE; - } else if (ahc->msgout_index > index) - found = TRUE; - } - index = end_index; - } else if (ahc->msgout_buf[index] >= MSG_SIMPLE_TASK - && ahc->msgout_buf[index] <= MSG_IGN_WIDE_RESIDUE) { - - /* Skip tag type and tag id or residue param*/ - index += 2; - } else { - /* Single byte message */ - if (type == AHCMSG_1B - && ahc->msgout_buf[index] == msgval - && ahc->msgout_index > index) - found = TRUE; - index++; - } - - if (found) - break; - } - return (found); -} - -/* - * Wait for a complete incoming message, parse it, and respond accordingly. - */ -static int -ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) -{ - struct ahc_initiator_tinfo *tinfo; - struct ahc_tmode_tstate *tstate; - int reject; - int done; - int response; - u_int targ_scsirate; - - done = MSGLOOP_IN_PROG; - response = FALSE; - reject = FALSE; - tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, - devinfo->target, &tstate); - targ_scsirate = tinfo->scsirate; - - /* - * Parse as much of the message as is availible, - * rejecting it if we don't support it. When - * the entire message is availible and has been - * handled, return MSGLOOP_MSGCOMPLETE, indicating - * that we have parsed an entire message. - * - * In the case of extended messages, we accept the length - * byte outright and perform more checking once we know the - * extended message type. - */ - switch (ahc->msgin_buf[0]) { - case MSG_DISCONNECT: - case MSG_SAVEDATAPOINTER: - case MSG_CMDCOMPLETE: - case MSG_RESTOREPOINTERS: - case MSG_IGN_WIDE_RESIDUE: - /* - * End our message loop as these are messages - * the sequencer handles on its own. - */ - done = MSGLOOP_TERMINATED; - break; - case MSG_MESSAGE_REJECT: - response = ahc_handle_msg_reject(ahc, devinfo); - /* FALLTHROUGH */ - case MSG_NOOP: - done = MSGLOOP_MSGCOMPLETE; - break; - case MSG_EXTENDED: - { - /* Wait for enough of the message to begin validation */ - if (ahc->msgin_index < 2) - break; - switch (ahc->msgin_buf[2]) { - case MSG_EXT_SDTR: - { - struct ahc_syncrate *syncrate; - u_int period; - u_int ppr_options; - u_int offset; - u_int saved_offset; - - if (ahc->msgin_buf[1] != MSG_EXT_SDTR_LEN) { - reject = TRUE; - break; - } - - /* - * Wait until we have both args before validating - * and acting on this message. - * - * Add one to MSG_EXT_SDTR_LEN to account for - * the extended message preamble. - */ - if (ahc->msgin_index < (MSG_EXT_SDTR_LEN + 1)) - break; - - period = ahc->msgin_buf[3]; - ppr_options = 0; - saved_offset = offset = ahc->msgin_buf[4]; - syncrate = ahc_devlimited_syncrate(ahc, tinfo, &period, - &ppr_options, - devinfo->role); - ahc_validate_offset(ahc, tinfo, syncrate, &offset, - targ_scsirate & WIDEXFER, - devinfo->role); - if (bootverbose) { - printf("(%s:%c:%d:%d): Received " - "SDTR period %x, offset %x\n\t" - "Filtered to period %x, offset %x\n", - ahc_name(ahc), devinfo->channel, - devinfo->target, devinfo->lun, - ahc->msgin_buf[3], saved_offset, - period, offset); - } - ahc_set_syncrate(ahc, devinfo, - syncrate, period, - offset, ppr_options, - AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, - /*paused*/TRUE); - - /* - * See if we initiated Sync Negotiation - * and didn't have to fall down to async - * transfers. - */ - if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_SDTR, TRUE)) { - /* We started it */ - if (saved_offset != offset) { - /* Went too low - force async */ - reject = TRUE; - } - } else { - /* - * Send our own SDTR in reply - */ - if (bootverbose - && devinfo->role == ROLE_INITIATOR) { - printf("(%s:%c:%d:%d): Target " - "Initiated SDTR\n", - ahc_name(ahc), devinfo->channel, - devinfo->target, devinfo->lun); - } - ahc->msgout_index = 0; - ahc->msgout_len = 0; - ahc_construct_sdtr(ahc, devinfo, - period, offset); - ahc->msgout_index = 0; - response = TRUE; - } - done = MSGLOOP_MSGCOMPLETE; - break; - } - case MSG_EXT_WDTR: - { - u_int bus_width; - u_int saved_width; - u_int sending_reply; - - sending_reply = FALSE; - if (ahc->msgin_buf[1] != MSG_EXT_WDTR_LEN) { - reject = TRUE; - break; - } - - /* - * Wait until we have our arg before validating - * and acting on this message. - * - * Add one to MSG_EXT_WDTR_LEN to account for - * the extended message preamble. - */ - if (ahc->msgin_index < (MSG_EXT_WDTR_LEN + 1)) - break; - - bus_width = ahc->msgin_buf[3]; - saved_width = bus_width; - ahc_validate_width(ahc, tinfo, &bus_width, - devinfo->role); - if (bootverbose) { - printf("(%s:%c:%d:%d): Received WDTR " - "%x filtered to %x\n", - ahc_name(ahc), devinfo->channel, - devinfo->target, devinfo->lun, - saved_width, bus_width); - } - - if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_WDTR, TRUE)) { - /* - * Don't send a WDTR back to the - * target, since we asked first. - * If the width went higher than our - * request, reject it. - */ - if (saved_width > bus_width) { - reject = TRUE; - printf("(%s:%c:%d:%d): requested %dBit " - "transfers. Rejecting...\n", - ahc_name(ahc), devinfo->channel, - devinfo->target, devinfo->lun, - 8 * (0x01 << bus_width)); - bus_width = 0; - } - } else { - /* - * Send our own WDTR in reply - */ - if (bootverbose - && devinfo->role == ROLE_INITIATOR) { - printf("(%s:%c:%d:%d): Target " - "Initiated WDTR\n", - ahc_name(ahc), devinfo->channel, - devinfo->target, devinfo->lun); - } - ahc->msgout_index = 0; - ahc->msgout_len = 0; - ahc_construct_wdtr(ahc, devinfo, bus_width); - ahc->msgout_index = 0; - response = TRUE; - sending_reply = TRUE; - } - ahc_set_width(ahc, devinfo, bus_width, - AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, - /*paused*/TRUE); - /* After a wide message, we are async */ - ahc_set_syncrate(ahc, devinfo, - /*syncrate*/NULL, /*period*/0, - /*offset*/0, /*ppr_options*/0, - AHC_TRANS_ACTIVE, /*paused*/TRUE); - if (sending_reply == FALSE && reject == FALSE) { - - if (tinfo->goal.period) { - ahc->msgout_index = 0; - ahc->msgout_len = 0; - ahc_build_transfer_msg(ahc, devinfo); - ahc->msgout_index = 0; - response = TRUE; - } - } - done = MSGLOOP_MSGCOMPLETE; - break; - } - case MSG_EXT_PPR: - { - struct ahc_syncrate *syncrate; - u_int period; - u_int offset; - u_int bus_width; - u_int ppr_options; - u_int saved_width; - u_int saved_offset; - u_int saved_ppr_options; - - if (ahc->msgin_buf[1] != MSG_EXT_PPR_LEN) { - reject = TRUE; - break; - } - - /* - * Wait until we have all args before validating - * and acting on this message. - * - * Add one to MSG_EXT_PPR_LEN to account for - * the extended message preamble. - */ - if (ahc->msgin_index < (MSG_EXT_PPR_LEN + 1)) - break; - - period = ahc->msgin_buf[3]; - offset = ahc->msgin_buf[5]; - bus_width = ahc->msgin_buf[6]; - saved_width = bus_width; - ppr_options = ahc->msgin_buf[7]; - /* - * According to the spec, a DT only - * period factor with no DT option - * set implies async. - */ - if ((ppr_options & MSG_EXT_PPR_DT_REQ) == 0 - && period == 9) - offset = 0; - saved_ppr_options = ppr_options; - saved_offset = offset; - - /* - * Mask out any options we don't support - * on any controller. Transfer options are - * only available if we are negotiating wide. - */ - ppr_options &= MSG_EXT_PPR_DT_REQ; - if (bus_width == 0) - ppr_options = 0; - - ahc_validate_width(ahc, tinfo, &bus_width, - devinfo->role); - syncrate = ahc_devlimited_syncrate(ahc, tinfo, &period, - &ppr_options, - devinfo->role); - ahc_validate_offset(ahc, tinfo, syncrate, - &offset, bus_width, - devinfo->role); - - if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_PPR, TRUE)) { - /* - * If we are unable to do any of the - * requested options (we went too low), - * then we'll have to reject the message. - */ - if (saved_width > bus_width - || saved_offset != offset - || saved_ppr_options != ppr_options) { - reject = TRUE; - period = 0; - offset = 0; - bus_width = 0; - ppr_options = 0; - syncrate = NULL; - } - } else { - if (devinfo->role != ROLE_TARGET) - printf("(%s:%c:%d:%d): Target " - "Initiated PPR\n", - ahc_name(ahc), devinfo->channel, - devinfo->target, devinfo->lun); - else - printf("(%s:%c:%d:%d): Initiator " - "Initiated PPR\n", - ahc_name(ahc), devinfo->channel, - devinfo->target, devinfo->lun); - ahc->msgout_index = 0; - ahc->msgout_len = 0; - ahc_construct_ppr(ahc, devinfo, period, offset, - bus_width, ppr_options); - ahc->msgout_index = 0; - response = TRUE; - } - if (bootverbose) { - printf("(%s:%c:%d:%d): Received PPR width %x, " - "period %x, offset %x,options %x\n" - "\tFiltered to width %x, period %x, " - "offset %x, options %x\n", - ahc_name(ahc), devinfo->channel, - devinfo->target, devinfo->lun, - saved_width, ahc->msgin_buf[3], - saved_offset, saved_ppr_options, - bus_width, period, offset, ppr_options); - } - ahc_set_width(ahc, devinfo, bus_width, - AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, - /*paused*/TRUE); - ahc_set_syncrate(ahc, devinfo, - syncrate, period, - offset, ppr_options, - AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, - /*paused*/TRUE); - done = MSGLOOP_MSGCOMPLETE; - break; - } - default: - /* Unknown extended message. Reject it. */ - reject = TRUE; - break; - } - break; - } -#ifdef AHC_TARGET_MODE - case MSG_BUS_DEV_RESET: - ahc_handle_devreset(ahc, devinfo, - CAM_BDR_SENT, - "Bus Device Reset Received", - /*verbose_level*/0); - ahc_restart(ahc); - done = MSGLOOP_TERMINATED; - break; - case MSG_ABORT_TAG: - case MSG_ABORT: - case MSG_CLEAR_QUEUE: - { - int tag; - - /* Target mode messages */ - if (devinfo->role != ROLE_TARGET) { - reject = TRUE; - break; - } - tag = SCB_LIST_NULL; - if (ahc->msgin_buf[0] == MSG_ABORT_TAG) - tag = ahc_inb(ahc, INITIATOR_TAG); - ahc_abort_scbs(ahc, devinfo->target, devinfo->channel, - devinfo->lun, tag, ROLE_TARGET, - CAM_REQ_ABORTED); - - tstate = ahc->enabled_targets[devinfo->our_scsiid]; - if (tstate != NULL) { - struct ahc_tmode_lstate* lstate; - - lstate = tstate->enabled_luns[devinfo->lun]; - if (lstate != NULL) { - ahc_queue_lstate_event(ahc, lstate, - devinfo->our_scsiid, - ahc->msgin_buf[0], - /*arg*/tag); - ahc_send_lstate_events(ahc, lstate); - } - } - ahc_restart(ahc); - done = MSGLOOP_TERMINATED; - break; - } -#endif - case MSG_TERM_IO_PROC: - default: - reject = TRUE; - break; - } - - if (reject) { - /* - * Setup to reject the message. - */ - ahc->msgout_index = 0; - ahc->msgout_len = 1; - ahc->msgout_buf[0] = MSG_MESSAGE_REJECT; - done = MSGLOOP_MSGCOMPLETE; - response = TRUE; - } - - if (done != MSGLOOP_IN_PROG && !response) - /* Clear the outgoing message buffer */ - ahc->msgout_len = 0; - - return (done); -} - -/* - * Process a message reject message. - */ -static int -ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) -{ - /* - * What we care about here is if we had an - * outstanding SDTR or WDTR message for this - * target. If we did, this is a signal that - * the target is refusing negotiation. - */ - struct scb *scb; - struct ahc_initiator_tinfo *tinfo; - struct ahc_tmode_tstate *tstate; - u_int scb_index; - u_int last_msg; - int response = 0; - - scb_index = ahc_inb(ahc, SCB_TAG); - scb = ahc_lookup_scb(ahc, scb_index); - tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, - devinfo->our_scsiid, - devinfo->target, &tstate); - /* Might be necessary */ - last_msg = ahc_inb(ahc, LAST_MSG); - - if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_PPR, /*full*/FALSE)) { - /* - * Target does not support the PPR message. - * Attempt to negotiate SPI-2 style. - */ - if (bootverbose) { - printf("(%s:%c:%d:%d): PPR Rejected. " - "Trying WDTR/SDTR\n", - ahc_name(ahc), devinfo->channel, - devinfo->target, devinfo->lun); - } - tinfo->goal.ppr_options = 0; - tinfo->curr.transport_version = 2; - tinfo->goal.transport_version = 2; - ahc->msgout_index = 0; - ahc->msgout_len = 0; - ahc_build_transfer_msg(ahc, devinfo); - ahc->msgout_index = 0; - response = 1; - } else if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_WDTR, /*full*/FALSE)) { - - /* note 8bit xfers */ - printf("(%s:%c:%d:%d): refuses WIDE negotiation. Using " - "8bit transfers\n", ahc_name(ahc), - devinfo->channel, devinfo->target, devinfo->lun); - ahc_set_width(ahc, devinfo, MSG_EXT_WDTR_BUS_8_BIT, - AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, - /*paused*/TRUE); - /* - * No need to clear the sync rate. If the target - * did not accept the command, our syncrate is - * unaffected. If the target started the negotiation, - * but rejected our response, we already cleared the - * sync rate before sending our WDTR. - */ - if (tinfo->goal.period) { - - /* Start the sync negotiation */ - ahc->msgout_index = 0; - ahc->msgout_len = 0; - ahc_build_transfer_msg(ahc, devinfo); - ahc->msgout_index = 0; - response = 1; - } - } else if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_SDTR, /*full*/FALSE)) { - /* note asynch xfers and clear flag */ - ahc_set_syncrate(ahc, devinfo, /*syncrate*/NULL, /*period*/0, - /*offset*/0, /*ppr_options*/0, - AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, - /*paused*/TRUE); - printf("(%s:%c:%d:%d): refuses synchronous negotiation. " - "Using asynchronous transfers\n", - ahc_name(ahc), devinfo->channel, - devinfo->target, devinfo->lun); - } else if ((scb->hscb->control & MSG_SIMPLE_TASK) != 0) { - int tag_type; - int mask; - - tag_type = (scb->hscb->control & MSG_SIMPLE_TASK); - - if (tag_type == MSG_SIMPLE_TASK) { - printf("(%s:%c:%d:%d): refuses tagged commands. " - "Performing non-tagged I/O\n", ahc_name(ahc), - devinfo->channel, devinfo->target, devinfo->lun); - ahc_set_tags(ahc, devinfo, AHC_QUEUE_NONE); - mask = ~0x23; - } else { - printf("(%s:%c:%d:%d): refuses %s tagged commands. " - "Performing simple queue tagged I/O only\n", - ahc_name(ahc), devinfo->channel, devinfo->target, - devinfo->lun, tag_type == MSG_ORDERED_TASK - ? "ordered" : "head of queue"); - ahc_set_tags(ahc, devinfo, AHC_QUEUE_BASIC); - mask = ~0x03; - } - - /* - * Resend the identify for this CCB as the target - * may believe that the selection is invalid otherwise. - */ - ahc_outb(ahc, SCB_CONTROL, - ahc_inb(ahc, SCB_CONTROL) & mask); - scb->hscb->control &= mask; - ahc_set_transaction_tag(scb, /*enabled*/FALSE, - /*type*/MSG_SIMPLE_TASK); - ahc_outb(ahc, MSG_OUT, MSG_IDENTIFYFLAG); - ahc_assert_atn(ahc); - - /* - * This transaction is now at the head of - * the untagged queue for this target. - */ - if ((ahc->flags & AHC_SCB_BTT) == 0) { - struct scb_tailq *untagged_q; - - untagged_q = - &(ahc->untagged_queues[devinfo->target_offset]); - TAILQ_INSERT_HEAD(untagged_q, scb, links.tqe); - scb->flags |= SCB_UNTAGGEDQ; - } - ahc_busy_tcl(ahc, BUILD_TCL(scb->hscb->scsiid, devinfo->lun), - scb->hscb->tag); - - /* - * Requeue all tagged commands for this target - * currently in our posession so they can be - * converted to untagged commands. - */ - ahc_search_qinfifo(ahc, SCB_GET_TARGET(ahc, scb), - SCB_GET_CHANNEL(ahc, scb), - SCB_GET_LUN(scb), /*tag*/SCB_LIST_NULL, - ROLE_INITIATOR, CAM_REQUEUE_REQ, - SEARCH_COMPLETE); - } else { - /* - * Otherwise, we ignore it. - */ - printf("%s:%c:%d: Message reject for %x -- ignored\n", - ahc_name(ahc), devinfo->channel, devinfo->target, - last_msg); - } - return (response); -} - -/* - * Process an ingnore wide residue message. - */ -static void -ahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) -{ - u_int scb_index; - struct scb *scb; - - scb_index = ahc_inb(ahc, SCB_TAG); - scb = ahc_lookup_scb(ahc, scb_index); - /* - * XXX Actually check data direction in the sequencer? - * Perhaps add datadir to some spare bits in the hscb? - */ - if ((ahc_inb(ahc, SEQ_FLAGS) & DPHASE) == 0 - || ahc_get_transfer_dir(scb) != CAM_DIR_IN) { - /* - * Ignore the message if we haven't - * seen an appropriate data phase yet. - */ - } else { - /* - * If the residual occurred on the last - * transfer and the transfer request was - * expected to end on an odd count, do - * nothing. Otherwise, subtract a byte - * and update the residual count accordingly. - */ - uint32_t sgptr; - - sgptr = ahc_inb(ahc, SCB_RESIDUAL_SGPTR); - if ((sgptr & SG_LIST_NULL) != 0 - && ahc_inb(ahc, DATA_COUNT_ODD) == 1) { - /* - * If the residual occurred on the last - * transfer and the transfer request was - * expected to end on an odd count, do - * nothing. - */ - } else { - struct ahc_dma_seg *sg; - uint32_t data_cnt; - uint32_t data_addr; - uint32_t sglen; - - /* Pull in the rest of the sgptr */ - sgptr |= (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 3) << 24) - | (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 2) << 16) - | (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 1) << 8); - sgptr &= SG_PTR_MASK; - data_cnt = (ahc_inb(ahc, SCB_RESIDUAL_DATACNT+3) << 24) - | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT+2) << 16) - | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT+1) << 8) - | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT)); - - data_addr = (ahc_inb(ahc, SHADDR + 3) << 24) - | (ahc_inb(ahc, SHADDR + 2) << 16) - | (ahc_inb(ahc, SHADDR + 1) << 8) - | (ahc_inb(ahc, SHADDR)); - - data_cnt += 1; - data_addr -= 1; - - sg = ahc_sg_bus_to_virt(scb, sgptr); - /* - * The residual sg ptr points to the next S/G - * to load so we must go back one. - */ - sg--; - sglen = ahc_le32toh(sg->len) & AHC_SG_LEN_MASK; - if (sg != scb->sg_list - && sglen < (data_cnt & AHC_SG_LEN_MASK)) { - - sg--; - sglen = ahc_le32toh(sg->len); - /* - * Preserve High Address and SG_LIST bits - * while setting the count to 1. - */ - data_cnt = 1 | (sglen & (~AHC_SG_LEN_MASK)); - data_addr = ahc_le32toh(sg->addr) - + (sglen & AHC_SG_LEN_MASK) - 1; - - /* - * Increment sg so it points to the - * "next" sg. - */ - sg++; - sgptr = ahc_sg_virt_to_bus(scb, sg); - ahc_outb(ahc, SCB_RESIDUAL_SGPTR + 3, - sgptr >> 24); - ahc_outb(ahc, SCB_RESIDUAL_SGPTR + 2, - sgptr >> 16); - ahc_outb(ahc, SCB_RESIDUAL_SGPTR + 1, - sgptr >> 8); - ahc_outb(ahc, SCB_RESIDUAL_SGPTR, sgptr); - } - - ahc_outb(ahc, SCB_RESIDUAL_DATACNT + 3, data_cnt >> 24); - ahc_outb(ahc, SCB_RESIDUAL_DATACNT + 2, data_cnt >> 16); - ahc_outb(ahc, SCB_RESIDUAL_DATACNT + 1, data_cnt >> 8); - ahc_outb(ahc, SCB_RESIDUAL_DATACNT, data_cnt); - } - } -} - - -/* - * Reinitialize the data pointers for the active transfer - * based on its current residual. - */ -static void -ahc_reinitialize_dataptrs(struct ahc_softc *ahc) -{ - struct scb *scb; - struct ahc_dma_seg *sg; - u_int scb_index; - uint32_t sgptr; - uint32_t resid; - uint32_t dataptr; - - scb_index = ahc_inb(ahc, SCB_TAG); - scb = ahc_lookup_scb(ahc, scb_index); - sgptr = (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 3) << 24) - | (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 2) << 16) - | (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 1) << 8) - | ahc_inb(ahc, SCB_RESIDUAL_SGPTR); - - sgptr &= SG_PTR_MASK; - sg = ahc_sg_bus_to_virt(scb, sgptr); - - /* The residual sg_ptr always points to the next sg */ - sg--; - - resid = (ahc_inb(ahc, SCB_RESIDUAL_DATACNT + 2) << 16) - | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT + 1) << 8) - | ahc_inb(ahc, SCB_RESIDUAL_DATACNT); - - dataptr = ahc_le32toh(sg->addr) - + (ahc_le32toh(sg->len) & AHC_SG_LEN_MASK) - - resid; - if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { - u_int dscommand1; - - dscommand1 = ahc_inb(ahc, DSCOMMAND1); - ahc_outb(ahc, DSCOMMAND1, dscommand1 | HADDLDSEL0); - ahc_outb(ahc, HADDR, - (ahc_le32toh(sg->len) >> 24) & SG_HIGH_ADDR_BITS); - ahc_outb(ahc, DSCOMMAND1, dscommand1); - } - ahc_outb(ahc, HADDR + 3, dataptr >> 24); - ahc_outb(ahc, HADDR + 2, dataptr >> 16); - ahc_outb(ahc, HADDR + 1, dataptr >> 8); - ahc_outb(ahc, HADDR, dataptr); - ahc_outb(ahc, HCNT + 2, resid >> 16); - ahc_outb(ahc, HCNT + 1, resid >> 8); - ahc_outb(ahc, HCNT, resid); - if ((ahc->features & AHC_ULTRA2) == 0) { - ahc_outb(ahc, STCNT + 2, resid >> 16); - ahc_outb(ahc, STCNT + 1, resid >> 8); - ahc_outb(ahc, STCNT, resid); - } -} - -/* - * Handle the effects of issuing a bus device reset message. - */ -static void -ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, - cam_status status, char *message, int verbose_level) -{ -#ifdef AHC_TARGET_MODE - struct ahc_tmode_tstate* tstate; - u_int lun; -#endif - int found; - - found = ahc_abort_scbs(ahc, devinfo->target, devinfo->channel, - CAM_LUN_WILDCARD, SCB_LIST_NULL, devinfo->role, - status); - -#ifdef AHC_TARGET_MODE - /* - * Send an immediate notify ccb to all target mord peripheral - * drivers affected by this action. - */ - tstate = ahc->enabled_targets[devinfo->our_scsiid]; - if (tstate != NULL) { - for (lun = 0; lun < AHC_NUM_LUNS; lun++) { - struct ahc_tmode_lstate* lstate; - - lstate = tstate->enabled_luns[lun]; - if (lstate == NULL) - continue; - - ahc_queue_lstate_event(ahc, lstate, devinfo->our_scsiid, - MSG_BUS_DEV_RESET, /*arg*/0); - ahc_send_lstate_events(ahc, lstate); - } - } -#endif - - /* - * Go back to async/narrow transfers and renegotiate. - */ - ahc_set_width(ahc, devinfo, MSG_EXT_WDTR_BUS_8_BIT, - AHC_TRANS_CUR, /*paused*/TRUE); - ahc_set_syncrate(ahc, devinfo, /*syncrate*/NULL, - /*period*/0, /*offset*/0, /*ppr_options*/0, - AHC_TRANS_CUR, /*paused*/TRUE); - - ahc_send_async(ahc, devinfo->channel, devinfo->target, - CAM_LUN_WILDCARD, AC_SENT_BDR, NULL); - - if (message != NULL - && (verbose_level <= bootverbose)) - printf("%s: %s on %c:%d. %d SCBs aborted\n", ahc_name(ahc), - message, devinfo->channel, devinfo->target, found); -} - -#ifdef AHC_TARGET_MODE -static void -ahc_setup_target_msgin(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, - struct scb *scb) -{ - - /* - * To facilitate adding multiple messages together, - * each routine should increment the index and len - * variables instead of setting them explicitly. - */ - ahc->msgout_index = 0; - ahc->msgout_len = 0; - - if (scb != NULL && (scb->flags & SCB_AUTO_NEGOTIATE) != 0) - ahc_build_transfer_msg(ahc, devinfo); - else - panic("ahc_intr: AWAITING target message with no message"); - - ahc->msgout_index = 0; - ahc->msg_type = MSG_TYPE_TARGET_MSGIN; -} -#endif -/**************************** Initialization **********************************/ -/* - * Allocate a controller structure for a new device - * and perform initial initializion. - */ -struct ahc_softc * -ahc_alloc(void *platform_arg, char *name) -{ - struct ahc_softc *ahc; - int i; - -#ifndef __FreeBSD__ - ahc = malloc(sizeof(*ahc), M_DEVBUF, M_NOWAIT); - if (!ahc) { - printf("aic7xxx: cannot malloc softc!\n"); - free(name, M_DEVBUF); - return NULL; - } -#else - ahc = device_get_softc((device_t)platform_arg); -#endif - memset(ahc, 0, sizeof(*ahc)); - ahc->seep_config = malloc(sizeof(*ahc->seep_config), - M_DEVBUF, M_NOWAIT); - if (ahc->seep_config == NULL) { -#ifndef __FreeBSD__ - free(ahc, M_DEVBUF); -#endif - free(name, M_DEVBUF); - return (NULL); - } - LIST_INIT(&ahc->pending_scbs); - /* We don't know our unit number until the OSM sets it */ - ahc->name = name; - ahc->unit = -1; - ahc->description = NULL; - ahc->channel = 'A'; - ahc->channel_b = 'B'; - ahc->chip = AHC_NONE; - ahc->features = AHC_FENONE; - ahc->bugs = AHC_BUGNONE; - ahc->flags = AHC_FNONE; - - for (i = 0; i < AHC_NUM_TARGETS; i++) - TAILQ_INIT(&ahc->untagged_queues[i]); - if (ahc_platform_alloc(ahc, platform_arg) != 0) { - ahc_free(ahc); - ahc = NULL; - } - return (ahc); -} - -int -ahc_softc_init(struct ahc_softc *ahc) -{ - - /* The IRQMS bit is only valid on VL and EISA chips */ - if ((ahc->chip & AHC_PCI) == 0) - ahc->unpause = ahc_inb(ahc, HCNTRL) & IRQMS; - else - ahc->unpause = 0; - ahc->pause = ahc->unpause | PAUSE; - /* XXX The shared scb data stuff should be deprecated */ - if (ahc->scb_data == NULL) { - ahc->scb_data = malloc(sizeof(*ahc->scb_data), - M_DEVBUF, M_NOWAIT); - if (ahc->scb_data == NULL) - return (ENOMEM); - memset(ahc->scb_data, 0, sizeof(*ahc->scb_data)); - } - - return (0); -} - -void -ahc_softc_insert(struct ahc_softc *ahc) -{ - struct ahc_softc *list_ahc; - -#if AHC_PCI_CONFIG > 0 - /* - * Second Function PCI devices need to inherit some - * settings from function 0. - */ - if ((ahc->chip & AHC_BUS_MASK) == AHC_PCI - && (ahc->features & AHC_MULTI_FUNC) != 0) { - TAILQ_FOREACH(list_ahc, &ahc_tailq, links) { - ahc_dev_softc_t list_pci; - ahc_dev_softc_t pci; - - list_pci = list_ahc->dev_softc; - pci = ahc->dev_softc; - if (ahc_get_pci_slot(list_pci) == ahc_get_pci_slot(pci) - && ahc_get_pci_bus(list_pci) == ahc_get_pci_bus(pci)) { - struct ahc_softc *master; - struct ahc_softc *slave; - - if (ahc_get_pci_function(list_pci) == 0) { - master = list_ahc; - slave = ahc; - } else { - master = ahc; - slave = list_ahc; - } - slave->flags &= ~AHC_BIOS_ENABLED; - slave->flags |= - master->flags & AHC_BIOS_ENABLED; - slave->flags &= ~AHC_PRIMARY_CHANNEL; - slave->flags |= - master->flags & AHC_PRIMARY_CHANNEL; - break; - } - } - } -#endif - - /* - * Insertion sort into our list of softcs. - */ - list_ahc = TAILQ_FIRST(&ahc_tailq); - while (list_ahc != NULL - && ahc_softc_comp(list_ahc, ahc) <= 0) - list_ahc = TAILQ_NEXT(list_ahc, links); - if (list_ahc != NULL) - TAILQ_INSERT_BEFORE(list_ahc, ahc, links); - else - TAILQ_INSERT_TAIL(&ahc_tailq, ahc, links); - ahc->init_level++; -} - -/* - * Verify that the passed in softc pointer is for a - * controller that is still configured. - */ -struct ahc_softc * -ahc_find_softc(struct ahc_softc *ahc) -{ - struct ahc_softc *list_ahc; - - TAILQ_FOREACH(list_ahc, &ahc_tailq, links) { - if (list_ahc == ahc) - return (ahc); - } - return (NULL); -} - -void -ahc_set_unit(struct ahc_softc *ahc, int unit) -{ - ahc->unit = unit; -} - -void -ahc_set_name(struct ahc_softc *ahc, char *name) -{ - if (ahc->name != NULL) - free(ahc->name, M_DEVBUF); - ahc->name = name; -} - -void -ahc_free(struct ahc_softc *ahc) -{ - int i; - - ahc_fini_scbdata(ahc); - switch (ahc->init_level) { - default: - case 5: - ahc_shutdown(ahc); - TAILQ_REMOVE(&ahc_tailq, ahc, links); - /* FALLTHROUGH */ - case 4: - ahc_dmamap_unload(ahc, ahc->shared_data_dmat, - ahc->shared_data_dmamap); - /* FALLTHROUGH */ - case 3: - ahc_dmamem_free(ahc, ahc->shared_data_dmat, ahc->qoutfifo, - ahc->shared_data_dmamap); - ahc_dmamap_destroy(ahc, ahc->shared_data_dmat, - ahc->shared_data_dmamap); - /* FALLTHROUGH */ - case 2: - ahc_dma_tag_destroy(ahc, ahc->shared_data_dmat); - case 1: -#ifndef __linux__ - ahc_dma_tag_destroy(ahc, ahc->buffer_dmat); -#endif - break; - case 0: - break; - } - -#ifndef __linux__ - ahc_dma_tag_destroy(ahc, ahc->parent_dmat); -#endif - ahc_platform_free(ahc); - for (i = 0; i < AHC_NUM_TARGETS; i++) { - struct ahc_tmode_tstate *tstate; - - tstate = ahc->enabled_targets[i]; - if (tstate != NULL) { -#if AHC_TARGET_MODE - int j; - - for (j = 0; j < AHC_NUM_LUNS; j++) { - struct ahc_tmode_lstate *lstate; - - lstate = tstate->enabled_luns[j]; - if (lstate != NULL) { - xpt_free_path(lstate->path); - free(lstate, M_DEVBUF); - } - } -#endif - free(tstate, M_DEVBUF); - } - } -#if AHC_TARGET_MODE - if (ahc->black_hole != NULL) { - xpt_free_path(ahc->black_hole->path); - free(ahc->black_hole, M_DEVBUF); - } -#endif - if (ahc->name != NULL) - free(ahc->name, M_DEVBUF); - if (ahc->seep_config != NULL) - free(ahc->seep_config, M_DEVBUF); -#ifndef __FreeBSD__ - free(ahc, M_DEVBUF); -#endif - return; -} - -void -ahc_shutdown(void *arg) -{ - struct ahc_softc *ahc; - int i; - - ahc = (struct ahc_softc *)arg; - - /* This will reset most registers to 0, but not all */ - ahc_reset(ahc); - ahc_outb(ahc, SCSISEQ, 0); - ahc_outb(ahc, SXFRCTL0, 0); - ahc_outb(ahc, DSPCISTATUS, 0); - - for (i = TARG_SCSIRATE; i < SCSICONF; i++) - ahc_outb(ahc, i, 0); -} - -/* - * Reset the controller and record some information about it - * that is only available just after a reset. - */ -int -ahc_reset(struct ahc_softc *ahc) -{ - u_int sblkctl; - u_int sxfrctl1_a, sxfrctl1_b; - int wait; - - /* - * Preserve the value of the SXFRCTL1 register for all channels. - * It contains settings that affect termination and we don't want - * to disturb the integrity of the bus. - */ - ahc_pause(ahc); - sxfrctl1_b = 0; - if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) { - u_int sblkctl; - - /* - * Save channel B's settings in case this chip - * is setup for TWIN channel operation. - */ - sblkctl = ahc_inb(ahc, SBLKCTL); - ahc_outb(ahc, SBLKCTL, sblkctl | SELBUSB); - sxfrctl1_b = ahc_inb(ahc, SXFRCTL1); - ahc_outb(ahc, SBLKCTL, sblkctl & ~SELBUSB); - } - sxfrctl1_a = ahc_inb(ahc, SXFRCTL1); - - ahc_outb(ahc, HCNTRL, CHIPRST | ahc->pause); - - /* - * Ensure that the reset has finished. We delay 1000us - * prior to reading the register to make sure the chip - * has sufficiently completed its reset to handle register - * accesses. - */ - wait = 1000; - do { - ahc_delay(1000); - } while (--wait && !(ahc_inb(ahc, HCNTRL) & CHIPRSTACK)); - - if (wait == 0) { - printf("%s: WARNING - Failed chip reset! " - "Trying to initialize anyway.\n", ahc_name(ahc)); - } - ahc_outb(ahc, HCNTRL, ahc->pause); - - /* Determine channel configuration */ - sblkctl = ahc_inb(ahc, SBLKCTL) & (SELBUSB|SELWIDE); - /* No Twin Channel PCI cards */ - if ((ahc->chip & AHC_PCI) != 0) - sblkctl &= ~SELBUSB; - switch (sblkctl) { - case 0: - /* Single Narrow Channel */ - break; - case 2: - /* Wide Channel */ - ahc->features |= AHC_WIDE; - break; - case 8: - /* Twin Channel */ - ahc->features |= AHC_TWIN; - break; - default: - printf(" Unsupported adapter type. Ignoring\n"); - return(-1); - } - - /* - * Reload sxfrctl1. - * - * We must always initialize STPWEN to 1 before we - * restore the saved values. STPWEN is initialized - * to a tri-state condition which can only be cleared - * by turning it on. - */ - if ((ahc->features & AHC_TWIN) != 0) { - u_int sblkctl; - - sblkctl = ahc_inb(ahc, SBLKCTL); - ahc_outb(ahc, SBLKCTL, sblkctl | SELBUSB); - ahc_outb(ahc, SXFRCTL1, sxfrctl1_b); - ahc_outb(ahc, SBLKCTL, sblkctl & ~SELBUSB); - } - ahc_outb(ahc, SXFRCTL1, sxfrctl1_a); - -#ifdef AHC_DUMP_SEQ - if (ahc->init_level == 0) - ahc_dumpseq(ahc); -#endif - - return (0); -} - -/* - * Determine the number of SCBs available on the controller - */ -int -ahc_probe_scbs(struct ahc_softc *ahc) { - int i; - - for (i = 0; i < AHC_SCB_MAX; i++) { - - ahc_outb(ahc, SCBPTR, i); - ahc_outb(ahc, SCB_BASE, i); - if (ahc_inb(ahc, SCB_BASE) != i) - break; - ahc_outb(ahc, SCBPTR, 0); - if (ahc_inb(ahc, SCB_BASE) != 0) - break; - } - return (i); -} - -static void -ahc_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - bus_addr_t *baddr; - - baddr = (bus_addr_t *)arg; - *baddr = segs->ds_addr; -} - -static void -ahc_build_free_scb_list(struct ahc_softc *ahc) -{ - int scbsize; - int i; - - scbsize = 32; - if ((ahc->flags & AHC_LSCBS_ENABLED) != 0) - scbsize = 64; - - for (i = 0; i < ahc->scb_data->maxhscbs; i++) { - int j; - - ahc_outb(ahc, SCBPTR, i); - - /* - * Touch all SCB bytes to avoid parity errors - * should one of our debugging routines read - * an otherwise uninitiatlized byte. - */ - for (j = 0; j < scbsize; j++) - ahc_outb(ahc, SCB_BASE+j, 0xFF); - - /* Clear the control byte. */ - ahc_outb(ahc, SCB_CONTROL, 0); - - /* Set the next pointer */ - if ((ahc->flags & AHC_PAGESCBS) != 0) - ahc_outb(ahc, SCB_NEXT, i+1); - else - ahc_outb(ahc, SCB_NEXT, SCB_LIST_NULL); - - /* Make the tag number, SCSIID, and lun invalid */ - ahc_outb(ahc, SCB_TAG, SCB_LIST_NULL); - ahc_outb(ahc, SCB_SCSIID, 0xFF); - ahc_outb(ahc, SCB_LUN, 0xFF); - } - - /* Make sure that the last SCB terminates the free list */ - ahc_outb(ahc, SCBPTR, i-1); - ahc_outb(ahc, SCB_NEXT, SCB_LIST_NULL); -} - -static int -ahc_init_scbdata(struct ahc_softc *ahc) -{ - struct scb_data *scb_data; - - scb_data = ahc->scb_data; - SLIST_INIT(&scb_data->free_scbs); - SLIST_INIT(&scb_data->sg_maps); - - /* Allocate SCB resources */ - scb_data->scbarray = - (struct scb *)malloc(sizeof(struct scb) * AHC_SCB_MAX_ALLOC, - M_DEVBUF, M_NOWAIT); - if (scb_data->scbarray == NULL) - return (ENOMEM); - memset(scb_data->scbarray, 0, sizeof(struct scb) * AHC_SCB_MAX_ALLOC); - - /* Determine the number of hardware SCBs and initialize them */ - - scb_data->maxhscbs = ahc_probe_scbs(ahc); - if ((ahc->flags & AHC_PAGESCBS) != 0) { - /* SCB 0 heads the free list */ - ahc_outb(ahc, FREE_SCBH, 0); - } else { - ahc_outb(ahc, FREE_SCBH, SCB_LIST_NULL); - } - - if (ahc->scb_data->maxhscbs == 0) { - printf("%s: No SCB space found\n", ahc_name(ahc)); - return (ENXIO); - } - - ahc_build_free_scb_list(ahc); - - /* - * Create our DMA tags. These tags define the kinds of device - * accessible memory allocations and memory mappings we will - * need to perform during normal operation. - * - * Unless we need to further restrict the allocation, we rely - * on the restrictions of the parent dmat, hence the common - * use of MAXADDR and MAXSIZE. - */ - - /* DMA tag for our hardware scb structures */ - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, - /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, - /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb), - /*nsegments*/1, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/0, &scb_data->hscb_dmat) != 0) { - goto error_exit; - } - - scb_data->init_level++; - - /* Allocation for our hscbs */ - if (ahc_dmamem_alloc(ahc, scb_data->hscb_dmat, - (void **)&scb_data->hscbs, - BUS_DMA_NOWAIT, &scb_data->hscb_dmamap) != 0) { - goto error_exit; - } - - scb_data->init_level++; - - /* And permanently map them */ - ahc_dmamap_load(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap, - scb_data->hscbs, - AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb), - ahc_dmamap_cb, &scb_data->hscb_busaddr, /*flags*/0); - - scb_data->init_level++; - - /* DMA tag for our sense buffers */ - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, - /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, - /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - AHC_SCB_MAX_ALLOC * sizeof(struct scsi_sense_data), - /*nsegments*/1, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/0, &scb_data->sense_dmat) != 0) { - goto error_exit; - } - - scb_data->init_level++; - - /* Allocate them */ - if (ahc_dmamem_alloc(ahc, scb_data->sense_dmat, - (void **)&scb_data->sense, - BUS_DMA_NOWAIT, &scb_data->sense_dmamap) != 0) { - goto error_exit; - } - - scb_data->init_level++; - - /* And permanently map them */ - ahc_dmamap_load(ahc, scb_data->sense_dmat, scb_data->sense_dmamap, - scb_data->sense, - AHC_SCB_MAX_ALLOC * sizeof(struct scsi_sense_data), - ahc_dmamap_cb, &scb_data->sense_busaddr, /*flags*/0); - - scb_data->init_level++; - - /* DMA tag for our S/G structures. We allocate in page sized chunks */ - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, - /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, - /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - PAGE_SIZE, /*nsegments*/1, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/0, &scb_data->sg_dmat) != 0) { - goto error_exit; - } - - scb_data->init_level++; - - /* Perform initial CCB allocation */ - memset(scb_data->hscbs, 0, - AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb)); - ahc_alloc_scbs(ahc); - - if (scb_data->numscbs == 0) { - printf("%s: ahc_init_scbdata - " - "Unable to allocate initial scbs\n", - ahc_name(ahc)); - goto error_exit; - } - - /* - * Tell the sequencer which SCB will be the next one it receives. - */ - ahc->next_queued_scb = ahc_get_scb(ahc); - ahc_outb(ahc, NEXT_QUEUED_SCB, ahc->next_queued_scb->hscb->tag); - - /* - * Note that we were successfull - */ - return (0); - -error_exit: - - return (ENOMEM); -} - -static void -ahc_fini_scbdata(struct ahc_softc *ahc) -{ - struct scb_data *scb_data; - - scb_data = ahc->scb_data; - if (scb_data == NULL) - return; - - switch (scb_data->init_level) { - default: - case 7: - { - struct sg_map_node *sg_map; - - while ((sg_map = SLIST_FIRST(&scb_data->sg_maps))!= NULL) { - SLIST_REMOVE_HEAD(&scb_data->sg_maps, links); - ahc_dmamap_unload(ahc, scb_data->sg_dmat, - sg_map->sg_dmamap); - ahc_dmamem_free(ahc, scb_data->sg_dmat, - sg_map->sg_vaddr, - sg_map->sg_dmamap); - free(sg_map, M_DEVBUF); - } - ahc_dma_tag_destroy(ahc, scb_data->sg_dmat); - } - case 6: - ahc_dmamap_unload(ahc, scb_data->sense_dmat, - scb_data->sense_dmamap); - case 5: - ahc_dmamem_free(ahc, scb_data->sense_dmat, scb_data->sense, - scb_data->sense_dmamap); - ahc_dmamap_destroy(ahc, scb_data->sense_dmat, - scb_data->sense_dmamap); - case 4: - ahc_dma_tag_destroy(ahc, scb_data->sense_dmat); - case 3: - ahc_dmamap_unload(ahc, scb_data->hscb_dmat, - scb_data->hscb_dmamap); - case 2: - ahc_dmamem_free(ahc, scb_data->hscb_dmat, scb_data->hscbs, - scb_data->hscb_dmamap); - ahc_dmamap_destroy(ahc, scb_data->hscb_dmat, - scb_data->hscb_dmamap); - case 1: - ahc_dma_tag_destroy(ahc, scb_data->hscb_dmat); - break; - case 0: - break; - } - if (scb_data->scbarray != NULL) - free(scb_data->scbarray, M_DEVBUF); -} - -void -ahc_alloc_scbs(struct ahc_softc *ahc) -{ - struct scb_data *scb_data; - struct scb *next_scb; - struct sg_map_node *sg_map; - bus_addr_t physaddr; - struct ahc_dma_seg *segs; - int newcount; - int i; - - scb_data = ahc->scb_data; - if (scb_data->numscbs >= AHC_SCB_MAX_ALLOC) - /* Can't allocate any more */ - return; - - next_scb = &scb_data->scbarray[scb_data->numscbs]; - - sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT); - - if (sg_map == NULL) - return; - - /* Allocate S/G space for the next batch of SCBS */ - if (ahc_dmamem_alloc(ahc, scb_data->sg_dmat, - (void **)&sg_map->sg_vaddr, - BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) { - free(sg_map, M_DEVBUF); - return; - } - - SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links); - - ahc_dmamap_load(ahc, scb_data->sg_dmat, sg_map->sg_dmamap, - sg_map->sg_vaddr, PAGE_SIZE, ahc_dmamap_cb, - &sg_map->sg_physaddr, /*flags*/0); - - segs = sg_map->sg_vaddr; - physaddr = sg_map->sg_physaddr; - - newcount = (PAGE_SIZE / (AHC_NSEG * sizeof(struct ahc_dma_seg))); - newcount = MIN(newcount, (AHC_SCB_MAX_ALLOC - scb_data->numscbs)); - for (i = 0; i < newcount; i++) { - struct scb_platform_data *pdata; -#ifndef __linux__ - int error; -#endif - pdata = (struct scb_platform_data *)malloc(sizeof(*pdata), - M_DEVBUF, M_NOWAIT); - if (pdata == NULL) - break; - next_scb->platform_data = pdata; - next_scb->sg_map = sg_map; - next_scb->sg_list = segs; - /* - * The sequencer always starts with the second entry. - * The first entry is embedded in the scb. - */ - next_scb->sg_list_phys = physaddr + sizeof(struct ahc_dma_seg); - next_scb->ahc_softc = ahc; - next_scb->flags = SCB_FREE; -#ifndef __linux__ - error = ahc_dmamap_create(ahc, ahc->buffer_dmat, /*flags*/0, - &next_scb->dmamap); - if (error != 0) - break; -#endif - next_scb->hscb = &scb_data->hscbs[scb_data->numscbs]; - next_scb->hscb->tag = ahc->scb_data->numscbs; - SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, - next_scb, links.sle); - segs += AHC_NSEG; - physaddr += (AHC_NSEG * sizeof(struct ahc_dma_seg)); - next_scb++; - ahc->scb_data->numscbs++; - } -} - -void -ahc_controller_info(struct ahc_softc *ahc, char *buf) -{ - int len; - - len = sprintf(buf, "%s: ", ahc_chip_names[ahc->chip & AHC_CHIPID_MASK]); - buf += len; - if ((ahc->features & AHC_TWIN) != 0) - len = sprintf(buf, "Twin Channel, A SCSI Id=%d, " - "B SCSI Id=%d, primary %c, ", - ahc->our_id, ahc->our_id_b, - (ahc->flags & AHC_PRIMARY_CHANNEL) + 'A'); - else { - const char *speed; - const char *type; - - speed = ""; - if ((ahc->features & AHC_ULTRA) != 0) { - speed = "Ultra "; - } else if ((ahc->features & AHC_DT) != 0) { - speed = "Ultra160 "; - } else if ((ahc->features & AHC_ULTRA2) != 0) { - speed = "Ultra2 "; - } - if ((ahc->features & AHC_WIDE) != 0) { - type = "Wide"; - } else { - type = "Single"; - } - len = sprintf(buf, "%s%s Channel %c, SCSI Id=%d, ", - speed, type, ahc->channel, ahc->our_id); - } - buf += len; - - if ((ahc->flags & AHC_PAGESCBS) != 0) - sprintf(buf, "%d/%d SCBs", - ahc->scb_data->maxhscbs, AHC_MAX_QUEUE); - else - sprintf(buf, "%d SCBs", ahc->scb_data->maxhscbs); -} - -/* - * Start the board, ready for normal operation - */ -int -ahc_init(struct ahc_softc *ahc) -{ - int max_targ; - int i; - int term; - u_int scsi_conf; - u_int scsiseq_template; - u_int ultraenb; - u_int discenable; - u_int tagenable; - size_t driver_data_size; - uint32_t physaddr; - -#ifdef AHC_DEBUG_SEQUENCER - ahc->flags |= AHC_SEQUENCER_DEBUG; -#endif - -#ifdef AHC_PRINT_SRAM - printf("Scratch Ram:"); - for (i = 0x20; i < 0x5f; i++) { - if (((i % 8) == 0) && (i != 0)) { - printf ("\n "); - } - printf (" 0x%x", ahc_inb(ahc, i)); - } - if ((ahc->features & AHC_MORE_SRAM) != 0) { - for (i = 0x70; i < 0x7f; i++) { - if (((i % 8) == 0) && (i != 0)) { - printf ("\n "); - } - printf (" 0x%x", ahc_inb(ahc, i)); - } - } - printf ("\n"); - /* - * Reading uninitialized scratch ram may - * generate parity errors. - */ - ahc_outb(ahc, CLRINT, CLRPARERR); - ahc_outb(ahc, CLRINT, CLRBRKADRINT); -#endif - max_targ = 15; - - /* - * Assume we have a board at this stage and it has been reset. - */ - if ((ahc->flags & AHC_USEDEFAULTS) != 0) - ahc->our_id = ahc->our_id_b = 7; - - /* - * Default to allowing initiator operations. - */ - ahc->flags |= AHC_INITIATORROLE; - - /* - * Only allow target mode features if this unit has them enabled. - */ - if ((AHC_TMODE_ENABLE & (0x1 << ahc->unit)) == 0) - ahc->features &= ~AHC_TARGETMODE; - -#ifndef __linux__ - /* DMA tag for mapping buffers into device visible space. */ - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, - /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, - /*lowaddr*/BUS_SPACE_MAXADDR, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - /*maxsize*/MAXBSIZE, /*nsegments*/AHC_NSEG, - /*maxsegsz*/AHC_MAXTRANSFER_SIZE, - /*flags*/BUS_DMA_ALLOCNOW, - &ahc->buffer_dmat) != 0) { - return (ENOMEM); - } -#endif - - ahc->init_level++; - - /* - * DMA tag for our command fifos and other data in system memory - * the card's sequencer must be able to access. For initiator - * roles, we need to allocate space for the the qinfifo and qoutfifo. - * The qinfifo and qoutfifo are composed of 256 1 byte elements. - * When providing for the target mode role, we must additionally - * provide space for the incoming target command fifo and an extra - * byte to deal with a dma bug in some chip versions. - */ - driver_data_size = 2 * 256 * sizeof(uint8_t); - if ((ahc->features & AHC_TARGETMODE) != 0) - driver_data_size += AHC_TMODE_CMDS * sizeof(struct target_cmd) - + /*DMA WideOdd Bug Buffer*/1; - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, - /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, - /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - driver_data_size, - /*nsegments*/1, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/0, &ahc->shared_data_dmat) != 0) { - return (ENOMEM); - } - - ahc->init_level++; - - /* Allocation of driver data */ - if (ahc_dmamem_alloc(ahc, ahc->shared_data_dmat, - (void **)&ahc->qoutfifo, - BUS_DMA_NOWAIT, &ahc->shared_data_dmamap) != 0) { - return (ENOMEM); - } - - ahc->init_level++; - - /* And permanently map it in */ - ahc_dmamap_load(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, - ahc->qoutfifo, driver_data_size, ahc_dmamap_cb, - &ahc->shared_data_busaddr, /*flags*/0); - - if ((ahc->features & AHC_TARGETMODE) != 0) { - ahc->targetcmds = (struct target_cmd *)ahc->qoutfifo; - ahc->qoutfifo = (uint8_t *)&ahc->targetcmds[AHC_TMODE_CMDS]; - ahc->dma_bug_buf = ahc->shared_data_busaddr - + driver_data_size - 1; - /* All target command blocks start out invalid. */ - for (i = 0; i < AHC_TMODE_CMDS; i++) - ahc->targetcmds[i].cmd_valid = 0; - ahc_sync_tqinfifo(ahc, BUS_DMASYNC_PREREAD); - ahc->tqinfifonext = 1; - ahc_outb(ahc, KERNEL_TQINPOS, ahc->tqinfifonext - 1); - ahc_outb(ahc, TQINPOS, ahc->tqinfifonext); - ahc->qoutfifo = (uint8_t *)&ahc->targetcmds[256]; - } - ahc->qinfifo = &ahc->qoutfifo[256]; - - ahc->init_level++; - - /* Allocate SCB data now that buffer_dmat is initialized */ - if (ahc->scb_data->maxhscbs == 0) - if (ahc_init_scbdata(ahc) != 0) - return (ENOMEM); - - /* - * Allocate a tstate to house information for our - * initiator presence on the bus as well as the user - * data for any target mode initiator. - */ - if (ahc_alloc_tstate(ahc, ahc->our_id, 'A') == NULL) { - printf("%s: unable to allocate ahc_tmode_tstate. " - "Failing attach\n", ahc_name(ahc)); - return (ENOMEM); - } - - if ((ahc->features & AHC_TWIN) != 0) { - if (ahc_alloc_tstate(ahc, ahc->our_id_b, 'B') == NULL) { - printf("%s: unable to allocate ahc_tmode_tstate. " - "Failing attach\n", ahc_name(ahc)); - return (ENOMEM); - } - } - - ahc_outb(ahc, SEQ_FLAGS, 0); - ahc_outb(ahc, SEQ_FLAGS2, 0); - - if (ahc->scb_data->maxhscbs < AHC_SCB_MAX_ALLOC) { - ahc->flags |= AHC_PAGESCBS; - } else { - ahc->flags &= ~AHC_PAGESCBS; - } - -#ifdef AHC_DEBUG - if (ahc_debug & AHC_SHOWMISC) { - printf("%s: hardware scb %d bytes; kernel scb %d bytes; " - "ahc_dma %d bytes\n", - ahc_name(ahc), - sizeof(struct hardware_scb), - sizeof(struct scb), - sizeof(struct ahc_dma_seg)); - } -#endif /* AHC_DEBUG */ - - /* Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1, for both channels*/ - if (ahc->features & AHC_TWIN) { - - /* - * The device is gated to channel B after a chip reset, - * so set those values first - */ - ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) | SELBUSB); - term = (ahc->flags & AHC_TERM_ENB_B) != 0 ? STPWEN : 0; - ahc_outb(ahc, SCSIID, ahc->our_id_b); - scsi_conf = ahc_inb(ahc, SCSICONF + 1); - ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL)) - |term|ahc->seltime_b|ENSTIMER|ACTNEGEN); - if ((ahc->features & AHC_ULTRA2) != 0) - ahc_outb(ahc, SIMODE0, ahc_inb(ahc, SIMODE0)|ENIOERR); - ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR); - ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN); - - if ((scsi_conf & RESET_SCSI) != 0 - && (ahc->flags & AHC_INITIATORROLE) != 0) - ahc->flags |= AHC_RESET_BUS_B; - - /* Select Channel A */ - ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~SELBUSB); - } - term = (ahc->flags & AHC_TERM_ENB_A) != 0 ? STPWEN : 0; - if ((ahc->features & AHC_ULTRA2) != 0) - ahc_outb(ahc, SCSIID_ULTRA2, ahc->our_id); - else - ahc_outb(ahc, SCSIID, ahc->our_id); - scsi_conf = ahc_inb(ahc, SCSICONF); - ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL)) - |term|ahc->seltime - |ENSTIMER|ACTNEGEN); - if ((ahc->features & AHC_ULTRA2) != 0) - ahc_outb(ahc, SIMODE0, ahc_inb(ahc, SIMODE0)|ENIOERR); - ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR); - ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN); - - if ((scsi_conf & RESET_SCSI) != 0 - && (ahc->flags & AHC_INITIATORROLE) != 0) - ahc->flags |= AHC_RESET_BUS_A; - - /* - * Look at the information that board initialization or - * the board bios has left us. - */ - ultraenb = 0; - tagenable = ALL_TARGETS_MASK; - - /* Grab the disconnection disable table and invert it for our needs */ - if ((ahc->flags & AHC_USEDEFAULTS) != 0) { - printf("%s: Host Adapter Bios disabled. Using default SCSI " - "device parameters\n", ahc_name(ahc)); - ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B| - AHC_TERM_ENB_A|AHC_TERM_ENB_B; - discenable = ALL_TARGETS_MASK; - if ((ahc->features & AHC_ULTRA) != 0) - ultraenb = ALL_TARGETS_MASK; - } else { - discenable = ~((ahc_inb(ahc, DISC_DSB + 1) << 8) - | ahc_inb(ahc, DISC_DSB)); - if ((ahc->features & (AHC_ULTRA|AHC_ULTRA2)) != 0) - ultraenb = (ahc_inb(ahc, ULTRA_ENB + 1) << 8) - | ahc_inb(ahc, ULTRA_ENB); - } - - if ((ahc->features & (AHC_WIDE|AHC_TWIN)) == 0) - max_targ = 7; - - for (i = 0; i <= max_targ; i++) { - struct ahc_initiator_tinfo *tinfo; - struct ahc_tmode_tstate *tstate; - u_int our_id; - u_int target_id; - char channel; - - channel = 'A'; - our_id = ahc->our_id; - target_id = i; - if (i > 7 && (ahc->features & AHC_TWIN) != 0) { - channel = 'B'; - our_id = ahc->our_id_b; - target_id = i % 8; - } - tinfo = ahc_fetch_transinfo(ahc, channel, our_id, - target_id, &tstate); - /* Default to async narrow across the board */ - memset(tinfo, 0, sizeof(*tinfo)); - if (ahc->flags & AHC_USEDEFAULTS) { - if ((ahc->features & AHC_WIDE) != 0) - tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT; - - /* - * These will be truncated when we determine the - * connection type we have with the target. - */ - tinfo->user.period = ahc_syncrates->period; - tinfo->user.offset = ~0; - } else { - u_int scsirate; - uint16_t mask; - - /* Take the settings leftover in scratch RAM. */ - scsirate = ahc_inb(ahc, TARG_SCSIRATE + i); - mask = (0x01 << i); - if ((ahc->features & AHC_ULTRA2) != 0) { - u_int offset; - u_int maxsync; - - if ((scsirate & SOFS) == 0x0F) { - /* - * Haven't negotiated yet, - * so the format is different. - */ - scsirate = (scsirate & SXFR) >> 4 - | (ultraenb & mask) - ? 0x08 : 0x0 - | (scsirate & WIDEXFER); - offset = MAX_OFFSET_ULTRA2; - } else - offset = ahc_inb(ahc, TARG_OFFSET + i); - if ((scsirate & ~WIDEXFER) == 0 && offset != 0) - /* Set to the lowest sync rate, 5MHz */ - scsirate |= 0x1c; - maxsync = AHC_SYNCRATE_ULTRA2; - if ((ahc->features & AHC_DT) != 0) - maxsync = AHC_SYNCRATE_DT; - tinfo->user.period = - ahc_find_period(ahc, scsirate, maxsync); - if (offset == 0) - tinfo->user.period = 0; - else - tinfo->user.offset = ~0; - if ((scsirate & SXFR_ULTRA2) <= 8/*10MHz*/ - && (ahc->features & AHC_DT) != 0) - tinfo->user.ppr_options = - MSG_EXT_PPR_DT_REQ; - } else if ((scsirate & SOFS) != 0) { - if ((scsirate & SXFR) == 0x40 - && (ultraenb & mask) != 0) { - /* Treat 10MHz as a non-ultra speed */ - scsirate &= ~SXFR; - ultraenb &= ~mask; - } - tinfo->user.period = - ahc_find_period(ahc, scsirate, - (ultraenb & mask) - ? AHC_SYNCRATE_ULTRA - : AHC_SYNCRATE_FAST); - if (tinfo->user.period != 0) - tinfo->user.offset = ~0; - } - if (tinfo->user.period == 0) - tinfo->user.offset = 0; - if ((scsirate & WIDEXFER) != 0 - && (ahc->features & AHC_WIDE) != 0) - tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT; - tinfo->user.protocol_version = 4; - if ((ahc->features & AHC_DT) != 0) - tinfo->user.transport_version = 3; - else - tinfo->user.transport_version = 2; - tinfo->goal.protocol_version = 2; - tinfo->goal.transport_version = 2; - tinfo->curr.protocol_version = 2; - tinfo->curr.transport_version = 2; - } - tstate->ultraenb = ultraenb; - } - ahc->user_discenable = discenable; - ahc->user_tagenable = tagenable; - - /* There are no untagged SCBs active yet. */ - for (i = 0; i < 16; i++) { - ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, 0)); - if ((ahc->flags & AHC_SCB_BTT) != 0) { - int lun; - - /* - * The SCB based BTT allows an entry per - * target and lun pair. - */ - for (lun = 1; lun < AHC_NUM_LUNS; lun++) - ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, lun)); - } - } - - /* All of our queues are empty */ - for (i = 0; i < 256; i++) - ahc->qoutfifo[i] = SCB_LIST_NULL; - ahc_sync_qoutfifo(ahc, BUS_DMASYNC_PREREAD); - - for (i = 0; i < 256; i++) - ahc->qinfifo[i] = SCB_LIST_NULL; - - if ((ahc->features & AHC_MULTI_TID) != 0) { - ahc_outb(ahc, TARGID, 0); - ahc_outb(ahc, TARGID + 1, 0); - } - - /* - * Tell the sequencer where it can find our arrays in memory. - */ - physaddr = ahc->scb_data->hscb_busaddr; - ahc_outb(ahc, HSCB_ADDR, physaddr & 0xFF); - ahc_outb(ahc, HSCB_ADDR + 1, (physaddr >> 8) & 0xFF); - ahc_outb(ahc, HSCB_ADDR + 2, (physaddr >> 16) & 0xFF); - ahc_outb(ahc, HSCB_ADDR + 3, (physaddr >> 24) & 0xFF); - - physaddr = ahc->shared_data_busaddr; - ahc_outb(ahc, SHARED_DATA_ADDR, physaddr & 0xFF); - ahc_outb(ahc, SHARED_DATA_ADDR + 1, (physaddr >> 8) & 0xFF); - ahc_outb(ahc, SHARED_DATA_ADDR + 2, (physaddr >> 16) & 0xFF); - ahc_outb(ahc, SHARED_DATA_ADDR + 3, (physaddr >> 24) & 0xFF); - - /* - * Initialize the group code to command length table. - * This overrides the values in TARG_SCSIRATE, so only - * setup the table after we have processed that information. - */ - ahc_outb(ahc, CMDSIZE_TABLE, 5); - ahc_outb(ahc, CMDSIZE_TABLE + 1, 9); - ahc_outb(ahc, CMDSIZE_TABLE + 2, 9); - ahc_outb(ahc, CMDSIZE_TABLE + 3, 0); - ahc_outb(ahc, CMDSIZE_TABLE + 4, 15); - ahc_outb(ahc, CMDSIZE_TABLE + 5, 11); - ahc_outb(ahc, CMDSIZE_TABLE + 6, 0); - ahc_outb(ahc, CMDSIZE_TABLE + 7, 0); - - /* Tell the sequencer of our initial queue positions */ - ahc_outb(ahc, KERNEL_QINPOS, 0); - ahc_outb(ahc, QINPOS, 0); - ahc_outb(ahc, QOUTPOS, 0); - - /* - * Use the built in queue management registers - * if they are available. - */ - if ((ahc->features & AHC_QUEUE_REGS) != 0) { - ahc_outb(ahc, QOFF_CTLSTA, SCB_QSIZE_256); - ahc_outb(ahc, SDSCB_QOFF, 0); - ahc_outb(ahc, SNSCB_QOFF, 0); - ahc_outb(ahc, HNSCB_QOFF, 0); - } - - - /* We don't have any waiting selections */ - ahc_outb(ahc, WAITING_SCBH, SCB_LIST_NULL); - - /* Our disconnection list is empty too */ - ahc_outb(ahc, DISCONNECTED_SCBH, SCB_LIST_NULL); - - /* Message out buffer starts empty */ - ahc_outb(ahc, MSG_OUT, MSG_NOOP); - - /* - * Setup the allowed SCSI Sequences based on operational mode. - * If we are a target, we'll enalbe select in operations once - * we've had a lun enabled. - */ - scsiseq_template = ENSELO|ENAUTOATNO|ENAUTOATNP; - if ((ahc->flags & AHC_INITIATORROLE) != 0) - scsiseq_template |= ENRSELI; - ahc_outb(ahc, SCSISEQ_TEMPLATE, scsiseq_template); - - /* - * Load the Sequencer program and Enable the adapter - * in "fast" mode. - */ - if (bootverbose) - printf("%s: Downloading Sequencer Program...", - ahc_name(ahc)); - - ahc_loadseq(ahc); - - if ((ahc->features & AHC_ULTRA2) != 0) { - int wait; - - /* - * Wait for up to 500ms for our transceivers - * to settle. If the adapter does not have - * a cable attached, the tranceivers may - * never settle, so don't complain if we - * fail here. - */ - ahc_pause(ahc); - for (wait = 5000; - (ahc_inb(ahc, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait; - wait--) - ahc_delay(100); - ahc_unpause(ahc); - } - return (0); -} - -void -ahc_intr_enable(struct ahc_softc *ahc, int enable) -{ - u_int hcntrl; - - hcntrl = ahc_inb(ahc, HCNTRL); - hcntrl &= ~INTEN; - ahc->pause &= ~INTEN; - ahc->unpause &= ~INTEN; - if (enable) { - hcntrl |= INTEN; - ahc->pause |= INTEN; - ahc->unpause |= INTEN; - } - ahc_outb(ahc, HCNTRL, hcntrl); -} - -/* - * Ensure that the card is paused in a location - * outside of all critical sections and that all - * pending work is completed prior to returning. - * This routine should only be called from outside - * an interrupt context. - */ -void -ahc_pause_and_flushwork(struct ahc_softc *ahc) -{ - int intstat; - int maxloops; - - maxloops = 1000; - ahc->flags |= AHC_ALL_INTERRUPTS; - intstat = 0; - do { - ahc_intr(ahc); - ahc_pause(ahc); - ahc_clear_critical_section(ahc); - if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0) - break; - maxloops--; - } while (((intstat = ahc_inb(ahc, INTSTAT)) & INT_PEND) && --maxloops); - if (maxloops == 0) { - printf("Infinite interrupt loop, INTSTAT = %x", - ahc_inb(ahc, INTSTAT)); - } - ahc_platform_flushwork(ahc); - ahc->flags &= ~AHC_ALL_INTERRUPTS; -} - -int -ahc_suspend(struct ahc_softc *ahc) -{ - uint8_t *ptr; - int i; - - ahc_pause_and_flushwork(ahc); - - if (LIST_FIRST(&ahc->pending_scbs) != NULL) - return (EBUSY); - -#if AHC_TARGET_MODE - /* - * XXX What about ATIOs that have not yet been serviced? - * Perhaps we should just refuse to be suspended if we - * are acting in a target role. - */ - if (ahc->pending_device != NULL) - return (EBUSY); -#endif - - /* Save volatile registers */ - if ((ahc->features & AHC_TWIN) != 0) { - ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) | SELBUSB); - ahc->suspend_state.channel[1].scsiseq = ahc_inb(ahc, SCSISEQ); - ahc->suspend_state.channel[1].sxfrctl0 = ahc_inb(ahc, SXFRCTL0); - ahc->suspend_state.channel[1].sxfrctl1 = ahc_inb(ahc, SXFRCTL1); - ahc->suspend_state.channel[1].simode0 = ahc_inb(ahc, SIMODE0); - ahc->suspend_state.channel[1].simode1 = ahc_inb(ahc, SIMODE1); - ahc->suspend_state.channel[1].seltimer = ahc_inb(ahc, SELTIMER); - ahc->suspend_state.channel[1].seqctl = ahc_inb(ahc, SEQCTL); - ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~SELBUSB); - } - ahc->suspend_state.channel[0].scsiseq = ahc_inb(ahc, SCSISEQ); - ahc->suspend_state.channel[0].sxfrctl0 = ahc_inb(ahc, SXFRCTL0); - ahc->suspend_state.channel[0].sxfrctl1 = ahc_inb(ahc, SXFRCTL1); - ahc->suspend_state.channel[0].simode0 = ahc_inb(ahc, SIMODE0); - ahc->suspend_state.channel[0].simode1 = ahc_inb(ahc, SIMODE1); - ahc->suspend_state.channel[0].seltimer = ahc_inb(ahc, SELTIMER); - ahc->suspend_state.channel[0].seqctl = ahc_inb(ahc, SEQCTL); - - if ((ahc->chip & AHC_PCI) != 0) { - ahc->suspend_state.dscommand0 = ahc_inb(ahc, DSCOMMAND0); - ahc->suspend_state.dspcistatus = ahc_inb(ahc, DSPCISTATUS); - } - - if ((ahc->features & AHC_DT) != 0) { - u_int sfunct; - - sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; - ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); - ahc->suspend_state.optionmode = ahc_inb(ahc, OPTIONMODE); - ahc_outb(ahc, SFUNCT, sfunct); - ahc->suspend_state.crccontrol1 = ahc_inb(ahc, CRCCONTROL1); - } - - if ((ahc->features & AHC_MULTI_FUNC) != 0) - ahc->suspend_state.scbbaddr = ahc_inb(ahc, SCBBADDR); - - if ((ahc->features & AHC_ULTRA2) != 0) - ahc->suspend_state.dff_thrsh = ahc_inb(ahc, DFF_THRSH); - - ptr = ahc->suspend_state.scratch_ram; - for (i = 0; i < 64; i++) - *ptr++ = ahc_inb(ahc, SRAM_BASE + i); - - if ((ahc->features & AHC_MORE_SRAM) != 0) { - for (i = 0; i < 16; i++) - *ptr++ = ahc_inb(ahc, TARG_OFFSET + i); - } - - ptr = ahc->suspend_state.btt; - if ((ahc->flags & AHC_SCB_BTT) != 0) { - for (i = 0;i < AHC_NUM_TARGETS; i++) { - int j; - - for (j = 0;j < AHC_NUM_LUNS; j++) { - u_int tcl; - - tcl = BUILD_TCL(i << 4, j); - *ptr = ahc_index_busy_tcl(ahc, tcl); - } - } - } - ahc_shutdown(ahc); - return (0); -} - -int -ahc_resume(struct ahc_softc *ahc) -{ - uint8_t *ptr; - int i; - - ahc_reset(ahc); - - ahc_build_free_scb_list(ahc); - - /* Restore volatile registers */ - if ((ahc->features & AHC_TWIN) != 0) { - ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) | SELBUSB); - ahc_outb(ahc, SCSIID, ahc->our_id); - ahc_outb(ahc, SCSISEQ, ahc->suspend_state.channel[1].scsiseq); - ahc_outb(ahc, SXFRCTL0, ahc->suspend_state.channel[1].sxfrctl0); - ahc_outb(ahc, SXFRCTL1, ahc->suspend_state.channel[1].sxfrctl1); - ahc_outb(ahc, SIMODE0, ahc->suspend_state.channel[1].simode0); - ahc_outb(ahc, SIMODE1, ahc->suspend_state.channel[1].simode1); - ahc_outb(ahc, SELTIMER, ahc->suspend_state.channel[1].seltimer); - ahc_outb(ahc, SEQCTL, ahc->suspend_state.channel[1].seqctl); - ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~SELBUSB); - } - ahc_outb(ahc, SCSISEQ, ahc->suspend_state.channel[0].scsiseq); - ahc_outb(ahc, SXFRCTL0, ahc->suspend_state.channel[0].sxfrctl0); - ahc_outb(ahc, SXFRCTL1, ahc->suspend_state.channel[0].sxfrctl1); - ahc_outb(ahc, SIMODE0, ahc->suspend_state.channel[0].simode0); - ahc_outb(ahc, SIMODE1, ahc->suspend_state.channel[0].simode1); - ahc_outb(ahc, SELTIMER, ahc->suspend_state.channel[0].seltimer); - ahc_outb(ahc, SEQCTL, ahc->suspend_state.channel[0].seqctl); - if ((ahc->features & AHC_ULTRA2) != 0) - ahc_outb(ahc, SCSIID_ULTRA2, ahc->our_id); - else - ahc_outb(ahc, SCSIID, ahc->our_id); - - if ((ahc->chip & AHC_PCI) != 0) { - ahc_outb(ahc, DSCOMMAND0, ahc->suspend_state.dscommand0); - ahc_outb(ahc, DSPCISTATUS, ahc->suspend_state.dspcistatus); - } - - if ((ahc->features & AHC_DT) != 0) { - u_int sfunct; - - sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; - ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); - ahc_outb(ahc, OPTIONMODE, ahc->suspend_state.optionmode); - ahc_outb(ahc, SFUNCT, sfunct); - ahc_outb(ahc, CRCCONTROL1, ahc->suspend_state.crccontrol1); - } - - if ((ahc->features & AHC_MULTI_FUNC) != 0) - ahc_outb(ahc, SCBBADDR, ahc->suspend_state.scbbaddr); - - if ((ahc->features & AHC_ULTRA2) != 0) - ahc_outb(ahc, DFF_THRSH, ahc->suspend_state.dff_thrsh); - - ptr = ahc->suspend_state.scratch_ram; - for (i = 0; i < 64; i++) - ahc_outb(ahc, SRAM_BASE + i, *ptr++); - - if ((ahc->features & AHC_MORE_SRAM) != 0) { - for (i = 0; i < 16; i++) - ahc_outb(ahc, TARG_OFFSET + i, *ptr++); - } - - ptr = ahc->suspend_state.btt; - if ((ahc->flags & AHC_SCB_BTT) != 0) { - for (i = 0;i < AHC_NUM_TARGETS; i++) { - int j; - - for (j = 0;j < AHC_NUM_LUNS; j++) { - u_int tcl; - - tcl = BUILD_TCL(i << 4, j); - ahc_busy_tcl(ahc, tcl, *ptr); - } - } - } - return (0); -} - -/************************** Busy Target Table *********************************/ -/* - * Return the untagged transaction id for a given target/channel lun. - * Optionally, clear the entry. - */ -u_int -ahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl) -{ - u_int scbid; - u_int target_offset; - - if ((ahc->flags & AHC_SCB_BTT) != 0) { - u_int saved_scbptr; - - saved_scbptr = ahc_inb(ahc, SCBPTR); - ahc_outb(ahc, SCBPTR, TCL_LUN(tcl)); - scbid = ahc_inb(ahc, SCB_64_BTT + TCL_TARGET_OFFSET(tcl)); - ahc_outb(ahc, SCBPTR, saved_scbptr); - } else { - target_offset = TCL_TARGET_OFFSET(tcl); - scbid = ahc_inb(ahc, BUSY_TARGETS + target_offset); - } - - return (scbid); -} - -void -ahc_unbusy_tcl(struct ahc_softc *ahc, u_int tcl) -{ - u_int target_offset; - - if ((ahc->flags & AHC_SCB_BTT) != 0) { - u_int saved_scbptr; - - saved_scbptr = ahc_inb(ahc, SCBPTR); - ahc_outb(ahc, SCBPTR, TCL_LUN(tcl)); - ahc_outb(ahc, SCB_64_BTT+TCL_TARGET_OFFSET(tcl), SCB_LIST_NULL); - ahc_outb(ahc, SCBPTR, saved_scbptr); - } else { - target_offset = TCL_TARGET_OFFSET(tcl); - ahc_outb(ahc, BUSY_TARGETS + target_offset, SCB_LIST_NULL); - } -} - -void -ahc_busy_tcl(struct ahc_softc *ahc, u_int tcl, u_int scbid) -{ - u_int target_offset; - - if ((ahc->flags & AHC_SCB_BTT) != 0) { - u_int saved_scbptr; - - saved_scbptr = ahc_inb(ahc, SCBPTR); - ahc_outb(ahc, SCBPTR, TCL_LUN(tcl)); - ahc_outb(ahc, SCB_64_BTT + TCL_TARGET_OFFSET(tcl), scbid); - ahc_outb(ahc, SCBPTR, saved_scbptr); - } else { - target_offset = TCL_TARGET_OFFSET(tcl); - ahc_outb(ahc, BUSY_TARGETS + target_offset, scbid); - } -} - -/************************** SCB and SCB queue management **********************/ -int -ahc_match_scb(struct ahc_softc *ahc, struct scb *scb, int target, - char channel, int lun, u_int tag, role_t role) -{ - int targ = SCB_GET_TARGET(ahc, scb); - char chan = SCB_GET_CHANNEL(ahc, scb); - int slun = SCB_GET_LUN(scb); - int match; - - match = ((chan == channel) || (channel == ALL_CHANNELS)); - if (match != 0) - match = ((targ == target) || (target == CAM_TARGET_WILDCARD)); - if (match != 0) - match = ((lun == slun) || (lun == CAM_LUN_WILDCARD)); - if (match != 0) { -#if AHC_TARGET_MODE - int group; - - group = XPT_FC_GROUP(scb->io_ctx->ccb_h.func_code); - if (role == ROLE_INITIATOR) { - match = (group != XPT_FC_GROUP_TMODE) - && ((tag == scb->hscb->tag) - || (tag == SCB_LIST_NULL)); - } else if (role == ROLE_TARGET) { - match = (group == XPT_FC_GROUP_TMODE) - && ((tag == scb->io_ctx->csio.tag_id) - || (tag == SCB_LIST_NULL)); - } -#else /* !AHC_TARGET_MODE */ - match = ((tag == scb->hscb->tag) || (tag == SCB_LIST_NULL)); -#endif /* AHC_TARGET_MODE */ - } - - return match; -} - -void -ahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb) -{ - int target; - char channel; - int lun; - - target = SCB_GET_TARGET(ahc, scb); - lun = SCB_GET_LUN(scb); - channel = SCB_GET_CHANNEL(ahc, scb); - - ahc_search_qinfifo(ahc, target, channel, lun, - /*tag*/SCB_LIST_NULL, ROLE_UNKNOWN, - CAM_REQUEUE_REQ, SEARCH_COMPLETE); - - ahc_platform_freeze_devq(ahc, scb); -} - -void -ahc_qinfifo_requeue_tail(struct ahc_softc *ahc, struct scb *scb) -{ - struct scb *prev_scb; - - prev_scb = NULL; - if (ahc_qinfifo_count(ahc) != 0) { - u_int prev_tag; - uint8_t prev_pos; - - prev_pos = ahc->qinfifonext - 1; - prev_tag = ahc->qinfifo[prev_pos]; - prev_scb = ahc_lookup_scb(ahc, prev_tag); - } - ahc_qinfifo_requeue(ahc, prev_scb, scb); - if ((ahc->features & AHC_QUEUE_REGS) != 0) { - ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext); - } else { - ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext); - } -} - -static void -ahc_qinfifo_requeue(struct ahc_softc *ahc, struct scb *prev_scb, - struct scb *scb) -{ - if (prev_scb == NULL) { - ahc_outb(ahc, NEXT_QUEUED_SCB, scb->hscb->tag); - } else { - prev_scb->hscb->next = scb->hscb->tag; - ahc_sync_scb(ahc, prev_scb, - BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); - } - ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag; - scb->hscb->next = ahc->next_queued_scb->hscb->tag; - ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); -} - -static int -ahc_qinfifo_count(struct ahc_softc *ahc) -{ - u_int8_t qinpos; - u_int8_t diff; - - if ((ahc->features & AHC_QUEUE_REGS) != 0) { - qinpos = ahc_inb(ahc, SNSCB_QOFF); - ahc_outb(ahc, SNSCB_QOFF, qinpos); - } else - qinpos = ahc_inb(ahc, QINPOS); - diff = ahc->qinfifonext - qinpos; - return (diff); -} - -int -ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, - int lun, u_int tag, role_t role, uint32_t status, - ahc_search_action action) -{ - struct scb *scb; - struct scb *prev_scb; - uint8_t qinstart; - uint8_t qinpos; - uint8_t qintail; - uint8_t next; - uint8_t prev; - uint8_t curscbptr; - int found; - int have_qregs; - - qintail = ahc->qinfifonext; - have_qregs = (ahc->features & AHC_QUEUE_REGS) != 0; - if (have_qregs) { - qinstart = ahc_inb(ahc, SNSCB_QOFF); - ahc_outb(ahc, SNSCB_QOFF, qinstart); - } else - qinstart = ahc_inb(ahc, QINPOS); - qinpos = qinstart; - found = 0; - prev_scb = NULL; - - if (action == SEARCH_COMPLETE) { - /* - * Don't attempt to run any queued untagged transactions - * until we are done with the abort process. - */ - ahc_freeze_untagged_queues(ahc); - } - - /* - * Start with an empty queue. Entries that are not chosen - * for removal will be re-added to the queue as we go. - */ - ahc->qinfifonext = qinpos; - ahc_outb(ahc, NEXT_QUEUED_SCB, ahc->next_queued_scb->hscb->tag); - - while (qinpos != qintail) { - scb = ahc_lookup_scb(ahc, ahc->qinfifo[qinpos]); - if (scb == NULL) { - printf("qinpos = %d, SCB index = %d\n", - qinpos, ahc->qinfifo[qinpos]); - panic("Loop 1\n"); - } - - if (ahc_match_scb(ahc, scb, target, channel, lun, tag, role)) { - /* - * We found an scb that needs to be acted on. - */ - found++; - switch (action) { - case SEARCH_COMPLETE: - { - cam_status ostat; - cam_status cstat; - - ostat = ahc_get_transaction_status(scb); - if (ostat == CAM_REQ_INPROG) - ahc_set_transaction_status(scb, status); - cstat = ahc_get_transaction_status(scb); - if (cstat != CAM_REQ_CMP) - ahc_freeze_scb(scb); - if ((scb->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB in qinfifo\n"); - ahc_done(ahc, scb); - - /* FALLTHROUGH */ - } - case SEARCH_REMOVE: - break; - case SEARCH_COUNT: - ahc_qinfifo_requeue(ahc, prev_scb, scb); - prev_scb = scb; - break; - } - } else { - ahc_qinfifo_requeue(ahc, prev_scb, scb); - prev_scb = scb; - } - qinpos++; - } - - if ((ahc->features & AHC_QUEUE_REGS) != 0) { - ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext); - } else { - ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext); - } - - if (action != SEARCH_COUNT - && (found != 0) - && (qinstart != ahc->qinfifonext)) { - /* - * The sequencer may be in the process of dmaing - * down the SCB at the beginning of the queue. - * This could be problematic if either the first, - * or the second SCB is removed from the queue - * (the first SCB includes a pointer to the "next" - * SCB to dma). If we have removed any entries, swap - * the first element in the queue with the next HSCB - * so the sequencer will notice that NEXT_QUEUED_SCB - * has changed during its dma attempt and will retry - * the DMA. - */ - scb = ahc_lookup_scb(ahc, ahc->qinfifo[qinstart]); - - if (scb == NULL) { - printf("found = %d, qinstart = %d, qinfifionext = %d\n", - found, qinstart, ahc->qinfifonext); - panic("First/Second Qinfifo fixup\n"); - } - /* - * ahc_swap_with_next_hscb forces our next pointer to - * point to the reserved SCB for future commands. Save - * and restore our original next pointer to maintain - * queue integrity. - */ - next = scb->hscb->next; - ahc->scb_data->scbindex[scb->hscb->tag] = NULL; - ahc_swap_with_next_hscb(ahc, scb); - scb->hscb->next = next; - ahc->qinfifo[qinstart] = scb->hscb->tag; - - /* Tell the card about the new head of the qinfifo. */ - ahc_outb(ahc, NEXT_QUEUED_SCB, scb->hscb->tag); - - /* Fixup the tail "next" pointer. */ - qintail = ahc->qinfifonext - 1; - scb = ahc_lookup_scb(ahc, ahc->qinfifo[qintail]); - scb->hscb->next = ahc->next_queued_scb->hscb->tag; - } - - /* - * Search waiting for selection list. - */ - curscbptr = ahc_inb(ahc, SCBPTR); - next = ahc_inb(ahc, WAITING_SCBH); /* Start at head of list. */ - prev = SCB_LIST_NULL; - - while (next != SCB_LIST_NULL) { - uint8_t scb_index; - - ahc_outb(ahc, SCBPTR, next); - scb_index = ahc_inb(ahc, SCB_TAG); - if (scb_index >= ahc->scb_data->numscbs) { - printf("Waiting List inconsistency. " - "SCB index == %d, yet numscbs == %d.", - scb_index, ahc->scb_data->numscbs); - ahc_dump_card_state(ahc); - panic("for safety"); - } - scb = ahc_lookup_scb(ahc, scb_index); - if (scb == NULL) { - printf("scb_index = %d, next = %d\n", - scb_index, next); - panic("Waiting List traversal\n"); - } - if (ahc_match_scb(ahc, scb, target, channel, - lun, SCB_LIST_NULL, role)) { - /* - * We found an scb that needs to be acted on. - */ - found++; - switch (action) { - case SEARCH_COMPLETE: - { - cam_status ostat; - cam_status cstat; - - ostat = ahc_get_transaction_status(scb); - if (ostat == CAM_REQ_INPROG) - ahc_set_transaction_status(scb, - status); - cstat = ahc_get_transaction_status(scb); - if (cstat != CAM_REQ_CMP) - ahc_freeze_scb(scb); - if ((scb->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB in Waiting List\n"); - ahc_done(ahc, scb); - /* FALLTHROUGH */ - } - case SEARCH_REMOVE: - next = ahc_rem_wscb(ahc, next, prev); - break; - case SEARCH_COUNT: - prev = next; - next = ahc_inb(ahc, SCB_NEXT); - break; - } - } else { - - prev = next; - next = ahc_inb(ahc, SCB_NEXT); - } - } - ahc_outb(ahc, SCBPTR, curscbptr); - - found += ahc_search_untagged_queues(ahc, /*ahc_io_ctx_t*/NULL, target, - channel, lun, status, action); - - if (action == SEARCH_COMPLETE) - ahc_release_untagged_queues(ahc); - return (found); -} - -int -ahc_search_untagged_queues(struct ahc_softc *ahc, ahc_io_ctx_t ctx, - int target, char channel, int lun, uint32_t status, - ahc_search_action action) -{ - struct scb *scb; - int maxtarget; - int found; - int i; - - if (action == SEARCH_COMPLETE) { - /* - * Don't attempt to run any queued untagged transactions - * until we are done with the abort process. - */ - ahc_freeze_untagged_queues(ahc); - } - - found = 0; - i = 0; - if ((ahc->flags & AHC_SCB_BTT) == 0) { - - maxtarget = 16; - if (target != CAM_TARGET_WILDCARD) { - - i = target; - if (channel == 'B') - i += 8; - maxtarget = i + 1; - } - } else { - maxtarget = 0; - } - - for (; i < maxtarget; i++) { - struct scb_tailq *untagged_q; - struct scb *next_scb; - - untagged_q = &(ahc->untagged_queues[i]); - next_scb = TAILQ_FIRST(untagged_q); - while (next_scb != NULL) { - - scb = next_scb; - next_scb = TAILQ_NEXT(scb, links.tqe); - - /* - * The head of the list may be the currently - * active untagged command for a device. - * We're only searching for commands that - * have not been started. A transaction - * marked active but still in the qinfifo - * is removed by the qinfifo scanning code - * above. - */ - if ((scb->flags & SCB_ACTIVE) != 0) - continue; - - if (ahc_match_scb(ahc, scb, target, channel, lun, - SCB_LIST_NULL, ROLE_INITIATOR) == 0 - || (ctx != NULL && ctx != scb->io_ctx)) - continue; - - /* - * We found an scb that needs to be acted on. - */ - found++; - switch (action) { - case SEARCH_COMPLETE: - { - cam_status ostat; - cam_status cstat; - - ostat = ahc_get_transaction_status(scb); - if (ostat == CAM_REQ_INPROG) - ahc_set_transaction_status(scb, status); - cstat = ahc_get_transaction_status(scb); - if (cstat != CAM_REQ_CMP) - ahc_freeze_scb(scb); - if ((scb->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB in untaggedQ\n"); - ahc_done(ahc, scb); - break; - } - case SEARCH_REMOVE: - TAILQ_REMOVE(untagged_q, scb, links.tqe); - break; - case SEARCH_COUNT: - break; - } - } - } - - if (action == SEARCH_COMPLETE) - ahc_release_untagged_queues(ahc); - return (found); -} - -int -ahc_search_disc_list(struct ahc_softc *ahc, int target, char channel, - int lun, u_int tag, int stop_on_first, int remove, - int save_state) -{ - struct scb *scbp; - u_int next; - u_int prev; - u_int count; - u_int active_scb; - - count = 0; - next = ahc_inb(ahc, DISCONNECTED_SCBH); - prev = SCB_LIST_NULL; - - if (save_state) { - /* restore this when we're done */ - active_scb = ahc_inb(ahc, SCBPTR); - } else - /* Silence compiler */ - active_scb = SCB_LIST_NULL; - - while (next != SCB_LIST_NULL) { - u_int scb_index; - - ahc_outb(ahc, SCBPTR, next); - scb_index = ahc_inb(ahc, SCB_TAG); - if (scb_index >= ahc->scb_data->numscbs) { - printf("Disconnected List inconsistency. " - "SCB index == %d, yet numscbs == %d.", - scb_index, ahc->scb_data->numscbs); - ahc_dump_card_state(ahc); - panic("for safety"); - } - - if (next == prev) { - panic("Disconnected List Loop. " - "cur SCBPTR == %x, prev SCBPTR == %x.", - next, prev); - } - scbp = ahc_lookup_scb(ahc, scb_index); - if (ahc_match_scb(ahc, scbp, target, channel, lun, - tag, ROLE_INITIATOR)) { - count++; - if (remove) { - next = - ahc_rem_scb_from_disc_list(ahc, prev, next); - } else { - prev = next; - next = ahc_inb(ahc, SCB_NEXT); - } - if (stop_on_first) - break; - } else { - prev = next; - next = ahc_inb(ahc, SCB_NEXT); - } - } - if (save_state) - ahc_outb(ahc, SCBPTR, active_scb); - return (count); -} - -/* - * Remove an SCB from the on chip list of disconnected transactions. - * This is empty/unused if we are not performing SCB paging. - */ -static u_int -ahc_rem_scb_from_disc_list(struct ahc_softc *ahc, u_int prev, u_int scbptr) -{ - u_int next; - - ahc_outb(ahc, SCBPTR, scbptr); - next = ahc_inb(ahc, SCB_NEXT); - - ahc_outb(ahc, SCB_CONTROL, 0); - - ahc_add_curscb_to_free_list(ahc); - - if (prev != SCB_LIST_NULL) { - ahc_outb(ahc, SCBPTR, prev); - ahc_outb(ahc, SCB_NEXT, next); - } else - ahc_outb(ahc, DISCONNECTED_SCBH, next); - - return (next); -} - -/* - * Add the SCB as selected by SCBPTR onto the on chip list of - * free hardware SCBs. This list is empty/unused if we are not - * performing SCB paging. - */ -static void -ahc_add_curscb_to_free_list(struct ahc_softc *ahc) -{ - /* - * Invalidate the tag so that our abort - * routines don't think it's active. - */ - ahc_outb(ahc, SCB_TAG, SCB_LIST_NULL); - - if ((ahc->flags & AHC_PAGESCBS) != 0) { - ahc_outb(ahc, SCB_NEXT, ahc_inb(ahc, FREE_SCBH)); - ahc_outb(ahc, FREE_SCBH, ahc_inb(ahc, SCBPTR)); - } -} - -/* - * Manipulate the waiting for selection list and return the - * scb that follows the one that we remove. - */ -static u_int -ahc_rem_wscb(struct ahc_softc *ahc, u_int scbpos, u_int prev) -{ - u_int curscb, next; - - /* - * Select the SCB we want to abort and - * pull the next pointer out of it. - */ - curscb = ahc_inb(ahc, SCBPTR); - ahc_outb(ahc, SCBPTR, scbpos); - next = ahc_inb(ahc, SCB_NEXT); - - /* Clear the necessary fields */ - ahc_outb(ahc, SCB_CONTROL, 0); - - ahc_add_curscb_to_free_list(ahc); - - /* update the waiting list */ - if (prev == SCB_LIST_NULL) { - /* First in the list */ - ahc_outb(ahc, WAITING_SCBH, next); - - /* - * Ensure we aren't attempting to perform - * selection for this entry. - */ - ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO)); - } else { - /* - * Select the scb that pointed to us - * and update its next pointer. - */ - ahc_outb(ahc, SCBPTR, prev); - ahc_outb(ahc, SCB_NEXT, next); - } - - /* - * Point us back at the original scb position. - */ - ahc_outb(ahc, SCBPTR, curscb); - return next; -} - -/******************************** Error Handling ******************************/ -/* - * Abort all SCBs that match the given description (target/channel/lun/tag), - * setting their status to the passed in status if the status has not already - * been modified from CAM_REQ_INPROG. This routine assumes that the sequencer - * is paused before it is called. - */ -int -ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel, - int lun, u_int tag, role_t role, uint32_t status) -{ - struct scb *scbp; - struct scb *scbp_next; - u_int active_scb; - int i, j; - int maxtarget; - int minlun; - int maxlun; - - int found; - - /* - * Don't attempt to run any queued untagged transactions - * until we are done with the abort process. - */ - ahc_freeze_untagged_queues(ahc); - - /* restore this when we're done */ - active_scb = ahc_inb(ahc, SCBPTR); - - found = ahc_search_qinfifo(ahc, target, channel, lun, SCB_LIST_NULL, - role, CAM_REQUEUE_REQ, SEARCH_COMPLETE); - - /* - * Clean out the busy target table for any untagged commands. - */ - i = 0; - maxtarget = 16; - if (target != CAM_TARGET_WILDCARD) { - i = target; - if (channel == 'B') - i += 8; - maxtarget = i + 1; - } - - if (lun == CAM_LUN_WILDCARD) { - - /* - * Unless we are using an SCB based - * busy targets table, there is only - * one table entry for all luns of - * a target. - */ - minlun = 0; - maxlun = 1; - if ((ahc->flags & AHC_SCB_BTT) != 0) - maxlun = AHC_NUM_LUNS; - } else { - minlun = lun; - maxlun = lun + 1; - } - - if (role != ROLE_TARGET) { - for (;i < maxtarget; i++) { - for (j = minlun;j < maxlun; j++) { - u_int scbid; - u_int tcl; - - tcl = BUILD_TCL(i << 4, j); - scbid = ahc_index_busy_tcl(ahc, tcl); - scbp = ahc_lookup_scb(ahc, scbid); - if (scbp == NULL - || ahc_match_scb(ahc, scbp, target, channel, - lun, tag, role) == 0) - continue; - ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, j)); - } - } - - /* - * Go through the disconnected list and remove any entries we - * have queued for completion, 0'ing their control byte too. - * We save the active SCB and restore it ourselves, so there - * is no reason for this search to restore it too. - */ - ahc_search_disc_list(ahc, target, channel, lun, tag, - /*stop_on_first*/FALSE, /*remove*/TRUE, - /*save_state*/FALSE); - } - - /* - * Go through the hardware SCB array looking for commands that - * were active but not on any list. In some cases, these remnants - * might not still have mappings in the scbindex array (e.g. unexpected - * bus free with the same scb queued for an abort). Don't hold this - * against them. - */ - for (i = 0; i < ahc->scb_data->maxhscbs; i++) { - u_int scbid; - - ahc_outb(ahc, SCBPTR, i); - scbid = ahc_inb(ahc, SCB_TAG); - scbp = ahc_lookup_scb(ahc, scbid); - if ((scbp == NULL && scbid != SCB_LIST_NULL) - || (scbp != NULL - && ahc_match_scb(ahc, scbp, target, channel, lun, tag, role))) - ahc_add_curscb_to_free_list(ahc); - } - - /* - * Go through the pending CCB list and look for - * commands for this target that are still active. - * These are other tagged commands that were - * disconnected when the reset occurred. - */ - scbp_next = LIST_FIRST(&ahc->pending_scbs); - while (scbp_next != NULL) { - scbp = scbp_next; - scbp_next = LIST_NEXT(scbp, pending_links); - if (ahc_match_scb(ahc, scbp, target, channel, lun, tag, role)) { - cam_status ostat; - - ostat = ahc_get_transaction_status(scbp); - if (ostat == CAM_REQ_INPROG) - ahc_set_transaction_status(scbp, status); - if (ahc_get_transaction_status(scbp) != CAM_REQ_CMP) - ahc_freeze_scb(scbp); - if ((scbp->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB on pending list\n"); - ahc_done(ahc, scbp); - found++; - } - } - ahc_outb(ahc, SCBPTR, active_scb); - ahc_platform_abort_scbs(ahc, target, channel, lun, tag, role, status); - ahc_release_untagged_queues(ahc); - return found; -} - -static void -ahc_reset_current_bus(struct ahc_softc *ahc) -{ - uint8_t scsiseq; - - ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENSCSIRST); - scsiseq = ahc_inb(ahc, SCSISEQ); - ahc_outb(ahc, SCSISEQ, scsiseq | SCSIRSTO); - ahc_flush_device_writes(ahc); - ahc_delay(AHC_BUSRESET_DELAY); - /* Turn off the bus reset */ - ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO); - - ahc_clear_intstat(ahc); - - /* Re-enable reset interrupts */ - ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) | ENSCSIRST); -} - -int -ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset) -{ - struct ahc_devinfo devinfo; - u_int initiator, target, max_scsiid; - u_int sblkctl; - u_int scsiseq; - u_int simode1; - int found; - int restart_needed; - char cur_channel; - - ahc->pending_device = NULL; - - ahc_compile_devinfo(&devinfo, - CAM_TARGET_WILDCARD, - CAM_TARGET_WILDCARD, - CAM_LUN_WILDCARD, - channel, ROLE_UNKNOWN); - ahc_pause(ahc); - - /* Make sure the sequencer is in a safe location. */ - ahc_clear_critical_section(ahc); - - /* - * Run our command complete fifos to ensure that we perform - * completion processing on any commands that 'completed' - * before the reset occurred. - */ - ahc_run_qoutfifo(ahc); -#if AHC_TARGET_MODE - /* - * XXX - In Twin mode, the tqinfifo may have commands - * for an unaffected channel in it. However, if - * we have run out of ATIO resources to drain that - * queue, we may not get them all out here. Further, - * the blocked transactions for the reset channel - * should just be killed off, irrespecitve of whether - * we are blocked on ATIO resources. Write a routine - * to compact the tqinfifo appropriately. - */ - if ((ahc->flags & AHC_TARGETROLE) != 0) { - ahc_run_tqinfifo(ahc, /*paused*/TRUE); - } -#endif - - /* - * Reset the bus if we are initiating this reset - */ - sblkctl = ahc_inb(ahc, SBLKCTL); - cur_channel = 'A'; - if ((ahc->features & AHC_TWIN) != 0 - && ((sblkctl & SELBUSB) != 0)) - cur_channel = 'B'; - scsiseq = ahc_inb(ahc, SCSISEQ_TEMPLATE); - if (cur_channel != channel) { - /* Case 1: Command for another bus is active - * Stealthily reset the other bus without - * upsetting the current bus. - */ - ahc_outb(ahc, SBLKCTL, sblkctl ^ SELBUSB); - simode1 = ahc_inb(ahc, SIMODE1) & ~(ENBUSFREE|ENSCSIRST); -#if AHC_TARGET_MODE - /* - * Bus resets clear ENSELI, so we cannot - * defer re-enabling bus reset interrupts - * if we are in target mode. - */ - if ((ahc->flags & AHC_TARGETROLE) != 0) - simode1 |= ENSCSIRST; -#endif - ahc_outb(ahc, SIMODE1, simode1); - if (initiate_reset) - ahc_reset_current_bus(ahc); - ahc_clear_intstat(ahc); - ahc_outb(ahc, SCSISEQ, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP)); - ahc_outb(ahc, SBLKCTL, sblkctl); - restart_needed = FALSE; - } else { - /* Case 2: A command from this bus is active or we're idle */ - simode1 = ahc_inb(ahc, SIMODE1) & ~(ENBUSFREE|ENSCSIRST); -#if AHC_TARGET_MODE - /* - * Bus resets clear ENSELI, so we cannot - * defer re-enabling bus reset interrupts - * if we are in target mode. - */ - if ((ahc->flags & AHC_TARGETROLE) != 0) - simode1 |= ENSCSIRST; -#endif - ahc_outb(ahc, SIMODE1, simode1); - if (initiate_reset) - ahc_reset_current_bus(ahc); - ahc_clear_intstat(ahc); - ahc_outb(ahc, SCSISEQ, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP)); - restart_needed = TRUE; - } - - /* - * Clean up all the state information for the - * pending transactions on this bus. - */ - found = ahc_abort_scbs(ahc, CAM_TARGET_WILDCARD, channel, - CAM_LUN_WILDCARD, SCB_LIST_NULL, - ROLE_UNKNOWN, CAM_SCSI_BUS_RESET); - - max_scsiid = (ahc->features & AHC_WIDE) ? 15 : 7; - -#ifdef AHC_TARGET_MODE - /* - * Send an immediate notify ccb to all target more peripheral - * drivers affected by this action. - */ - for (target = 0; target <= max_scsiid; target++) { - struct ahc_tmode_tstate* tstate; - u_int lun; - - tstate = ahc->enabled_targets[target]; - if (tstate == NULL) - continue; - for (lun = 0; lun < AHC_NUM_LUNS; lun++) { - struct ahc_tmode_lstate* lstate; - - lstate = tstate->enabled_luns[lun]; - if (lstate == NULL) - continue; - - ahc_queue_lstate_event(ahc, lstate, CAM_TARGET_WILDCARD, - EVENT_TYPE_BUS_RESET, /*arg*/0); - ahc_send_lstate_events(ahc, lstate); - } - } -#endif - /* Notify the XPT that a bus reset occurred */ - ahc_send_async(ahc, devinfo.channel, CAM_TARGET_WILDCARD, - CAM_LUN_WILDCARD, AC_BUS_RESET, NULL); - - /* - * Revert to async/narrow transfers until we renegotiate. - */ - for (target = 0; target <= max_scsiid; target++) { - - if (ahc->enabled_targets[target] == NULL) - continue; - for (initiator = 0; initiator <= max_scsiid; initiator++) { - struct ahc_devinfo devinfo; - - ahc_compile_devinfo(&devinfo, target, initiator, - CAM_LUN_WILDCARD, - channel, ROLE_UNKNOWN); - ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, - AHC_TRANS_CUR, /*paused*/TRUE); - ahc_set_syncrate(ahc, &devinfo, /*syncrate*/NULL, - /*period*/0, /*offset*/0, - /*ppr_options*/0, AHC_TRANS_CUR, - /*paused*/TRUE); - } - } - - if (restart_needed) - ahc_restart(ahc); - else - ahc_unpause(ahc); - return found; -} - - -/***************************** Residual Processing ****************************/ -/* - * Calculate the residual for a just completed SCB. - */ -void -ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb) -{ - struct hardware_scb *hscb; - struct status_pkt *spkt; - uint32_t sgptr; - uint32_t resid_sgptr; - uint32_t resid =0; - - /* - * 5 cases. - * 1) No residual. - * SG_RESID_VALID clear in sgptr. - * 2) Transferless command - * 3) Never performed any transfers. - * sgptr has SG_FULL_RESID set. - * 4) No residual but target did not - * save data pointers after the - * last transfer, so sgptr was - * never updated. - * 5) We have a partial residual. - * Use residual_sgptr to determine - * where we are. - */ - - hscb = scb->hscb; - sgptr = ahc_le32toh(hscb->sgptr); - if ((sgptr & SG_RESID_VALID) == 0) - /* Case 1 */ - return; - sgptr &= ~SG_RESID_VALID; - - if ((sgptr & SG_LIST_NULL) != 0) - /* Case 2 */ - return; - - spkt = &hscb->shared_data.status; - resid_sgptr = ahc_le32toh(spkt->residual_sg_ptr); - if ((sgptr & SG_FULL_RESID) != 0) { - /* Case 3 */ - resid = ahc_get_transfer_length(scb); - } else if ((resid_sgptr & SG_LIST_NULL) != 0) { - /* Case 4 */ - return; - } else if ((resid_sgptr & ~SG_PTR_MASK) != 0) { - panic("Bogus resid sgptr value 0x%x\n", resid_sgptr); - } else { - struct ahc_dma_seg *sg; - - /* - * Remainder of the SG where the transfer - * stopped. - */ - resid = ahc_le32toh(spkt->residual_datacnt) & AHC_SG_LEN_MASK; - sg = ahc_sg_bus_to_virt(scb, resid_sgptr & SG_PTR_MASK); - - /* The residual sg_ptr always points to the next sg */ - sg--; - - /* - * Add up the contents of all residual - * SG segments that are after the SG where - * the transfer stopped. - */ - while ((ahc_le32toh(sg->len) & AHC_DMA_LAST_SEG) == 0) { - sg++; - resid += ahc_le32toh(sg->len) & AHC_SG_LEN_MASK; - } - } - if ((scb->flags & SCB_SENSE) == 0) - ahc_set_residual(scb, resid); - else - ahc_set_sense_residual(scb, resid); - -#ifdef AHC_DEBUG - if ((ahc_debug & AHC_SHOWMISC) != 0) { - ahc_print_path(ahc, scb); - printf("Handled Residual of %d bytes\n", resid); - } -#endif -} - -/******************************* Target Mode **********************************/ -#ifdef AHC_TARGET_MODE -/* - * Add a target mode event to this lun's queue - */ -static void -ahc_queue_lstate_event(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate, - u_int initiator_id, u_int event_type, u_int event_arg) -{ - struct ahc_tmode_event *event; - int pending; - - xpt_freeze_devq(lstate->path, /*count*/1); - if (lstate->event_w_idx >= lstate->event_r_idx) - pending = lstate->event_w_idx - lstate->event_r_idx; - else - pending = AHC_TMODE_EVENT_BUFFER_SIZE + 1 - - (lstate->event_r_idx - lstate->event_w_idx); - - if (event_type == EVENT_TYPE_BUS_RESET - || event_type == MSG_BUS_DEV_RESET) { - /* - * Any earlier events are irrelevant, so reset our buffer. - * This has the effect of allowing us to deal with reset - * floods (an external device holding down the reset line) - * without losing the event that is really interesting. - */ - lstate->event_r_idx = 0; - lstate->event_w_idx = 0; - xpt_release_devq(lstate->path, pending, /*runqueue*/FALSE); - } - - if (pending == AHC_TMODE_EVENT_BUFFER_SIZE) { - xpt_print_path(lstate->path); - printf("immediate event %x:%x lost\n", - lstate->event_buffer[lstate->event_r_idx].event_type, - lstate->event_buffer[lstate->event_r_idx].event_arg); - lstate->event_r_idx++; - if (lstate->event_r_idx == AHC_TMODE_EVENT_BUFFER_SIZE) - lstate->event_r_idx = 0; - xpt_release_devq(lstate->path, /*count*/1, /*runqueue*/FALSE); - } - - event = &lstate->event_buffer[lstate->event_w_idx]; - event->initiator_id = initiator_id; - event->event_type = event_type; - event->event_arg = event_arg; - lstate->event_w_idx++; - if (lstate->event_w_idx == AHC_TMODE_EVENT_BUFFER_SIZE) - lstate->event_w_idx = 0; -} - -/* - * Send any target mode events queued up waiting - * for immediate notify resources. - */ -void -ahc_send_lstate_events(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate) -{ - struct ccb_hdr *ccbh; - struct ccb_immed_notify *inot; - - while (lstate->event_r_idx != lstate->event_w_idx - && (ccbh = SLIST_FIRST(&lstate->immed_notifies)) != NULL) { - struct ahc_tmode_event *event; - - event = &lstate->event_buffer[lstate->event_r_idx]; - SLIST_REMOVE_HEAD(&lstate->immed_notifies, sim_links.sle); - inot = (struct ccb_immed_notify *)ccbh; - switch (event->event_type) { - case EVENT_TYPE_BUS_RESET: - ccbh->status = CAM_SCSI_BUS_RESET|CAM_DEV_QFRZN; - break; - default: - ccbh->status = CAM_MESSAGE_RECV|CAM_DEV_QFRZN; - inot->message_args[0] = event->event_type; - inot->message_args[1] = event->event_arg; - break; - } - inot->initiator_id = event->initiator_id; - inot->sense_len = 0; - xpt_done((union ccb *)inot); - lstate->event_r_idx++; - if (lstate->event_r_idx == AHC_TMODE_EVENT_BUFFER_SIZE) - lstate->event_r_idx = 0; - } -} -#endif - -/******************** Sequencer Program Patching/Download *********************/ - -#ifdef AHC_DUMP_SEQ -void -ahc_dumpseq(struct ahc_softc* ahc) -{ - int i; - int max_prog; - - if ((ahc->chip & AHC_BUS_MASK) < AHC_PCI) - max_prog = 448; - else if ((ahc->features & AHC_ULTRA2) != 0) - max_prog = 768; - else - max_prog = 512; - - ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); - ahc_outb(ahc, SEQADDR0, 0); - ahc_outb(ahc, SEQADDR1, 0); - for (i = 0; i < max_prog; i++) { - uint8_t ins_bytes[4]; - - ahc_insb(ahc, SEQRAM, ins_bytes, 4); - printf("0x%08x\n", ins_bytes[0] << 24 - | ins_bytes[1] << 16 - | ins_bytes[2] << 8 - | ins_bytes[3]); - } -} -#endif - -static void -ahc_loadseq(struct ahc_softc *ahc) -{ - struct cs cs_table[num_critical_sections]; - u_int begin_set[num_critical_sections]; - u_int end_set[num_critical_sections]; - struct patch *cur_patch; - u_int cs_count; - u_int cur_cs; - u_int i; - int downloaded; - u_int skip_addr; - u_int sg_prefetch_cnt; - uint8_t download_consts[7]; - - /* - * Start out with 0 critical sections - * that apply to this firmware load. - */ - cs_count = 0; - cur_cs = 0; - memset(begin_set, 0, sizeof(begin_set)); - memset(end_set, 0, sizeof(end_set)); - - /* Setup downloadable constant table */ - download_consts[QOUTFIFO_OFFSET] = 0; - if (ahc->targetcmds != NULL) - download_consts[QOUTFIFO_OFFSET] += 32; - download_consts[QINFIFO_OFFSET] = download_consts[QOUTFIFO_OFFSET] + 1; - download_consts[CACHESIZE_MASK] = ahc->pci_cachesize - 1; - download_consts[INVERTED_CACHESIZE_MASK] = ~(ahc->pci_cachesize - 1); - sg_prefetch_cnt = ahc->pci_cachesize; - if (sg_prefetch_cnt < (2 * sizeof(struct ahc_dma_seg))) - sg_prefetch_cnt = 2 * sizeof(struct ahc_dma_seg); - download_consts[SG_PREFETCH_CNT] = sg_prefetch_cnt; - download_consts[SG_PREFETCH_ALIGN_MASK] = ~(sg_prefetch_cnt - 1); - download_consts[SG_PREFETCH_ADDR_MASK] = (sg_prefetch_cnt - 1); - - cur_patch = patches; - downloaded = 0; - skip_addr = 0; - ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); - ahc_outb(ahc, SEQADDR0, 0); - ahc_outb(ahc, SEQADDR1, 0); - - for (i = 0; i < sizeof(seqprog)/4; i++) { - if (ahc_check_patch(ahc, &cur_patch, i, &skip_addr) == 0) { - /* - * Don't download this instruction as it - * is in a patch that was removed. - */ - continue; - } - /* - * Move through the CS table until we find a CS - * that might apply to this instruction. - */ - for (; cur_cs < num_critical_sections; cur_cs++) { - if (critical_sections[cur_cs].end <= i) { - if (begin_set[cs_count] == TRUE - && end_set[cs_count] == FALSE) { - cs_table[cs_count].end = downloaded; - end_set[cs_count] = TRUE; - cs_count++; - } - continue; - } - if (critical_sections[cur_cs].begin <= i - && begin_set[cs_count] == FALSE) { - cs_table[cs_count].begin = downloaded; - begin_set[cs_count] = TRUE; - } - break; - } - ahc_download_instr(ahc, i, download_consts); - downloaded++; - } - - ahc->num_critical_sections = cs_count; - if (cs_count != 0) { - - cs_count *= sizeof(struct cs); - ahc->critical_sections = malloc(cs_count, M_DEVBUF, M_NOWAIT); - if (ahc->critical_sections == NULL) - panic("ahc_loadseq: Could not malloc"); - memcpy(ahc->critical_sections, cs_table, cs_count); - } - ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE); - ahc_restart(ahc); - - if (bootverbose) - printf(" %d instructions downloaded\n", downloaded); -} - -static int -ahc_check_patch(struct ahc_softc *ahc, struct patch **start_patch, - u_int start_instr, u_int *skip_addr) -{ - struct patch *cur_patch; - struct patch *last_patch; - u_int num_patches; - - num_patches = sizeof(patches)/sizeof(struct patch); - last_patch = &patches[num_patches]; - cur_patch = *start_patch; - - while (cur_patch < last_patch && start_instr == cur_patch->begin) { - - if (cur_patch->patch_func(ahc) == 0) { - - /* Start rejecting code */ - *skip_addr = start_instr + cur_patch->skip_instr; - cur_patch += cur_patch->skip_patch; - } else { - /* Accepted this patch. Advance to the next - * one and wait for our intruction pointer to - * hit this point. - */ - cur_patch++; - } - } - - *start_patch = cur_patch; - if (start_instr < *skip_addr) - /* Still skipping */ - return (0); - - return (1); -} - -static void -ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts) -{ - union ins_formats instr; - struct ins_format1 *fmt1_ins; - struct ins_format3 *fmt3_ins; - u_int opcode; - - /* - * The firmware is always compiled into a little endian format. - */ - instr.integer = ahc_le32toh(*(uint32_t*)&seqprog[instrptr * 4]); - - fmt1_ins = &instr.format1; - fmt3_ins = NULL; - - /* Pull the opcode */ - opcode = instr.format1.opcode; - switch (opcode) { - case AIC_OP_JMP: - case AIC_OP_JC: - case AIC_OP_JNC: - case AIC_OP_CALL: - case AIC_OP_JNE: - case AIC_OP_JNZ: - case AIC_OP_JE: - case AIC_OP_JZ: - { - struct patch *cur_patch; - int address_offset; - u_int address; - u_int skip_addr; - u_int i; - - fmt3_ins = &instr.format3; - address_offset = 0; - address = fmt3_ins->address; - cur_patch = patches; - skip_addr = 0; - - for (i = 0; i < address;) { - - ahc_check_patch(ahc, &cur_patch, i, &skip_addr); - - if (skip_addr > i) { - int end_addr; - - end_addr = MIN(address, skip_addr); - address_offset += end_addr - i; - i = skip_addr; - } else { - i++; - } - } - address -= address_offset; - fmt3_ins->address = address; - /* FALLTHROUGH */ - } - case AIC_OP_OR: - case AIC_OP_AND: - case AIC_OP_XOR: - case AIC_OP_ADD: - case AIC_OP_ADC: - case AIC_OP_BMOV: - if (fmt1_ins->parity != 0) { - fmt1_ins->immediate = dconsts[fmt1_ins->immediate]; - } - fmt1_ins->parity = 0; - if ((ahc->features & AHC_CMD_CHAN) == 0 - && opcode == AIC_OP_BMOV) { - /* - * Block move was added at the same time - * as the command channel. Verify that - * this is only a move of a single element - * and convert the BMOV to a MOV - * (AND with an immediate of FF). - */ - if (fmt1_ins->immediate != 1) - panic("%s: BMOV not supported\n", - ahc_name(ahc)); - fmt1_ins->opcode = AIC_OP_AND; - fmt1_ins->immediate = 0xff; - } - /* FALLTHROUGH */ - case AIC_OP_ROL: - if ((ahc->features & AHC_ULTRA2) != 0) { - int i, count; - - /* Calculate odd parity for the instruction */ - for (i = 0, count = 0; i < 31; i++) { - uint32_t mask; - - mask = 0x01 << i; - if ((instr.integer & mask) != 0) - count++; - } - if ((count & 0x01) == 0) - instr.format1.parity = 1; - } else { - /* Compress the instruction for older sequencers */ - if (fmt3_ins != NULL) { - instr.integer = - fmt3_ins->immediate - | (fmt3_ins->source << 8) - | (fmt3_ins->address << 16) - | (fmt3_ins->opcode << 25); - } else { - instr.integer = - fmt1_ins->immediate - | (fmt1_ins->source << 8) - | (fmt1_ins->destination << 16) - | (fmt1_ins->ret << 24) - | (fmt1_ins->opcode << 25); - } - } - /* The sequencer is a little endian cpu */ - instr.integer = ahc_htole32(instr.integer); - ahc_outsb(ahc, SEQRAM, instr.bytes, 4); - break; - default: - panic("Unknown opcode encountered in seq program"); - break; - } -} - -void -ahc_dump_card_state(struct ahc_softc *ahc) -{ - struct scb *scb; - struct scb_tailq *untagged_q; - int target; - int maxtarget; - int i; - uint8_t last_phase; - uint8_t qinpos; - uint8_t qintail; - uint8_t qoutpos; - uint8_t scb_index; - uint8_t saved_scbptr; - - saved_scbptr = ahc_inb(ahc, SCBPTR); - - last_phase = ahc_inb(ahc, LASTPHASE); - printf("%s: Dumping Card State %s, at SEQADDR 0x%x\n", - ahc_name(ahc), ahc_lookup_phase_entry(last_phase)->phasemsg, - ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); - printf("ACCUM = 0x%x, SINDEX = 0x%x, DINDEX = 0x%x, ARG_2 = 0x%x\n", - ahc_inb(ahc, ACCUM), ahc_inb(ahc, SINDEX), ahc_inb(ahc, DINDEX), - ahc_inb(ahc, ARG_2)); - printf("HCNT = 0x%x SCBPTR = 0x%x\n", ahc_inb(ahc, HCNT), - ahc_inb(ahc, SCBPTR)); - printf("SCSISEQ = 0x%x, SBLKCTL = 0x%x\n", - ahc_inb(ahc, SCSISEQ), ahc_inb(ahc, SBLKCTL)); - printf(" DFCNTRL = 0x%x, DFSTATUS = 0x%x\n", - ahc_inb(ahc, DFCNTRL), ahc_inb(ahc, DFSTATUS)); - printf("LASTPHASE = 0x%x, SCSISIGI = 0x%x, SXFRCTL0 = 0x%x\n", - last_phase, ahc_inb(ahc, SCSISIGI), ahc_inb(ahc, SXFRCTL0)); - printf("SSTAT0 = 0x%x, SSTAT1 = 0x%x\n", - ahc_inb(ahc, SSTAT0), ahc_inb(ahc, SSTAT1)); - if ((ahc->features & AHC_DT) != 0) - printf("SCSIPHASE = 0x%x\n", ahc_inb(ahc, SCSIPHASE)); - printf("STACK == 0x%x, 0x%x, 0x%x, 0x%x\n", - ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), - ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), - ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), - ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8)); - printf("SCB count = %d\n", ahc->scb_data->numscbs); - printf("Kernel NEXTQSCB = %d\n", ahc->next_queued_scb->hscb->tag); - printf("Card NEXTQSCB = %d\n", ahc_inb(ahc, NEXT_QUEUED_SCB)); - /* QINFIFO */ - printf("QINFIFO entries: "); - if ((ahc->features & AHC_QUEUE_REGS) != 0) { - qinpos = ahc_inb(ahc, SNSCB_QOFF); - ahc_outb(ahc, SNSCB_QOFF, qinpos); - } else - qinpos = ahc_inb(ahc, QINPOS); - qintail = ahc->qinfifonext; - while (qinpos != qintail) { - printf("%d ", ahc->qinfifo[qinpos]); - qinpos++; - } - printf("\n"); - - printf("Waiting Queue entries: "); - scb_index = ahc_inb(ahc, WAITING_SCBH); - i = 0; - while (scb_index != SCB_LIST_NULL && i++ < 256) { - ahc_outb(ahc, SCBPTR, scb_index); - printf("%d:%d ", scb_index, ahc_inb(ahc, SCB_TAG)); - scb_index = ahc_inb(ahc, SCB_NEXT); - } - printf("\n"); - - printf("Disconnected Queue entries: "); - scb_index = ahc_inb(ahc, DISCONNECTED_SCBH); - i = 0; - while (scb_index != SCB_LIST_NULL && i++ < 256) { - ahc_outb(ahc, SCBPTR, scb_index); - printf("%d:%d ", scb_index, ahc_inb(ahc, SCB_TAG)); - scb_index = ahc_inb(ahc, SCB_NEXT); - } - printf("\n"); - - ahc_sync_qoutfifo(ahc, BUS_DMASYNC_POSTREAD); - printf("QOUTFIFO entries: "); - qoutpos = ahc->qoutfifonext; - i = 0; - while (ahc->qoutfifo[qoutpos] != SCB_LIST_NULL && i++ < 256) { - printf("%d ", ahc->qoutfifo[qoutpos]); - qoutpos++; - } - printf("\n"); - - printf("Sequencer Free SCB List: "); - scb_index = ahc_inb(ahc, FREE_SCBH); - i = 0; - while (scb_index != SCB_LIST_NULL && i++ < 256) { - ahc_outb(ahc, SCBPTR, scb_index); - printf("%d ", scb_index); - scb_index = ahc_inb(ahc, SCB_NEXT); - } - printf("\n"); - - printf("Sequencer SCB Info: "); - for (i = 0; i < ahc->scb_data->maxhscbs; i++) { - ahc_outb(ahc, SCBPTR, i); - printf("%d(c 0x%x, s 0x%x, l %d, t 0x%x) ", - i, ahc_inb(ahc, SCB_CONTROL), - ahc_inb(ahc, SCB_SCSIID), - ahc_inb(ahc, SCB_LUN), - ahc_inb(ahc, SCB_TAG)); - } - printf("\n"); - - printf("Pending list: "); - i = 0; - LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) { - if (i++ > 256) - break; - if (scb != LIST_FIRST(&ahc->pending_scbs)) - printf(", "); - printf("%d(c 0x%x, s 0x%x, l %d)", scb->hscb->tag, - scb->hscb->control, scb->hscb->scsiid, scb->hscb->lun); - if ((ahc->flags & AHC_PAGESCBS) == 0) { - ahc_outb(ahc, SCBPTR, scb->hscb->tag); - printf("(0x%x, 0x%x)", ahc_inb(ahc, SCB_CONTROL), - ahc_inb(ahc, SCB_TAG)); - } - } - printf("\n"); - - printf("Kernel Free SCB list: "); - i = 0; - SLIST_FOREACH(scb, &ahc->scb_data->free_scbs, links.sle) { - if (i++ > 256) - break; - printf("%d ", scb->hscb->tag); - } - printf("\n"); - - maxtarget = (ahc->features & (AHC_WIDE|AHC_TWIN)) ? 15 : 7; - for (target = 0; target <= maxtarget; target++) { - untagged_q = &ahc->untagged_queues[target]; - if (TAILQ_FIRST(untagged_q) == NULL) - continue; - printf("Untagged Q(%d): ", target); - i = 0; - TAILQ_FOREACH(scb, untagged_q, links.tqe) { - if (i++ > 256) - break; - printf("%d ", scb->hscb->tag); - } - printf("\n"); - } - - ahc_platform_dump_card_state(ahc); - ahc_outb(ahc, SCBPTR, saved_scbptr); -} - -/************************* Target Mode ****************************************/ -#ifdef AHC_TARGET_MODE -cam_status -ahc_find_tmode_devs(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb, - struct ahc_tmode_tstate **tstate, - struct ahc_tmode_lstate **lstate, - int notfound_failure) -{ - - if ((ahc->features & AHC_TARGETMODE) == 0) - return (CAM_REQ_INVALID); - - /* - * Handle the 'black hole' device that sucks up - * requests to unattached luns on enabled targets. - */ - if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD - && ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) { - *tstate = NULL; - *lstate = ahc->black_hole; - } else { - u_int max_id; - - max_id = (ahc->features & AHC_WIDE) ? 15 : 7; - if (ccb->ccb_h.target_id > max_id) - return (CAM_TID_INVALID); - - if (ccb->ccb_h.target_lun >= AHC_NUM_LUNS) - return (CAM_LUN_INVALID); - - *tstate = ahc->enabled_targets[ccb->ccb_h.target_id]; - *lstate = NULL; - if (*tstate != NULL) - *lstate = - (*tstate)->enabled_luns[ccb->ccb_h.target_lun]; - } - - if (notfound_failure != 0 && *lstate == NULL) - return (CAM_PATH_INVALID); - - return (CAM_REQ_CMP); -} - -void -ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) -{ - struct ahc_tmode_tstate *tstate; - struct ahc_tmode_lstate *lstate; - struct ccb_en_lun *cel; - cam_status status; - u_int target; - u_int lun; - u_int target_mask; - u_long s; - char channel; - - status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, &lstate, - /*notfound_failure*/FALSE); - - if (status != CAM_REQ_CMP) { - ccb->ccb_h.status = status; - return; - } - - if ((ahc->features & AHC_MULTIROLE) != 0) { - u_int our_id; - - if (cam_sim_bus(sim) == 0) - our_id = ahc->our_id; - else - our_id = ahc->our_id_b; - - if (ccb->ccb_h.target_id != our_id) { - if ((ahc->features & AHC_MULTI_TID) != 0 - && (ahc->flags & AHC_INITIATORROLE) != 0) { - /* - * Only allow additional targets if - * the initiator role is disabled. - * The hardware cannot handle a re-select-in - * on the initiator id during a re-select-out - * on a different target id. - */ - status = CAM_TID_INVALID; - } else if ((ahc->flags & AHC_INITIATORROLE) != 0 - || ahc->enabled_luns > 0) { - /* - * Only allow our target id to change - * if the initiator role is not configured - * and there are no enabled luns which - * are attached to the currently registered - * scsi id. - */ - status = CAM_TID_INVALID; - } - } - } - - if (status != CAM_REQ_CMP) { - ccb->ccb_h.status = status; - return; - } - - /* - * We now have an id that is valid. - * If we aren't in target mode, switch modes. - */ - if ((ahc->flags & AHC_TARGETROLE) == 0 - && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) { - u_long s; - - printf("Configuring Target Mode\n"); - ahc_lock(ahc, &s); - if (LIST_FIRST(&ahc->pending_scbs) != NULL) { - ccb->ccb_h.status = CAM_BUSY; - ahc_unlock(ahc, &s); - return; - } - ahc->flags |= AHC_TARGETROLE; - if ((ahc->features & AHC_MULTIROLE) == 0) - ahc->flags &= ~AHC_INITIATORROLE; - ahc_pause(ahc); - ahc_loadseq(ahc); - ahc_unlock(ahc, &s); - } - cel = &ccb->cel; - target = ccb->ccb_h.target_id; - lun = ccb->ccb_h.target_lun; - channel = SIM_CHANNEL(ahc, sim); - target_mask = 0x01 << target; - if (channel == 'B') - target_mask <<= 8; - - if (cel->enable != 0) { - u_int scsiseq; - - /* Are we already enabled?? */ - if (lstate != NULL) { - xpt_print_path(ccb->ccb_h.path); - printf("Lun already enabled\n"); - ccb->ccb_h.status = CAM_LUN_ALRDY_ENA; - return; - } - - if (cel->grp6_len != 0 - || cel->grp7_len != 0) { - /* - * Don't (yet?) support vendor - * specific commands. - */ - ccb->ccb_h.status = CAM_REQ_INVALID; - printf("Non-zero Group Codes\n"); - return; - } - - /* - * Seems to be okay. - * Setup our data structures. - */ - if (target != CAM_TARGET_WILDCARD && tstate == NULL) { - tstate = ahc_alloc_tstate(ahc, target, channel); - if (tstate == NULL) { - xpt_print_path(ccb->ccb_h.path); - printf("Couldn't allocate tstate\n"); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; - return; - } - } - lstate = malloc(sizeof(*lstate), M_DEVBUF, M_NOWAIT); - if (lstate == NULL) { - xpt_print_path(ccb->ccb_h.path); - printf("Couldn't allocate lstate\n"); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; - return; - } - memset(lstate, 0, sizeof(*lstate)); - status = xpt_create_path(&lstate->path, /*periph*/NULL, - xpt_path_path_id(ccb->ccb_h.path), - xpt_path_target_id(ccb->ccb_h.path), - xpt_path_lun_id(ccb->ccb_h.path)); - if (status != CAM_REQ_CMP) { - free(lstate, M_DEVBUF); - xpt_print_path(ccb->ccb_h.path); - printf("Couldn't allocate path\n"); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; - return; - } - SLIST_INIT(&lstate->accept_tios); - SLIST_INIT(&lstate->immed_notifies); - ahc_lock(ahc, &s); - ahc_pause(ahc); - if (target != CAM_TARGET_WILDCARD) { - tstate->enabled_luns[lun] = lstate; - ahc->enabled_luns++; - - if ((ahc->features & AHC_MULTI_TID) != 0) { - u_int targid_mask; - - targid_mask = ahc_inb(ahc, TARGID) - | (ahc_inb(ahc, TARGID + 1) << 8); - - targid_mask |= target_mask; - ahc_outb(ahc, TARGID, targid_mask); - ahc_outb(ahc, TARGID+1, (targid_mask >> 8)); - - ahc_update_scsiid(ahc, targid_mask); - } else { - u_int our_id; - char channel; - - channel = SIM_CHANNEL(ahc, sim); - our_id = SIM_SCSI_ID(ahc, sim); - - /* - * This can only happen if selections - * are not enabled - */ - if (target != our_id) { - u_int sblkctl; - char cur_channel; - int swap; - - sblkctl = ahc_inb(ahc, SBLKCTL); - cur_channel = (sblkctl & SELBUSB) - ? 'B' : 'A'; - if ((ahc->features & AHC_TWIN) == 0) - cur_channel = 'A'; - swap = cur_channel != channel; - if (channel == 'A') - ahc->our_id = target; - else - ahc->our_id_b = target; - - if (swap) - ahc_outb(ahc, SBLKCTL, - sblkctl ^ SELBUSB); - - ahc_outb(ahc, SCSIID, target); - - if (swap) - ahc_outb(ahc, SBLKCTL, sblkctl); - } - } - } else - ahc->black_hole = lstate; - /* Allow select-in operations */ - if (ahc->black_hole != NULL && ahc->enabled_luns > 0) { - scsiseq = ahc_inb(ahc, SCSISEQ_TEMPLATE); - scsiseq |= ENSELI; - ahc_outb(ahc, SCSISEQ_TEMPLATE, scsiseq); - scsiseq = ahc_inb(ahc, SCSISEQ); - scsiseq |= ENSELI; - ahc_outb(ahc, SCSISEQ, scsiseq); - } - ahc_unpause(ahc); - ahc_unlock(ahc, &s); - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_print_path(ccb->ccb_h.path); - printf("Lun now enabled for target mode\n"); - } else { - struct scb *scb; - int i, empty; - - if (lstate == NULL) { - ccb->ccb_h.status = CAM_LUN_INVALID; - return; - } - - ahc_lock(ahc, &s); - - ccb->ccb_h.status = CAM_REQ_CMP; - LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) { - struct ccb_hdr *ccbh; - - ccbh = &scb->io_ctx->ccb_h; - if (ccbh->func_code == XPT_CONT_TARGET_IO - && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){ - printf("CTIO pending\n"); - ccb->ccb_h.status = CAM_REQ_INVALID; - ahc_unlock(ahc, &s); - return; - } - } - - if (SLIST_FIRST(&lstate->accept_tios) != NULL) { - printf("ATIOs pending\n"); - ccb->ccb_h.status = CAM_REQ_INVALID; - } - - if (SLIST_FIRST(&lstate->immed_notifies) != NULL) { - printf("INOTs pending\n"); - ccb->ccb_h.status = CAM_REQ_INVALID; - } - - if (ccb->ccb_h.status != CAM_REQ_CMP) { - ahc_unlock(ahc, &s); - return; - } - - xpt_print_path(ccb->ccb_h.path); - printf("Target mode disabled\n"); - xpt_free_path(lstate->path); - free(lstate, M_DEVBUF); - - ahc_pause(ahc); - /* Can we clean up the target too? */ - if (target != CAM_TARGET_WILDCARD) { - tstate->enabled_luns[lun] = NULL; - ahc->enabled_luns--; - for (empty = 1, i = 0; i < 8; i++) - if (tstate->enabled_luns[i] != NULL) { - empty = 0; - break; - } - - if (empty) { - ahc_free_tstate(ahc, target, channel, - /*force*/FALSE); - if (ahc->features & AHC_MULTI_TID) { - u_int targid_mask; - - targid_mask = ahc_inb(ahc, TARGID) - | (ahc_inb(ahc, TARGID + 1) - << 8); - - targid_mask &= ~target_mask; - ahc_outb(ahc, TARGID, targid_mask); - ahc_outb(ahc, TARGID+1, - (targid_mask >> 8)); - ahc_update_scsiid(ahc, targid_mask); - } - } - } else { - - ahc->black_hole = NULL; - - /* - * We can't allow selections without - * our black hole device. - */ - empty = TRUE; - } - if (ahc->enabled_luns == 0) { - /* Disallow select-in */ - u_int scsiseq; - - scsiseq = ahc_inb(ahc, SCSISEQ_TEMPLATE); - scsiseq &= ~ENSELI; - ahc_outb(ahc, SCSISEQ_TEMPLATE, scsiseq); - scsiseq = ahc_inb(ahc, SCSISEQ); - scsiseq &= ~ENSELI; - ahc_outb(ahc, SCSISEQ, scsiseq); - - if ((ahc->features & AHC_MULTIROLE) == 0) { - printf("Configuring Initiator Mode\n"); - ahc->flags &= ~AHC_TARGETROLE; - ahc->flags |= AHC_INITIATORROLE; - ahc_pause(ahc); - ahc_loadseq(ahc); - } - } - ahc_unpause(ahc); - ahc_unlock(ahc, &s); - } -} - -static void -ahc_update_scsiid(struct ahc_softc *ahc, u_int targid_mask) -{ - u_int scsiid_mask; - u_int scsiid; - - if ((ahc->features & AHC_MULTI_TID) == 0) - panic("ahc_update_scsiid called on non-multitid unit\n"); - - /* - * Since we will rely on the the TARGID mask - * for selection enables, ensure that OID - * in SCSIID is not set to some other ID - * that we don't want to allow selections on. - */ - if ((ahc->features & AHC_ULTRA2) != 0) - scsiid = ahc_inb(ahc, SCSIID_ULTRA2); - else - scsiid = ahc_inb(ahc, SCSIID); - scsiid_mask = 0x1 << (scsiid & OID); - if ((targid_mask & scsiid_mask) == 0) { - u_int our_id; - - /* ffs counts from 1 */ - our_id = ffs(targid_mask); - if (our_id == 0) - our_id = ahc->our_id; - else - our_id--; - scsiid &= TID; - scsiid |= our_id; - } - if ((ahc->features & AHC_ULTRA2) != 0) - ahc_outb(ahc, SCSIID_ULTRA2, scsiid); - else - ahc_outb(ahc, SCSIID, scsiid); -} - -void -ahc_run_tqinfifo(struct ahc_softc *ahc, int paused) -{ - struct target_cmd *cmd; - - /* - * If the card supports auto-access pause, - * we can access the card directly regardless - * of whether it is paused or not. - */ - if ((ahc->features & AHC_AUTOPAUSE) != 0) - paused = TRUE; - - ahc_sync_tqinfifo(ahc, BUS_DMASYNC_POSTREAD); - while ((cmd = &ahc->targetcmds[ahc->tqinfifonext])->cmd_valid != 0) { - - /* - * Only advance through the queue if we - * have the resources to process the command. - */ - if (ahc_handle_target_cmd(ahc, cmd) != 0) - break; - - cmd->cmd_valid = 0; - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, - ahc->shared_data_dmamap, - ahc_targetcmd_offset(ahc, ahc->tqinfifonext), - sizeof(struct target_cmd), - BUS_DMASYNC_PREREAD); - ahc->tqinfifonext++; - - /* - * Lazily update our position in the target mode incoming - * command queue as seen by the sequencer. - */ - if ((ahc->tqinfifonext & (HOST_TQINPOS - 1)) == 1) { - if ((ahc->features & AHC_HS_MAILBOX) != 0) { - u_int hs_mailbox; - - hs_mailbox = ahc_inb(ahc, HS_MAILBOX); - hs_mailbox &= ~HOST_TQINPOS; - hs_mailbox |= ahc->tqinfifonext & HOST_TQINPOS; - ahc_outb(ahc, HS_MAILBOX, hs_mailbox); - } else { - if (!paused) - ahc_pause(ahc); - ahc_outb(ahc, KERNEL_TQINPOS, - ahc->tqinfifonext & HOST_TQINPOS); - if (!paused) - ahc_unpause(ahc); - } - } - } -} - -static int -ahc_handle_target_cmd(struct ahc_softc *ahc, struct target_cmd *cmd) -{ - struct ahc_tmode_tstate *tstate; - struct ahc_tmode_lstate *lstate; - struct ccb_accept_tio *atio; - uint8_t *byte; - int initiator; - int target; - int lun; - - initiator = SCSIID_TARGET(ahc, cmd->scsiid); - target = SCSIID_OUR_ID(cmd->scsiid); - lun = (cmd->identify & MSG_IDENTIFY_LUNMASK); - - byte = cmd->bytes; - tstate = ahc->enabled_targets[target]; - lstate = NULL; - if (tstate != NULL) - lstate = tstate->enabled_luns[lun]; - - /* - * Commands for disabled luns go to the black hole driver. - */ - if (lstate == NULL) - lstate = ahc->black_hole; - - atio = (struct ccb_accept_tio*)SLIST_FIRST(&lstate->accept_tios); - if (atio == NULL) { - ahc->flags |= AHC_TQINFIFO_BLOCKED; - /* - * Wait for more ATIOs from the peripheral driver for this lun. - */ - if (bootverbose) - printf("%s: ATIOs exhausted\n", ahc_name(ahc)); - return (1); - } else - ahc->flags &= ~AHC_TQINFIFO_BLOCKED; -#if 0 - printf("Incoming command from %d for %d:%d%s\n", - initiator, target, lun, - lstate == ahc->black_hole ? "(Black Holed)" : ""); -#endif - SLIST_REMOVE_HEAD(&lstate->accept_tios, sim_links.sle); - - if (lstate == ahc->black_hole) { - /* Fill in the wildcards */ - atio->ccb_h.target_id = target; - atio->ccb_h.target_lun = lun; - } - - /* - * Package it up and send it off to - * whomever has this lun enabled. - */ - atio->sense_len = 0; - atio->init_id = initiator; - if (byte[0] != 0xFF) { - /* Tag was included */ - atio->tag_action = *byte++; - atio->tag_id = *byte++; - atio->ccb_h.flags = CAM_TAG_ACTION_VALID; - } else { - atio->ccb_h.flags = 0; - } - byte++; - - /* Okay. Now determine the cdb size based on the command code */ - switch (*byte >> CMD_GROUP_CODE_SHIFT) { - case 0: - atio->cdb_len = 6; - break; - case 1: - case 2: - atio->cdb_len = 10; - break; - case 4: - atio->cdb_len = 16; - break; - case 5: - atio->cdb_len = 12; - break; - case 3: - default: - /* Only copy the opcode. */ - atio->cdb_len = 1; - printf("Reserved or VU command code type encountered\n"); - break; - } - - memcpy(atio->cdb_io.cdb_bytes, byte, atio->cdb_len); - - atio->ccb_h.status |= CAM_CDB_RECVD; - - if ((cmd->identify & MSG_IDENTIFY_DISCFLAG) == 0) { - /* - * We weren't allowed to disconnect. - * We're hanging on the bus until a - * continue target I/O comes in response - * to this accept tio. - */ -#if 0 - printf("Received Immediate Command %d:%d:%d - %p\n", - initiator, target, lun, ahc->pending_device); -#endif - ahc->pending_device = lstate; - ahc_freeze_ccb((union ccb *)atio); - atio->ccb_h.flags |= CAM_DIS_DISCONNECT; - } - xpt_done((union ccb*)atio); - return (0); -} - -#endif diff --git a/xen/drivers/scsi/aic7xxx/aic7xxx_host.h b/xen/drivers/scsi/aic7xxx/aic7xxx_host.h deleted file mode 100644 index 23710c6ed4..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic7xxx_host.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Adaptec AIC7xxx device driver host template for Linux. - * - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_host.h#9 $ - */ - -#ifndef _AIC7XXX_HOST_H_ -#define _AIC7XXX_HOST_H_ - -#ifdef CONFIG_PROC_FS -int ahc_linux_proc_info(char *, char **, off_t, int, int, int); -#endif -int ahc_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); -int ahc_linux_detect(Scsi_Host_Template *); -int ahc_linux_release(struct Scsi_Host *); -const char *ahc_linux_info(struct Scsi_Host *); -int ahc_linux_biosparam(Disk *, kdev_t, int[]); -int ahc_linux_bus_reset(Scsi_Cmnd *); -int ahc_linux_dev_reset(Scsi_Cmnd *); -int ahc_linux_abort(Scsi_Cmnd *); - -#if defined(__i386__) -# define AIC7XXX_BIOSPARAM ahc_linux_biosparam -#else -# define AIC7XXX_BIOSPARAM NULL -#endif - -/* - * Scsi_Host_Template (see hosts.h) for AIC-7xxx - some fields - * to do with card config are filled in after the card is detected. - */ - -// proc_dir: NULL, - // proc_info: ahc_linux_proc_info, - - -#define AIC7XXX { \ - next: NULL, \ - module: NULL, \ - name: NULL, \ - detect: ahc_linux_detect, \ - release: ahc_linux_release, \ - info: ahc_linux_info, \ - command: NULL, \ - queuecommand: ahc_linux_queue, \ - eh_strategy_handler: NULL, \ - eh_abort_handler: ahc_linux_abort, \ - eh_device_reset_handler: ahc_linux_dev_reset, \ - eh_bus_reset_handler: ahc_linux_bus_reset, \ - eh_host_reset_handler: NULL, \ - abort: NULL, \ - reset: NULL, \ - slave_attach: NULL, \ - bios_param: AIC7XXX_BIOSPARAM, \ - can_queue: AHC_MAX_QUEUE,/* max simultaneous cmds */\ - this_id: -1, /* scsi id of host adapter */\ - sg_tablesize: AHC_NSEG, /* max scatter-gather cmds */\ - cmd_per_lun: 2, /* cmds per lun */\ - present: 0, /* number of 7xxx's present */\ - unchecked_isa_dma: 0, /* no memory DMA restrictions*/\ - use_clustering: ENABLE_CLUSTERING, \ - use_new_eh_code: 1 \ -} - -/* highmem_io: 1 \ - */ - -#endif /* _AIC7XXX_HOST_H_ */ diff --git a/xen/drivers/scsi/aic7xxx/aic7xxx_inline.h b/xen/drivers/scsi/aic7xxx/aic7xxx_inline.h deleted file mode 100644 index 2d774f2ab1..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic7xxx_inline.h +++ /dev/null @@ -1,563 +0,0 @@ -/* - * Inline routines shareable across OS platforms. - * - * Copyright (c) 1994-2001 Justin T. Gibbs. - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#35 $ - * - * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx_inline.h,v 1.2.2.11 2002/04/29 19:36:31 gibbs Exp $ - */ - -#ifndef _AIC7XXX_INLINE_H_ -#define _AIC7XXX_INLINE_H_ - -/************************* Sequencer Execution Control ************************/ -static __inline void ahc_pause_bug_fix(struct ahc_softc *ahc); -static __inline int ahc_is_paused(struct ahc_softc *ahc); -static __inline void ahc_pause(struct ahc_softc *ahc); -static __inline void ahc_unpause(struct ahc_softc *ahc); - -/* - * Work around any chip bugs related to halting sequencer execution. - * On Ultra2 controllers, we must clear the CIOBUS stretch signal by - * reading a register that will set this signal and deassert it. - * Without this workaround, if the chip is paused, by an interrupt or - * manual pause while accessing scb ram, accesses to certain registers - * will hang the system (infinite pci retries). - */ -static __inline void -ahc_pause_bug_fix(struct ahc_softc *ahc) -{ - if ((ahc->features & AHC_ULTRA2) != 0) - (void)ahc_inb(ahc, CCSCBCTL); -} - -/* - * Determine whether the sequencer has halted code execution. - * Returns non-zero status if the sequencer is stopped. - */ -static __inline int -ahc_is_paused(struct ahc_softc *ahc) -{ - return ((ahc_inb(ahc, HCNTRL) & PAUSE) != 0); -} - -/* - * Request that the sequencer stop and wait, indefinitely, for it - * to stop. The sequencer will only acknowledge that it is paused - * once it has reached an instruction boundary and PAUSEDIS is - * cleared in the SEQCTL register. The sequencer may use PAUSEDIS - * for critical sections. - */ -static __inline void -ahc_pause(struct ahc_softc *ahc) -{ - ahc_outb(ahc, HCNTRL, ahc->pause); - - /* - * Since the sequencer can disable pausing in a critical section, we - * must loop until it actually stops. - */ - while (ahc_is_paused(ahc) == 0) - ; - - ahc_pause_bug_fix(ahc); -} - -/* - * Allow the sequencer to continue program execution. - * We check here to ensure that no additional interrupt - * sources that would cause the sequencer to halt have been - * asserted. If, for example, a SCSI bus reset is detected - * while we are fielding a different, pausing, interrupt type, - * we don't want to release the sequencer before going back - * into our interrupt handler and dealing with this new - * condition. - */ -static __inline void -ahc_unpause(struct ahc_softc *ahc) -{ - if ((ahc_inb(ahc, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) == 0) - ahc_outb(ahc, HCNTRL, ahc->unpause); -} - -/*********************** Untagged Transaction Routines ************************/ -static __inline void ahc_freeze_untagged_queues(struct ahc_softc *ahc); -static __inline void ahc_release_untagged_queues(struct ahc_softc *ahc); - -/* - * Block our completion routine from starting the next untagged - * transaction for this target or target lun. - */ -static __inline void -ahc_freeze_untagged_queues(struct ahc_softc *ahc) -{ - if ((ahc->flags & AHC_SCB_BTT) == 0) - ahc->untagged_queue_lock++; -} - -/* - * Allow the next untagged transaction for this target or target lun - * to be executed. We use a counting semaphore to allow the lock - * to be acquired recursively. Once the count drops to zero, the - * transaction queues will be run. - */ -static __inline void -ahc_release_untagged_queues(struct ahc_softc *ahc) -{ - if ((ahc->flags & AHC_SCB_BTT) == 0) { - ahc->untagged_queue_lock--; - if (ahc->untagged_queue_lock == 0) - ahc_run_untagged_queues(ahc); - } -} - -/************************** Memory mapping routines ***************************/ -static __inline struct ahc_dma_seg * - ahc_sg_bus_to_virt(struct scb *scb, - uint32_t sg_busaddr); -static __inline uint32_t - ahc_sg_virt_to_bus(struct scb *scb, - struct ahc_dma_seg *sg); -static __inline uint32_t - ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index); -static __inline void ahc_sync_scb(struct ahc_softc *ahc, - struct scb *scb, int op); -static __inline void ahc_sync_sglist(struct ahc_softc *ahc, - struct scb *scb, int op); -static __inline uint32_t - ahc_targetcmd_offset(struct ahc_softc *ahc, - u_int index); - -static __inline struct ahc_dma_seg * -ahc_sg_bus_to_virt(struct scb *scb, uint32_t sg_busaddr) -{ - int sg_index; - - sg_index = (sg_busaddr - scb->sg_list_phys)/sizeof(struct ahc_dma_seg); - /* sg_list_phys points to entry 1, not 0 */ - sg_index++; - - return (&scb->sg_list[sg_index]); -} - -static __inline uint32_t -ahc_sg_virt_to_bus(struct scb *scb, struct ahc_dma_seg *sg) -{ - int sg_index; - - /* sg_list_phys points to entry 1, not 0 */ - sg_index = sg - &scb->sg_list[1]; - - return (scb->sg_list_phys + (sg_index * sizeof(*scb->sg_list))); -} - -static __inline uint32_t -ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index) -{ - return (ahc->scb_data->hscb_busaddr - + (sizeof(struct hardware_scb) * index)); -} - -static __inline void -ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op) -{ - ahc_dmamap_sync(ahc, ahc->scb_data->hscb_dmat, - ahc->scb_data->hscb_dmamap, - /*offset*/(scb->hscb - ahc->hscbs) * sizeof(*scb->hscb), - /*len*/sizeof(*scb->hscb), op); -} - -static __inline void -ahc_sync_sglist(struct ahc_softc *ahc, struct scb *scb, int op) -{ - if (scb->sg_count == 0) - return; - - ahc_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap, - /*offset*/(scb->sg_list - scb->sg_map->sg_vaddr) - * sizeof(struct ahc_dma_seg), - /*len*/sizeof(struct ahc_dma_seg) * scb->sg_count, op); -} - -static __inline uint32_t -ahc_targetcmd_offset(struct ahc_softc *ahc, u_int index) -{ - return (((uint8_t *)&ahc->targetcmds[index]) - ahc->qoutfifo); -} - -/******************************** Debugging ***********************************/ -static __inline char *ahc_name(struct ahc_softc *ahc); - -static __inline char * -ahc_name(struct ahc_softc *ahc) -{ - return (ahc->name); -} - -/*********************** Miscelaneous Support Functions ***********************/ - -static __inline void ahc_update_residual(struct ahc_softc *ahc, - struct scb *scb); -static __inline struct ahc_initiator_tinfo * - ahc_fetch_transinfo(struct ahc_softc *ahc, - char channel, u_int our_id, - u_int remote_id, - struct ahc_tmode_tstate **tstate); -static __inline struct scb* - ahc_get_scb(struct ahc_softc *ahc); -static __inline void ahc_free_scb(struct ahc_softc *ahc, struct scb *scb); -static __inline void ahc_swap_with_next_hscb(struct ahc_softc *ahc, - struct scb *scb); -static __inline void ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb); -static __inline struct scsi_sense_data * - ahc_get_sense_buf(struct ahc_softc *ahc, - struct scb *scb); -static __inline uint32_t - ahc_get_sense_bufaddr(struct ahc_softc *ahc, - struct scb *scb); - -/* - * Determine whether the sequencer reported a residual - * for this SCB/transaction. - */ -static __inline void -ahc_update_residual(struct ahc_softc *ahc, struct scb *scb) -{ - uint32_t sgptr; - - sgptr = ahc_le32toh(scb->hscb->sgptr); - if ((sgptr & SG_RESID_VALID) != 0) - ahc_calc_residual(ahc, scb); -} - -/* - * Return pointers to the transfer negotiation information - * for the specified our_id/remote_id pair. - */ -static __inline struct ahc_initiator_tinfo * -ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id, - u_int remote_id, struct ahc_tmode_tstate **tstate) -{ - /* - * Transfer data structures are stored from the perspective - * of the target role. Since the parameters for a connection - * in the initiator role to a given target are the same as - * when the roles are reversed, we pretend we are the target. - */ - if (channel == 'B') - our_id += 8; - *tstate = ahc->enabled_targets[our_id]; - return (&(*tstate)->transinfo[remote_id]); -} - -/* - * Get a free scb. If there are none, see if we can allocate a new SCB. - */ -static __inline struct scb * -ahc_get_scb(struct ahc_softc *ahc) -{ - struct scb *scb; - - if ((scb = SLIST_FIRST(&ahc->scb_data->free_scbs)) == NULL) { - ahc_alloc_scbs(ahc); - scb = SLIST_FIRST(&ahc->scb_data->free_scbs); - if (scb == NULL) - return (NULL); - } - SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links.sle); - return (scb); -} - -/* - * Return an SCB resource to the free list. - */ -static __inline void -ahc_free_scb(struct ahc_softc *ahc, struct scb *scb) -{ - struct hardware_scb *hscb; - - hscb = scb->hscb; - /* Clean up for the next user */ - ahc->scb_data->scbindex[hscb->tag] = NULL; - scb->flags = SCB_FREE; - hscb->control = 0; - - SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle); - - /* Notify the OSM that a resource is now available. */ - ahc_platform_scb_free(ahc, scb); -} - -static __inline struct scb * -ahc_lookup_scb(struct ahc_softc *ahc, u_int tag) -{ - struct scb* scb; - - scb = ahc->scb_data->scbindex[tag]; - if (scb != NULL) - ahc_sync_scb(ahc, scb, - BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); - return (scb); -} - -static __inline void -ahc_swap_with_next_hscb(struct ahc_softc *ahc, struct scb *scb) -{ - struct hardware_scb *q_hscb; - u_int saved_tag; - - /* - * Our queuing method is a bit tricky. The card - * knows in advance which HSCB to download, and we - * can't disappoint it. To achieve this, the next - * SCB to download is saved off in ahc->next_queued_scb. - * When we are called to queue "an arbitrary scb", - * we copy the contents of the incoming HSCB to the one - * the sequencer knows about, swap HSCB pointers and - * finally assign the SCB to the tag indexed location - * in the scb_array. This makes sure that we can still - * locate the correct SCB by SCB_TAG. - */ - q_hscb = ahc->next_queued_scb->hscb; - saved_tag = q_hscb->tag; - memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); - if ((scb->flags & SCB_CDB32_PTR) != 0) { - q_hscb->shared_data.cdb_ptr = - ahc_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag) - + offsetof(struct hardware_scb, cdb32)); - } - q_hscb->tag = saved_tag; - q_hscb->next = scb->hscb->tag; - - /* Now swap HSCB pointers. */ - ahc->next_queued_scb->hscb = scb->hscb; - scb->hscb = q_hscb; - - /* Now define the mapping from tag to SCB in the scbindex */ - ahc->scb_data->scbindex[scb->hscb->tag] = scb; -} - -/* - * Tell the sequencer about a new transaction to execute. - */ -static __inline void -ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb) -{ - ahc_swap_with_next_hscb(ahc, scb); - - if (scb->hscb->tag == SCB_LIST_NULL - || scb->hscb->next == SCB_LIST_NULL) - panic("Attempt to queue invalid SCB tag %x:%x\n", - scb->hscb->tag, scb->hscb->next); - - /* - * Keep a history of SCBs we've downloaded in the qinfifo. - */ - ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag; - - /* - * Make sure our data is consistant from the - * perspective of the adapter. - */ - ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); - - /* Tell the adapter about the newly queued SCB */ - if ((ahc->features & AHC_QUEUE_REGS) != 0) { - ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext); - } else { - if ((ahc->features & AHC_AUTOPAUSE) == 0) - ahc_pause(ahc); - ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext); - if ((ahc->features & AHC_AUTOPAUSE) == 0) - ahc_unpause(ahc); - } -} - -static __inline struct scsi_sense_data * -ahc_get_sense_buf(struct ahc_softc *ahc, struct scb *scb) -{ - int offset; - - offset = scb - ahc->scb_data->scbarray; - return (&ahc->scb_data->sense[offset]); -} - -static __inline uint32_t -ahc_get_sense_bufaddr(struct ahc_softc *ahc, struct scb *scb) -{ - int offset; - - offset = scb - ahc->scb_data->scbarray; - return (ahc->scb_data->sense_busaddr - + (offset * sizeof(struct scsi_sense_data))); -} - -/************************** Interrupt Processing ******************************/ -static __inline void ahc_sync_qoutfifo(struct ahc_softc *ahc, int op); -static __inline void ahc_sync_tqinfifo(struct ahc_softc *ahc, int op); -static __inline u_int ahc_check_cmdcmpltqueues(struct ahc_softc *ahc); -static __inline void ahc_intr(struct ahc_softc *ahc); - -static __inline void -ahc_sync_qoutfifo(struct ahc_softc *ahc, int op) -{ - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, - /*offset*/0, /*len*/256, op); -} - -static __inline void -ahc_sync_tqinfifo(struct ahc_softc *ahc, int op) -{ -#ifdef AHC_TARGET_MODE - if ((ahc->flags & AHC_TARGETROLE) != 0) { - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, - ahc->shared_data_dmamap, - ahc_targetcmd_offset(ahc, 0), - sizeof(struct target_cmd) * AHC_TMODE_CMDS, - op); - } -#endif -} - -/* - * See if the firmware has posted any completed commands - * into our in-core command complete fifos. - */ -#define AHC_RUN_QOUTFIFO 0x1 -#define AHC_RUN_TQINFIFO 0x2 -static __inline u_int -ahc_check_cmdcmpltqueues(struct ahc_softc *ahc) -{ - u_int retval; - - retval = 0; - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, - /*offset*/ahc->qoutfifonext, /*len*/1, - BUS_DMASYNC_POSTREAD); - if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL) - retval |= AHC_RUN_QOUTFIFO; -#ifdef AHC_TARGET_MODE - if ((ahc->flags & AHC_TARGETROLE) != 0 - && (ahc->flags & AHC_TQINFIFO_BLOCKED) == 0) { - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, - ahc->shared_data_dmamap, - ahc_targetcmd_offset(ahc, ahc->tqinfifofnext), - /*len*/sizeof(struct target_cmd), - BUS_DMASYNC_POSTREAD); - if (ahc->targetcmds[ahc->tqinfifonext].cmd_valid != 0) - retval |= AHC_RUN_TQINFIFO; - } -#endif - return (retval); -} - -/* - * Catch an interrupt from the adapter - */ -static __inline void -ahc_intr(struct ahc_softc *ahc) -{ - u_int intstat; - - /* - * Instead of directly reading the interrupt status register, - * infer the cause of the interrupt by checking our in-core - * completion queues. This avoids a costly PCI bus read in - * most cases. - */ - if ((ahc->flags & (AHC_ALL_INTERRUPTS|AHC_EDGE_INTERRUPT)) == 0 - && (ahc_check_cmdcmpltqueues(ahc) != 0)) - intstat = CMDCMPLT; - else { - intstat = ahc_inb(ahc, INTSTAT); - } - - if (intstat & CMDCMPLT) { - ahc_outb(ahc, CLRINT, CLRCMDINT); - - /* - * Ensure that the chip sees that we've cleared - * this interrupt before we walk the output fifo. - * Otherwise, we may, due to posted bus writes, - * clear the interrupt after we finish the scan, - * and after the sequencer has added new entries - * and asserted the interrupt again. - */ - ahc_flush_device_writes(ahc); - ahc_run_qoutfifo(ahc); -#ifdef AHC_TARGET_MODE - if ((ahc->flags & AHC_TARGETROLE) != 0) - ahc_run_tqinfifo(ahc, /*paused*/FALSE); -#endif - } - - if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0) - /* Hot eject */ - return; - - if ((intstat & INT_PEND) == 0) { -#if AHC_PCI_CONFIG > 0 - if (ahc->unsolicited_ints > 500) { - ahc->unsolicited_ints = 0; - if ((ahc->chip & AHC_PCI) != 0 - && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0) - ahc->bus_intr(ahc); - } -#endif - ahc->unsolicited_ints++; - return; - } - ahc->unsolicited_ints = 0; - - if (intstat & BRKADRINT) { - ahc_handle_brkadrint(ahc); - /* Fatal error, no more interrupts to handle. */ - return; - } - - if ((intstat & (SEQINT|SCSIINT)) != 0) - ahc_pause_bug_fix(ahc); - - if ((intstat & SEQINT) != 0) - ahc_handle_seqint(ahc, intstat); - - if ((intstat & SCSIINT) != 0) - ahc_handle_scsiint(ahc, intstat); -} - -#endif /* _AIC7XXX_INLINE_H_ */ diff --git a/xen/drivers/scsi/aic7xxx/aic7xxx_osm.c b/xen/drivers/scsi/aic7xxx/aic7xxx_osm.c deleted file mode 100644 index f305095da7..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ /dev/null @@ -1,3073 +0,0 @@ -/* - * Adaptec AIC7xxx device driver for Linux. - * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#103 $ - * - * Copyright (c) 1994 John Aycock - * The University of Calgary Department of Computer Science. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Sources include the Adaptec 1740 driver (aha1740.c), the Ultrastor 24F - * driver (ultrastor.c), various Linux kernel source, the Adaptec EISA - * config file (!adp7771.cfg), the Adaptec AHA-2740A Series User's Guide, - * the Linux Kernel Hacker's Guide, Writing a SCSI Device Driver for Linux, - * the Adaptec 1542 driver (aha1542.c), the Adaptec EISA overlay file - * (adp7770.ovl), the Adaptec AHA-2740 Series Technical Reference Manual, - * the Adaptec AIC-7770 Data Book, the ANSI SCSI specification, the - * ANSI SCSI-2 specification (draft 10c), ... - * - * -------------------------------------------------------------------------- - * - * Modifications by Daniel M. Eischen (deischen@iworks.InterWorks.org): - * - * Substantially modified to include support for wide and twin bus - * adapters, DMAing of SCBs, tagged queueing, IRQ sharing, bug fixes, - * SCB paging, and other rework of the code. - * - * -------------------------------------------------------------------------- - * Copyright (c) 1994-2000 Justin T. Gibbs. - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - *--------------------------------------------------------------------------- - * - * Thanks also go to (in alphabetical order) the following: - * - * Rory Bolt - Sequencer bug fixes - * Jay Estabrook - Initial DEC Alpha support - * Doug Ledford - Much needed abort/reset bug fixes - * Kai Makisara - DMAing of SCBs - * - * A Boot time option was also added for not resetting the scsi bus. - * - * Form: aic7xxx=extended - * aic7xxx=no_reset - * aic7xxx=verbose - * - * Daniel M. Eischen, deischen@iworks.InterWorks.org, 1/23/97 - * - * Id: aic7xxx.c,v 4.1 1997/06/12 08:23:42 deang Exp - */ - -/* - * Further driver modifications made by Doug Ledford - * - * Copyright (c) 1997-1999 Doug Ledford - * - * These changes are released under the same licensing terms as the FreeBSD - * driver written by Justin Gibbs. Please see his Copyright notice above - * for the exact terms and conditions covering my changes as well as the - * warranty statement. - * - * Modifications made to the aic7xxx.c,v 4.1 driver from Dan Eischen include - * but are not limited to: - * - * 1: Import of the latest FreeBSD sequencer code for this driver - * 2: Modification of kernel code to accomodate different sequencer semantics - * 3: Extensive changes throughout kernel portion of driver to improve - * abort/reset processing and error hanndling - * 4: Other work contributed by various people on the Internet - * 5: Changes to printk information and verbosity selection code - * 6: General reliability related changes, especially in IRQ management - * 7: Modifications to the default probe/attach order for supported cards - * 8: SMP friendliness has been improved - * - */ - -/* - * This is the only file where module.h should - * embed module global version info. - */ -//#define AHC_MODVERSION_FILE - -#include -#include -#include "aic7xxx_osm.h" -#include "aic7xxx_inline.h" - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) -#include /* __setup */ -#endif - -#include "../sd.h" /* For geometry detection */ - -#include /* For fetching system memory size */ -#include /* For block_size() */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) -/* - * Lock protecting manipulation of the ahc softc list. - */ -spinlock_t ahc_list_spinlock; -#endif - -/* - * To generate the correct addresses for the controller to issue - * on the bus. Originally added for DEC Alpha support. - */ -#define VIRT_TO_BUS(a) (uint32_t)virt_to_bus((void *)(a)) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -struct proc_dir_entry proc_scsi_aic7xxx = { - PROC_SCSI_AIC7XXX, 7, "aic7xxx", - S_IFDIR | S_IRUGO | S_IXUGO, 2, - 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; -#endif - -/* - * Set this to the delay in seconds after SCSI bus reset. - * Note, we honor this only for the initial bus reset. - * The scsi error recovery code performs its own bus settle - * delay handling for error recovery actions. - */ -#ifdef CONFIG_AIC7XXX_RESET_DELAY_MS -#define AIC7XXX_RESET_DELAY CONFIG_AIC7XXX_RESET_DELAY_MS -#else -#define AIC7XXX_RESET_DELAY 500 -#endif - -/* - * Control collection of SCSI transfer statistics for the /proc filesystem. - * - * NOTE: Do NOT enable this when running on kernels version 1.2.x and below. - * NOTE: This does affect performance since it has to maintain statistics. - */ -#ifdef CONFIG_AIC7XXX_PROC_STATS -#define AIC7XXX_PROC_STATS -#endif - -/* - * To change the default number of tagged transactions allowed per-device, - * add a line to the lilo.conf file like: - * append="aic7xxx=verbose,tag_info:{{32,32,32,32},{32,32,32,32}}" - * which will result in the first four devices on the first two - * controllers being set to a tagged queue depth of 32. - * - * The tag_commands is an array of 16 to allow for wide and twin adapters. - * Twin adapters will use indexes 0-7 for channel 0, and indexes 8-15 - * for channel 1. - */ -typedef struct { - uint8_t tag_commands[16]; /* Allow for wide/twin adapters. */ -} adapter_tag_info_t; - -/* - * Modify this as you see fit for your system. - * - * 0 tagged queuing disabled - * 1 <= n <= 253 n == max tags ever dispatched. - * - * The driver will throttle the number of commands dispatched to a - * device if it returns queue full. For devices with a fixed maximum - * queue depth, the driver will eventually determine this depth and - * lock it in (a console message is printed to indicate that a lock - * has occurred). On some devices, queue full is returned for a temporary - * resource shortage. These devices will return queue full at varying - * depths. The driver will throttle back when the queue fulls occur and - * attempt to slowly increase the depth over time as the device recovers - * from the resource shortage. - * - * In this example, the first line will disable tagged queueing for all - * the devices on the first probed aic7xxx adapter. - * - * The second line enables tagged queueing with 4 commands/LUN for IDs - * (0, 2-11, 13-15), disables tagged queueing for ID 12, and tells the - * driver to attempt to use up to 64 tags for ID 1. - * - * The third line is the same as the first line. - * - * The fourth line disables tagged queueing for devices 0 and 3. It - * enables tagged queueing for the other IDs, with 16 commands/LUN - * for IDs 1 and 4, 127 commands/LUN for ID 8, and 4 commands/LUN for - * IDs 2, 5-7, and 9-15. - */ - -/* - * NOTE: The below structure is for reference only, the actual structure - * to modify in order to change things is just below this comment block. -adapter_tag_info_t aic7xxx_tag_info[] = -{ - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{4, 64, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4}}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0, 16, 4, 0, 16, 4, 4, 4, 127, 4, 4, 4, 4, 4, 4, 4}} -}; -*/ - -#ifdef CONFIG_AIC7XXX_CMDS_PER_DEVICE -#define AIC7XXX_CMDS_PER_DEVICE CONFIG_AIC7XXX_CMDS_PER_DEVICE -#else -#define AIC7XXX_CMDS_PER_DEVICE AHC_MAX_QUEUE -#endif - -#define AIC7XXX_CONFIGED_TAG_COMMANDS { \ - AIC7XXX_CMDS_PER_DEVICE, AIC7XXX_CMDS_PER_DEVICE, \ - AIC7XXX_CMDS_PER_DEVICE, AIC7XXX_CMDS_PER_DEVICE, \ - AIC7XXX_CMDS_PER_DEVICE, AIC7XXX_CMDS_PER_DEVICE, \ - AIC7XXX_CMDS_PER_DEVICE, AIC7XXX_CMDS_PER_DEVICE, \ - AIC7XXX_CMDS_PER_DEVICE, AIC7XXX_CMDS_PER_DEVICE, \ - AIC7XXX_CMDS_PER_DEVICE, AIC7XXX_CMDS_PER_DEVICE, \ - AIC7XXX_CMDS_PER_DEVICE, AIC7XXX_CMDS_PER_DEVICE, \ - AIC7XXX_CMDS_PER_DEVICE, AIC7XXX_CMDS_PER_DEVICE \ -} - -/* - * By default, use the number of commands specified by - * the users kernel configuration. - */ -static adapter_tag_info_t aic7xxx_tag_info[] = -{ - {AIC7XXX_CONFIGED_TAG_COMMANDS}, - {AIC7XXX_CONFIGED_TAG_COMMANDS}, - {AIC7XXX_CONFIGED_TAG_COMMANDS}, - {AIC7XXX_CONFIGED_TAG_COMMANDS}, - {AIC7XXX_CONFIGED_TAG_COMMANDS}, - {AIC7XXX_CONFIGED_TAG_COMMANDS}, - {AIC7XXX_CONFIGED_TAG_COMMANDS}, - {AIC7XXX_CONFIGED_TAG_COMMANDS}, - {AIC7XXX_CONFIGED_TAG_COMMANDS}, - {AIC7XXX_CONFIGED_TAG_COMMANDS}, - {AIC7XXX_CONFIGED_TAG_COMMANDS}, - {AIC7XXX_CONFIGED_TAG_COMMANDS}, - {AIC7XXX_CONFIGED_TAG_COMMANDS}, - {AIC7XXX_CONFIGED_TAG_COMMANDS}, - {AIC7XXX_CONFIGED_TAG_COMMANDS}, - {AIC7XXX_CONFIGED_TAG_COMMANDS} -}; - -/* - * There should be a specific return value for this in scsi.h, but - * it seems that most drivers ignore it. - */ -#define DID_UNDERFLOW DID_ERROR - -void -ahc_print_path(struct ahc_softc *ahc, struct scb *scb) -{ - printf("(scsi%d:%c:%d:%d): ", - ahc->platform_data->host->host_no, - scb != NULL ? SCB_GET_CHANNEL(ahc, scb) : 'X', - scb != NULL ? SCB_GET_TARGET(ahc, scb) : -1, - scb != NULL ? SCB_GET_LUN(scb) : -1); -} - -/* - * XXX - these options apply unilaterally to _all_ 274x/284x/294x - * cards in the system. This should be fixed. Exceptions to this - * rule are noted in the comments. - */ - -/* - * Skip the scsi bus reset. Non 0 make us skip the reset at startup. This - * has no effect on any later resets that might occur due to things like - * SCSI bus timeouts. - */ -static uint32_t aic7xxx_no_reset; - -/* - * Certain PCI motherboards will scan PCI devices from highest to lowest, - * others scan from lowest to highest, and they tend to do all kinds of - * strange things when they come into contact with PCI bridge chips. The - * net result of all this is that the PCI card that is actually used to boot - * the machine is very hard to detect. Most motherboards go from lowest - * PCI slot number to highest, and the first SCSI controller found is the - * one you boot from. The only exceptions to this are when a controller - * has its BIOS disabled. So, we by default sort all of our SCSI controllers - * from lowest PCI slot number to highest PCI slot number. We also force - * all controllers with their BIOS disabled to the end of the list. This - * works on *almost* all computers. Where it doesn't work, we have this - * option. Setting this option to non-0 will reverse the order of the sort - * to highest first, then lowest, but will still leave cards with their BIOS - * disabled at the very end. That should fix everyone up unless there are - * really strange cirumstances. - */ -static int aic7xxx_reverse_scan = 0; - -/* - * Should we force EXTENDED translation on a controller. - * 0 == Use whatever is in the SEEPROM or default to off - * 1 == Use whatever is in the SEEPROM or default to on - */ -static uint32_t aic7xxx_extended = 0; - -/* - * PCI bus parity checking of the Adaptec controllers. This is somewhat - * dubious at best. To my knowledge, this option has never actually - * solved a PCI parity problem, but on certain machines with broken PCI - * chipset configurations, it can generate tons of false error messages. - * It's included in the driver for completeness. - * 0 = Shut off PCI parity check - * -1 = Normal polarity pci parity checking - * 1 = reverse polarity pci parity checking - * - * NOTE: you can't actually pass -1 on the lilo prompt. So, to set this - * variable to -1 you would actually want to simply pass the variable - * name without a number. That will invert the 0 which will result in - * -1. - */ -static int aic7xxx_pci_parity = 0; - -/* - * Certain newer motherboards have put new PCI based devices into the - * IO spaces that used to typically be occupied by VLB or EISA cards. - * This overlap can cause these newer motherboards to lock up when scanned - * for older EISA and VLB devices. Setting this option to non-0 will - * cause the driver to skip scanning for any VLB or EISA controllers and - * only support the PCI controllers. NOTE: this means that if the kernel - * os compiled with PCI support disabled, then setting this to non-0 - * would result in never finding any devices :) - */ -#ifndef CONFIG_AIC7XXX_PROBE_EISA_VL -#define CONFIG_AIC7XXX_PROBE_EISA_VL n -#endif -#if CONFIG_AIC7XXX_PROBE_EISA_VL == n -static int aic7xxx_no_probe = 1; -#else -static int aic7xxx_no_probe; -#endif - -/* - * aic7xxx_detect() has been run, so register all device arrivals - * immediately with the system rather than deferring to the sorted - * attachment performed by aic7xxx_detect(). - */ -int aic7xxx_detect_complete; - -/* - * So that we can set how long each device is given as a selection timeout. - * The table of values goes like this: - * 0 - 256ms - * 1 - 128ms - * 2 - 64ms - * 3 - 32ms - * We default to 256ms because some older devices need a longer time - * to respond to initial selection. - */ -static int aic7xxx_seltime = 0x00; - -/* - * Certain devices do not perform any aging on commands. Should the - * device be saturated by commands in one portion of the disk, it is - * possible for transactions on far away sectors to never be serviced. - * To handle these devices, we can periodically send an ordered tag to - * force all outstanding transactions to be serviced prior to a new - * transaction. - */ -int aic7xxx_periodic_otag; - -/* - * Module information and settable options. - */ -#ifdef MODULE -static char *aic7xxx = NULL; -/* - * Just in case someone uses commas to separate items on the insmod - * command line, we define a dummy buffer here to avoid having insmod - * write wild stuff into our code segment - */ -static char dummy_buffer[60] = "Please don't trounce on me insmod!!\n"; -/* -MODULE_AUTHOR("Maintainer: Justin T. Gibbs "); -MODULE_DESCRIPTION("Adaptec Aic77XX/78XX SCSI Host Bus Adapter driver"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10) -MODULE_LICENSE("Dual BSD/GPL"); -#endif -MODULE_PARM(aic7xxx, "s"); -MODULE_PARM_DESC(aic7xxx, "period delimited, options string. - verbose Enable verbose/diagnostic logging - no_probe Disable EISA/VLB controller probing - no_reset Supress initial bus resets - extended Enable extended geometry on all controllers - periodic_otag Send an ordered tagged transaction periodically - to prevent tag starvation. This may be - required by some older disk drives/RAID arrays. - reverse_scan Sort PCI devices highest Bus/Slot to lowest - tag_info: Set per-target tag depth - seltime: Selection Timeout(0/256ms,1/128ms,2/64ms,3/32ms) - - Sample /etc/modules.conf line: - Enable verbose logging - Disable EISA/VLB probing - Set tag depth on Controller 2/Target 2 to 10 tags - Shorten the selection timeout to 128ms from its default of 256 - - options aic7xxx='\"verbose.no_probe.tag_info:{{}.{}.{..10}}.seltime:1\"' -"); -*/ -#endif - -static void ahc_linux_handle_scsi_status(struct ahc_softc *, - struct ahc_linux_device *, - struct scb *); -static void ahc_linux_filter_command(struct ahc_softc*, Scsi_Cmnd*, - struct scb*); -#if 0 -static void ahc_linux_sem_timeout(u_long arg); -static void ahc_linux_freeze_sim_queue(struct ahc_softc *ahc); -static void ahc_linux_release_sim_queue(u_long arg); -#endif -static void ahc_linux_dev_timed_unfreeze(u_long arg); -static int ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag); -static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); -static void ahc_linux_select_queue_depth(struct Scsi_Host *host, - Scsi_Device *scsi_devs); -static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo); -static void ahc_linux_device_queue_depth(struct ahc_softc *ahc, - Scsi_Device *device); -static struct ahc_linux_target* ahc_linux_alloc_target(struct ahc_softc*, - u_int, u_int); -static void ahc_linux_free_target(struct ahc_softc*, - struct ahc_linux_target*); -static struct ahc_linux_device* ahc_linux_alloc_device(struct ahc_softc*, - struct ahc_linux_target*, - u_int); -static void ahc_linux_free_device(struct ahc_softc*, - struct ahc_linux_device*); -static void ahc_linux_run_device_queue(struct ahc_softc*, - struct ahc_linux_device*); -static void ahc_linux_setup_tag_info(char *p, char *end); -static int ahc_linux_next_unit(void); -static void ahc_runq_tasklet(unsigned long data); -#if 0 -static int ahc_linux_halt(struct notifier_block *nb, u_long event, void *buf); -#endif - -static __inline struct ahc_linux_device* - ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, - u_int target, u_int lun, int alloc); -static __inline void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, - Scsi_Cmnd *cmd); -static __inline void ahc_linux_run_complete_queue(struct ahc_softc *ahc, - struct ahc_cmd *acmd); -static __inline void ahc_linux_check_device_queue(struct ahc_softc *ahc, - struct ahc_linux_device *dev); -static __inline struct ahc_linux_device * - ahc_linux_next_device_to_run(struct ahc_softc *ahc); -static __inline void ahc_linux_run_device_queues(struct ahc_softc *ahc); -static __inline void ahc_linux_sniff_command(struct ahc_softc*, Scsi_Cmnd*, - struct scb*); -static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*); - -static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, - struct ahc_dma_seg *sg, - bus_addr_t addr, bus_size_t len); - -static __inline struct ahc_linux_device* -ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, - u_int lun, int alloc) -{ - struct ahc_linux_target *targ; - struct ahc_linux_device *dev; - u_int target_offset; - - target_offset = target; - if (channel != 0) - target_offset += 8; - targ = ahc->platform_data->targets[target_offset]; - if (targ == NULL) { - if (alloc != 0) { - targ = ahc_linux_alloc_target(ahc, channel, target); - if (targ == NULL) - return (NULL); - } else - return (NULL); - } - dev = targ->devices[lun]; - if (dev == NULL && alloc != 0) - dev = ahc_linux_alloc_device(ahc, targ, lun); - return (dev); -} - -static __inline void -ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, Scsi_Cmnd *cmd) -{ - /* - * Typically, the complete queue has very few entries - * queued to it before the queue is emptied by - * ahc_linux_run_complete_queue, so sorting the entries - * by generation number should be inexpensive. - * We perform the sort so that commands that complete - * with an error are retuned in the order origionally - * queued to the controller so that any subsequent retries - * are performed in order. The underlying ahc routines do - * not guarantee the order that aborted commands will be - * returned to us. - */ - struct ahc_completeq *completeq; - struct ahc_cmd *list_cmd; - struct ahc_cmd *acmd; - - /* - * If we want the request requeued, make sure there - * are sufficent retries. In the old scsi error code, - * we used to be able to specify a result code that - * bypassed the retry count. Now we must use this - * hack. - */ - if (cmd->result == (CAM_REQUEUE_REQ << 16)) - cmd->retries--; - completeq = &ahc->platform_data->completeq; - list_cmd = TAILQ_FIRST(completeq); - acmd = (struct ahc_cmd *)cmd; - while (list_cmd != NULL - && acmd_scsi_cmd(list_cmd).serial_number - < acmd_scsi_cmd(acmd).serial_number) - list_cmd = TAILQ_NEXT(list_cmd, acmd_links.tqe); - if (list_cmd != NULL) - TAILQ_INSERT_BEFORE(list_cmd, acmd, acmd_links.tqe); - else - TAILQ_INSERT_TAIL(completeq, acmd, acmd_links.tqe); -} - -static __inline void -ahc_linux_run_complete_queue(struct ahc_softc *ahc, struct ahc_cmd *acmd) -{ - u_long done_flags; - - ahc_done_lock(ahc, &done_flags); - while (acmd != NULL) { - Scsi_Cmnd *cmd; - - cmd = &acmd_scsi_cmd(acmd); - acmd = TAILQ_NEXT(acmd, acmd_links.tqe); - cmd->host_scribble = NULL; - cmd->scsi_done(cmd); - } - ahc_done_unlock(ahc, &done_flags); -} - -static __inline void -ahc_linux_check_device_queue(struct ahc_softc *ahc, - struct ahc_linux_device *dev) -{ - if ((dev->flags & AHC_DEV_FREEZE_TIL_EMPTY) != 0 - && dev->active == 0) { - dev->flags &= ~AHC_DEV_FREEZE_TIL_EMPTY; - dev->qfrozen--; - } - - if (TAILQ_FIRST(&dev->busyq) == NULL - || dev->openings == 0 || dev->qfrozen != 0) - return; - - ahc_linux_run_device_queue(ahc, dev); -} - -static __inline struct ahc_linux_device * -ahc_linux_next_device_to_run(struct ahc_softc *ahc) -{ - - if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0 - || ahc->platform_data->qfrozen != 0) - return (NULL); - return (TAILQ_FIRST(&ahc->platform_data->device_runq)); -} - -static __inline void -ahc_linux_run_device_queues(struct ahc_softc *ahc) -{ - struct ahc_linux_device *dev; - - while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) { - TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links); - dev->flags &= ~AHC_DEV_ON_RUN_LIST; - ahc_linux_check_device_queue(ahc, dev); - } -} - -static __inline void -ahc_linux_sniff_command(struct ahc_softc *ahc, Scsi_Cmnd *cmd, struct scb *scb) -{ - /* - * Determine whether we care to filter - * information out of this command. If so, - * pass it on to ahc_linux_filter_command() for more - * heavy weight processing. - */ - if (cmd->cmnd[0] == INQUIRY) - ahc_linux_filter_command(ahc, cmd, scb); -} - -static __inline void -ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb) -{ - Scsi_Cmnd *cmd; - - cmd = scb->io_ctx; - ahc_sync_sglist(ahc, scb, BUS_DMASYNC_POSTWRITE); - if (cmd->use_sg != 0) { - struct scatterlist *sg; - - sg = (struct scatterlist *)cmd->request_buffer; - pci_unmap_sg(ahc->dev_softc, sg, cmd->use_sg, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); - } else if (cmd->request_bufflen != 0) { - pci_unmap_single(ahc->dev_softc, - scb->platform_data->buf_busaddr, - cmd->request_bufflen, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); - } -} - -static __inline int -ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, - struct ahc_dma_seg *sg, bus_addr_t addr, bus_size_t len) -{ - int consumed; - - if ((scb->sg_count + 1) > AHC_NSEG) - panic("Too few segs for dma mapping. " - "Increase AHC_NSEG\n"); - - consumed = 1; - sg->addr = ahc_htole32(addr & 0xFFFFFFFF); - scb->platform_data->xfer_len += len; - if (sizeof(bus_addr_t) > 4 - && (ahc->flags & AHC_39BIT_ADDRESSING) != 0) { - /* - * Due to DAC restrictions, we can't - * cross a 4GB boundary. - */ - if ((addr ^ (addr + len - 1)) & ~0xFFFFFFFF) { - struct ahc_dma_seg *next_sg; - uint32_t next_len; - - printf("Crossed Seg\n"); - if ((scb->sg_count + 2) > AHC_NSEG) - panic("Too few segs for dma mapping. " - "Increase AHC_NSEG\n"); - - consumed++; - next_sg = sg + 1; - next_sg->addr = 0; - next_len = (uint32_t)((-addr) & 0xFFFFFFFF); - len -= next_len; - next_len |= ((addr >> 8) + 0x1000000) & 0x7F000000; - next_sg->len = ahc_htole32(next_len); - } - len |= (addr >> 8) & 0x7F000000; - } - sg->len = ahc_htole32(len); - return (consumed); -} - -/**************************** Tasklet Handler *********************************/ - -static void -ahc_runq_tasklet(unsigned long data) -{ - struct ahc_softc* ahc; - struct ahc_linux_device *dev; - u_long flags; - - ahc = (struct ahc_softc *)data; - ahc_lock(ahc, &flags); - while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) { - - TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links); - dev->flags &= ~AHC_DEV_ON_RUN_LIST; - ahc_linux_check_device_queue(ahc, dev); - /* Yeild to our interrupt handler */ - ahc_unlock(ahc, &flags); - ahc_lock(ahc, &flags); - } - ahc_unlock(ahc, &flags); -} - -/************************ Shutdown/halt/reboot hook ***************************/ -#include -#include - -#if XEN_KILLED -static struct notifier_block ahc_linux_notifier = { - ahc_linux_halt, NULL, 0 -}; - -static int ahc_linux_halt(struct notifier_block *nb, u_long event, void *buf) -{ - struct ahc_softc *ahc; - - if (event == SYS_DOWN || event == SYS_HALT) { - TAILQ_FOREACH(ahc, &ahc_tailq, links) { - ahc_shutdown(ahc); - } - } - return (NOTIFY_OK); -} -#endif - -/******************************** Macros **************************************/ -#define BUILD_SCSIID(ahc, cmd) \ - ((((cmd)->target << TID_SHIFT) & TID) \ - | (((cmd)->channel == 0) ? (ahc)->our_id : (ahc)->our_id_b) \ - | (((cmd)->channel == 0) ? 0 : TWIN_CHNLB)) - -/******************************** Bus DMA *************************************/ -int -ahc_dma_tag_create(struct ahc_softc *ahc, bus_dma_tag_t parent, - bus_size_t alignment, bus_size_t boundary, - bus_addr_t lowaddr, bus_addr_t highaddr, - bus_dma_filter_t *filter, void *filterarg, - bus_size_t maxsize, int nsegments, - bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag) -{ - bus_dma_tag_t dmat; - - dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT); - if (dmat == NULL) - return (ENOMEM); - - /* - * Linux is very simplistic about DMA memory. For now don't - * maintain all specification information. Once Linux supplies - * better facilities for doing these operations, or the - * needs of this particular driver change, we might need to do - * more here. - */ - dmat->alignment = alignment; - dmat->boundary = boundary; - dmat->maxsize = maxsize; - *ret_tag = dmat; - return (0); -} - -void -ahc_dma_tag_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat) -{ - free(dmat, M_DEVBUF); -} - -int -ahc_dmamem_alloc(struct ahc_softc *ahc, bus_dma_tag_t dmat, void** vaddr, - int flags, bus_dmamap_t *mapp) -{ - bus_dmamap_t map; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT); - if (map == NULL) - return (ENOMEM); - /* - * Although we can dma data above 4GB, our - * "consistent" memory is below 4GB for - * space efficiency reasons (only need a 4byte - * address). For this reason, we have to reset - * our dma mask when doing allocations. - */ - if (ahc->dev_softc != NULL) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3) - pci_set_dma_mask(ahc->dev_softc, 0xFFFFFFFF); -#else - ahc->dev_softc->dma_mask = 0xFFFFFFFF; -#endif - } - *vaddr = pci_alloc_consistent(ahc->dev_softc, - dmat->maxsize, &map->bus_addr); - if (ahc->dev_softc != NULL) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3) - pci_set_dma_mask(ahc->dev_softc, - ahc->platform_data->hw_dma_mask); -#else - ahc->dev_softc->dma_mask = ahc->platform_data->hw_dma_mask; -#endif - } -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) */ - /* - * At least in 2.2.14, malloc is a slab allocator so all - * allocations are aligned. We assume for these kernel versions - * that all allocations will be bellow 4Gig, physically contiguous, - * and accessable via DMA by the controller. - */ - map = NULL; /* No additional information to store */ - *vaddr = malloc(dmat->maxsize, M_DEVBUF, M_NOWAIT); -#endif - if (*vaddr == NULL) - return (ENOMEM); - *mapp = map; - return(0); -} - -void -ahc_dmamem_free(struct ahc_softc *ahc, bus_dma_tag_t dmat, - void* vaddr, bus_dmamap_t map) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - pci_free_consistent(ahc->dev_softc, dmat->maxsize, - vaddr, map->bus_addr); -#else - free(vaddr, M_DEVBUF); -#endif -} - -int -ahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map, - void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb, - void *cb_arg, int flags) -{ - /* - * Assume for now that this will only be used during - * initialization and not for per-transaction buffer mapping. - */ - bus_dma_segment_t stack_sg; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - stack_sg.ds_addr = map->bus_addr; -#else - stack_sg.ds_addr = VIRT_TO_BUS(buf); -#endif - stack_sg.ds_len = dmat->maxsize; - cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); - return (0); -} - -void -ahc_dmamap_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map) -{ - /* - * The map may is NULL in our < 2.3.X implementation. - */ - if (map != NULL) - free(map, M_DEVBUF); -} - -int -ahc_dmamap_unload(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map) -{ - /* Nothing to do */ - return (0); -} - -/********************* Platform Dependent Functions ***************************/ -int -ahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc) -{ - int value; - int rvalue; - int lvalue; - - /* - * Under Linux, cards are ordered as follows: - * 1) VLB/EISA BIOS enabled devices sorted by BIOS address. - * 2) PCI devices with BIOS enabled sorted by bus/slot/func. - * 3) All remaining VLB/EISA devices sorted by ioport. - * 4) All remaining PCI devices sorted by bus/slot/func. - */ - value = (lahc->flags & AHC_BIOS_ENABLED) - - (rahc->flags & AHC_BIOS_ENABLED); - if (value != 0) - /* Controllers with BIOS enabled have a *higher* priority */ - return (-value); - - /* - * Same BIOS setting, now sort based on bus type. - * EISA and VL controllers sort together. EISA/VL - * have higher priority than PCI. - */ - rvalue = (rahc->chip & AHC_BUS_MASK); - if (rvalue == AHC_VL) - rvalue = AHC_EISA; - lvalue = (lahc->chip & AHC_BUS_MASK); - if (lvalue == AHC_VL) - lvalue = AHC_EISA; - value = lvalue - rvalue; - if (value != 0) - return (value); - - /* Still equal. Sort by BIOS address, ioport, or bus/slot/func. */ - switch (rvalue) { - case AHC_PCI: - { - char primary_channel; - - if (aic7xxx_reverse_scan != 0) - value = ahc_get_pci_bus(rahc->dev_softc) - - ahc_get_pci_bus(lahc->dev_softc); - else - value = ahc_get_pci_bus(lahc->dev_softc) - - ahc_get_pci_bus(rahc->dev_softc); - if (value != 0) - break; - if (aic7xxx_reverse_scan != 0) - value = ahc_get_pci_slot(rahc->dev_softc) - - ahc_get_pci_slot(lahc->dev_softc); - else - value = ahc_get_pci_slot(lahc->dev_softc) - - ahc_get_pci_slot(rahc->dev_softc); - if (value != 0) - break; - /* - * On multi-function devices, the user can choose - * to have function 1 probed before function 0. - * Give whichever channel is the primary channel - * the lowest priority. - */ - primary_channel = (lahc->flags & AHC_PRIMARY_CHANNEL) + 'A'; - value = 1; - if (lahc->channel == primary_channel) - value = -1; - break; - } - case AHC_EISA: - if ((rahc->flags & AHC_BIOS_ENABLED) != 0) { - value = lahc->platform_data->bios_address - - rahc->platform_data->bios_address; - } else { - value = lahc->bsh.ioport - - rahc->bsh.ioport; - } - break; - default: - panic("ahc_softc_sort: invalid bus type"); - } - return (value); -} - -static void -ahc_linux_setup_tag_info(char *p, char *end) -{ - char *base; - char *tok; - char *tok_end; - char *tok_end2; - int i; - int instance; - int targ; - int done; - char tok_list[] = {'.', ',', '{', '}', '\0'}; - - if (*p != ':') - return; - - instance = -1; - targ = -1; - done = FALSE; - base = p; - /* Forward us just past the ':' */ - tok = base + 1; - tok_end = strchr(tok, '\0'); - if (tok_end < end) - *tok_end = ','; - while (!done) { - switch (*tok) { - case '{': - if (instance == -1) - instance = 0; - else if (targ == -1) - targ = 0; - tok++; - break; - case '}': - if (targ != -1) - targ = -1; - else if (instance != -1) - instance = -1; - tok++; - break; - case ',': - case '.': - if (instance == -1) - done = TRUE; - else if (targ >= 0) - targ++; - else if (instance >= 0) - instance++; - if ((targ >= AHC_NUM_TARGETS) || - (instance >= NUM_ELEMENTS(aic7xxx_tag_info))) - done = TRUE; - tok++; - if (!done) { - base = tok; - } - break; - case '\0': - done = TRUE; - break; - default: - done = TRUE; - tok_end = strchr(tok, '\0'); - for (i = 0; tok_list[i]; i++) { - tok_end2 = strchr(tok, tok_list[i]); - if ((tok_end2) && (tok_end2 < tok_end)) { - tok_end = tok_end2; - done = FALSE; - } - } - if ((instance >= 0) && (targ >= 0) - && (instance < NUM_ELEMENTS(aic7xxx_tag_info)) - && (targ < AHC_NUM_TARGETS)) { - aic7xxx_tag_info[instance].tag_commands[targ] = - simple_strtoul(tok, NULL, 0) & 0xff; - } - tok = tok_end; - break; - } - } - while ((p != base) && (p != NULL)) - p = strtok(NULL, ",."); -} - -/* - * Handle Linux boot parameters. This routine allows for assigning a value - * to a parameter with a ':' between the parameter and the value. - * ie. aic7xxx=stpwlev:1,extended - */ -int -aic7xxx_setup(char *s) -{ - int i, n; - char *p; - char *end; - - static struct { - const char *name; - uint32_t *flag; - } options[] = { - { "extended", &aic7xxx_extended }, - { "no_reset", &aic7xxx_no_reset }, - { "verbose", &aic7xxx_verbose }, - { "reverse_scan", &aic7xxx_reverse_scan }, - { "no_probe", &aic7xxx_no_probe }, - { "periodic_otag", &aic7xxx_periodic_otag }, - { "pci_parity", &aic7xxx_pci_parity }, - { "seltime", &aic7xxx_seltime }, - { "tag_info", NULL } - }; - - end = strchr(s, '\0'); - - for (p = strtok(s, ",."); p; p = strtok(NULL, ",.")) { - for (i = 0; i < NUM_ELEMENTS(options); i++) { - n = strlen(options[i].name); - - if (strncmp(options[i].name, p, n) != 0) - continue; - - if (strncmp(p, "tag_info", n) == 0) { - ahc_linux_setup_tag_info(p + n, end); - } else if (p[n] == ':') { - *(options[i].flag) = - simple_strtoul(p + n + 1, NULL, 0); - } else if (!strncmp(p, "verbose", n)) { - *(options[i].flag) = 1; - } else { - *(options[i].flag) = ~(*(options[i].flag)); - } - break; - } - } - return 1; -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) -__setup("aic7xxx=", aic7xxx_setup); -#endif - -int aic7xxx_verbose; - -/* - * Try to detect an Adaptec 7XXX controller. - */ -int -ahc_linux_detect(Scsi_Host_Template *template) -{ - struct ahc_softc *ahc; - int found; - - /* - * It is a bug that the upper layer takes - * this lock just prior to calling us. - */ - spin_unlock_irq(&io_request_lock); - - /* - * Sanity checking of Linux SCSI data structures so - * that some of our hacks^H^H^H^H^Hassumptions aren't - * violated. - */ - if (offsetof(struct ahc_cmd_internal, end) - > offsetof(struct scsi_cmnd, host_scribble)) { - printf("ahc_linux_detect: SCSI data structures changed.\n"); - printf("ahc_linux_detect: Unable to attach\n"); - return (0); - } -#ifdef MODULE - /* - * If we've been passed any parameters, process them now. - */ - if (aic7xxx) - aic7xxx_setup(aic7xxx); - if (dummy_buffer[0] != 'P') - printf(KERN_WARNING -"aic7xxx: Please read the file /usr/src/xen/drivers/scsi/README.aic7xxx\n" -"aic7xxx: to see the proper way to specify options to the aic7xxx module\n" -"aic7xxx: Specifically, don't use any commas when passing arguments to\n" -"aic7xxx: insmod or else it might trash certain memory areas.\n"); -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) - template->proc_name = "aic7xxx"; -#else - template->proc_dir = &proc_scsi_aic7xxx; -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) - /* - * We can only map 16MB per-SG - * so create a sector limit of - * "16MB" in 2K sectors. - */ - template->max_sectors = 8192; -#endif - - /* - * Initialize our softc list lock prior to - * probing for any adapters. - */ - ahc_list_lockinit(); - -#ifdef CONFIG_PCI - ahc_linux_pci_probe(template); -#endif - - if (aic7xxx_no_probe == 0) - aic7770_linux_probe(template); - - /* - * Register with the SCSI layer all - * controllers we've found. - */ - spin_lock_irq(&io_request_lock); - found = 0; - TAILQ_FOREACH(ahc, &ahc_tailq, links) { - - if (ahc_linux_register_host(ahc, template) == 0) - found++; - } - aic7xxx_detect_complete++; - return (found); -} - -int -ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template) -{ - char buf[80]; - struct Scsi_Host *host; - char *new_name; - u_long s; - - - template->name = ahc->description; - host = scsi_register(template, sizeof(struct ahc_softc *)); - if (host == NULL) - return (ENOMEM); - - ahc_lock(ahc, &s); - *((struct ahc_softc **)host->hostdata) = ahc; - ahc->platform_data->host = host; - host->can_queue = AHC_MAX_QUEUE; - host->cmd_per_lun = 2; - host->sg_tablesize = AHC_NSEG; - host->select_queue_depths = ahc_linux_select_queue_depth; - /* XXX No way to communicate the ID for multiple channels */ - host->this_id = ahc->our_id; - host->irq = ahc->platform_data->irq; - host->max_id = (ahc->features & AHC_WIDE) ? 16 : 8; - host->max_lun = AHC_NUM_LUNS; - host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0; - ahc_set_unit(ahc, ahc_linux_next_unit()); - sprintf(buf, "scsi%d", host->host_no); - new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); - if (new_name != NULL) { - strcpy(new_name, buf); - ahc_set_name(ahc, new_name); - } - host->unique_id = ahc->unit; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) - scsi_set_pci_device(host, ahc->dev_softc); -#endif - ahc_linux_initialize_scsi_bus(ahc); - ahc_unlock(ahc, &s); - return (0); -} - -uint64_t -ahc_linux_get_memsize() -{ - // struct sysinfo si; - // - // si_meminfo(&si); - // return (si.totalram << PAGE_SHIFT); - printf("JWS: aic7xxx: get_memsize\n"); - return 0; -} - -/* - * Find the smallest available unit number to use - * for a new device. We don't just use a static - * count to handle the "repeated hot-(un)plug" - * scenario. - */ -static int -ahc_linux_next_unit() -{ - struct ahc_softc *ahc; - int unit; - - unit = 0; -retry: - TAILQ_FOREACH(ahc, &ahc_tailq, links) { - if (ahc->unit == unit) { - unit++; - goto retry; - } - } - return (unit); -} - -/* - * Place the SCSI bus into a known state by either resetting it, - * or forcing transfer negotiations on the next command to any - * target. - */ -void -ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc) -{ - int i; - int numtarg; - - i = 0; - numtarg = 0; - - if (aic7xxx_no_reset != 0) - ahc->flags &= ~(AHC_RESET_BUS_A|AHC_RESET_BUS_B); - - if ((ahc->flags & AHC_RESET_BUS_A) != 0) - ahc_reset_channel(ahc, 'A', /*initiate_reset*/TRUE); - else - numtarg = (ahc->features & AHC_WIDE) ? 16 : 8; - - if ((ahc->features & AHC_TWIN) != 0) { - - if ((ahc->flags & AHC_RESET_BUS_B) != 0) { - ahc_reset_channel(ahc, 'B', /*initiate_reset*/TRUE); - } else { - if (numtarg == 0) - i = 8; - numtarg += 8; - } - } - - for (; i < numtarg; i++) { - struct ahc_devinfo devinfo; - struct ahc_initiator_tinfo *tinfo; - struct ahc_tmode_tstate *tstate; - u_int our_id; - u_int target_id; - char channel; - - channel = 'A'; - our_id = ahc->our_id; - target_id = i; - if (i > 7 && (ahc->features & AHC_TWIN) != 0) { - channel = 'B'; - our_id = ahc->our_id_b; - target_id = i % 8; - } - tinfo = ahc_fetch_transinfo(ahc, channel, our_id, - target_id, &tstate); - tinfo->goal = tinfo->user; - /* - * Don't try negotiations that require PPR messages - * until we successfully retrieve Inquiry data. - */ - tinfo->goal.ppr_options = 0; - if (tinfo->goal.transport_version > SCSI_REV_2) - tinfo->goal.transport_version = SCSI_REV_2; - ahc_compile_devinfo(&devinfo, our_id, target_id, - CAM_LUN_WILDCARD, channel, ROLE_INITIATOR); - ahc_update_neg_request(ahc, &devinfo, tstate, - tinfo, /*force*/FALSE); - } - /* Give the bus some time to recover */ - if ((ahc->flags & (AHC_RESET_BUS_A|AHC_RESET_BUS_B)) != 0) { - // JWS - XEN - DONT USE TIMERS HERE -#if 0 - ahc_linux_freeze_sim_queue(ahc); - init_timer(&ahc->platform_data->reset_timer); - ahc->platform_data->reset_timer.data = (u_long)ahc; - ahc->platform_data->reset_timer.expires = - jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000; - ahc->platform_data->reset_timer.function = - ahc_linux_release_sim_queue; - add_timer(&ahc->platform_data->reset_timer); -#else - mdelay(AIC7XXX_RESET_DELAY); -#endif - } -} - -int -ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) -{ - ahc->platform_data = - malloc(sizeof(struct ahc_platform_data), M_DEVBUF, M_NOWAIT); - if (ahc->platform_data == NULL) - return (ENOMEM); - memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data)); - TAILQ_INIT(&ahc->platform_data->completeq); - TAILQ_INIT(&ahc->platform_data->device_runq); - ahc->platform_data->irq = AHC_LINUX_NOIRQ; - ahc->platform_data->hw_dma_mask = 0xFFFFFFFF; - ahc_lockinit(ahc); - ahc_done_lockinit(ahc); -#if 0 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - init_MUTEX_LOCKED(&ahc->platform_data->eh_sem); -#else - ahc->platform_data->eh_sem = MUTEX_LOCKED; -#endif -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_init(&ahc->platform_data->runq_tasklet, ahc_runq_tasklet, - (unsigned long)ahc); -#endif - ahc->seltime = (aic7xxx_seltime & 0x3) << 4; - ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4; -#if XEN_KILLED - if (TAILQ_EMPTY(&ahc_tailq)) - register_reboot_notifier(&ahc_linux_notifier); -#endif - return (0); -} - -void -ahc_platform_free(struct ahc_softc *ahc) -{ - if (ahc->platform_data != NULL) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_kill(&ahc->platform_data->runq_tasklet); -#endif - if (ahc->platform_data->host != NULL) - scsi_unregister(ahc->platform_data->host); - if (ahc->platform_data->irq != AHC_LINUX_NOIRQ) - free_irq(ahc->platform_data->irq, ahc); - if (ahc->tag == BUS_SPACE_PIO - && ahc->bsh.ioport != 0) - release_region(ahc->bsh.ioport, 256); - if (ahc->tag == BUS_SPACE_MEMIO - && ahc->bsh.maddr != NULL) { - u_long base_addr; - - base_addr = (u_long)ahc->bsh.maddr; - base_addr &= PAGE_MASK; - iounmap((void *)base_addr); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - release_mem_region(ahc->platform_data->mem_busaddr, - 0x1000); -#endif - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - /* XXX Need an instance detach in the PCI code */ - if (ahc->dev_softc != NULL) - ahc->dev_softc->driver = NULL; -#endif - free(ahc->platform_data, M_DEVBUF); - } - if (TAILQ_EMPTY(&ahc_tailq)) { -#ifdef XEN_KILLED - unregister_reboot_notifier(&ahc_linux_notifier); -#endif -#ifdef CONFIG_PCI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pci_unregister_driver(&aic7xxx_pci_driver); -#endif -#endif - } -} - -void -ahc_platform_freeze_devq(struct ahc_softc *ahc, struct scb *scb) -{ - ahc_platform_abort_scbs(ahc, SCB_GET_TARGET(ahc, scb), - SCB_GET_CHANNEL(ahc, scb), - SCB_GET_LUN(scb), SCB_LIST_NULL, - ROLE_UNKNOWN, CAM_REQUEUE_REQ); -} - -void -ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, - ahc_queue_alg alg) -{ - struct ahc_linux_device *dev; - int was_queuing; - int now_queuing; - - dev = ahc_linux_get_device(ahc, devinfo->channel - 'A', - devinfo->target, - devinfo->lun, /*alloc*/FALSE); - if (dev == NULL) - return; - was_queuing = dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED); - now_queuing = alg != AHC_QUEUE_NONE; - if ((dev->flags & AHC_DEV_FREEZE_TIL_EMPTY) == 0 - && (was_queuing != now_queuing) - && (dev->active != 0)) { - dev->flags |= AHC_DEV_FREEZE_TIL_EMPTY; - dev->qfrozen++; - } - - dev->flags &= ~(AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED|AHC_DEV_PERIODIC_OTAG); - if (now_queuing) { - u_int usertags; - - usertags = ahc_linux_user_tagdepth(ahc, devinfo); - if (!was_queuing) { - /* - * Start out agressively and allow our - * dynamic queue depth algorithm to take - * care of the rest. - */ - dev->maxtags = usertags; - dev->openings = dev->maxtags - dev->active; - } - if (alg == AHC_QUEUE_TAGGED) { - dev->flags |= AHC_DEV_Q_TAGGED; - if (aic7xxx_periodic_otag != 0) - dev->flags |= AHC_DEV_PERIODIC_OTAG; - } else - dev->flags |= AHC_DEV_Q_BASIC; - } else { - /* We can only have one opening. */ - dev->maxtags = 0; - dev->openings = 1 - dev->active; - } -} - -int -ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, char channel, - int lun, u_int tag, role_t role, uint32_t status) -{ - int chan; - int maxchan; - int targ; - int maxtarg; - int clun; - int maxlun; - int count; - - if (tag != SCB_LIST_NULL) - return (0); - - chan = 0; - if (channel != ALL_CHANNELS) { - chan = channel - 'A'; - maxchan = chan + 1; - } else { - maxchan = (ahc->features & AHC_TWIN) ? 2 : 1; - } - targ = 0; - if (target != CAM_TARGET_WILDCARD) { - targ = target; - maxtarg = targ + 1; - } else { - maxtarg = (ahc->features & AHC_WIDE) ? 16 : 8; - } - clun = 0; - if (lun != CAM_LUN_WILDCARD) { - clun = lun; - maxlun = clun + 1; - } else { - maxlun = AHC_NUM_LUNS; - } - - count = 0; - for (; chan < maxchan; chan++) { - - for (; targ < maxtarg; targ++) { - - for (; clun < maxlun; clun++) { - struct ahc_linux_device *dev; - struct ahc_busyq *busyq; - struct ahc_cmd *acmd; - - dev = ahc_linux_get_device(ahc, chan, - targ, clun, - /*alloc*/FALSE); - if (dev == NULL) - continue; - - busyq = &dev->busyq; - while ((acmd = TAILQ_FIRST(busyq)) != NULL) { - Scsi_Cmnd *cmd; - - cmd = &acmd_scsi_cmd(acmd); - TAILQ_REMOVE(busyq, acmd, - acmd_links.tqe); - count++; - cmd->result = status << 16; - ahc_linux_queue_cmd_complete(ahc, cmd); - } - } - } - } - - return (count); -} - -/* - * Sets the queue depth for each SCSI device hanging - * off the input host adapter. - */ -static void -ahc_linux_select_queue_depth(struct Scsi_Host * host, - Scsi_Device * scsi_devs) -{ - Scsi_Device *device; - struct ahc_softc *ahc; - u_long flags; - int scbnum; - - ahc = *((struct ahc_softc **)host->hostdata); - ahc_lock(ahc, &flags); - scbnum = 0; - for (device = scsi_devs; device != NULL; device = device->next) { - if (device->host == host) { - ahc_linux_device_queue_depth(ahc, device); - scbnum += device->queue_depth; - } - } - ahc_unlock(ahc, &flags); -} - -static u_int -ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) -{ - static int warned_user; - u_int tags; - - tags = 0; - if ((ahc->user_discenable & devinfo->target_mask) != 0) { - if (warned_user == 0 - && ahc->unit >= NUM_ELEMENTS(aic7xxx_tag_info)) { - - printf("aic7xxx: WARNING, insufficient " - "tag_info instances for installed " - "controllers. Using defaults\n"); - printf("aic7xxx: Please update the " - "aic7xxx_tag_info array in the " - "aic7xxx.c source file.\n"); - tags = AHC_MAX_QUEUE; - warned_user++; - } else { - adapter_tag_info_t *tag_info; - - tag_info = &aic7xxx_tag_info[ahc->unit]; - tags = tag_info->tag_commands[devinfo->target_offset]; - if (tags > AHC_MAX_QUEUE) - tags = AHC_MAX_QUEUE; - } - } - return (tags); -} - -/* - * Determines the queue depth for a given device. - */ -static void -ahc_linux_device_queue_depth(struct ahc_softc *ahc, Scsi_Device * device) -{ - struct ahc_devinfo devinfo; - u_int tags; - - ahc_compile_devinfo(&devinfo, - device->channel == 0 ? ahc->our_id : ahc->our_id_b, - device->id, device->lun, - device->channel == 0 ? 'A' : 'B', - ROLE_INITIATOR); - tags = ahc_linux_user_tagdepth(ahc, &devinfo); - if (tags != 0 - && device->tagged_supported != 0) { - - device->queue_depth = tags; - ahc_set_tags(ahc, &devinfo, AHC_QUEUE_TAGGED); - printf("scsi%d:%c:%d:%d: Tagged Queuing enabled. Depth %d\n", - ahc->platform_data->host->host_no, devinfo.channel, - devinfo.target, devinfo.lun, tags); - } else { - /* - * We allow the OS to queue 2 untagged transactions to - * us at any time even though we can only execute them - * serially on the controller/device. This should remove - * some latency. - */ - device->queue_depth = 2; - } -} - -/* - * Queue an SCB to the controller. - */ -int -ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) -{ - struct ahc_softc *ahc; - struct ahc_linux_device *dev; - u_long flags; - - ahc = *(struct ahc_softc **)cmd->host->hostdata; - - /* - * Save the callback on completion function. - */ - cmd->scsi_done = scsi_done; - - ahc_lock(ahc, &flags); - dev = ahc_linux_get_device(ahc, cmd->channel, cmd->target, - cmd->lun, /*alloc*/TRUE); - if (dev == NULL) { - ahc_unlock(ahc, &flags); - printf("aic7xxx_linux_queue: Unable to allocate device!\n"); - return (-ENOMEM); - } - cmd->result = CAM_REQ_INPROG << 16; - TAILQ_INSERT_TAIL(&dev->busyq, (struct ahc_cmd *)cmd, acmd_links.tqe); - if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) { - TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links); - dev->flags |= AHC_DEV_ON_RUN_LIST; - ahc_linux_run_device_queues(ahc); - } - ahc_unlock(ahc, &flags); - return (0); -} - -static void -ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev) -{ - struct ahc_cmd *acmd; - struct scsi_cmnd *cmd; - struct scb *scb; - struct hardware_scb *hscb; - struct ahc_initiator_tinfo *tinfo; - struct ahc_tmode_tstate *tstate; - uint16_t mask; - - if ((dev->flags & AHC_DEV_ON_RUN_LIST) != 0) - panic("running device on run list"); - - while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL - && dev->openings > 0 && dev->qfrozen == 0) { - - /* - * Schedule us to run later. The only reason we are not - * running is because the whole controller Q is frozen. - */ - if (ahc->platform_data->qfrozen != 0) { - - TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, - dev, links); - dev->flags |= AHC_DEV_ON_RUN_LIST; - return; - } - /* - * Get an scb to use. - */ - if ((scb = ahc_get_scb(ahc)) == NULL) { - TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, - dev, links); - dev->flags |= AHC_DEV_ON_RUN_LIST; - ahc->flags |= AHC_RESOURCE_SHORTAGE; - return; - } - TAILQ_REMOVE(&dev->busyq, acmd, acmd_links.tqe); - cmd = &acmd_scsi_cmd(acmd); - scb->io_ctx = cmd; - scb->platform_data->dev = dev; - hscb = scb->hscb; - cmd->host_scribble = (char *)scb; - - /* - * Fill out basics of the HSCB. - */ - hscb->control = 0; - hscb->scsiid = BUILD_SCSIID(ahc, cmd); - hscb->lun = cmd->lun; - mask = SCB_GET_TARGET_MASK(ahc, scb); - tinfo = ahc_fetch_transinfo(ahc, SCB_GET_CHANNEL(ahc, scb), - SCB_GET_OUR_ID(scb), - SCB_GET_TARGET(ahc, scb), &tstate); - hscb->scsirate = tinfo->scsirate; - hscb->scsioffset = tinfo->curr.offset; - if ((tstate->ultraenb & mask) != 0) - hscb->control |= ULTRAENB; - - if ((ahc->user_discenable & mask) != 0) - hscb->control |= DISCENB; - - if ((tstate->auto_negotiate & mask) != 0) { - scb->flags |= SCB_AUTO_NEGOTIATE; - scb->hscb->control |= MK_MESSAGE; - } - - if ((dev->flags & (AHC_DEV_Q_TAGGED|AHC_DEV_Q_BASIC)) != 0) { - if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH - && (dev->flags & AHC_DEV_Q_TAGGED) != 0) { - hscb->control |= MSG_ORDERED_TASK; - dev->commands_since_idle_or_otag = 0; - } else { - hscb->control |= MSG_SIMPLE_TASK; - } - } - - hscb->cdb_len = cmd->cmd_len; - if (hscb->cdb_len <= 12) { - memcpy(hscb->shared_data.cdb, cmd->cmnd, hscb->cdb_len); - } else { - memcpy(hscb->cdb32, cmd->cmnd, hscb->cdb_len); - scb->flags |= SCB_CDB32_PTR; - } - - scb->platform_data->xfer_len = 0; - ahc_set_residual(scb, 0); - ahc_set_sense_residual(scb, 0); - scb->sg_count = 0; - if (cmd->use_sg != 0) { - struct ahc_dma_seg *sg; - struct scatterlist *cur_seg; - struct scatterlist *end_seg; - int nseg; - - cur_seg = (struct scatterlist *)cmd->request_buffer; - nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg, - scsi_to_pci_dma_dir(cmd ->sc_data_direction)); - end_seg = cur_seg + nseg; - /* Copy the segments into the SG list. */ - sg = scb->sg_list; - /* - * The sg_count may be larger than nseg if - * a transfer crosses a 32bit page. - */ - while (cur_seg < end_seg) { - bus_addr_t addr; - bus_size_t len; - int consumed; - - addr = sg_dma_address(cur_seg); - len = sg_dma_len(cur_seg); - consumed = ahc_linux_map_seg(ahc, scb, - sg, addr, len); - sg += consumed; - scb->sg_count += consumed; - cur_seg++; - } - sg--; - sg->len |= ahc_htole32(AHC_DMA_LAST_SEG); - - /* - * Reset the sg list pointer. - */ - scb->hscb->sgptr = - ahc_htole32(scb->sg_list_phys | SG_FULL_RESID); - - /* - * Copy the first SG into the "current" - * data pointer area. - */ - scb->hscb->dataptr = scb->sg_list->addr; - scb->hscb->datacnt = scb->sg_list->len; - } else if (cmd->request_bufflen != 0) { - struct ahc_dma_seg *sg; - bus_addr_t addr; - - sg = scb->sg_list; - addr = pci_map_single(ahc->dev_softc, - cmd->request_buffer, - cmd->request_bufflen, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); - scb->platform_data->buf_busaddr = addr; - scb->sg_count = ahc_linux_map_seg(ahc, scb, - sg, addr, - cmd->request_bufflen); - sg->len |= ahc_htole32(AHC_DMA_LAST_SEG); - - /* - * Reset the sg list pointer. - */ - scb->hscb->sgptr = - ahc_htole32(scb->sg_list_phys | SG_FULL_RESID); - - /* - * Copy the first SG into the "current" - * data pointer area. - */ - scb->hscb->dataptr = sg->addr; - scb->hscb->datacnt = sg->len; - } else { - scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL); - scb->hscb->dataptr = 0; - scb->hscb->datacnt = 0; - scb->sg_count = 0; - } - - ahc_sync_sglist(ahc, scb, BUS_DMASYNC_PREWRITE); - LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links); - dev->openings--; - dev->active++; - dev->commands_issued++; - if ((dev->flags & AHC_DEV_PERIODIC_OTAG) != 0) - dev->commands_since_idle_or_otag++; - - /* - * We only allow one untagged transaction - * per target in the initiator role unless - * we are storing a full busy target *lun* - * table in SCB space. - */ - if ((scb->hscb->control & (TARGET_SCB|TAG_ENB)) == 0 - && (ahc->features & AHC_SCB_BTT) == 0) { - struct scb_tailq *untagged_q; - int target_offset; - - target_offset = SCB_GET_TARGET_OFFSET(ahc, scb); - untagged_q = &(ahc->untagged_queues[target_offset]); - TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe); - scb->flags |= SCB_UNTAGGEDQ; - if (TAILQ_FIRST(untagged_q) != scb) - continue; - } - scb->flags |= SCB_ACTIVE; - ahc_queue_scb(ahc, scb); - } -} - -/* - * SCSI controller interrupt handler. - */ -void -ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs) -{ - struct ahc_softc *ahc; - struct ahc_cmd *acmd; - u_long flags; - struct ahc_linux_device *next_dev; - - ahc = (struct ahc_softc *) dev_id; - ahc_lock(ahc, &flags); - ahc_intr(ahc); - acmd = TAILQ_FIRST(&ahc->platform_data->completeq); - TAILQ_INIT(&ahc->platform_data->completeq); - next_dev = ahc_linux_next_device_to_run(ahc); - ahc_unlock(ahc, &flags); - if (next_dev) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_schedule(&ahc->platform_data->runq_tasklet); -#else - ahc_runq_tasklet((unsigned long)ahc); -#endif - } - if (acmd != NULL) - ahc_linux_run_complete_queue(ahc, acmd); -} - -void -ahc_platform_flushwork(struct ahc_softc *ahc) -{ - struct ahc_cmd *acmd; - - acmd = TAILQ_FIRST(&ahc->platform_data->completeq); - TAILQ_INIT(&ahc->platform_data->completeq); - if (acmd != NULL) - ahc_linux_run_complete_queue(ahc, acmd); -} - -static struct ahc_linux_target* -ahc_linux_alloc_target(struct ahc_softc *ahc, u_int channel, u_int target) -{ - struct ahc_linux_target *targ; - u_int target_offset; - - targ = malloc(sizeof(*targ), M_DEVBUG, M_NOWAIT); - if (targ == NULL) - return (NULL); - memset(targ, 0, sizeof(*targ)); - targ->channel = channel; - targ->target = target; - targ->ahc = ahc; - target_offset = target; - if (channel != 0) - target_offset += 8; - ahc->platform_data->targets[target_offset] = targ; - return (targ); -} - -static void -ahc_linux_free_target(struct ahc_softc *ahc, struct ahc_linux_target *targ) -{ - u_int target_offset; - - target_offset = targ->target; - if (targ->channel != 0) - target_offset += 8; - ahc->platform_data->targets[target_offset] = NULL; - free(targ, M_DEVBUF); -} - -static struct ahc_linux_device* -ahc_linux_alloc_device(struct ahc_softc *ahc, - struct ahc_linux_target *targ, u_int lun) -{ - struct ahc_linux_device *dev; - - dev = malloc(sizeof(*dev), M_DEVBUG, M_NOWAIT); - if (dev == NULL) - return (NULL); - memset(dev, 0, sizeof(*dev)); - init_timer(&dev->timer); - TAILQ_INIT(&dev->busyq); - dev->flags = AHC_DEV_UNCONFIGURED; - dev->lun = lun; - dev->target = targ; - - /* - * We start out life using untagged - * transactions of which we allow one. - */ - dev->openings = 1; - - /* - * Set maxtags to 0. This will be changed if we - * later determine that we are dealing with - * a tagged queuing capable device. - */ - dev->maxtags = 0; - - targ->refcount++; - targ->devices[lun] = dev; - return (dev); -} - -static void -ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev) -{ - struct ahc_linux_target *targ; - - del_timer(&dev->timer); - targ = dev->target; - targ->devices[dev->lun] = NULL; - free(dev, M_DEVBUF); - targ->refcount--; - if (targ->refcount == 0) - ahc_linux_free_target(ahc, targ); -} - -/* - * Return a string describing the driver. - */ -const char * -ahc_linux_info(struct Scsi_Host *host) -{ - static char buffer[512]; - char ahc_info[256]; - char *bp; - struct ahc_softc *ahc; - - bp = &buffer[0]; - ahc = *(struct ahc_softc **)host->hostdata; - memset(bp, 0, sizeof(buffer)); - strcpy(bp, "Adaptec AIC7XXX EISA/VLB/PCI SCSI HBA DRIVER, Rev "); - strcat(bp, AIC7XXX_DRIVER_VERSION); - strcat(bp, "\n"); - strcat(bp, " <"); - strcat(bp, ahc->description); - strcat(bp, ">\n"); - strcat(bp, " "); - ahc_controller_info(ahc, ahc_info); - strcat(bp, ahc_info); - strcat(bp, "\n"); - - return (bp); -} - -void -ahc_send_async(struct ahc_softc *ahc, char channel, - u_int target, u_int lun, ac_code code, void *arg) -{ - switch (code) { - case AC_TRANSFER_NEG: - { - char buf[80]; - struct ahc_linux_target *targ; - struct info_str info; - struct ahc_initiator_tinfo *tinfo; - struct ahc_tmode_tstate *tstate; - int target_offset; - - info.buffer = buf; - info.length = sizeof(buf); - info.offset = 0; - info.pos = 0; - tinfo = ahc_fetch_transinfo(ahc, channel, - channel == 'A' ? ahc->our_id - : ahc->our_id_b, - target, &tstate); - - /* - * Don't bother reporting results while - * negotiations are still pending. - */ - if (tinfo->curr.period != tinfo->goal.period - || tinfo->curr.width != tinfo->goal.width - || tinfo->curr.offset != tinfo->goal.offset - || tinfo->curr.ppr_options != tinfo->goal.ppr_options) - if (bootverbose == 0) - break; - - /* - * Don't bother reporting results that - * are identical to those last reported. - */ - target_offset = target; - if (channel == 'B') - target_offset += 8; - targ = ahc->platform_data->targets[target_offset]; - if (targ == NULL) - break; - if (tinfo->curr.period == targ->last_tinfo.period - && tinfo->curr.width == targ->last_tinfo.width - && tinfo->curr.offset == targ->last_tinfo.offset - && tinfo->curr.ppr_options == targ->last_tinfo.ppr_options) - if (bootverbose == 0) - break; - - targ->last_tinfo.period = tinfo->curr.period; - targ->last_tinfo.width = tinfo->curr.width; - targ->last_tinfo.offset = tinfo->curr.offset; - targ->last_tinfo.ppr_options = tinfo->curr.ppr_options; - - printf("(%s:%c:", ahc_name(ahc), channel); - if (target == CAM_TARGET_WILDCARD) - printf("*): "); - else - printf("%d): ", target); - ahc_format_transinfo(&info, &tinfo->curr); - if (info.pos < info.length) - *info.buffer = '\0'; - else - buf[info.length - 1] = '\0'; - printf("%s", buf); - break; - } - case AC_SENT_BDR: - break; - case AC_BUS_RESET: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - if (ahc->platform_data->host != NULL) { - scsi_report_bus_reset(ahc->platform_data->host, - channel - 'A'); - } -#endif - break; - default: - panic("ahc_send_async: Unexpected async event"); - } -} - -/* - * Calls the higher level scsi done function and frees the scb. - */ -void -ahc_done(struct ahc_softc *ahc, struct scb * scb) -{ - Scsi_Cmnd *cmd; - struct ahc_linux_device *dev; - - LIST_REMOVE(scb, pending_links); - if ((scb->flags & SCB_UNTAGGEDQ) != 0) { - struct scb_tailq *untagged_q; - int target_offset; - - target_offset = SCB_GET_TARGET_OFFSET(ahc, scb); - untagged_q = &(ahc->untagged_queues[target_offset]); - TAILQ_REMOVE(untagged_q, scb, links.tqe); - ahc_run_untagged_queue(ahc, untagged_q); - } - - if ((scb->flags & SCB_ACTIVE) == 0) { - printf("SCB %d done'd twice\n", scb->hscb->tag); - ahc_dump_card_state(ahc); - panic("Stopping for safety"); - } - cmd = scb->io_ctx; - dev = scb->platform_data->dev; - dev->active--; - dev->openings++; - ahc_linux_unmap_scb(ahc, scb); - if (scb->flags & SCB_SENSE) { - memcpy(cmd->sense_buffer, ahc_get_sense_buf(ahc, scb), - MIN(sizeof(struct scsi_sense_data), - sizeof(cmd->sense_buffer))); - cmd->result |= (DRIVER_SENSE << 24); - } else { - /* - * Guard against stale sense data. - * The Linux mid-layer assumes that sense - * was retrieved anytime the first byte of - * the sense buffer looks "sane". - */ - cmd->sense_buffer[0] = 0; - } - if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG) { - uint32_t amount_xferred; - - amount_xferred = - ahc_get_transfer_length(scb) - ahc_get_residual(scb); - if (amount_xferred < scb->io_ctx->underflow) { - printf("Saw underflow (%ld of %ld bytes). " - "Treated as error\n", - ahc_get_residual(scb), - ahc_get_transfer_length(scb)); - ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR); - } else { - ahc_set_transaction_status(scb, CAM_REQ_CMP); - ahc_linux_sniff_command(ahc, cmd, scb); - } - } else if (ahc_get_transaction_status(scb) == DID_OK) { - ahc_linux_handle_scsi_status(ahc, dev, scb); - } else if (ahc_get_transaction_status(scb) == DID_NO_CONNECT) { - /* - * Should a selection timeout kill the device? - * That depends on whether the selection timeout - * is persistent. Since we have no guarantee that - * the mid-layer will issue an inquiry for this device - * again, we can't just kill it off. - dev->flags |= AHC_DEV_UNCONFIGURED; - */ - } - - if (dev->openings == 1 - && ahc_get_transaction_status(scb) == CAM_REQ_CMP - && ahc_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL) - dev->tag_success_count++; - /* - * Some devices deal with temporary internal resource - * shortages by returning queue full. When the queue - * full occurrs, we throttle back. Slowly try to get - * back to our previous queue depth. - */ - if ((dev->openings + dev->active) < dev->maxtags - && dev->tag_success_count > AHC_TAG_SUCCESS_INTERVAL) { - dev->tag_success_count = 0; - dev->openings++; - } - - if (dev->active == 0) - dev->commands_since_idle_or_otag = 0; - - if (TAILQ_EMPTY(&dev->busyq)) { - if ((dev->flags & AHC_DEV_UNCONFIGURED) != 0 - && dev->active == 0) - ahc_linux_free_device(ahc, dev); - } else if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) { - TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links); - dev->flags |= AHC_DEV_ON_RUN_LIST; - } - - if ((scb->flags & SCB_RECOVERY_SCB) != 0) { - printf("Recovery SCB completes\n"); -#if 0 - up(&ahc->platform_data->eh_sem); -#endif - } - - ahc_free_scb(ahc, scb); - ahc_linux_queue_cmd_complete(ahc, cmd); -} - -static void -ahc_linux_handle_scsi_status(struct ahc_softc *ahc, - struct ahc_linux_device *dev, struct scb *scb) -{ - /* - * We don't currently trust the mid-layer to - * properly deal with queue full or busy. So, - * when one occurs, we tell the mid-layer to - * unconditionally requeue the command to us - * so that we can retry it ourselves. We also - * implement our own throttling mechanism so - * we don't clobber the device with too many - * commands. - */ - switch (ahc_get_scsi_status(scb)) { - default: - break; - case SCSI_STATUS_QUEUE_FULL: - { - /* - * By the time the core driver has returned this - * command, all other commands that were queued - * to us but not the device have been returned. - * This ensures that dev->active is equal to - * the number of commands actually queued to - * the device. - */ - dev->tag_success_count = 0; - if (dev->active != 0) { - /* - * Drop our opening count to the number - * of commands currently outstanding. - */ - dev->openings = 0; -/* - ahc_print_path(ahc, scb); - printf("Dropping tag count to %d\n", dev->active); - */ - if (dev->active == dev->tags_on_last_queuefull) { - - dev->last_queuefull_same_count++; - /* - * If we repeatedly see a queue full - * at the same queue depth, this - * device has a fixed number of tag - * slots. Lock in this tag depth - * so we stop seeing queue fulls from - * this device. - */ - if (dev->last_queuefull_same_count - == AHC_LOCK_TAGS_COUNT) { - dev->maxtags = dev->active; - ahc_print_path(ahc, scb); - printf("Locking max tag count at %d\n", - dev->active); - } - } else { - dev->tags_on_last_queuefull = dev->active; - dev->last_queuefull_same_count = 0; - } - ahc_set_transaction_status(scb, CAM_REQUEUE_REQ); - ahc_set_scsi_status(scb, SCSI_STATUS_OK); - break; - } - /* - * Drop down to a single opening, and treat this - * as if the target return BUSY SCSI status. - */ - dev->openings = 1; - /* FALLTHROUGH */ - } - case SCSI_STATUS_BUSY: - { - /* - * Set a short timer to defer sending commands for - * a bit since Linux will not delay in this case. - */ - if ((dev->flags & AHC_DEV_TIMER_ACTIVE) != 0) { - printf("%s:%c:%d: Device Timer still active during " - "busy processing\n", ahc_name(ahc), - dev->target->channel, dev->target->target); - break; - } - dev->flags |= AHC_DEV_TIMER_ACTIVE; - dev->qfrozen++; - init_timer(&dev->timer); - dev->timer.data = (u_long)dev; - dev->timer.expires = jiffies + (HZ/2); - dev->timer.function = ahc_linux_dev_timed_unfreeze; - add_timer(&dev->timer); - break; - } - } -} - -static void -ahc_linux_filter_command(struct ahc_softc *ahc, Scsi_Cmnd *cmd, struct scb *scb) -{ - switch (cmd->cmnd[0]) { - case INQUIRY: - { - struct ahc_devinfo devinfo; - struct scsi_inquiry *inq; - struct scsi_inquiry_data *sid; - struct ahc_initiator_tinfo *tinfo; - struct ahc_transinfo *user; - struct ahc_transinfo *goal; - struct ahc_transinfo *curr; - struct ahc_tmode_tstate *tstate; - struct ahc_syncrate *syncrate; - struct ahc_linux_device *dev; - u_int scsiid; - u_int maxsync; - int transferred_len; - int minlen; - u_int width; - u_int period; - u_int offset; - u_int ppr_options; - - /* - * Validate the command. We only want to filter - * standard inquiry commands, not those querying - * Vital Product Data. - */ - inq = (struct scsi_inquiry *)cmd->cmnd; - if ((inq->byte2 & SI_EVPD) != 0 - || inq->page_code != 0) - break; - - if (cmd->use_sg != 0) { - printf("%s: SG Inquiry response ignored\n", - ahc_name(ahc)); - break; - } - transferred_len = ahc_get_transfer_length(scb) - - ahc_get_residual(scb); - sid = (struct scsi_inquiry_data *)cmd->request_buffer; - - /* - * Determine if this lun actually exists. If so, - * hold on to its corresponding device structure. - * If not, make sure we release the device and - * don't bother processing the rest of this inquiry - * command. - */ - dev = ahc_linux_get_device(ahc, cmd->channel, - cmd->target, cmd->lun, - /*alloc*/FALSE); - if (transferred_len >= 1 - && SID_QUAL(sid) == SID_QUAL_LU_CONNECTED) { - - dev->flags &= ~AHC_DEV_UNCONFIGURED; - } else { - dev->flags |= AHC_DEV_UNCONFIGURED; - break; - } - - /* - * Update our notion of this device's transfer - * negotiation capabilities. - */ - scsiid = BUILD_SCSIID(ahc, cmd); - ahc_compile_devinfo(&devinfo, SCSIID_OUR_ID(scsiid), - cmd->target, cmd->lun, - SCSIID_CHANNEL(ahc, scsiid), - ROLE_INITIATOR); - tinfo = ahc_fetch_transinfo(ahc, devinfo.channel, - devinfo.our_scsiid, - devinfo.target, &tstate); - user = &tinfo->user; - goal = &tinfo->goal; - curr = &tinfo->curr; - width = user->width; - period = user->period; - offset = user->offset; - ppr_options = user->ppr_options; - minlen = offsetof(struct scsi_inquiry_data, version) + 1; - if (transferred_len >= minlen) { - curr->protocol_version = SID_ANSI_REV(sid); - - /* - * Only attempt SPI3 once we've verified that - * the device claims to support SPI3 features. - */ - if (curr->protocol_version < SCSI_REV_2) - curr->transport_version = SID_ANSI_REV(sid); - else - curr->transport_version = SCSI_REV_2; - } - - minlen = offsetof(struct scsi_inquiry_data, flags) + 1; - if (transferred_len >= minlen - && (sid->additional_length + 4) >= minlen) { - if ((sid->flags & SID_WBus16) == 0) - width = MSG_EXT_WDTR_BUS_8_BIT; - if ((sid->flags & SID_Sync) == 0) { - period = 0; - offset = 0; - ppr_options = 0; - } - } else { - /* Keep current settings */ - break; - } - minlen = offsetof(struct scsi_inquiry_data, spi3data) + 1; - /* - * This is a kludge to deal with inquiry requests that - * are not large enough for us to pull the spi3/4 bits. - * In this case, we assume that a device that tells us - * they can provide inquiry data that spans the SPI3 - * bits and says its SCSI3 can handle a PPR request. - * If the inquiry request has sufficient buffer space to - * cover SPI3 bits, we honor them regardless of reported - * SCSI REV. We also allow any device that has had its - * goal ppr_options set to allow DT speeds to keep that - * option if a short inquiry occurs that would fail the - * normal tests outlined above. - */ - if ((sid->additional_length + 4) >= minlen) { - if (transferred_len >= minlen) { - if ((sid->spi3data & SID_SPI_CLOCK_DT) == 0) - ppr_options = 0; - } else if ((goal->ppr_options & MSG_EXT_PPR_DT_REQ)== 0) - ppr_options = 0; - - if (curr->protocol_version > SCSI_REV_2) - curr->transport_version = 3; - } else { - ppr_options = 0; - } - ahc_validate_width(ahc, /*tinfo limit*/NULL, &width, - ROLE_UNKNOWN); - if ((ahc->features & AHC_ULTRA2) != 0) - maxsync = AHC_SYNCRATE_DT; - else if ((ahc->features & AHC_ULTRA) != 0) - maxsync = AHC_SYNCRATE_ULTRA; - else - maxsync = AHC_SYNCRATE_FAST; - - syncrate = ahc_find_syncrate(ahc, &period, - &ppr_options, maxsync); - ahc_validate_offset(ahc, /*tinfo limit*/NULL, syncrate, - &offset, width, ROLE_UNKNOWN); - if (offset == 0 || period == 0) { - period = 0; - offset = 0; - ppr_options = 0; - } - /* Apply our filtered user settings. */ - ahc_set_width(ahc, &devinfo, width, - AHC_TRANS_GOAL, /*paused*/FALSE); - ahc_set_syncrate(ahc, &devinfo, syncrate, period, - offset, ppr_options, AHC_TRANS_GOAL, - /*paused*/FALSE); - break; - } - default: - panic("ahc_linux_filter_command: Unexpected Command type %x\n", - cmd->cmnd[0]); - break; - } -} - -#if 0 -static void -ahc_linux_sem_timeout(u_long arg) -{ - struct semaphore *sem; - - sem = (struct semaphore *)arg; - up(sem); -} - -static void -ahc_linux_freeze_sim_queue(struct ahc_softc *ahc) -{ - ahc->platform_data->qfrozen++; - if (ahc->platform_data->qfrozen == 1) - scsi_block_requests(ahc->platform_data->host); -} - -static void -ahc_linux_release_sim_queue(u_long arg) -{ - struct ahc_softc *ahc; - u_long s; - int unblock_reqs; - - ahc = (struct ahc_softc *)arg; - unblock_reqs = 0; - ahc_lock(ahc, &s); - if (ahc->platform_data->qfrozen > 0) - ahc->platform_data->qfrozen--; - if (ahc->platform_data->qfrozen == 0) { - unblock_reqs = 1; - } - ahc_unlock(ahc, &s); - /* - * There is still a race here. The mid-layer - * should keep its own freeze count and use - * a bottom half handler to run the queues - * so we can unblock with our own lock held. - */ - if (unblock_reqs) { - scsi_unblock_requests(ahc->platform_data->host); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_schedule(&ahc->platform_data->runq_tasklet); -#else - ahc_runq_tasklet((unsigned long)ahc); -#endif - } -} -#endif /* 0 */ - -static void -ahc_linux_dev_timed_unfreeze(u_long arg) -{ - struct ahc_linux_device *dev; - struct ahc_softc *ahc; - u_long s; - - dev = (struct ahc_linux_device *)arg; - ahc = dev->target->ahc; - ahc_lock(ahc, &s); - dev->flags &= ~AHC_DEV_TIMER_ACTIVE; - if (dev->qfrozen > 0) - dev->qfrozen--; - if (dev->qfrozen == 0 - && (dev->flags & AHC_DEV_ON_RUN_LIST) == 0) - ahc_linux_run_device_queue(ahc, dev); - ahc_unlock(ahc, &s); -} - -static int -ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag) -{ - struct ahc_softc *ahc; - struct ahc_cmd *acmd; - struct ahc_cmd *list_acmd; - struct ahc_linux_device *dev; - struct scb *pending_scb; - u_long s; - u_int saved_scbptr; - u_int active_scb_index; - u_int last_phase; - int retval; - int paused; - int wait; - int disconnected; - - paused = FALSE; - wait = FALSE; - ahc = *(struct ahc_softc **)cmd->host->hostdata; - acmd = (struct ahc_cmd *)cmd; - - printf("%s:%d:%d:%d: Attempting to queue a%s message\n", - ahc_name(ahc), cmd->channel, cmd->target, cmd->lun, - flag == SCB_ABORT ? "n ABORT" : " TARGET RESET"); - - /* - * It is a bug that the upper layer takes - * this lock just prior to calling us. - */ - spin_unlock_irq(&io_request_lock); - - ahc_lock(ahc, &s); - - /* - * First determine if we currently own this command. - * Start by searching the device queue. If not found - * there, check the pending_scb list. If not found - * at all, and the system wanted us to just abort the - * command return success. - */ - dev = ahc_linux_get_device(ahc, cmd->channel, cmd->target, - cmd->lun, /*alloc*/FALSE); - - if (dev == NULL) { - /* - * No target device for this command exists, - * so we must not still own the command. - */ - printf("%s:%d:%d:%d: Is not an active device\n", - ahc_name(ahc), cmd->channel, cmd->target, cmd->lun); - retval = SUCCESS; - goto no_cmd; - } - - TAILQ_FOREACH(list_acmd, &dev->busyq, acmd_links.tqe) { - if (list_acmd == acmd) - break; - } - - if (list_acmd != NULL) { - printf("%s:%d:%d:%d: Command found on device queue\n", - ahc_name(ahc), cmd->channel, cmd->target, cmd->lun); - if (flag == SCB_ABORT) { - TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe); - cmd->result = DID_ABORT << 16; - ahc_linux_queue_cmd_complete(ahc, cmd); - retval = SUCCESS; - goto done; - } - } - - if ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0 - && ahc_search_untagged_queues(ahc, cmd, cmd->target, - cmd->channel + 'A', cmd->lun, - CAM_REQ_ABORTED, SEARCH_COMPLETE) != 0) { - printf("%s:%d:%d:%d: Command found on untagged queue\n", - ahc_name(ahc), cmd->channel, cmd->target, cmd->lun); - retval = SUCCESS; - goto done; - } - - /* - * See if we can find a matching cmd in the pending list. - */ - LIST_FOREACH(pending_scb, &ahc->pending_scbs, pending_links) { - if (pending_scb->io_ctx == cmd) - break; - } - - if (pending_scb == NULL && flag == SCB_DEVICE_RESET) { - - /* Any SCB for this device will do for a target reset */ - LIST_FOREACH(pending_scb, &ahc->pending_scbs, pending_links) { - if (ahc_match_scb(ahc, pending_scb, cmd->target, - cmd->channel + 'A', CAM_LUN_WILDCARD, - SCB_LIST_NULL, ROLE_INITIATOR) == 0) - break; - } - } - - if (pending_scb == NULL) { - printf("%s:%d:%d:%d: Command not found\n", - ahc_name(ahc), cmd->channel, cmd->target, cmd->lun); - goto no_cmd; - } - - if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) { - /* - * We can't queue two recovery actions using the same SCB - */ - retval = FAILED; - goto done; - } - - /* - * Ensure that the card doesn't do anything - * behind our back and that no selections have occurred - * that have not been serviced. Also make sure that we - * didn't "just" miss an interrupt that would - * affect this cmd. - */ - ahc->flags |= AHC_ALL_INTERRUPTS; - do { - if (paused) - ahc_unpause(ahc); - ahc_intr(ahc); - ahc_pause(ahc); - paused = TRUE; - ahc_outb(ahc, SCSISEQ, ahc_inb(ahc, SCSISEQ) & ~ENSELO); - ahc_clear_critical_section(ahc); - } while ((ahc_inb(ahc, INTSTAT) & INT_PEND) != 0 - || (ahc_inb(ahc, SSTAT0) & (SELDO|SELINGO))); - ahc->flags &= ~AHC_ALL_INTERRUPTS; - - ahc_dump_card_state(ahc); - - if ((pending_scb->flags & SCB_ACTIVE) == 0) { - printf("%s:%d:%d:%d: Command already completed\n", - ahc_name(ahc), cmd->channel, cmd->target, cmd->lun); - goto no_cmd; - } - - disconnected = TRUE; - if (flag == SCB_ABORT) { - if (ahc_search_qinfifo(ahc, cmd->target, cmd->channel + 'A', - cmd->lun, pending_scb->hscb->tag, - ROLE_INITIATOR, CAM_REQ_ABORTED, - SEARCH_COMPLETE) > 0) { - printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", - ahc_name(ahc), cmd->channel, cmd->target, - cmd->lun); - retval = SUCCESS; - goto done; - } - } else if (ahc_search_qinfifo(ahc, cmd->target, cmd->channel + 'A', - cmd->lun, pending_scb->hscb->tag, - ROLE_INITIATOR, /*status*/0, - SEARCH_COUNT) > 0) { - disconnected = FALSE; - } - - if (disconnected && (ahc_inb(ahc, SEQ_FLAGS) & IDENTIFY_SEEN) != 0) { - struct scb *bus_scb; - - bus_scb = ahc_lookup_scb(ahc, ahc_inb(ahc, SCB_TAG)); - if (bus_scb == pending_scb) - disconnected = FALSE; - else if (flag != SCB_ABORT - && ahc_inb(ahc, SAVED_SCSIID) == pending_scb->hscb->scsiid - && ahc_inb(ahc, SAVED_LUN) == pending_scb->hscb->lun) - disconnected = FALSE; - } - - /* - * At this point, pending_scb is the scb associated with the - * passed in command. That command is currently active on the - * bus, is in the disconnected state, or we're hoping to find - * a command for the same target active on the bus to abuse to - * send a BDR. Queue the appropriate message based on which of - * these states we are in. - */ - last_phase = ahc_inb(ahc, LASTPHASE); - saved_scbptr = ahc_inb(ahc, SCBPTR); - active_scb_index = ahc_inb(ahc, SCB_TAG); - if (last_phase != P_BUSFREE - && (pending_scb->hscb->tag == active_scb_index - || (flag == SCB_DEVICE_RESET - && SCSIID_TARGET(ahc, ahc_inb(ahc, SAVED_SCSIID)) == cmd->target))) { - - /* - * We're active on the bus, so assert ATN - * and hope that the target responds. - */ - pending_scb = ahc_lookup_scb(ahc, active_scb_index); - pending_scb->flags |= SCB_RECOVERY_SCB|flag; - ahc_outb(ahc, MSG_OUT, HOST_MSG); - ahc_outb(ahc, SCSISIGO, last_phase|ATNO); - printf("%s:%d:%d:%d: Device is active, asserting ATN\n", - ahc_name(ahc), cmd->channel, cmd->target, cmd->lun); - wait = TRUE; - } else if (disconnected) { - - /* - * Actually re-queue this SCB in an attempt - * to select the device before it reconnects. - * In either case (selection or reselection), - * we will now issue the approprate message - * to the timed-out device. - * - * Set the MK_MESSAGE control bit indicating - * that we desire to send a message. We - * also set the disconnected flag since - * in the paging case there is no guarantee - * that our SCB control byte matches the - * version on the card. We don't want the - * sequencer to abort the command thinking - * an unsolicited reselection occurred. - */ - pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED; - pending_scb->flags |= SCB_RECOVERY_SCB|flag; - - /* - * Remove any cached copy of this SCB in the - * disconnected list in preparation for the - * queuing of our abort SCB. We use the - * same element in the SCB, SCB_NEXT, for - * both the qinfifo and the disconnected list. - */ - ahc_search_disc_list(ahc, cmd->target, cmd->channel + 'A', - cmd->lun, pending_scb->hscb->tag, - /*stop_on_first*/TRUE, - /*remove*/TRUE, - /*save_state*/FALSE); - - /* - * In the non-paging case, the sequencer will - * never re-reference the in-core SCB. - * To make sure we are notified during - * reslection, set the MK_MESSAGE flag in - * the card's copy of the SCB. - */ - if ((ahc->flags & AHC_PAGESCBS) == 0) { - ahc_outb(ahc, SCBPTR, pending_scb->hscb->tag); - ahc_outb(ahc, SCB_CONTROL, - ahc_inb(ahc, SCB_CONTROL)|MK_MESSAGE); - } - - /* - * Clear out any entries in the QINFIFO first - * so we are the next SCB for this target - * to run. - */ - ahc_search_qinfifo(ahc, cmd->target, cmd->channel + 'A', - cmd->lun, SCB_LIST_NULL, ROLE_INITIATOR, - CAM_REQUEUE_REQ, SEARCH_COMPLETE); - ahc_print_path(ahc, pending_scb); - printf("Queuing a recovery SCB\n"); - ahc_qinfifo_requeue_tail(ahc, pending_scb); - ahc_outb(ahc, SCBPTR, saved_scbptr); - printf("%s:%d:%d:%d: Device is disconnected, re-queuing SCB\n", - ahc_name(ahc), cmd->channel, cmd->target, cmd->lun); - wait = TRUE; - } else { - printf("%s:%d:%d:%d: Unable to deliver message\n", - ahc_name(ahc), cmd->channel, cmd->target, cmd->lun); - retval = FAILED; - goto done; - } - -no_cmd: - /* - * Our assumption is that if we don't have the command, no - * recovery action was required, so we return success. Again, - * the semantics of the mid-layer recovery engine are not - * well defined, so this may change in time. - */ - retval = SUCCESS; -done: - if (paused) - ahc_unpause(ahc); - if (wait) { - // JWS - XEN - err... - printf("JWS - aic7xxx: recovery-wait: doh\n"); - retval=FAILED; - /* - struct timer_list timer; - int ret; - - ahc_unlock(ahc, &s); - init_timer(&timer); - timer.data = (u_long)&ahc->platform_data->eh_sem; - timer.expires = jiffies + (5 * HZ); - timer.function = ahc_linux_sem_timeout; - add_timer(&timer); - printf("Recovery code sleeping\n"); - down(&ahc->platform_data->eh_sem); - printf("Recovery code awake\n"); - ret = del_timer(&timer); - if (ret == 0) { - printf("Timer Expired\n"); - retval = FAILED; - } - ahc_lock(ahc, &s); - */ - } - acmd = TAILQ_FIRST(&ahc->platform_data->completeq); - TAILQ_INIT(&ahc->platform_data->completeq); - ahc_unlock(ahc, &s); - if (acmd != NULL) - ahc_linux_run_complete_queue(ahc, acmd); - ahc_runq_tasklet((unsigned long)ahc); - spin_lock_irq(&io_request_lock); - return (retval); -} - -/* - * Abort the current SCSI command(s). - */ -int -ahc_linux_abort(Scsi_Cmnd *cmd) -{ - int error; - - error = ahc_linux_queue_recovery_cmd(cmd, SCB_ABORT); - if (error != 0) - printf("aic7xxx_abort returns 0x%x\n", error); - return (error); -} - -/* - * Attempt to send a target reset message to the device that timed out. - */ -int -ahc_linux_dev_reset(Scsi_Cmnd *cmd) -{ - int error; - - error = ahc_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET); - if (error != 0) - printf("aic7xxx_dev_reset returns 0x%x\n", error); - return (error); -} - -/* - * Reset the SCSI bus. - */ -int -ahc_linux_bus_reset(Scsi_Cmnd *cmd) -{ - struct ahc_softc *ahc; - struct ahc_cmd *acmd; - u_long s; - int found; - - /* - * It is a bug that the upper layer takes - * this lock just prior to calling us. - */ - spin_unlock_irq(&io_request_lock); - - ahc = *(struct ahc_softc **)cmd->host->hostdata; - ahc_lock(ahc, &s); - found = ahc_reset_channel(ahc, cmd->channel + 'A', - /*initiate reset*/TRUE); - acmd = TAILQ_FIRST(&ahc->platform_data->completeq); - TAILQ_INIT(&ahc->platform_data->completeq); - ahc_unlock(ahc, &s); - if (bootverbose) - printf("%s: SCSI bus reset delivered. " - "%d SCBs aborted.\n", ahc_name(ahc), found); - - if (acmd != NULL) - ahc_linux_run_complete_queue(ahc, acmd); - - spin_lock_irq(&io_request_lock); - return SUCCESS; -} - -/* - * Return the disk geometry for the given SCSI device. - */ -int -ahc_linux_biosparam(Disk *disk, kdev_t dev, int geom[]) -{ - int heads; - int sectors; - int cylinders; - //int ret; - int extended; - struct ahc_softc *ahc; - //struct buffer_head *bh; - - ahc = *((struct ahc_softc **)disk->device->host->hostdata); -#if 0 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17) - bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, block_size(dev)); -#else - bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, 1024); -#endif - - if (bh) { - ret = scsi_partsize(bh, disk->capacity, - &geom[2], &geom[0], &geom[1]); - brelse(bh); - if (ret != -1) - return (ret); - } -#endif - heads = 64; - sectors = 32; - cylinders = disk->capacity / (heads * sectors); - - if (aic7xxx_extended != 0) - extended = 1; - else if (disk->device->channel == 0) - extended = (ahc->flags & AHC_EXTENDED_TRANS_A) != 0; - else - extended = (ahc->flags & AHC_EXTENDED_TRANS_B) != 0; - if (extended && cylinders >= 1024) { - heads = 255; - sectors = 63; - cylinders = disk->capacity / (heads * sectors); - } - geom[0] = heads; - geom[1] = sectors; - geom[2] = cylinders; - return (0); -} - -/* - * Free the passed in Scsi_Host memory structures prior to unloading the - * module. - */ -int -ahc_linux_release(struct Scsi_Host * host) -{ - struct ahc_softc *ahc; - u_long l; - - ahc_list_lock(&l); - if (host != NULL) { - - /* - * We should be able to just perform - * the free directly, but check our - * list for extra sanity. - */ - ahc = ahc_find_softc(*(struct ahc_softc **)host->hostdata); - if (ahc != NULL) { - u_long s; - - ahc_lock(ahc, &s); - ahc_intr_enable(ahc, FALSE); - ahc_unlock(ahc, &s); - ahc_free(ahc); - } - } - ahc_list_unlock(&l); - return (0); -} - -void -ahc_platform_dump_card_state(struct ahc_softc *ahc) -{ - struct ahc_linux_device *dev; - int channel; - int maxchannel; - int target; - int maxtarget; - int lun; - int i; - - maxchannel = (ahc->features & AHC_TWIN) ? 1 : 0; - maxtarget = (ahc->features & AHC_WIDE) ? 15 : 7; - for (channel = 0; channel <= maxchannel; channel++) { - - for (target = 0; target <=maxtarget; target++) { - - for (lun = 0; lun < AHC_NUM_LUNS; lun++) { - struct ahc_cmd *acmd; - - dev = ahc_linux_get_device(ahc, channel, target, - lun, /*alloc*/FALSE); - if (dev == NULL) - continue; - - printf("DevQ(%d:%d:%d): ", - channel, target, lun); - i = 0; - TAILQ_FOREACH(acmd, &dev->busyq, - acmd_links.tqe) { - if (i++ > AHC_SCB_MAX) - break; - } - printf("%d waiting\n", i); - } - } - } -} - - -#if defined(MODULE) || LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -static Scsi_Host_Template driver_template = AIC7XXX; -Scsi_Host_Template *aic7xxx_driver_template = &driver_template; -#include "../scsi_module.c.inc" -#endif - diff --git a/xen/drivers/scsi/aic7xxx/aic7xxx_osm.h b/xen/drivers/scsi/aic7xxx/aic7xxx_osm.h deleted file mode 100644 index de08fafafb..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ /dev/null @@ -1,1199 +0,0 @@ -/* - * Adaptec AIC7xxx device driver for Linux. - * - * Copyright (c) 1994 John Aycock - * The University of Calgary Department of Computer Science. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#82 $ - * - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#82 $ - * - */ - -#ifndef _AIC7XXX_LINUX_H_ -#define _AIC7XXX_LINUX_H_ -#include -#include -#include -#include -#include -#include -#include -#include -//#include -#ifndef AHC_MODVERSION_FILE -#define __NO_VERSION__ -#endif -#include -#include -#include - -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) -#endif - -#define LINUX_VERSION_CODE KERNEL_VERSION(2,4,20) - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -#include /* For tasklet support. */ -#include -#include -#else -#include -#endif - -/* Core SCSI definitions */ -#include "../scsi.h" -#include "../hosts.h" - -/* Name space conflict with BSD queue macros */ -#ifdef LIST_HEAD -#undef LIST_HEAD -#endif - -#include "cam.h" -#include "queue.h" -#include "scsi_message.h" - -/************************* Forward Declarations *******************************/ -struct ahc_softc; -typedef struct pci_dev *ahc_dev_softc_t; -typedef Scsi_Cmnd *ahc_io_ctx_t; - -/******************************* Byte Order ***********************************/ -#define ahc_htobe16(x) cpu_to_be16(x) -#define ahc_htobe32(x) cpu_to_be32(x) -#define ahc_htobe64(x) cpu_to_be64(x) -#define ahc_htole16(x) cpu_to_le16(x) -#define ahc_htole32(x) cpu_to_le32(x) -#define ahc_htole64(x) cpu_to_le64(x) - -#define ahc_be16toh(x) be16_to_cpu(x) -#define ahc_be32toh(x) be32_to_cpu(x) -#define ahc_be64toh(x) be64_to_cpu(x) -#define ahc_le16toh(x) le16_to_cpu(x) -#define ahc_le32toh(x) le32_to_cpu(x) -#define ahc_le64toh(x) le64_to_cpu(x) - -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN 1234 -#endif - -#ifndef BIG_ENDIAN -#define BIG_ENDIAN 4321 -#endif - -#ifndef BYTE_ORDER -#if defined(__BIG_ENDIAN) -#define BYTE_ORDER BIG_ENDIAN -#endif -#if defined(__LITTLE_ENDIAN) -#define BYTE_ORDER LITTLE_ENDIAN -#endif -#endif /* BYTE_ORDER */ - -/************************* Configuration Data *********************************/ -extern int aic7xxx_no_probe; -extern int aic7xxx_detect_complete; -extern Scsi_Host_Template* aic7xxx_driver_template; - -/***************************** Bus Space/DMA **********************************/ - -//#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,17) -typedef dma_addr_t bus_addr_t; -//#else -//typedef uint32_t bus_addr_t; -//#endif -typedef uint32_t bus_size_t; - -typedef enum { - BUS_SPACE_MEMIO, - BUS_SPACE_PIO -} bus_space_tag_t; - -typedef union { - u_long ioport; - volatile uint8_t *maddr; -} bus_space_handle_t; - -typedef struct bus_dma_segment -{ - bus_addr_t ds_addr; - bus_size_t ds_len; -} bus_dma_segment_t; - -struct ahc_linux_dma_tag -{ - bus_size_t alignment; - bus_size_t boundary; - bus_size_t maxsize; -}; -typedef struct ahc_linux_dma_tag* bus_dma_tag_t; - -struct ahc_linux_dmamap -{ - bus_addr_t bus_addr; -}; -typedef struct ahc_linux_dmamap* bus_dmamap_t; - -typedef int bus_dma_filter_t(void*, bus_addr_t); -typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); - -#define BUS_DMA_WAITOK 0x0 -#define BUS_DMA_NOWAIT 0x1 -#define BUS_DMA_ALLOCNOW 0x2 -#define BUS_DMA_LOAD_SEGS 0x4 /* - * Argument is an S/G list not - * a single buffer. - */ - -#define BUS_SPACE_MAXADDR 0xFFFFFFFF -#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF -#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF - -int ahc_dma_tag_create(struct ahc_softc *, bus_dma_tag_t /*parent*/, - bus_size_t /*alignment*/, bus_size_t /*boundary*/, - bus_addr_t /*lowaddr*/, bus_addr_t /*highaddr*/, - bus_dma_filter_t*/*filter*/, void */*filterarg*/, - bus_size_t /*maxsize*/, int /*nsegments*/, - bus_size_t /*maxsegsz*/, int /*flags*/, - bus_dma_tag_t */*dma_tagp*/); - -void ahc_dma_tag_destroy(struct ahc_softc *, bus_dma_tag_t /*tag*/); - -int ahc_dmamem_alloc(struct ahc_softc *, bus_dma_tag_t /*dmat*/, - void** /*vaddr*/, int /*flags*/, - bus_dmamap_t* /*mapp*/); - -void ahc_dmamem_free(struct ahc_softc *, bus_dma_tag_t /*dmat*/, - void* /*vaddr*/, bus_dmamap_t /*map*/); - -void ahc_dmamap_destroy(struct ahc_softc *, bus_dma_tag_t /*tag*/, - bus_dmamap_t /*map*/); - -int ahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t /*dmat*/, - bus_dmamap_t /*map*/, void * /*buf*/, - bus_size_t /*buflen*/, bus_dmamap_callback_t *, - void */*callback_arg*/, int /*flags*/); - -int ahc_dmamap_unload(struct ahc_softc *, bus_dma_tag_t, bus_dmamap_t); - -/* - * Operations performed by ahc_dmamap_sync(). - */ -#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ -#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ -#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ -#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ - -/* - * XXX - * ahc_dmamap_sync is only used on buffers allocated with - * the pci_alloc_consistent() API. Although I'm not sure how - * this works on architectures with a write buffer, Linux does - * not have an API to sync "coherent" memory. Perhaps we need - * to do an mb()? - */ -#define ahc_dmamap_sync(ahc, dma_tag, dmamap, offset, len, op) - -/************************** SCSI Constants/Structures *************************/ -#define SCSI_REV_2 2 -#define SCSI_STATUS_OK 0x00 -#define SCSI_STATUS_CHECK_COND 0x02 -#define SCSI_STATUS_COND_MET 0x04 -#define SCSI_STATUS_BUSY 0x08 -#define SCSI_STATUS_INTERMED 0x10 -#define SCSI_STATUS_INTERMED_COND_MET 0x14 -#define SCSI_STATUS_RESERV_CONFLICT 0x18 -#define SCSI_STATUS_CMD_TERMINATED 0x22 -#define SCSI_STATUS_QUEUE_FULL 0x28 - -/* - * 6 byte request sense CDB format. - */ -struct scsi_sense -{ - uint8_t opcode; - uint8_t byte2; - uint8_t unused[2]; - uint8_t length; - uint8_t control; -}; - -struct scsi_sense_data -{ - uint8_t error_code; - uint8_t segment; - uint8_t flags; - uint8_t info[4]; - uint8_t extra_len; - uint8_t cmd_spec_info[4]; - uint8_t add_sense_code; - uint8_t add_sense_code_qual; - uint8_t fru; - uint8_t sense_key_spec[3]; - uint8_t extra_bytes[14]; -}; - -struct scsi_inquiry -{ - u_int8_t opcode; - u_int8_t byte2; -#define SI_EVPD 0x01 - u_int8_t page_code; - u_int8_t reserved; - u_int8_t length; - u_int8_t control; -}; - -struct scsi_inquiry_data -{ - uint8_t device; -#define SID_TYPE(inq_data) ((inq_data)->device & 0x1f) -#define SID_QUAL(inq_data) (((inq_data)->device & 0xE0) >> 5) -#define SID_QUAL_LU_CONNECTED 0x00 /* - * The specified peripheral device - * type is currently connected to - * logical unit. If the target cannot - * determine whether or not a physical - * device is currently connected, it - * shall also use this peripheral - * qualifier when returning the INQUIRY - * data. This peripheral qualifier - * does not mean that the device is - * ready for access by the initiator. - */ -#define SID_QUAL_LU_OFFLINE 0x01 /* - * The target is capable of supporting - * the specified peripheral device type - * on this logical unit; however, the - * physical device is not currently - * connected to this logical unit. - */ -#define SID_QUAL_RSVD 0x02 -#define SID_QUAL_BAD_LU 0x03 /* - * The target is not capable of - * supporting a physical device on - * this logical unit. For this - * peripheral qualifier the peripheral - * device type shall be set to 1Fh to - * provide compatibility with previous - * versions of SCSI. All other - * peripheral device type values are - * reserved for this peripheral - * qualifier. - */ -#define SID_QUAL_IS_VENDOR_UNIQUE(inq_data) ((SID_QUAL(inq_data) & 0x08) != 0) - uint8_t dev_qual2; -#define SID_QUAL2 0x7F -#define SID_IS_REMOVABLE(inq_data) (((inq_data)->dev_qual2 & 0x80) != 0) - uint8_t version; -#define SID_ANSI_REV(inq_data) ((inq_data)->version & 0x07) -#define SCSI_REV_0 0 -#define SCSI_REV_CCS 1 -#define SCSI_REV_2 2 -#define SCSI_REV_SPC 3 -#define SCSI_REV_SPC2 4 - -#define SID_ECMA 0x38 -#define SID_ISO 0xC0 - uint8_t response_format; -#define SID_AENC 0x80 -#define SID_TrmIOP 0x40 - uint8_t additional_length; - uint8_t reserved[2]; - uint8_t flags; -#define SID_SftRe 0x01 -#define SID_CmdQue 0x02 -#define SID_Linked 0x08 -#define SID_Sync 0x10 -#define SID_WBus16 0x20 -#define SID_WBus32 0x40 -#define SID_RelAdr 0x80 -#define SID_VENDOR_SIZE 8 - char vendor[SID_VENDOR_SIZE]; -#define SID_PRODUCT_SIZE 16 - char product[SID_PRODUCT_SIZE]; -#define SID_REVISION_SIZE 4 - char revision[SID_REVISION_SIZE]; - /* - * The following fields were taken from SCSI Primary Commands - 2 - * (SPC-2) Revision 14, Dated 11 November 1999 - */ -#define SID_VENDOR_SPECIFIC_0_SIZE 20 - u_int8_t vendor_specific0[SID_VENDOR_SPECIFIC_0_SIZE]; - /* - * An extension of SCSI Parallel Specific Values - */ -#define SID_SPI_IUS 0x01 -#define SID_SPI_QAS 0x02 -#define SID_SPI_CLOCK_ST 0x00 -#define SID_SPI_CLOCK_DT 0x04 -#define SID_SPI_CLOCK_DT_ST 0x0C -#define SID_SPI_MASK 0x0F - uint8_t spi3data; - uint8_t reserved2; - /* - * Version Descriptors, stored 2 byte values. - */ - uint8_t version1[2]; - uint8_t version2[2]; - uint8_t version3[2]; - uint8_t version4[2]; - uint8_t version5[2]; - uint8_t version6[2]; - uint8_t version7[2]; - uint8_t version8[2]; - - uint8_t reserved3[22]; - -#define SID_VENDOR_SPECIFIC_1_SIZE 160 - uint8_t vendor_specific1[SID_VENDOR_SPECIFIC_1_SIZE]; -}; - -/********************************** Includes **********************************/ -/* Host template and function declarations referenced by the template. */ -#include "aic7xxx_host.h" - -/* Core driver definitions */ -#include "aic7xxx.h" - -/* SMP support */ -//#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,17) -#include -//#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93) -//#include -//#endif - -#define AIC7XXX_DRIVER_VERSION "6.2.8" - -/**************************** Front End Queues ********************************/ -/* - * Data structure used to cast the Linux struct scsi_cmnd to something - * that allows us to use the queue macros. The linux structure has - * plenty of space to hold the links fields as required by the queue - * macros, but the queue macors require them to have the correct type. - */ -struct ahc_cmd_internal { - /* Area owned by the Linux scsi layer. */ - uint8_t private[offsetof(struct scsi_cmnd, SCp.Status)]; - union { - STAILQ_ENTRY(ahc_cmd) ste; - LIST_ENTRY(ahc_cmd) le; - TAILQ_ENTRY(ahc_cmd) tqe; - } links; - uint32_t end; -}; - -struct ahc_cmd { - union { - struct ahc_cmd_internal icmd; - struct scsi_cmnd scsi_cmd; - } un; -}; - -#define acmd_icmd(cmd) ((cmd)->un.icmd) -#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd) -#define acmd_links un.icmd.links - -/*************************** Device Data Structures ***************************/ -/* - * A per probed device structure used to deal with some error recovery - * scenarios that the Linux mid-layer code just doesn't know how to - * handle. The structure allocated for a device only becomes persistant - * after a successfully completed inquiry command to the target when - * that inquiry data indicates a lun is present. - */ -TAILQ_HEAD(ahc_busyq, ahc_cmd); -typedef enum { - AHC_DEV_UNCONFIGURED = 0x01, - AHC_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */ - AHC_DEV_TIMER_ACTIVE = 0x04, /* Our timer is active */ - AHC_DEV_ON_RUN_LIST = 0x08, /* Queued to be run later */ - AHC_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */ - AHC_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */ - AHC_DEV_PERIODIC_OTAG = 0x40 /* Send OTAG to prevent starvation */ -} ahc_dev_flags; - -struct ahc_linux_target; -struct ahc_linux_device { - TAILQ_ENTRY(ahc_linux_device) links; - struct ahc_busyq busyq; - - /* - * The number of transactions currently - * queued to the device. - */ - int active; - - /* - * The currently allowed number of - * transactions that can be queued to - * the device. Must be signed for - * conversion from tagged to untagged - * mode where the device may have more - * than one outstanding active transaction. - */ - int openings; - - /* - * A positive count indicates that this - * device's queue is halted. - */ - u_int qfrozen; - - /* - * Cumulative command counter. - */ - u_long commands_issued; - - /* - * The number of tagged transactions when - * running at our current opening level - * that have been successfully received by - * this device since the last QUEUE FULL. - */ - u_int tag_success_count; -#define AHC_TAG_SUCCESS_INTERVAL 50 - - ahc_dev_flags flags; - - /* - * Per device timer. - */ - struct timer_list timer; - - /* - * The high limit for the tags variable. - */ - u_int maxtags; - - /* - * The computed number of tags outstanding - * at the time of the last QUEUE FULL event. - */ - u_int tags_on_last_queuefull; - - /* - * How many times we have seen a queue full - * with the same number of tags. This is used - * to stop our adaptive queue depth algorithm - * on devices with a fixed number of tags. - */ - u_int last_queuefull_same_count; -#define AHC_LOCK_TAGS_COUNT 50 - - /* - * How many transactions have been queued - * without the device going idle. We use - * this statistic to determine when to issue - * an ordered tag to prevent transaction - * starvation. This statistic is only updated - * if the AHC_DEV_PERIODIC_OTAG flag is set - * on this device. - */ - u_int commands_since_idle_or_otag; -#define AHC_OTAG_THRESH 500 - - int lun; - struct ahc_linux_target *target; -}; - -struct ahc_linux_target { - struct ahc_linux_device *devices[AHC_NUM_LUNS]; - int channel; - int target; - int refcount; - struct ahc_transinfo last_tinfo; - struct ahc_softc *ahc; -}; - -/********************* Definitions Required by the Core ***********************/ -/* - * Number of SG segments we require. So long as the S/G segments for - * a particular transaction are allocated in a physically contiguous - * manner and are allocated below 4GB, the number of S/G segments is - * unrestricted. - */ -#define AHC_NSEG 128 - -/* - * Per-SCB OSM storage. - */ -struct scb_platform_data { - struct ahc_linux_device *dev; - bus_addr_t buf_busaddr; - uint32_t xfer_len; - //#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - uint32_t resid; /* Transfer residual */ - //#endif -}; - -/* - * Define a structure used for each host adapter. All members are - * aligned on a boundary >= the size of the member to honor the - * alignment restrictions of the various platforms supported by - * this driver. - */ -TAILQ_HEAD(ahc_completeq, ahc_cmd); -struct ahc_platform_data { - /* - * Fields accessed from interrupt context. - */ - struct ahc_linux_target *targets[AHC_NUM_TARGETS]; - TAILQ_HEAD(, ahc_linux_device) device_runq; - struct ahc_completeq completeq; - - //#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) - spinlock_t spin_lock; - //#endif - //#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - struct tasklet_struct runq_tasklet; - //#endif - u_int qfrozen; - struct timer_list reset_timer; - // struct semaphore eh_sem; - struct Scsi_Host *host; /* pointer to scsi host */ -#define AHC_LINUX_NOIRQ ((uint32_t)~0) - uint32_t irq; /* IRQ for this adapter */ - uint32_t bios_address; - uint32_t mem_busaddr; /* Mem Base Addr */ - bus_addr_t hw_dma_mask; -}; - -/************************** OS Utility Wrappers *******************************/ -#define printf printk -#define M_NOWAIT GFP_ATOMIC -#define M_WAITOK 0 -#define malloc(size, type, flags) kmalloc(size, flags) -#define free(ptr, type) kfree(ptr) - -static __inline void ahc_delay(long); -static __inline void -ahc_delay(long usec) -{ - /* - * udelay on Linux can have problems for - * multi-millisecond waits. Wait at most - * 1024us per call. - */ - while (usec > 0) { - udelay(usec % 1024); - usec -= 1024; - } -} - - -/***************************** Low Level I/O **********************************/ -#if defined(__powerpc__) || defined(__i386__) || defined(__ia64__) -#define MMAPIO -#endif - -static __inline uint8_t ahc_inb(struct ahc_softc * ahc, long port); -static __inline void ahc_outb(struct ahc_softc * ahc, long port, uint8_t val); -static __inline void ahc_outsb(struct ahc_softc * ahc, long port, - uint8_t *, int count); -static __inline void ahc_insb(struct ahc_softc * ahc, long port, - uint8_t *, int count); - -static __inline uint8_t -ahc_inb(struct ahc_softc * ahc, long port) -{ - uint8_t x; -#ifdef MMAPIO - - if (ahc->tag == BUS_SPACE_MEMIO) { - x = readb(ahc->bsh.maddr + port); - } else { - x = inb(ahc->bsh.ioport + port); - } -#else - x = inb(ahc->bsh.ioport + port); -#endif - mb(); - return (x); -} - -static __inline void -ahc_outb(struct ahc_softc * ahc, long port, uint8_t val) -{ -#ifdef MMAPIO - if (ahc->tag == BUS_SPACE_MEMIO) { - writeb(val, ahc->bsh.maddr + port); - } else { - outb(val, ahc->bsh.ioport + port); - } -#else - outb(val, ahc->bsh.ioport + port); -#endif - mb(); -} - -static __inline void -ahc_outsb(struct ahc_softc * ahc, long port, uint8_t *array, int count) -{ - int i; - - /* - * There is probably a more efficient way to do this on Linux - * but we don't use this for anything speed critical and this - * should work. - */ - for (i = 0; i < count; i++) - ahc_outb(ahc, port, *array++); -} - -static __inline void -ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int count) -{ - int i; - - /* - * There is probably a more efficient way to do this on Linux - * but we don't use this for anything speed critical and this - * should work. - */ - for (i = 0; i < count; i++) - *array++ = ahc_inb(ahc, port); -} - -/**************************** Initialization **********************************/ -int ahc_linux_register_host(struct ahc_softc *, - Scsi_Host_Template *); - -uint64_t ahc_linux_get_memsize(void); - -/*************************** Pretty Printing **********************************/ - -#define off_t unsigned long - -struct info_str { - char *buffer; - int length; - off_t offset; - int pos; -}; - -void ahc_format_transinfo(struct info_str *info, - struct ahc_transinfo *tinfo); - - -/******************************** Locking *************************************/ -/* Lock protecting internal data structures */ -static __inline void ahc_lockinit(struct ahc_softc *); -static __inline void ahc_lock(struct ahc_softc *, unsigned long *flags); -static __inline void ahc_unlock(struct ahc_softc *, unsigned long *flags); - -/* Lock held during command compeletion to the upper layer */ -static __inline void ahc_done_lockinit(struct ahc_softc *); -static __inline void ahc_done_lock(struct ahc_softc *, unsigned long *flags); -static __inline void ahc_done_unlock(struct ahc_softc *, unsigned long *flags); - -/* Lock held during ahc_list manipulation and ahc softc frees */ -extern spinlock_t ahc_list_spinlock; -static __inline void ahc_list_lockinit(void); -static __inline void ahc_list_lock(unsigned long *flags); -static __inline void ahc_list_unlock(unsigned long *flags); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93) -static __inline void -ahc_lockinit(struct ahc_softc *ahc) -{ - spin_lock_init(&ahc->platform_data->spin_lock); -} - -static __inline void -ahc_lock(struct ahc_softc *ahc, unsigned long *flags) -{ - *flags = 0; - spin_lock_irqsave(&ahc->platform_data->spin_lock, *flags); -} - -static __inline void -ahc_unlock(struct ahc_softc *ahc, unsigned long *flags) -{ - spin_unlock_irqrestore(&ahc->platform_data->spin_lock, *flags); -} - -static __inline void -ahc_done_lockinit(struct ahc_softc *ahc) -{ - /* We don't own the iorequest lock, so we don't initialize it. */ -} - -static __inline void -ahc_done_lock(struct ahc_softc *ahc, unsigned long *flags) -{ - *flags = 0; - spin_lock_irqsave(&io_request_lock, *flags); -} - -static __inline void -ahc_done_unlock(struct ahc_softc *ahc, unsigned long *flags) -{ - spin_unlock_irqrestore(&io_request_lock, *flags); -} - -static __inline void -ahc_list_lockinit() -{ - spin_lock_init(&ahc_list_spinlock); -} - -static __inline void -ahc_list_lock(unsigned long *flags) -{ - *flags = 0; - spin_lock_irqsave(&ahc_list_spinlock, *flags); -} - -static __inline void -ahc_list_unlock(unsigned long *flags) -{ - spin_unlock_irqrestore(&ahc_list_spinlock, *flags); -} - -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) */ - -ahc_lockinit(struct ahc_softc *ahc) -{ -} - -static __inline void -ahc_lock(struct ahc_softc *ahc, unsigned long *flags) -{ - *flags = 0; - save_flags(*flags); - cli(); -} - -static __inline void -ahc_unlock(struct ahc_softc *ahc, unsigned long *flags) -{ - restore_flags(*flags); -} - -static __inline void -ahc_done_lockinit(struct ahc_softc *ahc) -{ -} - -static __inline void -ahc_done_lock(struct ahc_softc *ahc, unsigned long *flags) -{ - /* - * The done lock is always held while - * the ahc lock is held so blocking - * interrupts again would have no effect. - */ -} - -static __inline void -ahc_done_unlock(struct ahc_softc *ahc, unsigned long *flags) -{ -} - -static __inline void -ahc_list_lockinit() -{ -} - -static __inline void -ahc_list_lock(unsigned long *flags) -{ - *flags = 0; - save_flags(*flags); - cli(); -} - -static __inline void -ahc_list_unlock(unsigned long *flags) -{ - restore_flags(*flags); -} -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) */ - -/******************************* PCI Definitions ******************************/ -/* - * PCIM_xxx: mask to locate subfield in register - * PCIR_xxx: config register offset - * PCIC_xxx: device class - * PCIS_xxx: device subclass - * PCIP_xxx: device programming interface - * PCIV_xxx: PCI vendor ID (only required to fixup ancient devices) - * PCID_xxx: device ID - */ -#define PCIR_DEVVENDOR 0x00 -#define PCIR_VENDOR 0x00 -#define PCIR_DEVICE 0x02 -#define PCIR_COMMAND 0x04 -#define PCIM_CMD_PORTEN 0x0001 -#define PCIM_CMD_MEMEN 0x0002 -#define PCIM_CMD_BUSMASTEREN 0x0004 -#define PCIM_CMD_MWRICEN 0x0010 -#define PCIM_CMD_PERRESPEN 0x0040 -#define PCIR_STATUS 0x06 -#define PCIR_REVID 0x08 -#define PCIR_PROGIF 0x09 -#define PCIR_SUBCLASS 0x0a -#define PCIR_CLASS 0x0b -#define PCIR_CACHELNSZ 0x0c -#define PCIR_LATTIMER 0x0d -#define PCIR_HEADERTYPE 0x0e -#define PCIM_MFDEV 0x80 -#define PCIR_BIST 0x0f -#define PCIR_CAP_PTR 0x34 - -/* config registers for header type 0 devices */ -#define PCIR_MAPS 0x10 -#define PCIR_SUBVEND_0 0x2c -#define PCIR_SUBDEV_0 0x2e - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -extern struct pci_driver aic7xxx_pci_driver; -#endif - -typedef enum -{ - AHC_POWER_STATE_D0, - AHC_POWER_STATE_D1, - AHC_POWER_STATE_D2, - AHC_POWER_STATE_D3 -} ahc_power_state; - -void ahc_power_state_change(struct ahc_softc *ahc, - ahc_power_state new_state); -/**************************** VL/EISA Routines ********************************/ -int aic7770_linux_probe(Scsi_Host_Template *); -int aic7770_map_registers(struct ahc_softc *ahc, - u_int port); -int aic7770_map_int(struct ahc_softc *ahc, u_int irq); - -/******************************* PCI Routines *********************************/ -/* - * We need to use the bios32.h routines if we are kernel version 2.1.92 or less. - */ -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,92) -#if defined(__sparc_v9__) || defined(__powerpc__) -#error "PPC and Sparc platforms are only support under 2.1.92 and above" -#endif -#include -#endif - -int ahc_linux_pci_probe(Scsi_Host_Template *); -int ahc_pci_map_registers(struct ahc_softc *ahc); -int ahc_pci_map_int(struct ahc_softc *ahc); - -static __inline uint32_t ahc_pci_read_config(ahc_dev_softc_t pci, - int reg, int width); - -static __inline uint32_t -ahc_pci_read_config(ahc_dev_softc_t pci, int reg, int width) -{ - switch (width) { - case 1: - { - uint8_t retval; - - pci_read_config_byte(pci, reg, &retval); - return (retval); - } - case 2: - { - uint16_t retval; - pci_read_config_word(pci, reg, &retval); - return (retval); - } - case 4: - { - uint32_t retval; - pci_read_config_dword(pci, reg, &retval); - return (retval); - } - default: - panic("ahc_pci_read_config: Read size too big"); - /* NOTREACHED */ - return (0); - } -} - -static __inline void ahc_pci_write_config(ahc_dev_softc_t pci, - int reg, uint32_t value, - int width); - -static __inline void -ahc_pci_write_config(ahc_dev_softc_t pci, int reg, uint32_t value, int width) -{ - switch (width) { - case 1: - pci_write_config_byte(pci, reg, value); - break; - case 2: - pci_write_config_word(pci, reg, value); - break; - case 4: - pci_write_config_dword(pci, reg, value); - break; - default: - panic("ahc_pci_write_config: Write size too big"); - /* NOTREACHED */ - } -} - -static __inline int ahc_get_pci_function(ahc_dev_softc_t); -static __inline int -ahc_get_pci_function(ahc_dev_softc_t pci) -{ - return (PCI_FUNC(pci->devfn)); -} - -static __inline int ahc_get_pci_slot(ahc_dev_softc_t); -static __inline int -ahc_get_pci_slot(ahc_dev_softc_t pci) -{ - return (PCI_SLOT(pci->devfn)); -} - -static __inline int ahc_get_pci_bus(ahc_dev_softc_t); -static __inline int -ahc_get_pci_bus(ahc_dev_softc_t pci) -{ - return (pci->bus->number); -} - -static __inline void ahc_flush_device_writes(struct ahc_softc *); -static __inline void -ahc_flush_device_writes(struct ahc_softc *ahc) -{ - /* XXX Is this sufficient for all architectures??? */ - ahc_inb(ahc, INTSTAT); -} - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0) -#define pci_map_sg(pdev, sg_list, nseg, direction) (nseg) -#define pci_unmap_sg(pdev, sg_list, nseg, direction) -#define sg_dma_address(sg) (VIRT_TO_BUS((sg)->address)) -#define sg_dma_len(sg) ((sg)->length) -#define pci_map_single(pdev, buffer, bufflen, direction) \ - (VIRT_TO_BUS(buffer)) -#define pci_unmap_single(pdev, buffer, buflen, direction) -#endif - -/*********************** Transaction Access Wrappers **************************/ -static __inline void ahc_set_transaction_status(struct scb *, uint32_t); -static __inline -void ahc_set_transaction_status(struct scb *scb, uint32_t status) -{ - scb->io_ctx->result &= ~(CAM_STATUS_MASK << 16); - scb->io_ctx->result |= status << 16; -} - -static __inline void ahc_set_scsi_status(struct scb *, uint32_t); -static __inline -void ahc_set_scsi_status(struct scb *scb, uint32_t status) -{ - scb->io_ctx->result &= ~0xFFFF; - scb->io_ctx->result |= status; -} - -static __inline uint32_t ahc_get_transaction_status(struct scb *); -static __inline -uint32_t ahc_get_transaction_status(struct scb *scb) -{ - return ((scb->io_ctx->result >> 16) & CAM_STATUS_MASK); -} - -static __inline uint32_t ahc_get_scsi_status(struct scb *); -static __inline -uint32_t ahc_get_scsi_status(struct scb *scb) -{ - return (scb->io_ctx->result & 0xFFFF); -} - -static __inline void ahc_set_transaction_tag(struct scb *, int, u_int); -static __inline -void ahc_set_transaction_tag(struct scb *scb, int enabled, u_int type) -{ - /* - * Nothing to do for linux as the incoming transaction - * has no concept of tag/non tagged, etc. - */ -} - -static __inline u_long ahc_get_transfer_length(struct scb *); -static __inline -u_long ahc_get_transfer_length(struct scb *scb) -{ - return (scb->platform_data->xfer_len); -} - -static __inline int ahc_get_transfer_dir(struct scb *); -static __inline -int ahc_get_transfer_dir(struct scb *scb) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,40) - return (scb->io_ctx->sc_data_direction); -#else - if (scb->io_ctx->bufflen == 0) - return (CAM_DIR_NONE); - - switch(scb->io_ctx->cmnd[0]) { - case 0x08: /* READ(6) */ - case 0x28: /* READ(10) */ - case 0xA8: /* READ(12) */ - return (CAM_DIR_IN); - case 0x0A: /* WRITE(6) */ - case 0x2A: /* WRITE(10) */ - case 0xAA: /* WRITE(12) */ - return (CAM_DIR_OUT); - default: - return (CAM_DIR_NONE); - } -#endif -} - -static __inline void ahc_set_residual(struct scb *, u_long); -static __inline -void ahc_set_residual(struct scb *scb, u_long resid) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - scb->io_ctx->resid = resid; -#else - scb->platform_data->resid = resid; -#endif -} - -static __inline void ahc_set_sense_residual(struct scb *, u_long); -static __inline -void ahc_set_sense_residual(struct scb *scb, u_long resid) -{ - /* This can't be reported in Linux */ -} - -static __inline u_long ahc_get_residual(struct scb *); -static __inline -u_long ahc_get_residual(struct scb *scb) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - return (scb->io_ctx->resid); -#else - return (scb->platform_data->resid); -#endif -} - -static __inline int ahc_perform_autosense(struct scb *); -static __inline -int ahc_perform_autosense(struct scb *scb) -{ - /* - * We always perform autosense in Linux. - * On other platforms this is set on a - * per-transaction basis. - */ - return (1); -} - -static __inline uint32_t -ahc_get_sense_bufsize(struct ahc_softc *ahc, struct scb *scb) -{ - return (sizeof(struct scsi_sense_data)); -} - -static __inline void ahc_notify_xfer_settings_change(struct ahc_softc *, - struct ahc_devinfo *); -static __inline void -ahc_notify_xfer_settings_change(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo) -{ - /* Nothing to do here for linux */ -} - -static __inline void ahc_platform_scb_free(struct ahc_softc *ahc, - struct scb *scb); -static __inline void -ahc_platform_scb_free(struct ahc_softc *ahc, struct scb *scb) -{ - ahc->flags &= ~AHC_RESOURCE_SHORTAGE; -} - -int ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg); -void ahc_platform_free(struct ahc_softc *ahc); -void ahc_platform_freeze_devq(struct ahc_softc *ahc, struct scb *scb); -static __inline void ahc_freeze_scb(struct scb *scb); -static __inline void -ahc_freeze_scb(struct scb *scb) -{ - /* Noting to do here for linux */ -} - -void ahc_platform_set_tags(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo, ahc_queue_alg); -int ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, - char channel, int lun, u_int tag, - role_t role, uint32_t status); -void ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs); -void ahc_platform_flushwork(struct ahc_softc *ahc); -int ahc_softc_comp(struct ahc_softc *, struct ahc_softc *); -void ahc_done(struct ahc_softc*, struct scb*); -void ahc_send_async(struct ahc_softc *, char channel, - u_int target, u_int lun, ac_code, void *); -void ahc_print_path(struct ahc_softc *, struct scb *); -void ahc_platform_dump_card_state(struct ahc_softc *ahc); - -#ifdef CONFIG_PCI -#define AHC_PCI_CONFIG 1 -#else -#define AHC_PCI_CONFIG 0 -#endif -#define bootverbose aic7xxx_verbose -extern int aic7xxx_verbose; -#endif /* _AIC7XXX_LINUX_H_ */ diff --git a/xen/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/xen/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c deleted file mode 100644 index 95cc64c777..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Linux driver attachment glue for PCI based controllers. - * - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c#32 $ - */ - -#include "aic7xxx_osm.h" - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -struct pci_device_id -{ -}; -#endif - -static int ahc_linux_pci_dev_probe(struct pci_dev *pdev, - const struct pci_device_id *ent); -static int ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, - u_long *base); -#ifdef MMAPIO -static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc, - u_long *bus_addr, - uint8_t **maddr); -#endif /* MMAPIO */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -static void ahc_linux_pci_dev_remove(struct pci_dev *pdev); - -/* We do our own ID filtering. So, grab all SCSI storage class devices. */ -static struct pci_device_id ahc_linux_pci_id_table[] = { - { - 0x9004, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_STORAGE_SCSI << 8, 0xFFFF00, 0 - }, - { - 0x9005, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_STORAGE_SCSI << 8, 0xFFFF00, 0 - }, - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, ahc_linux_pci_id_table); - -struct pci_driver aic7xxx_pci_driver = { - name: "aic7xxx", - probe: ahc_linux_pci_dev_probe, - remove: ahc_linux_pci_dev_remove, - id_table: ahc_linux_pci_id_table -}; - -static void -ahc_linux_pci_dev_remove(struct pci_dev *pdev) -{ - struct ahc_softc *ahc; - u_long l; - - /* - * We should be able to just perform - * the free directly, but check our - * list for extra sanity. - */ - ahc_list_lock(&l); - ahc = ahc_find_softc((struct ahc_softc *)pdev->driver_data); - if (ahc != NULL) { - u_long s; - - ahc_lock(ahc, &s); - ahc_intr_enable(ahc, FALSE); - ahc_unlock(ahc, &s); - ahc_free(ahc); - } - ahc_list_unlock(&l); -} -#endif /* !LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) */ - -static int -ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - char buf[80]; - struct ahc_softc *ahc; - ahc_dev_softc_t pci; - struct ahc_pci_identity *entry; - char *name; - int error; - - /* - * Some BIOSen report the same device multiple times. - */ - TAILQ_FOREACH(ahc, &ahc_tailq, links) { - struct pci_dev *probed_pdev; - - probed_pdev = ahc->dev_softc; - if (probed_pdev->bus->number == pdev->bus->number - && probed_pdev->devfn == pdev->devfn) - break; - } - if (ahc != NULL) { - /* Skip duplicate. */ - return (-ENODEV); - } - - pci = pdev; - entry = ahc_find_pci_device(pci); - if (entry == NULL) - return (-ENODEV); - - /* - * Allocate a softc for this card and - * set it up for attachment by our - * common detect routine. - */ - sprintf(buf, "ahc_pci:%d:%d:%d", - ahc_get_pci_bus(pci), - ahc_get_pci_slot(pci), - ahc_get_pci_function(pci)); - name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); - if (name == NULL) - return (-ENOMEM); - strcpy(name, buf); - ahc = ahc_alloc(NULL, name); - if (ahc == NULL) - return (-ENOMEM); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - if (pci_enable_device(pdev)) { - ahc_free(ahc); - return (-ENODEV); - } - pci_set_master(pdev); - - if (sizeof(bus_addr_t) > 4 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3) - && ahc_linux_get_memsize() > 0x80000000 - && pci_set_dma_mask(pdev, 0x7FFFFFFFFFULL) == 0) { -#else - && ahc_linux_get_memsize() > 0x80000000) { - - ahc->dev_softc->dma_mask = - (bus_addr_t)(0x7FFFFFFFFFULL & (bus_addr_t)~0); -#endif - ahc->flags |= AHC_39BIT_ADDRESSING; - ahc->platform_data->hw_dma_mask = - (bus_addr_t)(0x7FFFFFFFFFULL & (bus_addr_t)~0); - } -#endif - ahc->dev_softc = pci; - error = ahc_pci_config(ahc, entry); - if (error != 0) { - ahc_free(ahc); - return (-error); - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pci_set_drvdata(pdev, ahc); - if (aic7xxx_detect_complete) - ahc_linux_register_host(ahc, aic7xxx_driver_template); -#endif - return (0); -} - -int -ahc_linux_pci_probe(Scsi_Host_Template *template) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - return (pci_module_init(&aic7xxx_pci_driver)); -#else - struct pci_dev *pdev; - u_int class; - int found; - - /* If we don't have a PCI bus, we can't find any adapters. */ - if (pci_present() == 0) - return (0); - - found = 0; - pdev = NULL; - class = PCI_CLASS_STORAGE_SCSI << 8; - while ((pdev = pci_find_class(class, pdev)) != NULL) { - ahc_dev_softc_t pci; - int error; - - pci = pdev; - error = ahc_linux_pci_dev_probe(pdev, /*pci_devid*/NULL); - if (error == 0) - found++; - } - return (found); -#endif -} - -static int -ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, u_long *base) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - *base = pci_resource_start(ahc->dev_softc, 0); -#else - *base = ahc_pci_read_config(ahc->dev_softc, PCIR_MAPS, 4); - *base &= PCI_BASE_ADDRESS_IO_MASK; -#endif - if (*base == 0) - return (ENOMEM); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - if (check_region(*base, 256) != 0) - return (ENOMEM); - else - request_region(*base, 256, "aic7xxx"); -#else - if (request_region(*base, 256, "aic7xxx") == 0) - return (ENOMEM); -#endif - return (0); -} - -#ifdef MMAPIO -static int -ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc, - u_long *bus_addr, - uint8_t **maddr) -{ - u_long start; - u_long base_page; - u_long base_offset; - int error; - - error = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - start = pci_resource_start(ahc->dev_softc, 1); - base_page = start & PAGE_MASK; - base_offset = start - base_page; -#else - start = ahc_pci_read_config(ahc->dev_softc, PCIR_MAPS+4, 4); - base_offset = start & PCI_BASE_ADDRESS_MEM_MASK; - base_page = base_offset & PAGE_MASK; - base_offset -= base_page; -#endif - if (start != 0) { - *bus_addr = start; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - if (request_mem_region(start, 0x1000, "aic7xxx") == 0) - error = ENOMEM; -#endif - if (error == 0) { - *maddr = ioremap_nocache(base_page, base_offset + 256); - if (*maddr == NULL) { - error = ENOMEM; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - release_mem_region(start, 0x1000); -#endif - } else - *maddr += base_offset; - } - } else - error = ENOMEM; - return (error); -} -#endif /* MMAPIO */ - -int -ahc_pci_map_registers(struct ahc_softc *ahc) -{ - uint32_t command; - u_long base; - uint8_t *maddr; - int error; - - /* - * If its allowed, we prefer memory mapped access. - */ - command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, 4); - command &= ~(PCIM_CMD_PORTEN|PCIM_CMD_MEMEN); - base = 0; - maddr = NULL; -#ifdef MMAPIO - error = ahc_linux_pci_reserve_mem_region(ahc, &base, &maddr); - if (error == 0) { - ahc->platform_data->mem_busaddr = base; - ahc->tag = BUS_SPACE_MEMIO; - ahc->bsh.maddr = maddr; - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, - command | PCIM_CMD_MEMEN, 4); - - /* - * Do a quick test to see if memory mapped - * I/O is functioning correctly. - */ - if (ahc_inb(ahc, HCNTRL) == 0xFF) { - - printf("aic7xxx: PCI Device %d:%d:%d " - "failed memory mapped test\n", - ahc_get_pci_bus(ahc->dev_softc), - ahc_get_pci_slot(ahc->dev_softc), - ahc_get_pci_function(ahc->dev_softc)); - iounmap((void *)((u_long)maddr & PAGE_MASK)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - release_mem_region(ahc->platform_data->mem_busaddr, - 0x1000); -#endif - ahc->bsh.maddr = NULL; - maddr = NULL; - } else - command |= PCIM_CMD_MEMEN; - } else { - printf("aic7xxx: PCI%d:%d:%d MEM region 0x%lx " - "unavailable. Cannot memory map device.\n", - ahc_get_pci_bus(ahc->dev_softc), - ahc_get_pci_slot(ahc->dev_softc), - ahc_get_pci_function(ahc->dev_softc), - base); - } -#endif /* MMAPIO */ - - /* - * We always prefer memory mapped access. - */ - if (maddr == NULL) { - - error = ahc_linux_pci_reserve_io_region(ahc, &base); - if (error == 0) { - ahc->tag = BUS_SPACE_PIO; - ahc->bsh.ioport = base; - command |= PCIM_CMD_PORTEN; - } else { - printf("aic7xxx: PCI%d:%d:%d IO region 0x%lx[0..255] " - "unavailable. Cannot map device.\n", - ahc_get_pci_bus(ahc->dev_softc), - ahc_get_pci_slot(ahc->dev_softc), - ahc_get_pci_function(ahc->dev_softc), - base); - } - } - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, 4); - return (error); -} - -int -ahc_pci_map_int(struct ahc_softc *ahc) -{ - int error; - - error = request_irq(ahc->dev_softc->irq, ahc_linux_isr, - SA_SHIRQ, "aic7xxx", ahc); - if (error == 0) - ahc->platform_data->irq = ahc->dev_softc->irq; - - return (-error); -} - -void -ahc_power_state_change(struct ahc_softc *ahc, ahc_power_state new_state) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pci_set_power_state(ahc->dev_softc, new_state); -#else - uint32_t cap; - u_int cap_offset; - - /* - * Traverse the capability list looking for - * the power management capability. - */ - cap = 0; - cap_offset = ahc_pci_read_config(ahc->dev_softc, - PCIR_CAP_PTR, /*bytes*/1); - while (cap_offset != 0) { - - cap = ahc_pci_read_config(ahc->dev_softc, - cap_offset, /*bytes*/4); - if ((cap & 0xFF) == 1 - && ((cap >> 16) & 0x3) > 0) { - uint32_t pm_control; - - pm_control = ahc_pci_read_config(ahc->dev_softc, - cap_offset + 4, - /*bytes*/4); - pm_control &= ~0x3; - pm_control |= new_state; - ahc_pci_write_config(ahc->dev_softc, - cap_offset + 4, - pm_control, /*bytes*/2); - break; - } - cap_offset = (cap >> 8) & 0xFF; - } -#endif -} diff --git a/xen/drivers/scsi/aic7xxx/aic7xxx_pci.c b/xen/drivers/scsi/aic7xxx/aic7xxx_pci.c deleted file mode 100644 index 6108b4f709..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic7xxx_pci.c +++ /dev/null @@ -1,2277 +0,0 @@ -/* - * Product specific probe and attach routines for: - * 3940, 2940, aic7895, aic7890, aic7880, - * aic7870, aic7860 and aic7850 SCSI controllers - * - * Copyright (c) 1994-2001 Justin T. Gibbs. - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#46 $ - * - * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx_pci.c,v 1.2.2.14 2002/04/29 19:36:31 gibbs Exp $ - */ - -#ifdef __linux__ -#include "aic7xxx_osm.h" -#include "aic7xxx_inline.h" -#include "aic7xxx_93cx6.h" -#else -#include -#include -#include -#endif - -#define AHC_PCI_IOADDR PCIR_MAPS /* I/O Address */ -#define AHC_PCI_MEMADDR (PCIR_MAPS + 4) /* Mem I/O Address */ - -static __inline uint64_t -ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) -{ - uint64_t id; - - id = subvendor - | (subdevice << 16) - | ((uint64_t)vendor << 32) - | ((uint64_t)device << 48); - - return (id); -} - -#define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull -#define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull -#define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull -#define ID_9005_SISL_MASK 0x000FFFFF00000000ull -#define ID_9005_SISL_ID 0x0005900500000000ull -#define ID_AIC7850 0x5078900400000000ull -#define ID_AHA_2902_04_10_15_20_30C 0x5078900478509004ull -#define ID_AIC7855 0x5578900400000000ull -#define ID_AIC7859 0x3860900400000000ull -#define ID_AHA_2930CU 0x3860900438699004ull -#define ID_AIC7860 0x6078900400000000ull -#define ID_AIC7860C 0x6078900478609004ull -#define ID_AHA_1480A 0x6075900400000000ull -#define ID_AHA_2940AU_0 0x6178900400000000ull -#define ID_AHA_2940AU_1 0x6178900478619004ull -#define ID_AHA_2940AU_CN 0x2178900478219004ull -#define ID_AHA_2930C_VAR 0x6038900438689004ull - -#define ID_AIC7870 0x7078900400000000ull -#define ID_AHA_2940 0x7178900400000000ull -#define ID_AHA_3940 0x7278900400000000ull -#define ID_AHA_398X 0x7378900400000000ull -#define ID_AHA_2944 0x7478900400000000ull -#define ID_AHA_3944 0x7578900400000000ull -#define ID_AHA_4944 0x7678900400000000ull - -#define ID_AIC7880 0x8078900400000000ull -#define ID_AIC7880_B 0x8078900478809004ull -#define ID_AHA_2940U 0x8178900400000000ull -#define ID_AHA_3940U 0x8278900400000000ull -#define ID_AHA_2944U 0x8478900400000000ull -#define ID_AHA_3944U 0x8578900400000000ull -#define ID_AHA_398XU 0x8378900400000000ull -#define ID_AHA_4944U 0x8678900400000000ull -#define ID_AHA_2940UB 0x8178900478819004ull -#define ID_AHA_2930U 0x8878900478889004ull -#define ID_AHA_2940U_PRO 0x8778900478879004ull -#define ID_AHA_2940U_CN 0x0078900478009004ull - -#define ID_AIC7895 0x7895900478959004ull -#define ID_AIC7895_ARO 0x7890900478939004ull -#define ID_AIC7895_ARO_MASK 0xFFF0FFFFFFFFFFFFull -#define ID_AHA_2940U_DUAL 0x7895900478919004ull -#define ID_AHA_3940AU 0x7895900478929004ull -#define ID_AHA_3944AU 0x7895900478949004ull - -#define ID_AIC7890 0x001F9005000F9005ull -#define ID_AIC7890_ARO 0x00139005000F9005ull -#define ID_AAA_131U2 0x0013900500039005ull -#define ID_AHA_2930U2 0x0011900501819005ull -#define ID_AHA_2940U2B 0x00109005A1009005ull -#define ID_AHA_2940U2_OEM 0x0010900521809005ull -#define ID_AHA_2940U2 0x00109005A1809005ull -#define ID_AHA_2950U2B 0x00109005E1009005ull - -#define ID_AIC7892 0x008F9005FFFF9005ull -#define ID_AIC7892_ARO 0x00839005FFFF9005ull -#define ID_AHA_29160 0x00809005E2A09005ull -#define ID_AHA_29160_CPQ 0x00809005E2A00E11ull -#define ID_AHA_29160N 0x0080900562A09005ull -#define ID_AHA_29160C 0x0080900562209005ull -#define ID_AHA_29160B 0x00809005E2209005ull -#define ID_AHA_19160B 0x0081900562A19005ull - -#define ID_AIC7896 0x005F9005FFFF9005ull -#define ID_AIC7896_ARO 0x00539005FFFF9005ull -#define ID_AHA_3950U2B_0 0x00509005FFFF9005ull -#define ID_AHA_3950U2B_1 0x00509005F5009005ull -#define ID_AHA_3950U2D_0 0x00519005FFFF9005ull -#define ID_AHA_3950U2D_1 0x00519005B5009005ull - -#define ID_AIC7899 0x00CF9005FFFF9005ull -#define ID_AIC7899_ARO 0x00C39005FFFF9005ull -#define ID_AHA_3960D 0x00C09005F6209005ull -#define ID_AHA_3960D_CPQ 0x00C09005F6200E11ull - -#define ID_AIC7810 0x1078900400000000ull -#define ID_AIC7815 0x7815900400000000ull - -#define DEVID_9005_TYPE(id) ((id) & 0xF) -#define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */ -#define DEVID_9005_TYPE_AAA 0x3 /* RAID Card */ -#define DEVID_9005_TYPE_SISL 0x5 /* Container ROMB */ -#define DEVID_9005_TYPE_MB 0xF /* On Motherboard */ - -#define DEVID_9005_MAXRATE(id) (((id) & 0x30) >> 4) -#define DEVID_9005_MAXRATE_U160 0x0 -#define DEVID_9005_MAXRATE_ULTRA2 0x1 -#define DEVID_9005_MAXRATE_ULTRA 0x2 -#define DEVID_9005_MAXRATE_FAST 0x3 - -#define DEVID_9005_MFUNC(id) (((id) & 0x40) >> 6) - -#define DEVID_9005_CLASS(id) (((id) & 0xFF00) >> 8) -#define DEVID_9005_CLASS_SPI 0x0 /* Parallel SCSI */ - -#define SUBID_9005_TYPE(id) ((id) & 0xF) -#define SUBID_9005_TYPE_MB 0xF /* On Motherboard */ -#define SUBID_9005_TYPE_CARD 0x0 /* Standard Card */ -#define SUBID_9005_TYPE_LCCARD 0x1 /* Low Cost Card */ -#define SUBID_9005_TYPE_RAID 0x3 /* Combined with Raid */ - -#define SUBID_9005_TYPE_KNOWN(id) \ - ((((id) & 0xF) == SUBID_9005_TYPE_MB) \ - || (((id) & 0xF) == SUBID_9005_TYPE_CARD) \ - || (((id) & 0xF) == SUBID_9005_TYPE_LCCARD) \ - || (((id) & 0xF) == SUBID_9005_TYPE_RAID)) - -#define SUBID_9005_MAXRATE(id) (((id) & 0x30) >> 4) -#define SUBID_9005_MAXRATE_ULTRA2 0x0 -#define SUBID_9005_MAXRATE_ULTRA 0x1 -#define SUBID_9005_MAXRATE_U160 0x2 -#define SUBID_9005_MAXRATE_RESERVED 0x3 - -#define SUBID_9005_SEEPTYPE(id) \ - ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ - ? ((id) & 0xC0) >> 6 \ - : ((id) & 0x300) >> 8) -#define SUBID_9005_SEEPTYPE_NONE 0x0 -#define SUBID_9005_SEEPTYPE_1K 0x1 -#define SUBID_9005_SEEPTYPE_2K_4K 0x2 -#define SUBID_9005_SEEPTYPE_RESERVED 0x3 -#define SUBID_9005_AUTOTERM(id) \ - ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ - ? (((id) & 0x400) >> 10) == 0 \ - : (((id) & 0x40) >> 6) == 0) - -#define SUBID_9005_NUMCHAN(id) \ - ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ - ? ((id) & 0x300) >> 8 \ - : ((id) & 0xC00) >> 10) - -#define SUBID_9005_LEGACYCONN(id) \ - ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ - ? 0 \ - : ((id) & 0x80) >> 7) - -#define SUBID_9005_MFUNCENB(id) \ - ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ - ? ((id) & 0x800) >> 11 \ - : ((id) & 0x1000) >> 12) -/* - * Informational only. Should use chip register to be - * certain, but may be use in identification strings. - */ -#define SUBID_9005_CARD_SCSIWIDTH_MASK 0x2000 -#define SUBID_9005_CARD_PCIWIDTH_MASK 0x4000 -#define SUBID_9005_CARD_SEDIFF_MASK 0x8000 - -static ahc_device_setup_t ahc_aic785X_setup; -static ahc_device_setup_t ahc_aic7860_setup; -static ahc_device_setup_t ahc_apa1480_setup; -static ahc_device_setup_t ahc_aic7870_setup; -static ahc_device_setup_t ahc_aha394X_setup; -static ahc_device_setup_t ahc_aha494X_setup; -static ahc_device_setup_t ahc_aha398X_setup; -static ahc_device_setup_t ahc_aic7880_setup; -static ahc_device_setup_t ahc_aha2940Pro_setup; -static ahc_device_setup_t ahc_aha394XU_setup; -static ahc_device_setup_t ahc_aha398XU_setup; -static ahc_device_setup_t ahc_aic7890_setup; -static ahc_device_setup_t ahc_aic7892_setup; -static ahc_device_setup_t ahc_aic7895_setup; -static ahc_device_setup_t ahc_aic7896_setup; -static ahc_device_setup_t ahc_aic7899_setup; -static ahc_device_setup_t ahc_aha29160C_setup; -static ahc_device_setup_t ahc_raid_setup; -static ahc_device_setup_t ahc_aha394XX_setup; -static ahc_device_setup_t ahc_aha494XX_setup; -static ahc_device_setup_t ahc_aha398XX_setup; - -struct ahc_pci_identity ahc_pci_ident_table [] = -{ - /* aic7850 based controllers */ - { - ID_AHA_2902_04_10_15_20_30C, - ID_ALL_MASK, - "Adaptec 2902/04/10/15/20/30C SCSI adapter", - ahc_aic785X_setup - }, - /* aic7860 based controllers */ - { - ID_AHA_2930CU, - ID_ALL_MASK, - "Adaptec 2930CU SCSI adapter", - ahc_aic7860_setup - }, - { - ID_AHA_1480A & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec 1480A Ultra SCSI adapter", - ahc_apa1480_setup - }, - { - ID_AHA_2940AU_0 & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec 2940A Ultra SCSI adapter", - ahc_aic7860_setup - }, - { - ID_AHA_2940AU_CN & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec 2940A/CN Ultra SCSI adapter", - ahc_aic7860_setup - }, - { - ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec 2930C Ultra SCSI adapter (VAR)", - ahc_aic7860_setup - }, - /* aic7870 based controllers */ - { - ID_AHA_2940, - ID_ALL_MASK, - "Adaptec 2940 SCSI adapter", - ahc_aic7870_setup - }, - { - ID_AHA_3940, - ID_ALL_MASK, - "Adaptec 3940 SCSI adapter", - ahc_aha394X_setup - }, - { - ID_AHA_398X, - ID_ALL_MASK, - "Adaptec 398X SCSI RAID adapter", - ahc_aha398X_setup - }, - { - ID_AHA_2944, - ID_ALL_MASK, - "Adaptec 2944 SCSI adapter", - ahc_aic7870_setup - }, - { - ID_AHA_3944, - ID_ALL_MASK, - "Adaptec 3944 SCSI adapter", - ahc_aha394X_setup - }, - { - ID_AHA_4944, - ID_ALL_MASK, - "Adaptec 4944 SCSI adapter", - ahc_aha494X_setup - }, - /* aic7880 based controllers */ - { - ID_AHA_2940U & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec 2940 Ultra SCSI adapter", - ahc_aic7880_setup - }, - { - ID_AHA_3940U & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec 3940 Ultra SCSI adapter", - ahc_aha394XU_setup - }, - { - ID_AHA_2944U & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec 2944 Ultra SCSI adapter", - ahc_aic7880_setup - }, - { - ID_AHA_3944U & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec 3944 Ultra SCSI adapter", - ahc_aha394XU_setup - }, - { - ID_AHA_398XU & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec 398X Ultra SCSI RAID adapter", - ahc_aha398XU_setup - }, - { - /* - * XXX Don't know the slot numbers - * so we can't identify channels - */ - ID_AHA_4944U & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec 4944 Ultra SCSI adapter", - ahc_aic7880_setup - }, - { - ID_AHA_2930U & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec 2930 Ultra SCSI adapter", - ahc_aic7880_setup - }, - { - ID_AHA_2940U_PRO & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec 2940 Pro Ultra SCSI adapter", - ahc_aha2940Pro_setup - }, - { - ID_AHA_2940U_CN & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec 2940/CN Ultra SCSI adapter", - ahc_aic7880_setup - }, - /* Ignore all SISL (AAC on MB) based controllers. */ - { - ID_9005_SISL_ID, - ID_9005_SISL_MASK, - NULL, - NULL - }, - /* aic7890 based controllers */ - { - ID_AHA_2930U2, - ID_ALL_MASK, - "Adaptec 2930 Ultra2 SCSI adapter", - ahc_aic7890_setup - }, - { - ID_AHA_2940U2B, - ID_ALL_MASK, - "Adaptec 2940B Ultra2 SCSI adapter", - ahc_aic7890_setup - }, - { - ID_AHA_2940U2_OEM, - ID_ALL_MASK, - "Adaptec 2940 Ultra2 SCSI adapter (OEM)", - ahc_aic7890_setup - }, - { - ID_AHA_2940U2, - ID_ALL_MASK, - "Adaptec 2940 Ultra2 SCSI adapter", - ahc_aic7890_setup - }, - { - ID_AHA_2950U2B, - ID_ALL_MASK, - "Adaptec 2950 Ultra2 SCSI adapter", - ahc_aic7890_setup - }, - { - ID_AIC7890_ARO, - ID_ALL_MASK, - "Adaptec aic7890/91 Ultra2 SCSI adapter (ARO)", - ahc_aic7890_setup - }, - { - ID_AAA_131U2, - ID_ALL_MASK, - "Adaptec AAA-131 Ultra2 RAID adapter", - ahc_aic7890_setup - }, - /* aic7892 based controllers */ - { - ID_AHA_29160, - ID_ALL_MASK, - "Adaptec 29160 Ultra160 SCSI adapter", - ahc_aic7892_setup - }, - { - ID_AHA_29160_CPQ, - ID_ALL_MASK, - "Adaptec (Compaq OEM) 29160 Ultra160 SCSI adapter", - ahc_aic7892_setup - }, - { - ID_AHA_29160N, - ID_ALL_MASK, - "Adaptec 29160N Ultra160 SCSI adapter", - ahc_aic7892_setup - }, - { - ID_AHA_29160C, - ID_ALL_MASK, - "Adaptec 29160C Ultra160 SCSI adapter", - ahc_aha29160C_setup - }, - { - ID_AHA_29160B, - ID_ALL_MASK, - "Adaptec 29160B Ultra160 SCSI adapter", - ahc_aic7892_setup - }, - { - ID_AHA_19160B, - ID_ALL_MASK, - "Adaptec 19160B Ultra160 SCSI adapter", - ahc_aic7892_setup - }, - { - ID_AIC7892_ARO, - ID_ALL_MASK, - "Adaptec aic7892 Ultra160 SCSI adapter (ARO)", - ahc_aic7892_setup - }, - /* aic7895 based controllers */ - { - ID_AHA_2940U_DUAL, - ID_ALL_MASK, - "Adaptec 2940/DUAL Ultra SCSI adapter", - ahc_aic7895_setup - }, - { - ID_AHA_3940AU, - ID_ALL_MASK, - "Adaptec 3940A Ultra SCSI adapter", - ahc_aic7895_setup - }, - { - ID_AHA_3944AU, - ID_ALL_MASK, - "Adaptec 3944A Ultra SCSI adapter", - ahc_aic7895_setup - }, - { - ID_AIC7895_ARO, - ID_AIC7895_ARO_MASK, - "Adaptec aic7895 Ultra SCSI adapter (ARO)", - ahc_aic7895_setup - }, - /* aic7896/97 based controllers */ - { - ID_AHA_3950U2B_0, - ID_ALL_MASK, - "Adaptec 3950B Ultra2 SCSI adapter", - ahc_aic7896_setup - }, - { - ID_AHA_3950U2B_1, - ID_ALL_MASK, - "Adaptec 3950B Ultra2 SCSI adapter", - ahc_aic7896_setup - }, - { - ID_AHA_3950U2D_0, - ID_ALL_MASK, - "Adaptec 3950D Ultra2 SCSI adapter", - ahc_aic7896_setup - }, - { - ID_AHA_3950U2D_1, - ID_ALL_MASK, - "Adaptec 3950D Ultra2 SCSI adapter", - ahc_aic7896_setup - }, - { - ID_AIC7896_ARO, - ID_ALL_MASK, - "Adaptec aic7896/97 Ultra2 SCSI adapter (ARO)", - ahc_aic7896_setup - }, - /* aic7899 based controllers */ - { - ID_AHA_3960D, - ID_ALL_MASK, - "Adaptec 3960D Ultra160 SCSI adapter", - ahc_aic7899_setup - }, - { - ID_AHA_3960D_CPQ, - ID_ALL_MASK, - "Adaptec (Compaq OEM) 3960D Ultra160 SCSI adapter", - ahc_aic7899_setup - }, - { - ID_AIC7899_ARO, - ID_ALL_MASK, - "Adaptec aic7899 Ultra160 SCSI adapter (ARO)", - ahc_aic7899_setup - }, - /* Generic chip probes for devices we don't know 'exactly' */ - { - ID_AIC7850 & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec aic7850 SCSI adapter", - ahc_aic785X_setup - }, - { - ID_AIC7855 & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec aic7855 SCSI adapter", - ahc_aic785X_setup - }, - { - ID_AIC7859 & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec aic7859 SCSI adapter", - ahc_aic7860_setup - }, - { - ID_AIC7860 & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec aic7860 Ultra SCSI adapter", - ahc_aic7860_setup - }, - { - ID_AIC7870 & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec aic7870 SCSI adapter", - ahc_aic7870_setup - }, - { - ID_AIC7880 & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec aic7880 Ultra SCSI adapter", - ahc_aic7880_setup - }, - { - ID_AIC7890 & ID_9005_GENERIC_MASK, - ID_9005_GENERIC_MASK, - "Adaptec aic7890/91 Ultra2 SCSI adapter", - ahc_aic7890_setup - }, - { - ID_AIC7892 & ID_9005_GENERIC_MASK, - ID_9005_GENERIC_MASK, - "Adaptec aic7892 Ultra160 SCSI adapter", - ahc_aic7892_setup - }, - { - ID_AIC7895 & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec aic7895 Ultra SCSI adapter", - ahc_aic7895_setup - }, - { - ID_AIC7896 & ID_9005_GENERIC_MASK, - ID_9005_GENERIC_MASK, - "Adaptec aic7896/97 Ultra2 SCSI adapter", - ahc_aic7896_setup - }, - { - ID_AIC7899 & ID_9005_GENERIC_MASK, - ID_9005_GENERIC_MASK, - "Adaptec aic7899 Ultra160 SCSI adapter", - ahc_aic7899_setup - }, - { - ID_AIC7810 & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec aic7810 RAID memory controller", - ahc_raid_setup - }, - { - ID_AIC7815 & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, - "Adaptec aic7815 RAID memory controller", - ahc_raid_setup - } -}; - -const u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table); - -#define AHC_394X_SLOT_CHANNEL_A 4 -#define AHC_394X_SLOT_CHANNEL_B 5 - -#define AHC_398X_SLOT_CHANNEL_A 4 -#define AHC_398X_SLOT_CHANNEL_B 8 -#define AHC_398X_SLOT_CHANNEL_C 12 - -#define AHC_494X_SLOT_CHANNEL_A 4 -#define AHC_494X_SLOT_CHANNEL_B 5 -#define AHC_494X_SLOT_CHANNEL_C 6 -#define AHC_494X_SLOT_CHANNEL_D 7 - -#define DEVCONFIG 0x40 -#define SCBSIZE32 0x00010000ul /* aic789X only */ -#define REXTVALID 0x00001000ul /* ultra cards only */ -#define MPORTMODE 0x00000400ul /* aic7870+ only */ -#define RAMPSM 0x00000200ul /* aic7870+ only */ -#define VOLSENSE 0x00000100ul -#define PCI64BIT 0x00000080ul /* 64Bit PCI bus (Ultra2 Only)*/ -#define SCBRAMSEL 0x00000080ul -#define MRDCEN 0x00000040ul -#define EXTSCBTIME 0x00000020ul /* aic7870 only */ -#define EXTSCBPEN 0x00000010ul /* aic7870 only */ -#define BERREN 0x00000008ul -#define DACEN 0x00000004ul -#define STPWLEVEL 0x00000002ul -#define DIFACTNEGEN 0x00000001ul /* aic7870 only */ - -#define CSIZE_LATTIME 0x0c -#define CACHESIZE 0x0000003ful /* only 5 bits */ -#define LATTIME 0x0000ff00ul - -static int ahc_9005_subdevinfo_valid(uint16_t vendor, uint16_t device, - uint16_t subvendor, uint16_t subdevice); -static int ahc_ext_scbram_present(struct ahc_softc *ahc); -static void ahc_scbram_config(struct ahc_softc *ahc, int enable, - int pcheck, int fast, int large); -static void ahc_probe_ext_scbram(struct ahc_softc *ahc); -static void check_extport(struct ahc_softc *ahc, u_int *sxfrctl1); -static void ahc_parse_pci_eeprom(struct ahc_softc *ahc, - struct seeprom_config *sc); -static void configure_termination(struct ahc_softc *ahc, - struct seeprom_descriptor *sd, - u_int adapter_control, - u_int *sxfrctl1); - -static void ahc_new_term_detect(struct ahc_softc *ahc, - int *enableSEC_low, - int *enableSEC_high, - int *enablePRI_low, - int *enablePRI_high, - int *eeprom_present); -static void aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present, - int *internal68_present, - int *externalcable_present, - int *eeprom_present); -static void aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present, - int *externalcable_present, - int *eeprom_present); -static void write_brdctl(struct ahc_softc *ahc, uint8_t value); -static uint8_t read_brdctl(struct ahc_softc *ahc); - -static int -ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor, - uint16_t subdevice, uint16_t subvendor) -{ - int result; - - /* Default to invalid. */ - result = 0; - if (vendor == 0x9005 - && subvendor == 0x9005 - && subdevice != device - && SUBID_9005_TYPE_KNOWN(subdevice) != 0) { - - switch (SUBID_9005_TYPE(subdevice)) { - case SUBID_9005_TYPE_MB: - break; - case SUBID_9005_TYPE_CARD: - case SUBID_9005_TYPE_LCCARD: - /* - * Currently only trust Adaptec cards to - * get the sub device info correct. - */ - if (DEVID_9005_TYPE(device) == DEVID_9005_TYPE_HBA) - result = 1; - break; - case SUBID_9005_TYPE_RAID: - break; - default: - break; - } - } - return (result); -} - -struct ahc_pci_identity * -ahc_find_pci_device(ahc_dev_softc_t pci) -{ - uint64_t full_id; - uint16_t device; - uint16_t vendor; - uint16_t subdevice; - uint16_t subvendor; - struct ahc_pci_identity *entry; - u_int i; - - vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); - device = ahc_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); - subvendor = ahc_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); - subdevice = ahc_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); - full_id = ahc_compose_id(device, - vendor, - subdevice, - subvendor); - - /* - * If the second function is not hooked up, ignore it. - * Unfortunately, not all MB vendors implement the - * subdevice ID as per the Adaptec spec, so do our best - * to sanity check it prior to accepting the subdevice - * ID as valid. - */ - if (ahc_get_pci_function(pci) > 0 - && ahc_9005_subdevinfo_valid(vendor, device, subvendor, subdevice) - && SUBID_9005_MFUNCENB(subdevice) == 0) - return (NULL); - - for (i = 0; i < ahc_num_pci_devs; i++) { - entry = &ahc_pci_ident_table[i]; - if (entry->full_id == (full_id & entry->id_mask)) { - /* Honor exclusion entries. */ - if (entry->name == NULL) - return (NULL); - return (entry); - } - } - return (NULL); -} - -int -ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) -{ - struct scb_data *shared_scb_data; - u_long l; - u_long s; - u_int command; - u_int our_id = 0; - u_int sxfrctl1; - u_int scsiseq; - u_int dscommand0; - int error; - uint8_t sblkctl; - - shared_scb_data = NULL; - error = entry->setup(ahc); - if (error != 0) - return (error); - ahc->chip |= AHC_PCI; - ahc->description = entry->name; - - ahc_power_state_change(ahc, AHC_POWER_STATE_D0); - - error = ahc_pci_map_registers(ahc); - if (error != 0) - return (error); - - /* - * Before we continue probing the card, ensure that - * its interrupts are *disabled*. We don't want - * a misstep to hang the machine in an interrupt - * storm. - */ - ahc_intr_enable(ahc, FALSE); - - /* - * If we need to support high memory, enable dual - * address cycles. This bit must be set to enable - * high address bit generation even if we are on a - * 64bit bus (PCI64BIT set in devconfig). - */ - if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { - uint32_t devconfig; - - if (bootverbose) - printf("%s: Enabling 39Bit Addressing\n", - ahc_name(ahc)); - devconfig = ahc_pci_read_config(ahc->dev_softc, - DEVCONFIG, /*bytes*/4); - devconfig |= DACEN; - ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, - devconfig, /*bytes*/4); - } - - /* Ensure busmastering is enabled */ - command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); - command |= PCIM_CMD_BUSMASTEREN; - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/1); - - /* On all PCI adapters, we allow SCB paging */ - ahc->flags |= AHC_PAGESCBS; - - error = ahc_softc_init(ahc); - if (error != 0) - return (error); - - ahc->bus_intr = ahc_pci_intr; - - /* Remeber how the card was setup in case there is no SEEPROM */ - if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) { - ahc_pause(ahc); - if ((ahc->features & AHC_ULTRA2) != 0) - our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID; - else - our_id = ahc_inb(ahc, SCSIID) & OID; - sxfrctl1 = ahc_inb(ahc, SXFRCTL1) & STPWEN; - scsiseq = ahc_inb(ahc, SCSISEQ); - } else { - sxfrctl1 = STPWEN; - our_id = 7; - scsiseq = 0; - } - - error = ahc_reset(ahc); - if (error != 0) - return (ENXIO); - - if ((ahc->features & AHC_DT) != 0) { - u_int sfunct; - - /* Perform ALT-Mode Setup */ - sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; - ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); - ahc_outb(ahc, OPTIONMODE, - OPTIONMODE_DEFAULTS|AUTOACKEN|BUSFREEREV|EXPPHASEDIS); - ahc_outb(ahc, SFUNCT, sfunct); - - /* Normal mode setup */ - ahc_outb(ahc, CRCCONTROL1, CRCVALCHKEN|CRCENDCHKEN|CRCREQCHKEN - |TARGCRCENDEN); - } - - dscommand0 = ahc_inb(ahc, DSCOMMAND0); - dscommand0 |= MPARCKEN|CACHETHEN; - if ((ahc->features & AHC_ULTRA2) != 0) { - - /* - * DPARCKEN doesn't work correctly on - * some MBs so don't use it. - */ - dscommand0 &= ~DPARCKEN; - } - - /* - * Handle chips that must have cache line - * streaming (dis/en)abled. - */ - if ((ahc->bugs & AHC_CACHETHEN_DIS_BUG) != 0) - dscommand0 |= CACHETHEN; - - if ((ahc->bugs & AHC_CACHETHEN_BUG) != 0) - dscommand0 &= ~CACHETHEN; - - ahc_outb(ahc, DSCOMMAND0, dscommand0); - - ahc->pci_cachesize = - ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, - /*bytes*/1) & CACHESIZE; - ahc->pci_cachesize *= 4; - - if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0 - && ahc->pci_cachesize == 4) { - - ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, - 0, /*bytes*/1); - ahc->pci_cachesize = 0; - } - - /* - * We cannot perform ULTRA speeds without the presense - * of the external precision resistor. - */ - if ((ahc->features & AHC_ULTRA) != 0) { - uint32_t devconfig; - - devconfig = ahc_pci_read_config(ahc->dev_softc, - DEVCONFIG, /*bytes*/4); - if ((devconfig & REXTVALID) == 0) - ahc->features &= ~AHC_ULTRA; - } - - /* See if we have a SEEPROM and perform auto-term */ - check_extport(ahc, &sxfrctl1); - - /* - * Take the LED out of diagnostic mode - */ - sblkctl = ahc_inb(ahc, SBLKCTL); - ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON))); - - if ((ahc->features & AHC_ULTRA2) != 0) { - ahc_outb(ahc, DFF_THRSH, RD_DFTHRSH_MAX|WR_DFTHRSH_MAX); - } else { - ahc_outb(ahc, DSPCISTATUS, DFTHRSH_100); - } - - if (ahc->flags & AHC_USEDEFAULTS) { - /* - * PCI Adapter default setup - * Should only be used if the adapter does not have - * a SEEPROM. - */ - /* See if someone else set us up already */ - if (scsiseq != 0) { - printf("%s: Using left over BIOS settings\n", - ahc_name(ahc)); - ahc->flags &= ~AHC_USEDEFAULTS; - ahc->flags |= AHC_BIOS_ENABLED; - } else { - /* - * Assume only one connector and always turn - * on termination. - */ - our_id = 0x07; - sxfrctl1 = STPWEN; - } - ahc_outb(ahc, SCSICONF, our_id|ENSPCHK|RESET_SCSI); - - ahc->our_id = our_id; - } - - /* - * Take a look to see if we have external SRAM. - * We currently do not attempt to use SRAM that is - * shared among multiple controllers. - */ - ahc_probe_ext_scbram(ahc); - - /* - * Record our termination setting for the - * generic initialization routine. - */ - if ((sxfrctl1 & STPWEN) != 0) - ahc->flags |= AHC_TERM_ENB_A; - - /* Core initialization */ - error = ahc_init(ahc); - if (error != 0) - return (error); - - /* - * Allow interrupts now that we are completely setup. - */ - error = ahc_pci_map_int(ahc); - if (error != 0) - return (error); - - ahc_list_lock(&l); - /* - * Link this softc in with all other ahc instances. - */ - ahc_softc_insert(ahc); - - ahc_lock(ahc, &s); - ahc_intr_enable(ahc, TRUE); - ahc_unlock(ahc, &s); - - ahc_list_unlock(&l); - return (0); -} - -/* - * Test for the presense of external sram in an - * "unshared" configuration. - */ -static int -ahc_ext_scbram_present(struct ahc_softc *ahc) -{ - u_int chip; - int ramps; - int single_user; - uint32_t devconfig; - - chip = ahc->chip & AHC_CHIPID_MASK; - devconfig = ahc_pci_read_config(ahc->dev_softc, - DEVCONFIG, /*bytes*/4); - single_user = (devconfig & MPORTMODE) != 0; - - if ((ahc->features & AHC_ULTRA2) != 0) - ramps = (ahc_inb(ahc, DSCOMMAND0) & RAMPS) != 0; - else if (chip == AHC_AIC7895 || chip == AHC_AIC7895C) - /* - * External SCBRAM arbitration is flakey - * on these chips. Unfortunately this means - * we don't use the extra SCB ram space on the - * 3940AUW. - */ - ramps = 0; - else if (chip >= AHC_AIC7870) - ramps = (devconfig & RAMPSM) != 0; - else - ramps = 0; - - if (ramps && single_user) - return (1); - return (0); -} - -/* - * Enable external scbram. - */ -static void -ahc_scbram_config(struct ahc_softc *ahc, int enable, int pcheck, - int fast, int large) -{ - uint32_t devconfig; - - if (ahc->features & AHC_MULTI_FUNC) { - /* - * Set the SCB Base addr (highest address bit) - * depending on which channel we are. - */ - ahc_outb(ahc, SCBBADDR, ahc_get_pci_function(ahc->dev_softc)); - } - - ahc->flags &= ~AHC_LSCBS_ENABLED; - if (large) - ahc->flags |= AHC_LSCBS_ENABLED; - devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); - if ((ahc->features & AHC_ULTRA2) != 0) { - u_int dscommand0; - - dscommand0 = ahc_inb(ahc, DSCOMMAND0); - if (enable) - dscommand0 &= ~INTSCBRAMSEL; - else - dscommand0 |= INTSCBRAMSEL; - if (large) - dscommand0 &= ~USCBSIZE32; - else - dscommand0 |= USCBSIZE32; - ahc_outb(ahc, DSCOMMAND0, dscommand0); - } else { - if (fast) - devconfig &= ~EXTSCBTIME; - else - devconfig |= EXTSCBTIME; - if (enable) - devconfig &= ~SCBRAMSEL; - else - devconfig |= SCBRAMSEL; - if (large) - devconfig &= ~SCBSIZE32; - else - devconfig |= SCBSIZE32; - } - if (pcheck) - devconfig |= EXTSCBPEN; - else - devconfig &= ~EXTSCBPEN; - - ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); -} - -/* - * Take a look to see if we have external SRAM. - * We currently do not attempt to use SRAM that is - * shared among multiple controllers. - */ -static void -ahc_probe_ext_scbram(struct ahc_softc *ahc) -{ - int num_scbs; - int test_num_scbs; - int enable; - int pcheck; - int fast; - int large; - - enable = FALSE; - pcheck = FALSE; - fast = FALSE; - large = FALSE; - num_scbs = 0; - - if (ahc_ext_scbram_present(ahc) == 0) - goto done; - - /* - * Probe for the best parameters to use. - */ - ahc_scbram_config(ahc, /*enable*/TRUE, pcheck, fast, large); - num_scbs = ahc_probe_scbs(ahc); - if (num_scbs == 0) { - /* The SRAM wasn't really present. */ - goto done; - } - enable = TRUE; - - /* - * Clear any outstanding parity error - * and ensure that parity error reporting - * is enabled. - */ - ahc_outb(ahc, SEQCTL, 0); - ahc_outb(ahc, CLRINT, CLRPARERR); - ahc_outb(ahc, CLRINT, CLRBRKADRINT); - - /* Now see if we can do parity */ - ahc_scbram_config(ahc, enable, /*pcheck*/TRUE, fast, large); - num_scbs = ahc_probe_scbs(ahc); - if ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0 - || (ahc_inb(ahc, ERROR) & MPARERR) == 0) - pcheck = TRUE; - - /* Clear any resulting parity error */ - ahc_outb(ahc, CLRINT, CLRPARERR); - ahc_outb(ahc, CLRINT, CLRBRKADRINT); - - /* Now see if we can do fast timing */ - ahc_scbram_config(ahc, enable, pcheck, /*fast*/TRUE, large); - test_num_scbs = ahc_probe_scbs(ahc); - if (test_num_scbs == num_scbs - && ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0 - || (ahc_inb(ahc, ERROR) & MPARERR) == 0)) - fast = TRUE; - - /* - * See if we can use large SCBs and still maintain - * the same overall count of SCBs. - */ - if ((ahc->features & AHC_LARGE_SCBS) != 0) { - ahc_scbram_config(ahc, enable, pcheck, fast, /*large*/TRUE); - test_num_scbs = ahc_probe_scbs(ahc); - if (test_num_scbs >= num_scbs) { - large = TRUE; - num_scbs = test_num_scbs; - if (num_scbs >= 64) { - /* - * We have enough space to move the - * "busy targets table" into SCB space - * and make it qualify all the way to the - * lun level. - */ - ahc->flags |= AHC_SCB_BTT; - } - } - } -done: - /* - * Disable parity error reporting until we - * can load instruction ram. - */ - ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS); - /* Clear any latched parity error */ - ahc_outb(ahc, CLRINT, CLRPARERR); - ahc_outb(ahc, CLRINT, CLRBRKADRINT); - if (bootverbose && enable) { - printf("%s: External SRAM, %s access%s, %dbytes/SCB\n", - ahc_name(ahc), fast ? "fast" : "slow", - pcheck ? ", parity checking enabled" : "", - large ? 64 : 32); - } - ahc_scbram_config(ahc, enable, pcheck, fast, large); -} - -/* - * Check the external port logic for a serial eeprom - * and termination/cable detection contrls. - */ -static void -check_extport(struct ahc_softc *ahc, u_int *sxfrctl1) -{ - struct seeprom_descriptor sd; - struct seeprom_config *sc; - int have_seeprom; - int have_autoterm; - - sd.sd_ahc = ahc; - sd.sd_control_offset = SEECTL; - sd.sd_status_offset = SEECTL; - sd.sd_dataout_offset = SEECTL; - sc = ahc->seep_config; - - /* - * For some multi-channel devices, the c46 is simply too - * small to work. For the other controller types, we can - * get our information from either SEEPROM type. Set the - * type to start our probe with accordingly. - */ - if (ahc->flags & AHC_LARGE_SEEPROM) - sd.sd_chip = C56_66; - else - sd.sd_chip = C46; - - sd.sd_MS = SEEMS; - sd.sd_RDY = SEERDY; - sd.sd_CS = SEECS; - sd.sd_CK = SEECK; - sd.sd_DO = SEEDO; - sd.sd_DI = SEEDI; - - have_seeprom = ahc_acquire_seeprom(ahc, &sd); - if (have_seeprom) { - - if (bootverbose) - printf("%s: Reading SEEPROM...", ahc_name(ahc)); - - for (;;) { - u_int start_addr; - - start_addr = 32 * (ahc->channel - 'A'); - - have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc, - start_addr, - sizeof(*sc)/2); - - if (have_seeprom) - have_seeprom = ahc_verify_cksum(sc); - - if (have_seeprom != 0 || sd.sd_chip == C56_66) { - if (bootverbose) { - if (have_seeprom == 0) - printf ("checksum error\n"); - else - printf ("done.\n"); - } - break; - } - sd.sd_chip = C56_66; - } - ahc_release_seeprom(&sd); - } - - if (!have_seeprom) { - /* - * Pull scratch ram settings and treat them as - * if they are the contents of an seeprom if - * the 'ADPT' signature is found in SCB2. - * We manually compose the data as 16bit values - * to avoid endian issues. - */ - ahc_outb(ahc, SCBPTR, 2); - if (ahc_inb(ahc, SCB_BASE) == 'A' - && ahc_inb(ahc, SCB_BASE + 1) == 'D' - && ahc_inb(ahc, SCB_BASE + 2) == 'P' - && ahc_inb(ahc, SCB_BASE + 3) == 'T') { - uint16_t *sc_data; - int i; - - sc_data = (uint16_t *)sc; - for (i = 0; i < 32; i++) { - uint16_t val; - int j; - - j = i * 2; - val = ahc_inb(ahc, SRAM_BASE + j) - | ahc_inb(ahc, SRAM_BASE + j + 1) << 8; - } - have_seeprom = ahc_verify_cksum(sc); - if (have_seeprom) - ahc->flags |= AHC_SCB_CONFIG_USED; - } - /* - * Clear any SCB parity errors in case this data and - * its associated parity was not initialized by the BIOS - */ - ahc_outb(ahc, CLRINT, CLRPARERR); - ahc_outb(ahc, CLRINT, CLRBRKADRINT); - } - - if (!have_seeprom) { - if (bootverbose) - printf("%s: No SEEPROM available.\n", ahc_name(ahc)); - ahc->flags |= AHC_USEDEFAULTS; - free(ahc->seep_config, M_DEVBUF); - ahc->seep_config = NULL; - sc = NULL; - } else { - ahc_parse_pci_eeprom(ahc, sc); - } - - /* - * Cards that have the external logic necessary to talk to - * a SEEPROM, are almost certain to have the remaining logic - * necessary for auto-termination control. This assumption - * hasn't failed yet... - */ - have_autoterm = have_seeprom; - - /* - * Some low-cost chips have SEEPROM and auto-term control built - * in, instead of using a GAL. They can tell us directly - * if the termination logic is enabled. - */ - if ((ahc->features & AHC_SPIOCAP) != 0) { - if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) == 0) - have_autoterm = FALSE; - } - - if (have_autoterm) { - ahc_acquire_seeprom(ahc, &sd); - configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1); - ahc_release_seeprom(&sd); - } else if (have_seeprom) { - *sxfrctl1 &= ~STPWEN; - if ((sc->adapter_control & CFSTERM) != 0) - *sxfrctl1 |= STPWEN; - if (bootverbose) - printf("%s: Low byte termination %sabled\n", - ahc_name(ahc), - (*sxfrctl1 & STPWEN) ? "en" : "dis"); - } -} - -static void -ahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc) -{ - /* - * Put the data we've collected down into SRAM - * where ahc_init will find it. - */ - int i; - int max_targ = sc->max_targets & CFMAXTARG; - u_int scsi_conf; - uint16_t discenable; - uint16_t ultraenb; - - discenable = 0; - ultraenb = 0; - if ((sc->adapter_control & CFULTRAEN) != 0) { - /* - * Determine if this adapter has a "newstyle" - * SEEPROM format. - */ - for (i = 0; i < max_targ; i++) { - if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) { - ahc->flags |= AHC_NEWEEPROM_FMT; - break; - } - } - } - - for (i = 0; i < max_targ; i++) { - u_int scsirate; - uint16_t target_mask; - - target_mask = 0x01 << i; - if (sc->device_flags[i] & CFDISC) - discenable |= target_mask; - if ((ahc->flags & AHC_NEWEEPROM_FMT) != 0) { - if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) - ultraenb |= target_mask; - } else if ((sc->adapter_control & CFULTRAEN) != 0) { - ultraenb |= target_mask; - } - if ((sc->device_flags[i] & CFXFER) == 0x04 - && (ultraenb & target_mask) != 0) { - /* Treat 10MHz as a non-ultra speed */ - sc->device_flags[i] &= ~CFXFER; - ultraenb &= ~target_mask; - } - if ((ahc->features & AHC_ULTRA2) != 0) { - u_int offset; - - if (sc->device_flags[i] & CFSYNCH) - offset = MAX_OFFSET_ULTRA2; - else - offset = 0; - ahc_outb(ahc, TARG_OFFSET + i, offset); - - /* - * The ultra enable bits contain the - * high bit of the ultra2 sync rate - * field. - */ - scsirate = (sc->device_flags[i] & CFXFER) - | ((ultraenb & target_mask) ? 0x8 : 0x0); - if (sc->device_flags[i] & CFWIDEB) - scsirate |= WIDEXFER; - } else { - scsirate = (sc->device_flags[i] & CFXFER) << 4; - if (sc->device_flags[i] & CFSYNCH) - scsirate |= SOFS; - if (sc->device_flags[i] & CFWIDEB) - scsirate |= WIDEXFER; - } - ahc_outb(ahc, TARG_SCSIRATE + i, scsirate); - } - ahc->our_id = sc->brtime_id & CFSCSIID; - - scsi_conf = (ahc->our_id & 0x7); - if (sc->adapter_control & CFSPARITY) - scsi_conf |= ENSPCHK; - if (sc->adapter_control & CFRESETB) - scsi_conf |= RESET_SCSI; - - ahc->flags |= (sc->adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT; - - if (sc->bios_control & CFEXTEND) - ahc->flags |= AHC_EXTENDED_TRANS_A; - - if (sc->bios_control & CFBIOSEN) - ahc->flags |= AHC_BIOS_ENABLED; - if (ahc->features & AHC_ULTRA - && (ahc->flags & AHC_NEWEEPROM_FMT) == 0) { - /* Should we enable Ultra mode? */ - if (!(sc->adapter_control & CFULTRAEN)) - /* Treat us as a non-ultra card */ - ultraenb = 0; - } - - if (sc->signature == CFSIGNATURE - || sc->signature == CFSIGNATURE2) { - uint32_t devconfig; - - /* Honor the STPWLEVEL settings */ - devconfig = ahc_pci_read_config(ahc->dev_softc, - DEVCONFIG, /*bytes*/4); - devconfig &= ~STPWLEVEL; - if ((sc->bios_control & CFSTPWLEVEL) != 0) - devconfig |= STPWLEVEL; - ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, - devconfig, /*bytes*/4); - } - /* Set SCSICONF info */ - ahc_outb(ahc, SCSICONF, scsi_conf); - ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff)); - ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff)); - ahc_outb(ahc, ULTRA_ENB, ultraenb & 0xff); - ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff); -} - -static void -configure_termination(struct ahc_softc *ahc, - struct seeprom_descriptor *sd, - u_int adapter_control, - u_int *sxfrctl1) -{ - uint8_t brddat; - - brddat = 0; - - /* - * Update the settings in sxfrctl1 to match the - * termination settings - */ - *sxfrctl1 = 0; - - /* - * SEECS must be on for the GALS to latch - * the data properly. Be sure to leave MS - * on or we will release the seeprom. - */ - SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS); - if ((adapter_control & CFAUTOTERM) != 0 - || (ahc->features & AHC_NEW_TERMCTL) != 0) { - int internal50_present; - int internal68_present; - int externalcable_present; - int eeprom_present; - int enableSEC_low; - int enableSEC_high; - int enablePRI_low; - int enablePRI_high; - int sum; - - enableSEC_low = 0; - enableSEC_high = 0; - enablePRI_low = 0; - enablePRI_high = 0; - if ((ahc->features & AHC_NEW_TERMCTL) != 0) { - ahc_new_term_detect(ahc, &enableSEC_low, - &enableSEC_high, - &enablePRI_low, - &enablePRI_high, - &eeprom_present); - if ((adapter_control & CFSEAUTOTERM) == 0) { - if (bootverbose) - printf("%s: Manual SE Termination\n", - ahc_name(ahc)); - enableSEC_low = (adapter_control & CFSELOWTERM); - enableSEC_high = - (adapter_control & CFSEHIGHTERM); - } - if ((adapter_control & CFAUTOTERM) == 0) { - if (bootverbose) - printf("%s: Manual LVD Termination\n", - ahc_name(ahc)); - enablePRI_low = (adapter_control & CFSTERM); - enablePRI_high = (adapter_control & CFWSTERM); - } - /* Make the table calculations below happy */ - internal50_present = 0; - internal68_present = 1; - externalcable_present = 1; - } else if ((ahc->features & AHC_SPIOCAP) != 0) { - aic785X_cable_detect(ahc, &internal50_present, - &externalcable_present, - &eeprom_present); - } else { - aic787X_cable_detect(ahc, &internal50_present, - &internal68_present, - &externalcable_present, - &eeprom_present); - } - - if ((ahc->features & AHC_WIDE) == 0) - internal68_present = 0; - - if (bootverbose - && (ahc->features & AHC_ULTRA2) == 0) { - printf("%s: internal 50 cable %s present", - ahc_name(ahc), - internal50_present ? "is":"not"); - - if ((ahc->features & AHC_WIDE) != 0) - printf(", internal 68 cable %s present", - internal68_present ? "is":"not"); - printf("\n%s: external cable %s present\n", - ahc_name(ahc), - externalcable_present ? "is":"not"); - } - if (bootverbose) - printf("%s: BIOS eeprom %s present\n", - ahc_name(ahc), eeprom_present ? "is" : "not"); - - if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) { - /* - * The 50 pin connector is a separate bus, - * so force it to always be terminated. - * In the future, perform current sensing - * to determine if we are in the middle of - * a properly terminated bus. - */ - internal50_present = 0; - } - - /* - * Now set the termination based on what - * we found. - * Flash Enable = BRDDAT7 - * Secondary High Term Enable = BRDDAT6 - * Secondary Low Term Enable = BRDDAT5 (7890) - * Primary High Term Enable = BRDDAT4 (7890) - */ - if ((ahc->features & AHC_ULTRA2) == 0 - && (internal50_present != 0) - && (internal68_present != 0) - && (externalcable_present != 0)) { - printf("%s: Illegal cable configuration!!. " - "Only two connectors on the " - "adapter may be used at a " - "time!\n", ahc_name(ahc)); - - /* - * Pretend there are no cables in the hope - * that having all of the termination on - * gives us a more stable bus. - */ - internal50_present = 0; - internal68_present = 0; - externalcable_present = 0; - } - - if ((ahc->features & AHC_WIDE) != 0 - && ((externalcable_present == 0) - || (internal68_present == 0) - || (enableSEC_high != 0))) { - brddat |= BRDDAT6; - if (bootverbose) { - if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) - printf("%s: 68 pin termination " - "Enabled\n", ahc_name(ahc)); - else - printf("%s: %sHigh byte termination " - "Enabled\n", ahc_name(ahc), - enableSEC_high ? "Secondary " - : ""); - } - } - - sum = internal50_present + internal68_present - + externalcable_present; - if (sum < 2 || (enableSEC_low != 0)) { - if ((ahc->features & AHC_ULTRA2) != 0) - brddat |= BRDDAT5; - else - *sxfrctl1 |= STPWEN; - if (bootverbose) { - if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) - printf("%s: 50 pin termination " - "Enabled\n", ahc_name(ahc)); - else - printf("%s: %sLow byte termination " - "Enabled\n", ahc_name(ahc), - enableSEC_low ? "Secondary " - : ""); - } - } - - if (enablePRI_low != 0) { - *sxfrctl1 |= STPWEN; - if (bootverbose) - printf("%s: Primary Low Byte termination " - "Enabled\n", ahc_name(ahc)); - } - - /* - * Setup STPWEN before setting up the rest of - * the termination per the tech note on the U160 cards. - */ - ahc_outb(ahc, SXFRCTL1, *sxfrctl1); - - if (enablePRI_high != 0) { - brddat |= BRDDAT4; - if (bootverbose) - printf("%s: Primary High Byte " - "termination Enabled\n", - ahc_name(ahc)); - } - - write_brdctl(ahc, brddat); - - } else { - if ((adapter_control & CFSTERM) != 0) { - *sxfrctl1 |= STPWEN; - - if (bootverbose) - printf("%s: %sLow byte termination Enabled\n", - ahc_name(ahc), - (ahc->features & AHC_ULTRA2) ? "Primary " - : ""); - } - - if ((adapter_control & CFWSTERM) != 0 - && (ahc->features & AHC_WIDE) != 0) { - brddat |= BRDDAT6; - if (bootverbose) - printf("%s: %sHigh byte termination Enabled\n", - ahc_name(ahc), - (ahc->features & AHC_ULTRA2) - ? "Secondary " : ""); - } - - /* - * Setup STPWEN before setting up the rest of - * the termination per the tech note on the U160 cards. - */ - ahc_outb(ahc, SXFRCTL1, *sxfrctl1); - - if ((ahc->features & AHC_WIDE) != 0) - write_brdctl(ahc, brddat); - } - SEEPROM_OUTB(sd, sd->sd_MS); /* Clear CS */ -} - -static void -ahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low, - int *enableSEC_high, int *enablePRI_low, - int *enablePRI_high, int *eeprom_present) -{ - uint8_t brdctl; - - /* - * BRDDAT7 = Eeprom - * BRDDAT6 = Enable Secondary High Byte termination - * BRDDAT5 = Enable Secondary Low Byte termination - * BRDDAT4 = Enable Primary high byte termination - * BRDDAT3 = Enable Primary low byte termination - */ - brdctl = read_brdctl(ahc); - *eeprom_present = brdctl & BRDDAT7; - *enableSEC_high = (brdctl & BRDDAT6); - *enableSEC_low = (brdctl & BRDDAT5); - *enablePRI_high = (brdctl & BRDDAT4); - *enablePRI_low = (brdctl & BRDDAT3); -} - -static void -aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present, - int *internal68_present, int *externalcable_present, - int *eeprom_present) -{ - uint8_t brdctl; - - /* - * First read the status of our cables. - * Set the rom bank to 0 since the - * bank setting serves as a multiplexor - * for the cable detection logic. - * BRDDAT5 controls the bank switch. - */ - write_brdctl(ahc, 0); - - /* - * Now read the state of the internal - * connectors. BRDDAT6 is INT50 and - * BRDDAT7 is INT68. - */ - brdctl = read_brdctl(ahc); - *internal50_present = (brdctl & BRDDAT6) ? 0 : 1; - *internal68_present = (brdctl & BRDDAT7) ? 0 : 1; - - /* - * Set the rom bank to 1 and determine - * the other signals. - */ - write_brdctl(ahc, BRDDAT5); - - /* - * Now read the state of the external - * connectors. BRDDAT6 is EXT68 and - * BRDDAT7 is EPROMPS. - */ - brdctl = read_brdctl(ahc); - *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; - *eeprom_present = (brdctl & BRDDAT7) ? 1 : 0; -} - -static void -aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present, - int *externalcable_present, int *eeprom_present) -{ - uint8_t brdctl; - uint8_t spiocap; - - spiocap = ahc_inb(ahc, SPIOCAP); - spiocap &= ~SOFTCMDEN; - spiocap |= EXT_BRDCTL; - ahc_outb(ahc, SPIOCAP, spiocap); - ahc_outb(ahc, BRDCTL, BRDRW|BRDCS); - ahc_outb(ahc, BRDCTL, 0); - brdctl = ahc_inb(ahc, BRDCTL); - *internal50_present = (brdctl & BRDDAT5) ? 0 : 1; - *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; - - *eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0; -} - -int -ahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd) -{ - int wait; - - if ((ahc->features & AHC_SPIOCAP) != 0 - && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0) - return (0); - - /* - * Request access of the memory port. When access is - * granted, SEERDY will go high. We use a 1 second - * timeout which should be near 1 second more than - * is needed. Reason: after the chip reset, there - * should be no contention. - */ - SEEPROM_OUTB(sd, sd->sd_MS); - wait = 1000; /* 1 second timeout in msec */ - while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) { - ahc_delay(1000); /* delay 1 msec */ - } - if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) { - SEEPROM_OUTB(sd, 0); - return (0); - } - return(1); -} - -void -ahc_release_seeprom(struct seeprom_descriptor *sd) -{ - /* Release access to the memory port and the serial EEPROM. */ - SEEPROM_OUTB(sd, 0); -} - -static void -write_brdctl(struct ahc_softc *ahc, uint8_t value) -{ - uint8_t brdctl; - - if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { - brdctl = BRDSTB; - if (ahc->channel == 'B') - brdctl |= BRDCS; - } else if ((ahc->features & AHC_ULTRA2) != 0) { - brdctl = 0; - } else { - brdctl = BRDSTB|BRDCS; - } - ahc_outb(ahc, BRDCTL, brdctl); - ahc_flush_device_writes(ahc); - brdctl |= value; - ahc_outb(ahc, BRDCTL, brdctl); - ahc_flush_device_writes(ahc); - if ((ahc->features & AHC_ULTRA2) != 0) - brdctl |= BRDSTB_ULTRA2; - else - brdctl &= ~BRDSTB; - ahc_outb(ahc, BRDCTL, brdctl); - ahc_flush_device_writes(ahc); - if ((ahc->features & AHC_ULTRA2) != 0) - brdctl = 0; - else - brdctl &= ~BRDCS; - ahc_outb(ahc, BRDCTL, brdctl); -} - -static uint8_t -read_brdctl(ahc) - struct ahc_softc *ahc; -{ - uint8_t brdctl; - uint8_t value; - - if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { - brdctl = BRDRW; - if (ahc->channel == 'B') - brdctl |= BRDCS; - } else if ((ahc->features & AHC_ULTRA2) != 0) { - brdctl = BRDRW_ULTRA2; - } else { - brdctl = BRDRW|BRDCS; - } - ahc_outb(ahc, BRDCTL, brdctl); - ahc_flush_device_writes(ahc); - value = ahc_inb(ahc, BRDCTL); - ahc_outb(ahc, BRDCTL, 0); - return (value); -} - -#define DPE 0x80 -#define SSE 0x40 -#define RMA 0x20 -#define RTA 0x10 -#define STA 0x08 -#define DPR 0x01 - -void -ahc_pci_intr(struct ahc_softc *ahc) -{ - u_int error; - u_int status1; - - error = ahc_inb(ahc, ERROR); - if ((error & PCIERRSTAT) == 0) - return; - - status1 = ahc_pci_read_config(ahc->dev_softc, - PCIR_STATUS + 1, /*bytes*/1); - - printf("%s: PCI error Interrupt at seqaddr = 0x%x\n", - ahc_name(ahc), - ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); - - if (status1 & DPE) { - printf("%s: Data Parity Error Detected during address " - "or write data phase\n", ahc_name(ahc)); - } - if (status1 & SSE) { - printf("%s: Signal System Error Detected\n", ahc_name(ahc)); - } - if (status1 & RMA) { - printf("%s: Received a Master Abort\n", ahc_name(ahc)); - } - if (status1 & RTA) { - printf("%s: Received a Target Abort\n", ahc_name(ahc)); - } - if (status1 & STA) { - printf("%s: Signaled a Target Abort\n", ahc_name(ahc)); - } - if (status1 & DPR) { - printf("%s: Data Parity Error has been reported via PERR#\n", - ahc_name(ahc)); - } - - /* Clear latched errors. */ - ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, - status1, /*bytes*/1); - - if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) { - printf("%s: Latched PCIERR interrupt with " - "no status bits set\n", ahc_name(ahc)); - } else { - ahc_outb(ahc, CLRINT, CLRPARERR); - } - - ahc_unpause(ahc); -} - -static int -ahc_aic785X_setup(struct ahc_softc *ahc) -{ - ahc_dev_softc_t pci; - uint8_t rev; - - pci = ahc->dev_softc; - ahc->channel = 'A'; - ahc->chip = AHC_AIC7850; - ahc->features = AHC_AIC7850_FE; - ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); - if (rev >= 1) - ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; - return (0); -} - -static int -ahc_aic7860_setup(struct ahc_softc *ahc) -{ - ahc_dev_softc_t pci; - uint8_t rev; - - pci = ahc->dev_softc; - ahc->channel = 'A'; - ahc->chip = AHC_AIC7860; - ahc->features = AHC_AIC7860_FE; - ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); - if (rev >= 1) - ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; - return (0); -} - -static int -ahc_apa1480_setup(struct ahc_softc *ahc) -{ - ahc_dev_softc_t pci; - int error; - - pci = ahc->dev_softc; - error = ahc_aic7860_setup(ahc); - if (error != 0) - return (error); - ahc->features |= AHC_REMOVABLE; - return (0); -} - -static int -ahc_aic7870_setup(struct ahc_softc *ahc) -{ - ahc_dev_softc_t pci; - - pci = ahc->dev_softc; - ahc->channel = 'A'; - ahc->chip = AHC_AIC7870; - ahc->features = AHC_AIC7870_FE; - ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; - return (0); -} - -static int -ahc_aha394X_setup(struct ahc_softc *ahc) -{ - int error; - - error = ahc_aic7870_setup(ahc); - if (error == 0) - error = ahc_aha394XX_setup(ahc); - return (error); -} - -static int -ahc_aha398X_setup(struct ahc_softc *ahc) -{ - int error; - - error = ahc_aic7870_setup(ahc); - if (error == 0) - error = ahc_aha398XX_setup(ahc); - return (error); -} - -static int -ahc_aha494X_setup(struct ahc_softc *ahc) -{ - int error; - - error = ahc_aic7870_setup(ahc); - if (error == 0) - error = ahc_aha494XX_setup(ahc); - return (error); -} - -static int -ahc_aic7880_setup(struct ahc_softc *ahc) -{ - ahc_dev_softc_t pci; - uint8_t rev; - - pci = ahc->dev_softc; - ahc->channel = 'A'; - ahc->chip = AHC_AIC7880; - ahc->features = AHC_AIC7880_FE; - ahc->bugs |= AHC_TMODE_WIDEODD_BUG; - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); - if (rev >= 1) { - ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; - } else { - ahc->bugs |= AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; - } - return (0); -} - -static int -ahc_aha2940Pro_setup(struct ahc_softc *ahc) -{ - ahc_dev_softc_t pci; - int error; - - pci = ahc->dev_softc; - ahc->flags |= AHC_INT50_SPEEDFLEX; - error = ahc_aic7880_setup(ahc); - return (0); -} - -static int -ahc_aha394XU_setup(struct ahc_softc *ahc) -{ - int error; - - error = ahc_aic7880_setup(ahc); - if (error == 0) - error = ahc_aha394XX_setup(ahc); - return (error); -} - -static int -ahc_aha398XU_setup(struct ahc_softc *ahc) -{ - int error; - - error = ahc_aic7880_setup(ahc); - if (error == 0) - error = ahc_aha398XX_setup(ahc); - return (error); -} - -static int -ahc_aic7890_setup(struct ahc_softc *ahc) -{ - ahc_dev_softc_t pci; - uint8_t rev; - - pci = ahc->dev_softc; - ahc->channel = 'A'; - ahc->chip = AHC_AIC7890; - ahc->features = AHC_AIC7890_FE; - ahc->flags |= AHC_NEWEEPROM_FMT; - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); - if (rev == 0) - ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG; - return (0); -} - -static int -ahc_aic7892_setup(struct ahc_softc *ahc) -{ - ahc_dev_softc_t pci; - - pci = ahc->dev_softc; - ahc->channel = 'A'; - ahc->chip = AHC_AIC7892; - ahc->features = AHC_AIC7892_FE; - ahc->flags |= AHC_NEWEEPROM_FMT; - ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG; - return (0); -} - -static int -ahc_aic7895_setup(struct ahc_softc *ahc) -{ - ahc_dev_softc_t pci; - uint8_t rev; - - pci = ahc->dev_softc; - ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; - /* - * The 'C' revision of the aic7895 has a few additional features. - */ - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); - if (rev >= 4) { - ahc->chip = AHC_AIC7895C; - ahc->features = AHC_AIC7895C_FE; - } else { - u_int command; - - ahc->chip = AHC_AIC7895; - ahc->features = AHC_AIC7895_FE; - - /* - * The BIOS disables the use of MWI transactions - * since it does not have the MWI bug work around - * we have. Disabling MWI reduces performance, so - * turn it on again. - */ - command = ahc_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1); - command |= PCIM_CMD_MWRICEN; - ahc_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1); - ahc->bugs |= AHC_PCI_MWI_BUG; - } - /* - * XXX Does CACHETHEN really not work??? What about PCI retry? - * on C level chips. Need to test, but for now, play it safe. - */ - ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG - | AHC_CACHETHEN_BUG; - -#if 0 - uint32_t devconfig; - - /* - * Cachesize must also be zero due to stray DAC - * problem when sitting behind some bridges. - */ - ahc_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1); - devconfig = ahc_pci_read_config(pci, DEVCONFIG, /*bytes*/1); - devconfig |= MRDCEN; - ahc_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1); -#endif - ahc->flags |= AHC_NEWEEPROM_FMT; - return (0); -} - -static int -ahc_aic7896_setup(struct ahc_softc *ahc) -{ - ahc_dev_softc_t pci; - - pci = ahc->dev_softc; - ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; - ahc->chip = AHC_AIC7896; - ahc->features = AHC_AIC7896_FE; - ahc->flags |= AHC_NEWEEPROM_FMT; - ahc->bugs |= AHC_CACHETHEN_DIS_BUG; - return (0); -} - -static int -ahc_aic7899_setup(struct ahc_softc *ahc) -{ - ahc_dev_softc_t pci; - - pci = ahc->dev_softc; - ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; - ahc->chip = AHC_AIC7899; - ahc->features = AHC_AIC7899_FE; - ahc->flags |= AHC_NEWEEPROM_FMT; - ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG; - return (0); -} - -static int -ahc_aha29160C_setup(struct ahc_softc *ahc) -{ - int error; - - error = ahc_aic7899_setup(ahc); - if (error != 0) - return (error); - ahc->features |= AHC_REMOVABLE; - return (0); -} - -static int -ahc_raid_setup(struct ahc_softc *ahc) -{ - printf("RAID functionality unsupported\n"); - return (ENXIO); -} - -static int -ahc_aha394XX_setup(struct ahc_softc *ahc) -{ - ahc_dev_softc_t pci; - - pci = ahc->dev_softc; - switch (ahc_get_pci_slot(pci)) { - case AHC_394X_SLOT_CHANNEL_A: - ahc->channel = 'A'; - break; - case AHC_394X_SLOT_CHANNEL_B: - ahc->channel = 'B'; - break; - default: - printf("adapter at unexpected slot %d\n" - "unable to map to a channel\n", - ahc_get_pci_slot(pci)); - ahc->channel = 'A'; - } - return (0); -} - -static int -ahc_aha398XX_setup(struct ahc_softc *ahc) -{ - ahc_dev_softc_t pci; - - pci = ahc->dev_softc; - switch (ahc_get_pci_slot(pci)) { - case AHC_398X_SLOT_CHANNEL_A: - ahc->channel = 'A'; - break; - case AHC_398X_SLOT_CHANNEL_B: - ahc->channel = 'B'; - break; - case AHC_398X_SLOT_CHANNEL_C: - ahc->channel = 'C'; - break; - default: - printf("adapter at unexpected slot %d\n" - "unable to map to a channel\n", - ahc_get_pci_slot(pci)); - ahc->channel = 'A'; - break; - } - ahc->flags |= AHC_LARGE_SEEPROM; - return (0); -} - -static int -ahc_aha494XX_setup(struct ahc_softc *ahc) -{ - ahc_dev_softc_t pci; - - pci = ahc->dev_softc; - switch (ahc_get_pci_slot(pci)) { - case AHC_494X_SLOT_CHANNEL_A: - ahc->channel = 'A'; - break; - case AHC_494X_SLOT_CHANNEL_B: - ahc->channel = 'B'; - break; - case AHC_494X_SLOT_CHANNEL_C: - ahc->channel = 'C'; - break; - case AHC_494X_SLOT_CHANNEL_D: - ahc->channel = 'D'; - break; - default: - printf("adapter at unexpected slot %d\n" - "unable to map to a channel\n", - ahc_get_pci_slot(pci)); - ahc->channel = 'A'; - } - ahc->flags |= AHC_LARGE_SEEPROM; - return (0); -} diff --git a/xen/drivers/scsi/aic7xxx/aic7xxx_proc.c b/xen/drivers/scsi/aic7xxx/aic7xxx_proc.c deleted file mode 100644 index 9c93f57ea1..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic7xxx_proc.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Copyright (c) 2000-2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * String handling code courtesy of Gerard Roudier's - * sym driver. - * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#19 $ - */ -#include "aic7xxx_osm.h" -#include "aic7xxx_inline.h" -#include "aic7xxx_93cx6.h" - -static void copy_mem_info(struct info_str *info, char *data, int len); -static int copy_info(struct info_str *info, char *fmt, ...); -static u_int scsi_calc_syncsrate(u_int period_factor); -static void ahc_dump_target_state(struct ahc_softc *ahc, - struct info_str *info, - u_int our_id, char channel, - u_int target_id, u_int target_offset); -static void ahc_dump_device_state(struct info_str *info, - struct ahc_linux_device *dev); -static int ahc_proc_write_seeprom(struct ahc_softc *ahc, - char *buffer, int length); - -static void -copy_mem_info(struct info_str *info, char *data, int len) -{ - if (info->pos + len > info->offset + info->length) - len = info->offset + info->length - info->pos; - - if (info->pos + len < info->offset) { - info->pos += len; - return; - } - - if (info->pos < info->offset) { - off_t partial; - - partial = info->offset - info->pos; - data += partial; - info->pos += partial; - len -= partial; - } - - if (len > 0) { - memcpy(info->buffer, data, len); - info->pos += len; - info->buffer += len; - } -} - -static int -copy_info(struct info_str *info, char *fmt, ...) -{ - va_list args; - char buf[256]; - int len; - - va_start(args, fmt); - len = vsprintf(buf, fmt, args); - va_end(args); - - copy_mem_info(info, buf, len); - return (len); -} - -/* - * Table of syncrates that don't follow the "divisible by 4" - * rule. This table will be expanded in future SCSI specs. - */ -static struct { - u_int period_factor; - u_int period; /* in 10ths of ns */ -} scsi_syncrates[] = { - { 0x09, 125 }, /* FAST-80 */ - { 0x0a, 250 }, /* FAST-40 40MHz */ - { 0x0b, 303 }, /* FAST-40 33MHz */ - { 0x0c, 500 } /* FAST-20 */ -}; - -/* - * Return the frequency in kHz corresponding to the given - * sync period factor. - */ -static u_int -scsi_calc_syncsrate(u_int period_factor) -{ - int i; - int num_syncrates; - - num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]); - /* See if the period is in the "exception" table */ - for (i = 0; i < num_syncrates; i++) { - - if (period_factor == scsi_syncrates[i].period_factor) { - /* Period in kHz */ - return (10000000 / scsi_syncrates[i].period); - } - } - - /* - * Wasn't in the table, so use the standard - * 4 times conversion. - */ - return (10000000 / (period_factor * 4 * 10)); -} - -void -ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo) -{ - u_int speed; - u_int freq; - u_int mb; - - speed = 3300; - freq = 0; - if (tinfo->offset != 0) { - freq = scsi_calc_syncsrate(tinfo->period); - speed = freq; - } - speed *= (0x01 << tinfo->width); - mb = speed / 1000; - if (mb > 0) - copy_info(info, "%d.%03dMB/s transfers", mb, speed % 1000); - else - copy_info(info, "%dKB/s transfers", speed); - - if (freq != 0) { - copy_info(info, " (%d.%03dMHz%s, offset %d", - freq / 1000, freq % 1000, - (tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0 - ? " DT" : "", tinfo->offset); - } - - if (tinfo->width > 0) { - if (freq != 0) { - copy_info(info, ", "); - } else { - copy_info(info, " ("); - } - copy_info(info, "%dbit)", 8 * (0x01 << tinfo->width)); - } else if (freq != 0) { - copy_info(info, ")"); - } - copy_info(info, "\n"); -} - -static void -ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info, - u_int our_id, char channel, u_int target_id, - u_int target_offset) -{ - struct ahc_linux_target *targ; - struct ahc_initiator_tinfo *tinfo; - struct ahc_tmode_tstate *tstate; - int lun; - - tinfo = ahc_fetch_transinfo(ahc, channel, our_id, - target_id, &tstate); - copy_info(info, "Channel %c Target %d Negotiation Settings\n", - channel, target_id); - copy_info(info, "\tUser: "); - ahc_format_transinfo(info, &tinfo->user); - targ = ahc->platform_data->targets[target_offset]; - if (targ == NULL) - return; - - copy_info(info, "\tGoal: "); - ahc_format_transinfo(info, &tinfo->goal); - copy_info(info, "\tCurr: "); - ahc_format_transinfo(info, &tinfo->curr); - - for (lun = 0; lun < AHC_NUM_LUNS; lun++) { - struct ahc_linux_device *dev; - - dev = targ->devices[lun]; - - if (dev == NULL) - continue; - - ahc_dump_device_state(info, dev); - } -} - -static void -ahc_dump_device_state(struct info_str *info, struct ahc_linux_device *dev) -{ - copy_info(info, "\tChannel %c Target %d Lun %d Settings\n", - dev->target->channel + 'A', dev->target->target, dev->lun); - - copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued); - copy_info(info, "\t\tCommands Active %d\n", dev->active); - copy_info(info, "\t\tCommand Openings %d\n", dev->openings); - copy_info(info, "\t\tMax Tagged Openings %d\n", dev->maxtags); - copy_info(info, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen); -} - -static int -ahc_proc_write_seeprom(struct ahc_softc *ahc, char *buffer, int length) -{ - struct seeprom_descriptor sd; - int have_seeprom; - u_long s; - int paused; - int written; - - /* Default to failure. */ - written = -EINVAL; - ahc_lock(ahc, &s); - paused = ahc_is_paused(ahc); - if (!paused) - ahc_pause(ahc); - - if (length != sizeof(struct seeprom_config)) { - printf("ahc_proc_write_seeprom: incorrect buffer size\n"); - goto done; - } - - have_seeprom = ahc_verify_cksum((struct seeprom_config*)buffer); - if (have_seeprom == 0) { - printf("ahc_proc_write_seeprom: cksum verification failed\n"); - goto done; - } - - sd.sd_ahc = ahc; - if ((ahc->chip & AHC_VL) != 0) { - sd.sd_control_offset = SEECTL_2840; - sd.sd_status_offset = STATUS_2840; - sd.sd_dataout_offset = STATUS_2840; - sd.sd_chip = C46; - sd.sd_MS = 0; - sd.sd_RDY = EEPROM_TF; - sd.sd_CS = CS_2840; - sd.sd_CK = CK_2840; - sd.sd_DO = DO_2840; - sd.sd_DI = DI_2840; - have_seeprom = TRUE; - } else { - sd.sd_control_offset = SEECTL; - sd.sd_status_offset = SEECTL; - sd.sd_dataout_offset = SEECTL; - if (ahc->flags & AHC_LARGE_SEEPROM) - sd.sd_chip = C56_66; - else - sd.sd_chip = C46; - sd.sd_MS = SEEMS; - sd.sd_RDY = SEERDY; - sd.sd_CS = SEECS; - sd.sd_CK = SEECK; - sd.sd_DO = SEEDO; - sd.sd_DI = SEEDI; - have_seeprom = ahc_acquire_seeprom(ahc, &sd); - } - - if (!have_seeprom) { - printf("ahc_proc_write_seeprom: No Serial EEPROM\n"); - goto done; - } else { - u_int start_addr; - - if (ahc->seep_config == NULL) { - ahc->seep_config = malloc(sizeof(*ahc->seep_config), - M_DEVBUF, M_NOWAIT); - if (ahc->seep_config == NULL) { - printf("aic7xxx: Unable to allocate serial " - "eeprom buffer. Write failing\n"); - goto done; - } - } - printf("aic7xxx: Writing Serial EEPROM\n"); - start_addr = 32 * (ahc->channel - 'A'); - ahc_write_seeprom(&sd, (u_int16_t *)buffer, start_addr, - sizeof(struct seeprom_config)/2); - ahc_read_seeprom(&sd, (uint16_t *)ahc->seep_config, - start_addr, sizeof(struct seeprom_config)/2); - if ((ahc->chip & AHC_VL) == 0) - ahc_release_seeprom(&sd); - written = length; - } - -done: - if (!paused) - ahc_unpause(ahc); - ahc_unlock(ahc, &s); - return (written); -} - -/* - * Return information to handle /proc support for the driver. - */ -int -ahc_linux_proc_info(char *buffer, char **start, off_t offset, - int length, int hostno, int inout) -{ - struct ahc_softc *ahc; - struct info_str info; - char ahc_info[256]; - u_long s; - u_int max_targ; - u_int i; - int retval; - - retval = -EINVAL; - ahc_list_lock(&s); - TAILQ_FOREACH(ahc, &ahc_tailq, links) { - if (ahc->platform_data->host->host_no == hostno) - break; - } - - if (ahc == NULL) - goto done; - - /* Has data been written to the file? */ - if (inout == TRUE) { - retval = ahc_proc_write_seeprom(ahc, buffer, length); - goto done; - } - - if (start) - *start = buffer; - - info.buffer = buffer; - info.length = length; - info.offset = offset; - info.pos = 0; - - copy_info(&info, "Adaptec AIC7xxx driver version: %s\n", - AIC7XXX_DRIVER_VERSION); - ahc_controller_info(ahc, ahc_info); - copy_info(&info, "%s\n\n", ahc_info); - - if (ahc->seep_config == NULL) - copy_info(&info, "No Serial EEPROM\n"); - else { - copy_info(&info, "Serial EEPROM:\n"); - for (i = 0; i < sizeof(*ahc->seep_config)/2; i++) { - if (((i % 8) == 0) && (i != 0)) { - copy_info(&info, "\n"); - } - copy_info(&info, "0x%.4x ", - ((uint16_t*)ahc->seep_config)[i]); - } - copy_info(&info, "\n"); - } - copy_info(&info, "\n"); - - max_targ = 15; - if ((ahc->features & (AHC_WIDE|AHC_TWIN)) == 0) - max_targ = 7; - - for (i = 0; i <= max_targ; i++) { - u_int our_id; - u_int target_id; - char channel; - - channel = 'A'; - our_id = ahc->our_id; - target_id = i; - if (i > 7 && (ahc->features & AHC_TWIN) != 0) { - channel = 'B'; - our_id = ahc->our_id_b; - target_id = i % 8; - } - - ahc_dump_target_state(ahc, &info, our_id, - channel, target_id, i); - } - retval = info.pos > info.offset ? info.pos - info.offset : 0; -done: - ahc_list_unlock(&s); - return (retval); -} diff --git a/xen/drivers/scsi/aic7xxx/aic7xxx_reg.h b/xen/drivers/scsi/aic7xxx/aic7xxx_reg.h deleted file mode 100644 index a82c3ae7eb..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic7xxx_reg.h +++ /dev/null @@ -1,722 +0,0 @@ -/* - * DO NOT EDIT - This file is automatically generated - * from the following source files: - * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#43 $ - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#30 $ - */ - -#define SCSISEQ 0x00 -#define TEMODE 0x80 -#define SCSIRSTO 0x01 - -#define SXFRCTL0 0x01 -#define DFON 0x80 -#define DFPEXP 0x40 -#define FAST20 0x20 -#define CLRSTCNT 0x10 -#define SPIOEN 0x08 -#define SCAMEN 0x04 -#define CLRCHN 0x02 - -#define SXFRCTL1 0x02 -#define BITBUCKET 0x80 -#define SWRAPEN 0x40 -#define STIMESEL 0x18 -#define ENSTIMER 0x04 -#define ACTNEGEN 0x02 -#define STPWEN 0x01 - -#define SCSISIGO 0x03 -#define CDO 0x80 -#define IOO 0x40 -#define MSGO 0x20 -#define ATNO 0x10 -#define SELO 0x08 -#define BSYO 0x04 -#define REQO 0x02 -#define ACKO 0x01 - -#define SCSISIGI 0x03 -#define P_DATAIN_DT 0x60 -#define P_DATAOUT_DT 0x20 -#define ATNI 0x10 -#define SELI 0x08 -#define BSYI 0x04 -#define REQI 0x02 -#define ACKI 0x01 - -#define SCSIRATE 0x04 -#define WIDEXFER 0x80 -#define SXFR 0x70 -#define ENABLE_CRC 0x40 -#define SINGLE_EDGE 0x10 -#define SOFS 0x0f -#define SXFR_ULTRA2 0x0f - -#define SCSIID 0x05 -#define SCSIOFFSET 0x05 -#define SOFS_ULTRA2 0x7f - -#define SCSIDATL 0x06 - -#define SCSIDATH 0x07 - -#define STCNT 0x08 - -#define OPTIONMODE 0x08 -#define AUTORATEEN 0x80 -#define AUTOACKEN 0x40 -#define ATNMGMNTEN 0x20 -#define BUSFREEREV 0x10 -#define EXPPHASEDIS 0x08 -#define SCSIDATL_IMGEN 0x04 -#define OPTIONMODE_DEFAULTS 0x03 -#define AUTO_MSGOUT_DE 0x02 -#define DIS_MSGIN_DUALEDGE 0x01 - -#define TARGCRCCNT 0x0a - -#define CLRSINT0 0x0b -#define CLRSELDO 0x40 -#define CLRSELDI 0x20 -#define CLRSELINGO 0x10 -#define CLRIOERR 0x08 -#define CLRSWRAP 0x08 -#define CLRSPIORDY 0x02 - -#define SSTAT0 0x0b -#define TARGET 0x80 -#define SELDO 0x40 -#define SELDI 0x20 -#define SELINGO 0x10 -#define SWRAP 0x08 -#define IOERR 0x08 -#define SDONE 0x04 -#define SPIORDY 0x02 -#define DMADONE 0x01 - -#define CLRSINT1 0x0c -#define CLRSELTIMEO 0x80 -#define CLRATNO 0x40 -#define CLRSCSIRSTI 0x20 -#define CLRBUSFREE 0x08 -#define CLRSCSIPERR 0x04 -#define CLRPHASECHG 0x02 -#define CLRREQINIT 0x01 - -#define SSTAT1 0x0c -#define SELTO 0x80 -#define ATNTARG 0x40 -#define SCSIRSTI 0x20 -#define PHASEMIS 0x10 -#define BUSFREE 0x08 -#define SCSIPERR 0x04 -#define PHASECHG 0x02 -#define REQINIT 0x01 - -#define SSTAT2 0x0d -#define OVERRUN 0x80 -#define SHVALID 0x40 -#define SFCNT 0x1f -#define EXP_ACTIVE 0x10 -#define CRCVALERR 0x08 -#define CRCENDERR 0x04 -#define CRCREQERR 0x02 -#define DUAL_EDGE_ERR 0x01 - -#define SSTAT3 0x0e -#define SCSICNT 0xf0 -#define U2OFFCNT 0x7f -#define OFFCNT 0x0f - -#define SCSIID_ULTRA2 0x0f - -#define SIMODE0 0x10 -#define ENSELDO 0x40 -#define ENSELDI 0x20 -#define ENSELINGO 0x10 -#define ENIOERR 0x08 -#define ENSWRAP 0x08 -#define ENSDONE 0x04 -#define ENSPIORDY 0x02 -#define ENDMADONE 0x01 - -#define SIMODE1 0x11 -#define ENSELTIMO 0x80 -#define ENATNTARG 0x40 -#define ENSCSIRST 0x20 -#define ENPHASEMIS 0x10 -#define ENBUSFREE 0x08 -#define ENSCSIPERR 0x04 -#define ENPHASECHG 0x02 -#define ENREQINIT 0x01 - -#define SCSIBUSL 0x12 - -#define SCSIBUSH 0x13 - -#define SHADDR 0x14 - -#define SELTIMER 0x18 -#define TARGIDIN 0x18 -#define STAGE6 0x20 -#define STAGE5 0x10 -#define STAGE4 0x08 -#define STAGE3 0x04 -#define STAGE2 0x02 -#define STAGE1 0x01 - -#define SELID 0x19 -#define SELID_MASK 0xf0 -#define ONEBIT 0x08 - -#define SCAMCTL 0x1a -#define ENSCAMSELO 0x80 -#define CLRSCAMSELID 0x40 -#define ALTSTIM 0x20 -#define DFLTTID 0x10 -#define SCAMLVL 0x03 - -#define TARGID 0x1b - -#define SPIOCAP 0x1b -#define SOFT1 0x80 -#define SOFT0 0x40 -#define SOFTCMDEN 0x20 -#define EXT_BRDCTL 0x10 -#define SEEPROM 0x08 -#define EEPROM 0x04 -#define ROM 0x02 -#define SSPIOCPS 0x01 - -#define BRDCTL 0x1d -#define BRDDAT7 0x80 -#define BRDDAT6 0x40 -#define BRDDAT5 0x20 -#define BRDDAT4 0x10 -#define BRDSTB 0x10 -#define BRDDAT3 0x08 -#define BRDCS 0x08 -#define BRDDAT2 0x04 -#define BRDRW 0x04 -#define BRDRW_ULTRA2 0x02 -#define BRDCTL1 0x02 -#define BRDCTL0 0x01 -#define BRDSTB_ULTRA2 0x01 - -#define SEECTL 0x1e -#define EXTARBACK 0x80 -#define EXTARBREQ 0x40 -#define SEEMS 0x20 -#define SEERDY 0x10 -#define SEECS 0x08 -#define SEECK 0x04 -#define SEEDO 0x02 -#define SEEDI 0x01 - -#define SBLKCTL 0x1f -#define DIAGLEDEN 0x80 -#define DIAGLEDON 0x40 -#define AUTOFLUSHDIS 0x20 -#define ENAB40 0x08 -#define SELBUSB 0x08 -#define ENAB20 0x04 -#define SELWIDE 0x02 -#define XCVR 0x01 - -#define BUSY_TARGETS 0x20 -#define TARG_SCSIRATE 0x20 - -#define ULTRA_ENB 0x30 -#define CMDSIZE_TABLE 0x30 - -#define DISC_DSB 0x32 - -#define CMDSIZE_TABLE_TAIL 0x34 - -#define MWI_RESIDUAL 0x38 - -#define NEXT_QUEUED_SCB 0x39 - -#define MSG_OUT 0x3a - -#define DMAPARAMS 0x3b -#define PRELOADEN 0x80 -#define WIDEODD 0x40 -#define SCSIEN 0x20 -#define SDMAEN 0x10 -#define SDMAENACK 0x10 -#define HDMAEN 0x08 -#define HDMAENACK 0x08 -#define DIRECTION 0x04 -#define FIFOFLUSH 0x02 -#define FIFORESET 0x01 - -#define SEQ_FLAGS 0x3c -#define IDENTIFY_SEEN 0x80 -#define TARGET_CMD_IS_TAGGED 0x40 -#define DPHASE 0x20 -#define TARG_CMD_PENDING 0x10 -#define CMDPHASE_PENDING 0x08 -#define DPHASE_PENDING 0x04 -#define SPHASE_PENDING 0x02 -#define NO_DISCONNECT 0x01 - -#define SAVED_SCSIID 0x3d - -#define SAVED_LUN 0x3e - -#define LASTPHASE 0x3f -#define P_MESGIN 0xe0 -#define PHASE_MASK 0xe0 -#define P_STATUS 0xc0 -#define P_MESGOUT 0xa0 -#define P_COMMAND 0x80 -#define CDI 0x80 -#define P_DATAIN 0x40 -#define IOI 0x40 -#define MSGI 0x20 -#define P_BUSFREE 0x01 -#define P_DATAOUT 0x00 - -#define WAITING_SCBH 0x40 - -#define DISCONNECTED_SCBH 0x41 - -#define FREE_SCBH 0x42 - -#define COMPLETE_SCBH 0x43 - -#define HSCB_ADDR 0x44 - -#define SHARED_DATA_ADDR 0x48 - -#define KERNEL_QINPOS 0x4c - -#define QINPOS 0x4d - -#define QOUTPOS 0x4e - -#define KERNEL_TQINPOS 0x4f - -#define TQINPOS 0x50 - -#define ARG_1 0x51 -#define RETURN_1 0x51 -#define SEND_MSG 0x80 -#define SEND_SENSE 0x40 -#define SEND_REJ 0x20 -#define MSGOUT_PHASEMIS 0x10 -#define EXIT_MSG_LOOP 0x08 -#define CONT_MSG_LOOP 0x04 -#define CONT_TARG_SESSION 0x02 - -#define ARG_2 0x52 -#define RETURN_2 0x52 - -#define LAST_MSG 0x53 - -#define SCSISEQ_TEMPLATE 0x54 -#define ENSELO 0x40 -#define ENSELI 0x20 -#define ENRSELI 0x10 -#define ENAUTOATNO 0x08 -#define ENAUTOATNI 0x04 -#define ENAUTOATNP 0x02 - -#define DATA_COUNT_ODD 0x55 - -#define HA_274_BIOSGLOBAL 0x56 -#define INITIATOR_TAG 0x56 -#define HA_274_EXTENDED_TRANS 0x01 - -#define SEQ_FLAGS2 0x57 -#define TARGET_MSG_PENDING 0x02 -#define SCB_DMA 0x01 - -#define SCSICONF 0x5a -#define TERM_ENB 0x80 -#define RESET_SCSI 0x40 -#define ENSPCHK 0x20 -#define HWSCSIID 0x0f -#define HSCSIID 0x07 - -#define INTDEF 0x5c -#define EDGE_TRIG 0x80 -#define VECTOR 0x0f - -#define HOSTCONF 0x5d - -#define HA_274_BIOSCTRL 0x5f -#define BIOSDISABLED 0x30 -#define BIOSMODE 0x30 -#define CHANNEL_B_PRIMARY 0x08 - -#define SEQCTL 0x60 -#define PERRORDIS 0x80 -#define PAUSEDIS 0x40 -#define FAILDIS 0x20 -#define FASTMODE 0x10 -#define BRKADRINTEN 0x08 -#define STEP 0x04 -#define SEQRESET 0x02 -#define LOADRAM 0x01 - -#define SEQRAM 0x61 - -#define SEQADDR0 0x62 - -#define SEQADDR1 0x63 -#define SEQADDR1_MASK 0x01 - -#define ACCUM 0x64 - -#define SINDEX 0x65 - -#define DINDEX 0x66 - -#define ALLONES 0x69 - -#define ALLZEROS 0x6a - -#define NONE 0x6a - -#define FLAGS 0x6b -#define ZERO 0x02 -#define CARRY 0x01 - -#define SINDIR 0x6c - -#define DINDIR 0x6d - -#define FUNCTION1 0x6e - -#define STACK 0x6f - -#define TARG_OFFSET 0x70 - -#define SRAM_BASE 0x70 - -#define BCTL 0x84 -#define ACE 0x08 -#define ENABLE 0x01 - -#define DSCOMMAND0 0x84 -#define CACHETHEN 0x80 -#define DPARCKEN 0x40 -#define MPARCKEN 0x20 -#define EXTREQLCK 0x10 -#define INTSCBRAMSEL 0x08 -#define RAMPS 0x04 -#define USCBSIZE32 0x02 -#define CIOPARCKEN 0x01 - -#define BUSTIME 0x85 -#define BOFF 0xf0 -#define BON 0x0f - -#define DSCOMMAND1 0x85 -#define DSLATT 0xfc -#define HADDLDSEL1 0x02 -#define HADDLDSEL0 0x01 - -#define BUSSPD 0x86 -#define DFTHRSH 0xc0 -#define DFTHRSH_75 0x80 -#define STBOFF 0x38 -#define STBON 0x07 - -#define HS_MAILBOX 0x86 -#define HOST_MAILBOX 0xf0 -#define HOST_TQINPOS 0x80 -#define SEQ_MAILBOX 0x0f - -#define DSPCISTATUS 0x86 -#define DFTHRSH_100 0xc0 - -#define HCNTRL 0x87 -#define POWRDN 0x40 -#define SWINT 0x10 -#define IRQMS 0x08 -#define PAUSE 0x04 -#define INTEN 0x02 -#define CHIPRST 0x01 -#define CHIPRSTACK 0x01 - -#define HADDR 0x88 - -#define HCNT 0x8c - -#define SCBPTR 0x90 - -#define INTSTAT 0x91 -#define SEQINT_MASK 0xf1 -#define OUT_OF_RANGE 0xe1 -#define NO_FREE_SCB 0xd1 -#define SCB_MISMATCH 0xc1 -#define MISSED_BUSFREE 0xb1 -#define MKMSG_FAILED 0xa1 -#define DATA_OVERRUN 0x91 -#define PERR_DETECTED 0x81 -#define BAD_STATUS 0x71 -#define HOST_MSG_LOOP 0x61 -#define PDATA_REINIT 0x51 -#define IGN_WIDE_RES 0x41 -#define NO_MATCH 0x31 -#define NO_IDENT 0x21 -#define SEND_REJECT 0x11 -#define INT_PEND 0x0f -#define BRKADRINT 0x08 -#define SCSIINT 0x04 -#define CMDCMPLT 0x02 -#define BAD_PHASE 0x01 -#define SEQINT 0x01 - -#define CLRINT 0x92 -#define CLRPARERR 0x10 -#define CLRBRKADRINT 0x08 -#define CLRSCSIINT 0x04 -#define CLRCMDINT 0x02 -#define CLRSEQINT 0x01 - -#define ERROR 0x92 -#define CIOPARERR 0x80 -#define PCIERRSTAT 0x40 -#define MPARERR 0x20 -#define DPARERR 0x10 -#define SQPARERR 0x08 -#define ILLOPCODE 0x04 -#define ILLSADDR 0x02 -#define ILLHADDR 0x01 - -#define DFCNTRL 0x93 - -#define DFSTATUS 0x94 -#define PRELOAD_AVAIL 0x80 -#define DFCACHETH 0x40 -#define FIFOQWDEMP 0x20 -#define MREQPEND 0x10 -#define HDONE 0x08 -#define DFTHRESH 0x04 -#define FIFOFULL 0x02 -#define FIFOEMP 0x01 - -#define DFWADDR 0x95 - -#define DFRADDR 0x97 - -#define DFDAT 0x99 - -#define SCBCNT 0x9a -#define SCBAUTO 0x80 -#define SCBCNT_MASK 0x1f - -#define QINFIFO 0x9b - -#define QINCNT 0x9c - -#define QOUTFIFO 0x9d - -#define CRCCONTROL1 0x9d -#define CRCONSEEN 0x80 -#define CRCVALCHKEN 0x40 -#define CRCENDCHKEN 0x20 -#define CRCREQCHKEN 0x10 -#define TARGCRCENDEN 0x08 -#define TARGCRCCNTEN 0x04 - -#define QOUTCNT 0x9e - -#define SCSIPHASE 0x9e -#define STATUS_PHASE 0x20 -#define COMMAND_PHASE 0x10 -#define MSG_IN_PHASE 0x08 -#define MSG_OUT_PHASE 0x04 -#define DATA_PHASE_MASK 0x03 -#define DATA_IN_PHASE 0x02 -#define DATA_OUT_PHASE 0x01 - -#define SFUNCT 0x9f -#define ALT_MODE 0x80 - -#define SCB_BASE 0xa0 - -#define SCB_CDB_PTR 0xa0 -#define SCB_RESIDUAL_DATACNT 0xa0 -#define SCB_CDB_STORE 0xa0 - -#define SCB_RESIDUAL_SGPTR 0xa4 - -#define SCB_SCSI_STATUS 0xa8 - -#define SCB_TARGET_PHASES 0xa9 - -#define SCB_TARGET_DATA_DIR 0xaa - -#define SCB_TARGET_ITAG 0xab - -#define SCB_DATAPTR 0xac - -#define SCB_DATACNT 0xb0 -#define SG_LAST_SEG 0x80 -#define SG_HIGH_ADDR_BITS 0x7f - -#define SCB_SGPTR 0xb4 -#define SG_RESID_VALID 0x04 -#define SG_FULL_RESID 0x02 -#define SG_LIST_NULL 0x01 - -#define SCB_CONTROL 0xb8 -#define TARGET_SCB 0x80 -#define DISCENB 0x40 -#define TAG_ENB 0x20 -#define MK_MESSAGE 0x10 -#define ULTRAENB 0x08 -#define DISCONNECTED 0x04 -#define SCB_TAG_TYPE 0x03 - -#define SCB_SCSIID 0xb9 -#define TID 0xf0 -#define TWIN_CHNLB 0x80 -#define TWIN_TID 0x70 -#define OID 0x0f - -#define SCB_LUN 0xba -#define LID 0xff - -#define SCB_TAG 0xbb - -#define SCB_CDB_LEN 0xbc - -#define SCB_SCSIRATE 0xbd - -#define SCB_SCSIOFFSET 0xbe - -#define SCB_NEXT 0xbf - -#define SCB_64_SPARE 0xc0 - -#define SEECTL_2840 0xc0 -#define CS_2840 0x04 -#define CK_2840 0x02 -#define DO_2840 0x01 - -#define STATUS_2840 0xc1 -#define EEPROM_TF 0x80 -#define BIOS_SEL 0x60 -#define ADSEL 0x1e -#define DI_2840 0x01 - -#define SCB_64_BTT 0xd0 - -#define CCHADDR 0xe0 - -#define CCHCNT 0xe8 - -#define CCSGRAM 0xe9 - -#define CCSGADDR 0xea - -#define CCSGCTL 0xeb -#define CCSGDONE 0x80 -#define CCSGEN 0x08 -#define SG_FETCH_NEEDED 0x02 -#define CCSGRESET 0x01 - -#define CCSCBRAM 0xec - -#define CCSCBADDR 0xed - -#define CCSCBCTL 0xee -#define CCSCBDONE 0x80 -#define ARRDONE 0x40 -#define CCARREN 0x10 -#define CCSCBEN 0x08 -#define CCSCBDIR 0x04 -#define CCSCBRESET 0x01 - -#define CCSCBCNT 0xef - -#define SCBBADDR 0xf0 - -#define CCSCBPTR 0xf1 - -#define HNSCB_QOFF 0xf4 - -#define SNSCB_QOFF 0xf6 - -#define SDSCB_QOFF 0xf8 - -#define QOFF_CTLSTA 0xfa -#define SCB_AVAIL 0x40 -#define SNSCB_ROLLOVER 0x20 -#define SDSCB_ROLLOVER 0x10 -#define SCB_QSIZE 0x07 -#define SCB_QSIZE_256 0x06 - -#define DFF_THRSH 0xfb -#define WR_DFTHRSH 0x70 -#define WR_DFTHRSH_MAX 0x70 -#define WR_DFTHRSH_90 0x60 -#define WR_DFTHRSH_85 0x50 -#define WR_DFTHRSH_75 0x40 -#define WR_DFTHRSH_63 0x30 -#define WR_DFTHRSH_50 0x20 -#define WR_DFTHRSH_25 0x10 -#define RD_DFTHRSH 0x07 -#define RD_DFTHRSH_MAX 0x07 -#define RD_DFTHRSH_90 0x06 -#define RD_DFTHRSH_85 0x05 -#define RD_DFTHRSH_75 0x04 -#define RD_DFTHRSH_63 0x03 -#define RD_DFTHRSH_50 0x02 -#define RD_DFTHRSH_25 0x01 -#define RD_DFTHRSH_MIN 0x00 -#define WR_DFTHRSH_MIN 0x00 - -#define SG_CACHE_SHADOW 0xfc -#define SG_ADDR_MASK 0xf8 -#define ODD_SEG 0x04 -#define LAST_SEG 0x02 -#define LAST_SEG_DONE 0x01 - -#define SG_CACHE_PRE 0xfc - - -#define MAX_OFFSET_ULTRA2 0x7f -#define MAX_OFFSET_16BIT 0x08 -#define BUS_8_BIT 0x00 -#define TARGET_CMD_CMPLT 0xfe -#define STATUS_QUEUE_FULL 0x28 -#define STATUS_BUSY 0x08 -#define MAX_OFFSET_8BIT 0x0f -#define BUS_32_BIT 0x02 -#define CCSGADDR_MAX 0x80 -#define TID_SHIFT 0x04 -#define SCB_DOWNLOAD_SIZE_64 0x30 -#define HOST_MAILBOX_SHIFT 0x04 -#define CMD_GROUP_CODE_SHIFT 0x05 -#define CCSGRAM_MAXSEGS 0x10 -#define SCB_LIST_NULL 0xff -#define SG_SIZEOF 0x08 -#define SCB_DOWNLOAD_SIZE 0x20 -#define SEQ_MAILBOX_SHIFT 0x00 -#define TARGET_DATA_IN 0x01 -#define HOST_MSG 0xff -#define BUS_16_BIT 0x01 -#define SCB_UPLOAD_SIZE 0x20 - - -/* Downloaded Constant Definitions */ -#define INVERTED_CACHESIZE_MASK 0x03 -#define SG_PREFETCH_ADDR_MASK 0x06 -#define SG_PREFETCH_ALIGN_MASK 0x05 -#define QOUTFIFO_OFFSET 0x00 -#define SG_PREFETCH_CNT 0x04 -#define CACHESIZE_MASK 0x02 -#define QINFIFO_OFFSET 0x01 -#define DOWNLOAD_CONST_COUNT 0x07 - - -/* Exported Labels */ diff --git a/xen/drivers/scsi/aic7xxx/aic7xxx_seq.h b/xen/drivers/scsi/aic7xxx/aic7xxx_seq.h deleted file mode 100644 index a31de71a1b..0000000000 --- a/xen/drivers/scsi/aic7xxx/aic7xxx_seq.h +++ /dev/null @@ -1,1301 +0,0 @@ -/* - * DO NOT EDIT - This file is automatically generated - * from the following source files: - * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#43 $ - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#30 $ - */ -static uint8_t seqprog[] = { - 0xb2, 0x00, 0x00, 0x08, - 0xf7, 0x11, 0x22, 0x08, - 0x00, 0x65, 0xe4, 0x59, - 0xf7, 0x01, 0x02, 0x08, - 0xff, 0x6a, 0x24, 0x08, - 0x40, 0x00, 0x40, 0x68, - 0x08, 0x1f, 0x3e, 0x10, - 0x40, 0x00, 0x40, 0x68, - 0xff, 0x40, 0x3c, 0x60, - 0x08, 0x1f, 0x3e, 0x10, - 0x60, 0x0b, 0x42, 0x68, - 0x40, 0xfa, 0x12, 0x78, - 0x01, 0x4d, 0xc8, 0x30, - 0x00, 0x4c, 0x12, 0x70, - 0x01, 0x39, 0xa2, 0x30, - 0x00, 0x6a, 0xb6, 0x5e, - 0x01, 0x51, 0x20, 0x31, - 0x01, 0x57, 0xae, 0x00, - 0x0d, 0x6a, 0x76, 0x00, - 0x00, 0x51, 0x08, 0x5e, - 0x01, 0x51, 0xc8, 0x30, - 0x00, 0x39, 0xc8, 0x60, - 0x00, 0xbb, 0x30, 0x70, - 0xc1, 0x6a, 0xce, 0x5e, - 0x01, 0xbf, 0x72, 0x30, - 0x01, 0x40, 0x7e, 0x31, - 0x01, 0x90, 0x80, 0x30, - 0x01, 0xf6, 0xd4, 0x30, - 0x01, 0x4d, 0x9a, 0x18, - 0xfe, 0x57, 0xae, 0x08, - 0x01, 0x40, 0x20, 0x31, - 0x00, 0x65, 0xcc, 0x58, - 0x60, 0x0b, 0x40, 0x78, - 0x08, 0x6a, 0x18, 0x00, - 0x08, 0x11, 0x22, 0x00, - 0x60, 0x0b, 0x00, 0x78, - 0x40, 0x0b, 0xfc, 0x68, - 0x80, 0x0b, 0xb6, 0x78, - 0x20, 0x6a, 0x16, 0x00, - 0xa4, 0x6a, 0x06, 0x00, - 0x08, 0x3c, 0x78, 0x00, - 0x01, 0x50, 0xc8, 0x30, - 0xe0, 0x6a, 0xcc, 0x00, - 0x48, 0x6a, 0xf2, 0x5d, - 0x01, 0x6a, 0xdc, 0x01, - 0x88, 0x6a, 0xcc, 0x00, - 0x48, 0x6a, 0xf2, 0x5d, - 0x01, 0x6a, 0x26, 0x01, - 0xf0, 0x19, 0x7a, 0x08, - 0x0f, 0x18, 0xc8, 0x08, - 0x0f, 0x0f, 0xc8, 0x08, - 0x0f, 0x05, 0xc8, 0x08, - 0x00, 0x3d, 0x7a, 0x00, - 0x08, 0x1f, 0x6e, 0x78, - 0x80, 0x3d, 0x7a, 0x00, - 0x01, 0x3d, 0xd8, 0x31, - 0x01, 0x3d, 0x32, 0x31, - 0x10, 0x03, 0x48, 0x79, - 0x00, 0x65, 0xf4, 0x58, - 0x80, 0x66, 0xae, 0x78, - 0x01, 0x66, 0xd8, 0x31, - 0x01, 0x66, 0x32, 0x31, - 0x3f, 0x66, 0x7c, 0x08, - 0x40, 0x66, 0x82, 0x68, - 0x01, 0x3c, 0x78, 0x00, - 0x10, 0x03, 0x9e, 0x78, - 0x00, 0x65, 0xf4, 0x58, - 0xe0, 0x66, 0xc8, 0x18, - 0x00, 0x65, 0xaa, 0x50, - 0xdd, 0x66, 0xc8, 0x18, - 0x00, 0x65, 0xaa, 0x48, - 0x01, 0x66, 0xd8, 0x31, - 0x01, 0x66, 0x32, 0x31, - 0x10, 0x03, 0x48, 0x79, - 0x00, 0x65, 0xf4, 0x58, - 0x01, 0x66, 0xd8, 0x31, - 0x01, 0x66, 0x32, 0x31, - 0x01, 0x66, 0xac, 0x30, - 0x40, 0x3c, 0x78, 0x00, - 0xff, 0x6a, 0xd8, 0x01, - 0xff, 0x6a, 0x32, 0x01, - 0x90, 0x3c, 0x78, 0x00, - 0x02, 0x57, 0x3c, 0x69, - 0x10, 0x03, 0x3a, 0x69, - 0x00, 0x65, 0x1e, 0x41, - 0x02, 0x57, 0xae, 0x00, - 0x00, 0x65, 0x9e, 0x40, - 0x61, 0x6a, 0xce, 0x5e, - 0x08, 0x51, 0x1e, 0x71, - 0x02, 0x0b, 0xb2, 0x78, - 0x00, 0x65, 0xae, 0x40, - 0x1a, 0x01, 0x02, 0x00, - 0xf0, 0x19, 0x7a, 0x08, - 0x0f, 0x0f, 0xc8, 0x08, - 0x0f, 0x05, 0xc8, 0x08, - 0x00, 0x3d, 0x7a, 0x00, - 0x08, 0x1f, 0xc4, 0x78, - 0x80, 0x3d, 0x7a, 0x00, - 0x20, 0x6a, 0x16, 0x00, - 0x00, 0x65, 0xc4, 0x41, - 0x00, 0x65, 0xa8, 0x5e, - 0x00, 0x65, 0x12, 0x40, - 0x20, 0x11, 0xd2, 0x68, - 0x20, 0x6a, 0x18, 0x00, - 0x20, 0x11, 0x22, 0x00, - 0xf7, 0x1f, 0xca, 0x08, - 0x80, 0xb9, 0xd8, 0x78, - 0x08, 0x65, 0xca, 0x00, - 0x01, 0x65, 0x3e, 0x30, - 0x01, 0xb9, 0x1e, 0x30, - 0x7f, 0xb9, 0x0a, 0x08, - 0x01, 0xb9, 0x0a, 0x30, - 0x01, 0x54, 0xca, 0x30, - 0x80, 0xb8, 0xe6, 0x78, - 0x80, 0x65, 0xca, 0x00, - 0x01, 0x65, 0x00, 0x34, - 0x01, 0x54, 0x00, 0x34, - 0x1a, 0x01, 0x02, 0x00, - 0x08, 0xb8, 0xf0, 0x78, - 0x20, 0x01, 0x02, 0x00, - 0x02, 0xbd, 0x08, 0x34, - 0x01, 0xbd, 0x08, 0x34, - 0x08, 0x01, 0x02, 0x00, - 0x02, 0x0b, 0xf6, 0x78, - 0xf7, 0x01, 0x02, 0x08, - 0x01, 0x06, 0xcc, 0x34, - 0xb2, 0x00, 0x00, 0x08, - 0x01, 0x40, 0x20, 0x31, - 0x01, 0xbf, 0x80, 0x30, - 0x01, 0xb9, 0x7a, 0x30, - 0x01, 0xba, 0x7c, 0x30, - 0x00, 0x65, 0xea, 0x58, - 0x80, 0x0b, 0xbe, 0x79, - 0xe4, 0x6a, 0x64, 0x5d, - 0x40, 0x6a, 0x16, 0x00, - 0x80, 0xba, 0x7a, 0x5d, - 0x20, 0xb8, 0x16, 0x79, - 0x20, 0x6a, 0x7a, 0x5d, - 0x00, 0xab, 0x7a, 0x5d, - 0x01, 0xa9, 0x78, 0x30, - 0x10, 0xb8, 0x1e, 0x79, - 0xe4, 0x6a, 0x64, 0x5d, - 0x00, 0x65, 0xae, 0x40, - 0x10, 0x03, 0x38, 0x69, - 0x08, 0x3c, 0x54, 0x69, - 0x04, 0x3c, 0x8c, 0x69, - 0x02, 0x3c, 0x92, 0x69, - 0x01, 0x3c, 0x3e, 0x79, - 0x01, 0x6a, 0xa2, 0x30, - 0x00, 0x65, 0x9e, 0x59, - 0x04, 0x51, 0x2c, 0x61, - 0x00, 0x6a, 0xb6, 0x5e, - 0x0d, 0x6a, 0x76, 0x00, - 0x00, 0xbb, 0x08, 0x5e, - 0x00, 0x65, 0xec, 0x58, - 0x00, 0x65, 0x16, 0x41, - 0xa4, 0x6a, 0x06, 0x00, - 0x00, 0x65, 0xf4, 0x58, - 0x00, 0x65, 0xae, 0x40, - 0xe4, 0x6a, 0x64, 0x5d, - 0x20, 0x3c, 0x44, 0x79, - 0x02, 0x6a, 0x7a, 0x5d, - 0x04, 0x6a, 0x7a, 0x5d, - 0x01, 0x03, 0x46, 0x69, - 0xf7, 0x11, 0x22, 0x08, - 0xff, 0x6a, 0x24, 0x08, - 0xff, 0x6a, 0x06, 0x08, - 0x01, 0x6a, 0x7e, 0x00, - 0x00, 0x65, 0x9e, 0x59, - 0x00, 0x65, 0x04, 0x40, - 0x80, 0x86, 0xc8, 0x08, - 0x01, 0x4f, 0xc8, 0x30, - 0x00, 0x50, 0x66, 0x61, - 0xc4, 0x6a, 0x64, 0x5d, - 0x40, 0x3c, 0x62, 0x79, - 0x28, 0x6a, 0x7a, 0x5d, - 0x00, 0x65, 0x46, 0x41, - 0x08, 0x6a, 0x7a, 0x5d, - 0x00, 0x65, 0x46, 0x41, - 0x84, 0x6a, 0x64, 0x5d, - 0x00, 0x65, 0xf4, 0x58, - 0x01, 0x66, 0xc8, 0x30, - 0x01, 0x64, 0xd8, 0x31, - 0x01, 0x64, 0x32, 0x31, - 0x5b, 0x64, 0xc8, 0x28, - 0x30, 0x64, 0xca, 0x18, - 0x01, 0x6c, 0xc8, 0x30, - 0xff, 0x64, 0x88, 0x79, - 0x08, 0x01, 0x02, 0x00, - 0x02, 0x0b, 0x7a, 0x79, - 0x01, 0x64, 0x80, 0x61, - 0xf7, 0x01, 0x02, 0x08, - 0x01, 0x06, 0xd8, 0x31, - 0x01, 0x06, 0x32, 0x31, - 0xff, 0x64, 0xc8, 0x18, - 0xff, 0x64, 0x7a, 0x69, - 0xf7, 0x3c, 0x78, 0x08, - 0x00, 0x65, 0x1e, 0x41, - 0x40, 0xaa, 0x7e, 0x10, - 0x04, 0xaa, 0x64, 0x5d, - 0x00, 0x65, 0x56, 0x42, - 0xc4, 0x6a, 0x64, 0x5d, - 0xc0, 0x6a, 0x7e, 0x00, - 0x00, 0xa8, 0x7a, 0x5d, - 0xe4, 0x6a, 0x06, 0x00, - 0x00, 0x6a, 0x7a, 0x5d, - 0x00, 0x65, 0x46, 0x41, - 0x10, 0x3c, 0xa2, 0x69, - 0x00, 0xbb, 0x84, 0x44, - 0x18, 0x6a, 0xda, 0x01, - 0x01, 0x69, 0xd8, 0x31, - 0x1c, 0x6a, 0xd0, 0x01, - 0x09, 0xee, 0xdc, 0x01, - 0x80, 0xee, 0xaa, 0x79, - 0xff, 0x6a, 0xdc, 0x09, - 0x01, 0x93, 0x26, 0x01, - 0x03, 0x6a, 0x2a, 0x01, - 0x01, 0x69, 0x32, 0x31, - 0x1c, 0x6a, 0xd6, 0x5d, - 0x0a, 0x93, 0x26, 0x01, - 0x00, 0x65, 0x9e, 0x5e, - 0x01, 0x50, 0xa0, 0x18, - 0x02, 0x6a, 0x22, 0x05, - 0x80, 0x6a, 0x74, 0x00, - 0x80, 0x3c, 0x78, 0x00, - 0x40, 0x6a, 0x16, 0x00, - 0x00, 0x65, 0xce, 0x5d, - 0x01, 0x3f, 0xc8, 0x30, - 0xbf, 0x64, 0x56, 0x7a, - 0x80, 0x64, 0xaa, 0x73, - 0xa0, 0x64, 0x08, 0x74, - 0xc0, 0x64, 0xfc, 0x73, - 0xe0, 0x64, 0x38, 0x74, - 0x01, 0x6a, 0xce, 0x5e, - 0x00, 0x65, 0xc4, 0x41, - 0xf7, 0x11, 0x22, 0x08, - 0x01, 0x06, 0xd4, 0x30, - 0xff, 0x6a, 0x24, 0x08, - 0xf7, 0x01, 0x02, 0x08, - 0x09, 0x0c, 0xde, 0x79, - 0x08, 0x0c, 0x04, 0x68, - 0xb1, 0x6a, 0xce, 0x5e, - 0xff, 0x6a, 0x26, 0x09, - 0x12, 0x01, 0x02, 0x00, - 0x02, 0x6a, 0x08, 0x30, - 0xff, 0x6a, 0x08, 0x08, - 0xdf, 0x01, 0x02, 0x08, - 0x01, 0x6a, 0x7e, 0x00, - 0xff, 0x6a, 0x78, 0x0c, - 0xff, 0x6a, 0xc8, 0x08, - 0x08, 0xa4, 0x48, 0x19, - 0x00, 0xa5, 0x4a, 0x21, - 0x00, 0xa6, 0x4c, 0x21, - 0x00, 0xa7, 0x4e, 0x25, - 0x08, 0xeb, 0xd2, 0x7e, - 0x80, 0xeb, 0xfe, 0x79, - 0xff, 0x6a, 0xd6, 0x09, - 0x08, 0xeb, 0x02, 0x6a, - 0xff, 0x6a, 0xd4, 0x0c, - 0x80, 0xa3, 0xd2, 0x6e, - 0x88, 0xeb, 0x18, 0x72, - 0x08, 0xeb, 0xd2, 0x6e, - 0x04, 0xea, 0x1c, 0xe2, - 0x08, 0xee, 0xd2, 0x6e, - 0x04, 0x6a, 0xd0, 0x81, - 0x05, 0xa4, 0xc0, 0x89, - 0x03, 0xa5, 0xc2, 0x31, - 0x09, 0x6a, 0xd6, 0x05, - 0x00, 0x65, 0x00, 0x5a, - 0x06, 0xa4, 0xd4, 0x89, - 0x80, 0x94, 0xd2, 0x7e, - 0x07, 0xe9, 0x10, 0x31, - 0x01, 0x8c, 0x24, 0x7a, - 0x01, 0x55, 0xaa, 0x10, - 0x01, 0xe9, 0x46, 0x31, - 0x00, 0xa3, 0xb0, 0x5e, - 0x00, 0x65, 0xf2, 0x59, - 0x01, 0xa4, 0xca, 0x30, - 0x01, 0x55, 0x30, 0x7a, - 0x04, 0x65, 0xca, 0x00, - 0x80, 0xa3, 0x34, 0x7a, - 0x02, 0x65, 0xca, 0x00, - 0x01, 0x65, 0xf8, 0x31, - 0x80, 0x93, 0x26, 0x01, - 0xff, 0x6a, 0xd4, 0x0c, - 0x01, 0x8c, 0xc8, 0x30, - 0x00, 0x88, 0xc8, 0x18, - 0x02, 0x64, 0xc8, 0x88, - 0xff, 0x64, 0xd2, 0x7e, - 0xff, 0x8d, 0x4a, 0x6a, - 0xff, 0x8e, 0x4a, 0x6a, - 0x03, 0x8c, 0xd4, 0x98, - 0x00, 0x65, 0xd2, 0x56, - 0x01, 0x64, 0x70, 0x30, - 0xff, 0x64, 0xc8, 0x10, - 0x01, 0x64, 0xc8, 0x18, - 0x00, 0x8c, 0x18, 0x19, - 0xff, 0x8d, 0x1a, 0x21, - 0xff, 0x8e, 0x1c, 0x25, - 0x80, 0x3c, 0x5a, 0x6a, - 0x21, 0x6a, 0xce, 0x46, - 0xa8, 0x6a, 0x76, 0x00, - 0x79, 0x6a, 0x76, 0x00, - 0x40, 0x3f, 0x62, 0x6a, - 0x04, 0x3b, 0x76, 0x00, - 0x04, 0x6a, 0xd4, 0x81, - 0x20, 0x3c, 0x6a, 0x7a, - 0x51, 0x6a, 0xce, 0x5e, - 0x00, 0x65, 0x84, 0x42, - 0x20, 0x3c, 0x78, 0x00, - 0x00, 0xb3, 0xb0, 0x5e, - 0x07, 0xac, 0x10, 0x31, - 0x05, 0xb3, 0x46, 0x31, - 0x88, 0x6a, 0xcc, 0x00, - 0xac, 0x6a, 0xe4, 0x5d, - 0xa3, 0x6a, 0xcc, 0x00, - 0xb3, 0x6a, 0xe8, 0x5d, - 0x00, 0x65, 0x3a, 0x5a, - 0xfd, 0xa4, 0x48, 0x09, - 0x01, 0x8c, 0xaa, 0x08, - 0x03, 0x8c, 0x10, 0x30, - 0x00, 0x65, 0xdc, 0x5d, - 0x01, 0xa4, 0x96, 0x7a, - 0x04, 0x3b, 0x76, 0x08, - 0x01, 0x3b, 0x26, 0x31, - 0x80, 0x02, 0x04, 0x00, - 0x10, 0x0c, 0x8c, 0x7a, - 0x03, 0x9e, 0x8e, 0x6a, - 0x7f, 0x02, 0x04, 0x08, - 0x91, 0x6a, 0xce, 0x5e, - 0x00, 0x65, 0xc4, 0x41, - 0x01, 0xa4, 0xca, 0x30, - 0x80, 0xa3, 0x9c, 0x7a, - 0x02, 0x65, 0xca, 0x00, - 0x01, 0x55, 0xa0, 0x7a, - 0x04, 0x65, 0xca, 0x00, - 0x01, 0x65, 0xf8, 0x31, - 0x01, 0x3b, 0x26, 0x31, - 0x00, 0x65, 0x06, 0x5a, - 0x01, 0xfc, 0xae, 0x6a, - 0x80, 0x0b, 0xa4, 0x6a, - 0x10, 0x0c, 0xa4, 0x7a, - 0x20, 0x93, 0xa4, 0x6a, - 0x02, 0x93, 0x26, 0x01, - 0x02, 0xfc, 0xb8, 0x7a, - 0x40, 0x0d, 0xd2, 0x6a, - 0x01, 0xa4, 0x48, 0x01, - 0x00, 0x65, 0xd2, 0x42, - 0x40, 0x0d, 0xbe, 0x6a, - 0x00, 0x65, 0x06, 0x5a, - 0x00, 0x65, 0xb0, 0x42, - 0x80, 0xfc, 0xc8, 0x7a, - 0x80, 0xa4, 0xc8, 0x6a, - 0xff, 0xa5, 0x4a, 0x19, - 0xff, 0xa6, 0x4c, 0x21, - 0xff, 0xa7, 0x4e, 0x21, - 0xf8, 0xfc, 0x48, 0x09, - 0xff, 0x6a, 0xaa, 0x08, - 0x04, 0xfc, 0xd0, 0x7a, - 0x01, 0x55, 0xaa, 0x00, - 0xff, 0x6a, 0x46, 0x09, - 0x04, 0x3b, 0xea, 0x6a, - 0x02, 0x93, 0x26, 0x01, - 0x01, 0x94, 0xd4, 0x7a, - 0x01, 0x94, 0xd4, 0x7a, - 0x01, 0x94, 0xd4, 0x7a, - 0x01, 0x94, 0xd4, 0x7a, - 0x01, 0x94, 0xd4, 0x7a, - 0x01, 0xa4, 0xe8, 0x7a, - 0x01, 0xfc, 0xe2, 0x7a, - 0x01, 0x94, 0xea, 0x6a, - 0x00, 0x65, 0x84, 0x42, - 0x01, 0x94, 0xe8, 0x7a, - 0x10, 0x94, 0xea, 0x6a, - 0xd7, 0x93, 0x26, 0x09, - 0x28, 0x93, 0xee, 0x6a, - 0x01, 0x85, 0x0a, 0x01, - 0x02, 0xfc, 0xf6, 0x6a, - 0x01, 0x14, 0x46, 0x31, - 0xff, 0x6a, 0x10, 0x09, - 0xfe, 0x85, 0x0a, 0x09, - 0xff, 0x38, 0x04, 0x6b, - 0x80, 0xa3, 0x04, 0x7b, - 0x80, 0x0b, 0x02, 0x7b, - 0x04, 0x3b, 0x04, 0x7b, - 0xbf, 0x3b, 0x76, 0x08, - 0x01, 0x3b, 0x26, 0x31, - 0x00, 0x65, 0x06, 0x5a, - 0x01, 0x0b, 0x12, 0x6b, - 0x10, 0x0c, 0x06, 0x7b, - 0x04, 0x93, 0x10, 0x6b, - 0x01, 0x94, 0x0e, 0x7b, - 0x10, 0x94, 0x10, 0x6b, - 0xc7, 0x93, 0x26, 0x09, - 0x01, 0x99, 0xd4, 0x30, - 0x38, 0x93, 0x14, 0x6b, - 0xff, 0x08, 0x66, 0x6b, - 0xff, 0x09, 0x66, 0x6b, - 0xff, 0x0a, 0x66, 0x6b, - 0xff, 0x38, 0x30, 0x7b, - 0x04, 0x14, 0x10, 0x31, - 0x01, 0x38, 0x18, 0x31, - 0x02, 0x6a, 0x1a, 0x31, - 0x88, 0x6a, 0xcc, 0x00, - 0x14, 0x6a, 0xea, 0x5d, - 0x00, 0x38, 0xd6, 0x5d, - 0xff, 0x6a, 0x70, 0x08, - 0x00, 0x65, 0x5c, 0x43, - 0x80, 0xa3, 0x36, 0x7b, - 0x01, 0xa4, 0x48, 0x01, - 0x00, 0x65, 0x66, 0x43, - 0x08, 0xeb, 0x3c, 0x7b, - 0x00, 0x65, 0x06, 0x5a, - 0x08, 0xeb, 0x38, 0x6b, - 0x07, 0xe9, 0x10, 0x31, - 0x01, 0xe9, 0xca, 0x30, - 0x01, 0x65, 0x46, 0x31, - 0x00, 0x6a, 0xb0, 0x5e, - 0x88, 0x6a, 0xcc, 0x00, - 0xa4, 0x6a, 0xea, 0x5d, - 0x08, 0x6a, 0xd6, 0x5d, - 0x0d, 0x93, 0x26, 0x01, - 0x00, 0x65, 0x9e, 0x5e, - 0x88, 0x6a, 0xcc, 0x00, - 0x00, 0x65, 0x80, 0x5e, - 0x01, 0x99, 0x46, 0x31, - 0x00, 0xa3, 0xb0, 0x5e, - 0x01, 0x88, 0x10, 0x31, - 0x00, 0x65, 0x3a, 0x5a, - 0x00, 0x65, 0xf2, 0x59, - 0x03, 0x8c, 0x10, 0x30, - 0x00, 0x65, 0xdc, 0x5d, - 0x01, 0x8c, 0x64, 0x7b, - 0x01, 0x55, 0xaa, 0x10, - 0x80, 0x0b, 0x84, 0x6a, - 0x80, 0x0b, 0x6e, 0x6b, - 0x01, 0x0c, 0x68, 0x7b, - 0x10, 0x0c, 0x84, 0x7a, - 0x03, 0x9e, 0x84, 0x6a, - 0x00, 0x65, 0xfc, 0x59, - 0x00, 0x6a, 0xb0, 0x5e, - 0x01, 0xa4, 0x8e, 0x6b, - 0xff, 0x38, 0x84, 0x7b, - 0x01, 0x38, 0xc8, 0x30, - 0x00, 0x08, 0x40, 0x19, - 0xff, 0x6a, 0xc8, 0x08, - 0x00, 0x09, 0x42, 0x21, - 0x00, 0x0a, 0x44, 0x21, - 0xff, 0x6a, 0x70, 0x08, - 0x00, 0x65, 0x86, 0x43, - 0x03, 0x08, 0x40, 0x31, - 0x03, 0x08, 0x40, 0x31, - 0x01, 0x08, 0x40, 0x31, - 0x01, 0x09, 0x42, 0x31, - 0x01, 0x0a, 0x44, 0x31, - 0xfd, 0xb4, 0x68, 0x09, - 0x12, 0x01, 0x02, 0x00, - 0x12, 0x01, 0x02, 0x00, - 0x04, 0x3c, 0xc4, 0x79, - 0xfb, 0x3c, 0x78, 0x08, - 0x04, 0x93, 0x1e, 0x79, - 0x01, 0x0c, 0x9a, 0x6b, - 0x01, 0x55, 0x1e, 0x79, - 0x80, 0x04, 0x1e, 0x79, - 0xe4, 0x6a, 0x64, 0x5d, - 0x23, 0x6a, 0x7a, 0x5d, - 0x01, 0x6a, 0x7a, 0x5d, - 0x00, 0x65, 0x1e, 0x41, - 0x00, 0x65, 0xc4, 0x41, - 0x80, 0x3c, 0xae, 0x6b, - 0x21, 0x6a, 0xce, 0x46, - 0x01, 0xbc, 0x18, 0x31, - 0x02, 0x6a, 0x1a, 0x31, - 0x02, 0x6a, 0xf8, 0x01, - 0x01, 0xbc, 0x10, 0x30, - 0x02, 0x6a, 0x12, 0x30, - 0x01, 0xbc, 0x10, 0x30, - 0xff, 0x6a, 0x12, 0x08, - 0xff, 0x6a, 0x14, 0x08, - 0xf3, 0xbc, 0xd4, 0x18, - 0xa0, 0x6a, 0xd4, 0x53, - 0x04, 0xa0, 0x10, 0x31, - 0xac, 0x6a, 0x26, 0x01, - 0x04, 0xa0, 0x10, 0x31, - 0x03, 0x08, 0x18, 0x31, - 0x88, 0x6a, 0xcc, 0x00, - 0xa0, 0x6a, 0xea, 0x5d, - 0x00, 0xbc, 0xd6, 0x5d, - 0x3d, 0x6a, 0x26, 0x01, - 0x00, 0x65, 0xec, 0x43, - 0xff, 0x6a, 0x10, 0x09, - 0xa4, 0x6a, 0x26, 0x01, - 0x0c, 0xa0, 0x32, 0x31, - 0x05, 0x6a, 0x26, 0x01, - 0x35, 0x6a, 0x26, 0x01, - 0x0c, 0xa0, 0x32, 0x31, - 0x36, 0x6a, 0x26, 0x01, - 0x02, 0x93, 0x26, 0x01, - 0x35, 0x6a, 0x26, 0x01, - 0x00, 0x65, 0x92, 0x5e, - 0x00, 0x65, 0x92, 0x5e, - 0x02, 0x93, 0x26, 0x01, - 0x04, 0x0b, 0xf0, 0x6b, - 0x10, 0x0c, 0xec, 0x7b, - 0x01, 0x03, 0xf0, 0x6b, - 0x20, 0x93, 0xec, 0x6b, - 0xc7, 0x93, 0x26, 0x09, - 0x38, 0x93, 0xf6, 0x6b, - 0x10, 0x01, 0x02, 0x00, - 0x00, 0x65, 0xc4, 0x41, - 0x80, 0x3c, 0x00, 0x6c, - 0x21, 0x6a, 0xce, 0x46, - 0x01, 0x06, 0x50, 0x31, - 0x00, 0x65, 0xc4, 0x41, - 0x10, 0x3f, 0x06, 0x00, - 0x10, 0x6a, 0x06, 0x00, - 0x01, 0x3a, 0xca, 0x30, - 0x80, 0x65, 0x24, 0x64, - 0x10, 0xb8, 0x48, 0x6c, - 0xc0, 0xba, 0xca, 0x00, - 0x40, 0xb8, 0x14, 0x6c, - 0xbf, 0x65, 0xca, 0x08, - 0x20, 0xb8, 0x28, 0x7c, - 0x01, 0x65, 0x0c, 0x30, - 0x00, 0x65, 0xce, 0x5d, - 0xa0, 0x3f, 0x30, 0x64, - 0x23, 0xb8, 0x0c, 0x08, - 0x00, 0x65, 0xce, 0x5d, - 0xa0, 0x3f, 0x30, 0x64, - 0x00, 0xbb, 0x28, 0x44, - 0xff, 0x65, 0x28, 0x64, - 0x00, 0x65, 0x48, 0x44, - 0x40, 0x6a, 0x18, 0x00, - 0x01, 0x65, 0x0c, 0x30, - 0x00, 0x65, 0xce, 0x5d, - 0xa0, 0x3f, 0x04, 0x74, - 0x40, 0x6a, 0x18, 0x00, - 0x01, 0x3a, 0xa6, 0x30, - 0x08, 0x6a, 0x74, 0x00, - 0x00, 0x65, 0xc4, 0x41, - 0x64, 0x6a, 0x5e, 0x5d, - 0x80, 0x64, 0xce, 0x6c, - 0x04, 0x64, 0x94, 0x74, - 0x02, 0x64, 0xa2, 0x74, - 0x00, 0x6a, 0x64, 0x74, - 0x03, 0x64, 0xc0, 0x74, - 0x23, 0x64, 0x50, 0x74, - 0x08, 0x64, 0x60, 0x74, - 0x61, 0x6a, 0xce, 0x5e, - 0x00, 0x65, 0xce, 0x5d, - 0x08, 0x51, 0xc6, 0x71, - 0x00, 0x65, 0x48, 0x44, - 0x80, 0x04, 0x5e, 0x7c, - 0x51, 0x6a, 0x54, 0x5d, - 0x01, 0x51, 0x5e, 0x64, - 0x01, 0xa4, 0x5a, 0x7c, - 0x01, 0x55, 0x60, 0x7c, - 0x41, 0x6a, 0xce, 0x5e, - 0x00, 0x65, 0x60, 0x44, - 0x07, 0x6a, 0x4a, 0x5d, - 0x01, 0x06, 0xd4, 0x30, - 0x00, 0x65, 0xc4, 0x41, - 0x10, 0xb8, 0x68, 0x7c, - 0xa1, 0x6a, 0xce, 0x5e, - 0x01, 0xb4, 0x6e, 0x6c, - 0x02, 0xb4, 0x70, 0x6c, - 0x01, 0xa4, 0x70, 0x7c, - 0xff, 0xa8, 0x80, 0x7c, - 0x04, 0xb4, 0x68, 0x01, - 0x01, 0x6a, 0x76, 0x00, - 0x00, 0xbb, 0x08, 0x5e, - 0xff, 0xa8, 0x80, 0x7c, - 0x71, 0x6a, 0xce, 0x5e, - 0x40, 0x51, 0x80, 0x64, - 0x00, 0x65, 0xa8, 0x5e, - 0x00, 0x65, 0xd6, 0x41, - 0x00, 0xbb, 0x84, 0x5c, - 0x00, 0x65, 0xd6, 0x41, - 0x00, 0x65, 0xa8, 0x5e, - 0x01, 0x65, 0xa2, 0x30, - 0x01, 0xf8, 0xc8, 0x30, - 0x01, 0x4e, 0xc8, 0x30, - 0x00, 0x6a, 0xac, 0xdd, - 0x00, 0x51, 0xbe, 0x5d, - 0x01, 0x4e, 0x9c, 0x18, - 0x02, 0x6a, 0x22, 0x05, - 0x04, 0xb8, 0x70, 0x01, - 0x00, 0x65, 0xca, 0x5e, - 0x20, 0xb8, 0xd6, 0x69, - 0x01, 0xbb, 0xa2, 0x30, - 0x01, 0xba, 0x7c, 0x30, - 0x00, 0xb9, 0xc4, 0x5c, - 0x00, 0x65, 0xd6, 0x41, - 0x01, 0x06, 0xd4, 0x30, - 0x20, 0x3c, 0xc4, 0x79, - 0x20, 0x3c, 0x60, 0x7c, - 0x01, 0xa4, 0xb0, 0x7c, - 0x01, 0xb4, 0x68, 0x01, - 0x00, 0x65, 0xc4, 0x41, - 0x00, 0x65, 0x60, 0x44, - 0x04, 0x14, 0x58, 0x31, - 0x01, 0x06, 0xd4, 0x30, - 0x08, 0xa0, 0x60, 0x31, - 0xac, 0x6a, 0xcc, 0x00, - 0x14, 0x6a, 0xea, 0x5d, - 0x01, 0x06, 0xd4, 0x30, - 0xa0, 0x6a, 0xe2, 0x5d, - 0x00, 0x65, 0xc4, 0x41, - 0xdf, 0x3c, 0x78, 0x08, - 0x00, 0x65, 0x60, 0x44, - 0x4c, 0x65, 0xcc, 0x28, - 0x01, 0x3e, 0x20, 0x31, - 0xd0, 0x66, 0xcc, 0x18, - 0x20, 0x66, 0xcc, 0x18, - 0x01, 0x51, 0xda, 0x34, - 0x4c, 0x3d, 0xca, 0x28, - 0x3f, 0x64, 0x7c, 0x08, - 0xd0, 0x65, 0xca, 0x18, - 0x01, 0x3e, 0x20, 0x31, - 0x30, 0x65, 0xd4, 0x18, - 0x00, 0x65, 0xdc, 0x4c, - 0xe1, 0x6a, 0x22, 0x01, - 0xff, 0x6a, 0xd4, 0x08, - 0x20, 0x65, 0xd4, 0x18, - 0x00, 0x65, 0xe4, 0x54, - 0xe1, 0x6a, 0x22, 0x01, - 0xff, 0x6a, 0xd4, 0x08, - 0x20, 0x65, 0xca, 0x18, - 0xe0, 0x65, 0xd4, 0x18, - 0x00, 0x65, 0xee, 0x4c, - 0xe1, 0x6a, 0x22, 0x01, - 0xff, 0x6a, 0xd4, 0x08, - 0xd0, 0x65, 0xd4, 0x18, - 0x00, 0x65, 0xf6, 0x54, - 0xe1, 0x6a, 0x22, 0x01, - 0xff, 0x6a, 0xd4, 0x08, - 0x01, 0x6c, 0xa2, 0x30, - 0xff, 0x51, 0x08, 0x75, - 0x00, 0x51, 0x84, 0x5d, - 0x01, 0x51, 0x20, 0x31, - 0x00, 0x65, 0x2a, 0x45, - 0x01, 0xba, 0xc8, 0x30, - 0x00, 0x3e, 0x2a, 0x75, - 0x00, 0x65, 0xa6, 0x5e, - 0x80, 0x3c, 0x78, 0x00, - 0x01, 0x06, 0xd4, 0x30, - 0x00, 0x65, 0xce, 0x5d, - 0x01, 0x3c, 0x78, 0x00, - 0xe0, 0x3f, 0x46, 0x65, - 0x02, 0x3c, 0x78, 0x00, - 0x20, 0x12, 0x46, 0x65, - 0x51, 0x6a, 0x54, 0x5d, - 0x00, 0x51, 0x84, 0x5d, - 0x51, 0x6a, 0x54, 0x5d, - 0x01, 0x51, 0x20, 0x31, - 0x04, 0x3c, 0x78, 0x00, - 0x01, 0xb9, 0xc8, 0x30, - 0x00, 0x3d, 0x44, 0x65, - 0x08, 0x3c, 0x78, 0x00, - 0x01, 0xba, 0xc8, 0x30, - 0x00, 0x3e, 0x44, 0x65, - 0x10, 0x3c, 0x78, 0x00, - 0x04, 0xb8, 0x44, 0x7d, - 0xfb, 0xb8, 0x70, 0x09, - 0x20, 0xb8, 0x3a, 0x6d, - 0x01, 0x90, 0xc8, 0x30, - 0xff, 0x6a, 0xa2, 0x00, - 0x00, 0x3d, 0xc4, 0x5c, - 0x01, 0x64, 0x20, 0x31, - 0x80, 0x6a, 0x78, 0x00, - 0x00, 0x65, 0xec, 0x58, - 0x10, 0xb8, 0x60, 0x7c, - 0xff, 0x6a, 0x4a, 0x5d, - 0x00, 0x65, 0x60, 0x44, - 0x00, 0x65, 0xa6, 0x5e, - 0x31, 0x6a, 0xce, 0x5e, - 0x00, 0x65, 0x60, 0x44, - 0x10, 0x3f, 0x06, 0x00, - 0x10, 0x6a, 0x06, 0x00, - 0x01, 0x65, 0x74, 0x34, - 0x81, 0x6a, 0xce, 0x5e, - 0x00, 0x65, 0x56, 0x45, - 0x01, 0x06, 0xd4, 0x30, - 0x01, 0x0c, 0x56, 0x7d, - 0x04, 0x0c, 0x50, 0x6d, - 0xe0, 0x03, 0x7e, 0x08, - 0xe0, 0x3f, 0xc4, 0x61, - 0x01, 0x65, 0xcc, 0x30, - 0x01, 0x12, 0xda, 0x34, - 0x01, 0x06, 0xd4, 0x34, - 0x01, 0x03, 0x64, 0x6d, - 0x40, 0x03, 0xcc, 0x08, - 0x01, 0x65, 0x06, 0x30, - 0x40, 0x65, 0xc8, 0x08, - 0x00, 0x66, 0x72, 0x75, - 0x40, 0x65, 0x72, 0x7d, - 0x00, 0x65, 0x72, 0x5d, - 0xff, 0x6a, 0xd4, 0x08, - 0xff, 0x6a, 0xd4, 0x08, - 0xff, 0x6a, 0xd4, 0x08, - 0xff, 0x6a, 0xd4, 0x0c, - 0x08, 0x01, 0x02, 0x00, - 0x02, 0x0b, 0x7c, 0x7d, - 0x01, 0x65, 0x0c, 0x30, - 0x02, 0x0b, 0x80, 0x7d, - 0xf7, 0x01, 0x02, 0x0c, - 0x01, 0x65, 0xc8, 0x30, - 0xff, 0x41, 0xa4, 0x75, - 0x01, 0x41, 0x20, 0x31, - 0xff, 0x6a, 0xa4, 0x00, - 0x00, 0x65, 0x94, 0x45, - 0xff, 0xbf, 0xa4, 0x75, - 0x01, 0x90, 0xa4, 0x30, - 0x01, 0xbf, 0x20, 0x31, - 0x00, 0xbb, 0x8e, 0x65, - 0xff, 0x52, 0xa2, 0x75, - 0x01, 0xbf, 0xcc, 0x30, - 0x01, 0x90, 0xca, 0x30, - 0x01, 0x52, 0x20, 0x31, - 0x01, 0x66, 0x7e, 0x31, - 0x01, 0x65, 0x20, 0x35, - 0x01, 0xbf, 0x82, 0x34, - 0x01, 0x64, 0xa2, 0x30, - 0x00, 0x6a, 0xb6, 0x5e, - 0x0d, 0x6a, 0x76, 0x00, - 0x00, 0x51, 0x08, 0x46, - 0x01, 0x65, 0xa4, 0x30, - 0xe0, 0x6a, 0xcc, 0x00, - 0x48, 0x6a, 0xfc, 0x5d, - 0x01, 0x6a, 0xd0, 0x01, - 0x01, 0x6a, 0xdc, 0x05, - 0x88, 0x6a, 0xcc, 0x00, - 0x48, 0x6a, 0xfc, 0x5d, - 0x01, 0x6a, 0xd6, 0x5d, - 0x01, 0x6a, 0x26, 0x05, - 0x01, 0x65, 0xd8, 0x31, - 0x09, 0xee, 0xdc, 0x01, - 0x80, 0xee, 0xc2, 0x7d, - 0xff, 0x6a, 0xdc, 0x0d, - 0x01, 0x65, 0x32, 0x31, - 0x0a, 0x93, 0x26, 0x01, - 0x00, 0x65, 0x9e, 0x46, - 0x81, 0x6a, 0xce, 0x5e, - 0x01, 0x0c, 0xce, 0x7d, - 0x04, 0x0c, 0xcc, 0x6d, - 0xe0, 0x03, 0x06, 0x08, - 0xe0, 0x03, 0x7e, 0x0c, - 0x01, 0x65, 0x18, 0x31, - 0xff, 0x6a, 0x1a, 0x09, - 0xff, 0x6a, 0x1c, 0x0d, - 0x01, 0x8c, 0x10, 0x30, - 0x01, 0x8d, 0x12, 0x30, - 0x01, 0x8e, 0x14, 0x34, - 0x01, 0x6c, 0xda, 0x30, - 0x01, 0x6c, 0xda, 0x30, - 0x01, 0x6c, 0xda, 0x30, - 0x01, 0x6c, 0xda, 0x30, - 0x01, 0x6c, 0xda, 0x30, - 0x01, 0x6c, 0xda, 0x30, - 0x01, 0x6c, 0xda, 0x30, - 0x01, 0x6c, 0xda, 0x34, - 0x3d, 0x64, 0xa4, 0x28, - 0x55, 0x64, 0xc8, 0x28, - 0x00, 0x65, 0xfc, 0x45, - 0x2e, 0x64, 0xa4, 0x28, - 0x66, 0x64, 0xc8, 0x28, - 0x00, 0x6c, 0xda, 0x18, - 0x01, 0x52, 0xc8, 0x30, - 0x00, 0x6c, 0xda, 0x20, - 0xff, 0x6a, 0xc8, 0x08, - 0x00, 0x6c, 0xda, 0x20, - 0x00, 0x6c, 0xda, 0x24, - 0x01, 0x65, 0xc8, 0x30, - 0xe0, 0x6a, 0xcc, 0x00, - 0x44, 0x6a, 0xf8, 0x5d, - 0x01, 0x90, 0xe2, 0x31, - 0x04, 0x3b, 0x1c, 0x7e, - 0x30, 0x6a, 0xd0, 0x01, - 0x20, 0x6a, 0xd0, 0x01, - 0x1d, 0x6a, 0xdc, 0x01, - 0xdc, 0xee, 0x18, 0x66, - 0x00, 0x65, 0x34, 0x46, - 0x20, 0x6a, 0xd0, 0x01, - 0x01, 0x6a, 0xdc, 0x01, - 0x20, 0xa0, 0xd8, 0x31, - 0x09, 0xee, 0xdc, 0x01, - 0x80, 0xee, 0x24, 0x7e, - 0x11, 0x6a, 0xdc, 0x01, - 0x50, 0xee, 0x28, 0x66, - 0x20, 0x6a, 0xd0, 0x01, - 0x09, 0x6a, 0xdc, 0x01, - 0x88, 0xee, 0x2e, 0x66, - 0x19, 0x6a, 0xdc, 0x01, - 0xd8, 0xee, 0x32, 0x66, - 0xff, 0x6a, 0xdc, 0x09, - 0x18, 0xee, 0x36, 0x6e, - 0xff, 0x6a, 0xd4, 0x0c, - 0x88, 0x6a, 0xcc, 0x00, - 0x44, 0x6a, 0xf8, 0x5d, - 0x20, 0x6a, 0xd6, 0x5d, - 0x01, 0x3b, 0x26, 0x31, - 0x04, 0x3b, 0x50, 0x6e, - 0xa0, 0x6a, 0xca, 0x00, - 0x20, 0x65, 0xc8, 0x18, - 0x00, 0x65, 0x8e, 0x5e, - 0x00, 0x65, 0x48, 0x66, - 0x0a, 0x93, 0x26, 0x01, - 0x00, 0x65, 0x9e, 0x46, - 0xa0, 0x6a, 0xcc, 0x00, - 0xff, 0x6a, 0xc8, 0x08, - 0x20, 0x94, 0x54, 0x6e, - 0x10, 0x94, 0x56, 0x6e, - 0x08, 0x94, 0x70, 0x6e, - 0x08, 0x94, 0x70, 0x6e, - 0x08, 0x94, 0x70, 0x6e, - 0xff, 0x8c, 0xc8, 0x10, - 0xc1, 0x64, 0xc8, 0x18, - 0xf8, 0x64, 0xc8, 0x08, - 0x01, 0x99, 0xda, 0x30, - 0x00, 0x66, 0x64, 0x66, - 0xc0, 0x66, 0xa0, 0x76, - 0x60, 0x66, 0xc8, 0x18, - 0x3d, 0x64, 0xc8, 0x28, - 0x00, 0x65, 0x54, 0x46, - 0xf7, 0x93, 0x26, 0x09, - 0x08, 0x93, 0x72, 0x6e, - 0x00, 0x62, 0xc4, 0x18, - 0x00, 0x65, 0x9e, 0x5e, - 0x00, 0x65, 0x7e, 0x5e, - 0x00, 0x65, 0x7e, 0x5e, - 0x00, 0x65, 0x7e, 0x5e, - 0x01, 0x99, 0xda, 0x30, - 0x01, 0x99, 0xda, 0x30, - 0x01, 0x99, 0xda, 0x30, - 0x01, 0x99, 0xda, 0x30, - 0x01, 0x99, 0xda, 0x30, - 0x01, 0x99, 0xda, 0x30, - 0x01, 0x99, 0xda, 0x30, - 0x01, 0x99, 0xda, 0x34, - 0x01, 0x6c, 0x32, 0x31, - 0x01, 0x6c, 0x32, 0x31, - 0x01, 0x6c, 0x32, 0x31, - 0x01, 0x6c, 0x32, 0x31, - 0x01, 0x6c, 0x32, 0x31, - 0x01, 0x6c, 0x32, 0x31, - 0x01, 0x6c, 0x32, 0x31, - 0x01, 0x6c, 0x32, 0x35, - 0x08, 0x94, 0x9e, 0x7e, - 0xf7, 0x93, 0x26, 0x09, - 0x08, 0x93, 0xa2, 0x6e, - 0xff, 0x6a, 0xd4, 0x0c, - 0x04, 0xb8, 0xca, 0x6e, - 0x01, 0x42, 0x7e, 0x31, - 0xff, 0x6a, 0x76, 0x01, - 0x01, 0x90, 0x84, 0x34, - 0xff, 0x6a, 0x76, 0x05, - 0x01, 0x85, 0x0a, 0x01, - 0x7f, 0x65, 0x10, 0x09, - 0xfe, 0x85, 0x0a, 0x0d, - 0xff, 0x42, 0xc6, 0x66, - 0xff, 0x41, 0xbe, 0x66, - 0xd1, 0x6a, 0xce, 0x5e, - 0xff, 0x6a, 0xca, 0x04, - 0x01, 0x41, 0x20, 0x31, - 0x01, 0xbf, 0x82, 0x30, - 0x01, 0x6a, 0x76, 0x00, - 0x00, 0xbb, 0x08, 0x46, - 0x01, 0x42, 0x20, 0x31, - 0x01, 0xbf, 0x84, 0x34, - 0x01, 0x41, 0x7e, 0x31, - 0x01, 0x90, 0x82, 0x34, - 0x01, 0x65, 0x22, 0x31, - 0xff, 0x6a, 0xd4, 0x08, - 0xff, 0x6a, 0xd4, 0x0c -}; - -static int aic_patch23_func(struct ahc_softc *ahc); - -static int -aic_patch23_func(struct ahc_softc *ahc) -{ - return ((ahc->bugs & AHC_SCBCHAN_UPLOAD_BUG) != 0); -} - -static int aic_patch22_func(struct ahc_softc *ahc); - -static int -aic_patch22_func(struct ahc_softc *ahc) -{ - return ((ahc->features & AHC_CMD_CHAN) == 0); -} - -static int aic_patch21_func(struct ahc_softc *ahc); - -static int -aic_patch21_func(struct ahc_softc *ahc) -{ - return ((ahc->features & AHC_QUEUE_REGS) == 0); -} - -static int aic_patch20_func(struct ahc_softc *ahc); - -static int -aic_patch20_func(struct ahc_softc *ahc) -{ - return ((ahc->features & AHC_WIDE) != 0); -} - -static int aic_patch19_func(struct ahc_softc *ahc); - -static int -aic_patch19_func(struct ahc_softc *ahc) -{ - return ((ahc->flags & AHC_SCB_BTT) != 0); -} - -static int aic_patch18_func(struct ahc_softc *ahc); - -static int -aic_patch18_func(struct ahc_softc *ahc) -{ - return ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0); -} - -static int aic_patch17_func(struct ahc_softc *ahc); - -static int -aic_patch17_func(struct ahc_softc *ahc) -{ - return ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0); -} - -static int aic_patch16_func(struct ahc_softc *ahc); - -static int -aic_patch16_func(struct ahc_softc *ahc) -{ - return ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0); -} - -static int aic_patch15_func(struct ahc_softc *ahc); - -static int -aic_patch15_func(struct ahc_softc *ahc) -{ - return ((ahc->features & AHC_ULTRA2) == 0); -} - -static int aic_patch14_func(struct ahc_softc *ahc); - -static int -aic_patch14_func(struct ahc_softc *ahc) -{ - return ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0); -} - -static int aic_patch13_func(struct ahc_softc *ahc); - -static int -aic_patch13_func(struct ahc_softc *ahc) -{ - return ((ahc->flags & AHC_39BIT_ADDRESSING) != 0); -} - -static int aic_patch12_func(struct ahc_softc *ahc); - -static int -aic_patch12_func(struct ahc_softc *ahc) -{ - return ((ahc->features & AHC_HS_MAILBOX) != 0); -} - -static int aic_patch11_func(struct ahc_softc *ahc); - -static int -aic_patch11_func(struct ahc_softc *ahc) -{ - return ((ahc->features & AHC_ULTRA) != 0); -} - -static int aic_patch10_func(struct ahc_softc *ahc); - -static int -aic_patch10_func(struct ahc_softc *ahc) -{ - return ((ahc->features & AHC_MULTI_TID) != 0); -} - -static int aic_patch9_func(struct ahc_softc *ahc); - -static int -aic_patch9_func(struct ahc_softc *ahc) -{ - return ((ahc->features & AHC_CMD_CHAN) != 0); -} - -static int aic_patch8_func(struct ahc_softc *ahc); - -static int -aic_patch8_func(struct ahc_softc *ahc) -{ - return ((ahc->flags & AHC_INITIATORROLE) != 0); -} - -static int aic_patch7_func(struct ahc_softc *ahc); - -static int -aic_patch7_func(struct ahc_softc *ahc) -{ - return ((ahc->flags & AHC_TARGETROLE) != 0); -} - -static int aic_patch6_func(struct ahc_softc *ahc); - -static int -aic_patch6_func(struct ahc_softc *ahc) -{ - return ((ahc->features & AHC_DT) == 0); -} - -static int aic_patch5_func(struct ahc_softc *ahc); - -static int -aic_patch5_func(struct ahc_softc *ahc) -{ - return ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0); -} - -static int aic_patch4_func(struct ahc_softc *ahc); - -static int -aic_patch4_func(struct ahc_softc *ahc) -{ - return ((ahc->flags & AHC_PAGESCBS) != 0); -} - -static int aic_patch3_func(struct ahc_softc *ahc); - -static int -aic_patch3_func(struct ahc_softc *ahc) -{ - return ((ahc->features & AHC_QUEUE_REGS) != 0); -} - -static int aic_patch2_func(struct ahc_softc *ahc); - -static int -aic_patch2_func(struct ahc_softc *ahc) -{ - return ((ahc->features & AHC_TWIN) != 0); -} - -static int aic_patch1_func(struct ahc_softc *ahc); - -static int -aic_patch1_func(struct ahc_softc *ahc) -{ - return ((ahc->features & AHC_ULTRA2) != 0); -} - -static int aic_patch0_func(struct ahc_softc *ahc); - -static int -aic_patch0_func(struct ahc_softc *ahc) -{ - return (0); -} - -typedef int patch_func_t (struct ahc_softc *ahc); -static struct patch { - patch_func_t *patch_func; - uint32_t begin :10, - skip_instr :10, - skip_patch :12; -} patches[] = { - { aic_patch1_func, 4, 1, 1 }, - { aic_patch2_func, 6, 2, 1 }, - { aic_patch2_func, 9, 1, 1 }, - { aic_patch3_func, 11, 1, 2 }, - { aic_patch0_func, 12, 2, 1 }, - { aic_patch4_func, 15, 1, 2 }, - { aic_patch0_func, 16, 1, 1 }, - { aic_patch5_func, 22, 2, 1 }, - { aic_patch3_func, 27, 1, 2 }, - { aic_patch0_func, 28, 1, 1 }, - { aic_patch6_func, 34, 1, 1 }, - { aic_patch7_func, 37, 54, 19 }, - { aic_patch8_func, 37, 1, 1 }, - { aic_patch9_func, 42, 3, 2 }, - { aic_patch0_func, 45, 3, 1 }, - { aic_patch10_func, 49, 1, 2 }, - { aic_patch0_func, 50, 2, 3 }, - { aic_patch1_func, 50, 1, 2 }, - { aic_patch0_func, 51, 1, 1 }, - { aic_patch2_func, 53, 2, 1 }, - { aic_patch9_func, 55, 1, 2 }, - { aic_patch0_func, 56, 1, 1 }, - { aic_patch9_func, 60, 1, 2 }, - { aic_patch0_func, 61, 1, 1 }, - { aic_patch9_func, 71, 1, 2 }, - { aic_patch0_func, 72, 1, 1 }, - { aic_patch9_func, 75, 1, 2 }, - { aic_patch0_func, 76, 1, 1 }, - { aic_patch9_func, 79, 1, 2 }, - { aic_patch0_func, 80, 1, 1 }, - { aic_patch8_func, 91, 9, 4 }, - { aic_patch1_func, 93, 1, 2 }, - { aic_patch0_func, 94, 1, 1 }, - { aic_patch2_func, 96, 2, 1 }, - { aic_patch2_func, 105, 4, 1 }, - { aic_patch1_func, 109, 1, 2 }, - { aic_patch0_func, 110, 2, 3 }, - { aic_patch2_func, 110, 1, 2 }, - { aic_patch0_func, 111, 1, 1 }, - { aic_patch7_func, 112, 4, 2 }, - { aic_patch0_func, 116, 1, 1 }, - { aic_patch11_func, 118, 2, 1 }, - { aic_patch1_func, 120, 1, 2 }, - { aic_patch0_func, 121, 1, 1 }, - { aic_patch7_func, 122, 4, 1 }, - { aic_patch7_func, 132, 91, 11 }, - { aic_patch4_func, 151, 1, 1 }, - { aic_patch1_func, 165, 1, 1 }, - { aic_patch12_func, 170, 1, 2 }, - { aic_patch0_func, 171, 1, 1 }, - { aic_patch9_func, 182, 1, 2 }, - { aic_patch0_func, 183, 1, 1 }, - { aic_patch9_func, 192, 1, 2 }, - { aic_patch0_func, 193, 1, 1 }, - { aic_patch9_func, 209, 6, 2 }, - { aic_patch0_func, 215, 6, 1 }, - { aic_patch8_func, 223, 19, 2 }, - { aic_patch1_func, 237, 1, 1 }, - { aic_patch1_func, 244, 1, 2 }, - { aic_patch0_func, 245, 2, 2 }, - { aic_patch11_func, 246, 1, 1 }, - { aic_patch9_func, 254, 31, 3 }, - { aic_patch1_func, 270, 14, 2 }, - { aic_patch13_func, 275, 1, 1 }, - { aic_patch14_func, 285, 14, 1 }, - { aic_patch1_func, 301, 1, 2 }, - { aic_patch0_func, 302, 1, 1 }, - { aic_patch9_func, 305, 1, 1 }, - { aic_patch13_func, 310, 1, 1 }, - { aic_patch9_func, 311, 2, 2 }, - { aic_patch0_func, 313, 4, 1 }, - { aic_patch14_func, 317, 1, 1 }, - { aic_patch15_func, 320, 2, 3 }, - { aic_patch9_func, 320, 1, 2 }, - { aic_patch0_func, 321, 1, 1 }, - { aic_patch6_func, 326, 1, 2 }, - { aic_patch0_func, 327, 1, 1 }, - { aic_patch1_func, 331, 50, 11 }, - { aic_patch6_func, 340, 2, 4 }, - { aic_patch7_func, 340, 1, 1 }, - { aic_patch8_func, 341, 1, 1 }, - { aic_patch0_func, 342, 1, 1 }, - { aic_patch16_func, 343, 1, 1 }, - { aic_patch6_func, 362, 6, 3 }, - { aic_patch16_func, 362, 5, 1 }, - { aic_patch0_func, 368, 5, 1 }, - { aic_patch13_func, 376, 5, 1 }, - { aic_patch0_func, 381, 54, 17 }, - { aic_patch14_func, 381, 1, 1 }, - { aic_patch7_func, 383, 2, 2 }, - { aic_patch17_func, 384, 1, 1 }, - { aic_patch9_func, 387, 1, 1 }, - { aic_patch18_func, 394, 1, 1 }, - { aic_patch14_func, 399, 9, 3 }, - { aic_patch9_func, 400, 3, 2 }, - { aic_patch0_func, 403, 3, 1 }, - { aic_patch9_func, 411, 6, 2 }, - { aic_patch0_func, 417, 9, 2 }, - { aic_patch13_func, 417, 1, 1 }, - { aic_patch13_func, 426, 2, 1 }, - { aic_patch14_func, 428, 1, 1 }, - { aic_patch9_func, 430, 1, 2 }, - { aic_patch0_func, 431, 1, 1 }, - { aic_patch7_func, 434, 1, 1 }, - { aic_patch7_func, 435, 1, 1 }, - { aic_patch8_func, 436, 3, 3 }, - { aic_patch6_func, 437, 1, 2 }, - { aic_patch0_func, 438, 1, 1 }, - { aic_patch9_func, 439, 1, 1 }, - { aic_patch15_func, 440, 1, 2 }, - { aic_patch13_func, 440, 1, 1 }, - { aic_patch14_func, 442, 9, 4 }, - { aic_patch9_func, 442, 1, 1 }, - { aic_patch9_func, 449, 2, 1 }, - { aic_patch0_func, 451, 4, 3 }, - { aic_patch9_func, 451, 1, 2 }, - { aic_patch0_func, 452, 3, 1 }, - { aic_patch1_func, 456, 2, 1 }, - { aic_patch7_func, 458, 10, 2 }, - { aic_patch0_func, 468, 1, 1 }, - { aic_patch8_func, 469, 109, 23 }, - { aic_patch1_func, 471, 3, 2 }, - { aic_patch0_func, 474, 5, 3 }, - { aic_patch9_func, 474, 2, 2 }, - { aic_patch0_func, 476, 3, 1 }, - { aic_patch1_func, 481, 2, 2 }, - { aic_patch0_func, 483, 6, 3 }, - { aic_patch9_func, 483, 2, 2 }, - { aic_patch0_func, 485, 3, 1 }, - { aic_patch1_func, 491, 2, 2 }, - { aic_patch0_func, 493, 9, 7 }, - { aic_patch9_func, 493, 5, 6 }, - { aic_patch19_func, 493, 1, 2 }, - { aic_patch0_func, 494, 1, 1 }, - { aic_patch19_func, 496, 1, 2 }, - { aic_patch0_func, 497, 1, 1 }, - { aic_patch0_func, 498, 4, 1 }, - { aic_patch6_func, 502, 3, 2 }, - { aic_patch0_func, 505, 1, 1 }, - { aic_patch1_func, 508, 1, 1 }, - { aic_patch6_func, 514, 1, 2 }, - { aic_patch0_func, 515, 1, 1 }, - { aic_patch20_func, 552, 7, 1 }, - { aic_patch3_func, 580, 1, 2 }, - { aic_patch0_func, 581, 1, 1 }, - { aic_patch21_func, 584, 1, 1 }, - { aic_patch8_func, 586, 104, 33 }, - { aic_patch4_func, 587, 1, 1 }, - { aic_patch1_func, 593, 2, 2 }, - { aic_patch0_func, 595, 1, 1 }, - { aic_patch1_func, 598, 1, 2 }, - { aic_patch0_func, 599, 1, 1 }, - { aic_patch9_func, 600, 3, 3 }, - { aic_patch15_func, 601, 1, 1 }, - { aic_patch0_func, 603, 4, 1 }, - { aic_patch19_func, 611, 2, 2 }, - { aic_patch0_func, 613, 1, 1 }, - { aic_patch19_func, 617, 10, 3 }, - { aic_patch5_func, 619, 8, 1 }, - { aic_patch0_func, 627, 9, 2 }, - { aic_patch5_func, 628, 8, 1 }, - { aic_patch4_func, 638, 1, 2 }, - { aic_patch0_func, 639, 1, 1 }, - { aic_patch19_func, 640, 1, 2 }, - { aic_patch0_func, 641, 3, 2 }, - { aic_patch4_func, 643, 1, 1 }, - { aic_patch5_func, 644, 1, 1 }, - { aic_patch5_func, 647, 1, 1 }, - { aic_patch5_func, 649, 1, 1 }, - { aic_patch4_func, 651, 2, 2 }, - { aic_patch0_func, 653, 2, 1 }, - { aic_patch5_func, 655, 1, 1 }, - { aic_patch5_func, 658, 1, 1 }, - { aic_patch5_func, 661, 1, 1 }, - { aic_patch19_func, 665, 1, 1 }, - { aic_patch19_func, 668, 1, 1 }, - { aic_patch4_func, 674, 1, 1 }, - { aic_patch6_func, 677, 1, 2 }, - { aic_patch0_func, 678, 1, 1 }, - { aic_patch7_func, 690, 16, 1 }, - { aic_patch4_func, 706, 20, 1 }, - { aic_patch9_func, 727, 4, 2 }, - { aic_patch0_func, 731, 4, 1 }, - { aic_patch9_func, 735, 4, 2 }, - { aic_patch0_func, 739, 3, 1 }, - { aic_patch6_func, 745, 1, 1 }, - { aic_patch22_func, 747, 14, 1 }, - { aic_patch7_func, 761, 3, 1 }, - { aic_patch9_func, 773, 24, 8 }, - { aic_patch19_func, 777, 1, 2 }, - { aic_patch0_func, 778, 1, 1 }, - { aic_patch15_func, 783, 4, 2 }, - { aic_patch0_func, 787, 7, 3 }, - { aic_patch23_func, 787, 5, 2 }, - { aic_patch0_func, 792, 2, 1 }, - { aic_patch0_func, 797, 42, 3 }, - { aic_patch18_func, 809, 18, 2 }, - { aic_patch0_func, 827, 1, 1 }, - { aic_patch4_func, 851, 1, 1 }, - { aic_patch4_func, 852, 3, 2 }, - { aic_patch0_func, 855, 1, 1 }, - { aic_patch13_func, 856, 3, 1 }, - { aic_patch4_func, 859, 12, 1 } -}; -static struct cs { - u_int16_t begin; - u_int16_t end; -} critical_sections[] = { - { 11, 18 }, - { 21, 30 }, - { 706, 722 }, - { 852, 855 }, - { 859, 865 }, - { 867, 869 }, - { 869, 871 } -}; -static const int num_critical_sections = sizeof(critical_sections) - / sizeof(*critical_sections); diff --git a/xen/drivers/scsi/aic7xxx/aicasm/Makefile b/xen/drivers/scsi/aic7xxx/aicasm/Makefile deleted file mode 100644 index 16394e1f8f..0000000000 --- a/xen/drivers/scsi/aic7xxx/aicasm/Makefile +++ /dev/null @@ -1,65 +0,0 @@ -PROG= aicasm - -.SUFFIXES= .l .y .c .h - -CSRCS= aicasm.c aicasm_symbol.c -YSRCS= aicasm_gram.y aicasm_macro_gram.y -LSRCS= aicasm_scan.l aicasm_macro_scan.l - -GENHDRS= aicdb.h $(YSRCS:.y=.h) -GENSRCS= $(YSRCS:.y=.c) $(LSRCS:.l=.c) - -SRCS= ${CSRCS} ${GENSRCS} -CLEANFILES= ${GENSRCS} ${GENHDRS} $(YSRCS:.y=.output) -# Override default kernel CFLAGS. This is a userland app. -AICASM_CFLAGS:= -I/usr/include -I. -ldb -YFLAGS= -d - -NOMAN= noman - -ifneq ($(HOSTCC),) -AICASM_CC= $(HOSTCC) -else -AICASM_CC= $(CC) -endif - -ifdef DEBUG -CFLAGS+= -DDEBUG -g -YFLAGS+= -t -v -LFLAGS= -d -endif - -$(PROG): ${GENHDRS} $(SRCS) - $(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG) - -aicdb.h: - @if [ -e "/usr/include/db3/db_185.h" ]; then \ - echo "#include " > aicdb.h; \ - elif [ -e "/usr/include/db2/db_185.h" ]; then \ - echo "#include " > aicdb.h; \ - elif [ -e "/usr/include/db/db_185.h" ]; then \ - echo "#include " > aicdb.h; \ - elif [ -e "/usr/include/db_185.h" ]; then \ - echo "#include " > aicdb.h; \ - else \ - echo "*** Install db development libraries"; \ - fi - -clean: - rm -f $(CLEANFILES) $(PROG) - -aicasm_gram.c aicasm_gram.h: aicasm_gram.y - $(YACC) $(YFLAGS) -b $(<:.y=) $< - mv $(<:.y=).tab.c $(<:.y=.c) - mv $(<:.y=).tab.h $(<:.y=.h) - -aicasm_macro_gram.c aicasm_macro_gram.h: aicasm_macro_gram.y - $(YACC) $(YFLAGS) -b $(<:.y=) -p mm $< - mv $(<:.y=).tab.c $(<:.y=.c) - mv $(<:.y=).tab.h $(<:.y=.h) - -aicasm_scan.c: aicasm_scan.l - $(LEX) $(LFLAGS) -o$@ $< - -aicasm_macro_scan.c: aicasm_macro_scan.l - $(LEX) $(LFLAGS) -Pmm -o$@ $< diff --git a/xen/drivers/scsi/aic7xxx/aicasm/aicasm.c b/xen/drivers/scsi/aic7xxx/aicasm/aicasm.c deleted file mode 100644 index bc93c3d6ec..0000000000 --- a/xen/drivers/scsi/aic7xxx/aicasm/aicasm.c +++ /dev/null @@ -1,809 +0,0 @@ -/* - * Aic7xxx SCSI host adapter firmware asssembler - * - * Copyright (c) 1997, 1998, 2000, 2001 Justin T. Gibbs. - * Copyright (c) 2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#16 $ - * - * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm.c,v 1.28.2.5 2002/04/29 19:36:36 gibbs Exp $ - */ -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#if linux -#include -#else -#include -#endif - -#include "aicasm.h" -#include "aicasm_symbol.h" -#include "aicasm_insformat.h" - -typedef struct patch { - STAILQ_ENTRY(patch) links; - int patch_func; - u_int begin; - u_int skip_instr; - u_int skip_patch; -} patch_t; - -STAILQ_HEAD(patch_list, patch) patches; - -static void usage(void); -static void back_patch(void); -static void output_code(void); -static void output_listing(char *ifilename); -static void dump_scope(scope_t *scope); -static void emit_patch(scope_t *scope, int patch); -static int check_patch(patch_t **start_patch, int start_instr, - int *skip_addr, int *func_vals); - -struct path_list search_path; -int includes_search_curdir; -char *appname; -FILE *ofile; -char *ofilename; -char *regfilename; -FILE *regfile; -char *listfilename; -FILE *listfile; -int src_mode; -int dst_mode; - -static STAILQ_HEAD(,instruction) seq_program; -struct cs_tailq cs_tailq; -struct scope_list scope_stack; -symlist_t patch_functions; - -#if DEBUG -extern int yy_flex_debug; -extern int mm_flex_debug; -extern int yydebug; -extern int mmdebug; -#endif -extern FILE *yyin; -extern int yyparse(void); - -int main(int argc, char *argv[]); - -int -main(int argc, char *argv[]) -{ - extern char *optarg; - extern int optind; - int ch; - int retval; - char *inputfilename; - scope_t *sentinal; - - STAILQ_INIT(&patches); - SLIST_INIT(&search_path); - STAILQ_INIT(&seq_program); - TAILQ_INIT(&cs_tailq); - SLIST_INIT(&scope_stack); - - /* Set Sentinal scope node */ - sentinal = scope_alloc(); - sentinal->type = SCOPE_ROOT; - - includes_search_curdir = 1; - appname = *argv; - regfile = NULL; - listfile = NULL; -#if DEBUG - yy_flex_debug = 0; - mm_flex_debug = 0; - yydebug = 0; - mmdebug = 0; -#endif - while ((ch = getopt(argc, argv, "d:l:n:o:r:I:O:")) != -1) { - switch(ch) { - case 'd': -#if DEBUG - if (strcmp(optarg, "s") == 0) { - yy_flex_debug = 1; - mm_flex_debug = 1; - } else if (strcmp(optarg, "p") == 0) { - yydebug = 1; - mmdebug = 1; - } else { - fprintf(stderr, "%s: -d Requires either an " - "'s' or 'p' argument\n", appname); - usage(); - } -#else - stop("-d: Assembler not built with debugging " - "information", EX_SOFTWARE); -#endif - break; - case 'l': - /* Create a program listing */ - if ((listfile = fopen(optarg, "w")) == NULL) { - perror(optarg); - stop(NULL, EX_CANTCREAT); - } - listfilename = optarg; - break; - case 'n': - /* Don't complain about the -nostdinc directrive */ - if (strcmp(optarg, "ostdinc")) { - fprintf(stderr, "%s: Unknown option -%c%s\n", - appname, ch, optarg); - usage(); - /* NOTREACHED */ - } - break; - case 'o': - if ((ofile = fopen(optarg, "w")) == NULL) { - perror(optarg); - stop(NULL, EX_CANTCREAT); - } - ofilename = optarg; - break; - case 'r': - if ((regfile = fopen(optarg, "w")) == NULL) { - perror(optarg); - stop(NULL, EX_CANTCREAT); - } - regfilename = optarg; - break; - case 'I': - { - path_entry_t include_dir; - - if (strcmp(optarg, "-") == 0) { - if (includes_search_curdir == 0) { - fprintf(stderr, "%s: Warning - '-I-' " - "specified multiple " - "times\n", appname); - } - includes_search_curdir = 0; - for (include_dir = SLIST_FIRST(&search_path); - include_dir != NULL; - include_dir = SLIST_NEXT(include_dir, - links)) - /* - * All entries before a '-I-' only - * apply to includes specified with - * quotes instead of "<>". - */ - include_dir->quoted_includes_only = 1; - } else { - include_dir = - (path_entry_t)malloc(sizeof(*include_dir)); - if (include_dir == NULL) { - perror(optarg); - stop(NULL, EX_OSERR); - } - include_dir->directory = strdup(optarg); - if (include_dir->directory == NULL) { - perror(optarg); - stop(NULL, EX_OSERR); - } - include_dir->quoted_includes_only = 0; - SLIST_INSERT_HEAD(&search_path, include_dir, - links); - } - break; - } - case '?': - default: - usage(); - /* NOTREACHED */ - } - } - argc -= optind; - argv += optind; - - if (argc != 1) { - fprintf(stderr, "%s: No input file specifiled\n", appname); - usage(); - /* NOTREACHED */ - } - - symtable_open(); - inputfilename = *argv; - include_file(*argv, SOURCE_FILE); - retval = yyparse(); - if (retval == 0) { - if (SLIST_FIRST(&scope_stack) == NULL - || SLIST_FIRST(&scope_stack)->type != SCOPE_ROOT) { - stop("Unterminated conditional expression", EX_DATAERR); - /* NOTREACHED */ - } - - /* Process outmost scope */ - process_scope(SLIST_FIRST(&scope_stack)); - /* - * Decend the tree of scopes and insert/emit - * patches as appropriate. We perform a depth first - * tranversal, recursively handling each scope. - */ - /* start at the root scope */ - dump_scope(SLIST_FIRST(&scope_stack)); - - /* Patch up forward jump addresses */ - back_patch(); - - if (ofile != NULL) - output_code(); - if (regfile != NULL) { - symtable_dump(regfile); - } - if (listfile != NULL) - output_listing(inputfilename); - } - - stop(NULL, 0); - /* NOTREACHED */ - return (0); -} - -static void -usage() -{ - - (void)fprintf(stderr, -"usage: %-16s [-nostdinc] [-I-] [-I directory] [-o output_file] - [-r register_output_file] [-l program_list_file] - input_file\n", - appname); - exit(EX_USAGE); -} - -static void -back_patch() -{ - struct instruction *cur_instr; - - for (cur_instr = STAILQ_FIRST(&seq_program); - cur_instr != NULL; - cur_instr = STAILQ_NEXT(cur_instr, links)) { - if (cur_instr->patch_label != NULL) { - struct ins_format3 *f3_instr; - u_int address; - - if (cur_instr->patch_label->type != LABEL) { - char buf[255]; - - snprintf(buf, sizeof(buf), - "Undefined label %s", - cur_instr->patch_label->name); - stop(buf, EX_DATAERR); - /* NOTREACHED */ - } - f3_instr = &cur_instr->format.format3; - address = f3_instr->address; - address += cur_instr->patch_label->info.linfo->address; - f3_instr->address = address; - } - } -} - -static void -output_code() -{ - struct instruction *cur_instr; - patch_t *cur_patch; - critical_section_t *cs; - symbol_node_t *cur_node; - int instrcount; - - instrcount = 0; - fprintf(ofile, -"/* - * DO NOT EDIT - This file is automatically generated - * from the following source files: - * -%s */\n", versions); - - fprintf(ofile, "static uint8_t seqprog[] = {\n"); - for (cur_instr = STAILQ_FIRST(&seq_program); - cur_instr != NULL; - cur_instr = STAILQ_NEXT(cur_instr, links)) { - - fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x", - cur_instr == STAILQ_FIRST(&seq_program) ? "" : ",\n", -#if BYTE_ORDER == LITTLE_ENDIAN - cur_instr->format.bytes[0], - cur_instr->format.bytes[1], - cur_instr->format.bytes[2], - cur_instr->format.bytes[3]); -#else - cur_instr->format.bytes[3], - cur_instr->format.bytes[2], - cur_instr->format.bytes[1], - cur_instr->format.bytes[0]); -#endif - instrcount++; - } - fprintf(ofile, "\n};\n\n"); - - if (patch_arg_list == NULL) - stop("Patch argument list not defined", - EX_DATAERR); - - /* - * Output patch information. Patch functions first. - */ - for (cur_node = SLIST_FIRST(&patch_functions); - cur_node != NULL; - cur_node = SLIST_NEXT(cur_node,links)) { - fprintf(ofile, -"static int aic_patch%d_func(%s); - -static int -aic_patch%d_func(%s) -{ - return (%s); -}\n\n", - cur_node->symbol->info.condinfo->func_num, - patch_arg_list, - cur_node->symbol->info.condinfo->func_num, - patch_arg_list, - cur_node->symbol->name); - } - - fprintf(ofile, -"typedef int patch_func_t (%s); -static struct patch { - patch_func_t *patch_func; - uint32_t begin :10, - skip_instr :10, - skip_patch :12; -} patches[] = {\n", patch_arg_list); - - for (cur_patch = STAILQ_FIRST(&patches); - cur_patch != NULL; - cur_patch = STAILQ_NEXT(cur_patch,links)) { - fprintf(ofile, "%s\t{ aic_patch%d_func, %d, %d, %d }", - cur_patch == STAILQ_FIRST(&patches) ? "" : ",\n", - cur_patch->patch_func, cur_patch->begin, - cur_patch->skip_instr, cur_patch->skip_patch); - } - - fprintf(ofile, "\n};\n"); - - fprintf(ofile, -"static struct cs { - u_int16_t begin; - u_int16_t end; -} critical_sections[] = {\n"); - - for (cs = TAILQ_FIRST(&cs_tailq); - cs != NULL; - cs = TAILQ_NEXT(cs, links)) { - fprintf(ofile, "%s\t{ %d, %d }", - cs == TAILQ_FIRST(&cs_tailq) ? "" : ",\n", - cs->begin_addr, cs->end_addr); - } - - fprintf(ofile, "\n};\n"); - - fprintf(ofile, -"static const int num_critical_sections = sizeof(critical_sections) - / sizeof(*critical_sections);\n"); - - fprintf(stderr, "%s: %d instructions used\n", appname, instrcount); -} - -static void -dump_scope(scope_t *scope) -{ - scope_t *cur_scope; - - /* - * Emit the first patch for this scope - */ - emit_patch(scope, 0); - - /* - * Dump each scope within this one. - */ - cur_scope = TAILQ_FIRST(&scope->inner_scope); - - while (cur_scope != NULL) { - - dump_scope(cur_scope); - - cur_scope = TAILQ_NEXT(cur_scope, scope_links); - } - - /* - * Emit the second, closing, patch for this scope - */ - emit_patch(scope, 1); -} - -void -emit_patch(scope_t *scope, int patch) -{ - patch_info_t *pinfo; - patch_t *new_patch; - - pinfo = &scope->patches[patch]; - - if (pinfo->skip_instr == 0) - /* No-Op patch */ - return; - - new_patch = (patch_t *)malloc(sizeof(*new_patch)); - - if (new_patch == NULL) - stop("Could not malloc patch structure", EX_OSERR); - - memset(new_patch, 0, sizeof(*new_patch)); - - if (patch == 0) { - new_patch->patch_func = scope->func_num; - new_patch->begin = scope->begin_addr; - } else { - new_patch->patch_func = 0; - new_patch->begin = scope->end_addr; - } - new_patch->skip_instr = pinfo->skip_instr; - new_patch->skip_patch = pinfo->skip_patch; - STAILQ_INSERT_TAIL(&patches, new_patch, links); -} - -void -output_listing(char *ifilename) -{ - char buf[1024]; - FILE *ifile; - struct instruction *cur_instr; - patch_t *cur_patch; - symbol_node_t *cur_func; - int *func_values; - int instrcount; - int instrptr; - int line; - int func_count; - int skip_addr; - - instrcount = 0; - instrptr = 0; - line = 1; - skip_addr = 0; - if ((ifile = fopen(ifilename, "r")) == NULL) { - perror(ifilename); - stop(NULL, EX_DATAERR); - } - - /* - * Determine which options to apply to this listing. - */ - for (func_count = 0, cur_func = SLIST_FIRST(&patch_functions); - cur_func != NULL; - cur_func = SLIST_NEXT(cur_func, links)) - func_count++; - - func_values = NULL; - if (func_count != 0) { - func_values = (int *)malloc(func_count * sizeof(int)); - - if (func_values == NULL) - stop("Could not malloc", EX_OSERR); - - func_values[0] = 0; /* FALSE func */ - func_count--; - - /* - * Ask the user to fill in the return values for - * the rest of the functions. - */ - - - for (cur_func = SLIST_FIRST(&patch_functions); - cur_func != NULL && SLIST_NEXT(cur_func, links) != NULL; - cur_func = SLIST_NEXT(cur_func, links), func_count--) { - int input; - - fprintf(stdout, "\n(%s)\n", cur_func->symbol->name); - fprintf(stdout, - "Enter the return value for " - "this expression[T/F]:"); - - while (1) { - - input = getchar(); - input = toupper(input); - - if (input == 'T') { - func_values[func_count] = 1; - break; - } else if (input == 'F') { - func_values[func_count] = 0; - break; - } - } - if (isatty(fileno(stdin)) == 0) - putchar(input); - } - fprintf(stdout, "\nThanks!\n"); - } - - /* Now output the listing */ - cur_patch = STAILQ_FIRST(&patches); - for (cur_instr = STAILQ_FIRST(&seq_program); - cur_instr != NULL; - cur_instr = STAILQ_NEXT(cur_instr, links), instrcount++) { - - if (check_patch(&cur_patch, instrcount, - &skip_addr, func_values) == 0) { - /* Don't count this instruction as it is in a patch - * that was removed. - */ - continue; - } - - while (line < cur_instr->srcline) { - fgets(buf, sizeof(buf), ifile); - fprintf(listfile, "\t\t%s", buf); - line++; - } - fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr, -#if BYTE_ORDER == LITTLE_ENDIAN - cur_instr->format.bytes[0], - cur_instr->format.bytes[1], - cur_instr->format.bytes[2], - cur_instr->format.bytes[3]); -#else - cur_instr->format.bytes[3], - cur_instr->format.bytes[2], - cur_instr->format.bytes[1], - cur_instr->format.bytes[0]); -#endif - fgets(buf, sizeof(buf), ifile); - fprintf(listfile, "\t%s", buf); - line++; - instrptr++; - } - /* Dump the remainder of the file */ - while(fgets(buf, sizeof(buf), ifile) != NULL) - fprintf(listfile, "\t\t%s", buf); - - fclose(ifile); -} - -static int -check_patch(patch_t **start_patch, int start_instr, - int *skip_addr, int *func_vals) -{ - patch_t *cur_patch; - - cur_patch = *start_patch; - - while (cur_patch != NULL && start_instr == cur_patch->begin) { - if (func_vals[cur_patch->patch_func] == 0) { - int skip; - - /* Start rejecting code */ - *skip_addr = start_instr + cur_patch->skip_instr; - for (skip = cur_patch->skip_patch; - skip > 0 && cur_patch != NULL; - skip--) - cur_patch = STAILQ_NEXT(cur_patch, links); - } else { - /* Accepted this patch. Advance to the next - * one and wait for our intruction pointer to - * hit this point. - */ - cur_patch = STAILQ_NEXT(cur_patch, links); - } - } - - *start_patch = cur_patch; - if (start_instr < *skip_addr) - /* Still skipping */ - return (0); - - return (1); -} - -/* - * Print out error information if appropriate, and clean up before - * terminating the program. - */ -void -stop(const char *string, int err_code) -{ - if (string != NULL) { - fprintf(stderr, "%s: ", appname); - if (yyfilename != NULL) { - fprintf(stderr, "Stopped at file %s, line %d - ", - yyfilename, yylineno); - } - fprintf(stderr, "%s\n", string); - } - - if (ofile != NULL) { - fclose(ofile); - if (err_code != 0) { - fprintf(stderr, "%s: Removing %s due to error\n", - appname, ofilename); - unlink(ofilename); - } - } - - if (regfile != NULL) { - fclose(regfile); - if (err_code != 0) { - fprintf(stderr, "%s: Removing %s due to error\n", - appname, regfilename); - unlink(regfilename); - } - } - - if (listfile != NULL) { - fclose(listfile); - if (err_code != 0) { - fprintf(stderr, "%s: Removing %s due to error\n", - appname, listfilename); - unlink(listfilename); - } - } - - symlist_free(&patch_functions); - symtable_close(); - - exit(err_code); -} - -struct instruction * -seq_alloc() -{ - struct instruction *new_instr; - - new_instr = (struct instruction *)malloc(sizeof(struct instruction)); - if (new_instr == NULL) - stop("Unable to malloc instruction object", EX_SOFTWARE); - memset(new_instr, 0, sizeof(*new_instr)); - STAILQ_INSERT_TAIL(&seq_program, new_instr, links); - new_instr->srcline = yylineno; - return new_instr; -} - -critical_section_t * -cs_alloc() -{ - critical_section_t *new_cs; - - new_cs= (critical_section_t *)malloc(sizeof(critical_section_t)); - if (new_cs == NULL) - stop("Unable to malloc critical_section object", EX_SOFTWARE); - memset(new_cs, 0, sizeof(*new_cs)); - - TAILQ_INSERT_TAIL(&cs_tailq, new_cs, links); - return new_cs; -} - -scope_t * -scope_alloc() -{ - scope_t *new_scope; - - new_scope = (scope_t *)malloc(sizeof(scope_t)); - if (new_scope == NULL) - stop("Unable to malloc scope object", EX_SOFTWARE); - memset(new_scope, 0, sizeof(*new_scope)); - TAILQ_INIT(&new_scope->inner_scope); - - if (SLIST_FIRST(&scope_stack) != NULL) { - TAILQ_INSERT_TAIL(&SLIST_FIRST(&scope_stack)->inner_scope, - new_scope, scope_links); - } - /* This patch is now the current scope */ - SLIST_INSERT_HEAD(&scope_stack, new_scope, scope_stack_links); - return new_scope; -} - -void -process_scope(scope_t *scope) -{ - /* - * We are "leaving" this scope. We should now have - * enough information to process the lists of scopes - * we encapsulate. - */ - scope_t *cur_scope; - u_int skip_patch_count; - u_int skip_instr_count; - - cur_scope = TAILQ_LAST(&scope->inner_scope, scope_tailq); - skip_patch_count = 0; - skip_instr_count = 0; - while (cur_scope != NULL) { - u_int patch0_patch_skip; - - patch0_patch_skip = 0; - switch (cur_scope->type) { - case SCOPE_IF: - case SCOPE_ELSE_IF: - if (skip_instr_count != 0) { - /* Create a tail patch */ - patch0_patch_skip++; - cur_scope->patches[1].skip_patch = - skip_patch_count + 1; - cur_scope->patches[1].skip_instr = - skip_instr_count; - } - - /* Count Head patch */ - patch0_patch_skip++; - - /* Count any patches contained in our inner scope */ - patch0_patch_skip += cur_scope->inner_scope_patches; - - cur_scope->patches[0].skip_patch = patch0_patch_skip; - cur_scope->patches[0].skip_instr = - cur_scope->end_addr - cur_scope->begin_addr; - - skip_instr_count += cur_scope->patches[0].skip_instr; - - skip_patch_count += patch0_patch_skip; - if (cur_scope->type == SCOPE_IF) { - scope->inner_scope_patches += skip_patch_count; - skip_patch_count = 0; - skip_instr_count = 0; - } - break; - case SCOPE_ELSE: - /* Count any patches contained in our innter scope */ - skip_patch_count += cur_scope->inner_scope_patches; - - skip_instr_count += cur_scope->end_addr - - cur_scope->begin_addr; - break; - case SCOPE_ROOT: - stop("Unexpected scope type encountered", EX_SOFTWARE); - /* NOTREACHED */ - } - - cur_scope = TAILQ_PREV(cur_scope, scope_tailq, scope_links); - } -} diff --git a/xen/drivers/scsi/aic7xxx/aicasm/aicasm.h b/xen/drivers/scsi/aic7xxx/aicasm/aicasm.h deleted file mode 100644 index d18314a2b3..0000000000 --- a/xen/drivers/scsi/aic7xxx/aicasm/aicasm.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Assembler for the sequencer program downloaded to Aic7xxx SCSI host adapters - * - * Copyright (c) 1997 Justin T. Gibbs. - * Copyright (c) 2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.h#10 $ - * - * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm.h,v 1.11.2.4 2002/04/29 19:36:36 gibbs Exp $ - */ - -#ifdef __linux__ -#include "../queue.h" -#else -#include -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -typedef struct path_entry { - char *directory; - int quoted_includes_only; - SLIST_ENTRY(path_entry) links; -} *path_entry_t; - -typedef enum { - QUOTED_INCLUDE, - BRACKETED_INCLUDE, - SOURCE_FILE -} include_type; - -SLIST_HEAD(path_list, path_entry); - -extern struct path_list search_path; -extern struct cs_tailq cs_tailq; -extern struct scope_list scope_stack; -extern struct symlist patch_functions; -extern int includes_search_curdir; /* False if we've seen -I- */ -extern char *appname; -extern int yylineno; -extern char *yyfilename; -extern char *patch_arg_list; -extern char *versions; -extern int src_mode; -extern int dst_mode; -struct symbol; - -void stop(const char *errstring, int err_code); -void include_file(char *file_name, include_type type); -void expand_macro(struct symbol *macro_symbol); -struct instruction *seq_alloc(void); -struct critical_section *cs_alloc(void); -struct scope *scope_alloc(void); -void process_scope(struct scope *); diff --git a/xen/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y b/xen/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y deleted file mode 100644 index 6d9213e3ae..0000000000 --- a/xen/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y +++ /dev/null @@ -1,1858 +0,0 @@ -%{ -/* - * Parser for the Aic7xxx SCSI Host adapter sequencer assembler. - * - * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. - * Copyright (c) 2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#15 $ - * - * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_gram.y,v 1.11.2.5 2002/04/29 19:36:36 gibbs Exp $ - */ - -#include - -#include -#include -#include -#include -#include -#include - -#ifdef __linux__ -#include "../queue.h" -#else -#include -#endif - -#include "aicasm.h" -#include "aicasm_symbol.h" -#include "aicasm_insformat.h" - -int yylineno; -char *yyfilename; -char *patch_arg_list; -char *versions; -static char errbuf[255]; -static char regex_pattern[255]; -static symbol_t *cur_symbol; -static symbol_t *scb_or_sram_symbol; -static symtype cur_symtype; -static symbol_ref_t accumulator; -static symbol_ref_t mode_ptr; -static symbol_ref_t allones; -static symbol_ref_t allzeros; -static symbol_ref_t none; -static symbol_ref_t sindex; -static int instruction_ptr; -static int num_srams; -static int sram_or_scb_offset; -static int download_constant_count; -static int in_critical_section; - -static void process_bitmask(int mask_type, symbol_t *sym, int mask); -static void initialize_symbol(symbol_t *symbol); -static void add_macro_arg(const char *argtext, int position); -static void add_macro_body(const char *bodytext); -static void process_register(symbol_t **p_symbol); -static void format_1_instr(int opcode, symbol_ref_t *dest, - expression_t *immed, symbol_ref_t *src, int ret); -static void format_2_instr(int opcode, symbol_ref_t *dest, - expression_t *places, symbol_ref_t *src, int ret); -static void format_3_instr(int opcode, symbol_ref_t *src, - expression_t *immed, symbol_ref_t *address); -static void test_readable_symbol(symbol_t *symbol); -static void test_writable_symbol(symbol_t *symbol); -static void type_check(symbol_t *symbol, expression_t *expression, int and_op); -static void make_expression(expression_t *immed, int value); -static void add_conditional(symbol_t *symbol); -static void add_version(const char *verstring); -static int is_download_const(expression_t *immed); - -#define SRAM_SYMNAME "SRAM_BASE" -#define SCB_SYMNAME "SCB_BASE" -%} - -%union { - u_int value; - char *str; - symbol_t *sym; - symbol_ref_t sym_ref; - expression_t expression; -} - -%token T_REGISTER - -%token T_CONST - -%token T_EXPORT - -%token T_DOWNLOAD - -%token T_SCB - -%token T_SRAM - -%token T_ALIAS - -%token T_SIZE - -%token T_EXPR_LSHIFT - -%token T_EXPR_RSHIFT - -%token T_ADDRESS - -%token T_ACCESS_MODE - -%token T_MODES - -%token T_DEFINE - -%token T_SET_SRC_MODE - -%token T_SET_DST_MODE - -%token T_MODE - -%token T_BEGIN_CS - -%token T_END_CS - -%token T_BIT - -%token T_MASK - -%token T_NUMBER - -%token T_PATH T_STRING T_ARG T_MACROBODY - -%token T_CEXPR - -%token T_EOF T_INCLUDE T_VERSION T_PATCH_ARG_LIST - -%token T_SHR T_SHL T_ROR T_ROL - -%token T_MVI T_MOV T_CLR T_BMOV - -%token T_JMP T_JC T_JNC T_JE T_JNE T_JNZ T_JZ T_CALL - -%token T_ADD T_ADC - -%token T_INC T_DEC - -%token T_STC T_CLC - -%token T_CMP T_NOT T_XOR - -%token T_TEST T_AND - -%token T_OR - -%token T_RET - -%token T_NOP - -%token T_ACCUM T_ALLONES T_ALLZEROS T_NONE T_SINDEX T_MODE_PTR - -%token T_A - -%token T_SYMBOL - -%token T_NL - -%token T_IF T_ELSE T_ELSE_IF T_ENDIF - -%type reg_symbol address destination source opt_source - -%type expression immediate immediate_or_a - -%type export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne - -%type numerical_value mode_value mode_list macro_arglist - -%left '|' -%left '&' -%left T_EXPR_LSHIFT T_EXPR_RSHIFT -%left '+' '-' -%left '*' '/' -%right '~' -%nonassoc UMINUS -%% - -program: - include -| program include -| patch_arg_list -| program patch_arg_list -| version -| program version -| register -| program register -| constant -| program constant -| macrodefn -| program macrodefn -| scratch_ram -| program scratch_ram -| scb -| program scb -| label -| program label -| set_src_mode -| program set_src_mode -| set_dst_mode -| program set_dst_mode -| critical_section_start -| program critical_section_start -| critical_section_end -| program critical_section_end -| conditional -| program conditional -| code -| program code -; - -include: - T_INCLUDE '<' T_PATH '>' - { - include_file($3, BRACKETED_INCLUDE); - } -| T_INCLUDE '"' T_PATH '"' - { - include_file($3, QUOTED_INCLUDE); - } -; - -patch_arg_list: - T_PATCH_ARG_LIST '=' T_STRING - { - if (patch_arg_list != NULL) - stop("Patch argument list multiply defined", - EX_DATAERR); - patch_arg_list = strdup($3); - if (patch_arg_list == NULL) - stop("Unable to record patch arg list", EX_SOFTWARE); - } -; - -version: - T_VERSION '=' T_STRING - { add_version($3); } -; - -register: - T_REGISTER { cur_symtype = REGISTER; } reg_definition -; - -reg_definition: - T_SYMBOL '{' - { - if ($1->type != UNINITIALIZED) { - stop("Register multiply defined", EX_DATAERR); - /* NOTREACHED */ - } - cur_symbol = $1; - cur_symbol->type = cur_symtype; - initialize_symbol(cur_symbol); - } - reg_attribute_list - '}' - { - /* - * Default to allowing everything in for registers - * with no bit or mask definitions. - */ - if (cur_symbol->info.rinfo->valid_bitmask == 0) - cur_symbol->info.rinfo->valid_bitmask = 0xFF; - - if (cur_symbol->info.rinfo->size == 0) - cur_symbol->info.rinfo->size = 1; - - /* - * This might be useful for registers too. - */ - if (cur_symbol->type != REGISTER) { - if (cur_symbol->info.rinfo->address == 0) - cur_symbol->info.rinfo->address = - sram_or_scb_offset; - sram_or_scb_offset += - cur_symbol->info.rinfo->size; - } - cur_symbol = NULL; - } -; - -reg_attribute_list: - reg_attribute -| reg_attribute_list reg_attribute -; - -reg_attribute: - reg_address -| size -| access_mode -| modes -| bit_defn -| mask_defn -| alias -| accumulator -| mode_pointer -| allones -| allzeros -| none -| sindex -; - -reg_address: - T_ADDRESS T_NUMBER - { - cur_symbol->info.rinfo->address = $2; - } -; - -size: - T_SIZE T_NUMBER - { - cur_symbol->info.rinfo->size = $2; - if (scb_or_sram_symbol != NULL) { - u_int max_addr; - u_int sym_max_addr; - - max_addr = scb_or_sram_symbol->info.rinfo->address - + scb_or_sram_symbol->info.rinfo->size; - sym_max_addr = cur_symbol->info.rinfo->address - + cur_symbol->info.rinfo->size; - - if (sym_max_addr > max_addr) - stop("SCB or SRAM space exhausted", EX_DATAERR); - } - } -; - -access_mode: - T_ACCESS_MODE T_MODE - { - cur_symbol->info.rinfo->mode = $2; - } -; - -modes: - T_MODES mode_list - { - cur_symbol->info.rinfo->modes = $2; - } -; - -mode_list: - mode_value - { - $$ = $1; - } -| mode_list ',' mode_value - { - $$ = $1 | $3; - } -; - -mode_value: - T_NUMBER - { - if ($1 > 4) { - stop("Valid register modes range between 0 and 4.", - EX_DATAERR); - /* NOTREACHED */ - } - - $$ = (0x1 << $1); - } -| T_SYMBOL - { - symbol_t *symbol; - - symbol = $1; - if (symbol->type != CONST) { - stop("Only \"const\" symbols allowed in " - "mode definitions.", EX_DATAERR); - /* NOTREACHED */ - } - if (symbol->info.cinfo->value > 4) { - stop("Valid register modes range between 0 and 4.", - EX_DATAERR); - /* NOTREACHED */ - } - $$ = (0x1 << symbol->info.cinfo->value); - } -; - -bit_defn: - T_BIT T_SYMBOL T_NUMBER - { - process_bitmask(BIT, $2, $3); - } -; - -mask_defn: - T_MASK T_SYMBOL expression - { - process_bitmask(MASK, $2, $3.value); - } -; - -alias: - T_ALIAS T_SYMBOL - { - if ($2->type != UNINITIALIZED) { - stop("Re-definition of register alias", - EX_DATAERR); - /* NOTREACHED */ - } - $2->type = ALIAS; - initialize_symbol($2); - $2->info.ainfo->parent = cur_symbol; - } -; - -accumulator: - T_ACCUM - { - if (accumulator.symbol != NULL) { - stop("Only one accumulator definition allowed", - EX_DATAERR); - /* NOTREACHED */ - } - accumulator.symbol = cur_symbol; - } -; - -mode_pointer: - T_MODE_PTR - { - if (mode_ptr.symbol != NULL) { - stop("Only one mode pointer definition allowed", - EX_DATAERR); - /* NOTREACHED */ - } - mode_ptr.symbol = cur_symbol; - } -; - -allones: - T_ALLONES - { - if (allones.symbol != NULL) { - stop("Only one definition of allones allowed", - EX_DATAERR); - /* NOTREACHED */ - } - allones.symbol = cur_symbol; - } -; - -allzeros: - T_ALLZEROS - { - if (allzeros.symbol != NULL) { - stop("Only one definition of allzeros allowed", - EX_DATAERR); - /* NOTREACHED */ - } - allzeros.symbol = cur_symbol; - } -; - -none: - T_NONE - { - if (none.symbol != NULL) { - stop("Only one definition of none allowed", - EX_DATAERR); - /* NOTREACHED */ - } - none.symbol = cur_symbol; - } -; - -sindex: - T_SINDEX - { - if (sindex.symbol != NULL) { - stop("Only one definition of sindex allowed", - EX_DATAERR); - /* NOTREACHED */ - } - sindex.symbol = cur_symbol; - } -; - -expression: - expression '|' expression - { - $$.value = $1.value | $3.value; - symlist_merge(&$$.referenced_syms, - &$1.referenced_syms, - &$3.referenced_syms); - } -| expression '&' expression - { - $$.value = $1.value & $3.value; - symlist_merge(&$$.referenced_syms, - &$1.referenced_syms, - &$3.referenced_syms); - } -| expression '+' expression - { - $$.value = $1.value + $3.value; - symlist_merge(&$$.referenced_syms, - &$1.referenced_syms, - &$3.referenced_syms); - } -| expression '-' expression - { - $$.value = $1.value - $3.value; - symlist_merge(&($$.referenced_syms), - &($1.referenced_syms), - &($3.referenced_syms)); - } -| expression '*' expression - { - $$.value = $1.value * $3.value; - symlist_merge(&($$.referenced_syms), - &($1.referenced_syms), - &($3.referenced_syms)); - } -| expression '/' expression - { - $$.value = $1.value / $3.value; - symlist_merge(&($$.referenced_syms), - &($1.referenced_syms), - &($3.referenced_syms)); - } -| expression T_EXPR_LSHIFT expression - { - $$.value = $1.value << $3.value; - symlist_merge(&$$.referenced_syms, - &$1.referenced_syms, - &$3.referenced_syms); - } -| expression T_EXPR_RSHIFT expression - { - $$.value = $1.value >> $3.value; - symlist_merge(&$$.referenced_syms, - &$1.referenced_syms, - &$3.referenced_syms); - } -| '(' expression ')' - { - $$ = $2; - } -| '~' expression - { - $$ = $2; - $$.value = (~$$.value) & 0xFF; - } -| '-' expression %prec UMINUS - { - $$ = $2; - $$.value = -$$.value; - } -| T_NUMBER - { - $$.value = $1; - SLIST_INIT(&$$.referenced_syms); - } -| T_SYMBOL - { - symbol_t *symbol; - - symbol = $1; - switch (symbol->type) { - case ALIAS: - symbol = $1->info.ainfo->parent; - case REGISTER: - case SCBLOC: - case SRAMLOC: - $$.value = symbol->info.rinfo->address; - break; - case MASK: - case BIT: - $$.value = symbol->info.minfo->mask; - break; - case DOWNLOAD_CONST: - case CONST: - $$.value = symbol->info.cinfo->value; - break; - case UNINITIALIZED: - default: - { - snprintf(errbuf, sizeof(errbuf), - "Undefined symbol %s referenced", - symbol->name); - stop(errbuf, EX_DATAERR); - /* NOTREACHED */ - break; - } - } - SLIST_INIT(&$$.referenced_syms); - symlist_add(&$$.referenced_syms, symbol, SYMLIST_INSERT_HEAD); - } -; - -constant: - T_CONST T_SYMBOL numerical_value - { - if ($2->type != UNINITIALIZED) { - stop("Re-definition of symbol as a constant", - EX_DATAERR); - /* NOTREACHED */ - } - $2->type = CONST; - initialize_symbol($2); - $2->info.cinfo->value = $3; - } -| T_CONST T_SYMBOL T_DOWNLOAD - { - if ($1) { - stop("Invalid downloaded constant declaration", - EX_DATAERR); - /* NOTREACHED */ - } - if ($2->type != UNINITIALIZED) { - stop("Re-definition of symbol as a downloaded constant", - EX_DATAERR); - /* NOTREACHED */ - } - $2->type = DOWNLOAD_CONST; - initialize_symbol($2); - $2->info.cinfo->value = download_constant_count++; - } -; - -macrodefn_prologue: - T_DEFINE T_SYMBOL - { - if ($2->type != UNINITIALIZED) { - stop("Re-definition of symbol as a macro", - EX_DATAERR); - /* NOTREACHED */ - } - cur_symbol = $2; - cur_symbol->type = MACRO; - initialize_symbol(cur_symbol); - } -; - -macrodefn: - macrodefn_prologue T_MACROBODY - { - add_macro_body($2); - } -| macrodefn_prologue '(' macro_arglist ')' T_MACROBODY - { - add_macro_body($5); - cur_symbol->info.macroinfo->narg = $3; - } -; - -macro_arglist: - { - /* Macros can take no arguments */ - $$ = 0; - } -| T_ARG - { - $$ = 1; - add_macro_arg($1, 0); - } -| macro_arglist ',' T_ARG - { - if ($1 == 0) { - stop("Comma without preceeding argument in arg list", - EX_DATAERR); - /* NOTREACHED */ - } - $$ = $1 + 1; - add_macro_arg($3, $1); - } -; - -numerical_value: - T_NUMBER - { - $$ = $1; - } -| '-' T_NUMBER - { - $$ = -$2; - } -; - -scratch_ram: - T_SRAM '{' - { - snprintf(errbuf, sizeof(errbuf), "%s%d", SRAM_SYMNAME, - num_srams); - cur_symbol = symtable_get(SRAM_SYMNAME); - cur_symtype = SRAMLOC; - cur_symbol->type = SRAMLOC; - initialize_symbol(cur_symbol); - } - reg_address - { - sram_or_scb_offset = cur_symbol->info.rinfo->address; - } - size - { - scb_or_sram_symbol = cur_symbol; - } - scb_or_sram_attributes - '}' - { - cur_symbol = NULL; - scb_or_sram_symbol = NULL; - } -; - -scb: - T_SCB '{' - { - cur_symbol = symtable_get(SCB_SYMNAME); - cur_symtype = SCBLOC; - if (cur_symbol->type != UNINITIALIZED) { - stop("Only one SRAM definition allowed", - EX_SOFTWARE); - /* NOTREACHED */ - } - cur_symbol->type = SCBLOC; - initialize_symbol(cur_symbol); - /* 64 bytes of SCB space */ - cur_symbol->info.rinfo->size = 64; - } - reg_address - { - sram_or_scb_offset = cur_symbol->info.rinfo->address; - } - size - { - scb_or_sram_symbol = cur_symbol; - } - scb_or_sram_attributes - '}' - { - cur_symbol = NULL; - scb_or_sram_symbol = NULL; - } -; - -scb_or_sram_attributes: - /* NULL definition is okay */ -| modes -| scb_or_sram_reg_list -| modes scb_or_sram_reg_list -; - -scb_or_sram_reg_list: - reg_definition -| scb_or_sram_reg_list reg_definition -; - -reg_symbol: - T_SYMBOL - { - process_register(&$1); - $$.symbol = $1; - $$.offset = 0; - } -| T_SYMBOL '[' T_SYMBOL ']' - { - process_register(&$1); - if ($3->type != CONST) { - stop("register offset must be a constant", EX_DATAERR); - /* NOTREACHED */ - } - if (($3->info.cinfo->value + 1) > $1->info.rinfo->size) { - stop("Accessing offset beyond range of register", - EX_DATAERR); - /* NOTREACHED */ - } - $$.symbol = $1; - $$.offset = $3->info.cinfo->value; - } -| T_SYMBOL '[' T_NUMBER ']' - { - process_register(&$1); - if (($3 + 1) > $1->info.rinfo->size) { - stop("Accessing offset beyond range of register", - EX_DATAERR); - /* NOTREACHED */ - } - $$.symbol = $1; - $$.offset = $3; - } -| T_A - { - if (accumulator.symbol == NULL) { - stop("No accumulator has been defined", EX_DATAERR); - /* NOTREACHED */ - } - $$.symbol = accumulator.symbol; - $$.offset = 0; - } -; - -destination: - reg_symbol - { - test_writable_symbol($1.symbol); - $$ = $1; - } -; - -immediate: - expression - { $$ = $1; } -; - -immediate_or_a: - expression - { - if ($1.value == 0 && is_download_const(&$1) == 0) { - snprintf(errbuf, sizeof(errbuf), - "\nExpression evaluates to 0 and thus " - "references the accumulator.\n " - "If this is the desired effect, use 'A' " - "instead.\n"); - stop(errbuf, EX_DATAERR); - } - $$ = $1; - } -| T_A - { - SLIST_INIT(&$$.referenced_syms); - $$.value = 0; - } -; - -source: - reg_symbol - { - test_readable_symbol($1.symbol); - $$ = $1; - } -; - -opt_source: - { - $$.symbol = NULL; - $$.offset = 0; - } -| ',' source - { $$ = $2; } -; - -ret: - { $$ = 0; } -| T_RET - { $$ = 1; } -; - -set_src_mode: - T_SET_SRC_MODE T_NUMBER ';' - { - src_mode = $2; - } -; - -set_dst_mode: - T_SET_DST_MODE T_NUMBER ';' - { - dst_mode = $2; - } -; - -critical_section_start: - T_BEGIN_CS ';' - { - critical_section_t *cs; - - if (in_critical_section != FALSE) { - stop("Critical Section within Critical Section", - EX_DATAERR); - /* NOTREACHED */ - } - cs = cs_alloc(); - cs->begin_addr = instruction_ptr; - in_critical_section = TRUE; - } - -critical_section_end: - T_END_CS ';' - { - critical_section_t *cs; - - if (in_critical_section == FALSE) { - stop("Unballanced 'end_cs'", EX_DATAERR); - /* NOTREACHED */ - } - cs = TAILQ_LAST(&cs_tailq, cs_tailq); - cs->end_addr = instruction_ptr; - in_critical_section = FALSE; - } - -export: - { $$ = 0; } -| T_EXPORT - { $$ = 1; } -; - -label: - export T_SYMBOL ':' - { - if ($2->type != UNINITIALIZED) { - stop("Program label multiply defined", EX_DATAERR); - /* NOTREACHED */ - } - $2->type = LABEL; - initialize_symbol($2); - $2->info.linfo->address = instruction_ptr; - $2->info.linfo->exported = $1; - } -; - -address: - T_SYMBOL - { - $$.symbol = $1; - $$.offset = 0; - } -| T_SYMBOL '+' T_NUMBER - { - $$.symbol = $1; - $$.offset = $3; - } -| T_SYMBOL '-' T_NUMBER - { - $$.symbol = $1; - $$.offset = -$3; - } -| '.' - { - $$.symbol = NULL; - $$.offset = 0; - } -| '.' '+' T_NUMBER - { - $$.symbol = NULL; - $$.offset = $3; - } -| '.' '-' T_NUMBER - { - $$.symbol = NULL; - $$.offset = -$3; - } -; - -conditional: - T_IF T_CEXPR '{' - { - scope_t *new_scope; - - add_conditional($2); - new_scope = scope_alloc(); - new_scope->type = SCOPE_IF; - new_scope->begin_addr = instruction_ptr; - new_scope->func_num = $2->info.condinfo->func_num; - } -| T_ELSE T_IF T_CEXPR '{' - { - scope_t *new_scope; - scope_t *scope_context; - scope_t *last_scope; - - /* - * Ensure that the previous scope is either an - * if or and else if. - */ - scope_context = SLIST_FIRST(&scope_stack); - last_scope = TAILQ_LAST(&scope_context->inner_scope, - scope_tailq); - if (last_scope == NULL - || last_scope->type == T_ELSE) { - - stop("'else if' without leading 'if'", EX_DATAERR); - /* NOTREACHED */ - } - add_conditional($3); - new_scope = scope_alloc(); - new_scope->type = SCOPE_ELSE_IF; - new_scope->begin_addr = instruction_ptr; - new_scope->func_num = $3->info.condinfo->func_num; - } -| T_ELSE '{' - { - scope_t *new_scope; - scope_t *scope_context; - scope_t *last_scope; - - /* - * Ensure that the previous scope is either an - * if or and else if. - */ - scope_context = SLIST_FIRST(&scope_stack); - last_scope = TAILQ_LAST(&scope_context->inner_scope, - scope_tailq); - if (last_scope == NULL - || last_scope->type == SCOPE_ELSE) { - - stop("'else' without leading 'if'", EX_DATAERR); - /* NOTREACHED */ - } - new_scope = scope_alloc(); - new_scope->type = SCOPE_ELSE; - new_scope->begin_addr = instruction_ptr; - } -; - -conditional: - '}' - { - scope_t *scope_context; - - scope_context = SLIST_FIRST(&scope_stack); - if (scope_context->type == SCOPE_ROOT) { - stop("Unexpected '}' encountered", EX_DATAERR); - /* NOTREACHED */ - } - - scope_context->end_addr = instruction_ptr; - - /* Pop the scope */ - SLIST_REMOVE_HEAD(&scope_stack, scope_stack_links); - - process_scope(scope_context); - - if (SLIST_FIRST(&scope_stack) == NULL) { - stop("Unexpected '}' encountered", EX_DATAERR); - /* NOTREACHED */ - } - } -; - -f1_opcode: - T_AND { $$ = AIC_OP_AND; } -| T_XOR { $$ = AIC_OP_XOR; } -| T_ADD { $$ = AIC_OP_ADD; } -| T_ADC { $$ = AIC_OP_ADC; } -; - -code: - f1_opcode destination ',' immediate_or_a opt_source ret ';' - { - format_1_instr($1, &$2, &$4, &$5, $6); - } -; - -code: - T_OR reg_symbol ',' immediate_or_a opt_source ret ';' - { - format_1_instr(AIC_OP_OR, &$2, &$4, &$5, $6); - } -; - -code: - T_INC destination opt_source ret ';' - { - expression_t immed; - - make_expression(&immed, 1); - format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); - } -; - -code: - T_DEC destination opt_source ret ';' - { - expression_t immed; - - make_expression(&immed, -1); - format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); - } -; - -code: - T_CLC ret ';' - { - expression_t immed; - - make_expression(&immed, -1); - format_1_instr(AIC_OP_ADD, &none, &immed, &allzeros, $2); - } -| T_CLC T_MVI destination ',' immediate_or_a ret ';' - { - format_1_instr(AIC_OP_ADD, &$3, &$5, &allzeros, $6); - } -; - -code: - T_STC ret ';' - { - expression_t immed; - - make_expression(&immed, 1); - format_1_instr(AIC_OP_ADD, &none, &immed, &allones, $2); - } -| T_STC destination ret ';' - { - expression_t immed; - - make_expression(&immed, 1); - format_1_instr(AIC_OP_ADD, &$2, &immed, &allones, $3); - } -; - -code: - T_BMOV destination ',' source ',' immediate ret ';' - { - format_1_instr(AIC_OP_BMOV, &$2, &$6, &$4, $7); - } -; - -code: - T_MOV destination ',' source ret ';' - { - expression_t immed; - - make_expression(&immed, 1); - format_1_instr(AIC_OP_BMOV, &$2, &immed, &$4, $5); - } -; - -code: - T_MVI destination ',' immediate_or_a ret ';' - { - format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5); - } -; - -code: - T_NOT destination opt_source ret ';' - { - expression_t immed; - - make_expression(&immed, 0xff); - format_1_instr(AIC_OP_XOR, &$2, &immed, &$3, $4); - } -; - -code: - T_CLR destination ret ';' - { - expression_t immed; - - make_expression(&immed, 0xff); - format_1_instr(AIC_OP_AND, &$2, &immed, &allzeros, $3); - } -; - -code: - T_NOP ret ';' - { - expression_t immed; - - make_expression(&immed, 0xff); - format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, $2); - } -; - -code: - T_RET ';' - { - expression_t immed; - - make_expression(&immed, 0xff); - format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, TRUE); - } -; - - /* - * This grammer differs from the one in the aic7xxx - * reference manual since the grammer listed there is - * ambiguous and causes a shift/reduce conflict. - * It also seems more logical as the "immediate" - * argument is listed as the second arg like the - * other formats. - */ - -f2_opcode: - T_SHL { $$ = AIC_OP_SHL; } -| T_SHR { $$ = AIC_OP_SHR; } -| T_ROL { $$ = AIC_OP_ROL; } -| T_ROR { $$ = AIC_OP_ROR; } -; - -code: - f2_opcode destination ',' expression opt_source ret ';' - { - format_2_instr($1, &$2, &$4, &$5, $6); - } -; - -jmp_jc_jnc_call: - T_JMP { $$ = AIC_OP_JMP; } -| T_JC { $$ = AIC_OP_JC; } -| T_JNC { $$ = AIC_OP_JNC; } -| T_CALL { $$ = AIC_OP_CALL; } -; - -jz_jnz: - T_JZ { $$ = AIC_OP_JZ; } -| T_JNZ { $$ = AIC_OP_JNZ; } -; - -je_jne: - T_JE { $$ = AIC_OP_JE; } -| T_JNE { $$ = AIC_OP_JNE; } -; - -code: - jmp_jc_jnc_call address ';' - { - expression_t immed; - - make_expression(&immed, 0); - format_3_instr($1, &sindex, &immed, &$2); - } -; - -code: - T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';' - { - format_3_instr($5, &$2, &$4, &$6); - } -; - -code: - T_TEST source ',' immediate_or_a jz_jnz address ';' - { - format_3_instr($5, &$2, &$4, &$6); - } -; - -code: - T_CMP source ',' immediate_or_a je_jne address ';' - { - format_3_instr($5, &$2, &$4, &$6); - } -; - -code: - T_MOV source jmp_jc_jnc_call address ';' - { - expression_t immed; - - make_expression(&immed, 0); - format_3_instr($3, &$2, &immed, &$4); - } -; - -code: - T_MVI immediate jmp_jc_jnc_call address ';' - { - format_3_instr($3, &allzeros, &$2, &$4); - } -; - -%% - -static void -process_bitmask(int mask_type, symbol_t *sym, int mask) -{ - /* - * Add the current register to its - * symbol list, if it already exists, - * warn if we are setting it to a - * different value, or in the bit to - * the "allowed bits" of this register. - */ - if (sym->type == UNINITIALIZED) { - sym->type = mask_type; - initialize_symbol(sym); - if (mask_type == BIT) { - if (mask == 0) { - stop("Bitmask with no bits set", EX_DATAERR); - /* NOTREACHED */ - } - if ((mask & ~(0x01 << (ffs(mask) - 1))) != 0) { - stop("Bitmask with more than one bit set", - EX_DATAERR); - /* NOTREACHED */ - } - } - sym->info.minfo->mask = mask; - } else if (sym->type != mask_type) { - stop("Bit definition mirrors a definition of the same " - " name, but a different type", EX_DATAERR); - /* NOTREACHED */ - } else if (mask != sym->info.minfo->mask) { - stop("Bitmask redefined with a conflicting value", EX_DATAERR); - /* NOTREACHED */ - } - /* Fail if this symbol is already listed */ - if (symlist_search(&(sym->info.minfo->symrefs), - cur_symbol->name) != NULL) { - stop("Bitmask defined multiple times for register", EX_DATAERR); - /* NOTREACHED */ - } - symlist_add(&(sym->info.minfo->symrefs), cur_symbol, - SYMLIST_INSERT_HEAD); - cur_symbol->info.rinfo->valid_bitmask |= mask; - cur_symbol->info.rinfo->typecheck_masks = TRUE; -} - -static void -initialize_symbol(symbol_t *symbol) -{ - switch (symbol->type) { - case UNINITIALIZED: - stop("Call to initialize_symbol with type field unset", - EX_SOFTWARE); - /* NOTREACHED */ - break; - case REGISTER: - case SRAMLOC: - case SCBLOC: - symbol->info.rinfo = - (struct reg_info *)malloc(sizeof(struct reg_info)); - if (symbol->info.rinfo == NULL) { - stop("Can't create register info", EX_SOFTWARE); - /* NOTREACHED */ - } - memset(symbol->info.rinfo, 0, - sizeof(struct reg_info)); - /* - * Default to allowing access in all register modes - * or to the mode specified by the SCB or SRAM space - * we are in. - */ - if (scb_or_sram_symbol != NULL) - symbol->info.rinfo->modes = - scb_or_sram_symbol->info.rinfo->modes; - else - symbol->info.rinfo->modes = ~0; - break; - case ALIAS: - symbol->info.ainfo = - (struct alias_info *)malloc(sizeof(struct alias_info)); - if (symbol->info.ainfo == NULL) { - stop("Can't create alias info", EX_SOFTWARE); - /* NOTREACHED */ - } - memset(symbol->info.ainfo, 0, - sizeof(struct alias_info)); - break; - case MASK: - case BIT: - symbol->info.minfo = - (struct mask_info *)malloc(sizeof(struct mask_info)); - if (symbol->info.minfo == NULL) { - stop("Can't create bitmask info", EX_SOFTWARE); - /* NOTREACHED */ - } - memset(symbol->info.minfo, 0, sizeof(struct mask_info)); - SLIST_INIT(&(symbol->info.minfo->symrefs)); - break; - case CONST: - case DOWNLOAD_CONST: - symbol->info.cinfo = - (struct const_info *)malloc(sizeof(struct const_info)); - if (symbol->info.cinfo == NULL) { - stop("Can't create alias info", EX_SOFTWARE); - /* NOTREACHED */ - } - memset(symbol->info.cinfo, 0, - sizeof(struct const_info)); - break; - case LABEL: - symbol->info.linfo = - (struct label_info *)malloc(sizeof(struct label_info)); - if (symbol->info.linfo == NULL) { - stop("Can't create label info", EX_SOFTWARE); - /* NOTREACHED */ - } - memset(symbol->info.linfo, 0, - sizeof(struct label_info)); - break; - case CONDITIONAL: - symbol->info.condinfo = - (struct cond_info *)malloc(sizeof(struct cond_info)); - if (symbol->info.condinfo == NULL) { - stop("Can't create conditional info", EX_SOFTWARE); - /* NOTREACHED */ - } - memset(symbol->info.condinfo, 0, - sizeof(struct cond_info)); - break; - case MACRO: - symbol->info.macroinfo = - (struct macro_info *)malloc(sizeof(struct macro_info)); - if (symbol->info.macroinfo == NULL) { - stop("Can't create macro info", EX_SOFTWARE); - /* NOTREACHED */ - } - memset(symbol->info.macroinfo, 0, - sizeof(struct macro_info)); - STAILQ_INIT(&symbol->info.macroinfo->args); - break; - default: - stop("Call to initialize_symbol with invalid symbol type", - EX_SOFTWARE); - /* NOTREACHED */ - break; - } -} - -static void -add_macro_arg(const char *argtext, int argnum) -{ - struct macro_arg *marg; - int i; - int retval; - - - if (cur_symbol == NULL || cur_symbol->type != MACRO) { - stop("Invalid current symbol for adding macro arg", - EX_SOFTWARE); - /* NOTREACHED */ - } - - marg = (struct macro_arg *)malloc(sizeof(*marg)); - if (marg == NULL) { - stop("Can't create macro_arg structure", EX_SOFTWARE); - /* NOTREACHED */ - } - marg->replacement_text = NULL; - retval = snprintf(regex_pattern, sizeof(regex_pattern), - "[^-/A-Za-z0-9_](%s)([^-/A-Za-z0-9_]|$)", - argtext); - if (retval >= sizeof(regex_pattern)) { - stop("Regex text buffer too small for arg", - EX_SOFTWARE); - /* NOTREACHED */ - } - retval = regcomp(&marg->arg_regex, regex_pattern, REG_EXTENDED); - if (retval != 0) { - stop("Regex compilation failed", EX_SOFTWARE); - /* NOTREACHED */ - } - STAILQ_INSERT_TAIL(&cur_symbol->info.macroinfo->args, marg, links); -} - -static void -add_macro_body(const char *bodytext) -{ - if (cur_symbol == NULL || cur_symbol->type != MACRO) { - stop("Invalid current symbol for adding macro arg", - EX_SOFTWARE); - /* NOTREACHED */ - } - cur_symbol->info.macroinfo->body = strdup(bodytext); - if (cur_symbol->info.macroinfo->body == NULL) { - stop("Can't duplicate macro body text", EX_SOFTWARE); - /* NOTREACHED */ - } -} - -static void -process_register(symbol_t **p_symbol) -{ - symbol_t *symbol = *p_symbol; - - if (symbol->type == UNINITIALIZED) { - snprintf(errbuf, sizeof(errbuf), "Undefined register %s", - symbol->name); - stop(errbuf, EX_DATAERR); - /* NOTREACHED */ - } else if (symbol->type == ALIAS) { - *p_symbol = symbol->info.ainfo->parent; - } else if ((symbol->type != REGISTER) - && (symbol->type != SCBLOC) - && (symbol->type != SRAMLOC)) { - snprintf(errbuf, sizeof(errbuf), - "Specified symbol %s is not a register", - symbol->name); - stop(errbuf, EX_DATAERR); - } -} - -static void -format_1_instr(int opcode, symbol_ref_t *dest, expression_t *immed, - symbol_ref_t *src, int ret) -{ - struct instruction *instr; - struct ins_format1 *f1_instr; - - if (src->symbol == NULL) - src = dest; - - /* Test register permissions */ - test_writable_symbol(dest->symbol); - test_readable_symbol(src->symbol); - - /* Ensure that immediate makes sense for this destination */ - type_check(dest->symbol, immed, opcode); - - /* Allocate sequencer space for the instruction and fill it out */ - instr = seq_alloc(); - f1_instr = &instr->format.format1; - f1_instr->ret = ret ? 1 : 0; - f1_instr->opcode = opcode; - f1_instr->destination = dest->symbol->info.rinfo->address - + dest->offset; - f1_instr->source = src->symbol->info.rinfo->address - + src->offset; - f1_instr->immediate = immed->value; - - if (is_download_const(immed)) - f1_instr->parity = 1; - else if (dest->symbol == mode_ptr.symbol) { - u_int src_value; - u_int dst_value; - - /* - * Attempt to update mode information if - * we are operating on the mode register. - */ - if (src->symbol == allones.symbol) - src_value = 0xFF; - else if (src->symbol == allzeros.symbol) - src_value = 0; - else if (src->symbol == mode_ptr.symbol) - src_value = (dst_mode << 4) | src_mode; - else - goto cant_update; - - switch (opcode) { - case AIC_OP_AND: - dst_value = src_value & immed->value; - break; - case AIC_OP_XOR: - dst_value = src_value ^ immed->value; - break; - case AIC_OP_ADD: - dst_value = (src_value + immed->value) & 0xFF; - break; - case AIC_OP_OR: - dst_value = src_value | immed->value; - break; - break; - case AIC_OP_BMOV: - dst_value = src_value; - break; - default: - goto cant_update; - } - src_mode = dst_value & 0xF; - dst_mode = (dst_value >> 4) & 0xF; -cant_update: - } - - symlist_free(&immed->referenced_syms); - instruction_ptr++; -} - -static void -format_2_instr(int opcode, symbol_ref_t *dest, expression_t *places, - symbol_ref_t *src, int ret) -{ - struct instruction *instr; - struct ins_format2 *f2_instr; - uint8_t shift_control; - - if (src->symbol == NULL) - src = dest; - - /* Test register permissions */ - test_writable_symbol(dest->symbol); - test_readable_symbol(src->symbol); - - /* Allocate sequencer space for the instruction and fill it out */ - instr = seq_alloc(); - f2_instr = &instr->format.format2; - f2_instr->ret = ret ? 1 : 0; - f2_instr->opcode = AIC_OP_ROL; - f2_instr->destination = dest->symbol->info.rinfo->address - + dest->offset; - f2_instr->source = src->symbol->info.rinfo->address - + src->offset; - if (places->value > 8 || places->value <= 0) { - stop("illegal shift value", EX_DATAERR); - /* NOTREACHED */ - } - switch (opcode) { - case AIC_OP_SHL: - if (places->value == 8) - shift_control = 0xf0; - else - shift_control = (places->value << 4) | places->value; - break; - case AIC_OP_SHR: - if (places->value == 8) { - shift_control = 0xf8; - } else { - shift_control = (places->value << 4) - | (8 - places->value) - | 0x08; - } - break; - case AIC_OP_ROL: - shift_control = places->value & 0x7; - break; - case AIC_OP_ROR: - shift_control = (8 - places->value) | 0x08; - break; - default: - shift_control = 0; /* Quiet Compiler */ - stop("Invalid shift operation specified", EX_SOFTWARE); - /* NOTREACHED */ - break; - }; - f2_instr->shift_control = shift_control; - symlist_free(&places->referenced_syms); - instruction_ptr++; -} - -static void -format_3_instr(int opcode, symbol_ref_t *src, - expression_t *immed, symbol_ref_t *address) -{ - struct instruction *instr; - struct ins_format3 *f3_instr; - int addr; - - /* Test register permissions */ - test_readable_symbol(src->symbol); - - /* Ensure that immediate makes sense for this source */ - type_check(src->symbol, immed, opcode); - - /* Allocate sequencer space for the instruction and fill it out */ - instr = seq_alloc(); - f3_instr = &instr->format.format3; - if (address->symbol == NULL) { - /* 'dot' referrence. Use the current instruction pointer */ - addr = instruction_ptr + address->offset; - } else if (address->symbol->type == UNINITIALIZED) { - /* forward reference */ - addr = address->offset; - instr->patch_label = address->symbol; - } else - addr = address->symbol->info.linfo->address + address->offset; - f3_instr->opcode = opcode; - f3_instr->address = addr; - f3_instr->source = src->symbol->info.rinfo->address - + src->offset; - f3_instr->immediate = immed->value; - - if (is_download_const(immed)) - f3_instr->parity = 1; - - symlist_free(&immed->referenced_syms); - instruction_ptr++; -} - -static void -test_readable_symbol(symbol_t *symbol) -{ - - if ((symbol->info.rinfo->modes & (0x1 << src_mode)) == 0) { - snprintf(errbuf, sizeof(errbuf), - "Register %s unavailable in source reg mode %d", - symbol->name, src_mode); - stop(errbuf, EX_DATAERR); - } - - if (symbol->info.rinfo->mode == WO) { - stop("Write Only register specified as source", - EX_DATAERR); - /* NOTREACHED */ - } -} - -static void -test_writable_symbol(symbol_t *symbol) -{ - - if ((symbol->info.rinfo->modes & (0x1 << dst_mode)) == 0) { - snprintf(errbuf, sizeof(errbuf), - "Register %s unavailable in destination reg mode %d", - symbol->name, dst_mode); - stop(errbuf, EX_DATAERR); - } - - if (symbol->info.rinfo->mode == RO) { - stop("Read Only register specified as destination", - EX_DATAERR); - /* NOTREACHED */ - } -} - -static void -type_check(symbol_t *symbol, expression_t *expression, int opcode) -{ - symbol_node_t *node; - int and_op; - - and_op = FALSE; - if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || AIC_OP_JZ) - and_op = TRUE; - - /* - * Make sure that we aren't attempting to write something - * that hasn't been defined. If this is an and operation, - * this is a mask, so "undefined" bits are okay. - */ - if (and_op == FALSE - && (expression->value & ~symbol->info.rinfo->valid_bitmask) != 0) { - snprintf(errbuf, sizeof(errbuf), - "Invalid bit(s) 0x%x in immediate written to %s", - expression->value & ~symbol->info.rinfo->valid_bitmask, - symbol->name); - stop(errbuf, EX_DATAERR); - /* NOTREACHED */ - } - - /* - * Now make sure that all of the symbols referenced by the - * expression are defined for this register. - */ - if (symbol->info.rinfo->typecheck_masks != FALSE) { - for(node = expression->referenced_syms.slh_first; - node != NULL; - node = node->links.sle_next) { - if ((node->symbol->type == MASK - || node->symbol->type == BIT) - && symlist_search(&node->symbol->info.minfo->symrefs, - symbol->name) == NULL) { - snprintf(errbuf, sizeof(errbuf), - "Invalid bit or mask %s " - "for register %s", - node->symbol->name, symbol->name); - stop(errbuf, EX_DATAERR); - /* NOTREACHED */ - } - } - } -} - -static void -make_expression(expression_t *immed, int value) -{ - SLIST_INIT(&immed->referenced_syms); - immed->value = value & 0xff; -} - -static void -add_conditional(symbol_t *symbol) -{ - static int numfuncs; - - if (numfuncs == 0) { - /* add a special conditional, "0" */ - symbol_t *false_func; - - false_func = symtable_get("0"); - if (false_func->type != UNINITIALIZED) { - stop("Conditional expression '0' " - "conflicts with a symbol", EX_DATAERR); - /* NOTREACHED */ - } - false_func->type = CONDITIONAL; - initialize_symbol(false_func); - false_func->info.condinfo->func_num = numfuncs++; - symlist_add(&patch_functions, false_func, SYMLIST_INSERT_HEAD); - } - - /* This condition has occurred before */ - if (symbol->type == CONDITIONAL) - return; - - if (symbol->type != UNINITIALIZED) { - stop("Conditional expression conflicts with a symbol", - EX_DATAERR); - /* NOTREACHED */ - } - - symbol->type = CONDITIONAL; - initialize_symbol(symbol); - symbol->info.condinfo->func_num = numfuncs++; - symlist_add(&patch_functions, symbol, SYMLIST_INSERT_HEAD); -} - -static void -add_version(const char *verstring) -{ - const char prefix[] = " * "; - int newlen; - int oldlen; - - newlen = strlen(verstring) + strlen(prefix); - oldlen = 0; - if (versions != NULL) - oldlen = strlen(versions); - versions = realloc(versions, newlen + oldlen + 2); - if (versions == NULL) - stop("Can't allocate version string", EX_SOFTWARE); - strcpy(&versions[oldlen], prefix); - strcpy(&versions[oldlen + strlen(prefix)], verstring); - versions[newlen + oldlen] = '\n'; - versions[newlen + oldlen + 1] = '\0'; -} - -void -yyerror(const char *string) -{ - stop(string, EX_DATAERR); -} - -static int -is_download_const(expression_t *immed) -{ - if ((immed->referenced_syms.slh_first != NULL) - && (immed->referenced_syms.slh_first->symbol->type == DOWNLOAD_CONST)) - return (TRUE); - - return (FALSE); -} diff --git a/xen/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h b/xen/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h deleted file mode 100644 index aeba6dacbb..0000000000 --- a/xen/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Instruction formats for the sequencer program downloaded to - * Aic7xxx SCSI host adapters - * - * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_insformat.h#9 $ - * - * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_insformat.h,v 1.3.2.3 2002/04/29 19:36:36 gibbs Exp $ - */ - -struct ins_format1 { -#if BYTE_ORDER == LITTLE_ENDIAN - uint32_t immediate : 8, - source : 9, - destination : 9, - ret : 1, - opcode : 4, - parity : 1; -#else - uint32_t parity : 1, - opcode : 4, - ret : 1, - destination : 9, - source : 9, - immediate : 8; -#endif -}; - -struct ins_format2 { -#if BYTE_ORDER == LITTLE_ENDIAN - uint32_t shift_control : 8, - source : 9, - destination : 9, - ret : 1, - opcode : 4, - parity : 1; -#else - uint32_t parity : 1, - opcode : 4, - ret : 1, - destination : 9, - source : 9, - shift_control : 8; -#endif -}; - -struct ins_format3 { -#if BYTE_ORDER == LITTLE_ENDIAN - uint32_t immediate : 8, - source : 9, - address : 10, - opcode : 4, - parity : 1; -#else - uint32_t parity : 1, - opcode : 4, - address : 10, - source : 9, - immediate : 8; -#endif -}; - -union ins_formats { - struct ins_format1 format1; - struct ins_format2 format2; - struct ins_format3 format3; - uint8_t bytes[4]; - uint32_t integer; -}; -struct instruction { - union ins_formats format; - u_int srcline; - struct symbol *patch_label; - STAILQ_ENTRY(instruction) links; -}; - -#define AIC_OP_OR 0x0 -#define AIC_OP_AND 0x1 -#define AIC_OP_XOR 0x2 -#define AIC_OP_ADD 0x3 -#define AIC_OP_ADC 0x4 -#define AIC_OP_ROL 0x5 -#define AIC_OP_BMOV 0x6 - -#define AIC_OP_JMP 0x8 -#define AIC_OP_JC 0x9 -#define AIC_OP_JNC 0xa -#define AIC_OP_CALL 0xb -#define AIC_OP_JNE 0xc -#define AIC_OP_JNZ 0xd -#define AIC_OP_JE 0xe -#define AIC_OP_JZ 0xf - -/* Pseudo Ops */ -#define AIC_OP_SHL 0x10 -#define AIC_OP_SHR 0x20 -#define AIC_OP_ROR 0x30 diff --git a/xen/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y b/xen/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y deleted file mode 100644 index dabc6c2f2f..0000000000 --- a/xen/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y +++ /dev/null @@ -1,164 +0,0 @@ -%{ -/* - * Sub-parser for macro invocation in the Aic7xxx SCSI - * Host adapter sequencer assembler. - * - * Copyright (c) 2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id$ - * - * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_macro_gram.y,v 1.1.2.1 2002/04/29 19:36:36 gibbs Exp $ - */ - -#include - -#include -#include -#include -#include -#include -#include - -#ifdef __linux__ -#include "../queue.h" -#else -#include -#endif - -#include "aicasm.h" -#include "aicasm_symbol.h" -#include "aicasm_insformat.h" - -static symbol_t *macro_symbol; - -static void add_macro_arg(const char *argtext, int position); - -%} - -%union { - int value; - char *str; - symbol_t *sym; -} - - -%token T_ARG - -%token T_SYMBOL - -%type macro_arglist - -%% - -macrocall: - T_SYMBOL '(' - { - macro_symbol = $1; - } - macro_arglist ')' - { - if (macro_symbol->info.macroinfo->narg != $4) { - printf("Narg == %d", macro_symbol->info.macroinfo->narg); - stop("Too few arguments for macro invocation", - EX_DATAERR); - /* NOTREACHED */ - } - macro_symbol = NULL; - YYACCEPT; - } -; - -macro_arglist: - { - /* Macros can take 0 arguments */ - $$ = 0; - } -| T_ARG - { - $$ = 1; - add_macro_arg($1, 1); - } -| macro_arglist ',' T_ARG - { - if ($1 == 0) { - stop("Comma without preceeding argument in arg list", - EX_DATAERR); - /* NOTREACHED */ - } - $$ = $1 + 1; - add_macro_arg($3, $$); - } -; - -%% - -static void -add_macro_arg(const char *argtext, int argnum) -{ - struct macro_arg *marg; - int i; - - if (macro_symbol == NULL || macro_symbol->type != MACRO) { - stop("Invalid current symbol for adding macro arg", - EX_SOFTWARE); - /* NOTREACHED */ - } - /* - * Macro Invocation. Find the appropriate argument and fill - * in the replace ment text for this call. - */ - i = 0; - STAILQ_FOREACH(marg, ¯o_symbol->info.macroinfo->args, links) { - i++; - if (i == argnum) - break; - } - if (marg == NULL) { - stop("Too many arguments for macro invocation", EX_DATAERR); - /* NOTREACHED */ - } - marg->replacement_text = strdup(argtext); - if (marg->replacement_text == NULL) { - stop("Unable to replicate replacement text", EX_SOFTWARE); - /* NOTREACHED */ - } -} - -void -mmerror(const char *string) -{ - stop(string, EX_DATAERR); -} diff --git a/xen/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l b/xen/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l deleted file mode 100644 index c1bf57efbb..0000000000 --- a/xen/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l +++ /dev/null @@ -1,154 +0,0 @@ -%{ -/* - * Sub-Lexical Analyzer for macro invokation in - * the Aic7xxx SCSI Host adapter sequencer assembler. - * - * Copyright (c) 2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id$ - * - * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_macro_scan.l,v 1.1.2.1 2002/04/29 19:36:36 gibbs Exp $ - */ - -#include - -#include -#include -#include -#include -#include -#ifdef __linux__ -#include "../queue.h" -#else -#include -#endif - -#include "aicasm.h" -#include "aicasm_symbol.h" -#include "aicasm_macro_gram.h" - -#define MAX_STR_CONST 4096 -static char string_buf[MAX_STR_CONST]; -static char *string_buf_ptr; -static int parren_count; -static char buf[255]; -%} - -WORD [A-Za-z_][-A-Za-z_0-9]* -SPACE [ \t]+ -MCARG [^(), \t]+ - -%x ARGLIST - -%% -\n { - ++yylineno; - } -{SPACE} ; -\( { - parren_count++; - if (parren_count == 1) { - string_buf_ptr = string_buf; - return ('('); - } - *string_buf_ptr++ = '('; - } -\) { - if (parren_count == 1) { - if (string_buf_ptr != string_buf) { - /* - * Return an argument and - * rescan this parren so we - * can return it as well. - */ - *string_buf_ptr = '\0'; - mmlval.str = string_buf; - string_buf_ptr = string_buf; - unput(')'); - return T_ARG; - } - BEGIN INITIAL; - return (')'); - } - parren_count--; - *string_buf_ptr++ = ')'; - } -{MCARG} { - char *yptr; - - yptr = mmtext; - while (*yptr) - *string_buf_ptr++ = *yptr++; - } -\, { - if (string_buf_ptr != string_buf) { - /* - * Return an argument and - * rescan this comma so we - * can return it as well. - */ - *string_buf_ptr = '\0'; - mmlval.str = string_buf; - string_buf_ptr = string_buf; - unput(','); - return T_ARG; - } - return ','; - } -{WORD}[(] { - /* May be a symbol or a macro invocation. */ - mmlval.sym = symtable_get(mmtext); - if (mmlval.sym->type != MACRO) { - stop("Expecting Macro Name", - EX_DATAERR); - } - unput('('); - parren_count = 0; - BEGIN ARGLIST; - return T_SYMBOL; - } -. { - snprintf(buf, sizeof(buf), "Invalid character " - "'%c'", mmtext[0]); - stop(buf, EX_DATAERR); - } -%% - -int -mmwrap() -{ - stop("EOF encountered in macro call", EX_DATAERR); -} diff --git a/xen/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l b/xen/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l deleted file mode 100644 index 024c5765cd..0000000000 --- a/xen/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l +++ /dev/null @@ -1,594 +0,0 @@ -%{ -/* - * Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler. - * - * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. - * Copyright (c) 2001 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#11 $ - * - * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_scan.l,v 1.13.2.4 2002/04/29 19:36:36 gibbs Exp $ - */ - -#include - -#include -#include -#include -#include -#include -#ifdef __linux__ -#include "../queue.h" -#else -#include -#endif - -#include "aicasm.h" -#include "aicasm_symbol.h" -#include "aicasm_gram.h" - -/* This is used for macro body capture too, so err on the large size. */ -#define MAX_STR_CONST 4096 -static char string_buf[MAX_STR_CONST]; -static char *string_buf_ptr; -static int parren_count; -static int quote_count; -static char buf[255]; -%} - -PATH ([/]*[-A-Za-z0-9_.])+ -WORD [A-Za-z_][-A-Za-z_0-9]* -SPACE [ \t]+ -MCARG [^(), \t]+ -MBODY ((\\[^\n])*[^\n\\]*)+ - -%x COMMENT -%x CEXPR -%x INCLUDE -%x STRING -%x MACRODEF -%x MACROARGLIST -%x MACROCALLARGS -%x MACROBODY - -%% -\n { ++yylineno; } -"/*" { BEGIN COMMENT; /* Enter comment eating state */ } -"/*" { fprintf(stderr, "Warning! Comment within comment."); } -\n { ++yylineno; } -[^*/\n]* ; -"*"+[^*/\n]* ; -"/"+[^*/\n]* ; -"*"+"/" { BEGIN INITIAL; } -if[ \t]*\( { - string_buf_ptr = string_buf; - parren_count = 1; - BEGIN CEXPR; - return T_IF; - } -\( { *string_buf_ptr++ = '('; parren_count++; } -\) { - parren_count--; - if (parren_count == 0) { - /* All done */ - BEGIN INITIAL; - *string_buf_ptr = '\0'; - yylval.sym = symtable_get(string_buf); - return T_CEXPR; - } else { - *string_buf_ptr++ = ')'; - } - } -\n { ++yylineno; } -[^()\n]+ { - char *yptr; - - yptr = yytext; - while (*yptr != '\0') { - /* Remove duplicate spaces */ - if (*yptr == '\t') - *yptr = ' '; - if (*yptr == ' ' - && string_buf_ptr != string_buf - && string_buf_ptr[-1] == ' ') - yptr++; - else - *string_buf_ptr++ = *yptr++; - } - } - -VERSION { return T_VERSION; } -PATCH_ARG_LIST { return T_PATCH_ARG_LIST; } -\" { - string_buf_ptr = string_buf; - BEGIN STRING; - } -[^"]+ { - char *yptr; - - yptr = yytext; - while (*yptr) - *string_buf_ptr++ = *yptr++; - } -\" { - /* All done */ - BEGIN INITIAL; - *string_buf_ptr = '\0'; - yylval.str = string_buf; - return T_STRING; - } -{SPACE} ; - - /* Register/SCB/SRAM definition keywords */ -export { return T_EXPORT; } -register { return T_REGISTER; } -const { yylval.value = FALSE; return T_CONST; } -download { return T_DOWNLOAD; } -address { return T_ADDRESS; } -access_mode { return T_ACCESS_MODE; } -modes { return T_MODES; } -RW|RO|WO { - if (strcmp(yytext, "RW") == 0) - yylval.value = RW; - else if (strcmp(yytext, "RO") == 0) - yylval.value = RO; - else - yylval.value = WO; - return T_MODE; - } -BEGIN_CRITICAL { return T_BEGIN_CS; } -END_CRITICAL { return T_END_CS; } -SET_SRC_MODE { return T_SET_SRC_MODE; } -SET_DST_MODE { return T_SET_DST_MODE; } -bit { return T_BIT; } -mask { return T_MASK; } -alias { return T_ALIAS; } -size { return T_SIZE; } -scb { return T_SCB; } -scratch_ram { return T_SRAM; } -accumulator { return T_ACCUM; } -mode_pointer { return T_MODE_PTR; } -allones { return T_ALLONES; } -allzeros { return T_ALLZEROS; } -none { return T_NONE; } -sindex { return T_SINDEX; } -A { return T_A; } - - /* Opcodes */ -shl { return T_SHL; } -shr { return T_SHR; } -ror { return T_ROR; } -rol { return T_ROL; } -mvi { return T_MVI; } -mov { return T_MOV; } -clr { return T_CLR; } -jmp { return T_JMP; } -jc { return T_JC; } -jnc { return T_JNC; } -je { return T_JE; } -jne { return T_JNE; } -jz { return T_JZ; } -jnz { return T_JNZ; } -call { return T_CALL; } -add { return T_ADD; } -adc { return T_ADC; } -bmov { return T_BMOV; } -inc { return T_INC; } -dec { return T_DEC; } -stc { return T_STC; } -clc { return T_CLC; } -cmp { return T_CMP; } -not { return T_NOT; } -xor { return T_XOR; } -test { return T_TEST;} -and { return T_AND; } -or { return T_OR; } -ret { return T_RET; } -nop { return T_NOP; } -else { return T_ELSE; } - - /* Allowed Symbols */ -\<\< { return T_EXPR_LSHIFT; } -\>\> { return T_EXPR_RSHIFT; } -[-+,:()~|&."{};<>[\]/*!=] { return yytext[0]; } - - /* Number processing */ -0[0-7]* { - yylval.value = strtol(yytext, NULL, 8); - return T_NUMBER; - } - -0[xX][0-9a-fA-F]+ { - yylval.value = strtoul(yytext + 2, NULL, 16); - return T_NUMBER; - } - -[1-9][0-9]* { - yylval.value = strtol(yytext, NULL, 10); - return T_NUMBER; - } - /* Include Files */ -#include{SPACE} { - BEGIN INCLUDE; - quote_count = 0; - return T_INCLUDE; - } -[<] { return yytext[0]; } -[>] { BEGIN INITIAL; return yytext[0]; } -[\"] { - if (quote_count != 0) - BEGIN INITIAL; - quote_count++; - return yytext[0]; - } -{PATH} { - char *yptr; - - yptr = yytext; - string_buf_ptr = string_buf; - while (*yptr) - *string_buf_ptr++ = *yptr++; - yylval.str = string_buf; - *string_buf_ptr = '\0'; - return T_PATH; - } -. { stop("Invalid include line", EX_DATAERR); } -#define{SPACE} { - BEGIN MACRODEF; - return T_DEFINE; - } -{WORD}{SPACE} { - char *yptr; - - /* Strip space and return as a normal symbol */ - yptr = yytext; - while (*yptr != ' ' && *yptr != '\t') - yptr++; - *yptr = '\0'; - yylval.sym = symtable_get(yytext); - string_buf_ptr = string_buf; - BEGIN MACROBODY; - return T_SYMBOL; - } -{WORD}\( { - /* - * We store the symbol with its opening - * parren so we can differentiate macros - * that take args from macros with the - * same name that do not take args as - * is allowed in C. - */ - BEGIN MACROARGLIST; - yylval.sym = symtable_get(yytext); - unput('('); - return T_SYMBOL; - } -{WORD} { - yylval.str = yytext; - return T_ARG; - } -{SPACE} ; -[(,] { - return yytext[0]; - } -[)] { - string_buf_ptr = string_buf; - BEGIN MACROBODY; - return ')'; - } -. { - snprintf(buf, sizeof(buf), "Invalid character " - "'%c' in macro argument list", - yytext[0]); - stop(buf, EX_DATAERR); - } -{SPACE} ; -\( { - parren_count++; - if (parren_count == 1) - return ('('); - *string_buf_ptr++ = '('; - } -\) { - parren_count--; - if (parren_count == 0) { - BEGIN INITIAL; - return (')'); - } - *string_buf_ptr++ = ')'; - } -{MCARG} { - char *yptr; - - yptr = yytext; - while (*yptr) - *string_buf_ptr++ = *yptr++; - } -\, { - if (string_buf_ptr != string_buf) { - /* - * Return an argument and - * rescan this comma so we - * can return it as well. - */ - *string_buf_ptr = '\0'; - yylval.str = string_buf; - string_buf_ptr = string_buf; - unput(','); - return T_ARG; - } - return ','; - } -\\\n { - /* Eat escaped newlines. */ - ++yylineno; - } -\n { - /* Macros end on the first unescaped newline. */ - BEGIN INITIAL; - *string_buf_ptr = '\0'; - yylval.str = string_buf; - ++yylineno; - return T_MACROBODY; - } -{MBODY} { - char *yptr; - - yptr = yytext; - while (*yptr) - *string_buf_ptr++ = *yptr++; - } -{WORD}\( { - char *yptr; - char *ycopy; - - /* May be a symbol or a macro invocation. */ - yylval.sym = symtable_get(yytext); - if (yylval.sym->type == MACRO) { - YY_BUFFER_STATE old_state; - YY_BUFFER_STATE temp_state; - - ycopy = strdup(yytext); - yptr = ycopy + yyleng; - while (yptr > ycopy) - unput(*--yptr); - old_state = YY_CURRENT_BUFFER; - temp_state = - yy_create_buffer(stdin, - YY_BUF_SIZE); - yy_switch_to_buffer(temp_state); - mm_switch_to_buffer(old_state); - mmparse(); - mm_switch_to_buffer(temp_state); - yy_switch_to_buffer(old_state); - mm_delete_buffer(temp_state); - expand_macro(yylval.sym); - } else { - if (yylval.sym->type == UNINITIALIZED) { - /* Try without the '(' */ - symbol_delete(yylval.sym); - yytext[yyleng-1] = '\0'; - yylval.sym = - symtable_get(yytext); - } - unput('('); - return T_SYMBOL; - } - } -{WORD} { - yylval.sym = symtable_get(yytext); - if (yylval.sym->type == MACRO) { - expand_macro(yylval.sym); - } else { - return T_SYMBOL; - } - } -. { - snprintf(buf, sizeof(buf), "Invalid character " - "'%c'", yytext[0]); - stop(buf, EX_DATAERR); - } -%% - -typedef struct include { - YY_BUFFER_STATE buffer; - int lineno; - char *filename; - SLIST_ENTRY(include) links; -}include_t; - -SLIST_HEAD(, include) include_stack; - -void -include_file(char *file_name, include_type type) -{ - FILE *newfile; - include_t *include; - - newfile = NULL; - /* Try the current directory first */ - if (includes_search_curdir != 0 || type == SOURCE_FILE) - newfile = fopen(file_name, "r"); - - if (newfile == NULL && type != SOURCE_FILE) { - path_entry_t include_dir; - for (include_dir = search_path.slh_first; - include_dir != NULL; - include_dir = include_dir->links.sle_next) { - char fullname[PATH_MAX]; - - if ((include_dir->quoted_includes_only == TRUE) - && (type != QUOTED_INCLUDE)) - continue; - - snprintf(fullname, sizeof(fullname), - "%s/%s", include_dir->directory, file_name); - - if ((newfile = fopen(fullname, "r")) != NULL) - break; - } - } - - if (newfile == NULL) { - perror(file_name); - stop("Unable to open input file", EX_SOFTWARE); - /* NOTREACHED */ - } - - if (type != SOURCE_FILE) { - include = (include_t *)malloc(sizeof(include_t)); - if (include == NULL) { - stop("Unable to allocate include stack entry", - EX_SOFTWARE); - /* NOTREACHED */ - } - include->buffer = YY_CURRENT_BUFFER; - include->lineno = yylineno; - include->filename = yyfilename; - SLIST_INSERT_HEAD(&include_stack, include, links); - } - yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE)); - yylineno = 1; - yyfilename = strdup(file_name); -} - -static void next_substitution(struct symbol *mac_symbol, const char *body_pos, - const char **next_match, - struct macro_arg **match_marg, regmatch_t *match); - -void -expand_macro(struct symbol *macro_symbol) -{ - struct macro_arg *marg; - struct macro_arg *match_marg; - const char *body_head; - const char *body_pos; - const char *next_match; - - /* - * Due to the nature of unput, we must work - * backwards through the macro body performing - * any expansions. - */ - body_head = macro_symbol->info.macroinfo->body; - body_pos = body_head + strlen(body_head); - while (body_pos > body_head) { - regmatch_t match; - - next_match = body_head; - match_marg = NULL; - next_substitution(macro_symbol, body_pos, &next_match, - &match_marg, &match); - - /* Put back everything up until the replacement. */ - while (body_pos > next_match) - unput(*--body_pos); - - /* Perform the replacement. */ - if (match_marg != NULL) { - const char *strp; - - next_match = match_marg->replacement_text; - strp = next_match + strlen(next_match); - while (strp > next_match) - unput(*--strp); - - /* Skip past the unexpanded macro arg. */ - body_pos -= match.rm_eo - match.rm_so; - } - } - - /* Cleanup replacement text. */ - STAILQ_FOREACH(marg, ¯o_symbol->info.macroinfo->args, links) { - free(marg->replacement_text); - } -} - -/* - * Find the next substitution in the macro working backwards from - * body_pos until the beginning of the macro buffer. next_match - * should be initialized to the beginning of the macro buffer prior - * to calling this routine. - */ -static void -next_substitution(struct symbol *mac_symbol, const char *body_pos, - const char **next_match, struct macro_arg **match_marg, - regmatch_t *match) -{ - regmatch_t matches[2]; - struct macro_arg *marg; - const char *search_pos; - int retval; - - do { - search_pos = *next_match; - - STAILQ_FOREACH(marg, &mac_symbol->info.macroinfo->args, links) { - - retval = regexec(&marg->arg_regex, search_pos, 2, - matches, 0); - if (retval == 0 - && (matches[1].rm_eo + search_pos) <= body_pos - && (matches[1].rm_eo + search_pos) > *next_match) { - *match = matches[1]; - *next_match = match->rm_eo + search_pos; - *match_marg = marg; - } - } - } while (search_pos != *next_match); -} - -int -yywrap() -{ - include_t *include; - - yy_delete_buffer(YY_CURRENT_BUFFER); - (void)fclose(yyin); - if (yyfilename != NULL) - free(yyfilename); - yyfilename = NULL; - include = include_stack.slh_first; - if (include != NULL) { - yy_switch_to_buffer(include->buffer); - yylineno = include->lineno; - yyfilename = include->filename; - SLIST_REMOVE_HEAD(&include_stack, links); - free(include); - return (0); - } - return (1); -} diff --git a/xen/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c b/xen/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c deleted file mode 100644 index acb356004d..0000000000 --- a/xen/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * Aic7xxx SCSI host adapter firmware asssembler symbol table implementation - * - * Copyright (c) 1997 Justin T. Gibbs. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_symbol.c#14 $ - * - * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_symbol.c,v 1.11.2.4 2002/04/29 19:36:36 gibbs Exp $ - */ - -#include - -#ifdef __linux__ -#include "aicdb.h" -#else -#include -#endif -#include -#include -#include -#include -#include -#include - -#include "aicasm_symbol.h" -#include "aicasm.h" - -static DB *symtable; - -symbol_t * -symbol_create(char *name) -{ - symbol_t *new_symbol; - - new_symbol = (symbol_t *)malloc(sizeof(symbol_t)); - if (new_symbol == NULL) { - perror("Unable to create new symbol"); - exit(EX_SOFTWARE); - } - memset(new_symbol, 0, sizeof(*new_symbol)); - new_symbol->name = strdup(name); - new_symbol->type = UNINITIALIZED; - return (new_symbol); -} - -void -symbol_delete(symbol_t *symbol) -{ - if (symtable != NULL) { - DBT key; - - key.data = symbol->name; - key.size = strlen(symbol->name); - symtable->del(symtable, &key, /*flags*/0); - } - switch(symbol->type) { - case SCBLOC: - case SRAMLOC: - case REGISTER: - if (symbol->info.rinfo != NULL) - free(symbol->info.rinfo); - break; - case ALIAS: - if (symbol->info.ainfo != NULL) - free(symbol->info.ainfo); - break; - case MASK: - case BIT: - if (symbol->info.minfo != NULL) { - symlist_free(&symbol->info.minfo->symrefs); - free(symbol->info.minfo); - } - break; - case DOWNLOAD_CONST: - case CONST: - if (symbol->info.cinfo != NULL) - free(symbol->info.cinfo); - break; - case LABEL: - if (symbol->info.linfo != NULL) - free(symbol->info.linfo); - break; - case UNINITIALIZED: - default: - break; - } - free(symbol->name); - free(symbol); -} - -void -symtable_open() -{ - symtable = dbopen(/*filename*/NULL, - O_CREAT | O_NONBLOCK | O_RDWR, /*mode*/0, DB_HASH, - /*openinfo*/NULL); - - if (symtable == NULL) { - perror("Symbol table creation failed"); - exit(EX_SOFTWARE); - /* NOTREACHED */ - } -} - -void -symtable_close() -{ - if (symtable != NULL) { - DBT key; - DBT data; - - while (symtable->seq(symtable, &key, &data, R_FIRST) == 0) { - symbol_t *stored_ptr; - - memcpy(&stored_ptr, data.data, sizeof(stored_ptr)); - symbol_delete(stored_ptr); - } - symtable->close(symtable); - } -} - -/* - * The semantics of get is to return an uninitialized symbol entry - * if a lookup fails. - */ -symbol_t * -symtable_get(char *name) -{ - symbol_t *stored_ptr; - DBT key; - DBT data; - int retval; - - key.data = (void *)name; - key.size = strlen(name); - - if ((retval = symtable->get(symtable, &key, &data, /*flags*/0)) != 0) { - if (retval == -1) { - perror("Symbol table get operation failed"); - exit(EX_SOFTWARE); - /* NOTREACHED */ - } else if (retval == 1) { - /* Symbol wasn't found, so create a new one */ - symbol_t *new_symbol; - - new_symbol = symbol_create(name); - data.data = &new_symbol; - data.size = sizeof(new_symbol); - if (symtable->put(symtable, &key, &data, - /*flags*/0) !=0) { - perror("Symtable put failed"); - exit(EX_SOFTWARE); - } - return (new_symbol); - } else { - perror("Unexpected return value from db get routine"); - exit(EX_SOFTWARE); - /* NOTREACHED */ - } - } - memcpy(&stored_ptr, data.data, sizeof(stored_ptr)); - return (stored_ptr); -} - -symbol_node_t * -symlist_search(symlist_t *symlist, char *symname) -{ - symbol_node_t *curnode; - - curnode = SLIST_FIRST(symlist); - while(curnode != NULL) { - if (strcmp(symname, curnode->symbol->name) == 0) - break; - curnode = SLIST_NEXT(curnode, links); - } - return (curnode); -} - -void -symlist_add(symlist_t *symlist, symbol_t *symbol, int how) -{ - symbol_node_t *newnode; - - newnode = (symbol_node_t *)malloc(sizeof(symbol_node_t)); - if (newnode == NULL) { - stop("symlist_add: Unable to malloc symbol_node", EX_SOFTWARE); - /* NOTREACHED */ - } - newnode->symbol = symbol; - if (how == SYMLIST_SORT) { - symbol_node_t *curnode; - int mask; - - mask = FALSE; - switch(symbol->type) { - case REGISTER: - case SCBLOC: - case SRAMLOC: - break; - case BIT: - case MASK: - mask = TRUE; - break; - default: - stop("symlist_add: Invalid symbol type for sorting", - EX_SOFTWARE); - /* NOTREACHED */ - } - - curnode = SLIST_FIRST(symlist); - if (curnode == NULL - || (mask && (curnode->symbol->info.minfo->mask > - newnode->symbol->info.minfo->mask)) - || (!mask && (curnode->symbol->info.rinfo->address > - newnode->symbol->info.rinfo->address))) { - SLIST_INSERT_HEAD(symlist, newnode, links); - return; - } - - while (1) { - if (SLIST_NEXT(curnode, links) == NULL) { - SLIST_INSERT_AFTER(curnode, newnode, - links); - break; - } else { - symbol_t *cursymbol; - - cursymbol = SLIST_NEXT(curnode, links)->symbol; - if ((mask && (cursymbol->info.minfo->mask > - symbol->info.minfo->mask)) - || (!mask &&(cursymbol->info.rinfo->address > - symbol->info.rinfo->address))){ - SLIST_INSERT_AFTER(curnode, newnode, - links); - break; - } - } - curnode = SLIST_NEXT(curnode, links); - } - } else { - SLIST_INSERT_HEAD(symlist, newnode, links); - } -} - -void -symlist_free(symlist_t *symlist) -{ - symbol_node_t *node1, *node2; - - node1 = SLIST_FIRST(symlist); - while (node1 != NULL) { - node2 = SLIST_NEXT(node1, links); - free(node1); - node1 = node2; - } - SLIST_INIT(symlist); -} - -void -symlist_merge(symlist_t *symlist_dest, symlist_t *symlist_src1, - symlist_t *symlist_src2) -{ - symbol_node_t *node; - - *symlist_dest = *symlist_src1; - while((node = SLIST_FIRST(symlist_src2)) != NULL) { - SLIST_REMOVE_HEAD(symlist_src2, links); - SLIST_INSERT_HEAD(symlist_dest, node, links); - } - - /* These are now empty */ - SLIST_INIT(symlist_src1); - SLIST_INIT(symlist_src2); -} - -void -symtable_dump(FILE *ofile) -{ - /* - * Sort the registers by address with a simple insertion sort. - * Put bitmasks next to the first register that defines them. - * Put constants at the end. - */ - symlist_t registers; - symlist_t masks; - symlist_t constants; - symlist_t download_constants; - symlist_t aliases; - symlist_t exported_labels; - u_int i; - - SLIST_INIT(®isters); - SLIST_INIT(&masks); - SLIST_INIT(&constants); - SLIST_INIT(&download_constants); - SLIST_INIT(&aliases); - SLIST_INIT(&exported_labels); - - if (symtable != NULL) { - DBT key; - DBT data; - int flag = R_FIRST; - - while (symtable->seq(symtable, &key, &data, flag) == 0) { - symbol_t *cursym; - - memcpy(&cursym, data.data, sizeof(cursym)); - switch(cursym->type) { - case REGISTER: - case SCBLOC: - case SRAMLOC: - symlist_add(®isters, cursym, SYMLIST_SORT); - break; - case MASK: - case BIT: - symlist_add(&masks, cursym, SYMLIST_SORT); - break; - case CONST: - symlist_add(&constants, cursym, - SYMLIST_INSERT_HEAD); - break; - case DOWNLOAD_CONST: - symlist_add(&download_constants, cursym, - SYMLIST_INSERT_HEAD); - break; - case ALIAS: - symlist_add(&aliases, cursym, - SYMLIST_INSERT_HEAD); - break; - case LABEL: - if (cursym->info.linfo->exported == 0) - break; - symlist_add(&exported_labels, cursym, - SYMLIST_INSERT_HEAD); - break; - default: - break; - } - flag = R_NEXT; - } - - /* Put in the masks and bits */ - while (SLIST_FIRST(&masks) != NULL) { - symbol_node_t *curnode; - symbol_node_t *regnode; - char *regname; - - curnode = SLIST_FIRST(&masks); - SLIST_REMOVE_HEAD(&masks, links); - - regnode = - SLIST_FIRST(&curnode->symbol->info.minfo->symrefs); - regname = regnode->symbol->name; - regnode = symlist_search(®isters, regname); - SLIST_INSERT_AFTER(regnode, curnode, links); - } - - /* Add the aliases */ - while (SLIST_FIRST(&aliases) != NULL) { - symbol_node_t *curnode; - symbol_node_t *regnode; - char *regname; - - curnode = SLIST_FIRST(&aliases); - SLIST_REMOVE_HEAD(&aliases, links); - - regname = curnode->symbol->info.ainfo->parent->name; - regnode = symlist_search(®isters, regname); - SLIST_INSERT_AFTER(regnode, curnode, links); - } - - /* Output what we have */ - fprintf(ofile, -"/* - * DO NOT EDIT - This file is automatically generated - * from the following source files: - * -%s */\n", versions); - while (SLIST_FIRST(®isters) != NULL) { - symbol_node_t *curnode; - u_int value; - char *tab_str; - char *tab_str2; - - curnode = SLIST_FIRST(®isters); - SLIST_REMOVE_HEAD(®isters, links); - switch(curnode->symbol->type) { - case REGISTER: - case SCBLOC: - case SRAMLOC: - fprintf(ofile, "\n"); - value = curnode->symbol->info.rinfo->address; - tab_str = "\t"; - tab_str2 = "\t\t"; - break; - case ALIAS: - { - symbol_t *parent; - - parent = curnode->symbol->info.ainfo->parent; - value = parent->info.rinfo->address; - tab_str = "\t"; - tab_str2 = "\t\t"; - break; - } - case MASK: - case BIT: - value = curnode->symbol->info.minfo->mask; - tab_str = "\t\t"; - tab_str2 = "\t"; - break; - default: - value = 0; /* Quiet compiler */ - tab_str = NULL; - tab_str2 = NULL; - stop("symtable_dump: Invalid symbol type " - "encountered", EX_SOFTWARE); - break; - } - fprintf(ofile, "#define%s%-16s%s0x%02x\n", - tab_str, curnode->symbol->name, tab_str2, - value); - free(curnode); - } - fprintf(ofile, "\n\n"); - - while (SLIST_FIRST(&constants) != NULL) { - symbol_node_t *curnode; - - curnode = SLIST_FIRST(&constants); - SLIST_REMOVE_HEAD(&constants, links); - fprintf(ofile, "#define\t%-8s\t0x%02x\n", - curnode->symbol->name, - curnode->symbol->info.cinfo->value); - free(curnode); - } - - - fprintf(ofile, "\n\n/* Downloaded Constant Definitions */\n"); - - for (i = 0; SLIST_FIRST(&download_constants) != NULL; i++) { - symbol_node_t *curnode; - - curnode = SLIST_FIRST(&download_constants); - SLIST_REMOVE_HEAD(&download_constants, links); - fprintf(ofile, "#define\t%-8s\t0x%02x\n", - curnode->symbol->name, - curnode->symbol->info.cinfo->value); - free(curnode); - } - fprintf(ofile, "#define\tDOWNLOAD_CONST_COUNT\t0x%02x\n", i); - - fprintf(ofile, "\n\n/* Exported Labels */\n"); - - while (SLIST_FIRST(&exported_labels) != NULL) { - symbol_node_t *curnode; - - curnode = SLIST_FIRST(&exported_labels); - SLIST_REMOVE_HEAD(&exported_labels, links); - fprintf(ofile, "#define\tLABEL_%-8s\t0x%02x\n", - curnode->symbol->name, - curnode->symbol->info.linfo->address); - free(curnode); - } - } -} - diff --git a/xen/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h b/xen/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h deleted file mode 100644 index 1100c62c2d..0000000000 --- a/xen/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Aic7xxx SCSI host adapter firmware asssembler symbol table definitions - * - * Copyright (c) 1997 Justin T. Gibbs. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_symbol.h#11 $ - * - * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_symbol.h,v 1.11.2.3 2002/04/29 19:36:36 gibbs Exp $ - */ - -#ifdef __linux__ -#include "../queue.h" -#else -#include -#endif - -typedef enum { - UNINITIALIZED, - REGISTER, - ALIAS, - SCBLOC, - SRAMLOC, - MASK, - BIT, - CONST, - DOWNLOAD_CONST, - LABEL, - CONDITIONAL, - MACRO -} symtype; - -typedef enum { - RO = 0x01, - WO = 0x02, - RW = 0x03 -}amode_t; - -struct reg_info { - u_int address; - int size; - amode_t mode; - u_int8_t valid_bitmask; - u_int8_t modes; - int typecheck_masks; -}; - -typedef SLIST_HEAD(symlist, symbol_node) symlist_t; - -struct mask_info { - symlist_t symrefs; - u_int8_t mask; -}; - -struct const_info { - u_int value; - int define; -}; - -struct alias_info { - struct symbol *parent; -}; - -struct label_info { - int address; - int exported; -}; - -struct cond_info { - int func_num; -}; - -struct macro_arg { - STAILQ_ENTRY(macro_arg) links; - regex_t arg_regex; - char *replacement_text; -}; -STAILQ_HEAD(macro_arg_list, macro_arg) args; - -struct macro_info { - struct macro_arg_list args; - int narg; - const char* body; -}; - -typedef struct expression_info { - symlist_t referenced_syms; - int value; -} expression_t; - -typedef struct symbol { - char *name; - symtype type; - union { - struct reg_info *rinfo; - struct mask_info *minfo; - struct const_info *cinfo; - struct alias_info *ainfo; - struct label_info *linfo; - struct cond_info *condinfo; - struct macro_info *macroinfo; - }info; -} symbol_t; - -typedef struct symbol_ref { - symbol_t *symbol; - int offset; -} symbol_ref_t; - -typedef struct symbol_node { - SLIST_ENTRY(symbol_node) links; - symbol_t *symbol; -} symbol_node_t; - -typedef struct critical_section { - TAILQ_ENTRY(critical_section) links; - int begin_addr; - int end_addr; -} critical_section_t; - -typedef enum { - SCOPE_ROOT, - SCOPE_IF, - SCOPE_ELSE_IF, - SCOPE_ELSE -} scope_type; - -typedef struct patch_info { - int skip_patch; - int skip_instr; -} patch_info_t; - -typedef struct scope { - SLIST_ENTRY(scope) scope_stack_links; - TAILQ_ENTRY(scope) scope_links; - TAILQ_HEAD(, scope) inner_scope; - scope_type type; - int inner_scope_patches; - int begin_addr; - int end_addr; - patch_info_t patches[2]; - int func_num; -} scope_t; - -TAILQ_HEAD(cs_tailq, critical_section); -SLIST_HEAD(scope_list, scope); -TAILQ_HEAD(scope_tailq, scope); - -void symbol_delete __P((symbol_t *symbol)); - -void symtable_open __P((void)); - -void symtable_close __P((void)); - -symbol_t * - symtable_get __P((char *name)); - -symbol_node_t * - symlist_search __P((symlist_t *symlist, char *symname)); - -void - symlist_add __P((symlist_t *symlist, symbol_t *symbol, int how)); -#define SYMLIST_INSERT_HEAD 0x00 -#define SYMLIST_SORT 0x01 - -void symlist_free __P((symlist_t *symlist)); - -void symlist_merge __P((symlist_t *symlist_dest, symlist_t *symlist_src1, - symlist_t *symlist_src2)); -void symtable_dump __P((FILE *ofile)); diff --git a/xen/drivers/scsi/aic7xxx/cam.h b/xen/drivers/scsi/aic7xxx/cam.h deleted file mode 100644 index d7a526fe99..0000000000 --- a/xen/drivers/scsi/aic7xxx/cam.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Data structures and definitions for the CAM system. - * - * Copyright (c) 1997 Justin T. Gibbs. - * Copyright (c) 2000 Adaptec Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL"). - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/cam.h#11 $ - */ - -#ifndef _AIC7XXX_CAM_H -#define _AIC7XXX_CAM_H 1 - -/* Provide a mapping from CAM constructs to Linux SCSI constructs */ - -#define CAM_BUS_WILDCARD ((u_int)~0) -#define CAM_TARGET_WILDCARD ((u_int)~0) -#define CAM_LUN_WILDCARD ((u_int)~0) - -/* CAM Status field values */ -typedef enum { - /* CCB request is in progress */ - CAM_REQ_INPROG = 0x3F, /* Some value unused by Linux */ - /* CCB request completed without error */ - CAM_REQ_CMP = DID_OK, - /* CCB request aborted by the host */ - CAM_REQ_ABORTED = DID_ABORT, - /* Unable to abort CCB request */ - CAM_UA_ABORT = DID_ERROR, - /* CCB request completed with an error */ - CAM_REQ_CMP_ERR = DID_ERROR, - /* CAM subsytem is busy */ - CAM_BUSY = DID_BUS_BUSY, - /* CCB request was invalid */ - CAM_REQ_INVALID = DID_BAD_TARGET, - /* Supplied Path ID is invalid */ - CAM_PATH_INVALID = DID_BAD_TARGET, - /* Target Selection Timeout */ - CAM_SEL_TIMEOUT = DID_NO_CONNECT, - /* Command timeout */ - CAM_CMD_TIMEOUT = DID_ERROR, /* - * Should never occur in Linux - * as the upper level code - * handles all timeout processing. - */ - /* SCSI error, look at error code in CCB */ - CAM_SCSI_STATUS_ERROR = DID_OK, /* Linux looks at status byte */ - /* SCSI Bus Reset Sent/Received */ - CAM_SCSI_BUS_RESET = DID_RESET, - /* Uncorrectable parity error occurred */ - CAM_UNCOR_PARITY = DID_PARITY, - /* Autosense: request sense cmd fail */ - CAM_AUTOSENSE_FAIL = DID_ERROR, - /* No HBA Detected Error */ - CAM_NO_HBA = DID_ERROR, - /* Data Overrun error */ - CAM_DATA_RUN_ERR = DID_ERROR, - /* Unexpected Bus Free */ - CAM_UNEXP_BUSFREE = DID_ERROR, - /* CCB length supplied is inadequate */ - CAM_CCB_LEN_ERR = DID_ERROR, - /* Unable to provide requested capability */ - CAM_PROVIDE_FAIL = DID_ERROR, - /* A SCSI BDR msg was sent to target */ - CAM_BDR_SENT = DID_RESET, - /* CCB request terminated by the host */ - CAM_REQ_TERMIO = DID_ERROR, - /* Unrecoverable Host Bus Adapter Error */ - CAM_UNREC_HBA_ERROR = DID_ERROR, - /* The request was too large for this host */ - CAM_REQ_TOO_BIG = DID_ERROR, - /* - * This request should be requeued to preserve - * transaction ordering. This typically occurs - * when the SIM recognizes an error that should - * freeze the queue and must place additional - * requests for the target at the sim level - * back into the XPT queue. - */ - CAM_REQUEUE_REQ = DID_BUS_BUSY, - - CAM_STATUS_MASK = 0x3F -} cam_status; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -#define SCSI_DATA_READ 1 -#define SCSI_DATA_WRITE 2 -#define SCSI_DATA_NONE 3 -#endif - -/* - * Definitions for the asynchronous callback CCB fields. - */ -typedef enum { - AC_GETDEV_CHANGED = 0x800,/* Getdev info might have changed */ - AC_INQ_CHANGED = 0x400,/* Inquiry info might have changed */ - AC_TRANSFER_NEG = 0x200,/* New transfer settings in effect */ - AC_LOST_DEVICE = 0x100,/* A device went away */ - AC_FOUND_DEVICE = 0x080,/* A new device was found */ - AC_PATH_DEREGISTERED = 0x040,/* A path has de-registered */ - AC_PATH_REGISTERED = 0x020,/* A new path has been registered */ - AC_SENT_BDR = 0x010,/* A BDR message was sent to target */ - AC_SCSI_AEN = 0x008,/* A SCSI AEN has been received */ - AC_UNSOL_RESEL = 0x002,/* Unsolicited reselection occurred */ - AC_BUS_RESET = 0x001 /* A SCSI bus reset occurred */ -} ac_code; - -typedef enum { - CAM_DIR_IN = SCSI_DATA_READ, - CAM_DIR_OUT = SCSI_DATA_WRITE, - CAM_DIR_NONE = SCSI_DATA_NONE -} ccb_flags; - -#endif /* _AIC7XXX_CAM_H */ diff --git a/xen/drivers/scsi/aic7xxx/queue.h b/xen/drivers/scsi/aic7xxx/queue.h deleted file mode 100644 index 8adf8003a1..0000000000 --- a/xen/drivers/scsi/aic7xxx/queue.h +++ /dev/null @@ -1,501 +0,0 @@ -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - * $FreeBSD: src/sys/sys/queue.h,v 1.38 2000/05/26 02:06:56 jake Exp $ - */ - -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ - -/* - * This file defines five types of data structures: singly-linked lists, - * singly-linked tail queues, lists, tail queues, and circular queues. - * - * A singly-linked list is headed by a single forward pointer. The elements - * are singly linked for minimum space and pointer manipulation overhead at - * the expense of O(n) removal for arbitrary elements. New elements can be - * added to the list after an existing element or at the head of the list. - * Elements being removed from the head of the list should use the explicit - * macro for this purpose for optimum efficiency. A singly-linked list may - * only be traversed in the forward direction. Singly-linked lists are ideal - * for applications with large datasets and few or no removals or for - * implementing a LIFO queue. - * - * A singly-linked tail queue is headed by a pair of pointers, one to the - * head of the list and the other to the tail of the list. The elements are - * singly linked for minimum space and pointer manipulation overhead at the - * expense of O(n) removal for arbitrary elements. New elements can be added - * to the list after an existing element, at the head of the list, or at the - * end of the list. Elements being removed from the head of the tail queue - * should use the explicit macro for this purpose for optimum efficiency. - * A singly-linked tail queue may only be traversed in the forward direction. - * Singly-linked tail queues are ideal for applications with large datasets - * and few or no removals or for implementing a FIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * A circle queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the list. - * A circle queue may be traversed in either direction, but has a more - * complex end of list detection. - * - * For details on the use of these macros, see the queue(3) manual page. - * - * - * SLIST LIST STAILQ TAILQ CIRCLEQ - * _HEAD + + + + + - * _HEAD_INITIALIZER + + + + + - * _ENTRY + + + + + - * _INIT + + + + + - * _EMPTY + + + + + - * _FIRST + + + + + - * _NEXT + + + + + - * _PREV - - - + + - * _LAST - - + + + - * _FOREACH + + + + + - * _FOREACH_REVERSE - - - + + - * _INSERT_HEAD + + + + + - * _INSERT_BEFORE - + - + + - * _INSERT_AFTER + + + + + - * _INSERT_TAIL - - + + + - * _REMOVE_HEAD + - + - - - * _REMOVE + + + + + - * - */ - -/* - * Singly-linked List declarations. - */ -#define SLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define SLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define SLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} - -/* - * Singly-linked List functions. - */ -#define SLIST_EMPTY(head) ((head)->slh_first == NULL) - -#define SLIST_FIRST(head) ((head)->slh_first) - -#define SLIST_FOREACH(var, head, field) \ - for ((var) = SLIST_FIRST((head)); \ - (var); \ - (var) = SLIST_NEXT((var), field)) - -#define SLIST_INIT(head) do { \ - SLIST_FIRST((head)) = NULL; \ -} while (0) - -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ - SLIST_NEXT((slistelm), field) = (elm); \ -} while (0) - -#define SLIST_INSERT_HEAD(head, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ - SLIST_FIRST((head)) = (elm); \ -} while (0) - -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_REMOVE(head, elm, type, field) do { \ - if (SLIST_FIRST((head)) == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ - } \ - else { \ - struct type *curelm = SLIST_FIRST((head)); \ - while (SLIST_NEXT(curelm, field) != (elm)) \ - curelm = SLIST_NEXT(curelm, field); \ - SLIST_NEXT(curelm, field) = \ - SLIST_NEXT(SLIST_NEXT(curelm, field), field); \ - } \ -} while (0) - -#define SLIST_REMOVE_HEAD(head, field) do { \ - SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ -} while (0) - -/* - * Singly-linked Tail queue declarations. - */ -#define STAILQ_HEAD(name, type) \ -struct name { \ - struct type *stqh_first;/* first element */ \ - struct type **stqh_last;/* addr of last next element */ \ -} - -#define STAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).stqh_first } - -#define STAILQ_ENTRY(type) \ -struct { \ - struct type *stqe_next; /* next element */ \ -} - -/* - * Singly-linked Tail queue functions. - */ -#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) - -#define STAILQ_FIRST(head) ((head)->stqh_first) - -#define STAILQ_FOREACH(var, head, field) \ - for((var) = STAILQ_FIRST((head)); \ - (var); \ - (var) = STAILQ_NEXT((var), field)) - -#define STAILQ_INIT(head) do { \ - STAILQ_FIRST((head)) = NULL; \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_NEXT((tqelm), field) = (elm); \ -} while (0) - -#define STAILQ_INSERT_HEAD(head, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_FIRST((head)) = (elm); \ -} while (0) - -#define STAILQ_INSERT_TAIL(head, elm, field) do { \ - STAILQ_NEXT((elm), field) = NULL; \ - STAILQ_LAST((head)) = (elm); \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ -} while (0) - -#define STAILQ_LAST(head) (*(head)->stqh_last) - -#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) - -#define STAILQ_REMOVE(head, elm, type, field) do { \ - if (STAILQ_FIRST((head)) == (elm)) { \ - STAILQ_REMOVE_HEAD(head, field); \ - } \ - else { \ - struct type *curelm = STAILQ_FIRST((head)); \ - while (STAILQ_NEXT(curelm, field) != (elm)) \ - curelm = STAILQ_NEXT(curelm, field); \ - if ((STAILQ_NEXT(curelm, field) = \ - STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\ - (head)->stqh_last = &STAILQ_NEXT((curelm), field);\ - } \ -} while (0) - -#define STAILQ_REMOVE_HEAD(head, field) do { \ - if ((STAILQ_FIRST((head)) = \ - STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \ - if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -/* - * List declarations. - */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -/* - * List functions. - */ - -#define LIST_EMPTY(head) ((head)->lh_first == NULL) - -#define LIST_FIRST(head) ((head)->lh_first) - -#define LIST_FOREACH(var, head, field) \ - for ((var) = LIST_FIRST((head)); \ - (var); \ - (var) = LIST_NEXT((var), field)) - -#define LIST_INIT(head) do { \ - LIST_FIRST((head)) = NULL; \ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ - LIST_NEXT((listelm), field)->field.le_prev = \ - &LIST_NEXT((elm), field); \ - LIST_NEXT((listelm), field) = (elm); \ - (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - LIST_NEXT((elm), field) = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ - LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ - LIST_FIRST((head)) = (elm); \ - (elm)->field.le_prev = &LIST_FIRST((head)); \ -} while (0) - -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_REMOVE(elm, field) do { \ - if (LIST_NEXT((elm), field) != NULL) \ - LIST_NEXT((elm), field)->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = LIST_NEXT((elm), field); \ -} while (0) - -/* - * Tail queue declarations. - */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ -} - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ -} - -/* - * Tail queue functions. - */ -#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) - -#define TAILQ_FIRST(head) ((head)->tqh_first) - -#define TAILQ_FOREACH(var, head, field) \ - for ((var) = TAILQ_FIRST((head)); \ - (var); \ - (var) = TAILQ_NEXT((var), field)) - -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var); \ - (var) = TAILQ_PREV((var), headname, field)) - -#define TAILQ_INIT(head) do { \ - TAILQ_FIRST((head)) = NULL; \ - (head)->tqh_last = &TAILQ_FIRST((head)); \ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - TAILQ_NEXT((listelm), field) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - TAILQ_NEXT((elm), field) = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ - TAILQ_FIRST((head))->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - TAILQ_FIRST((head)) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - TAILQ_NEXT((elm), field) = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ -} while (0) - -#define TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) - -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) - -#define TAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) - -#define TAILQ_REMOVE(head, elm, field) do { \ - if ((TAILQ_NEXT((elm), field)) != NULL) \ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ -} while (0) - -/* - * Circular queue declarations. - */ -#define CIRCLEQ_HEAD(name, type) \ -struct name { \ - struct type *cqh_first; /* first element */ \ - struct type *cqh_last; /* last element */ \ -} - -#define CIRCLEQ_HEAD_INITIALIZER(head) \ - { (void *)&(head), (void *)&(head) } - -#define CIRCLEQ_ENTRY(type) \ -struct { \ - struct type *cqe_next; /* next element */ \ - struct type *cqe_prev; /* previous element */ \ -} - -/* - * Circular queue functions. - */ -#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) - -#define CIRCLEQ_FIRST(head) ((head)->cqh_first) - -#define CIRCLEQ_FOREACH(var, head, field) \ - for ((var) = CIRCLEQ_FIRST((head)); \ - (var) != (void *)(head); \ - (var) = CIRCLEQ_NEXT((var), field)) - -#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ - for ((var) = CIRCLEQ_LAST((head)); \ - (var) != (void *)(head); \ - (var) = CIRCLEQ_PREV((var), field)) - -#define CIRCLEQ_INIT(head) do { \ - CIRCLEQ_FIRST((head)) = (void *)(head); \ - CIRCLEQ_LAST((head)) = (void *)(head); \ -} while (0) - -#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field); \ - CIRCLEQ_PREV((elm), field) = (listelm); \ - if (CIRCLEQ_NEXT((listelm), field) == (void *)(head)) \ - CIRCLEQ_LAST((head)) = (elm); \ - else \ - CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm);\ - CIRCLEQ_NEXT((listelm), field) = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ - CIRCLEQ_NEXT((elm), field) = (listelm); \ - CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field); \ - if (CIRCLEQ_PREV((listelm), field) == (void *)(head)) \ - CIRCLEQ_FIRST((head)) = (elm); \ - else \ - CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm);\ - CIRCLEQ_PREV((listelm), field) = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ - CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head)); \ - CIRCLEQ_PREV((elm), field) = (void *)(head); \ - if (CIRCLEQ_LAST((head)) == (void *)(head)) \ - CIRCLEQ_LAST((head)) = (elm); \ - else \ - CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm); \ - CIRCLEQ_FIRST((head)) = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ - CIRCLEQ_NEXT((elm), field) = (void *)(head); \ - CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head)); \ - if (CIRCLEQ_FIRST((head)) == (void *)(head)) \ - CIRCLEQ_FIRST((head)) = (elm); \ - else \ - CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm); \ - CIRCLEQ_LAST((head)) = (elm); \ -} while (0) - -#define CIRCLEQ_LAST(head) ((head)->cqh_last) - -#define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next) - -#define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev) - -#define CIRCLEQ_REMOVE(head, elm, field) do { \ - if (CIRCLEQ_NEXT((elm), field) == (void *)(head)) \ - CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field); \ - else \ - CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) = \ - CIRCLEQ_PREV((elm), field); \ - if (CIRCLEQ_PREV((elm), field) == (void *)(head)) \ - CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field); \ - else \ - CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) = \ - CIRCLEQ_NEXT((elm), field); \ -} while (0) - -#endif /* !_SYS_QUEUE_H_ */ diff --git a/xen/drivers/scsi/aic7xxx/scsi_iu.h b/xen/drivers/scsi/aic7xxx/scsi_iu.h deleted file mode 100644 index 801da0af4c..0000000000 --- a/xen/drivers/scsi/aic7xxx/scsi_iu.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is in the public domain. - */ -#ifndef _SCSI_SCSI_IU_H -#define _SCSI_SCSI_IU_H 1 - -struct scsi_status_iu_header -{ - u_int8_t reserved[2]; - u_int8_t flags; -#define SIU_SNSVALID 0x2 -#define SIU_RSPVALID 0x1 - u_int8_t status; - u_int8_t sense_length[4]; - u_int8_t pkt_failures_length[4]; - u_int8_t pkt_failures[1]; -}; - -#define SIU_PKTFAIL_OFFSET(siu) 12 -#define SIU_PKTFAIL_CODE(siu) (scsi_4btoul((siu)->pkt_failures) & 0xFF) -#define SIU_PFC_NONE 0 -#define SIU_PFC_CIU_FIELDS_INVALID 2 -#define SIU_PFC_TMF_NOT_SUPPORTED 4 -#define SIU_PFC_TMF_FAILED 5 -#define SIU_PFC_INVALID_TYPE_CODE 6 -#define SIU_PFC_ILLEGAL_REQUEST 7 -#define SIU_SENSE_OFFSET(siu) \ - (12 + (((siu)->flags & SIU_RSPVALID) \ - ? scsi_4btoul((siu)->pkt_failures_length) \ - : 0)) -#endif /*_SCSI_SCSI_IU_H*/ diff --git a/xen/drivers/scsi/aic7xxx/scsi_message.h b/xen/drivers/scsi/aic7xxx/scsi_message.h deleted file mode 100644 index 75811e245e..0000000000 --- a/xen/drivers/scsi/aic7xxx/scsi_message.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is in the public domain. - * $FreeBSD: src/sys/cam/scsi/scsi_message.h,v 1.2 2000/05/01 20:21:29 peter Exp $ - */ - -/* Messages (1 byte) */ /* I/T (M)andatory or (O)ptional */ -#define MSG_CMDCOMPLETE 0x00 /* M/M */ -#define MSG_TASK_COMPLETE 0x00 /* M/M */ /* SPI3 Terminology */ -#define MSG_EXTENDED 0x01 /* O/O */ -#define MSG_SAVEDATAPOINTER 0x02 /* O/O */ -#define MSG_RESTOREPOINTERS 0x03 /* O/O */ -#define MSG_DISCONNECT 0x04 /* O/O */ -#define MSG_INITIATOR_DET_ERR 0x05 /* M/M */ -#define MSG_ABORT 0x06 /* O/M */ -#define MSG_ABORT_TASK_SET 0x06 /* O/M */ /* SPI3 Terminology */ -#define MSG_MESSAGE_REJECT 0x07 /* M/M */ -#define MSG_NOOP 0x08 /* M/M */ -#define MSG_PARITY_ERROR 0x09 /* M/M */ -#define MSG_LINK_CMD_COMPLETE 0x0a /* O/O */ -#define MSG_LINK_CMD_COMPLETEF 0x0b /* O/O */ -#define MSG_BUS_DEV_RESET 0x0c /* O/M */ -#define MSG_TARGET_RESET 0x0c /* O/M */ /* SPI3 Terminology */ -#define MSG_ABORT_TAG 0x0d /* O/O */ -#define MSG_ABORT_TASK 0x0d /* O/O */ /* SPI3 Terminology */ -#define MSG_CLEAR_QUEUE 0x0e /* O/O */ -#define MSG_CLEAR_TASK_SET 0x0e /* O/O */ /* SPI3 Terminology */ -#define MSG_INIT_RECOVERY 0x0f /* O/O */ /* Deprecated in SPI3 */ -#define MSG_REL_RECOVERY 0x10 /* O/O */ /* Deprecated in SPI3 */ -#define MSG_TERM_IO_PROC 0x11 /* O/O */ /* Deprecated in SPI3 */ -#define MSG_CLEAR_ACA 0x16 /* O/O */ /* SPI3 */ -#define MSG_LOGICAL_UNIT_RESET 0x17 /* O/O */ /* SPI3 */ -#define MSG_QAS_REQUEST 0x55 /* O/O */ /* SPI3 */ - -/* Messages (2 byte) */ -#define MSG_SIMPLE_Q_TAG 0x20 /* O/O */ -#define MSG_SIMPLE_TASK 0x20 /* O/O */ /* SPI3 Terminology */ -#define MSG_HEAD_OF_Q_TAG 0x21 /* O/O */ -#define MSG_HEAD_OF_QUEUE_TASK 0x21 /* O/O */ /* SPI3 Terminology */ -#define MSG_ORDERED_Q_TAG 0x22 /* O/O */ -#define MSG_ORDERED_TASK 0x22 /* O/O */ /* SPI3 Terminology */ -#define MSG_IGN_WIDE_RESIDUE 0x23 /* O/O */ -#define MSG_ACA_TASK 0x24 /* 0/0 */ /* SPI3 */ - -/* Identify message */ /* M/M */ -#define MSG_IDENTIFYFLAG 0x80 -#define MSG_IDENTIFY_DISCFLAG 0x40 -#define MSG_IDENTIFY(lun, disc) (((disc) ? 0xc0 : MSG_IDENTIFYFLAG) | (lun)) -#define MSG_ISIDENTIFY(m) ((m) & MSG_IDENTIFYFLAG) -#define MSG_IDENTIFY_LUNMASK 0x3F - -/* Extended messages (opcode and length) */ -#define MSG_EXT_SDTR 0x01 -#define MSG_EXT_SDTR_LEN 0x03 - -#define MSG_EXT_WDTR 0x03 -#define MSG_EXT_WDTR_LEN 0x02 -#define MSG_EXT_WDTR_BUS_8_BIT 0x00 -#define MSG_EXT_WDTR_BUS_16_BIT 0x01 -#define MSG_EXT_WDTR_BUS_32_BIT 0x02 /* Deprecated in SPI3 */ - -#define MSG_EXT_PPR 0x04 /* SPI3 */ -#define MSG_EXT_PPR_LEN 0x06 -#define MSG_EXT_PPR_PCOMP_EN 0x80 -#define MSG_EXT_PPR_RTI 0x40 -#define MSG_EXT_PPR_RD_STRM 0x20 -#define MSG_EXT_PPR_WR_FLOW 0x10 -#define MSG_EXT_PPR_HOLD_MCS 0x08 -#define MSG_EXT_PPR_QAS_REQ 0x04 -#define MSG_EXT_PPR_DT_REQ 0x02 -#define MSG_EXT_PPR_IU_REQ 0x01 diff --git a/xen/drivers/scsi/constants.c b/xen/drivers/scsi/constants.c deleted file mode 100644 index 4a72d6ca47..0000000000 --- a/xen/drivers/scsi/constants.c +++ /dev/null @@ -1,1005 +0,0 @@ -/* - * ASCII values for a number of symbolic constants, printing functions, - * etc. - * Additions for SCSI 2 and Linux 2.2.x by D. Gilbert (990422) - * - */ - -#define __NO_VERSION__ -#include - -#include -#include -/*#include */ -#include "scsi.h" -#include "hosts.h" - -#define CONST_COMMAND 0x01 -#define CONST_STATUS 0x02 -#define CONST_SENSE 0x04 -#define CONST_XSENSE 0x08 -#define CONST_CMND 0x10 -#define CONST_MSG 0x20 -#define CONST_HOST 0x40 -#define CONST_DRIVER 0x80 - -static const char unknown[] = "UNKNOWN"; - -#ifdef CONFIG_SCSI_CONSTANTS -#ifdef CONSTANTS -#undef CONSTANTS -#endif -#define CONSTANTS (CONST_COMMAND | CONST_STATUS | CONST_SENSE | CONST_XSENSE \ - | CONST_CMND | CONST_MSG | CONST_HOST | CONST_DRIVER) -#endif - -#if (CONSTANTS & CONST_COMMAND) -static const char * group_0_commands[] = { -/* 00-03 */ "Test Unit Ready", "Rezero Unit", unknown, "Request Sense", -/* 04-07 */ "Format Unit", "Read Block Limits", unknown, "Reasssign Blocks", -/* 08-0d */ "Read (6)", unknown, "Write (6)", "Seek (6)", unknown, unknown, -/* 0e-12 */ unknown, "Read Reverse", "Write Filemarks", "Space", "Inquiry", -/* 13-16 */ "Verify", "Recover Buffered Data", "Mode Select", "Reserve", -/* 17-1b */ "Release", "Copy", "Erase", "Mode Sense", "Start/Stop Unit", -/* 1c-1d */ "Receive Diagnostic", "Send Diagnostic", -/* 1e-1f */ "Prevent/Allow Medium Removal", unknown, -}; - - -static const char *group_1_commands[] = { -/* 20-22 */ unknown, unknown, unknown, -/* 23-28 */ unknown, "Define window parameters", "Read Capacity", - unknown, unknown, "Read (10)", -/* 29-2d */ "Read Generation", "Write (10)", "Seek (10)", "Erase", - "Read updated block", -/* 2e-31 */ "Write Verify","Verify", "Search High", "Search Equal", -/* 32-34 */ "Search Low", "Set Limits", "Prefetch or Read Position", -/* 35-37 */ "Synchronize Cache","Lock/Unlock Cache", "Read Defect Data", -/* 38-3c */ "Medium Scan", "Compare", "Copy Verify", "Write Buffer", - "Read Buffer", -/* 3d-3f */ "Update Block", "Read Long", "Write Long", -}; - - -static const char *group_2_commands[] = { -/* 40-41 */ "Change Definition", "Write Same", -/* 42-48 */ "Read sub-channel", "Read TOC", "Read header", - "Play audio (10)", unknown, "Play audio msf", - "Play audio track/index", -/* 49-4f */ "Play track relative (10)", unknown, "Pause/resume", - "Log Select", "Log Sense", unknown, unknown, -/* 50-55 */ unknown, unknown, unknown, unknown, unknown, "Mode Select (10)", -/* 56-5b */ unknown, unknown, unknown, unknown, "Mode Sense (10)", unknown, -/* 5c-5f */ unknown, unknown, unknown, -}; - - -/* The following are 16 byte commands in group 4 */ -static const char *group_4_commands[] = { -/* 80-84 */ unknown, unknown, unknown, unknown, unknown, -/* 85-89 */ "Memory Export In (16)", unknown, unknown, unknown, - "Memory Export Out (16)", -/* 8a-8f */ unknown, unknown, unknown, unknown, unknown, unknown, -/* 90-94 */ unknown, unknown, unknown, unknown, unknown, -/* 95-99 */ unknown, unknown, unknown, unknown, unknown, -/* 9a-9f */ unknown, unknown, unknown, unknown, unknown, unknown, -}; - - -/* The following are 12 byte commands in group 5 */ -static const char *group_5_commands[] = { -/* a0-a5 */ unknown, unknown, unknown, unknown, unknown, - "Move medium/play audio(12)", -/* a6-a9 */ "Exchange medium", unknown, "Read(12)", "Play track relative(12)", -/* aa-ae */ "Write(12)", unknown, "Erase(12)", unknown, - "Write and verify(12)", -/* af-b1 */ "Verify(12)", "Search data high(12)", "Search data equal(12)", -/* b2-b4 */ "Search data low(12)", "Set limits(12)", unknown, -/* b5-b6 */ "Request volume element address", "Send volume tag", -/* b7-b9 */ "Read defect data(12)", "Read element status", unknown, -/* ba-bf */ unknown, unknown, unknown, unknown, unknown, unknown, -}; - - - -#define group(opcode) (((opcode) >> 5) & 7) - -#define RESERVED_GROUP 0 -#define VENDOR_GROUP 1 - -static const char **commands[] = { - group_0_commands, group_1_commands, group_2_commands, - (const char **) RESERVED_GROUP, group_4_commands, - group_5_commands, (const char **) VENDOR_GROUP, - (const char **) VENDOR_GROUP -}; - -static const char reserved[] = "RESERVED"; -static const char vendor[] = "VENDOR SPECIFIC"; - -static void print_opcode(int opcode) { - const char **table = commands[ group(opcode) ]; - switch ((unsigned long) table) { - case RESERVED_GROUP: - printk("%s(0x%02x) ", reserved, opcode); - break; - case VENDOR_GROUP: - printk("%s(0x%02x) ", vendor, opcode); - break; - default: - if (table[opcode & 0x1f] != unknown) - printk("%s ",table[opcode & 0x1f]); - else - printk("%s(0x%02x) ", unknown, opcode); - break; - } -} -#else /* CONST & CONST_COMMAND */ -static void print_opcode(int opcode) { - printk("0x%02x ", opcode); -} -#endif - -void print_command (unsigned char *command) { - int i,s; - print_opcode(command[0]); - for ( i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i) - printk("%02x ", command[i]); - printk("\n"); -} - -#if (CONSTANTS & CONST_STATUS) -static const char * statuses[] = { -/* 0-4 */ "Good", "Check Condition", "Condition Met", unknown, "Busy", -/* 5-9 */ unknown, unknown, unknown, "Intermediate", unknown, -/* a-c */ "Intermediate-Condition Met", unknown, "Reservation Conflict", -/* d-10 */ unknown, unknown, unknown, unknown, -/* 11-14 */ "Command Terminated", unknown, unknown, "Queue Full", -/* 15-1a */ unknown, unknown, unknown, unknown, unknown, unknown, -/* 1b-1f */ unknown, unknown, unknown, unknown, unknown, -}; -#endif - -void print_status (int status) { - status = (status >> 1) & 0x1f; -#if (CONSTANTS & CONST_STATUS) - printk("%s ",statuses[status]); -#else - printk("0x%0x ", status); -#endif -} - -#if (CONSTANTS & CONST_XSENSE) -#define D 0x0001 /* DIRECT ACCESS DEVICE (disk) */ -#define T 0x0002 /* SEQUENTIAL ACCESS DEVICE (tape) */ -#define L 0x0004 /* PRINTER DEVICE */ -#define P 0x0008 /* PROCESSOR DEVICE */ -#define W 0x0010 /* WRITE ONCE READ MULTIPLE DEVICE */ -#define R 0x0020 /* READ ONLY (CD-ROM) DEVICE */ -#define S 0x0040 /* SCANNER DEVICE */ -#define O 0x0080 /* OPTICAL MEMORY DEVICE */ -#define M 0x0100 /* MEDIA CHANGER DEVICE */ -#define C 0x0200 /* COMMUNICATION DEVICE */ -#define A 0x0400 /* ARRAY STORAGE */ -#define E 0x0800 /* ENCLOSURE SERVICES DEVICE */ -#define B 0x1000 /* SIMPLIFIED DIRECT ACCESS DEVICE */ -#define K 0x2000 /* OPTICAL CARD READER/WRITER DEVICE */ - -struct error_info{ - unsigned char code1, code2; - unsigned short int devices; - const char * text; -}; - -struct error_info2{ - unsigned char code1, code2_min, code2_max; - unsigned short int devices; - const char * text; -}; - -static struct error_info2 additional2[] = -{ - {0x40,0x00,0x7f,D,"Ram failure (%x)"}, - {0x40,0x80,0xff,D|T|L|P|W|R|S|O|M|C,"Diagnostic failure on component (%x)"}, - {0x41,0x00,0xff,D,"Data path failure (%x)"}, - {0x42,0x00,0xff,D,"Power-on or self-test failure (%x)"}, - {0, 0, 0, 0, NULL} -}; - -static struct error_info additional[] = -{ - {0x00,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"No additional sense information"}, - {0x00,0x01,T,"Filemark detected"}, - {0x00,0x02,T|S,"End-of-partition/medium detected"}, - {0x00,0x03,T,"Setmark detected"}, - {0x00,0x04,T|S,"Beginning-of-partition/medium detected"}, - {0x00,0x05,T|L|S,"End-of-data detected"}, - {0x00,0x06,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"I/O process terminated"}, - {0x00,0x11,R,"Audio play operation in progress"}, - {0x00,0x12,R,"Audio play operation paused"}, - {0x00,0x13,R,"Audio play operation successfully completed"}, - {0x00,0x14,R,"Audio play operation stopped due to error"}, - {0x00,0x15,R,"No current audio status to return"}, - {0x00,0x16,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Operation in progress"}, - {0x00,0x17,D|T|L|W|R|S|O|M|A|E|B|K,"Cleaning requested"}, - {0x01,0x00,D|W|O|B|K,"No index/sector signal"}, - {0x02,0x00,D|W|R|O|M|B|K,"No seek complete"}, - {0x03,0x00,D|T|L|W|S|O|B|K,"Peripheral device write fault"}, - {0x03,0x01,T,"No write current"}, - {0x03,0x02,T,"Excessive write errors"}, - {0x04,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit not ready,cause not reportable"}, - {0x04,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit is in process of becoming ready"}, - {0x04,0x02,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit not ready,initializing cmd. required"}, - {0x04,0x03,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit not ready,manual intervention required"}, - {0x04,0x04,D|T|L|R|O|B,"Logical unit not ready,format in progress"}, - {0x04,0x05,D|T|W|O|M|C|A|B|K,"Logical unit not ready,rebuild in progress"}, - {0x04,0x06,D|T|W|O|M|C|A|B|K,"Logical unit not ready,recalculation in progress"}, - {0x04,0x07,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit not ready,operation in progress"}, - {0x04,0x08,R,"Logical unit not ready,long write in progress"}, - {0x04,0x09,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit not ready,self-test in progress"}, - {0x05,0x00,D|T|L|W|R|S|O|M|C|A|E|B|K,"Logical unit does not respond to selection"}, - {0x06,0x00,D|W|R|O|M|B|K,"No reference position found"}, - {0x07,0x00,D|T|L|W|R|S|O|M|B|K,"Multiple peripheral devices selected"}, - {0x08,0x00,D|T|L|W|R|S|O|M|C|A|E|B|K,"Logical unit communication failure"}, - {0x08,0x01,D|T|L|W|R|S|O|M|C|A|E|B|K,"Logical unit communication time-out"}, - {0x08,0x02,D|T|L|W|R|S|O|M|C|A|E|B|K,"Logical unit communication parity error"}, - {0x08,0x03,D|T|R|O|M|B|K,"Logical unit communication CRC error (Ultra-DMA/32)"}, - {0x08,0x04,D|T|L|P|W|R|S|O|C|K,"Unreachable copy target"}, - {0x09,0x00,D|T|W|R|O|B,"Track following error"}, - {0x09,0x01,W|R|O|K,"Tracking servo failure"}, - {0x09,0x02,W|R|O|K,"Focus servo failure"}, - {0x09,0x03,W|R|O,"Spindle servo failure"}, - {0x09,0x04,D|T|W|R|O|B,"Head select fault"}, - {0x0A,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Error log overflow"}, - {0x0B,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Warning"}, - {0x0B,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Warning - specified temperature exceeded"}, - {0x0B,0x02,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Warning - enclosure degraded"}, - {0x0C,0x00,T|R|S,"Write error"}, - {0x0C,0x01,K,"Write error - recovered with auto reallocation"}, - {0x0C,0x02,D|W|O|B|K,"Write error - auto reallocation failed"}, - {0x0C,0x03,D|W|O|B|K,"Write error - recommend reassignment"}, - {0x0C,0x04,D|T|W|O|B,"Compression check miscompare error"}, - {0x0C,0x05,D|T|W|O|B,"Data expansion occurred during compression"}, - {0x0C,0x06,D|T|W|O|B,"Block not compressible"}, - {0x0C,0x07,R,"Write error - recovery needed"}, - {0x0C,0x08,R,"Write error - recovery failed"}, - {0x0C,0x09,R,"Write error - loss of streaming"}, - {0x0C,0x0A,R,"Write error - padding blocks added"}, - {0x10,0x00,D|W|O|B|K,"Id CRC or ECC error"}, - {0x11,0x00,D|T|W|R|S|O|B|K,"Unrecovered read error"}, - {0x11,0x01,D|T|W|R|S|O|B|K,"Read retries exhausted"}, - {0x11,0x02,D|T|W|R|S|O|B|K,"Error too long to correct"}, - {0x11,0x03,D|T|W|S|O|B|K,"Multiple read errors"}, - {0x11,0x04,D|W|O|B|K,"Unrecovered read error - auto reallocate failed"}, - {0x11,0x05,W|R|O|B,"L-EC uncorrectable error"}, - {0x11,0x06,W|R|O|B,"CIRC unrecovered error"}, - {0x11,0x07,W|O|B,"Data re-synchronization error"}, - {0x11,0x08,T,"Incomplete block read"}, - {0x11,0x09,T,"No gap found"}, - {0x11,0x0A,D|T|O|B|K,"Miscorrected error"}, - {0x11,0x0B,D|W|O|B|K,"Unrecovered read error - recommend reassignment"}, - {0x11,0x0C,D|W|O|B|K,"Unrecovered read error - recommend rewrite the data"}, - {0x11,0x0D,D|T|W|R|O|B,"De-compression CRC error"}, - {0x11,0x0E,D|T|W|R|O|B,"Cannot decompress using declared algorithm"}, - {0x11,0x0F,R,"Error reading UPC/EAN number"}, - {0x11,0x10,R,"Error reading ISRC number"}, - {0x11,0x11,R,"Read error - loss of streaming"}, - {0x12,0x00,D|W|O|B|K,"Address mark not found for id field"}, - {0x13,0x00,D|W|O|B|K,"Address mark not found for data field"}, - {0x14,0x00,D|T|L|W|R|S|O|B|K,"Recorded entity not found"}, - {0x14,0x01,D|T|W|R|O|B|K,"Record not found"}, - {0x14,0x02,T,"Filemark or setmark not found"}, - {0x14,0x03,T,"End-of-data not found"}, - {0x14,0x04,T,"Block sequence error"}, - {0x14,0x05,D|T|W|O|B|K,"Record not found - recommend reassignment"}, - {0x14,0x06,D|T|W|O|B|K,"Record not found - data auto-reallocated"}, - {0x15,0x00,D|T|L|W|R|S|O|M|B|K,"Random positioning error"}, - {0x15,0x01,D|T|L|W|R|S|O|M|B|K,"Mechanical positioning error"}, - {0x15,0x02,D|T|W|R|O|B|K,"Positioning error detected by read of medium"}, - {0x16,0x00,D|W|O|B|K,"Data synchronization mark error"}, - {0x16,0x01,D|W|O|B|K,"Data sync error - data rewritten"}, - {0x16,0x02,D|W|O|B|K,"Data sync error - recommend rewrite"}, - {0x16,0x03,D|W|O|B|K,"Data sync error - data auto-reallocated"}, - {0x16,0x04,D|W|O|B|K,"Data sync error - recommend reassignment"}, - {0x17,0x00,D|T|W|R|S|O|B|K,"Recovered data with no error correction applied"}, - {0x17,0x01,D|T|W|R|S|O|B|K,"Recovered data with retries"}, - {0x17,0x02,D|T|W|R|O|B|K,"Recovered data with positive head offset"}, - {0x17,0x03,D|T|W|R|O|B|K,"Recovered data with negative head offset"}, - {0x17,0x04,W|R|O|B,"Recovered data with retries and/or circ applied"}, - {0x17,0x05,D|W|R|O|B|K,"Recovered data using previous sector id"}, - {0x17,0x06,D|W|O|B|K,"Recovered data without ecc - data auto-reallocated"}, - {0x17,0x07,D|W|R|O|B|K,"Recovered data without ecc - recommend reassignment"}, - {0x17,0x08,D|W|R|O|B|K,"Recovered data without ecc - recommend rewrite"}, - {0x17,0x09,D|W|R|O|B|K,"Recovered data without ecc - data rewritten"}, - {0x18,0x00,D|T|W|R|O|B|K,"Recovered data with error correction applied"}, - {0x18,0x01,D|W|R|O|B|K,"Recovered data with error corr. & retries applied"}, - {0x18,0x02,D|W|R|O|B|K,"Recovered data - data auto-reallocated"}, - {0x18,0x03,R,"Recovered data with CIRC"}, - {0x18,0x04,R,"Recovered data with L-EC"}, - {0x18,0x05,D|W|R|O|B|K,"Recovered data - recommend reassignment"}, - {0x18,0x06,D|W|R|O|B|K,"Recovered data - recommend rewrite"}, - {0x18,0x07,D|W|O|B|K,"Recovered data with ecc - data rewritten"}, - {0x19,0x00,D|O|K,"Defect list error"}, - {0x19,0x01,D|O|K,"Defect list not available"}, - {0x19,0x02,D|O|K,"Defect list error in primary list"}, - {0x19,0x03,D|O|K,"Defect list error in grown list"}, - {0x1A,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Parameter list length error"}, - {0x1B,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Synchronous data transfer error"}, - {0x1C,0x00,D|O|B|K,"Defect list not found"}, - {0x1C,0x01,D|O|B|K,"Primary defect list not found"}, - {0x1C,0x02,D|O|B|K,"Grown defect list not found"}, - {0x1D,0x00,D|T|W|R|O|B|K,"Miscompare during verify operation"}, - {0x1E,0x00,D|W|O|B|K,"Recovered id with ecc correction"}, - {0x1F,0x00,D|O|K,"Partial defect list transfer"}, - {0x20,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Invalid command operation code"}, - {0x21,0x00,D|T|W|R|O|M|B|K,"Logical block address out of range"}, - {0x21,0x01,D|T|W|R|O|M|B|K,"Invalid element address"}, - {0x22,0x00,D,"Illegal function (use 20 00,24 00,or 26 00)"}, - {0x24,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Invalid field in cdb"}, - {0x24,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"CDB decryption error"}, - {0x25,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit not supported"}, - {0x26,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Invalid field in parameter list"}, - {0x26,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Parameter not supported"}, - {0x26,0x02,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Parameter value invalid"}, - {0x26,0x03,D|T|L|P|W|R|S|O|M|C|A|E|K,"Threshold parameters not supported"}, - {0x26,0x04,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Invalid release of persistent reservation"}, - {0x26,0x05,D|T|L|P|W|R|S|O|M|C|A|B|K,"Data decryption error"}, - {0x26,0x06,D|T|L|P|W|R|S|O|C|K,"Too many target descriptors"}, - {0x26,0x07,D|T|L|P|W|R|S|O|C|K,"Unsupported target descriptor type code"}, - {0x26,0x08,D|T|L|P|W|R|S|O|C|K,"Too many segment descriptors"}, - {0x26,0x09,D|T|L|P|W|R|S|O|C|K,"Unsupported segment descriptor type code"}, - {0x26,0x0A,D|T|L|P|W|R|S|O|C|K,"Unexpected inexact segment"}, - {0x26,0x0B,D|T|L|P|W|R|S|O|C|K,"Inline data length exceeded"}, - {0x26,0x0C,D|T|L|P|W|R|S|O|C|K,"Invalid operation for copy source or destination"}, - {0x26,0x0D,D|T|L|P|W|R|S|O|C|K,"Copy segment granularity violation"}, - {0x27,0x00,D|T|W|R|O|B|K,"Write protected"}, - {0x27,0x01,D|T|W|R|O|B|K,"Hardware write protected"}, - {0x27,0x02,D|T|W|R|O|B|K,"Logical unit software write protected"}, - {0x27,0x03,T|R,"Associated write protect"}, - {0x27,0x04,T|R,"Persistent write protect"}, - {0x27,0x05,T|R,"Permanent write protect"}, - {0x28,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Not ready to ready change,medium may have changed"}, - {0x28,0x01,D|T|W|R|O|M|B,"Import or export element accessed"}, - {0x29,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Power on,reset,or bus device reset occurred"}, - {0x29,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Power on occurred"}, - {0x29,0x02,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Scsi bus reset occurred"}, - {0x29,0x03,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Bus device reset function occurred"}, - {0x29,0x04,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Device internal reset"}, - {0x29,0x05,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Transceiver mode changed to single-ended"}, - {0x29,0x06,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Transceiver mode changed to lvd"}, - {0x2A,0x00,D|T|L|W|R|S|O|M|C|A|E|B|K,"Parameters changed"}, - {0x2A,0x01,D|T|L|W|R|S|O|M|C|A|E|B|K,"Mode parameters changed"}, - {0x2A,0x02,D|T|L|W|R|S|O|M|C|A|E|K,"Log parameters changed"}, - {0x2A,0x03,D|T|L|P|W|R|S|O|M|C|A|E|K,"Reservations preempted"}, - {0x2A,0x04,D|T|L|P|W|R|S|O|M|C|A|E,"Reservations released"}, - {0x2A,0x05,D|T|L|P|W|R|S|O|M|C|A|E,"Registrations preempted"}, - {0x2B,0x00,D|T|L|P|W|R|S|O|C|K,"Copy cannot execute since host cannot disconnect"}, - {0x2C,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Command sequence error"}, - {0x2C,0x01,S,"Too many windows specified"}, - {0x2C,0x02,S,"Invalid combination of windows specified"}, - {0x2C,0x03,R,"Current program area is not empty"}, - {0x2C,0x04,R,"Current program area is empty"}, - {0x2C,0x05,B,"Illegal power condition request"}, - {0x2D,0x00,T,"Overwrite error on update in place"}, - {0x2F,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Commands cleared by another initiator"}, - {0x30,0x00,D|T|W|R|O|M|B|K,"Incompatible medium installed"}, - {0x30,0x01,D|T|W|R|O|B|K,"Cannot read medium - unknown format"}, - {0x30,0x02,D|T|W|R|O|B|K,"Cannot read medium - incompatible format"}, - {0x30,0x03,D|T|R|K,"Cleaning cartridge installed"}, - {0x30,0x04,D|T|W|R|O|B|K,"Cannot write medium - unknown format"}, - {0x30,0x05,D|T|W|R|O|B|K,"Cannot write medium - incompatible format"}, - {0x30,0x06,D|T|W|R|O|B,"Cannot format medium - incompatible medium"}, - {0x30,0x07,D|T|L|W|R|S|O|M|A|E|B|K,"Cleaning failure"}, - {0x30,0x08,R,"Cannot write - application code mismatch"}, - {0x30,0x09,R,"Current session not fixated for append"}, - {0x31,0x00,D|T|W|R|O|B|K,"Medium format corrupted"}, - {0x31,0x01,D|L|R|O|B,"Format command failed"}, - {0x32,0x00,D|W|O|B|K,"No defect spare location available"}, - {0x32,0x01,D|W|O|B|K,"Defect list update failure"}, - {0x33,0x00,T,"Tape length error"}, - {0x34,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Enclosure failure"}, - {0x35,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Enclosure services failure"}, - {0x35,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Unsupported enclosure function"}, - {0x35,0x02,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Enclosure services unavailable"}, - {0x35,0x03,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Enclosure services transfer failure"}, - {0x35,0x04,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Enclosure services transfer refused"}, - {0x36,0x00,L,"Ribbon,ink,or toner failure"}, - {0x37,0x00,D|T|L|W|R|S|O|M|C|A|E|B|K,"Rounded parameter"}, - {0x38,0x00,B,"Event status notification"}, - {0x38,0x02,B,"Esn - power management class event"}, - {0x38,0x04,B,"Esn - media class event"}, - {0x38,0x06,B,"Esn - device busy class event"}, - {0x39,0x00,D|T|L|W|R|S|O|M|C|A|E|K,"Saving parameters not supported"}, - {0x3A,0x00,D|T|L|W|R|S|O|M|B|K,"Medium not present"}, - {0x3A,0x01,D|T|W|R|O|M|B|K,"Medium not present - tray closed"}, - {0x3A,0x02,D|T|W|R|O|M|B|K,"Medium not present - tray open"}, - {0x3A,0x03,D|T|W|R|O|M|B,"Medium not present - loadable"}, - {0x3A,0x04,D|T|W|R|O|M|B,"Medium not present - medium auxiliary memory accessible"}, - {0x3B,0x00,T|L,"Sequential positioning error"}, - {0x3B,0x01,T,"Tape position error at beginning-of-medium"}, - {0x3B,0x02,T,"Tape position error at end-of-medium"}, - {0x3B,0x03,L,"Tape or electronic vertical forms unit not ready"}, - {0x3B,0x04,L,"Slew failure"}, - {0x3B,0x05,L,"Paper jam"}, - {0x3B,0x06,L,"Failed to sense top-of-form"}, - {0x3B,0x07,L,"Failed to sense bottom-of-form"}, - {0x3B,0x08,T,"Reposition error"}, - {0x3B,0x09,S,"Read past end of medium"}, - {0x3B,0x0A,S,"Read past beginning of medium"}, - {0x3B,0x0B,S,"Position past end of medium"}, - {0x3B,0x0C,T|S,"Position past beginning of medium"}, - {0x3B,0x0D,D|T|W|R|O|M|B|K,"Medium destination element full"}, - {0x3B,0x0E,D|T|W|R|O|M|B|K,"Medium source element empty"}, - {0x3B,0x0F,R,"End of medium reached"}, - {0x3B,0x11,D|T|W|R|O|M|B|K,"Medium magazine not accessible"}, - {0x3B,0x12,D|T|W|R|O|M|B|K,"Medium magazine removed"}, - {0x3B,0x13,D|T|W|R|O|M|B|K,"Medium magazine inserted"}, - {0x3B,0x14,D|T|W|R|O|M|B|K,"Medium magazine locked"}, - {0x3B,0x15,D|T|W|R|O|M|B|K,"Medium magazine unlocked"}, - {0x3B,0x16,R,"Mechanical positioning or changer error"}, - {0x3D,0x00,D|T|L|P|W|R|S|O|M|C|A|E|K,"Invalid bits in identify message"}, - {0x3E,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit has not self-configured yet"}, - {0x3E,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit failure"}, - {0x3E,0x02,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Timeout on logical unit"}, - {0x3E,0x03,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit failed self-test"}, - {0x3E,0x04,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit unable to update self-test log"}, - {0x3F,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Target operating conditions have changed"}, - {0x3F,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Microcode has been changed"}, - {0x3F,0x02,D|T|L|P|W|R|S|O|M|C|B|K,"Changed operating definition"}, - {0x3F,0x03,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Inquiry data has changed"}, - {0x3F,0x04,D|T|W|R|O|M|C|A|E|B|K,"Component device attached"}, - {0x3F,0x05,D|T|W|R|O|M|C|A|E|B|K,"Device identifier changed"}, - {0x3F,0x06,D|T|W|R|O|M|C|A|E|B,"Redundancy group created or modified"}, - {0x3F,0x07,D|T|W|R|O|M|C|A|E|B,"Redundancy group deleted"}, - {0x3F,0x08,D|T|W|R|O|M|C|A|E|B,"Spare created or modified"}, - {0x3F,0x09,D|T|W|R|O|M|C|A|E|B,"Spare deleted"}, - {0x3F,0x0A,D|T|W|R|O|M|C|A|E|B|K,"Volume set created or modified"}, - {0x3F,0x0B,D|T|W|R|O|M|C|A|E|B|K,"Volume set deleted"}, - {0x3F,0x0C,D|T|W|R|O|M|C|A|E|B|K,"Volume set deassigned"}, - {0x3F,0x0D,D|T|W|R|O|M|C|A|E|B|K,"Volume set reassigned"}, - {0x3F,0x0E,D|T|L|P|W|R|S|O|M|C|A|E,"Reported luns data has changed"}, - {0x3F,0x10,D|T|W|R|O|M|B,"Medium loadable"}, - {0x3F,0x11,D|T|W|R|O|M|B,"Medium auxiliary memory accessible"}, - {0x40,0x00,D,"Ram failure (should use 40 nn)"}, - /* - * FIXME(eric) - need a way to represent wildcards here. - */ - {0x40,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Diagnostic failure on component nn (80h-ffh)"}, - {0x41,0x00,D,"Data path failure (should use 40 nn)"}, - {0x42,0x00,D,"Power-on or self-test failure (should use 40 nn)"}, - {0x43,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Message error"}, - {0x44,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Internal target failure"}, - {0x45,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Select or reselect failure"}, - {0x46,0x00,D|T|L|P|W|R|S|O|M|C|B|K,"Unsuccessful soft reset"}, - {0x47,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Scsi parity error"}, - {0x47,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Data phase CRC error detected"}, - {0x47,0x02,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Scsi parity error detected during st data phase"}, - {0x47,0x03,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Information unit CRC error detected"}, - {0x47,0x04,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Asynchronous information protection error detected"}, - {0x48,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Initiator detected error message received"}, - {0x49,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Invalid message error"}, - {0x4A,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Command phase error"}, - {0x4B,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Data phase error"}, - {0x4C,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit failed self-configuration"}, - /* - * FIXME(eric) - need a way to represent wildcards here. - */ - {0x4D,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Tagged overlapped commands (nn = queue tag)"}, - {0x4E,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Overlapped commands attempted"}, - {0x50,0x00,T,"Write append error"}, - {0x50,0x01,T,"Write append position error"}, - {0x50,0x02,T,"Position error related to timing"}, - {0x51,0x00,T|R|O,"Erase failure"}, - {0x52,0x00,T,"Cartridge fault"}, - {0x53,0x00,D|T|L|W|R|S|O|M|B|K,"Media load or eject failed"}, - {0x53,0x01,T,"Unload tape failure"}, - {0x53,0x02,D|T|W|R|O|M|B|K,"Medium removal prevented"}, - {0x54,0x00,P,"Scsi to host system interface failure"}, - {0x55,0x00,P,"System resource failure"}, - {0x55,0x01,D|O|B|K,"System buffer full"}, - {0x55,0x02,D|T|L|P|W|R|S|O|M|A|E|K,"Insufficient reservation resources"}, - {0x55,0x03,D|T|L|P|W|R|S|O|M|C|A|E,"Insufficient resources"}, - {0x55,0x04,D|T|L|P|W|R|S|O|M|A|E,"Insufficient registration resources"}, - {0x57,0x00,R,"Unable to recover table-of-contents"}, - {0x58,0x00,O,"Generation does not exist"}, - {0x59,0x00,O,"Updated block read"}, - {0x5A,0x00,D|T|L|P|W|R|S|O|M|B|K,"Operator request or state change input"}, - {0x5A,0x01,D|T|W|R|O|M|B|K,"Operator medium removal request"}, - {0x5A,0x02,D|T|W|R|O|A|B|K,"Operator selected write protect"}, - {0x5A,0x03,D|T|W|R|O|A|B|K,"Operator selected write permit"}, - {0x5B,0x00,D|T|L|P|W|R|S|O|M|K,"Log exception"}, - {0x5B,0x01,D|T|L|P|W|R|S|O|M|K,"Threshold condition met"}, - {0x5B,0x02,D|T|L|P|W|R|S|O|M|K,"Log counter at maximum"}, - {0x5B,0x03,D|T|L|P|W|R|S|O|M|K,"Log list codes exhausted"}, - {0x5C,0x00,D|O,"Rpl status change"}, - {0x5C,0x01,D|O,"Spindles synchronized"}, - {0x5C,0x02,D|O,"Spindles not synchronized"}, - {0x5D,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Failure prediction threshold exceeded"}, - {0x5D,0x01,R|B,"Media failure prediction threshold exceeded"}, - {0x5D,0x02,R,"Logical unit failure prediction threshold exceeded"}, - {0x5D,0x10,D|B,"Hardware impending failure general hard drive failure"}, - {0x5D,0x11,D|B,"Hardware impending failure drive error rate too high"}, - {0x5D,0x12,D|B,"Hardware impending failure data error rate too high"}, - {0x5D,0x13,D|B,"Hardware impending failure seek error rate too high"}, - {0x5D,0x14,D|B,"Hardware impending failure too many block reassigns"}, - {0x5D,0x15,D|B,"Hardware impending failure access times too high"}, - {0x5D,0x16,D|B,"Hardware impending failure start unit times too high"}, - {0x5D,0x17,D|B,"Hardware impending failure channel parametrics"}, - {0x5D,0x18,D|B,"Hardware impending failure controller detected"}, - {0x5D,0x19,D|B,"Hardware impending failure throughput performance"}, - {0x5D,0x1A,D|B,"Hardware impending failure seek time performance"}, - {0x5D,0x1B,D|B,"Hardware impending failure spin-up retry count"}, - {0x5D,0x1C,D|B,"Hardware impending failure drive calibration retry count"}, - {0x5D,0x20,D|B,"Controller impending failure general hard drive failure"}, - {0x5D,0x21,D|B,"Controller impending failure drive error rate too high"}, - {0x5D,0x22,D|B,"Controller impending failure data error rate too high"}, - {0x5D,0x23,D|B,"Controller impending failure seek error rate too high"}, - {0x5D,0x24,D|B,"Controller impending failure too many block reassigns"}, - {0x5D,0x25,D|B,"Controller impending failure access times too high"}, - {0x5D,0x26,D|B,"Controller impending failure start unit times too high"}, - {0x5D,0x27,D|B,"Controller impending failure channel parametrics"}, - {0x5D,0x28,D|B,"Controller impending failure controller detected"}, - {0x5D,0x29,D|B,"Controller impending failure throughput performance"}, - {0x5D,0x2A,D|B,"Controller impending failure seek time performance"}, - {0x5D,0x2B,D|B,"Controller impending failure spin-up retry count"}, - {0x5D,0x2C,D|B,"Controller impending failure drive calibration retry count"}, - {0x5D,0x30,D|B,"Data channel impending failure general hard drive failure"}, - {0x5D,0x31,D|B,"Data channel impending failure drive error rate too high"}, - {0x5D,0x32,D|B,"Data channel impending failure data error rate too high"}, - {0x5D,0x33,D|B,"Data channel impending failure seek error rate too high"}, - {0x5D,0x34,D|B,"Data channel impending failure too many block reassigns"}, - {0x5D,0x35,D|B,"Data channel impending failure access times too high"}, - {0x5D,0x36,D|B,"Data channel impending failure start unit times too high"}, - {0x5D,0x37,D|B,"Data channel impending failure channel parametrics"}, - {0x5D,0x38,D|B,"Data channel impending failure controller detected"}, - {0x5D,0x39,D|B,"Data channel impending failure throughput performance"}, - {0x5D,0x3A,D|B,"Data channel impending failure seek time performance"}, - {0x5D,0x3B,D|B,"Data channel impending failure spin-up retry count"}, - {0x5D,0x3C,D|B,"Data channel impending failure drive calibration retry count"}, - {0x5D,0x40,D|B,"Servo impending failure general hard drive failure"}, - {0x5D,0x41,D|B,"Servo impending failure drive error rate too high"}, - {0x5D,0x42,D|B,"Servo impending failure data error rate too high"}, - {0x5D,0x43,D|B,"Servo impending failure seek error rate too high"}, - {0x5D,0x44,D|B,"Servo impending failure too many block reassigns"}, - {0x5D,0x45,D|B,"Servo impending failure access times too high"}, - {0x5D,0x46,D|B,"Servo impending failure start unit times too high"}, - {0x5D,0x47,D|B,"Servo impending failure channel parametrics"}, - {0x5D,0x48,D|B,"Servo impending failure controller detected"}, - {0x5D,0x49,D|B,"Servo impending failure throughput performance"}, - {0x5D,0x4A,D|B,"Servo impending failure seek time performance"}, - {0x5D,0x4B,D|B,"Servo impending failure spin-up retry count"}, - {0x5D,0x4C,D|B,"Servo impending failure drive calibration retry count"}, - {0x5D,0x50,D|B,"Spindle impending failure general hard drive failure"}, - {0x5D,0x51,D|B,"Spindle impending failure drive error rate too high"}, - {0x5D,0x52,D|B,"Spindle impending failure data error rate too high"}, - {0x5D,0x53,D|B,"Spindle impending failure seek error rate too high"}, - {0x5D,0x54,D|B,"Spindle impending failure too many block reassigns"}, - {0x5D,0x55,D|B,"Spindle impending failure access times too high"}, - {0x5D,0x56,D|B,"Spindle impending failure start unit times too high"}, - {0x5D,0x57,D|B,"Spindle impending failure channel parametrics"}, - {0x5D,0x58,D|B,"Spindle impending failure controller detected"}, - {0x5D,0x59,D|B,"Spindle impending failure throughput performance"}, - {0x5D,0x5A,D|B,"Spindle impending failure seek time performance"}, - {0x5D,0x5B,D|B,"Spindle impending failure spin-up retry count"}, - {0x5D,0x5C,D|B,"Spindle impending failure drive calibration retry count"}, - {0x5D,0x60,D|B,"Firmware impending failure general hard drive failure"}, - {0x5D,0x61,D|B,"Firmware impending failure drive error rate too high"}, - {0x5D,0x62,D|B,"Firmware impending failure data error rate too high"}, - {0x5D,0x63,D|B,"Firmware impending failure seek error rate too high"}, - {0x5D,0x64,D|B,"Firmware impending failure too many block reassigns"}, - {0x5D,0x65,D|B,"Firmware impending failure access times too high"}, - {0x5D,0x66,D|B,"Firmware impending failure start unit times too high"}, - {0x5D,0x67,D|B,"Firmware impending failure channel parametrics"}, - {0x5D,0x68,D|B,"Firmware impending failure controller detected"}, - {0x5D,0x69,D|B,"Firmware impending failure throughput performance"}, - {0x5D,0x6A,D|B,"Firmware impending failure seek time performance"}, - {0x5D,0x6B,D|B,"Firmware impending failure spin-up retry count"}, - {0x5D,0x6C,D|B,"Firmware impending failure drive calibration retry count"}, - {0x5D,0xFF,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Failure prediction threshold exceeded (false)"}, - {0x5E,0x00,D|T|L|P|W|R|S|O|C|A|K,"Low power condition on"}, - {0x5E,0x01,D|T|L|P|W|R|S|O|C|A|K,"Idle condition activated by timer"}, - {0x5E,0x02,D|T|L|P|W|R|S|O|C|A|K,"Standby condition activated by timer"}, - {0x5E,0x03,D|T|L|P|W|R|S|O|C|A|K,"Idle condition activated by command"}, - {0x5E,0x04,D|T|L|P|W|R|S|O|C|A|K,"Standby condition activated by command"}, - {0x5E,0x41,B,"Power state change to active"}, - {0x5E,0x42,B,"Power state change to idle"}, - {0x5E,0x43,B,"Power state change to standby"}, - {0x5E,0x45,B,"Power state change to sleep"}, - {0x5E,0x47,B|K,"Power state change to device control"}, - {0x60,0x00,S,"Lamp failure"}, - {0x61,0x00,S,"Video acquisition error"}, - {0x61,0x01,S,"Unable to acquire video"}, - {0x61,0x02,S,"Out of focus"}, - {0x62,0x00,S,"Scan head positioning error"}, - {0x63,0x00,R,"End of user area encountered on this track"}, - {0x63,0x01,R,"Packet does not fit in available space"}, - {0x64,0x00,R,"Illegal mode for this track"}, - {0x64,0x01,R,"Invalid packet size"}, - {0x65,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Voltage fault"}, - {0x66,0x00,S,"Automatic document feeder cover up"}, - {0x66,0x01,S,"Automatic document feeder lift up"}, - {0x66,0x02,S,"Document jam in automatic document feeder"}, - {0x66,0x03,S,"Document miss feed automatic in document feeder"}, - {0x67,0x00,A,"Configuration failure"}, - {0x67,0x01,A,"Configuration of incapable logical units failed"}, - {0x67,0x02,A,"Add logical unit failed"}, - {0x67,0x03,A,"Modification of logical unit failed"}, - {0x67,0x04,A,"Exchange of logical unit failed"}, - {0x67,0x05,A,"Remove of logical unit failed"}, - {0x67,0x06,A,"Attachment of logical unit failed"}, - {0x67,0x07,A,"Creation of logical unit failed"}, - {0x67,0x08,A,"Assign failure occurred"}, - {0x67,0x09,A,"Multiply assigned logical unit"}, - {0x68,0x00,A,"Logical unit not configured"}, - {0x69,0x00,A,"Data loss on logical unit"}, - {0x69,0x01,A,"Multiple logical unit failures"}, - {0x69,0x02,A,"Parity/data mismatch"}, - {0x6A,0x00,A,"Informational,refer to log"}, - {0x6B,0x00,A,"State change has occurred"}, - {0x6B,0x01,A,"Redundancy level got better"}, - {0x6B,0x02,A,"Redundancy level got worse"}, - {0x6C,0x00,A,"Rebuild failure occurred"}, - {0x6D,0x00,A,"Recalculate failure occurred"}, - {0x6E,0x00,A,"Command to logical unit failed"}, - {0x6F,0x00,R,"Copy protection key exchange failure - authentication failure"}, - {0x6F,0x01,R,"Copy protection key exchange failure - key not present"}, - {0x6F,0x02,R,"Copy protection key exchange failure - key not established"}, - {0x6F,0x03,R,"Read of scrambled sector without authentication"}, - {0x6F,0x04,R,"Media region code is mismatched to logical unit region"}, - {0x6F,0x05,R,"Drive region must be permanent/region reset count error"}, - /* - * FIXME(eric) - need a way to represent wildcards here. - */ - {0x70,0x00,T,"Decompression exception short algorithm id of nn"}, - {0x71,0x00,T,"Decompression exception long algorithm id"}, - {0x72,0x00,R,"Session fixation error"}, - {0x72,0x01,R,"Session fixation error writing lead-in"}, - {0x72,0x02,R,"Session fixation error writing lead-out"}, - {0x72,0x03,R,"Session fixation error - incomplete track in session"}, - {0x72,0x04,R,"Empty or partially written reserved track"}, - {0x72,0x05,R,"No more track reservations allowed"}, - {0x73,0x00,R,"Cd control error"}, - {0x73,0x01,R,"Power calibration area almost full"}, - {0x73,0x02,R,"Power calibration area is full"}, - {0x73,0x03,R,"Power calibration area error"}, - {0x73,0x04,R,"Program memory area update failure"}, - {0x73,0x05,R,"Program memory area is full"}, - {0x73,0x06,R,"RMA/PMA is full"}, - {0, 0, 0, NULL} -}; -#endif - -#if (CONSTANTS & CONST_SENSE) -static const char *snstext[] = { - "None", /* There is no sense information */ - "Recovered Error", /* The last command completed successfully - but used error correction */ - "Not Ready", /* The addressed target is not ready */ - "Medium Error", /* Data error detected on the medium */ - "Hardware Error", /* Controller or device failure */ - "Illegal Request", - "Unit Attention", /* Removable medium was changed, or - the target has been reset */ - "Data Protect", /* Access to the data is blocked */ - "Blank Check", /* Reached unexpected written or unwritten - region of the medium */ - "Key=9", /* Vendor specific */ - "Copy Aborted", /* COPY or COMPARE was aborted */ - "Aborted Command", /* The target aborted the command */ - "Equal", /* A SEARCH DATA command found data equal */ - "Volume Overflow", /* Medium full with still data to be written */ - "Miscompare", /* Source data and data on the medium - do not agree */ - "Key=15" /* Reserved */ -}; -#endif - -/* Print sense information */ -static -void print_sense_internal(const char * devclass, - const unsigned char * sense_buffer, - kdev_t dev) -{ - int i, s; - int sense_class, valid, code, info; - const char * error = NULL; - - sense_class = (sense_buffer[0] >> 4) & 0x07; - code = sense_buffer[0] & 0xf; - valid = sense_buffer[0] & 0x80; - - if (sense_class == 7) { /* extended sense data */ - s = sense_buffer[7] + 8; - if(s > SCSI_SENSE_BUFFERSIZE) - s = SCSI_SENSE_BUFFERSIZE; - - info = ((sense_buffer[3] << 24) | (sense_buffer[4] << 16) | - (sense_buffer[5] << 8) | sense_buffer[6]); - if (info || valid) { - printk("Info fld=0x%x", info); - if (!valid) /* info data not according to standard */ - printk(" (nonstd)"); - printk(", "); - } - if (sense_buffer[2] & 0x80) - printk( "FMK "); /* current command has read a filemark */ - if (sense_buffer[2] & 0x40) - printk( "EOM "); /* end-of-medium condition exists */ - if (sense_buffer[2] & 0x20) - printk( "ILI "); /* incorrect block length requested */ - - switch (code) { - case 0x0: - error = "Current"; /* error concerns current command */ - break; - case 0x1: - error = "Deferred"; /* error concerns some earlier command */ - /* e.g., an earlier write to disk cache succeeded, but - now the disk discovers that it cannot write the data */ - break; - default: - error = "Invalid"; - } - - printk("%s ", error); - -#if (CONSTANTS & CONST_SENSE) - printk( "%s%s: sense key %s\n", devclass, - kdevname(dev), snstext[sense_buffer[2] & 0x0f]); -#else - printk("%s%s: sns = %2x %2x\n", devclass, - kdevname(dev), sense_buffer[0], sense_buffer[2]); -#endif - - /* Check to see if additional sense information is available */ - if(sense_buffer[7] + 7 < 13 || - (sense_buffer[12] == 0 && sense_buffer[13] == 0)) goto done; - -#if (CONSTANTS & CONST_XSENSE) - for(i=0; additional[i].text; i++) - if(additional[i].code1 == sense_buffer[12] && - additional[i].code2 == sense_buffer[13]) - printk("Additional sense indicates %s\n", additional[i].text); - - for(i=0; additional2[i].text; i++) - if(additional2[i].code1 == sense_buffer[12] && - additional2[i].code2_min >= sense_buffer[13] && - additional2[i].code2_max <= sense_buffer[13]) { - printk("Additional sense indicates "); - printk(additional2[i].text, sense_buffer[13]); - printk("\n"); - }; -#else - printk("ASC=%2x ASCQ=%2x\n", sense_buffer[12], sense_buffer[13]); -#endif - } else { /* non-extended sense data */ - - /* - * Standard says: - * sense_buffer[0] & 0200 : address valid - * sense_buffer[0] & 0177 : vendor-specific error code - * sense_buffer[1] & 0340 : vendor-specific - * sense_buffer[1..3] : 21-bit logical block address - */ - -#if (CONSTANTS & CONST_SENSE) - if (sense_buffer[0] < 15) - printk("%s%s: old sense key %s\n", devclass, - kdevname(dev), snstext[sense_buffer[0] & 0x0f]); - else -#endif - printk("%s%s: sns = %2x %2x\n", devclass, - kdevname(dev), sense_buffer[0], sense_buffer[2]); - - printk("Non-extended sense class %d code 0x%0x\n", sense_class, code); - s = 4; - } - - done: -#if !(CONSTANTS & CONST_SENSE) - printk("Raw sense data:"); - for (i = 0; i < s; ++i) - printk("0x%02x ", sense_buffer[i]); - printk("\n"); -#endif - return; -} - -void print_sense(const char * devclass, Scsi_Cmnd * SCpnt) -{ - print_sense_internal(devclass, SCpnt->sense_buffer, - SCpnt->request.rq_dev); -} - -void print_req_sense(const char * devclass, Scsi_Request * SRpnt) -{ - print_sense_internal(devclass, SRpnt->sr_sense_buffer, - SRpnt->sr_request.rq_dev); -} - -#if (CONSTANTS & CONST_MSG) -static const char *one_byte_msgs[] = { -/* 0x00 */ "Command Complete", NULL, "Save Pointers", -/* 0x03 */ "Restore Pointers", "Disconnect", "Initiator Error", -/* 0x06 */ "Abort", "Message Reject", "Nop", "Message Parity Error", -/* 0x0a */ "Linked Command Complete", "Linked Command Complete w/flag", -/* 0x0c */ "Bus device reset", "Abort Tag", "Clear Queue", -/* 0x0f */ "Initiate Recovery", "Release Recovery" -}; - -#define NO_ONE_BYTE_MSGS (sizeof(one_byte_msgs) / sizeof (const char *)) - -static const char *two_byte_msgs[] = { -/* 0x20 */ "Simple Queue Tag", "Head of Queue Tag", "Ordered Queue Tag" -/* 0x23 */ "Ignore Wide Residue" -}; - -#define NO_TWO_BYTE_MSGS (sizeof(two_byte_msgs) / sizeof (const char *)) - -static const char *extended_msgs[] = { -/* 0x00 */ "Modify Data Pointer", "Synchronous Data Transfer Request", -/* 0x02 */ "SCSI-I Extended Identify", "Wide Data Transfer Request" -}; - -#define NO_EXTENDED_MSGS (sizeof(two_byte_msgs) / sizeof (const char *)) -#endif /* (CONSTANTS & CONST_MSG) */ - -int print_msg (const unsigned char *msg) { - int len = 0, i; - if (msg[0] == EXTENDED_MESSAGE) { - len = 3 + msg[1]; -#if (CONSTANTS & CONST_MSG) - if (msg[2] < NO_EXTENDED_MSGS) - printk ("%s ", extended_msgs[msg[2]]); - else - printk ("Extended Message, reserved code (0x%02x) ", (int) msg[2]); - switch (msg[2]) { - case EXTENDED_MODIFY_DATA_POINTER: - printk("pointer = %d", (int) (msg[3] << 24) | (msg[4] << 16) | - (msg[5] << 8) | msg[6]); - break; - case EXTENDED_SDTR: - printk("period = %d ns, offset = %d", (int) msg[3] * 4, (int) - msg[4]); - break; - case EXTENDED_WDTR: - printk("width = 2^%d bytes", msg[3]); - break; - default: - for (i = 2; i < len; ++i) - printk("%02x ", msg[i]); - } -#else - for (i = 0; i < len; ++i) - printk("%02x ", msg[i]); -#endif - /* Identify */ - } else if (msg[0] & 0x80) { -#if (CONSTANTS & CONST_MSG) - printk("Identify disconnect %sallowed %s %d ", - (msg[0] & 0x40) ? "" : "not ", - (msg[0] & 0x20) ? "target routine" : "lun", - msg[0] & 0x7); -#else - printk("%02x ", msg[0]); -#endif - len = 1; - /* Normal One byte */ - } else if (msg[0] < 0x1f) { -#if (CONSTANTS & CONST_MSG) - if (msg[0] < NO_ONE_BYTE_MSGS) - printk(one_byte_msgs[msg[0]]); - else - printk("reserved (%02x) ", msg[0]); -#else - printk("%02x ", msg[0]); -#endif - len = 1; - /* Two byte */ - } else if (msg[0] <= 0x2f) { -#if (CONSTANTS & CONST_MSG) - if ((msg[0] - 0x20) < NO_TWO_BYTE_MSGS) - printk("%s %02x ", two_byte_msgs[msg[0] - 0x20], - msg[1]); - else - printk("reserved two byte (%02x %02x) ", - msg[0], msg[1]); -#else - printk("%02x %02x", msg[0], msg[1]); -#endif - len = 2; - } else -#if (CONSTANTS & CONST_MSG) - printk(reserved); -#else - printk("%02x ", msg[0]); -#endif - return len; -} - -void print_Scsi_Cmnd (Scsi_Cmnd *cmd) { - printk("scsi%d : destination target %d, lun %d\n", - cmd->host->host_no, - cmd->target, - cmd->lun); - printk(" command = "); - print_command (cmd->cmnd); -} - -#if (CONSTANTS & CONST_HOST) -static const char * hostbyte_table[]={ -"DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET", -"DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR", -"DID_PASSTHROUGH", "DID_SOFT_ERROR", NULL}; - -void print_hostbyte(int scsiresult) -{ static int maxcode=0; - int i; - - if(!maxcode) { - for(i=0;hostbyte_table[i];i++) ; - maxcode=i-1; - } - printk("Hostbyte=0x%02x",host_byte(scsiresult)); - if(host_byte(scsiresult)>maxcode) { - printk("is invalid "); - return; - } - printk("(%s) ",hostbyte_table[host_byte(scsiresult)]); -} -#else -void print_hostbyte(int scsiresult) -{ printk("Hostbyte=0x%02x ",host_byte(scsiresult)); -} -#endif - -#if (CONSTANTS & CONST_DRIVER) -static const char * driverbyte_table[]={ -"DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", "DRIVER_ERROR", -"DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD",NULL }; - -static const char * driversuggest_table[]={"SUGGEST_OK", -"SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE", -unknown,unknown,unknown, "SUGGEST_SENSE",NULL}; - - -void print_driverbyte(int scsiresult) -{ static int driver_max=0,suggest_max=0; - int i,dr=driver_byte(scsiresult)&DRIVER_MASK, - su=(driver_byte(scsiresult)&SUGGEST_MASK)>>4; - - if(!driver_max) { - for(i=0;driverbyte_table[i];i++) ; - driver_max=i; - for(i=0;driversuggest_table[i];i++) ; - suggest_max=i; - } - printk("Driverbyte=0x%02x",driver_byte(scsiresult)); - printk("(%s,%s) ", - dr - * - * Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli - * Added QLOGIC QLA1280 SCSI controller kernel host support. - * August 4, 1999 Fred Lewis, Intel DuPont - * - * Updated to reflect the new initialization scheme for the higher - * level of scsi drivers (sd/sr/st) - * September 17, 2000 Torben Mathiasen - */ - - -/* - * This file contains the medium level SCSI - * host interface initialization, as well as the scsi_hosts array of SCSI - * hosts currently present in the system. - */ - -#define __NO_VERSION__ -#include -#include -/* #include */ -/* #include */ -/* #include */ -/* #include */ -#include - -#define __KERNEL_SYSCALLS__ - -/* #include */ - -#include "scsi.h" -#include "hosts.h" - -/* -static const char RCSid[] = "$Header: /vger/u4/cvs/linux/drivers/scsi/hosts.c,v 1.20 1996/12/12 19:18:32 davem Exp $"; -*/ - -/* - * The scsi host entries should be in the order you wish the - * cards to be detected. A driver may appear more than once IFF - * it can deal with being detected (and therefore initialized) - * with more than one simultaneous host number, can handle being - * reentrant, etc. - * - * They may appear in any order, as each SCSI host is told which host - * number it is during detection. - */ - -/* This is a placeholder for controllers that are not configured into - * the system - we do this to ensure that the controller numbering is - * always consistent, no matter how the kernel is configured. */ - -#define NO_CONTROLLER {NULL, NULL, NULL, NULL, NULL, NULL, NULL, \ - NULL, NULL, 0, 0, 0, 0, 0, 0} - -/* - * When figure is run, we don't want to link to any object code. Since - * the macro for each host will contain function pointers, we cannot - * use it and instead must use a "blank" that does no such - * idiocy. - */ - -Scsi_Host_Template * scsi_hosts; - - -/* - * Our semaphores and timeout counters, where size depends on - * MAX_SCSI_HOSTS here. - */ - -Scsi_Host_Name * scsi_host_no_list; -struct Scsi_Host * scsi_hostlist; -struct Scsi_Device_Template * scsi_devicelist; - -int max_scsi_hosts; -int next_scsi_host; - -void -scsi_unregister(struct Scsi_Host * sh){ - struct Scsi_Host * shpnt; - Scsi_Host_Name *shn; - - if(scsi_hostlist == sh) - scsi_hostlist = sh->next; - else { - shpnt = scsi_hostlist; - while(shpnt->next != sh) shpnt = shpnt->next; - shpnt->next = shpnt->next->next; - } - - /* - * We have to unregister the host from the scsi_host_no_list as well. - * Decide by the host_no not by the name because most host drivers are - * able to handle more than one adapters from the same kind (or family). - */ - for ( shn=scsi_host_no_list; shn && (sh->host_no != shn->host_no); - shn=shn->next); - if (shn) shn->host_registered = 0; - /* else {} : This should not happen, we should panic here... */ - - /* If we are removing the last host registered, it is safe to reuse - * its host number (this avoids "holes" at boot time) (DB) - * It is also safe to reuse those of numbers directly below which have - * been released earlier (to avoid some holes in numbering). - */ - if(sh->host_no == max_scsi_hosts - 1) { - while(--max_scsi_hosts >= next_scsi_host) { - shpnt = scsi_hostlist; - while(shpnt && shpnt->host_no != max_scsi_hosts - 1) - shpnt = shpnt->next; - if(shpnt) - break; - } - } - next_scsi_host--; - kfree((char *) sh); -} - -/* We call this when we come across a new host adapter. We only do this - * once we are 100% sure that we want to use this host adapter - it is a - * pain to reverse this, so we try to avoid it - */ - -struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){ - struct Scsi_Host * retval, *shpnt, *o_shp; - Scsi_Host_Name *shn, *shn2; - int flag_new = 1; - const char * hname; - size_t hname_len; - retval = (struct Scsi_Host *)kmalloc(sizeof(struct Scsi_Host) + j, - (tpnt->unchecked_isa_dma && j ? - GFP_DMA : 0) | GFP_ATOMIC); - if(retval == NULL) - { - printk("scsi: out of memory in scsi_register.\n"); - return NULL; - } - - memset(retval, 0, sizeof(struct Scsi_Host) + j); - - /* trying to find a reserved entry (host_no) */ - hname = (tpnt->proc_name) ? tpnt->proc_name : ""; - hname_len = strlen(hname); - for (shn = scsi_host_no_list;shn;shn = shn->next) { - if (!(shn->host_registered) && - (hname_len > 0) && (0 == strncmp(hname, shn->name, hname_len))) { - flag_new = 0; - retval->host_no = shn->host_no; - shn->host_registered = 1; - shn->loaded_as_module = 1; - break; - } - } - atomic_set(&retval->host_active,0); - retval->host_busy = 0; - retval->host_failed = 0; - if(j > 0xffff) panic("Too many extra bytes requested\n"); - retval->extra_bytes = j; - retval->loaded_as_module = 1; - if (flag_new) { - shn = (Scsi_Host_Name *) kmalloc(sizeof(Scsi_Host_Name), GFP_ATOMIC); - if (!shn) { - kfree(retval); - printk(KERN_ERR "scsi: out of memory(2) in scsi_register.\n"); - return NULL; - } - shn->name = kmalloc(hname_len + 1, GFP_ATOMIC); - if (hname_len > 0) - strncpy(shn->name, hname, hname_len); - shn->name[hname_len] = 0; - shn->host_no = max_scsi_hosts++; - shn->host_registered = 1; - shn->loaded_as_module = 1; - shn->next = NULL; - if (scsi_host_no_list) { - for (shn2 = scsi_host_no_list;shn2->next;shn2 = shn2->next) - ; - shn2->next = shn; - } - else - scsi_host_no_list = shn; - retval->host_no = shn->host_no; - } - next_scsi_host++; - retval->host_queue = NULL; -#if 0 - init_waitqueue_head(&retval->host_wait); -#endif - retval->resetting = 0; - retval->last_reset = 0; - retval->irq = 0; - retval->dma_channel = 0xff; - - /* These three are default values which can be overridden */ - retval->max_channel = 0; - retval->max_id = 8; - retval->max_lun = 8; - - /* - * All drivers right now should be able to handle 12 byte commands. - * Every so often there are requests for 16 byte commands, but individual - * low-level drivers need to certify that they actually do something - * sensible with such commands. - */ - retval->max_cmd_len = 12; - - retval->unique_id = 0; - retval->io_port = 0; - retval->hostt = tpnt; - retval->next = NULL; - retval->in_recovery = 0; - retval->ehandler = NULL; /* Initial value until the thing starts up. */ - retval->eh_notify = NULL; /* Who we notify when we exit. */ - - - retval->host_blocked = FALSE; - retval->host_self_blocked = FALSE; - -#ifdef DEBUG - printk("Register %x %x: %d\n", (int)retval, (int)retval->hostt, j); -#endif - - /* The next six are the default values which can be overridden - * if need be */ - retval->this_id = tpnt->this_id; - retval->can_queue = tpnt->can_queue; - retval->sg_tablesize = tpnt->sg_tablesize; - retval->cmd_per_lun = tpnt->cmd_per_lun; - retval->unchecked_isa_dma = tpnt->unchecked_isa_dma; - retval->use_clustering = tpnt->use_clustering; - - retval->select_queue_depths = tpnt->select_queue_depths; - retval->max_sectors = tpnt->max_sectors; - - if(!scsi_hostlist) - scsi_hostlist = retval; - else { - shpnt = scsi_hostlist; - if (retval->host_no < shpnt->host_no) { - retval->next = shpnt; - wmb(); /* want all to see these writes in this order */ - scsi_hostlist = retval; - } - else { - for (o_shp = shpnt, shpnt = shpnt->next; shpnt; - o_shp = shpnt, shpnt = shpnt->next) { - if (retval->host_no < shpnt->host_no) { - retval->next = shpnt; - wmb(); - o_shp->next = retval; - break; - } - } - if (! shpnt) - o_shp->next = retval; - } - } - - return retval; -} - -int -scsi_register_device(struct Scsi_Device_Template * sdpnt) -{ - if(sdpnt->next) panic("Device already registered"); - sdpnt->next = scsi_devicelist; - scsi_devicelist = sdpnt; - return 0; -} - -void -scsi_deregister_device(struct Scsi_Device_Template * tpnt) -{ - struct Scsi_Device_Template *spnt; - struct Scsi_Device_Template *prev_spnt; - - spnt = scsi_devicelist; - prev_spnt = NULL; - while (spnt != tpnt) { - prev_spnt = spnt; - spnt = spnt->next; - } - if (prev_spnt == NULL) - scsi_devicelist = tpnt->next; - else - prev_spnt->next = spnt->next; -} - - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/xen/drivers/scsi/hosts.h b/xen/drivers/scsi/hosts.h deleted file mode 100644 index 77ee019eb8..0000000000 --- a/xen/drivers/scsi/hosts.h +++ /dev/null @@ -1,591 +0,0 @@ -/* - * hosts.h Copyright (C) 1992 Drew Eckhardt - * Copyright (C) 1993, 1994, 1995, 1998, 1999 Eric Youngdale - * - * mid to low-level SCSI driver interface header - * Initial versions: Drew Eckhardt - * Subsequent revisions: Eric Youngdale - * - * - * - * Modified by Eric Youngdale eric@andante.org to - * add scatter-gather, multiple outstanding request, and other - * enhancements. - * - * Further modified by Eric Youngdale to support multiple host adapters - * of the same type. - * - * Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli - */ - -#ifndef _HOSTS_H -#define _HOSTS_H - -/* - $Header: /vger/u4/cvs/linux/drivers/scsi/hosts.h,v 1.6 1997/01/19 23:07:13 davem Exp $ -*/ - -#include -/*#include */ -#include - -/* It is senseless to set SG_ALL any higher than this - the performance - * does not get any better, and it wastes memory - */ -#define SG_NONE 0 -#define SG_ALL 0xff - -#define DISABLE_CLUSTERING 0 -#define ENABLE_CLUSTERING 1 - -/* The various choices mean: - * NONE: Self evident. Host adapter is not capable of scatter-gather. - * ALL: Means that the host adapter module can do scatter-gather, - * and that there is no limit to the size of the table to which - * we scatter/gather data. - * Anything else: Indicates the maximum number of chains that can be - * used in one scatter-gather request. - */ - -/* - * The Scsi_Host_Template type has all that is needed to interface with a SCSI - * host in a device independent matter. There is one entry for each different - * type of host adapter that is supported on the system. - */ - -typedef struct scsi_disk Disk; - -typedef struct SHT -{ - - /* Used with loadable modules so we can construct a linked list. */ - struct SHT * next; - - /* Used with loadable modules so that we know when it is safe to unload */ - struct module * module; - -#ifdef CONFIG_PROC_FS - /* The pointer to the /proc/scsi directory entry */ - struct proc_dir_entry *proc_dir; - - /* proc-fs info function. - * Can be used to export driver statistics and other infos to the world - * outside the kernel ie. userspace and it also provides an interface - * to feed the driver with information. Check eata_dma_proc.c for reference - */ - int (*proc_info)(char *, char **, off_t, int, int, int); -#endif - - /* - * The name pointer is a pointer to the name of the SCSI - * device detected. - */ - const char *name; - - /* - * The detect function shall return non zero on detection, - * indicating the number of host adapters of this particular - * type were found. It should also - * initialize all data necessary for this particular - * SCSI driver. It is passed the host number, so this host - * knows where the first entry is in the scsi_hosts[] array. - * - * Note that the detect routine MUST not call any of the mid level - * functions to queue commands because things are not guaranteed - * to be set up yet. The detect routine can send commands to - * the host adapter as long as the program control will not be - * passed to scsi.c in the processing of the command. Note - * especially that scsi_malloc/scsi_free must not be called. - */ - int (* detect)(struct SHT *); - - int (*revoke)(Scsi_Device *); - - /* Used with loadable modules to unload the host structures. Note: - * there is a default action built into the modules code which may - * be sufficient for most host adapters. Thus you may not have to supply - * this at all. - */ - int (*release)(struct Scsi_Host *); - - /* - * The info function will return whatever useful - * information the developer sees fit. If not provided, then - * the name field will be used instead. - */ - const char *(* info)(struct Scsi_Host *); - - /* - * ioctl interface - */ - int (*ioctl)(Scsi_Device *dev, int cmd, void *arg); - - /* - * The command function takes a target, a command (this is a SCSI - * command formatted as per the SCSI spec, nothing strange), a - * data buffer pointer, and data buffer length pointer. The return - * is a status int, bit fielded as follows : - * Byte What - * 0 SCSI status code - * 1 SCSI 1 byte message - * 2 host error return. - * 3 mid level error return - */ - int (* command)(Scsi_Cmnd *); - - /* - * The QueueCommand function works in a similar manner - * to the command function. It takes an additional parameter, - * void (* done)(int host, int code) which is passed the host - * # and exit result when the command is complete. - * Host number is the POSITION IN THE hosts array of THIS - * host adapter. - * - * The done() function must only be called after QueueCommand() - * has returned. - */ - int (* queuecommand)(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); - - /* - * This is an error handling strategy routine. You don't need to - * define one of these if you don't want to - there is a default - * routine that is present that should work in most cases. For those - * driver authors that have the inclination and ability to write their - * own strategy routine, this is where it is specified. Note - the - * strategy routine is *ALWAYS* run in the context of the kernel eh - * thread. Thus you are guaranteed to *NOT* be in an interrupt handler - * when you execute this, and you are also guaranteed to *NOT* have any - * other commands being queued while you are in the strategy routine. - * When you return from this function, operations return to normal. - * - * See scsi_error.c scsi_unjam_host for additional comments about what - * this function should and should not be attempting to do. - */ - int (*eh_strategy_handler)(struct Scsi_Host *); - int (*eh_abort_handler)(Scsi_Cmnd *); - int (*eh_device_reset_handler)(Scsi_Cmnd *); - int (*eh_bus_reset_handler)(Scsi_Cmnd *); - int (*eh_host_reset_handler)(Scsi_Cmnd *); - - /* - * Since the mid level driver handles time outs, etc, we want to - * be able to abort the current command. Abort returns 0 if the - * abortion was successful. The field SCpnt->abort reason - * can be filled in with the appropriate reason why we wanted - * the abort in the first place, and this will be used - * in the mid-level code instead of the host_byte(). - * If non-zero, the code passed to it - * will be used as the return code, otherwise - * DID_ABORT should be returned. - * - * Note that the scsi driver should "clean up" after itself, - * resetting the bus, etc. if necessary. - * - * NOTE - this interface is depreciated, and will go away. Use - * the eh_ routines instead. - */ - int (* abort)(Scsi_Cmnd *); - - /* - * The reset function will reset the SCSI bus. Any executing - * commands should fail with a DID_RESET in the host byte. - * The Scsi_Cmnd is passed so that the reset routine can figure - * out which host adapter should be reset, and also which command - * within the command block was responsible for the reset in - * the first place. Some hosts do not implement a reset function, - * and these hosts must call scsi_request_sense(SCpnt) to keep - * the command alive. - * - * NOTE - this interface is depreciated, and will go away. Use - * the eh_ routines instead. - */ - int (* reset)(Scsi_Cmnd *, unsigned int); - - /* - * This function is used to select synchronous communications, - * which will result in a higher data throughput. Not implemented - * yet. - */ - int (* slave_attach)(int, int); - - /* - * This function determines the bios parameters for a given - * harddisk. These tend to be numbers that are made up by - * the host adapter. Parameters: - * size, device number, list (heads, sectors, cylinders) - */ - int (* bios_param)(Disk *, kdev_t, int []); - - - /* - * Used to set the queue depth for a specific device. - */ - void (*select_queue_depths)(struct Scsi_Host *, Scsi_Device *); - - /* - * This determines if we will use a non-interrupt driven - * or an interrupt driven scheme, It is set to the maximum number - * of simultaneous commands a given host adapter will accept. - */ - int can_queue; - - /* - * In many instances, especially where disconnect / reconnect are - * supported, our host also has an ID on the SCSI bus. If this is - * the case, then it must be reserved. Please set this_id to -1 if - * your setup is in single initiator mode, and the host lacks an - * ID. - */ - int this_id; - - /* - * This determines the degree to which the host adapter is capable - * of scatter-gather. - */ - short unsigned int sg_tablesize; - - /* - * if the host adapter has limitations beside segment count - */ - short unsigned int max_sectors; - - /* - * True if this host adapter can make good use of linked commands. - * This will allow more than one command to be queued to a given - * unit on a given host. Set this to the maximum number of command - * blocks to be provided for each device. Set this to 1 for one - * command block per lun, 2 for two, etc. Do not set this to 0. - * You should make sure that the host adapter will do the right thing - * before you try setting this above 1. - */ - short cmd_per_lun; - - /* - * present contains counter indicating how many boards of this - * type were found when we did the scan. - */ - unsigned char present; - - /* - * true if this host adapter uses unchecked DMA onto an ISA bus. - */ - unsigned unchecked_isa_dma:1; - - /* - * true if this host adapter can make good use of clustering. - * I originally thought that if the tablesize was large that it - * was a waste of CPU cycles to prepare a cluster list, but - * it works out that the Buslogic is faster if you use a smaller - * number of segments (i.e. use clustering). I guess it is - * inefficient. - */ - unsigned use_clustering:1; - - /* - * True if this driver uses the new error handling code. This flag is - * really only temporary until all of the other drivers get converted - * to use the new error handling code. - */ - unsigned use_new_eh_code:1; - - /* - * True for emulated SCSI host adapters (e.g. ATAPI) - */ - unsigned emulated:1; - - /* - * Name of proc directory - */ - char *proc_name; - -} Scsi_Host_Template; - -/* - * The scsi_hosts array is the array containing the data for all - * possible scsi hosts. This is similar to the - * Scsi_Host_Template, except that we have one entry for each - * actual physical host adapter on the system, stored as a linked - * list. Note that if there are 2 aha1542 boards, then there will - * be two Scsi_Host entries, but only 1 Scsi_Host_Template entry. - */ - -struct Scsi_Host -{ -/* private: */ - /* - * This information is private to the scsi mid-layer. Wrapping it in a - * struct private is a way of marking it in a sort of C++ type of way. - */ - struct Scsi_Host * next; - Scsi_Device * host_queue; - - - struct task_struct * ehandler; /* Error recovery thread. */ - struct semaphore * eh_wait; /* The error recovery thread waits on - this. */ - struct semaphore * eh_notify; /* wait for eh to begin */ - struct semaphore * eh_action; /* Wait for specific actions on the - host. */ - unsigned int eh_active:1; /* Indicates the eh thread is awake and active if - this is true. */ -#if 0 - wait_queue_head_t host_wait; -#endif - Scsi_Host_Template * hostt; - atomic_t host_active; /* commands checked out */ - volatile unsigned short host_busy; /* commands actually active on low-level */ - volatile unsigned short host_failed; /* commands that failed. */ - -/* public: */ - unsigned short extra_bytes; - unsigned short host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */ - int resetting; /* if set, it means that last_reset is a valid value */ - unsigned long last_reset; - - - /* - * These three parameters can be used to allow for wide scsi, - * and for host adapters that support multiple busses - * The first two should be set to 1 more than the actual max id - * or lun (i.e. 8 for normal systems). - */ - unsigned int max_id; - unsigned int max_lun; - unsigned int max_channel; - - /* These parameters should be set by the detect routine */ - unsigned long base; - unsigned long io_port; - unsigned char n_io_port; - unsigned char dma_channel; - unsigned int irq; - - /* - * This is a unique identifier that must be assigned so that we - * have some way of identifying each detected host adapter properly - * and uniquely. For hosts that do not support more than one card - * in the system at one time, this does not need to be set. It is - * initialized to 0 in scsi_register. - */ - unsigned int unique_id; - - /* - * The rest can be copied from the template, or specifically - * initialized, as required. - */ - - /* - * The maximum length of SCSI commands that this host can accept. - * Probably 12 for most host adapters, but could be 16 for others. - * For drivers that don't set this field, a value of 12 is - * assumed. I am leaving this as a number rather than a bit - * because you never know what subsequent SCSI standards might do - * (i.e. could there be a 20 byte or a 24-byte command a few years - * down the road?). - */ - unsigned char max_cmd_len; - - int this_id; - int can_queue; - short cmd_per_lun; - short unsigned int sg_tablesize; - short unsigned int max_sectors; - - unsigned in_recovery:1; - unsigned unchecked_isa_dma:1; - unsigned use_clustering:1; - /* - * True if this host was loaded as a loadable module - */ - unsigned loaded_as_module:1; - - /* - * Host has rejected a command because it was busy. - */ - unsigned host_blocked:1; - - /* - * Host has requested that no further requests come through for the - * time being. - */ - unsigned host_self_blocked:1; - - /* - * Host uses correct SCSI ordering not PC ordering. The bit is - * set for the minority of drivers whose authors actually read the spec ;) - */ - unsigned reverse_ordering:1; - - /* - * Indicates that one or more devices on this host were starved, and - * when the device becomes less busy that we need to feed them. - */ - unsigned some_device_starved:1; - - void (*select_queue_depths)(struct Scsi_Host *, Scsi_Device *); - - /* - * For SCSI hosts which are PCI devices, set pci_dev so that - * we can do BIOS EDD 3.0 mappings - */ - struct pci_dev *pci_dev; - - /* - * We should ensure that this is aligned, both for better performance - * and also because some compilers (m68k) don't automatically force - * alignment to a long boundary. - */ - unsigned long hostdata[0] /* Used for storage of host specific stuff */ - __attribute__ ((aligned (sizeof(unsigned long)))); -}; - -/* - * These two functions are used to allocate and free a pseudo device - * which will connect to the host adapter itself rather than any - * physical device. You must deallocate when you are done with the - * thing. This physical pseudo-device isn't real and won't be available - * from any high-level drivers. - */ -extern void scsi_free_host_dev(Scsi_Device * SDpnt); -extern Scsi_Device * scsi_get_host_dev(struct Scsi_Host * SHpnt); - -extern void scsi_unblock_requests(struct Scsi_Host * SHpnt); -extern void scsi_block_requests(struct Scsi_Host * SHpnt); -extern void scsi_report_bus_reset(struct Scsi_Host * SHpnt, int channel); - -typedef struct SHN - { - struct SHN * next; - char * name; - unsigned short host_no; - unsigned short host_registered; - unsigned loaded_as_module; - } Scsi_Host_Name; - -extern Scsi_Host_Name * scsi_host_no_list; -extern struct Scsi_Host * scsi_hostlist; -extern struct Scsi_Device_Template * scsi_devicelist; - -extern Scsi_Host_Template * scsi_hosts; - -extern void build_proc_dir_entries(Scsi_Host_Template *); - -/* - * scsi_init initializes the scsi hosts. - */ - -extern int next_scsi_host; - -unsigned int scsi_init(void); -extern struct Scsi_Host * scsi_register(Scsi_Host_Template *, int j); -extern void scsi_unregister(struct Scsi_Host * i); - -extern void scsi_register_blocked_host(struct Scsi_Host * SHpnt); -extern void scsi_deregister_blocked_host(struct Scsi_Host * SHpnt); - -static inline void scsi_set_pci_device(struct Scsi_Host *SHpnt, - struct pci_dev *pdev) -{ - SHpnt->pci_dev = pdev; -} - - -/* - * Prototypes for functions/data in scsi_scan.c - */ -extern void scan_scsis(struct Scsi_Host *shpnt, - uint hardcoded, - uint hchannel, - uint hid, - uint hlun); - -extern void scsi_mark_host_reset(struct Scsi_Host *Host); - -#define BLANK_HOST {"", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - -struct Scsi_Device_Template -{ - struct Scsi_Device_Template * next; - const char * name; - const char * tag; - struct module * module; /* Used for loadable modules */ - unsigned char scsi_type; - unsigned int major; - unsigned int min_major; /* Minimum major in range. */ - unsigned int max_major; /* Maximum major in range. */ - unsigned int nr_dev; /* Number currently attached */ - unsigned int dev_noticed; /* Number of devices detected. */ - unsigned int dev_max; /* Current size of arrays */ - unsigned blk:1; /* 0 if character device */ - int (*detect)(Scsi_Device *); /* Returns 1 if we can attach this device */ - int (*init)(void); /* Sizes arrays based upon number of devices - * detected */ - void (*finish)(void); /* Perform initialization after attachment */ - int (*attach)(Scsi_Device *); /* Attach devices to arrays */ - void (*detach)(Scsi_Device *); - int (*init_command)(Scsi_Cmnd *); /* Used by new queueing code. - Selects command for blkdevs */ -}; - -void scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt); - -int scsi_register_device(struct Scsi_Device_Template * sdpnt); -void scsi_deregister_device(struct Scsi_Device_Template * tpnt); - -#if 0 -/* These are used by loadable modules */ -extern int scsi_register_module(int, void *); -extern int scsi_unregister_module(int, void *); -#endif - -/* The different types of modules that we can load and unload */ -#define MODULE_SCSI_HA 1 -#define MODULE_SCSI_CONST 2 -#define MODULE_SCSI_IOCTL 3 -#define MODULE_SCSI_DEV 4 - - -/* - * This is an ugly hack. If we expect to be able to load devices at run time, - * we need to leave extra room in some of the data structures. Doing a - * realloc to enlarge the structures would be riddled with race conditions, - * so until a better solution is discovered, we use this crude approach - * - * Even bigger hack for SparcSTORAGE arrays. Those are at least 6 disks, but - * usually up to 30 disks, so everyone would need to change this. -jj - * - * Note: These things are all evil and all need to go away. My plan is to - * tackle the character devices first, as there aren't any locking implications - * in the block device layer. The block devices will require more work. - * - * The generics driver has been updated to resize as required. So as the tape - * driver. Two down, two more to go. - */ -#ifndef CONFIG_SD_EXTRA_DEVS -#define CONFIG_SD_EXTRA_DEVS 2 -#endif -#ifndef CONFIG_SR_EXTRA_DEVS -#define CONFIG_SR_EXTRA_DEVS 2 -#endif -#define SD_EXTRA_DEVS CONFIG_SD_EXTRA_DEVS -#define SR_EXTRA_DEVS CONFIG_SR_EXTRA_DEVS - -#endif -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/xen/drivers/scsi/megaraid.c b/xen/drivers/scsi/megaraid.c deleted file mode 100644 index 74a589f5b9..0000000000 --- a/xen/drivers/scsi/megaraid.c +++ /dev/null @@ -1,5544 +0,0 @@ -/*=================================================================== - * - * Linux MegaRAID device driver - * - * Copyright 2001 LSI Logic Corporation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Version : v1.18d (Aug 7, 2002) - * - * Description: Linux device driver for LSI Logic MegaRAID controller - * - * Supported controllers: MegaRAID 418, 428, 438, 466, 762, 467, 471, 490 - * 493. - * History: - * - * Version 0.90: - * Original source contributed by Dell; integrated it into the kernel and - * cleaned up some things. Added support for 438/466 controllers. - * Version 0.91: - * Aligned mailbox area on 16-byte boundary. - * Added schedule() at the end to properly clean up. - * Made improvements for conformity to linux driver standards. - * - * Version 0.92: - * Added support for 2.1 kernels. - * Reads from pci_dev struct, so it's not dependent on pcibios. - * Added some missing virt_to_bus() translations. - * Added support for SMP. - * Changed global cli()'s to spinlocks for 2.1, and simulated - * spinlocks for 2.0. - * Removed setting of SA_INTERRUPT flag when requesting Irq. - * - * Version 0.92ac: - * Small changes to the comments/formatting. Plus a couple of - * added notes. Returned to the authors. No actual code changes - * save printk levels. - * 8 Oct 98 Alan Cox - * - * Merged with 2.1.131 source tree. - * 12 Dec 98 K. Baranowski - * - * Version 0.93: - * Added support for vendor specific ioctl commands (M_RD_IOCTL_CMD+xxh) - * Changed some fields in MEGARAID struct to better values. - * Added signature check for Rp controllers under 2.0 kernels - * Changed busy-wait loop to be time-based - * Fixed SMP race condition in isr - * Added kfree (sgList) on release - * Added #include linux/version.h to megaraid.h for hosts.h - * Changed max_id to represent max logical drives instead of targets. - * - * Version 0.94: - * Got rid of some excess locking/unlocking - * Fixed slight memory corruption problem while memcpy'ing into mailbox - * Changed logical drives to be reported as luns rather than targets - * Changed max_id to 16 since it is now max targets/chan again. - * Improved ioctl interface for upcoming megamgr - * - * Version 0.95: - * Fixed problem of queueing multiple commands to adapter; - * still has some strange problems on some setups, so still - * defaults to single. To enable parallel commands change - * #define MULTI_IO in megaraid.h - * Changed kmalloc allocation to be done in beginning. - * Got rid of C++ style comments - * - * Version 0.96: - * 762 fully supported. - * - * Version 0.97: - * Changed megaraid_command to use wait_queue. - * - * Version 1.00: - * Checks to see if an irq occurred while in isr, and runs through - * routine again. - * Copies mailbox to temp area before processing in isr - * Added barrier() in busy wait to fix volatility bug - * Uses separate list for freed Scbs, keeps track of cmd state - * Put spinlocks around entire queue function for now... - * Full multi-io commands working stablely without previous problems - * Added skipXX LILO option for Madrona motherboard support - * - * Version 1.01: - * Fixed bug in mega_cmd_done() for megamgr control commands, - * the host_byte in the result code from the scsi request to - * scsi midlayer is set to DID_BAD_TARGET when adapter's - * returned codes are 0xF0 and 0xF4. - * - * Version 1.02: - * Fixed the tape drive bug by extending the adapter timeout value - * for passthrough command to 60 seconds in mega_build_cmd(). - * - * Version 1.03: - * Fixed Madrona support. - * Changed the adapter timeout value from 60 sec in 1.02 to 10 min - * for bigger and slower tape drive. - * Added driver version printout at driver loadup time - * - * Version 1.04 - * Added code for 40 ld FW support. - * Added new ioctl command 0x81 to support NEW_READ/WRITE_CONFIG with - * data area greater than 4 KB, which is the upper bound for data - * tranfer through scsi_ioctl interface. - * The additional 32 bit field for 64bit address in the newly defined - * mailbox64 structure is set to 0 at this point. - * - * Version 1.05 - * Changed the queing implementation for handling SCBs and completed - * commands. - * Added spinlocks in the interrupt service routine to enable the driver - * function in the SMP environment. - * Fixed the problem of unnecessary aborts in the abort entry point, which - * also enables the driver to handle large amount of I/O requests for - * long duration of time. - * Version 1.06 - * Intel Release - * Version 1.07 - * Removed the usage of uaccess.h file for kernel versions less than - * 2.0.36, as this file is not present in those versions. - * - * Version 108 - * Modified mega_ioctl so that 40LD megamanager would run - * Made some changes for 2.3.XX compilation , esp wait structures - * Code merge between 1.05 and 1.06 . - * Bug fixed problem with ioctl interface for concurrency between - * 8ld and 40ld firwmare - * Removed the flawed semaphore logic for handling new config command - * Added support for building own scatter / gather list for big user - * mode buffers - * Added /proc file system support ,so that information is available in - * human readable format - * - * Version 1a08 - * Changes for IA64 kernels. Checked for CONFIG_PROC_FS flag - * - * Version 1b08 - * Include file changes. - * Version 1b08b - * Change PCI ID value for the 471 card, use #defines when searching - * for megaraid cards. - * - * Version 1.10 - * - * I) Changes made to make following ioctl commands work in 0x81 interface - * a)DCMD_DELETE_LOGDRV - * b)DCMD_GET_DISK_CONFIG - * c)DCMD_DELETE_DRIVEGROUP - * d)NC_SUBOP_ENQUIRY3 - * e)DCMD_CHANGE_LDNO - * f)DCMD_CHANGE_LOOPID - * g)DCMD_FC_READ_NVRAM_CONFIG - * h)DCMD_WRITE_CONFIG - * II) Added mega_build_kernel_sg function - * III)Firmware flashing option added - * - * Version 1.10a - * - * I)Dell updates included in the source code. - * Note: This change is not tested due to the unavailability of IA64 kernel - * and it is in the #ifdef DELL_MODIFICATION macro which is not defined - * - * Version 1.10b - * - * I)In M_RD_IOCTL_CMD_NEW command the wrong way of copying the data - * to the user address corrected - * - * Version 1.10c - * - * I) DCMD_GET_DISK_CONFIG opcode updated for the firmware changes. - * - * Version 1.11 - * I) Version number changed from 1.10c to 1.11 - * II) DCMD_WRITE_CONFIG(0x0D) command in the driver changed from - * scatter/gather list mode to direct pointer mode.. - * Fixed bug of undesirably detecting HP onboard controllers which - * are disabled. - * - * Version 1.12 (Sep 21, 2000) - * - * I. Changes have been made for Dynamic DMA mapping in IA64 platform. - * To enable all these changes define M_RD_DYNAMIC_DMA_SUPPORT in megaraid.h - * II. Got rid of windows mode comments - * III. Removed unwanted code segments - * IV. Fixed bug of HP onboard controller information (commented with - * MEGA_HP_FIX) - * - * Version 1a12 - * I. reboot notifier and new ioctl changes ported from 1c09 - * - * Version 1b12 - * I. Changes in new ioctl interface routines ( Nov 06, 2000 ) - * - * Version 1c12 - * I. Changes in new ioctl interface routines ( Nov 07, 2000 ) - * - * Version 1d12 - * I. Compilation error under kernel 2.4.0 for 32-bit machine in mega_ioctl - * - * Version 1e12, 1f12 - * 1. Fixes for pci_map_single, pci_alloc_consistent along with mailbox - * alignment - * - * Version 1.13beta - * Added Support for Full 64bit address space support. If firmware - * supports 64bit, it goes to 64 bit mode even on x86 32bit - * systems. Data Corruption Issues while running on test9 kernel - * on IA64 systems. This issue not seen on test11 on x86 system - * - * Version 1.13c - * 1. Resolved Memory Leak when using M_RD_IOCTL_CMD interface - * 2. Resolved Queuing problem when MailBox Blocks - * 3. Added unregister_reboot_notifier support - * - * Version 1.13d - * Experimental changes in interfacing with the controller in ISR - * - * Version 1.13e - * Fixed Broken 2.2.XX compilation changes + misc changes - * - * Version 1.13f to 1.13i - * misc changes + code clean up - * Cleaned up the ioctl code and added set_mbox_xfer_addr() - * Support for START_DEV (6) - * - * Version 1.13j - * Moved some code to megaraid.h file, replaced some hard coded values - * with respective macros. Changed some functions to static - * - * Version 1.13k - * Only some idendation correction to 1.13j - * - * Version 1.13l , 1.13m, 1.13n, 1.13o - * Minor Identation changes + misc changes - * - * Version 1.13q - * Paded the new uioctl_t MIMD structure for maintaining alignment - * and size across 32 / 64 bit platforms - * Changed the way MIMD IOCTL interface used virt_to_bus() to use pci - * memory location - * - * Version 1.13r - * 2.4.xx SCSI Changes. - * - * Version 1.13s - * Stats counter fixes - * Temporary fix for some 64 bit firmwares in 2.4.XX kernels - * - * Version 1.13t - * Support for 64bit version of READ/WRITE/VIEW DISK CONFIG - * - * Version 1.14 - * Did away with MEGADEV_IOCTL flag. It is now standard part of driver - * without need for a special #define flag - * Disabled old scsi ioctl path for kernel versions > 2.3.xx. This is due - * to the nature in which the new scsi code queues a new scsi command to - * controller during SCSI IO Completion - * Driver now checks for sub-system vendor id before taking ownership of - * the controller - * - * Version 1.14a - * Added Host re-ordering - * - * Version 1.14b - * Corrected some issue which caused the older cards not to work - * - * Version 1.14c - * IOCTL changes for not handling the non-64bit firmwares under 2.4.XX - * kernel - * - * Version 1.14d - * Fixed Various MIMD Synchronization Issues - * - * Version 1.14e - * Fixed the error handling during card initialization - * - * Version 1.14f - * Multiple invocations of mimd phase I ioctl stalls the cpu. Replaced - * spinlock with semaphore(mutex) - * - * Version 1.14g - * Fixed running out of scbs issues while running MIMD apps under heavy IO - * - * Version 1.14g-ac - 02/03/01 - * Reformatted to Linux format so I could compare to old one and cross - * check bug fixes - * Re fixed the assorted missing 'static' cases - * Removed some unneeded version checks - * Cleaned up some of the VERSION checks in the code - * Left 2.0 support but removed 2.1.x support. - * Collected much of the compat glue into one spot - * - * Version 1.14g-ac2 - 22/03/01 - * Fixed a non obvious dereference after free in the driver unload path - * - * Version 1.14i - * changes for making 32bit application run on IA64 - * - * Version 1.14j - * Tue Mar 13 14:27:54 EST 2001 - AM - * Changes made in the driver to be able to run applications if the - * system has memory >4GB. - * - * - * Version 1.14k - * Thu Mar 15 18:38:11 EST 2001 - AM - * - * Firmware version check removed if subsysid==0x1111 and - * subsysvid==0x1111, since its not yet initialized. - * - * changes made to correctly calculate the base in mega_findCard. - * - * Driver informational messages now appear on the console as well as - * with dmesg - * - * Older ioctl interface is returned failure on newer(2.4.xx) kernels. - * - * Inclusion of "modversions.h" is still a debatable question. It is - * included anyway with this release. - * - * Version 1.14l - * Mon Mar 19 17:39:46 EST 2001 - AM - * - * Assorted changes to remove compilation error in 1.14k when compiled - * with kernel < 2.4.0 - * - * Version 1.14m - * Tue Mar 27 12:09:22 EST 2001 - AM - * - * Added support for extended CDBs ( > 10 bytes ) and OBDR ( One Button - * Disaster Recovery ) feature. - * - * - * Version 1.14n - * Tue Apr 10 14:28:13 EDT 2001 - AM - * - * "modeversions.h" is no longer included in the code. - * 2.4.xx style mutex initialization used for older kernels also - * - * Version 1.14o - * Wed Apr 18 17:47:26 EDT 2001 - PJ - * - * Before returning status for 'inquiry', we first check if request buffer - * is SG list, and then return appropriate status - * - * Version 1.14p - * Wed Apr 25 13:44:48 EDT 2001 - PJ - * - * SCSI result made appropriate in case of check conditions for extended - * passthru commands - * - * Do not support lun >7 for physically accessed devices - * - * - * Version 1.15 - * Thu Apr 19 09:38:38 EDT 2001 - AM - * - * 1.14l rollover to 1.15 - merged with main trunk after 1.15d - * - * Version 1.15b - * Wed May 16 20:10:01 EDT 2001 - AM - * - * "modeversions.h" is no longer included in the code. - * 2.4.xx style mutex initialization used for older kernels also - * Brought in-sync with Alan's changes in 2.4.4 - * Note: 1.15a is on OBDR branch(main trunk), and is not merged with yet. - * - * Version 1.15c - * Mon May 21 23:10:42 EDT 2001 - AM - * - * ioctl interface uses 2.4.x conforming pci dma calls - * similar calls used for older kernels - * - * Version 1.15d - * Wed May 30 17:30:41 EDT 2001 - AM - * - * NULL is not a valid first argument for pci_alloc_consistent() on - * IA64(2.4.3-2.10.1). Code shuffling done in ioctl interface to get - * "pci_dev" before making calls to pci interface routines. - * - * Version 1.16pre - * Fri Jun 1 19:40:48 EDT 2001 - AM - * - * 1.14p and 1.15d merged - * ROMB support added - * - * Version 1.16-pre1 - * Mon Jun 4 15:01:01 EDT 2001 - AM - * - * Non-ROMB firmware do no DMA support 0xA9 command. Value 0xFF - * (all channels are raid ) is chosen for those firmware. - * - * Version 1.16-pre2 - * Mon Jun 11 18:15:31 EDT 2001 - AM - * - * Changes for boot from any logical drive - * - * Version 1.16 - * Tue Jun 26 18:07:02 EDT 2001 - AM - * - * branched at 1.14p - * - * Check added for HP 1M/2M controllers if having firmware H.01.07 or - * H.01.08. If found, disable 64 bit support since these firmware have - * limitations for 64 bit addressing - * - * - * Version 1.17 - * Thu Jul 12 11:14:09 EDT 2001 - AM - * - * 1.16pre2 and 1.16 merged. - * - * init_MUTEX and init_MUTEX_LOCKED are defined in 2.2.19. Pre-processor - * statements are added for them - * - * Linus's 2.4.7pre3 kernel introduces a new field 'max_sectors' in Scsi_Host - * structure, to improve IO performance. - * - * - * Version 1.17a - * Fri Jul 13 18:44:01 EDT 2001 - AM - * - * Starting from kernel 2.4.x, LUN is not < 8 - following SCSI-III. So to have - * our current formula working to calculate logical drive number, return - * failure for LUN > 7 - * - * - * Version 1.17b - * Mon Jul 30 19:24:02 EDT 2001 - AM - * - * Added support for random deletion of logical drives - * - * Version 1.17c - * Tue Sep 25 09:37:49 EDT 2001 - Atul Mukker - * - * With single and dual channel controllers, some virtaul channels are - * displayed negative. - * - * Version 1.17a-ac - * Mon Aug 6 14:59:29 BST 2001 - "Michael Johnson" - * - * Make the HP print formatting and check for buggy firmware runtime not - * ifdef dependant. - * - * - * Version 1.17d - * Thu Oct 11 10:48:45 EDT 2001 - Atul Mukker - * - * Driver 1.17c oops when loaded without controller. - * - * Special case for "use_sg == 1" removed while building the scatter gather - * list. - * - * Version 1.18 - * Thu Oct 11 15:02:53 EDT 2001 - Atul Mukker - * - * References to AMI have been changed to LSI Logic. - * - * Version 1.18a - * Mon Mar 11 11:38:38 EST 2002 - Atul Mukker - * - * RAID On MotherBoard (ROMB) - boot from logical or physical drives - * - * Support added for discovery(ROMB) vendor and device ids. - * - * Data transfer length for passthru commands must be valid even if the - * command has an associated scatter-gather list. - * - * - * Version 1.18b - * Tue Apr 23 11:01:58 EDT 2002 - Atul Mukker - * - * typo corrected for scsi condition CHECK_CONDITION in mega_cmd_done() - * - * Support added for PCI_VENDOR_ID_LSI_LOGIC with device id - * PCI_DEVICE_ID_AMI_MEGARAID3. - * - * - * Version 1.18c - * Thu May 16 10:27:55 EDT 2002 - Atul Mukker - * - * Retrun valid return status for mega passthru commands resulting in - * contingent allegiance condition. Check for 64-bit passthru commands also. - * - * Do not check_region() anymore and check for return value of - * request_region() - * - * Send valid sense data to appliations using the private ioctl interface. - * - * - * Version 1.18d - * Wed Aug 7 18:51:51 EDT 2002 - Atul Mukker - * - * Added support for yellowstone and verde controller - * - * - * BUGS: - * Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that - * fails to detect the controller as a pci device on the system. - * - * Timeout period for upper scsi layer, i.e. SD_TIMEOUT in - * /drivers/scsi/sd.c, is too short for this controller. SD_TIMEOUT - * value must be increased to (30 * HZ) otherwise false timeouts - * will occur in the upper layer. - * - * Never set skip_id. The existing PCI code the megaraid uses fails - * to properly check the vendor subid in some cases. Setting this then - * makes it steal other i960's and crashes some boxes - * - * Far too many ifdefs for versions. - * - *===================================================================*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -#include -#include -//#include -#include -//#include -#include -#include -#include -//#include - -#include -#include -//#include -#include /* for kmalloc() */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) /* 0x20100 */ -#include -#else -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) /* 0x20300 */ -#include -#else -#include -#endif -#endif - -#include -#include - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,0,24) /* 0x020024 */ -#include -#endif - -/* - * These header files are required for Shutdown Notification routines - */ -#include -#include -#include - -#include "sd.h" -#include "scsi.h" -#include "hosts.h" - -#include "megaraid.h" - -/* - *================================================================ - * #Defines - *================================================================ - */ - -#define MAX_SERBUF 160 -#define COM_BASE 0x2f8 - -static ulong RDINDOOR (mega_host_config * megaCfg) -{ - return readl (megaCfg->base + 0x20); -} - -static void WRINDOOR (mega_host_config * megaCfg, ulong value) -{ - writel (value, megaCfg->base + 0x20); -} - -static ulong RDOUTDOOR (mega_host_config * megaCfg) -{ - return readl (megaCfg->base + 0x2C); -} - -static void WROUTDOOR (mega_host_config * megaCfg, ulong value) -{ - writel (value, megaCfg->base + 0x2C); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) /* 0x020200 */ -#include -#define cpuid smp_processor_id() -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4) -#define scsi_set_pci_device(x,y) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* 0x020400 */ - -/* - * Linux 2.4 and higher - * - * No driver private lock - * Use the io_request_lock not cli/sti - * queue task is a simple api without irq forms - */ - -MODULE_AUTHOR ("LSI Logic Corporation"); -MODULE_DESCRIPTION ("LSI Logic MegaRAID driver"); -MODULE_LICENSE ("GPL"); - -#define DRIVER_LOCK_T -#define DRIVER_LOCK_INIT(p) -#define DRIVER_LOCK(p) -#define DRIVER_UNLOCK(p) -#define IO_LOCK_T unsigned long io_flags = 0 -#define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags); -#define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags); - -#define queue_task_irq(a,b) queue_task(a,b) -#define queue_task_irq_off(a,b) queue_task(a,b) - -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) /* 0x020200 */ - -/* - * Linux 2.2 and higher - * - * No driver private lock - * Use the io_request_lock not cli/sti - * No pci region api - * queue_task is now a single simple API - */ - -static char kernel_version[] = UTS_RELEASE; -MODULE_AUTHOR ("LSI Logic Corporation"); -MODULE_DESCRIPTION ("LSI Logic MegaRAID driver"); - -#define DRIVER_LOCK_T -#define DRIVER_LOCK_INIT(p) -#define DRIVER_LOCK(p) -#define DRIVER_UNLOCK(p) -#define IO_LOCK_T unsigned long io_flags = 0 -#define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags); -#define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags); - -#define pci_free_consistent(a,b,c,d) -#define pci_unmap_single(a,b,c,d) -#define pci_enable_device(x) (0) -#define queue_task_irq(a,b) queue_task(a,b) -#define queue_task_irq_off(a,b) queue_task(a,b) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,19) /* 0x020219 */ -#define init_MUTEX_LOCKED(x) (*(x)=MUTEX_LOCKED) -#define init_MUTEX(x) (*(x)=MUTEX) -#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue *x = NULL -#endif - - -#else - -/* - * Linux 2.0 macros. Here we have to provide some of our own - * functionality. We also only work little endian 32bit. - * Again no pci_alloc/free api - * IO_LOCK/IO_LOCK_T were never used in 2.0 so now are empty - */ - -#define cpuid 0 -#define DRIVER_LOCK_T long cpu_flags; -#define DRIVER_LOCK_INIT(p) -#define DRIVER_LOCK(p) \ - save_flags(cpu_flags); \ - cli(); -#define DRIVER_UNLOCK(p) \ - restore_flags(cpu_flags); -#define IO_LOCK_T -#define IO_LOCK(p) -#define IO_UNLOCK(p) -#define le32_to_cpu(x) (x) -#define cpu_to_le32(x) (x) - -#define pci_free_consistent(a,b,c,d) -#define pci_unmap_single(a,b,c,d) - -#define init_MUTEX_LOCKED(x) (*(x)=MUTEX_LOCKED) -#define init_MUTEX(x) (*(x)=MUTEX) - -#define pci_enable_device(x) (0) - -/* - * 2.0 lacks spinlocks, iounmap/ioremap - */ - -#define ioremap vremap -#define iounmap vfree - - /* simulate spin locks */ -typedef struct { - volatile char lock; -} spinlock_t; - -#define spin_lock_init(x) { (x)->lock = 0;} -#define spin_lock_irqsave(x,flags) { while ((x)->lock) barrier();\ - (x)->lock=1; save_flags(flags);\ - cli();} -#define spin_unlock_irqrestore(x,flags) { (x)->lock=0; restore_flags(flags);} - -#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue *x = NULL - -#endif - - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* 0x020400 */ -#define dma_alloc_consistent pci_alloc_consistent -#define dma_free_consistent pci_free_consistent -#else -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,19) /* 0x020219 */ -typedef unsigned long dma_addr_t; -#endif -void *dma_alloc_consistent(void *, size_t, dma_addr_t *); -void dma_free_consistent(void *, size_t, void *, dma_addr_t); -int mega_get_order(int); -int pow_2(int); -#endif - -/* set SERDEBUG to 1 to enable serial debugging */ -#define SERDEBUG 0 -#if SERDEBUG -static void ser_init (void); -static void ser_puts (char *str); -static void ser_putc (char c); -static int ser_printk (const char *fmt, ...); -#endif - -#ifdef CONFIG_PROC_FS -#define COPY_BACK if (offset > megaCfg->procidx) { \ - *eof = TRUE; \ - megaCfg->procidx = 0; \ - megaCfg->procbuf[0] = 0; \ - return 0;} \ - if ((count + offset) > megaCfg->procidx) { \ - count = megaCfg->procidx - offset; \ - *eof = TRUE; } \ - memcpy(page, &megaCfg->procbuf[offset], count); \ - megaCfg->procidx = 0; \ - megaCfg->procbuf[0] = 0; -#endif - -/* - * ================================================================ - * Global variables - *================================================================ - */ - -/* Use "megaraid=skipXX" as LILO option to prohibit driver from scanning - XX scsi id on each channel. Used for Madrona motherboard, where SAF_TE - processor id cannot be scanned */ - -static char *megaraid; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0) /* 0x20100 */ -#ifdef MODULE -MODULE_PARM (megaraid, "s"); -#endif -#endif -static int skip_id = -1; -static int numCtlrs = 0; -static mega_host_config *megaCtlrs[FC_MAX_CHANNELS] = { 0 }; -#if XEN_KILLED -static struct proc_dir_entry *mega_proc_dir_entry; -#endif - -#if DEBUG -static u32 maxCmdTime = 0; -#endif - -static mega_scb *pLastScb = NULL; -#if XEN_KILLED -static struct notifier_block mega_notifier = { - megaraid_reboot_notify, - NULL, - 0 -}; -#endif - -/* For controller re-ordering */ -struct mega_hbas mega_hbas[MAX_CONTROLLERS]; - -/* - * The File Operations structure for the serial/ioctl interface of the driver - */ -/* For controller re-ordering */ -#if XEN_KILLED -static struct file_operations megadev_fops = { - ioctl:megadev_ioctl_entry, - open:megadev_open, - release:megadev_close, -}; -#endif -/* - * Array to structures for storing the information about the controllers. This - * information is sent to the user level applications, when they do an ioctl - * for this information. - */ -static struct mcontroller mcontroller[MAX_CONTROLLERS]; - -#if XEN_KILLED -/* The current driver version */ -static u32 driver_ver = 0x118C; - -/* major number used by the device for character interface */ -static int major; - -static struct semaphore mimd_ioctl_sem; -static struct semaphore mimd_entry_mtx; -#endif - -#if SERDEBUG -volatile static spinlock_t serial_lock; -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) /* 0x20300 */ -static struct proc_dir_entry proc_scsi_megaraid = { - PROC_SCSI_MEGARAID, 8, "megaraid", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; -#endif - -#ifdef CONFIG_PROC_FS -extern struct proc_dir_entry proc_root; -#endif - -#define IS_RAID_CH(this, ch) ( (this->mega_ch_class >> (ch)) & 0x01 ) - -#if SERDEBUG -static char strbuf[MAX_SERBUF + 1]; - -static void ser_init (void) -{ - unsigned port = COM_BASE; - - outb (0x80, port + 3); - outb (0, port + 1); - /* 9600 Baud, if 19200: outb(6,port) */ - outb (12, port); - outb (3, port + 3); - outb (0, port + 1); -} - -static void ser_puts (char *str) -{ - char *ptr; - - ser_init (); - for (ptr = str; *ptr; ++ptr) - ser_putc (*ptr); -} - -static void ser_putc (char c) -{ - unsigned port = COM_BASE; - - while ((inb (port + 5) & 0x20) == 0) ; - outb (c, port); - if (c == 0x0a) { - while ((inb (port + 5) & 0x20) == 0) ; - outb (0x0d, port); - } -} - -static int ser_printk (const char *fmt, ...) -{ - va_list args; - int i; - long flags; - - spin_lock_irqsave (&serial_lock, flags); - va_start (args, fmt); - i = vsprintf (strbuf, fmt, args); - ser_puts (strbuf); - va_end (args); - spin_unlock_irqrestore (&serial_lock, flags); - - return i; -} - -#define TRACE(a) { ser_printk a;} - -#else -#define TRACE(A) -#endif - -#define TRACE1(a) - -static void callDone (Scsi_Cmnd * SCpnt) -{ - if (SCpnt->result) { - TRACE (("*** %.08lx %.02x <%d.%d.%d> = %x\n", - SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, - SCpnt->target, SCpnt->lun, SCpnt->result)); - } - SCpnt->scsi_done (SCpnt); -} - -/*------------------------------------------------------------------------- - * - * Local functions - * - *-------------------------------------------------------------------------*/ - -/*======================= - * Free a SCB structure - *======================= - */ -static void mega_freeSCB (mega_host_config * megaCfg, mega_scb * pScb) -{ - - mega_scb *pScbtmp; - - if ((pScb == NULL) || (pScb->idx >= 0xFE)) { - return; - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - switch (pScb->dma_type) { - case M_RD_DMA_TYPE_NONE: - break; - case M_RD_PTHRU_WITH_BULK_DATA: - pci_unmap_single (megaCfg->dev, pScb->dma_h_bulkdata, - pScb->pthru->dataxferlen, - pScb->dma_direction); - break; - case M_RD_EPTHRU_WITH_BULK_DATA: - pci_unmap_single (megaCfg->dev, pScb->dma_h_bulkdata, - pScb->epthru->dataxferlen, - pScb->dma_direction); - break; - case M_RD_PTHRU_WITH_SGLIST: - { - int count; - for (count = 0; count < pScb->sglist_count; count++) { - pci_unmap_single (megaCfg->dev, - pScb->dma_h_sglist[count], - pScb->sgList[count].length, - pScb->dma_direction); - - } - break; - } - case M_RD_BULK_DATA_ONLY: - pci_unmap_single (megaCfg->dev, - pScb->dma_h_bulkdata, - pScb->iDataSize, pScb->dma_direction); - - break; - case M_RD_SGLIST_ONLY: - pci_unmap_sg (megaCfg->dev, - pScb->SCpnt->request_buffer, - pScb->SCpnt->use_sg, pScb->dma_direction); - break; - default: - break; - } -#endif - - /* Unlink from pending queue */ - if (pScb == megaCfg->qPendingH) { - - if (megaCfg->qPendingH == megaCfg->qPendingT) - megaCfg->qPendingH = megaCfg->qPendingT = NULL; - else - megaCfg->qPendingH = megaCfg->qPendingH->next; - - megaCfg->qPcnt--; - - } else { - for (pScbtmp = megaCfg->qPendingH; pScbtmp; - pScbtmp = pScbtmp->next) { - - if (pScbtmp->next == pScb) { - - pScbtmp->next = pScb->next; - - if (pScb == megaCfg->qPendingT) { - megaCfg->qPendingT = pScbtmp; - } - - megaCfg->qPcnt--; - break; - } - } - } - - /* Link back into free list */ - pScb->state = SCB_FREE; - pScb->SCpnt = NULL; - - if (megaCfg->qFreeH == (mega_scb *) NULL) { - megaCfg->qFreeH = megaCfg->qFreeT = pScb; - } else { - megaCfg->qFreeT->next = pScb; - megaCfg->qFreeT = pScb; - } - - megaCfg->qFreeT->next = NULL; - megaCfg->qFcnt++; - -} - -/*=========================== - * Allocate a SCB structure - *=========================== - */ -static mega_scb *mega_allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt) -{ - mega_scb *pScb; - - /* Unlink command from Free List */ - if ((pScb = megaCfg->qFreeH) != NULL) { - megaCfg->qFreeH = pScb->next; - megaCfg->qFcnt--; - - pScb->isrcount = jiffies; - pScb->next = NULL; - pScb->state = SCB_ACTIVE; - pScb->SCpnt = SCpnt; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pScb->dma_type = M_RD_DMA_TYPE_NONE; -#endif - - return pScb; - } - - printk (KERN_WARNING "Megaraid: Could not allocate free SCB!!!\n"); - - return NULL; -} - -/* Run through the list of completed requests and finish it */ -static void mega_rundoneq (mega_host_config * megaCfg) -{ - Scsi_Cmnd *SCpnt; - - while ((SCpnt = megaCfg->qCompletedH) != NULL) { - megaCfg->qCompletedH = (Scsi_Cmnd *) SCpnt->host_scribble; - megaCfg->qCcnt--; - - SCpnt->host_scribble = (unsigned char *) NULL; /* XC : sep 14 */ - /* Callback */ - callDone (SCpnt); - } - - megaCfg->qCompletedH = megaCfg->qCompletedT = NULL; -} - -/* - * Runs through the list of pending requests - * Assumes that mega_lock spin_lock has been acquired. - */ -static int mega_runpendq (mega_host_config * megaCfg) -{ - mega_scb *pScb; - int rc; - - /* Issue any pending commands to the card */ - for (pScb = megaCfg->qPendingH; pScb; pScb = pScb->next) { - if (pScb->state == SCB_ACTIVE) { - if ((rc = - megaIssueCmd (megaCfg, pScb->mboxData, pScb, 1)) == -1) - return rc; - } - } - return 0; -} - -/* Add command to the list of completed requests */ - -static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb, int status) -{ - int islogical; - Scsi_Cmnd *SCpnt; - mega_passthru *pthru; - mega_ext_passthru *epthru; - mega_mailbox *mbox; - struct scatterlist *sgList; - u8 c; - - if (pScb == NULL) { - TRACE (("NULL pScb in mega_cmd_done!")); - printk(KERN_CRIT "NULL pScb in mega_cmd_done!"); - } - - SCpnt = pScb->SCpnt; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pthru = pScb->pthru; - epthru = pScb->epthru; -#else - pthru = &pScb->pthru; - epthru = &pScb->epthru; -#endif - - mbox = (mega_mailbox *) & pScb->mboxData; - - if (SCpnt == NULL) { - TRACE (("NULL SCpnt in mega_cmd_done!")); - TRACE (("pScb->idx = ", pScb->idx)); - TRACE (("pScb->state = ", pScb->state)); - TRACE (("pScb->state = ", pScb->state)); - panic(KERN_ERR "megaraid:Problem...!\n"); - } - -#if 0 - islogical = ( (SCpnt->channel >= megaCfg->productInfo.SCSIChanPresent) && - (SCpnt->channel <= megaCfg->host->max_channel) ); -#endif -#if 0 - islogical = (SCpnt->channel == megaCfg->host->max_channel); -#endif - islogical = megaCfg->logdrv_chan[SCpnt->channel]; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - /* Special Case to handle PassThrough->XferAddrress > 4GB */ - switch (SCpnt->cmnd[0]) { - case INQUIRY: - case READ_CAPACITY: - memcpy (SCpnt->request_buffer, - pScb->bounce_buffer, SCpnt->request_bufflen); - break; - } -#endif - - mega_freeSCB (megaCfg, pScb); - - /* - * Do not return the presence of hard disk on the channel so, inquiry - * sent, and returned data==hard disk or removable hard disk and not - * logical, request should return failure! - PJ - */ -#if 0 - if (SCpnt->cmnd[0] == INQUIRY && ((((u_char *) SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) && !islogical) { - status = 0xF0; - } -#endif - if (SCpnt->cmnd[0] == INQUIRY && !islogical) { - if ( SCpnt->use_sg ) { - sgList = (struct scatterlist *)SCpnt->request_buffer; - memcpy(&c, sgList[0].address, 0x1); - } else { - memcpy(&c, SCpnt->request_buffer, 0x1); - } -#if 0 - if( (c & 0x1F ) == TYPE_DISK ) { - status = 0xF0; - } -#endif - if(IS_RAID_CH(megaCfg, SCpnt->channel) && ((c & 0x1F) == TYPE_DISK)) { - status = 0xF0; - } - } - - - /* clear result; otherwise, success returns corrupt value */ - SCpnt->result = 0; - - if ( 0 && SCpnt->cmnd[0] & M_RD_IOCTL_CMD ) { /* i.e. ioctl cmd such as M_RD_IOCTL_CMD, M_RD_IOCTL_CMD_NEW of megamgr */ - switch (status) { - case 2: - case 0xF0: - case 0xF4: - SCpnt->result = (DID_BAD_TARGET << 16) | status; - break; - default: - SCpnt->result |= status; - } /*end of switch */ - } else { - /* Convert MegaRAID status to Linux error code */ - switch (status) { - case 0x00: /* SUCCESS , i.e. SCSI_STATUS_GOOD */ - SCpnt->result |= (DID_OK << 16); - break; - - case 0x02: /* ERROR_ABORTED, i.e. SCSI_STATUS_CHECK_CONDITION */ - - /*set sense_buffer and result fields */ - if (mbox->cmd == MEGA_MBOXCMD_PASSTHRU || mbox->cmd == - MEGA_MBOXCMD_PASSTHRU64 ) { - - memcpy (SCpnt->sense_buffer, pthru->reqsensearea, 14); - - SCpnt->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | - (CHECK_CONDITION << 1); - - } else if (mbox->cmd == MEGA_MBOXCMD_EXTPASSTHRU) { - - memcpy( SCpnt->sense_buffer, epthru->reqsensearea, 14); - - SCpnt->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | - (CHECK_CONDITION << 1); - - } else { - SCpnt->sense_buffer[0] = 0x70; - SCpnt->sense_buffer[2] = ABORTED_COMMAND; - SCpnt->result |= (CHECK_CONDITION << 1); - } - break; - - case 0x08: /* ERR_DEST_DRIVE_FAILED, i.e. SCSI_STATUS_BUSY */ - SCpnt->result |= (DID_BUS_BUSY << 16) | status; - break; - - default: - SCpnt->result |= (DID_BAD_TARGET << 16) | status; - break; - } - } - - /* Add Scsi_Command to end of completed queue */ - if (megaCfg->qCompletedH == NULL) { - megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt; - } else { - megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt; - megaCfg->qCompletedT = SCpnt; - } - - megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL; - megaCfg->qCcnt++; -} - -/*------------------------------------------------------------------- - * - * Build a SCB from a Scsi_Cmnd - * - * Returns a SCB pointer, or NULL - * If NULL is returned, the scsi_done function MUST have been called - * - *-------------------------------------------------------------------*/ - -static mega_scb *mega_build_cmd (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt) -{ - mega_scb *pScb; - mega_mailbox *mbox; - mega_passthru *pthru; - mega_ext_passthru *epthru; - long seg; - char islogical; - int max_ldrv_num; - int channel = 0; - int target = 0; - int ldrv_num = 0; /* logical drive number */ - - if ((SCpnt->cmnd[0] == MEGADEVIOC)) - return megadev_doioctl (megaCfg, SCpnt); - - if ((SCpnt->cmnd[0] == M_RD_IOCTL_CMD) - || (SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW)) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - return mega_ioctl (megaCfg, SCpnt); /* Handle IOCTL command */ -#else - { - printk(KERN_WARNING "megaraid ioctl: older interface - " - "not supported.\n"); - return NULL; - } -#endif - -#if 0 - islogical = ( (SCpnt->channel >= megaCfg->productInfo.SCSIChanPresent) && - (SCpnt->channel <= megaCfg->host->max_channel) ); -#endif -#if 0 - islogical = (IS_RAID_CH(SCpnt->channel) && /* virtual ch is raid - AM */ - (SCpnt->channel == megaCfg->host->max_channel)); -#endif - - /* - * We know on what channels are our logical drives - mega_findCard() - */ - islogical = megaCfg->logdrv_chan[SCpnt->channel]; - - /* - * The theory: If physical drive is chosen for boot, all the physical - * devices are exported before the logical drives, otherwise physical - * devices are pushed after logical drives, in which case - Kernel sees - * the physical devices on virtual channel which is obviously converted - * to actual channel on the HBA. - */ - if( megaCfg->boot_pdrv_enabled ) { - if( islogical ) { - /* logical channel */ - channel = SCpnt->channel - megaCfg->productInfo.SCSIChanPresent; - } - else { - channel = SCpnt->channel; /* this is physical channel */ - target = SCpnt->target; - - /* - * boot from a physical disk, that disk needs to be exposed first - * IF both the channels are SCSI, then booting from the second - * channel is not allowed. - */ - if( target == 0 ) { - target = megaCfg->boot_pdrv_tgt; - } - else if( target == megaCfg->boot_pdrv_tgt ) { - target = 0; - } - } - } - else { - if( islogical ) { - channel = SCpnt->channel; /* this is the logical channel */ - } - else { - channel = SCpnt->channel - NVIRT_CHAN; /* physical channel */ - target = SCpnt->target; - } - } - - if ( ! megaCfg->support_ext_cdb ) { - if (!islogical && SCpnt->lun != 0) { - SCpnt->result = (DID_BAD_TARGET << 16); - callDone (SCpnt); - return NULL; - } - } - - if (!islogical && SCpnt->target == skip_id) { - SCpnt->result = (DID_BAD_TARGET << 16); - callDone (SCpnt); - return NULL; - } - - if (islogical) { - - /* have just LUN 0 for each target on virtual channels */ - if( SCpnt->lun != 0 ) { - SCpnt->result = (DID_BAD_TARGET << 16); - callDone (SCpnt); - return NULL; - } - - ldrv_num = mega_get_ldrv_num(megaCfg, SCpnt, channel); - - max_ldrv_num = (megaCfg->flag & BOARD_40LD) ? - FC_MAX_LOGICAL_DRIVES : MAX_LOGICAL_DRIVES; - - /* - * max_ldrv_num increases by 0x80 if some logical drive was deleted. - */ - if(megaCfg->read_ldidmap) { - max_ldrv_num += 0x80; - } - - if( ldrv_num > max_ldrv_num ) { - SCpnt->result = (DID_BAD_TARGET << 16); - callDone (SCpnt); - return NULL; - } - - } else { - if ( SCpnt->lun > 7) { - /* Do not support lun >7 for physically accessed devices */ - SCpnt->result = (DID_BAD_TARGET << 16); - callDone (SCpnt); - return NULL; - } - } - /*----------------------------------------------------- - * - * Logical drive commands - * - *-----------------------------------------------------*/ - if (islogical) { - switch (SCpnt->cmnd[0]) { - case TEST_UNIT_READY: - memset (SCpnt->request_buffer, 0, SCpnt->request_bufflen); - SCpnt->result = (DID_OK << 16); - callDone (SCpnt); - return NULL; - - case MODE_SENSE: - memset (SCpnt->request_buffer, 0, SCpnt->cmnd[4]); - SCpnt->result = (DID_OK << 16); - callDone (SCpnt); - return NULL; - - case READ_CAPACITY: - case INQUIRY: - if(!(megaCfg->flag & (1L << SCpnt->channel))) { - printk(KERN_NOTICE - "scsi%d: scanning virtual channel %d for logical drives.\n", - megaCfg->host->host_no, channel); - - megaCfg->flag |= (1L << SCpnt->channel); - } - - /* Allocate a SCB and initialize passthru */ - if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) { - SCpnt->result = (DID_ERROR << 16); - callDone (SCpnt); - return NULL; - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pthru = pScb->pthru; -#else - pthru = &pScb->pthru; -#endif - - mbox = (mega_mailbox *) & pScb->mboxData; - memset (mbox, 0, sizeof (pScb->mboxData)); - memset (pthru, 0, sizeof (mega_passthru)); - pthru->timeout = 0; - pthru->ars = 1; - pthru->reqsenselen = 14; - pthru->islogical = 1; - pthru->logdrv = ldrv_num; - pthru->cdblen = SCpnt->cmd_len; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - /*Not sure about the direction */ - pScb->dma_direction = PCI_DMA_BIDIRECTIONAL; - pScb->dma_type = M_RD_PTHRU_WITH_BULK_DATA; - -#if 0 -/* Normal Code w/o the need for bounce buffer */ - pScb->dma_h_bulkdata - = pci_map_single (megaCfg->dev, - SCpnt->request_buffer, - SCpnt->request_bufflen, - pScb->dma_direction); - - pthru->dataxferaddr = pScb->dma_h_bulkdata; -#else -/* Special Code to use bounce buffer for READ_CAPA/INQ */ - pthru->dataxferaddr = pScb->dma_bounce_buffer; - pScb->dma_type = M_RD_DMA_TYPE_NONE; -#endif - -#else - pthru->dataxferaddr = - virt_to_bus (SCpnt->request_buffer); -#endif - - pthru->dataxferlen = SCpnt->request_bufflen; - memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len); - - /* Initialize mailbox area */ - mbox->cmd = MEGA_MBOXCMD_PASSTHRU; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - mbox->xferaddr = pScb->dma_passthruhandle64; - TRACE1 (("M_RD_PTHRU_WITH_BULK_DATA Enabled \n")); -#else - mbox->xferaddr = virt_to_bus (pthru); -#endif - return pScb; - - case READ_6: - case WRITE_6: - case READ_10: - case WRITE_10: - /* Allocate a SCB and initialize mailbox */ - if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) { - SCpnt->result = (DID_ERROR << 16); - callDone (SCpnt); - return NULL; - } - mbox = (mega_mailbox *) & pScb->mboxData; - - memset (mbox, 0, sizeof (pScb->mboxData)); - mbox->logdrv = ldrv_num; - - if (megaCfg->flag & BOARD_64BIT) { - mbox->cmd = (*SCpnt->cmnd == READ_6 - || *SCpnt->cmnd == - READ_10) ? MEGA_MBOXCMD_LREAD64 : - MEGA_MBOXCMD_LWRITE64; - } else { - mbox->cmd = (*SCpnt->cmnd == READ_6 - || *SCpnt->cmnd == - READ_10) ? MEGA_MBOXCMD_LREAD : - MEGA_MBOXCMD_LWRITE; - } - - /* 6-byte */ - if (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == WRITE_6) { - mbox->numsectors = (u32) SCpnt->cmnd[4]; - mbox->lba = - ((u32) SCpnt->cmnd[1] << 16) | - ((u32) SCpnt->cmnd[2] << 8) | - (u32) SCpnt->cmnd[3]; - mbox->lba &= 0x1FFFFF; - - if (*SCpnt->cmnd == READ_6) { - megaCfg->nReads[(int)ldrv_num]++; - megaCfg->nReadBlocks[(int)ldrv_num] += - mbox->numsectors; - } else { - megaCfg->nWrites[(int)ldrv_num]++; - megaCfg->nWriteBlocks[(int)ldrv_num] += - mbox->numsectors; - } - } - - /* 10-byte */ - if (*SCpnt->cmnd == READ_10 || *SCpnt->cmnd == WRITE_10) { - mbox->numsectors = - (u32) SCpnt->cmnd[8] | - ((u32) SCpnt->cmnd[7] << 8); - mbox->lba = - ((u32) SCpnt->cmnd[2] << 24) | - ((u32) SCpnt->cmnd[3] << 16) | - ((u32) SCpnt->cmnd[4] << 8) | - (u32) SCpnt->cmnd[5]; - - if (*SCpnt->cmnd == READ_10) { - megaCfg->nReads[(int)ldrv_num]++; - megaCfg->nReadBlocks[(int)ldrv_num] += - mbox->numsectors; - } else { - megaCfg->nWrites[(int)ldrv_num]++; - megaCfg->nWriteBlocks[(int)ldrv_num] += - mbox->numsectors; - } - } - - /* 12-byte */ - if (*SCpnt->cmnd == READ_12 || *SCpnt->cmnd == WRITE_12) { - mbox->lba = - ((u32) SCpnt->cmnd[2] << 24) | - ((u32) SCpnt->cmnd[3] << 16) | - ((u32) SCpnt->cmnd[4] << 8) | - (u32) SCpnt->cmnd[5]; - - mbox->numsectors = - ((u32) SCpnt->cmnd[6] << 24) | - ((u32) SCpnt->cmnd[7] << 16) | - ((u32) SCpnt->cmnd[8] << 8) | - (u32) SCpnt->cmnd[9]; - - if (*SCpnt->cmnd == READ_12) { - megaCfg->nReads[(int)ldrv_num]++; - megaCfg->nReadBlocks[(int)ldrv_num] += - mbox->numsectors; - } else { - megaCfg->nWrites[(int)ldrv_num]++; - megaCfg->nWriteBlocks[(int)ldrv_num] += - mbox->numsectors; - } - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - if (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10 - || *SCpnt->cmnd == READ_12) { - pScb->dma_direction = PCI_DMA_FROMDEVICE; - } else { /*WRITE_6 or WRITE_10 */ - pScb->dma_direction = PCI_DMA_TODEVICE; - } -#endif - - /* Calculate Scatter-Gather info */ - mbox->numsgelements = mega_build_sglist (megaCfg, pScb, - (u32 *)&mbox->xferaddr, (u32 *)&seg); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pScb->iDataSize = seg; - - if (mbox->numsgelements) { - pScb->dma_type = M_RD_SGLIST_ONLY; - TRACE1 (("M_RD_SGLIST_ONLY Enabled \n")); - } else { - pScb->dma_type = M_RD_BULK_DATA_ONLY; - TRACE1 (("M_RD_BULK_DATA_ONLY Enabled \n")); - } -#endif - - return pScb; - default: - SCpnt->result = (DID_BAD_TARGET << 16); - callDone (SCpnt); - return NULL; - } - } - /*----------------------------------------------------- - * - * Passthru drive commands - * - *-----------------------------------------------------*/ - else { - /* Allocate a SCB and initialize passthru */ - if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) { - SCpnt->result = (DID_ERROR << 16); - callDone (SCpnt); - return NULL; - } - - mbox = (mega_mailbox *) pScb->mboxData; - memset (mbox, 0, sizeof (pScb->mboxData)); - - if ( megaCfg->support_ext_cdb && SCpnt->cmd_len > 10 ) { - epthru = mega_prepare_extpassthru(megaCfg, pScb, SCpnt, channel, - target); - mbox->cmd = MEGA_MBOXCMD_EXTPASSTHRU; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - mbox->xferaddr = pScb->dma_ext_passthruhandle64; - - if(epthru->numsgelements) { - pScb->dma_type = M_RD_PTHRU_WITH_SGLIST; - } else { - pScb->dma_type = M_RD_EPTHRU_WITH_BULK_DATA; - } -#else - mbox->xferaddr = virt_to_bus(epthru); -#endif - } - else { - pthru = mega_prepare_passthru(megaCfg, pScb, SCpnt, channel, - target); - - /* Initialize mailbox */ - mbox->cmd = MEGA_MBOXCMD_PASSTHRU; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - mbox->xferaddr = pScb->dma_passthruhandle64; - - if (pthru->numsgelements) { - pScb->dma_type = M_RD_PTHRU_WITH_SGLIST; - } else { - pScb->dma_type = M_RD_PTHRU_WITH_BULK_DATA; - } -#else - mbox->xferaddr = virt_to_bus(pthru); -#endif - } - return pScb; - } - return NULL; -} - -static int -mega_get_ldrv_num(mega_host_config *this_hba, Scsi_Cmnd *sc, int channel) -{ - int tgt; - int ldrv_num; - - tgt = sc->target; - - if ( tgt > 7 ) tgt--; /* we do not get inquires for tgt 7 */ - - ldrv_num = (channel * 15) + tgt; /* 14 targets per channel */ - - /* - * If we have a logical drive with boot enabled, project it first - */ - if( this_hba->boot_ldrv_enabled ) { - if( ldrv_num == 0 ) { - ldrv_num = this_hba->boot_ldrv; - } - else { - if( ldrv_num <= this_hba->boot_ldrv ) { - ldrv_num--; - } - } - } - - /* - * If "delete logical drive" feature is enabled on this controller. - * Do only if at least one delete logical drive operation was done. - * - * Also, after logical drive deletion, instead of logical drive number, - * the value returned should be 0x80+logical drive id. - * - * These is valid only for IO commands. - */ - - if( this_hba->support_random_del && this_hba->read_ldidmap ) { - switch(sc->cmnd[0]) { - case READ_6: /* fall through */ - case WRITE_6: /* fall through */ - case READ_10: /* fall through */ - case WRITE_10: - ldrv_num += 0x80; - } - } - - return ldrv_num; -} - - -static mega_passthru * -mega_prepare_passthru(mega_host_config *megacfg, mega_scb *scb, Scsi_Cmnd *sc, - int channel, int target) -{ - mega_passthru *pthru; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pthru = scb->pthru; -#else - pthru = &scb->pthru; -#endif - memset (pthru, 0, sizeof (mega_passthru)); - - /* set adapter timeout value to 10 min. for tape drive */ - /* 0=6sec/1=60sec/2=10min/3=3hrs */ - pthru->timeout = 2; - pthru->ars = 1; - pthru->reqsenselen = 14; - pthru->islogical = 0; - pthru->channel = (megacfg->flag & BOARD_40LD) ? 0 : channel; - pthru->target = (megacfg->flag & BOARD_40LD) ? - (channel << 4) | target : target; - pthru->cdblen = sc->cmd_len; - pthru->logdrv = sc->lun; - - memcpy (pthru->cdb, sc->cmnd, sc->cmd_len); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - /* Not sure about the direction */ - scb->dma_direction = PCI_DMA_BIDIRECTIONAL; - - /* Special Code for Handling READ_CAPA/ INQ using bounce buffers */ - switch (sc->cmnd[0]) { - case INQUIRY: - case READ_CAPACITY: - - if(!(megacfg->flag & (1L << sc->channel))) { - printk(KERN_NOTICE - "scsi%d: scanning physical channel %d for devices.\n", - megacfg->host->host_no, channel); - - megacfg->flag |= (1L << sc->channel); - } - - pthru->numsgelements = 0; - pthru->dataxferaddr = scb->dma_bounce_buffer; - pthru->dataxferlen = sc->request_bufflen; - break; - default: - pthru->numsgelements = - mega_build_sglist( - megacfg, scb, (u32 *)&pthru->dataxferaddr, - (u32 *)&pthru->dataxferlen - ); - break; - } -#else - pthru->numsgelements = - mega_build_sglist( - megacfg, scb, (u32 *)&pthru->dataxferaddr, - (u32 *)&pthru->dataxferlen - ); -#endif - return pthru; -} - -static mega_ext_passthru * -mega_prepare_extpassthru(mega_host_config *megacfg, mega_scb *scb, - Scsi_Cmnd *sc, int channel, int target) -{ - mega_ext_passthru *epthru; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - epthru = scb->epthru; -#else - epthru = &scb->epthru; -#endif - memset(epthru, 0, sizeof(mega_ext_passthru)); - - /* set adapter timeout value to 10 min. for tape drive */ - /* 0=6sec/1=60sec/2=10min/3=3hrs */ - epthru->timeout = 2; - epthru->ars = 1; - epthru->reqsenselen = 14; - epthru->islogical = 0; - epthru->channel = (megacfg->flag & BOARD_40LD) ? 0 : channel; - epthru->target = (megacfg->flag & BOARD_40LD) ? - (channel << 4) | target : target; - epthru->cdblen = sc->cmd_len; - epthru->logdrv = sc->lun; - - memcpy(epthru->cdb, sc->cmnd, sc->cmd_len); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - /* Not sure about the direction */ - scb->dma_direction = PCI_DMA_BIDIRECTIONAL; - - /* Special Code for Handling READ_CAPA/ INQ using bounce buffers */ - switch (sc->cmnd[0]) { - case INQUIRY: - case READ_CAPACITY: - if(!(megacfg->flag & (1L << sc->channel))) { - printk(KERN_NOTICE - "scsi%d: scanning physical channel %d for devices.\n", - megacfg->host->host_no, channel); - - megacfg->flag |= (1L << sc->channel); - } - - epthru->numsgelements = 0; - epthru->dataxferaddr = scb->dma_bounce_buffer; - epthru->dataxferlen = sc->request_bufflen; - break; - default: - epthru->numsgelements = - mega_build_sglist( - megacfg, scb, (u32 *)&epthru->dataxferaddr, - (u32 *)&epthru->dataxferlen - ); - break; - } -#else - epthru->numsgelements = - mega_build_sglist( - megacfg, scb, (u32 *)&epthru->dataxferaddr, - (u32 *)&epthru->dataxferlen - ); -#endif - return epthru; -} - -/* Handle Driver Level IOCTLs - * Return value of 0 indicates this function could not handle , so continue - * processing -*/ - -static int mega_driver_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt) -{ - unsigned char *data = (unsigned char *) SCpnt->request_buffer; - mega_driver_info driver_info; - - /* If this is not our command dont do anything */ - if (SCpnt->cmnd[0] != M_RD_DRIVER_IOCTL_INTERFACE) - return 0; - - switch (SCpnt->cmnd[1]) { - case GET_DRIVER_INFO: - if (SCpnt->request_bufflen < sizeof (driver_info)) { - SCpnt->result = DID_BAD_TARGET << 16; - callDone (SCpnt); - return 1; - } - - driver_info.size = sizeof (driver_info) - sizeof (int); - driver_info.version = MEGARAID_IOCTL_VERSION; - memcpy (data, &driver_info, sizeof (driver_info)); - break; - default: - SCpnt->result = DID_BAD_TARGET << 16; - } - - callDone (SCpnt); - return 1; -} - -static void inline set_mbox_xfer_addr (mega_host_config * megaCfg, mega_scb * pScb, - mega_ioctl_mbox * mbox, u32 direction) -{ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - switch (direction) { - case TO_DEVICE: - pScb->dma_direction = PCI_DMA_TODEVICE; - break; - case FROM_DEVICE: - pScb->dma_direction = PCI_DMA_FROMDEVICE; - break; - case FROMTO_DEVICE: - pScb->dma_direction = PCI_DMA_BIDIRECTIONAL; - break; - } - - pScb->dma_h_bulkdata - = pci_map_single (megaCfg->dev, - pScb->buff_ptr, - pScb->iDataSize, pScb->dma_direction); - mbox->xferaddr = pScb->dma_h_bulkdata; - pScb->dma_type = M_RD_BULK_DATA_ONLY; - TRACE1 (("M_RD_BULK_DATA_ONLY Enabled \n")); -#else - mbox->xferaddr = virt_to_bus (pScb->buff_ptr); -#endif -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - -/*-------------------------------------------------------------------- - * build RAID commands for controller, passed down through ioctl() - *--------------------------------------------------------------------*/ -static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt) -{ - mega_scb *pScb; - mega_ioctl_mbox *mbox; - mega_mailbox *mailbox; - mega_passthru *pthru; - u8 *mboxdata; - long seg, i = 0; - unsigned char *data = (unsigned char *) SCpnt->request_buffer; - - if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) { - SCpnt->result = (DID_ERROR << 16); - callDone (SCpnt); - return NULL; - } - pthru = &pScb->pthru; - - mboxdata = (u8 *) & pScb->mboxData; - mbox = (mega_ioctl_mbox *) & pScb->mboxData; - mailbox = (mega_mailbox *) & pScb->mboxData; - memset (mailbox, 0, sizeof (pScb->mboxData)); - - if (data[0] == 0x03) { /* passthrough command */ - unsigned char cdblen = data[2]; - memset (pthru, 0, sizeof (mega_passthru)); - pthru->islogical = (data[cdblen + 3] & 0x80) ? 1 : 0; - pthru->timeout = data[cdblen + 3] & 0x07; - pthru->reqsenselen = 14; - pthru->ars = (data[cdblen + 3] & 0x08) ? 1 : 0; - pthru->logdrv = data[cdblen + 4]; - pthru->channel = data[cdblen + 5]; - pthru->target = data[cdblen + 6]; - pthru->cdblen = cdblen; - memcpy (pthru->cdb, &data[3], cdblen); - - mailbox->cmd = MEGA_MBOXCMD_PASSTHRU; - - - pthru->numsgelements = mega_build_sglist (megaCfg, pScb, - (u32 *) & pthru-> - dataxferaddr, - (u32 *) & pthru-> - dataxferlen); - - mailbox->xferaddr = virt_to_bus (pthru); - - for (i = 0; i < (SCpnt->request_bufflen - cdblen - 7); i++) { - data[i] = data[i + cdblen + 7]; - } - return pScb; - } - /* else normal (nonpassthru) command */ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,0,24) /*0x020024 */ - /* - *usage of the function copy from user is used in case of data more than - *4KB.This is used only with adapters which supports more than 8 logical - * drives.This feature is disabled on kernels earlier or same as 2.0.36 - * as the uaccess.h file is not available with those kernels. - */ - - if (SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) { - /* use external data area for large xfers */ - /* If cmnd[0] is set to M_RD_IOCTL_CMD_NEW then * - * cmnd[4..7] = external user buffer * - * cmnd[8..11] = length of buffer * - * */ - char *user_area = (char *)*((u32*)&SCpnt->cmnd[4]); - u32 xfer_size = *((u32 *) & SCpnt->cmnd[8]); - switch (data[0]) { - case FW_FIRE_WRITE: - case FW_FIRE_FLASH: - if ((ulong) user_area & (PAGE_SIZE - 1)) { - printk - ("megaraid:user address not aligned on 4K boundary.Error.\n"); - SCpnt->result = (DID_ERROR << 16); - callDone (SCpnt); - return NULL; - } - break; - default: - break; - } - - if (!(pScb->buff_ptr = kmalloc (xfer_size, GFP_KERNEL))) { - printk - ("megaraid: Insufficient mem for M_RD_IOCTL_CMD_NEW.\n"); - SCpnt->result = (DID_ERROR << 16); - callDone (SCpnt); - return NULL; - } - - copy_from_user (pScb->buff_ptr, user_area, xfer_size); - pScb->iDataSize = xfer_size; - - switch (data[0]) { - case DCMD_FC_CMD: - switch (data[1]) { - case DCMD_FC_READ_NVRAM_CONFIG: - case DCMD_GET_DISK_CONFIG: - { - if ((ulong) pScb-> - buff_ptr & (PAGE_SIZE - 1)) { - printk - ("megaraid:user address not sufficient Error.\n"); - SCpnt->result = - (DID_ERROR << 16); - callDone (SCpnt); - return NULL; - } - - /*building SG list */ - mega_build_kernel_sg (pScb->buff_ptr, - xfer_size, - pScb, mbox); - break; - } - default: - break; - } /*switch (data[1]) */ - break; - } - - } -#endif - - mbox->cmd = data[0]; - mbox->channel = data[1]; - mbox->param = data[2]; - mbox->pad[0] = data[3]; - mbox->logdrv = data[4]; - - if (SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) { - switch (data[0]) { - case FW_FIRE_WRITE: - mbox->cmd = FW_FIRE_WRITE; - mbox->channel = data[1]; /* Current Block Number */ - set_mbox_xfer_addr (megaCfg, pScb, mbox, TO_DEVICE); - mbox->numsgelements = 0; - break; - case FW_FIRE_FLASH: - mbox->cmd = FW_FIRE_FLASH; - mbox->channel = data[1] | 0x80; /* Origin */ - set_mbox_xfer_addr (megaCfg, pScb, mbox, TO_DEVICE); - mbox->numsgelements = 0; - break; - case DCMD_FC_CMD: - *(mboxdata + 0) = data[0]; /*mailbox byte 0: DCMD_FC_CMD */ - *(mboxdata + 2) = data[1]; /*sub command */ - switch (data[1]) { - case DCMD_FC_READ_NVRAM_CONFIG: - case DCMD_FC_READ_NVRAM_CONFIG_64: - /* number of elements in SG list */ - *(mboxdata + 3) = mbox->numsgelements; - if (megaCfg->flag & BOARD_64BIT) - *(mboxdata + 2) = - DCMD_FC_READ_NVRAM_CONFIG_64; - break; - case DCMD_WRITE_CONFIG: - case DCMD_WRITE_CONFIG_64: - if (megaCfg->flag & BOARD_64BIT) - *(mboxdata + 2) = DCMD_WRITE_CONFIG_64; - set_mbox_xfer_addr (megaCfg, pScb, mbox, - TO_DEVICE); - mbox->numsgelements = 0; - break; - case DCMD_GET_DISK_CONFIG: - case DCMD_GET_DISK_CONFIG_64: - if (megaCfg->flag & BOARD_64BIT) - *(mboxdata + 2) = - DCMD_GET_DISK_CONFIG_64; - *(mboxdata + 3) = data[2]; /*number of elements in SG list */ - /*nr of elements in SG list */ - *(mboxdata + 4) = mbox->numsgelements; - break; - case DCMD_DELETE_LOGDRV: - case DCMD_DELETE_DRIVEGROUP: - case NC_SUBOP_ENQUIRY3: - *(mboxdata + 3) = data[2]; - set_mbox_xfer_addr (megaCfg, pScb, mbox, - FROMTO_DEVICE); - mbox->numsgelements = 0; - break; - case DCMD_CHANGE_LDNO: - case DCMD_CHANGE_LOOPID: - *(mboxdata + 3) = data[2]; - *(mboxdata + 4) = data[3]; - set_mbox_xfer_addr (megaCfg, pScb, mbox, - TO_DEVICE); - mbox->numsgelements = 0; - break; - default: - set_mbox_xfer_addr (megaCfg, pScb, mbox, - FROMTO_DEVICE); - mbox->numsgelements = 0; - break; - } /*switch */ - break; - default: - set_mbox_xfer_addr (megaCfg, pScb, mbox, FROMTO_DEVICE); - mbox->numsgelements = 0; - break; - } - } else { - - mbox->numsgelements = mega_build_sglist (megaCfg, pScb, - (u32 *) & mbox-> - xferaddr, - (u32 *) & seg); - - /* Handling some of the fw special commands */ - switch (data[0]) { - case 6: /* START_DEV */ - mbox->xferaddr = *((u32 *) & data[i + 6]); - break; - default: - break; - } - - for (i = 0; i < (SCpnt->request_bufflen - 6); i++) { - data[i] = data[i + 6]; - } - } - - return (pScb); -} - - -static void mega_build_kernel_sg (char *barea, ulong xfersize, mega_scb * pScb, mega_ioctl_mbox * mbox) -{ - ulong i, buffer_area, len, end, end_page, x, idx = 0; - - buffer_area = (ulong) barea; - i = buffer_area; - end = buffer_area + xfersize; - end_page = (end) & ~(PAGE_SIZE - 1); - - do { - len = PAGE_SIZE - (i % PAGE_SIZE); - x = pScb->sgList[idx].address = - virt_to_bus ((volatile void *) i); - pScb->sgList[idx].length = len; - i += len; - idx++; - } while (i < end_page); - - if ((end - i) < 0) { - printk ("megaraid:Error in user address\n"); - } - - if (end - i) { - pScb->sgList[idx].address = virt_to_bus ((volatile void *) i); - pScb->sgList[idx].length = end - i; - idx++; - } - mbox->xferaddr = virt_to_bus (pScb->sgList); - mbox->numsgelements = idx; -} -#endif - - -#if DEBUG -static unsigned int cum_time = 0; -static unsigned int cum_time_cnt = 0; - -static void showMbox (mega_scb * pScb) -{ - mega_mailbox *mbox; - - if (pScb == NULL) - return; - - mbox = (mega_mailbox *) pScb->mboxData; - printk ("%u cmd:%x id:%x #scts:%x lba:%x addr:%x logdrv:%x #sg:%x\n", - pScb->SCpnt->pid, - mbox->cmd, mbox->cmdid, mbox->numsectors, - mbox->lba, mbox->xferaddr, mbox->logdrv, mbox->numsgelements); -} - -#endif - -/*-------------------------------------------------------------------- - * Interrupt service routine - *--------------------------------------------------------------------*/ -static void megaraid_isr (int irq, void *devp, struct pt_regs *regs) -{ - IO_LOCK_T; - mega_host_config * megaCfg; - u_char byte, idx, sIdx, tmpBox[MAILBOX_SIZE]; - u32 dword = 0; - mega_mailbox *mbox; - mega_scb *pScb; - u_char qCnt, qStatus; - u_char completed[MAX_FIRMWARE_STATUS]; - Scsi_Cmnd *SCpnt; - - megaCfg = (mega_host_config *) devp; - mbox = (mega_mailbox *) tmpBox; - - if (megaCfg->host->irq == irq) { - if (megaCfg->flag & IN_ISR) { - TRACE (("ISR called reentrantly!!\n")); - printk ("ISR called reentrantly!!\n"); - } - megaCfg->flag |= IN_ISR; - - if (mega_busyWaitMbox (megaCfg)) { - printk (KERN_WARNING "Error: mailbox busy in isr!\n"); - } - - /* Check if a valid interrupt is pending */ - if (megaCfg->flag & BOARD_QUARTZ) { - dword = RDOUTDOOR (megaCfg); - if (dword != 0x10001234) { - /* Spurious interrupt */ - megaCfg->flag &= ~IN_ISR; - return; - } - } else { - byte = READ_PORT (megaCfg->host->io_port, INTR_PORT); - if ((byte & VALID_INTR_BYTE) == 0) { - /* Spurious interrupt */ - megaCfg->flag &= ~IN_ISR; - return; - } - WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte); - } - - for (idx = 0; idx < MAX_FIRMWARE_STATUS; idx++) - completed[idx] = 0; - - IO_LOCK; - - megaCfg->nInterrupts++; - qCnt = 0xff; - while ((qCnt = megaCfg->mbox->numstatus) == 0xFF) ; - - qStatus = 0xff; - while ((qStatus = megaCfg->mbox->status) == 0xFF) ; - - /* Get list of completed requests */ - for (idx = 0; idx < qCnt; idx++) { - while ((sIdx = megaCfg->mbox->completed[idx]) == 0xFF) { - printk ("p"); - } - completed[idx] = sIdx; - sIdx = 0xFF; - } - - if (megaCfg->flag & BOARD_QUARTZ) { - WROUTDOOR (megaCfg, dword); - /* Acknowledge interrupt */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - /* In this case mbox contains physical address */ -#if 0 - WRINDOOR (megaCfg, megaCfg->adjdmahandle64 | 0x2); -#else - WRINDOOR (megaCfg, 0x2); -#endif - -#else - -#if 0 - WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2); -#else - WRINDOOR (megaCfg, 0x2); -#endif - -#endif - -#if 0 - while (RDINDOOR (megaCfg) & 0x02) ; -#endif - } else { - CLEAR_INTR (megaCfg->host->io_port); - } - -#if DEBUG - if (qCnt >= MAX_FIRMWARE_STATUS) { - printk ("megaraid_isr: cmplt=%d ", qCnt); - } -#endif - - for (idx = 0; idx < qCnt; idx++) { - sIdx = completed[idx]; - if ((sIdx > 0) && (sIdx <= MAX_COMMANDS)) { - pScb = &megaCfg->scbList[sIdx - 1]; - - /* ASSERT(pScb->state == SCB_ISSUED); */ - -#if DEBUG - if (((jiffies) - pScb->isrcount) > maxCmdTime) { - maxCmdTime = (jiffies) - pScb->isrcount; - printk - ("megaraid_isr : cmd time = %u\n", - maxCmdTime); - } -#endif - /* - * Assuming that the scsi command, for which - * an abort request was received earlier, has - * completed. - */ - if (pScb->state == SCB_ABORTED) { - SCpnt = pScb->SCpnt; - } - if (pScb->state == SCB_RESET) { - SCpnt = pScb->SCpnt; - mega_freeSCB (megaCfg, pScb); - SCpnt->result = (DID_RESET << 16); - if (megaCfg->qCompletedH == NULL) { - megaCfg->qCompletedH = - megaCfg->qCompletedT = - SCpnt; - } else { - megaCfg->qCompletedT-> - host_scribble = - (unsigned char *) SCpnt; - megaCfg->qCompletedT = SCpnt; - } - megaCfg->qCompletedT->host_scribble = - (unsigned char *) NULL; - megaCfg->qCcnt++; - continue; - } - - /* We don't want the ISR routine to touch M_RD_IOCTL_CMD_NEW commands, so - * don't mark them as complete, instead we pop their semaphore so - * that the queue routine can finish them off - */ - if (pScb->SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) { - /* save the status byte for the queue routine to use */ - pScb->SCpnt->result = qStatus; -#if XEN_KILLED - up (&pScb->ioctl_sem); -#endif - } else { - /* Mark command as completed */ - mega_cmd_done (megaCfg, pScb, qStatus); - } - } else { - printk - ("megaraid: wrong cmd id completed from firmware:id=%x\n", - sIdx); - } - } - - mega_rundoneq (megaCfg); - - megaCfg->flag &= ~IN_ISR; - /* Loop through any pending requests */ - mega_runpendq (megaCfg); - IO_UNLOCK; - - } - -} - -/*==================================================*/ -/* Wait until the controller's mailbox is available */ -/*==================================================*/ - -static int mega_busyWaitMbox (mega_host_config * megaCfg) -{ - mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox; - long counter; - - for (counter = 0; counter < 10000; counter++) { - if (!mbox->busy) { - return 0; - } - udelay (100); - barrier (); - } - return -1; /* give up after 1 second */ -} - -/*===================================================== - * Post a command to the card - * - * Arguments: - * mega_host_config *megaCfg - Controller structure - * u_char *mboxData - Mailbox area, 16 bytes - * mega_scb *pScb - SCB posting (or NULL if N/A) - * int intr - if 1, interrupt, 0 is blocking - * Return Value: (added on 7/26 for 40ld/64bit) - * -1: the command was not actually issued out - * other cases: - * intr==0, return ScsiStatus, i.e. mbox->status - * intr==1, return 0 - *===================================================== - */ -static int megaIssueCmd (mega_host_config * megaCfg, u_char * mboxData, - mega_scb * pScb, int intr) -{ - volatile mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - volatile mega_mailbox64 *mbox64 = (mega_mailbox64 *) megaCfg->mbox64; -#endif - - u_char byte; - -#ifdef __LP64__ - u64 phys_mbox; -#else - u32 phys_mbox; -#endif - u8 retval = -1; - - mboxData[0x1] = (pScb ? pScb->idx + 1 : 0xFE); /* Set cmdid */ - mboxData[0xF] = 1; /* Set busy */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - /* In this case mbox contains physical address */ - phys_mbox = megaCfg->adjdmahandle64; -#else - phys_mbox = virt_to_bus (megaCfg->mbox); -#endif - -#if DEBUG - ShowMbox (pScb); -#endif - - /* Wait until mailbox is free */ - if (mega_busyWaitMbox (megaCfg)) { - printk ("Blocked mailbox......!!\n"); - udelay (1000); - -#if DEBUG - showMbox (pLastScb); -#endif - - /* Abort command */ - if (pScb == NULL) { - TRACE (("NULL pScb in megaIssue\n")); - printk ("NULL pScb in megaIssue\n"); - } - mega_cmd_done (megaCfg, pScb, 0x08); - return -1; - } - - pLastScb = pScb; - - /* Copy mailbox data into host structure */ - megaCfg->mbox64->xferSegment_lo = 0; - megaCfg->mbox64->xferSegment_hi = 0; - - memcpy ((char *) mbox, mboxData, 16); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - switch (mboxData[0]) { - case MEGA_MBOXCMD_LREAD64: - case MEGA_MBOXCMD_LWRITE64: - mbox64->xferSegment_lo = mbox->xferaddr; - mbox64->xferSegment_hi = 0; - mbox->xferaddr = 0xFFFFFFFF; - break; - } -#endif - - /* Kick IO */ - if (intr) { - /* Issue interrupt (non-blocking) command */ - if (megaCfg->flag & BOARD_QUARTZ) { - mbox->mraid_poll = 0; - mbox->mraid_ack = 0; - - WRINDOOR (megaCfg, phys_mbox | 0x1); - } else { - ENABLE_INTR (megaCfg->host->io_port); - ISSUE_COMMAND (megaCfg->host->io_port); - } - pScb->state = SCB_ISSUED; - - retval = 0; - } else { /* Issue non-ISR (blocking) command */ - disable_irq (megaCfg->host->irq); - if (megaCfg->flag & BOARD_QUARTZ) { - mbox->mraid_poll = 0; - mbox->mraid_ack = 0; - mbox->numstatus = 0xFF; - mbox->status = 0xFF; - WRINDOOR (megaCfg, phys_mbox | 0x1); - - while (mbox->numstatus == 0xFF) ; - while (mbox->status == 0xFF) ; - while (mbox->mraid_poll != 0x77) ; - mbox->mraid_poll = 0; - mbox->mraid_ack = 0x77; - - /* while ((cmdDone = RDOUTDOOR (megaCfg)) != 0x10001234); - WROUTDOOR (megaCfg, cmdDone); */ - - if (pScb) { - mega_cmd_done (megaCfg, pScb, mbox->status); - } - - WRINDOOR (megaCfg, phys_mbox | 0x2); - while (RDINDOOR (megaCfg) & 0x2) ; - - } else { - DISABLE_INTR (megaCfg->host->io_port); - ISSUE_COMMAND (megaCfg->host->io_port); - - while (! - ((byte = - READ_PORT (megaCfg->host->io_port, - INTR_PORT)) & INTR_VALID)) ; - WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte); - - ENABLE_INTR (megaCfg->host->io_port); - CLEAR_INTR (megaCfg->host->io_port); - - if (pScb) { - mega_cmd_done (megaCfg, pScb, mbox->status); - } else { - TRACE (("Error: NULL pScb!\n")); - } - } - enable_irq (megaCfg->host->irq); - retval = mbox->status; - } -#if DEBUG - while (mega_busyWaitMbox (megaCfg)) { - printk(KERN_ERR "Blocked mailbox on exit......!\n"); - udelay (1000); - } -#endif - - return retval; -} - -/*------------------------------------------------------------------- - * Copies data to SGLIST - *-------------------------------------------------------------------*/ -/* Note: - For 64 bit cards, we need a minimum of one SG element for read/write -*/ - -static int -mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb, - u32 * buffer, u32 * length) -{ - struct scatterlist *sgList; - int idx; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - int sgcnt; -#endif - - mega_mailbox *mbox = NULL; - - mbox = (mega_mailbox *) scb->mboxData; - /* Scatter-gather not used */ - if (scb->SCpnt->use_sg == 0) { - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - scb->dma_h_bulkdata = pci_map_single (megaCfg->dev, - scb->SCpnt->request_buffer, - scb->SCpnt->request_bufflen, - scb->dma_direction); - /* We need to handle special commands like READ64, WRITE64 - as they need a minimum of 1 SG irrespective of actually SG - */ - if ((megaCfg->flag & BOARD_64BIT) && - ((mbox->cmd == MEGA_MBOXCMD_LREAD64) || - (mbox->cmd == MEGA_MBOXCMD_LWRITE64))) { - scb->sg64List[0].address = scb->dma_h_bulkdata; - scb->sg64List[0].length = scb->SCpnt->request_bufflen; - *buffer = scb->dma_sghandle64; - *length = (u32)scb->SCpnt->request_bufflen; - scb->sglist_count = 1; - return 1; - } else { - *buffer = scb->dma_h_bulkdata; - *length = (u32) scb->SCpnt->request_bufflen; - } -#else - *buffer = virt_to_bus (scb->SCpnt->request_buffer); - *length = (u32) scb->SCpnt->request_bufflen; -#endif - return 0; - } - - sgList = (struct scatterlist *) scb->SCpnt->request_buffer; -#if 0 - if (scb->SCpnt->use_sg == 1) { - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - scb->dma_h_bulkdata = pci_map_single (megaCfg->dev, - sgList[0].address, - sgList[0].length, scb->dma_direction); - - if ((megaCfg->flag & BOARD_64BIT) && - ((mbox->cmd == MEGA_MBOXCMD_LREAD64) || - (mbox->cmd == MEGA_MBOXCMD_LWRITE64))) { - scb->sg64List[0].address = scb->dma_h_bulkdata; - scb->sg64List[0].length = scb->SCpnt->request_bufflen; - *buffer = scb->dma_sghandle64; - *length = 0; - scb->sglist_count = 1; - return 1; - } else { - *buffer = scb->dma_h_bulkdata; - *length = (u32) sgList[0].length; - } -#else - *buffer = virt_to_bus (sgList[0].address); - *length = (u32) sgList[0].length; -#endif - - return 0; - } -#endif - /* Copy Scatter-Gather list info into controller structure */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - sgcnt = pci_map_sg (megaCfg->dev, - sgList, scb->SCpnt->use_sg, scb->dma_direction); - - /* Determine the validity of the new count */ - if (sgcnt == 0) - printk ("pci_map_sg returned zero!!! "); - - for (idx = 0; idx < sgcnt; idx++, sgList++) { - - if ((megaCfg->flag & BOARD_64BIT) && - ((mbox->cmd == MEGA_MBOXCMD_LREAD64) || - (mbox->cmd == MEGA_MBOXCMD_LWRITE64))) { - scb->sg64List[idx].address = sg_dma_address (sgList); - scb->sg64List[idx].length = sg_dma_len (sgList); - } else { - scb->sgList[idx].address = sg_dma_address (sgList); - scb->sgList[idx].length = sg_dma_len (sgList); - } - - } - -#else - for (idx = 0; idx < scb->SCpnt->use_sg; idx++) { - scb->sgList[idx].address = virt_to_bus (sgList[idx].address); - scb->sgList[idx].length = (u32) sgList[idx].length; - } -#endif - - /* Reset pointer and length fields */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - *buffer = scb->dma_sghandle64; - scb->sglist_count = scb->SCpnt->use_sg; -#else - *buffer = virt_to_bus (scb->sgList); -#endif - -#if 0 - *length = 0; -#endif - /* - * For passthru command, dataxferlen must be set, even for commands with a - * sg list - */ - *length = (u32)scb->SCpnt->request_bufflen; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - /* Return count of SG requests */ - return sgcnt; -#else - /* Return count of SG requests */ - return scb->SCpnt->use_sg; -#endif -} - -/*-------------------------------------------------------------------- - * Initializes the address of the controller's mailbox register - * The mailbox register is used to issue commands to the card. - * Format of the mailbox area: - * 00 01 command - * 01 01 command id - * 02 02 # of sectors - * 04 04 logical bus address - * 08 04 physical buffer address - * 0C 01 logical drive # - * 0D 01 length of scatter/gather list - * 0E 01 reserved - * 0F 01 mailbox busy - * 10 01 numstatus byte - * 11 01 status byte - *--------------------------------------------------------------------*/ -static int -mega_register_mailbox (mega_host_config * megaCfg, u32 paddr) -{ - /* align on 16-byte boundary */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - megaCfg->mbox = &megaCfg->mailbox64ptr->mailbox; -#else - megaCfg->mbox = &megaCfg->mailbox64.mailbox; -#endif - -#ifdef __LP64__ - megaCfg->mbox = (mega_mailbox *) ((((u64) megaCfg->mbox) + 16) & ((u64) (-1) ^ 0x0F)); - megaCfg->adjdmahandle64 = (megaCfg->dma_handle64 + 16) & ((u64) (-1) ^ 0x0F); - megaCfg->mbox64 = (mega_mailbox64 *) ((u_char *) megaCfg->mbox - sizeof (u64)); - paddr = (paddr + 4 + 16) & ((u64) (-1) ^ 0x0F); -#else - megaCfg->mbox - = (mega_mailbox *) ((((u32) megaCfg->mbox) + 16) & 0xFFFFFFF0); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - megaCfg->adjdmahandle64 = ((megaCfg->dma_handle64 + 16) & 0xFFFFFFF0); -#endif - - megaCfg->mbox64 = (mega_mailbox64 *) ((u_char *) megaCfg->mbox - 8); - paddr = (paddr + 4 + 16) & 0xFFFFFFF0; -#endif - - /* Register mailbox area with the firmware */ - if (!(megaCfg->flag & BOARD_QUARTZ)) { - WRITE_PORT (megaCfg->host->io_port, MBOX_PORT0, paddr & 0xFF); - WRITE_PORT (megaCfg->host->io_port, MBOX_PORT1, - (paddr >> 8) & 0xFF); - WRITE_PORT (megaCfg->host->io_port, MBOX_PORT2, - (paddr >> 16) & 0xFF); - WRITE_PORT (megaCfg->host->io_port, MBOX_PORT3, - (paddr >> 24) & 0xFF); - WRITE_PORT (megaCfg->host->io_port, ENABLE_MBOX_REGION, - ENABLE_MBOX_BYTE); - - CLEAR_INTR (megaCfg->host->io_port); - ENABLE_INTR (megaCfg->host->io_port); - } - return 0; -} - -/*--------------------------------------------------------------------------- - * mega_Convert8ldTo40ld() -- takes all info in AdapterInquiry structure and - * puts it into ProductInfo and Enquiry3 structures for later use - *---------------------------------------------------------------------------*/ -static void mega_Convert8ldTo40ld (mega_RAIDINQ * inquiry, - mega_Enquiry3 * enquiry3, - megaRaidProductInfo * productInfo) -{ - int i; - - productInfo->MaxConcCmds = inquiry->AdpInfo.MaxConcCmds; - enquiry3->rbldRate = inquiry->AdpInfo.RbldRate; - productInfo->SCSIChanPresent = inquiry->AdpInfo.ChanPresent; - - for (i = 0; i < 4; i++) { - productInfo->FwVer[i] = inquiry->AdpInfo.FwVer[i]; - productInfo->BiosVer[i] = inquiry->AdpInfo.BiosVer[i]; - } - enquiry3->cacheFlushInterval = inquiry->AdpInfo.CacheFlushInterval; - productInfo->DramSize = inquiry->AdpInfo.DramSize; - - enquiry3->numLDrv = inquiry->LogdrvInfo.NumLDrv; - - for (i = 0; i < MAX_LOGICAL_DRIVES; i++) { - enquiry3->lDrvSize[i] = inquiry->LogdrvInfo.LDrvSize[i]; - enquiry3->lDrvProp[i] = inquiry->LogdrvInfo.LDrvProp[i]; - enquiry3->lDrvState[i] - = inquiry->LogdrvInfo.LDrvState[i]; - } - - for (i = 0; i < (MAX_PHYSICAL_DRIVES); i++) { - enquiry3->pDrvState[i] - = inquiry->PhysdrvInfo.PDrvState[i]; - } -} - -/*------------------------------------------------------------------- - * Issue an adapter info query to the controller - *-------------------------------------------------------------------*/ -static int mega_i_query_adapter (mega_host_config * megaCfg) -{ - mega_Enquiry3 *enquiry3Pnt; - mega_mailbox *mbox; - u_char mboxData[16]; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - dma_addr_t raid_inq_dma_handle = 0, prod_info_dma_handle = 0, enquiry3_dma_handle = 0; -#endif - u8 retval; - - /* Initialize adapter inquiry mailbox */ - - mbox = (mega_mailbox *) mboxData; - - memset ((void *) megaCfg->mega_buffer, 0, - sizeof (megaCfg->mega_buffer)); - memset (mbox, 0, 16); - -/* - * Try to issue Enquiry3 command - * if not succeeded, then issue MEGA_MBOXCMD_ADAPTERINQ command and - * update enquiry3 structure - */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - enquiry3_dma_handle = pci_map_single (megaCfg->dev, - (void *) megaCfg->mega_buffer, - (2 * 1024L), PCI_DMA_FROMDEVICE); - - mbox->xferaddr = enquiry3_dma_handle; -#else - /*Taken care */ - mbox->xferaddr = virt_to_bus ((void *) megaCfg->mega_buffer); -#endif - - /* Initialize mailbox databuffer addr */ - enquiry3Pnt = (mega_Enquiry3 *) megaCfg->mega_buffer; - /* point mega_Enguiry3 to the data buf */ - - mboxData[0] = FC_NEW_CONFIG; /* i.e. mbox->cmd=0xA1 */ - mboxData[2] = NC_SUBOP_ENQUIRY3; /* i.e. 0x0F */ - mboxData[3] = ENQ3_GET_SOLICITED_FULL; /* i.e. 0x02 */ - - /* Issue a blocking command to the card */ - if ((retval = megaIssueCmd (megaCfg, mboxData, NULL, 0)) != 0) { /* the adapter does not support 40ld */ - mega_RAIDINQ adapterInquiryData; - mega_RAIDINQ *adapterInquiryPnt = &adapterInquiryData; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - raid_inq_dma_handle = pci_map_single (megaCfg->dev, - (void *) adapterInquiryPnt, - sizeof (mega_RAIDINQ), - PCI_DMA_FROMDEVICE); - mbox->xferaddr = raid_inq_dma_handle; -#else - /*taken care */ - mbox->xferaddr = virt_to_bus ((void *) adapterInquiryPnt); -#endif - - mbox->cmd = MEGA_MBOXCMD_ADAPTERINQ; /*issue old 0x05 command to adapter */ - /* Issue a blocking command to the card */ ; - retval = megaIssueCmd (megaCfg, mboxData, NULL, 0); - - pci_unmap_single (megaCfg->dev, - raid_inq_dma_handle, - sizeof (mega_RAIDINQ), PCI_DMA_FROMDEVICE); - - /*update Enquiry3 and ProductInfo structures with mega_RAIDINQ structure*/ - mega_Convert8ldTo40ld (adapterInquiryPnt, - enquiry3Pnt, - (megaRaidProductInfo *) & megaCfg-> - productInfo); - - } else { /* adapter supports 40ld */ - megaCfg->flag |= BOARD_40LD; - - pci_unmap_single (megaCfg->dev, - enquiry3_dma_handle, - (2 * 1024L), PCI_DMA_FROMDEVICE); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -/*get productInfo, which is static information and will be unchanged*/ - prod_info_dma_handle - = pci_map_single (megaCfg->dev, - (void *) &megaCfg->productInfo, - sizeof (megaRaidProductInfo), - PCI_DMA_FROMDEVICE); - mbox->xferaddr = prod_info_dma_handle; -#else - /*taken care */ - mbox->xferaddr = virt_to_bus ((void *) &megaCfg->productInfo); -#endif - - mboxData[0] = FC_NEW_CONFIG; /* i.e. mbox->cmd=0xA1 */ - mboxData[2] = NC_SUBOP_PRODUCT_INFO; /* i.e. 0x0E */ - - if ((retval = megaIssueCmd (megaCfg, mboxData, NULL, 0)) != 0) - printk ("megaraid: Product_info cmd failed with error: %d\n", - retval); - - pci_unmap_single (megaCfg->dev, - prod_info_dma_handle, - sizeof (megaRaidProductInfo), - PCI_DMA_FROMDEVICE); - } - - /* - * kernel scans the channels from 0 to <= max_channel - */ - megaCfg->host->max_channel = - megaCfg->productInfo.SCSIChanPresent + NVIRT_CHAN -1; - - megaCfg->host->max_id = 16; /* max targets per channel */ - - megaCfg->host->max_lun = 7; /* Upto 7 luns for non disk devices */ - - megaCfg->host->cmd_per_lun = MAX_CMD_PER_LUN; - - megaCfg->numldrv = enquiry3Pnt->numLDrv; - megaCfg->max_cmds = megaCfg->productInfo.MaxConcCmds; - if (megaCfg->max_cmds > MAX_COMMANDS) - megaCfg->max_cmds = MAX_COMMANDS - 1; - - megaCfg->host->can_queue = megaCfg->max_cmds - 1; - - /* use HP firmware and bios version encoding */ - if (megaCfg->productInfo.subSystemVendorID == HP_SUBSYS_ID) { - sprintf (megaCfg->fwVer, "%c%d%d.%d%d", - megaCfg->productInfo.FwVer[2], - megaCfg->productInfo.FwVer[1] >> 8, - megaCfg->productInfo.FwVer[1] & 0x0f, - megaCfg->productInfo.FwVer[0] >> 8, - megaCfg->productInfo.FwVer[0] & 0x0f); - sprintf (megaCfg->biosVer, "%c%d%d.%d%d", - megaCfg->productInfo.BiosVer[2], - megaCfg->productInfo.BiosVer[1] >> 8, - megaCfg->productInfo.BiosVer[1] & 0x0f, - megaCfg->productInfo.BiosVer[0] >> 8, - megaCfg->productInfo.BiosVer[0] & 0x0f); - } else { - memcpy (megaCfg->fwVer, (char *) megaCfg->productInfo.FwVer, 4); - megaCfg->fwVer[4] = 0; - - memcpy (megaCfg->biosVer, (char *) megaCfg->productInfo.BiosVer, 4); - megaCfg->biosVer[4] = 0; - } - megaCfg->support_ext_cdb = mega_support_ext_cdb(megaCfg); - - printk (KERN_NOTICE "megaraid: [%s:%s] detected %d logical drives" M_RD_CRLFSTR, - megaCfg->fwVer, megaCfg->biosVer, megaCfg->numldrv); - - if ( megaCfg->support_ext_cdb ) { - printk(KERN_NOTICE "megaraid: supports extended CDBs.\n"); - } - - /* - * I hope that I can unmap here, reason DMA transaction is not required any more - * after this - */ - - return 0; -} - -/*------------------------------------------------------------------------- - * - * Driver interface functions - * - *-------------------------------------------------------------------------*/ - -/*---------------------------------------------------------- - * Returns data to be displayed in /proc/scsi/megaraid/X - *----------------------------------------------------------*/ -#if XEN_KILLED -int megaraid_proc_info (char *buffer, char **start, off_t offset, - int length, int host_no, int inout) -{ - *start = buffer; - return 0; -} -#endif - -static int mega_findCard (Scsi_Host_Template * pHostTmpl, - u16 pciVendor, u16 pciDev, long flag) -{ - mega_host_config *megaCfg = NULL; - struct Scsi_Host *host = NULL; - u_char pciBus, pciDevFun, megaIrq; - - u16 magic; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - u32 magic64; -#endif - - int i, j; - -#ifdef __LP64__ - u64 megaBase; -#else - u32 megaBase; -#endif - - u16 pciIdx = 0; - u16 numFound = 0; - u16 subsysid, subsysvid; -#if 0 - u8 mega_ch_class; -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) /* 0x20100 */ - while (!pcibios_find_device - (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) { -#else - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) /*0x20300 */ - struct pci_dev *pdev = NULL; -#else - struct pci_dev *pdev = pci_devices; -#endif - - while ((pdev = pci_find_device (pciVendor, pciDev, pdev))) { - if(pci_enable_device (pdev)) - continue; - pciBus = pdev->bus->number; - pciDevFun = pdev->devfn; -#endif - if ((flag & BOARD_QUARTZ) && (skip_id == -1)) { - if( (pciVendor == PCI_VENDOR_ID_PERC4_DI_YSTONE && - pciDev == PCI_DEVICE_ID_PERC4_DI_YSTONE) || - (pciVendor == PCI_VENDOR_ID_PERC4_QC_VERDE && - pciDev == PCI_DEVICE_ID_PERC4_QC_VERDE) ) { - - flag |= BOARD_64BIT; - } - else { - pcibios_read_config_word (pciBus, pciDevFun, - PCI_CONF_AMISIG, &magic); - if ((magic != AMI_SIGNATURE) - && (magic != AMI_SIGNATURE_471)) { - pciIdx++; - continue; /* not an AMI board */ - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pcibios_read_config_dword (pciBus, pciDevFun, - PCI_CONF_AMISIG64, &magic64); - - if (magic64 == AMI_64BIT_SIGNATURE) - flag |= BOARD_64BIT; -#endif - } - } - - /* Hmmm...Should we not make this more modularized so that in future we dont add - for each firmware */ - - if (flag & BOARD_QUARTZ) { - /* Check to see if this is a Dell PERC RAID controller model 466 */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) /* 0x20100 */ - pcibios_read_config_word (pciBus, pciDevFun, - PCI_SUBSYSTEM_VENDOR_ID, - &subsysvid); - pcibios_read_config_word (pciBus, pciDevFun, - PCI_SUBSYSTEM_ID, &subsysid); -#else - pci_read_config_word (pdev, - PCI_SUBSYSTEM_VENDOR_ID, - &subsysvid); - pci_read_config_word (pdev, - PCI_SUBSYSTEM_ID, &subsysid); -#endif - - /* - * If we do not find the valid subsys vendor id, refuse to load - * the driver. This is part of PCI200X compliance - */ - if( (subsysvid != AMI_SUBSYS_ID) && - (subsysvid != DELL_SUBSYS_ID) && - (subsysvid != LSI_SUBSYS_ID) && - (subsysvid != HP_SUBSYS_ID) ) continue; - - } - - printk (KERN_NOTICE - "megaraid: found 0x%4.04x:0x%4.04x:idx %d:bus %d:slot %d:func %d\n", - pciVendor, pciDev, pciIdx, pciBus, PCI_SLOT (pciDevFun), - PCI_FUNC (pciDevFun)); - /* Read the base port and IRQ from PCI */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) /* 0x20100 */ - pcibios_read_config_dword (pciBus, pciDevFun, - PCI_BASE_ADDRESS_0, - (u_int *) & megaBase); - pcibios_read_config_byte (pciBus, pciDevFun, - PCI_INTERRUPT_LINE, &megaIrq); -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) /*0x20300 */ - megaBase = pdev->base_address[0]; - megaIrq = pdev->irq; -#else - - megaBase = pci_resource_start (pdev, 0); - megaIrq = pdev->irq; -#endif - - pciIdx++; - - if (flag & BOARD_QUARTZ) { - megaBase &= PCI_BASE_ADDRESS_MEM_MASK; - megaBase = (long) ioremap (megaBase, 128); - if (!megaBase) - continue; - } else { - megaBase &= PCI_BASE_ADDRESS_IO_MASK; - megaBase += 0x10; - } - - /* Initialize SCSI Host structure */ - host = scsi_register (pHostTmpl, sizeof (mega_host_config)); - if (!host) - goto err_unmap; - - /* - * Comment the following initialization if you know 'max_sectors' is - * not defined for this kernel. - * This field was introduced in Linus's kernel 2.4.7pre3 and it - * greatly increases the IO performance - AM - */ - host->max_sectors = 1024; - - scsi_set_pci_device(host, pdev); - megaCfg = (mega_host_config *) host->hostdata; - memset (megaCfg, 0, sizeof (mega_host_config)); - - printk (KERN_NOTICE "scsi%d : Found a MegaRAID controller at 0x%x, IRQ: %d" - M_RD_CRLFSTR, host->host_no, (u_int) megaBase, megaIrq); - - if (flag & BOARD_64BIT) - printk (KERN_NOTICE "scsi%d : Enabling 64 bit support\n", - host->host_no); - - /* Copy resource info into structure */ - megaCfg->qCompletedH = NULL; - megaCfg->qCompletedT = NULL; - megaCfg->qPendingH = NULL; - megaCfg->qPendingT = NULL; - megaCfg->qFreeH = NULL; - megaCfg->qFreeT = NULL; - megaCfg->qFcnt = 0; - megaCfg->qPcnt = 0; - megaCfg->qCcnt = 0; - megaCfg->lock_free = SPIN_LOCK_UNLOCKED; - megaCfg->lock_pend = SPIN_LOCK_UNLOCKED; - megaCfg->lock_scsicmd = SPIN_LOCK_UNLOCKED; - megaCfg->flag = flag; -#if XEN_KILLED_DELLOGDRV - megaCfg->int_qh = NULL; - megaCfg->int_qt = NULL; - megaCfg->int_qlen = 0; -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - megaCfg->dev = pdev; -#endif - megaCfg->host = host; - megaCfg->base = megaBase; - megaCfg->host->irq = megaIrq; - megaCfg->host->io_port = megaBase; - megaCfg->host->n_io_port = 16; - megaCfg->host->unique_id = (pciBus << 8) | pciDevFun; - megaCtlrs[numCtlrs] = megaCfg; - - if (!(flag & BOARD_QUARTZ)) { - - /* Request our IO Range */ - if( !request_region(megaBase, 16, "megaraid") ) - goto err_unregister; - } - - /* Request our IRQ */ - if (request_irq (megaIrq, megaraid_isr, SA_SHIRQ, - "megaraid", megaCfg)) { - printk (KERN_WARNING - "megaraid: Couldn't register IRQ %d!\n", - megaIrq); - goto err_release; - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - /* - * unmap while releasing the driver, Is it required to be - * PCI_DMA_BIDIRECTIONAL - */ - - megaCfg->mailbox64ptr - = pci_alloc_consistent (megaCfg->dev, - sizeof (mega_mailbox64), - &(megaCfg->dma_handle64)); - - mega_register_mailbox (megaCfg, - virt_to_bus ((void *) megaCfg-> - mailbox64ptr)); -#else - mega_register_mailbox (megaCfg, - virt_to_bus ((void *) &megaCfg-> - mailbox64)); -#endif - - mega_i_query_adapter (megaCfg); - - if ((subsysid == 0x1111) && (subsysvid == 0x1111)) { - - /* - * Which firmware - */ - if( strcmp(megaCfg->fwVer, "3.00") == 0 || - strcmp(megaCfg->fwVer, "3.01") == 0 ) { - - printk( KERN_WARNING - "megaraid: Your card is a Dell PERC 2/SC RAID controller " - "with firmware\nmegaraid: 3.00 or 3.01. This driver is " - "known to have corruption issues\nmegaraid: with those " - "firmware versions on this specific card. In order\n" - "megaraid: to protect your data, please upgrade your " - "firmware to version\nmegaraid: 3.10 or later, available " - "from the Dell Technical Support web\nmegaraid: site at\n" - "http://support.dell.com/us/en/filelib/download/" - "index.asp?fileid=2940\n" - ); - } - } - - /* - * If we have a HP 1M(0x60E7)/2M(0x60E8) controller with - * firmware H.01.07 or H.01.08, disable 64 bit support, - * since this firmware cannot handle 64 bit addressing - */ - - if( (subsysvid == HP_SUBSYS_ID) && - ((subsysid == 0x60E7)||(subsysid == 0x60E8)) ) { - - /* - * which firmware - */ - if( strcmp(megaCfg->fwVer, "H01.07") == 0 || - strcmp(megaCfg->fwVer, "H01.08") == 0 || - strcmp(megaCfg->fwVer, "H01.09") == 0 ) - { - printk(KERN_WARNING - "megaraid: Firmware H.01.07/8/9 on 1M/2M " - "controllers\nmegaraid: do not support 64 bit " - "addressing.\n" - "megaraid: DISABLING 64 bit support.\n"); - megaCfg->flag &= ~BOARD_64BIT; - } - } - - if (mega_is_bios_enabled (megaCfg)) { - mega_hbas[numCtlrs].is_bios_enabled = 1; - } - - /* - * Find out which channel is raid and which is scsi - */ - mega_enum_raid_scsi(megaCfg); - - /* - * Find out if a logical drive is set as the boot drive. If there is - * one, will make that as the first logical drive. - * ROMB: Do we have to boot from a physical drive. Then all the - * physical drives would appear before the logical disks. Else, all - * the physical drives would be exported to the mid layer after - * logical disks. - */ - mega_get_boot_drv(megaCfg); - - if( ! megaCfg->boot_pdrv_enabled ) { - for( i = 0; i < NVIRT_CHAN; i++ ) - megaCfg->logdrv_chan[i] = 1; - - for( i = NVIRT_CHAN; i < MAX_CHANNEL + NVIRT_CHAN; i++ ) - megaCfg->logdrv_chan[i] = 0; - - megaCfg->mega_ch_class <<= NVIRT_CHAN; - } - else { - j = megaCfg->productInfo.SCSIChanPresent; - for( i = 0; i < j; i++ ) - megaCfg->logdrv_chan[i] = 0; - - for( i = j; i < NVIRT_CHAN + j; i++ ) - megaCfg->logdrv_chan[i] = 1; - } - - - mega_hbas[numCtlrs].hostdata_addr = megaCfg; - - /* - * Do we support random deletion and addition of logical drives - */ - megaCfg->read_ldidmap = 0; /* set it after first logdrv delete cmd */ - megaCfg->support_random_del = mega_support_random_del(megaCfg); - - /* Initialize SCBs */ - if (mega_init_scb (megaCfg)) { - pci_free_consistent (megaCfg->dev, - sizeof (mega_mailbox64), - (void *) megaCfg->mailbox64ptr, - megaCfg->dma_handle64); - scsi_unregister (host); - continue; - } - - /* - * Fill in the structure which needs to be passed back to the - * application when it does an ioctl() for controller related - * information. - */ - - i = numCtlrs; - numCtlrs++; - - mcontroller[i].base = megaBase; - mcontroller[i].irq = megaIrq; - mcontroller[i].numldrv = megaCfg->numldrv; - mcontroller[i].pcibus = pciBus; - mcontroller[i].pcidev = pciDev; - mcontroller[i].pcifun = PCI_FUNC (pciDevFun); - mcontroller[i].pciid = pciIdx; - mcontroller[i].pcivendor = pciVendor; - mcontroller[i].pcislot = PCI_SLOT (pciDevFun); - mcontroller[i].uid = (pciBus << 8) | pciDevFun; - - numFound++; - - /* Set the Mode of addressing to 64 bit */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - if ((megaCfg->flag & BOARD_64BIT) && BITS_PER_LONG == 64) -#ifdef __LP64__ - pdev->dma_mask = 0xffffffffffffffff; -#else - pdev->dma_mask = 0xffffffff; -#endif -#endif - continue; - err_release: - if (flag & BOARD_QUARTZ) - release_region (megaBase, 16); - err_unregister: - scsi_unregister (host); - err_unmap: - if (flag & BOARD_QUARTZ) - iounmap ((void *) megaBase); - } - return numFound; -} - -/*--------------------------------------------------------- - * Detects if a megaraid controller exists in this system - *---------------------------------------------------------*/ - -int megaraid_detect (Scsi_Host_Template * pHostTmpl) -{ -#if XEN_KILLED - int ctlridx = 0; -#endif - int count = 0; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) /*0x20300 */ - pHostTmpl->proc_dir = &proc_scsi_megaraid; -#else - pHostTmpl->proc_name = "megaraid"; -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) /* 0x20100 */ - if (!pcibios_present ()) { - printk (KERN_WARNING "megaraid: PCI bios not present." - M_RD_CRLFSTR); - return 0; - } -#endif - skip_id = -1; - if (megaraid && !strncmp (megaraid, "skip", strlen ("skip"))) { - if (megaraid[4] != '\0') { - skip_id = megaraid[4] - '0'; - if (megaraid[5] != '\0') { - skip_id = (skip_id * 10) + (megaraid[5] - '0'); - } - } - skip_id = (skip_id > 15) ? -1 : skip_id; - } - - memset (mega_hbas, 0, sizeof (mega_hbas)); - - /* Detect ROMBs first */ - count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_DISCOVERY, - PCI_DEVICE_ID_DISCOVERY, BOARD_QUARTZ); - count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_PERC4_DI_YSTONE, - PCI_DEVICE_ID_PERC4_DI_YSTONE, BOARD_QUARTZ); - /* Then detect cards based on date they were produced, oldest first */ - count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_AMI, - PCI_DEVICE_ID_AMI_MEGARAID, 0); - count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_AMI, - PCI_DEVICE_ID_AMI_MEGARAID2, 0); - count += mega_findCard (pHostTmpl, 0x8086, - PCI_DEVICE_ID_AMI_MEGARAID3, BOARD_QUARTZ); - count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_AMI, - PCI_DEVICE_ID_AMI_MEGARAID3, BOARD_QUARTZ); - count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_LSI_LOGIC, - PCI_DEVICE_ID_AMI_MEGARAID3, BOARD_QUARTZ); - count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_PERC4_QC_VERDE, - PCI_DEVICE_ID_PERC4_QC_VERDE, BOARD_QUARTZ); - - if (count) - printk (KERN_NOTICE "megaraid: " MEGARAID_VERSION); - - if (count) - mega_reorder_hosts (); - -#ifdef CONFIG_PROC_FS - if (count) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) /*0x20300 */ - mega_proc_dir_entry = proc_mkdir ("megaraid", &proc_root); -#else - mega_proc_dir_entry = create_proc_entry ("megaraid", - S_IFDIR | S_IRUGO | - S_IXUGO, &proc_root); -#endif - if (!mega_proc_dir_entry) - printk ("megaraid: failed to create megaraid root\n"); - else - for (ctlridx = 0; ctlridx < count; ctlridx++) - mega_create_proc_entry (ctlridx, - mega_proc_dir_entry); - } -#endif - - /* - * Register the driver as a character device, for applications to access - * it for ioctls. - * Ideally, this should go in the init_module() routine, but since it is - * hidden in the file "scsi_module.c" ( included in the end ), we define - * it here - * First argument (major) to register_chrdev implies a dynamic major - * number allocation. - */ -#if XEN_KILLED - if (count) { - major = register_chrdev (0, "megadev", &megadev_fops); - - /* - * Register the Shutdown Notification hook in kernel - */ - if (register_reboot_notifier (&mega_notifier)) { - printk ("MegaRAID Shutdown routine not registered!!\n"); - } - - init_MUTEX (&mimd_entry_mtx); - } -#endif - - return count; -} - -/*--------------------------------------------------------------------- - * Release the controller's resources - *---------------------------------------------------------------------*/ -int megaraid_release (struct Scsi_Host *pSHost) -{ - mega_host_config *megaCfg; - mega_mailbox *mbox; - u_char mboxData[16]; -#ifdef CONFIG_PROC_FS - int i; -#endif - - megaCfg = (mega_host_config *) pSHost->hostdata; - mbox = (mega_mailbox *) mboxData; - - /* Flush cache to disk */ - memset (mbox, 0, 16); - mboxData[0] = 0xA; - - free_irq (megaCfg->host->irq, megaCfg); /* Must be freed first, otherwise - extra interrupt is generated */ - - /* Issue a blocking (interrupts disabled) command to the card */ - megaIssueCmd (megaCfg, mboxData, NULL, 0); - - /* Free our resources */ - if (megaCfg->flag & BOARD_QUARTZ) { - iounmap ((void *) megaCfg->base); - } else { - release_region (megaCfg->host->io_port, 16); - } - - mega_freeSgList (megaCfg); - pci_free_consistent (megaCfg->dev, - sizeof (mega_mailbox64), - (void *) megaCfg->mailbox64ptr, - megaCfg->dma_handle64); - -#ifdef CONFIG_PROC_FS - if (megaCfg->controller_proc_dir_entry) { - remove_proc_entry ("stat", megaCfg->controller_proc_dir_entry); - remove_proc_entry ("status", - megaCfg->controller_proc_dir_entry); - remove_proc_entry ("config", - megaCfg->controller_proc_dir_entry); - remove_proc_entry ("mailbox", - megaCfg->controller_proc_dir_entry); - for (i = 0; i < numCtlrs; i++) { - char buf[12] = { 0 }; - sprintf (buf, "%d", i); - remove_proc_entry (buf, mega_proc_dir_entry); - } - remove_proc_entry ("megaraid", &proc_root); - } -#endif - - /* - * Release the controller memory. A word of warning this frees - * hostdata and that includes megaCfg-> so be careful what you - * dereference beyond this point - */ - - scsi_unregister (pSHost); - - /* - * Unregister the character device interface to the driver. Ideally this - * should have been done in cleanup_module routine. Since this is hidden - * in file "scsi_module.c", we do it here. - * major is the major number of the character device returned by call to - * register_chrdev() routine. - */ - -#if XEN_KILLED - unregister_chrdev (major, "megadev"); - unregister_reboot_notifier (&mega_notifier); -#endif - - return 0; -} - -static int mega_is_bios_enabled (mega_host_config * megacfg) -{ - mega_mailbox *mboxpnt; - unsigned char mbox[16]; - int ret; - - mboxpnt = (mega_mailbox *) mbox; - - memset (mbox, 0, sizeof (mbox)); - memset ((void *) megacfg->mega_buffer, - 0, sizeof (megacfg->mega_buffer)); - - /* - * issue command to find out if the BIOS is enabled for this controller - */ - mbox[0] = IS_BIOS_ENABLED; - mbox[2] = GET_BIOS; - - mboxpnt->xferaddr = virt_to_bus ((void *) megacfg->mega_buffer); - - ret = megaIssueCmd (megacfg, mbox, NULL, 0); - - return (*(char *) megacfg->mega_buffer); -} - -/* - * Find out what channels are RAID/SCSI - */ -static void -mega_enum_raid_scsi(mega_host_config *megacfg) -{ - mega_mailbox *mboxp; - unsigned char mbox[16]; - int i; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - dma_addr_t dma_handle; -#endif - - mboxp = (mega_mailbox *)mbox; - - memset(mbox, 0, sizeof(mbox)); - /* - * issue command to find out what channels are raid/scsi - */ - mbox[0] = CHNL_CLASS; - mbox[2] = GET_CHNL_CLASS; - - memset((void *)megacfg->mega_buffer, 0, sizeof(megacfg->mega_buffer)); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - dma_handle = pci_map_single(megacfg->dev, (void *)megacfg->mega_buffer, - (2 * 1024L), PCI_DMA_FROMDEVICE); - - mboxp->xferaddr = dma_handle; -#else - mboxp->xferaddr = virt_to_bus((void *)megacfg->mega_buffer); -#endif - - /* - * Non-ROMB firware fail this command, so all channels - * must be shown RAID - */ - megacfg->mega_ch_class = 0xFF; - if( megaIssueCmd(megacfg, mbox, NULL, 0) == 0 ) { - megacfg->mega_ch_class = *((char *)megacfg->mega_buffer); - } - - for( i = 0; i < megacfg->productInfo.SCSIChanPresent; i++ ) { - if( (megacfg->mega_ch_class >> i) & 0x01 ) - printk(KERN_NOTICE"megaraid: channel[%d] is raid.\n", i+1); - else - printk(KERN_NOTICE"megaraid: channel[%d] is scsi.\n", i+1); - } - - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pci_unmap_single(megacfg->dev, dma_handle, - (2 * 1024L), PCI_DMA_FROMDEVICE); -#endif - -} - - -/* - * get the boot logical drive number if enabled - */ -void -mega_get_boot_drv(mega_host_config *megacfg) -{ - mega_mailbox *mboxp; - unsigned char mbox[16]; - struct private_bios_data *prv_bios_data; - u16 cksum = 0; - u8 *cksum_p; - u8 boot_pdrv; - int i; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - dma_addr_t dma_handle; -#endif - - mboxp = (mega_mailbox *)mbox; - - memset(mbox, 0, sizeof(mbox)); - - mbox[0] = BIOS_PVT_DATA; - mbox[2] = GET_BIOS_PVT_DATA; - - memset((void *)megacfg->mega_buffer, 0, sizeof(megacfg->mega_buffer)); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - dma_handle = pci_map_single(megacfg->dev, (void *)megacfg->mega_buffer, - (2 * 1024L), PCI_DMA_FROMDEVICE); - - mboxp->xferaddr = dma_handle; -#else - mboxp->xferaddr = virt_to_bus((void *)megacfg->mega_buffer); -#endif - - megacfg->boot_ldrv_enabled = 0; - megacfg->boot_ldrv = 0; - - megacfg->boot_pdrv_enabled = 0; - megacfg->boot_pdrv_ch = 0; - megacfg->boot_pdrv_tgt = 0; - - if( megaIssueCmd(megacfg, mbox, NULL, 0) == 0 ) { - prv_bios_data = (struct private_bios_data *)megacfg->mega_buffer; - - cksum = 0; - cksum_p = (u8 *)prv_bios_data; - for( i = 0; i < 14; i++ ) { - cksum += *cksum_p++; - } - - if( prv_bios_data->cksum == (u16)(0-cksum) ) { - - /* - * If MSB is set, a physical drive is set as boot device - */ - if( prv_bios_data->boot_drv & 0x80 ) { - megacfg->boot_pdrv_enabled = 1; - boot_pdrv = prv_bios_data->boot_drv & 0x7F; - megacfg->boot_pdrv_ch = boot_pdrv / 16; - megacfg->boot_pdrv_tgt = boot_pdrv % 16; - } - else { - megacfg->boot_ldrv_enabled = 1; - megacfg->boot_ldrv = prv_bios_data->boot_drv; - } - } - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pci_unmap_single(megacfg->dev, dma_handle, - (2 * 1024L), PCI_DMA_FROMDEVICE); -#endif - -} - - -static void mega_reorder_hosts (void) -{ - struct Scsi_Host *shpnt; - struct Scsi_Host *shone; - struct Scsi_Host *shtwo; - mega_host_config *boot_host; - int i; - - /* - * Find the (first) host which has it's BIOS enabled - */ - boot_host = NULL; - for (i = 0; i < MAX_CONTROLLERS; i++) { - if (mega_hbas[i].is_bios_enabled) { - boot_host = mega_hbas[i].hostdata_addr; - break; - } - } - - if (boot_host == NULL) { - printk (KERN_WARNING "megaraid: no BIOS enabled.\n"); - return; - } - - /* - * Traverse through the list of SCSI hosts for our HBA locations - */ - shone = shtwo = NULL; - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - /* Is it one of ours? */ - for (i = 0; i < MAX_CONTROLLERS; i++) { - if ((mega_host_config *) shpnt->hostdata == - mega_hbas[i].hostdata_addr) { - /* Does this one has BIOS enabled */ - if (mega_hbas[i].hostdata_addr == boot_host) { - - /* Are we first */ - if (shtwo == NULL) /* Yes! */ - return; - else { /* :-( */ - shone = shpnt; - } - } else { - if (!shtwo) { - /* were we here before? xchng first */ - shtwo = shpnt; - } - } - break; - } - } - /* - * Have we got the boot host and one which does not have the bios - * enabled. - */ - if (shone && shtwo) - break; - } - if (shone && shtwo) { - mega_swap_hosts (shone, shtwo); - } - - return; -} - -static void mega_swap_hosts (struct Scsi_Host *shone, struct Scsi_Host *shtwo) -{ - struct Scsi_Host *prevtoshtwo; - struct Scsi_Host *prevtoshone; - struct Scsi_Host *save = NULL;; - - /* Are these two nodes adjacent */ - if (shtwo->next == shone) { - - if (shtwo == scsi_hostlist && shone->next == NULL) { - - /* just two nodes */ - scsi_hostlist = shone; - shone->next = shtwo; - shtwo->next = NULL; - } else if (shtwo == scsi_hostlist) { - /* first two nodes of the list */ - - scsi_hostlist = shone; - shtwo->next = shone->next; - scsi_hostlist->next = shtwo; - } else if (shone->next == NULL) { - /* last two nodes of the list */ - - prevtoshtwo = scsi_hostlist; - - while (prevtoshtwo->next != shtwo) - prevtoshtwo = prevtoshtwo->next; - - prevtoshtwo->next = shone; - shone->next = shtwo; - shtwo->next = NULL; - } else { - prevtoshtwo = scsi_hostlist; - - while (prevtoshtwo->next != shtwo) - prevtoshtwo = prevtoshtwo->next; - - prevtoshtwo->next = shone; - shtwo->next = shone->next; - shone->next = shtwo; - } - - } else if (shtwo == scsi_hostlist && shone->next == NULL) { - /* shtwo at head, shone at tail, not adjacent */ - - prevtoshone = scsi_hostlist; - - while (prevtoshone->next != shone) - prevtoshone = prevtoshone->next; - - scsi_hostlist = shone; - shone->next = shtwo->next; - prevtoshone->next = shtwo; - shtwo->next = NULL; - } else if (shtwo == scsi_hostlist && shone->next != NULL) { - /* shtwo at head, shone is not at tail */ - - prevtoshone = scsi_hostlist; - while (prevtoshone->next != shone) - prevtoshone = prevtoshone->next; - - scsi_hostlist = shone; - prevtoshone->next = shtwo; - save = shtwo->next; - shtwo->next = shone->next; - shone->next = save; - } else if (shone->next == NULL) { - /* shtwo not at head, shone at tail */ - - prevtoshtwo = scsi_hostlist; - prevtoshone = scsi_hostlist; - - while (prevtoshtwo->next != shtwo) - prevtoshtwo = prevtoshtwo->next; - while (prevtoshone->next != shone) - prevtoshone = prevtoshone->next; - - prevtoshtwo->next = shone; - shone->next = shtwo->next; - prevtoshone->next = shtwo; - shtwo->next = NULL; - - } else { - prevtoshtwo = scsi_hostlist; - prevtoshone = scsi_hostlist; - save = NULL;; - - while (prevtoshtwo->next != shtwo) - prevtoshtwo = prevtoshtwo->next; - while (prevtoshone->next != shone) - prevtoshone = prevtoshone->next; - - prevtoshtwo->next = shone; - save = shone->next; - shone->next = shtwo->next; - prevtoshone->next = shtwo; - shtwo->next = save; - } - return; -} - -static inline void mega_freeSgList (mega_host_config * megaCfg) -{ - int i; - - for (i = 0; i < megaCfg->max_cmds; i++) { - if (megaCfg->scbList[i].sgList) - pci_free_consistent (megaCfg->dev, - sizeof (mega_64sglist) * - MAX_SGLIST, - megaCfg->scbList[i].sgList, - megaCfg->scbList[i]. - dma_sghandle64); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) /* 0x020400 */ - kfree (megaCfg->scbList[i].sgList); /* free sgList */ -#endif - } -} - -/*---------------------------------------------- - * Get information about the card/driver - *----------------------------------------------*/ -const char *megaraid_info (struct Scsi_Host *pSHost) -{ - static char buffer[512]; - mega_host_config *megaCfg; - - megaCfg = (mega_host_config *) pSHost->hostdata; - - sprintf (buffer, - "LSI Logic MegaRAID %s %d commands %d targs %d chans %d luns", - megaCfg->fwVer, megaCfg->productInfo.MaxConcCmds, - megaCfg->host->max_id-1, megaCfg->host->max_channel, - megaCfg->host->max_lun); - return buffer; -} - -/*----------------------------------------------------------------- - * Perform a SCSI command - * Mailbox area: - * 00 01 command - * 01 01 command id - * 02 02 # of sectors - * 04 04 logical bus address - * 08 04 physical buffer address - * 0C 01 logical drive # - * 0D 01 length of scatter/gather list - * 0E 01 reserved - * 0F 01 mailbox busy - * 10 01 numstatus byte - * 11 01 status byte - *-----------------------------------------------------------------*/ -int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *)) -{ - DRIVER_LOCK_T mega_host_config * megaCfg; - mega_scb *pScb; - char *user_area = NULL; - - megaCfg = (mega_host_config *) SCpnt->host->hostdata; - DRIVER_LOCK (megaCfg); - -#if 0 - if (!(megaCfg->flag & (1L << SCpnt->channel))) { - if (SCpnt->channel < megaCfg->productInfo.SCSIChanPresent) - printk ( KERN_NOTICE - "scsi%d: scanning channel %d for devices.\n", - megaCfg->host->host_no, SCpnt->channel); - else - printk ( KERN_NOTICE - "scsi%d: scanning virtual channel %d for logical drives.\n", - megaCfg->host->host_no, - SCpnt->channel-megaCfg->productInfo.SCSIChanPresent+1); - - megaCfg->flag |= (1L << SCpnt->channel); - } -#endif - - SCpnt->scsi_done = pktComp; - - if (mega_driver_ioctl (megaCfg, SCpnt)) - return 0; - - /* If driver in abort or reset.. cancel this command */ - if (megaCfg->flag & IN_ABORT) { - SCpnt->result = (DID_ABORT << 16); - /* Add Scsi_Command to end of completed queue */ - if (megaCfg->qCompletedH == NULL) { - megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt; - } else { - megaCfg->qCompletedT->host_scribble = - (unsigned char *) SCpnt; - megaCfg->qCompletedT = SCpnt; - } - megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL; - megaCfg->qCcnt++; - - DRIVER_UNLOCK (megaCfg); - return 0; - } else if (megaCfg->flag & IN_RESET) { - SCpnt->result = (DID_RESET << 16); - /* Add Scsi_Command to end of completed queue */ - if (megaCfg->qCompletedH == NULL) { - megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt; - } else { - megaCfg->qCompletedT->host_scribble = - (unsigned char *) SCpnt; - megaCfg->qCompletedT = SCpnt; - } - megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL; - megaCfg->qCcnt++; - - DRIVER_UNLOCK (megaCfg); - return 0; - } - - megaCfg->flag |= IN_QUEUE; - /* Allocate and build a SCB request */ - if ((pScb = mega_build_cmd (megaCfg, SCpnt)) != NULL) { - - /* - * Check if the HBA is in quiescent state, e.g., during a delete - * logical drive opertion. If it is, queue the commands in the - * internal queue until the delete operation is complete. - */ -#if XEN_KILLED_DELLOGDRV - if( ! megaCfg->quiescent ) { -#endif - /* Add SCB to the head of the pending queue */ - if (megaCfg->qPendingH == NULL) { - megaCfg->qPendingH = megaCfg->qPendingT = pScb; - } else { - megaCfg->qPendingT->next = pScb; - megaCfg->qPendingT = pScb; - } - megaCfg->qPendingT->next = NULL; - megaCfg->qPcnt++; - - if (mega_runpendq (megaCfg) == -1) { - DRIVER_UNLOCK (megaCfg); - return 0; - } -#if XEN_KILLED_DELLOGDRV - } - else { - /* Add SCB to the internal queue */ - if (megaCfg->int_qh == NULL) { - megaCfg->int_qh = megaCfg->int_qt = pScb; - } else { - megaCfg->int_qt->next = pScb; - megaCfg->int_qt = pScb; - } - megaCfg->int_qt->next = NULL; - megaCfg->int_qlen++; - } -#endif - - if (pScb->SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) { -#if XEN_KILLED - init_MUTEX_LOCKED (&pScb->ioctl_sem); -#endif - spin_unlock_irq (&io_request_lock); -#if XEN_KILLED - down (&pScb->ioctl_sem); -#endif - user_area = (char *)*((u32*)&pScb->SCpnt->cmnd[4]); - if (copy_to_user - (user_area, pScb->buff_ptr, pScb->iDataSize)) { - printk - ("megaraid: Error copying ioctl return value to user buffer.\n"); - pScb->SCpnt->result = (DID_ERROR << 16); - } - spin_lock_irq (&io_request_lock); - DRIVER_LOCK (megaCfg); - kfree (pScb->buff_ptr); - pScb->buff_ptr = NULL; - mega_cmd_done (megaCfg, pScb, pScb->SCpnt->result); - mega_rundoneq (megaCfg); - mega_runpendq (megaCfg); - DRIVER_UNLOCK (megaCfg); - } - - megaCfg->flag &= ~IN_QUEUE; - - } - - DRIVER_UNLOCK (megaCfg); - return 0; -} - -/*---------------------------------------------------------------------- - * Issue a blocking command to the controller - *----------------------------------------------------------------------*/ -#if XEN_KILLED -volatile static int internal_done_flag = 0; -volatile static int internal_done_errcode = 0; - -static DECLARE_WAIT_QUEUE_HEAD (internal_wait); - -static void internal_done (Scsi_Cmnd * SCpnt) -{ - internal_done_errcode = SCpnt->result; - internal_done_flag++; - wake_up (&internal_wait); -} - -/* shouldn't be used, but included for completeness */ - -int megaraid_command (Scsi_Cmnd * SCpnt) -{ - internal_done_flag = 0; - - /* Queue command, and wait until it has completed */ - megaraid_queue (SCpnt, internal_done); - - while (!internal_done_flag) { - interruptible_sleep_on (&internal_wait); - } - - return internal_done_errcode; -} -#endif - -/*--------------------------------------------------------------------- - * Abort a previous SCSI request - *---------------------------------------------------------------------*/ -int megaraid_abort (Scsi_Cmnd * SCpnt) -{ - mega_host_config *megaCfg; - int rc; /*, idx; */ - mega_scb *pScb; - - rc = SCSI_ABORT_NOT_RUNNING; - - megaCfg = (mega_host_config *) SCpnt->host->hostdata; - - megaCfg->flag |= IN_ABORT; - - for (pScb = megaCfg->qPendingH; pScb; pScb = pScb->next) { - if (pScb->SCpnt == SCpnt) { - /* Found an aborting command */ -#if DEBUG - showMbox (pScb); -#endif - - /* - * If the command is queued to be issued to the firmware, abort the scsi cmd, - * If the command is already aborted in a previous call to the _abort entry - * point, return SCSI_ABORT_SNOOZE, suggesting a reset. - * If the command is issued to the firmware, which might complete after - * some time, we will mark the scb as aborted, and return to the mid layer, - * that abort could not be done. - * In the ISR, when this command actually completes, we will perform a normal - * completion. - * - * Oct 27, 1999 - */ - - switch (pScb->state) { - case SCB_ABORTED: /* Already aborted */ - rc = SCSI_ABORT_SNOOZE; - break; - case SCB_ISSUED: /* Waiting on ISR result */ - rc = SCSI_ABORT_NOT_RUNNING; - pScb->state = SCB_ABORTED; - break; - case SCB_ACTIVE: /* still on the pending queue */ - mega_freeSCB (megaCfg, pScb); - SCpnt->result = (DID_ABORT << 16); - if (megaCfg->qCompletedH == NULL) { - megaCfg->qCompletedH = - megaCfg->qCompletedT = SCpnt; - } else { - megaCfg->qCompletedT->host_scribble = - (unsigned char *) SCpnt; - megaCfg->qCompletedT = SCpnt; - } - megaCfg->qCompletedT->host_scribble = - (unsigned char *) NULL; - megaCfg->qCcnt++; - rc = SCSI_ABORT_SUCCESS; - break; - default: - printk - ("megaraid_abort: unknown command state!!\n"); - rc = SCSI_ABORT_NOT_RUNNING; - break; - } - break; - } - } - - megaCfg->flag &= ~IN_ABORT; - -#if DEBUG - if (megaCfg->flag & IN_QUEUE) - printk ("ma:flag is in queue\n"); - if (megaCfg->qCompletedH == NULL) - printk ("ma:qchead == null\n"); -#endif - - /* - * This is required here to complete any completed requests to be communicated - * over to the mid layer. - * Calling just mega_rundoneq() did not work. - */ - if (megaCfg->qCompletedH) { - SCpnt = megaCfg->qCompletedH; - megaCfg->qCompletedH = (Scsi_Cmnd *) SCpnt->host_scribble; - megaCfg->qCcnt--; - - SCpnt->host_scribble = (unsigned char *) NULL; - /* Callback */ - callDone (SCpnt); - } - mega_rundoneq (megaCfg); - - return rc; -} - -/*--------------------------------------------------------------------- - * Reset a previous SCSI request - *---------------------------------------------------------------------*/ - -int megaraid_reset (Scsi_Cmnd * SCpnt, unsigned int rstflags) -{ - mega_host_config *megaCfg; - int idx; - int rc; - mega_scb *pScb; - - rc = SCSI_RESET_NOT_RUNNING; - megaCfg = (mega_host_config *) SCpnt->host->hostdata; - - megaCfg->flag |= IN_RESET; - - printk - ("megaraid_RESET: %.08lx cmd=%.02x , flag = %x\n", - SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, - SCpnt->target, SCpnt->lun, rstflags); - - TRACE (("RESET: %.08lx %.02x <%d.%d.%d>\n", - SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, - SCpnt->target, SCpnt->lun)); - - /* - * Walk list of SCBs for any that are still outstanding - */ - for (idx = 0; idx < megaCfg->max_cmds; idx++) { - if (megaCfg->scbList[idx].state != SCB_FREE) { - SCpnt = megaCfg->scbList[idx].SCpnt; - pScb = &megaCfg->scbList[idx]; - if (SCpnt != NULL) { - pScb->state = SCB_RESET; - break; - } - } - } - - megaCfg->flag &= ~IN_RESET; - - mega_rundoneq (megaCfg); - return rc; -} - -#ifdef CONFIG_PROC_FS -/* Following code handles /proc fs */ -static int proc_printf (mega_host_config * megaCfg, const char *fmt, ...) -{ - va_list args; - int i; - - if (megaCfg->procidx > PROCBUFSIZE) - return 0; - - va_start (args, fmt); - i = vsprintf ((megaCfg->procbuf + megaCfg->procidx), fmt, args); - va_end (args); - - megaCfg->procidx += i; - return i; -} - -static int proc_read_config (char *page, char **start, off_t offset, - int count, int *eof, void *data) -{ - - mega_host_config *megaCfg = (mega_host_config *) data; - - *start = page; - - if (megaCfg->productInfo.ProductName[0] != 0) - proc_printf (megaCfg, "%s\n", megaCfg->productInfo.ProductName); - - proc_printf (megaCfg, "Controller Type: "); - - if (megaCfg->flag & BOARD_QUARTZ) - proc_printf (megaCfg, "438/466/467/471/493\n"); - else - proc_printf (megaCfg, "418/428/434\n"); - - if (megaCfg->flag & BOARD_40LD) - proc_printf (megaCfg, - "Controller Supports 40 Logical Drives\n"); - - if (megaCfg->flag & BOARD_64BIT) - proc_printf (megaCfg, - "Controller / Driver uses 64 bit memory addressing\n"); - - proc_printf (megaCfg, "Base = %08x, Irq = %d, ", megaCfg->base, - megaCfg->host->irq); - - proc_printf (megaCfg, "Logical Drives = %d, Channels = %d\n", - megaCfg->numldrv, megaCfg->productInfo.SCSIChanPresent); - - proc_printf (megaCfg, "Version =%s:%s, DRAM = %dMb\n", - megaCfg->fwVer, megaCfg->biosVer, - megaCfg->productInfo.DramSize); - - proc_printf (megaCfg, - "Controller Queue Depth = %d, Driver Queue Depth = %d\n", - megaCfg->productInfo.MaxConcCmds, megaCfg->max_cmds); - COPY_BACK; - return count; -} - -static int proc_read_stat (char *page, char **start, off_t offset, - int count, int *eof, void *data) -{ - int i; - mega_host_config *megaCfg = (mega_host_config *) data; - - *start = page; - - proc_printf (megaCfg, "Statistical Information for this controller\n"); - proc_printf (megaCfg, "Interrupts Collected = %lu\n", - megaCfg->nInterrupts); - - for (i = 0; i < megaCfg->numldrv; i++) { - proc_printf (megaCfg, "Logical Drive %d:\n", i); - - proc_printf (megaCfg, - "\tReads Issued = %lu, Writes Issued = %lu\n", - megaCfg->nReads[i], megaCfg->nWrites[i]); - - proc_printf (megaCfg, - "\tSectors Read = %lu, Sectors Written = %lu\n\n", - megaCfg->nReadBlocks[i], megaCfg->nWriteBlocks[i]); - - } - - COPY_BACK; - return count; -} - -static int proc_read_status (char *page, char **start, off_t offset, - int count, int *eof, void *data) -{ - mega_host_config *megaCfg = (mega_host_config *) data; - *start = page; - - proc_printf (megaCfg, "TBD\n"); - COPY_BACK; - return count; -} - -static int proc_read_mbox (char *page, char **start, off_t offset, - int count, int *eof, void *data) -{ - - mega_host_config *megaCfg = (mega_host_config *) data; - volatile mega_mailbox *mbox = megaCfg->mbox; - - *start = page; - - proc_printf (megaCfg, "Contents of Mail Box Structure\n"); - proc_printf (megaCfg, " Fw Command = 0x%02x\n", mbox->cmd); - proc_printf (megaCfg, " Cmd Sequence = 0x%02x\n", mbox->cmdid); - proc_printf (megaCfg, " No of Sectors= %04d\n", mbox->numsectors); - proc_printf (megaCfg, " LBA = 0x%02x\n", mbox->lba); - proc_printf (megaCfg, " DTA = 0x%08x\n", mbox->xferaddr); - proc_printf (megaCfg, " Logical Drive= 0x%02x\n", mbox->logdrv); - proc_printf (megaCfg, " No of SG Elmt= 0x%02x\n", mbox->numsgelements); - proc_printf (megaCfg, " Busy = %01x\n", mbox->busy); - proc_printf (megaCfg, " Status = 0x%02x\n", mbox->status); - - /* proc_printf(megaCfg, "Dump of MailBox\n"); - for (i = 0; i < 16; i++) - proc_printf(megaCfg, "%02x ",*(mbox + i)); - - proc_printf(megaCfg, "\n\nNumber of Status = %02d\n",mbox->numstatus); - - for (i = 0; i < 46; i++) { - proc_printf(megaCfg,"%02d ",*(mbox + 16 + i)); - if (i%16) - proc_printf(megaCfg,"\n"); - } - - if (!mbox->numsgelements) { - dta = phys_to_virt(mbox->xferaddr); - for (i = 0; i < mbox->numsgelements; i++) - if (dta) { - proc_printf(megaCfg,"Addr = %08x\n", (ulong)*(dta + i)); proc_printf(megaCfg,"Length = %08x\n", - (ulong)*(dta + i + 4)); - } - }*/ - COPY_BACK; - return count; -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) /*0x20300 */ -#define CREATE_READ_PROC(string, fxn) create_proc_read_entry(string, \ - S_IRUSR | S_IFREG,\ - controller_proc_dir_entry,\ - fxn, megaCfg) -#else -#define CREATE_READ_PROC(string, fxn) create_proc_read_entry(string,S_IRUSR | S_IFREG, controller_proc_dir_entry, fxn, megaCfg) - -static struct proc_dir_entry * -create_proc_read_entry (const char *string, - int mode, - struct proc_dir_entry *parent, - read_proc_t * fxn, mega_host_config * megaCfg) -{ - struct proc_dir_entry *temp = NULL; - - temp = kmalloc (sizeof (struct proc_dir_entry), GFP_KERNEL); - if (!temp) - return NULL; - memset (temp, 0, sizeof (struct proc_dir_entry)); - - if ((temp->name = kmalloc (strlen (string) + 1, GFP_KERNEL)) == NULL) { - kfree (temp); - return NULL; - } - - strcpy ((char *) temp->name, string); - temp->namelen = strlen (string); - temp->mode = mode; /*S_IFREG | S_IRUSR */ ; - temp->data = (void *) megaCfg; - temp->read_proc = fxn; - proc_register (parent, temp); - return temp; -} -#endif - -static void mega_create_proc_entry (int index, struct proc_dir_entry *parent) -{ - u_char string[64] = { 0 }; - mega_host_config *megaCfg = megaCtlrs[index]; - struct proc_dir_entry *controller_proc_dir_entry = NULL; - - sprintf (string, "%d", index); - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) /*0x20300 */ - controller_proc_dir_entry = - megaCfg->controller_proc_dir_entry = proc_mkdir (string, parent); -#else - controller_proc_dir_entry = - megaCfg->controller_proc_dir_entry = - create_proc_entry (string, S_IFDIR | S_IRUGO | S_IXUGO, parent); -#endif - - if (!controller_proc_dir_entry) - printk ("\nmegaraid: proc_mkdir failed\n"); - else { - megaCfg->proc_read = - CREATE_READ_PROC ("config", proc_read_config); - megaCfg->proc_status = - CREATE_READ_PROC ("status", proc_read_status); - megaCfg->proc_stat = CREATE_READ_PROC ("stat", proc_read_stat); - megaCfg->proc_mbox = - CREATE_READ_PROC ("mailbox", proc_read_mbox); - } - -} -#endif /* CONFIG_PROC_FS */ - -/*------------------------------------------------------------- - * Return the disk geometry for a particular disk - * Input: - * Disk *disk - Disk geometry - * kdev_t dev - Device node - * int *geom - Returns geometry fields - * geom[0] = heads - * geom[1] = sectors - * geom[2] = cylinders - *-------------------------------------------------------------*/ -int megaraid_biosparam (Disk * disk, kdev_t dev, int *geom) -{ - int heads, sectors, cylinders; - mega_host_config *megaCfg; - - /* Get pointer to host config structure */ - megaCfg = (mega_host_config *) disk->device->host->hostdata; - - if( IS_RAID_CH(megaCfg, disk->device->channel)) { - /* Default heads (64) & sectors (32) */ - heads = 64; - sectors = 32; - cylinders = disk->capacity / (heads * sectors); - - /* Handle extended translation size for logical drives > 1Gb */ - if (disk->capacity >= 0x200000) { - heads = 255; - sectors = 63; - cylinders = disk->capacity / (heads * sectors); - } - - /* return result */ - geom[0] = heads; - geom[1] = sectors; - geom[2] = cylinders; - } - else { - if( mega_partsize(disk, dev, geom) == 0 ) return 0; - - printk(KERN_WARNING - "megaraid: invalid partition on this disk on channel %d\n", - disk->device->channel); - - /* Default heads (64) & sectors (32) */ - heads = 64; - sectors = 32; - cylinders = disk->capacity / (heads * sectors); - - /* Handle extended translation size for logical drives > 1Gb */ - if (disk->capacity >= 0x200000) { - heads = 255; - sectors = 63; - cylinders = disk->capacity / (heads * sectors); - } - - /* return result */ - geom[0] = heads; - geom[1] = sectors; - geom[2] = cylinders; - } - - return 0; -} - -/* - * Function : static int mega_partsize(Disk * disk, kdev_t dev, int *geom) - * - * Purpose : to determine the BIOS mapping used to create the partition - * table, storing the results (cyls, hds, and secs) in geom - * - * Note: Code is picked from scsicam.h - * - * Returns : -1 on failure, 0 on success. - */ -static int -mega_partsize(Disk * disk, kdev_t dev, int *geom) -{ -#if XEN_KILLED - struct buffer_head *bh; - struct partition *p, *largest = NULL; - int i, largest_cyl; - int heads, cyls, sectors; - int capacity = disk->capacity; - - int ma = MAJOR(dev); - int mi = (MINOR(dev) & ~0xf); - - int block = 1024; - - - if(blksize_size[ma]) - block = blksize_size[ma][mi]; - - if(!(bh = bread(MKDEV(ma,mi), 0, block))) - return -1; - - if( *(unsigned short *)(bh->b_data + 510) == 0xAA55 ) { - - for( largest_cyl = -1, p = (struct partition *)(0x1BE + bh->b_data), - i = 0; i < 4; ++i, ++p) { - - if (!p->sys_ind) continue; - - cyls = p->end_cyl + ((p->end_sector & 0xc0) << 2); - - if(cyls >= largest_cyl) { - largest_cyl = cyls; - largest = p; - } - } - } - - if (largest) { - heads = largest->end_head + 1; - sectors = largest->end_sector & 0x3f; - - if (heads == 0 || sectors == 0) { - brelse(bh); - return -1; - } - - cyls = capacity/(heads * sectors); - - geom[0] = heads; - geom[1] = sectors; - geom[2] = cyls; - - brelse(bh); - return 0; - } - - brelse(bh); -#endif - return -1; -} - - -#if 0 /* XEN */ -/* - * This routine will be called when the use has done a forced shutdown on the - * system. Flush the Adapter cache, that's the most we can do. - */ -static int megaraid_reboot_notify (struct notifier_block *this, unsigned long code, - void *unused) -{ - struct Scsi_Host *pSHost; - mega_host_config *megaCfg; - mega_mailbox *mbox; - u_char mboxData[16]; - int i; - - if (code == SYS_DOWN || code == SYS_HALT) { - for (i = 0; i < numCtlrs; i++) { - pSHost = megaCtlrs[i]->host; - - megaCfg = (mega_host_config *) pSHost->hostdata; - mbox = (mega_mailbox *) mboxData; - - /* Flush cache to disk */ - memset (mbox, 0, 16); - mboxData[0] = 0xA; - - /* - * Free irq, otherwise extra interrupt is generated - */ - free_irq (megaCfg->host->irq, megaCfg); - - /* - * Issue a blocking (interrupts disabled) command to - * the card - */ - megaIssueCmd (megaCfg, mboxData, NULL, 0); - } - } - return NOTIFY_DONE; -} -#endif /* 0 (XEN) */ - -static int mega_init_scb (mega_host_config * megacfg) -{ - int idx; - -#if DEBUG - if (megacfg->max_cmds >= MAX_COMMANDS) { - printk ("megaraid:ctlr max cmds = %x : MAX_CMDS = %x", - megacfg->max_cmds, MAX_COMMANDS); - } -#endif - - for (idx = megacfg->max_cmds - 1; idx >= 0; idx--) { - - megacfg->scbList[idx].idx = idx; - - /* - * ISR will make this flag zero to indicate the command has been - * completed. This is only for user ioctl calls. Rest of the driver - * and the mid-layer operations are not connected with this flag. - */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - megacfg->scbList[idx].sgList = - pci_alloc_consistent (megacfg->dev, - sizeof (mega_64sglist) * MAX_SGLIST, - &(megacfg->scbList[idx]. - dma_sghandle64)); - - megacfg->scbList[idx].sg64List = - (mega_64sglist *) megacfg->scbList[idx].sgList; -#else - megacfg->scbList[idx].sgList = kmalloc (sizeof (mega_sglist) * MAX_SGLIST, GFP_ATOMIC | GFP_DMA); -#endif - - if (megacfg->scbList[idx].sgList == NULL) { - printk (KERN_WARNING - "Can't allocate sglist for id %d\n", idx); - mega_freeSgList (megacfg); - return -1; - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - megacfg->scbList[idx].pthru = pci_alloc_consistent (megacfg->dev, - sizeof (mega_passthru), - &(megacfg->scbList[idx]. - dma_passthruhandle64)); - - if (megacfg->scbList[idx].pthru == NULL) { - printk (KERN_WARNING - "Can't allocate passthru for id %d\n", idx); - } - - megacfg->scbList[idx].epthru = - pci_alloc_consistent( - megacfg->dev, sizeof(mega_ext_passthru), - &(megacfg->scbList[idx].dma_ext_passthruhandle64) - ); - - if (megacfg->scbList[idx].epthru == NULL) { - printk (KERN_WARNING - "Can't allocate extended passthru for id %d\n", idx); - } - /* - * Allocate a 256 Byte Bounce Buffer for handling INQ/RD_CAPA - */ - megacfg->scbList[idx].bounce_buffer = pci_alloc_consistent (megacfg->dev, - 256, - &(megacfg->scbList[idx]. - dma_bounce_buffer)); - - if (!megacfg->scbList[idx].bounce_buffer) - printk - ("megaraid: allocation for bounce buffer failed\n"); - - megacfg->scbList[idx].dma_type = M_RD_DMA_TYPE_NONE; -#endif - - if (idx < MAX_COMMANDS) { - /* - * Link to free list - * lock not required since we are loading the driver, so no - * commands possible right now. - */ - enq_scb_freelist (megacfg, &megacfg->scbList[idx], - NO_LOCK, INTR_ENB); - - } - } - - return 0; -} - -/* - * Enqueues a SCB - */ -static void enq_scb_freelist (mega_host_config * megacfg, mega_scb * scb, int lock, - int intr) -{ - - if (lock == INTERNAL_LOCK || intr == INTR_DIS) { - if (intr == INTR_DIS) - spin_lock_irq (&megacfg->lock_free); - else - spin_lock (&megacfg->lock_free); - } - - scb->state = SCB_FREE; - scb->SCpnt = NULL; - - if (megacfg->qFreeH == (mega_scb *) NULL) { - megacfg->qFreeH = megacfg->qFreeT = scb; - } else { - megacfg->qFreeT->next = scb; - megacfg->qFreeT = scb; - } - - megacfg->qFreeT->next = NULL; - megacfg->qFcnt++; - - if (lock == INTERNAL_LOCK || intr == INTR_DIS) { - if (intr == INTR_DIS) - spin_unlock_irq (&megacfg->lock_free); - else - spin_unlock (&megacfg->lock_free); - } -} - -#if 0 /* XEN */ -/* - * Routines for the character/ioctl interface to the driver - */ -static int megadev_open (struct inode *inode, struct file *filep) -{ - MOD_INC_USE_COUNT; - return 0; /* success */ -} - -static int megadev_ioctl_entry (struct inode *inode, struct file *filep, - unsigned int cmd, unsigned long arg) -{ - int ret = -1; - - /* - * We do not allow parallel ioctls to the driver as of now. - */ -#if XEN_KILLED // XXX JWS killed the locking! - down (&mimd_entry_mtx); - ret = megadev_ioctl (inode, filep, cmd, arg); - up (&mimd_entry_mtx); -#else - ret = megadev_ioctl (inode, filep, cmd, arg); -#endif - - return ret; - -} - -static int megadev_ioctl (struct inode *inode, struct file *filep, - unsigned int cmd, unsigned long arg) -{ - int adapno; - kdev_t dev; - u32 inlen; - struct uioctl_t ioc; - char *kvaddr = NULL; - int nadap = numCtlrs; - u8 opcode; - u32 outlen; - int ret; - u8 subopcode; - Scsi_Cmnd *scsicmd; - struct Scsi_Host *shpnt; - char *uaddr; - struct uioctl_t *uioc; - dma_addr_t dma_addr; - u32 length; - mega_host_config *megacfg = NULL; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* 0x020400 */ - struct pci_dev pdev; - struct pci_dev *pdevp = &pdev; -#else - char *pdevp = NULL; -#endif - IO_LOCK_T; - - if (!inode || !(dev = inode->i_rdev)) - return -EINVAL; - - if (_IOC_TYPE (cmd) != MEGAIOC_MAGIC) - return (-EINVAL); - - /* - * Get the user ioctl structure - */ - ret = verify_area (VERIFY_WRITE, (char *) arg, sizeof (struct uioctl_t)); - - if (ret) - return ret; - - if(copy_from_user (&ioc, (char *) arg, sizeof (struct uioctl_t))) - return -EFAULT; - - /* - * The first call the applications should make is to find out the - * number of controllers in the system. The next logical call should - * be for getting the list of controllers in the system as detected - * by the driver. - */ - - /* - * Get the opcode and subopcode for the commands - */ - opcode = ioc.ui.fcs.opcode; - subopcode = ioc.ui.fcs.subopcode; - - switch (opcode) { - case M_RD_DRIVER_IOCTL_INTERFACE: - switch (subopcode) { - case MEGAIOC_QDRVRVER: /* Query driver version */ - put_user (driver_ver, (u32 *) ioc.data); - return 0; - - case MEGAIOC_QNADAP: /* Get # of adapters */ - put_user (nadap, (int *) ioc.data); - return nadap; - - case MEGAIOC_QADAPINFO: /* Get adapter information */ - /* - * which adapter? - */ - adapno = ioc.ui.fcs.adapno; - - /* - * The adapter numbers do not start with 0, at least in - * the user space. This is just to make sure, 0 is not the - * default value which will refer to adapter 1. So the - * user needs to make use of macros MKADAP() and GETADAP() - * (See megaraid.h) while making ioctl() call. - */ - adapno = GETADAP (adapno); - - if (adapno >= numCtlrs) - return (-ENODEV); - - ret = verify_area (VERIFY_WRITE, - ioc.data, - sizeof (struct mcontroller)); - if (ret) - return ret; - - /* - * Copy struct mcontroller to user area - */ - if (copy_to_user (ioc.data, - mcontroller + adapno, - sizeof (struct mcontroller))) - return -EFAULT; - return 0; - - default: - return (-EINVAL); - - } /* inner switch */ - break; - - case M_RD_IOCTL_CMD_NEW: - - /* - * Deletion of logical drives is only handled in 0x80 commands - */ - if( ioc.mbox[0] == FC_DEL_LOGDRV && ioc.mbox[2] == OP_DEL_LOGDRV ) { - return -EINVAL; - } - - /* which adapter? */ - adapno = ioc.ui.fcs.adapno; - - /* See comment above: MEGAIOC_QADAPINFO */ - adapno = GETADAP(adapno); - - if (adapno >= numCtlrs) - return(-ENODEV); - - length = ioc.ui.fcs.length; - - /* Check for zero length buffer or very large buffers */ - if( !length || length > 32*1024 ) - return -EINVAL; - - /* save the user address */ - uaddr = ioc.ui.fcs.buffer; - - /* - * For M_RD_IOCTL_CMD_NEW commands, the fields outlen and inlen of - * uioctl_t structure are treated as flags. If outlen is 1, the - * data is transferred from the device and if inlen is 1, the data - * is transferred to the device. - */ - outlen = ioc.outlen; - inlen = ioc.inlen; - - if(outlen) { - ret = verify_area(VERIFY_WRITE, (char *)ioc.ui.fcs.buffer, length); - if (ret) return ret; - } - if(inlen) { - ret = verify_area(VERIFY_READ, (char *) ioc.ui.fcs.buffer, length); - if (ret) return ret; - } - - /* - * Find this host - */ - for( shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next ) { - if( shpnt->hostdata == (unsigned long *)megaCtlrs[adapno] ) { - megacfg = (mega_host_config *)shpnt->hostdata; - break; - } - } - if(shpnt == NULL) return -ENODEV; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - scsicmd = (Scsi_Cmnd *)kmalloc(sizeof(Scsi_Cmnd), GFP_KERNEL|GFP_DMA); -#else - scsicmd = (Scsi_Cmnd *)scsi_init_malloc(sizeof(Scsi_Cmnd), - GFP_ATOMIC | GFP_DMA); -#endif - if(scsicmd == NULL) return -ENOMEM; - - memset(scsicmd, 0, sizeof(Scsi_Cmnd)); - scsicmd->host = shpnt; - - if( outlen || inlen ) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pdevp = &pdev; - memcpy(pdevp, megacfg->dev, sizeof(struct pci_dev)); - pdevp->dma_mask = 0xffffffff; -#else - pdevp = NULL; -#endif - kvaddr = dma_alloc_consistent(pdevp, length, &dma_addr); - - if( kvaddr == NULL ) { - printk(KERN_WARNING "megaraid:allocation failed\n"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /*0x20400 */ - kfree(scsicmd); -#else - scsi_init_free((char *)scsicmd, sizeof(Scsi_Cmnd)); -#endif - return -ENOMEM; - } - - ioc.ui.fcs.buffer = kvaddr; - - if (inlen) { - /* copyin the user data */ - copy_from_user(kvaddr, (char *)uaddr, length ); - } - } - - scsicmd->cmnd[0] = MEGADEVIOC; - scsicmd->request_buffer = (void *)&ioc; - -#if XEN_KILLED - init_MUTEX_LOCKED(&mimd_ioctl_sem); -#endif - - IO_LOCK; - megaraid_queue(scsicmd, megadev_ioctl_done); - - IO_UNLOCK; -#if XEN_KILLED - down(&mimd_ioctl_sem); -#endif - if( !scsicmd->result && outlen ) { - if (copy_to_user(uaddr, kvaddr, length)) - return -EFAULT; - } - - /* - * copyout the result - */ - uioc = (struct uioctl_t *)arg; - - if( ioc.mbox[0] == MEGA_MBOXCMD_PASSTHRU ) { - put_user( scsicmd->result, &uioc->pthru.scsistatus ); - if (copy_to_user( uioc->pthru.reqsensearea, scsicmd->sense_buffer, - MAX_REQ_SENSE_LEN )); - ret= -EFAULT; - } else { - put_user(1, &uioc->mbox[16]); /* numstatus */ - /* status */ - put_user (scsicmd->result, &uioc->mbox[17]); - } - - if (kvaddr) { - dma_free_consistent(pdevp, length, kvaddr, dma_addr); - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /*0x20400 */ - kfree (scsicmd); -#else - scsi_init_free((char *)scsicmd, sizeof(Scsi_Cmnd)); -#endif - - /* restore the user address */ - ioc.ui.fcs.buffer = uaddr; - - return ret; - - case M_RD_IOCTL_CMD: - /* which adapter? */ - adapno = ioc.ui.fcs.adapno; - - /* See comment above: MEGAIOC_QADAPINFO */ - adapno = GETADAP (adapno); - - if (adapno >= numCtlrs) - return (-ENODEV); - - /* save the user address */ - uaddr = ioc.data; - outlen = ioc.outlen; - inlen = ioc.inlen; - - if ((outlen >= IOCTL_MAX_DATALEN) || (inlen >= IOCTL_MAX_DATALEN)) - return (-EINVAL); - - if (outlen) { - ret = verify_area (VERIFY_WRITE, ioc.data, outlen); - if (ret) return ret; - } - if (inlen) { - ret = verify_area (VERIFY_READ, ioc.data, inlen); - if (ret) return ret; - } - - /* - * Find this host - */ - for( shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next ) { - if( shpnt->hostdata == (unsigned long *)megaCtlrs[adapno] ) { - megacfg = (mega_host_config *)shpnt->hostdata; - break; - } - } - if(shpnt == NULL) return -ENODEV; - - /* - * ioctls for deleting logical drives is a special case, so check - * for it first - */ - if( ioc.mbox[0] == FC_DEL_LOGDRV && ioc.mbox[2] == OP_DEL_LOGDRV ) { - - if( !megacfg->support_random_del ) { - printk("megaraid: logdrv delete on non supporting f/w.\n"); - return -EINVAL; - } - - uioc = (struct uioctl_t *)arg; - - ret = mega_del_logdrv(megacfg, ioc.mbox[3]); - - put_user(1, &uioc->mbox[16]); /* numstatus */ - put_user(ret, &uioc->mbox[17]); /* status */ - - /* if deletion failed, let the user know by failing ioctl */ - return ret; - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - scsicmd = (Scsi_Cmnd *)kmalloc(sizeof(Scsi_Cmnd), GFP_KERNEL|GFP_DMA); -#else - scsicmd = (Scsi_Cmnd *)scsi_init_malloc(sizeof(Scsi_Cmnd), - GFP_ATOMIC | GFP_DMA); -#endif - if(scsicmd == NULL) return -ENOMEM; - - memset(scsicmd, 0, sizeof(Scsi_Cmnd)); - scsicmd->host = shpnt; - - if (outlen || inlen) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pdevp = &pdev; - memcpy(pdevp, megacfg->dev, sizeof(struct pci_dev)); - pdevp->dma_mask = 0xffffffff; -#else - pdevp = NULL; -#endif - /* - * Allocate a page of kernel space. - */ - kvaddr = dma_alloc_consistent(pdevp, PAGE_SIZE, &dma_addr); - - if( kvaddr == NULL ) { - printk (KERN_WARNING "megaraid:allocation failed\n"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /*0x20400 */ - kfree(scsicmd); -#else - scsi_init_free((char *)scsicmd, sizeof(Scsi_Cmnd)); -#endif - return -ENOMEM; - } - - ioc.data = kvaddr; - - if (inlen) { - if (ioc.mbox[0] == MEGA_MBOXCMD_PASSTHRU) { - /* copyin the user data */ - copy_from_user (kvaddr, uaddr, ioc.pthru.dataxferlen); - } else { - copy_from_user (kvaddr, uaddr, inlen); - } - } - } - - scsicmd->cmnd[0] = MEGADEVIOC; - scsicmd->request_buffer = (void *) &ioc; - -#if XEN_KILLED - init_MUTEX_LOCKED (&mimd_ioctl_sem); -#endif - - IO_LOCK; - megaraid_queue (scsicmd, megadev_ioctl_done); - - IO_UNLOCK; -#if XEN_KILLED - down (&mimd_ioctl_sem); -#endif - - if (!scsicmd->result && outlen) { - if (ioc.mbox[0] == MEGA_MBOXCMD_PASSTHRU) { - if (copy_to_user (uaddr, kvaddr, ioc.pthru.dataxferlen)) - ret = -EFAULT; - } else { - if (copy_to_user (uaddr, kvaddr, outlen)) - ret = -EFAULT; - } - } - - /* - * copyout the result - */ - uioc = (struct uioctl_t *) arg; - - if (ioc.mbox[0] == MEGA_MBOXCMD_PASSTHRU) { - put_user (scsicmd->result, &uioc->pthru.scsistatus); - - /* - * If scsicmd->result is 0x02 (CHECK CONDITION) then copy the - * SCSI sense data into user area - */ - if (copy_to_user( uioc->pthru.reqsensearea, scsicmd->sense_buffer, - MAX_REQ_SENSE_LEN )) - ret = -EFAULT; - - } else { - put_user (1, &uioc->mbox[16]); /* numstatus */ - put_user (scsicmd->result, &uioc->mbox[17]); /* status */ - } - - if (kvaddr) { - dma_free_consistent(pdevp, PAGE_SIZE, kvaddr, dma_addr ); - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - kfree (scsicmd); -#else - scsi_init_free((char *)scsicmd, sizeof(Scsi_Cmnd)); -#endif - - /* restore user pointer */ - ioc.data = uaddr; - - return ret; - - default: - return (-EINVAL); - - }/* Outer switch */ - - return 0; -} - -static void -megadev_ioctl_done(Scsi_Cmnd *sc) -{ - up (&mimd_ioctl_sem); -} -#endif /* 0 (XEN) */ - -static mega_scb * -megadev_doioctl (mega_host_config * megacfg, Scsi_Cmnd * sc) -{ - u8 cmd; - struct uioctl_t *ioc = NULL; - mega_mailbox *mbox = NULL; - mega_ioctl_mbox *mboxioc = NULL; - struct mbox_passthru *mboxpthru = NULL; - mega_scb *scb = NULL; - mega_passthru *pthru = NULL; - - if ((scb = mega_allocateSCB (megacfg, sc)) == NULL) { - sc->result = (DID_ERROR << 16); - callDone (sc); - return NULL; - } - - ioc = (struct uioctl_t *) sc->request_buffer; - - memcpy (scb->mboxData, ioc->mbox, sizeof (scb->mboxData)); - - /* The generic mailbox */ - mbox = (mega_mailbox *) ioc->mbox; - - /* - * Get the user command - */ - cmd = ioc->mbox[0]; - - switch (cmd) { - case MEGA_MBOXCMD_PASSTHRU: - /* - * prepare the SCB with information from the user ioctl structure - */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pthru = scb->pthru; -#else - pthru = &scb->pthru; -#endif - memcpy (pthru, &ioc->pthru, sizeof (mega_passthru)); - mboxpthru = (struct mbox_passthru *) scb->mboxData; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - if (megacfg->flag & BOARD_64BIT) { - /* This is just a sample with one element - * This if executes onlu on 2.4 kernels - */ - mboxpthru->dataxferaddr = scb->dma_passthruhandle64; - scb->sg64List[0].address = - pci_map_single (megacfg->dev, - ioc->data, - 4096, PCI_DMA_BIDIRECTIONAL); - scb->sg64List[0].length = 4096; // TODO: Check this - pthru->dataxferaddr = scb->dma_sghandle64; - pthru->numsgelements = 1; - mboxpthru->cmd = MEGA_MBOXCMD_PASSTHRU64; - } else { - mboxpthru->dataxferaddr = scb->dma_passthruhandle64; - pthru->dataxferaddr = - pci_map_single (megacfg->dev, - ioc->data, - 4096, PCI_DMA_BIDIRECTIONAL); - pthru->numsgelements = 0; - } - -#else - { - mboxpthru->dataxferaddr = virt_to_bus (&scb->pthru); - pthru->dataxferaddr = virt_to_bus (ioc->data); - pthru->numsgelements = 0; - } -#endif - - pthru->reqsenselen = 14; - break; - - default: /* Normal command */ - mboxioc = (mega_ioctl_mbox *) scb->mboxData; - - if (ioc->ui.fcs.opcode == M_RD_IOCTL_CMD_NEW) { - scb->buff_ptr = ioc->ui.fcs.buffer; - scb->iDataSize = ioc->ui.fcs.length; - } else { - scb->buff_ptr = ioc->data; - scb->iDataSize = 4096; // TODO:check it - } - - set_mbox_xfer_addr (megacfg, scb, mboxioc, FROMTO_DEVICE); - mboxioc->numsgelements = 0; - break; - } - - return scb; -} - -#if 0 -static int -megadev_close (struct inode *inode, struct file *filep) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif - return 0; -} -#endif /* 0 */ - - -static int -mega_support_ext_cdb(mega_host_config *this_hba) -{ - mega_mailbox *mboxpnt; - unsigned char mbox[16]; - int ret; - - mboxpnt = (mega_mailbox *) mbox; - - memset(mbox, 0, sizeof (mbox)); - /* - * issue command to find out if controller supports extended CDBs. - */ - mbox[0] = 0xA4; - mbox[2] = 0x16; - - ret = megaIssueCmd(this_hba, mbox, NULL, 0); - - return !ret; -} - - -/* - * Find out if this controller supports random deletion and addition of - * logical drives - */ -static int -mega_support_random_del(mega_host_config *this_hba) -{ -#if XEN_KILLED - mega_mailbox *mboxpnt; - unsigned char mbox[16]; - int ret; - - mboxpnt = (mega_mailbox *)mbox; - - memset(mbox, 0, sizeof(mbox)); - - /* - * issue command - */ - mbox[0] = FC_DEL_LOGDRV; - mbox[2] = OP_SUP_DEL_LOGDRV; - - ret = megaIssueCmd(this_hba, mbox, NULL, 0); - - return !ret; -#endif - return 0; // no support for random deletions -} - -#if 0 /* XEN */ -static int -mega_del_logdrv(mega_host_config *this_hba, int logdrv) -{ - int rval; - IO_LOCK_T; - DECLARE_WAIT_QUEUE_HEAD(wq); - mega_scb *scbp; - - /* - * Stop sending commands to the controller, queue them internally. - * When deletion is complete, ISR will flush the queue. - */ - IO_LOCK; - this_hba->quiescent = 1; - IO_UNLOCK; - - while( this_hba->qPcnt ) { - sleep_on_timeout( &wq, 1*HZ ); /* sleep for 1s */ - } - rval = mega_do_del_logdrv(this_hba, logdrv); - - IO_LOCK; - /* - * Attach the internal queue to the pending queue - */ - if( this_hba->qPendingH == NULL ) { - /* - * If pending queue head is null, make internal queue as - * pending queue - */ - this_hba->qPendingH = this_hba->int_qh; - this_hba->qPendingT = this_hba->int_qt; - this_hba->qPcnt = this_hba->int_qlen; - } - else { - /* - * Append pending queue to internal queue - */ - if( this_hba->int_qt ) { - this_hba->int_qt->next = this_hba->qPendingH; - - this_hba->qPendingH = this_hba->int_qh; - this_hba->qPcnt += this_hba->int_qlen; - } - } - - this_hba->int_qh = this_hba->int_qt = NULL; - this_hba->int_qlen = 0; - - /* - * If delete operation was successful, add 0x80 to the logical drive - * ids for commands in the pending queue. - */ - if( this_hba->read_ldidmap) { - for( scbp = this_hba->qPendingH; scbp; scbp = scbp->next ) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - if( scbp->pthru->logdrv < 0x80 ) - scbp->pthru->logdrv += 0x80; -#else - if( scbp->pthru.logdrv < 0x80 ) - scbp->pthru.logdrv += 0x80; -#endif - } - } - this_hba->quiescent = 0; - - IO_UNLOCK; - - return rval; -} - -static int -mega_do_del_logdrv(mega_host_config *this_hba, int logdrv) -{ - mega_mailbox *mboxpnt; - unsigned char mbox[16]; - int rval; - - mboxpnt = (mega_mailbox *)mbox; - - memset(mbox, 0, sizeof(mbox)); - - mbox[0] = FC_DEL_LOGDRV; - mbox[2] = OP_DEL_LOGDRV; - mbox[3] = logdrv; - - rval = megaIssueCmd(this_hba, mbox, NULL, 0); - - /* log this event */ - if( rval != 0 ) { - printk("megaraid: Attempt to delete logical drive %d failed.", - logdrv); - return rval; - } - - printk("megaraid: logical drive %d deleted.\n", logdrv); - - /* - * After deleting first logical drive, the logical drives must be - * addressed by adding 0x80 to the logical drive id. - */ - this_hba->read_ldidmap = 1; - - return rval; -} -#endif /* 0 (XEN) */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -void * -dma_alloc_consistent(void *dev, size_t size, dma_addr_t *dma_addr) -{ - void *_tv; - int npages; - int order = 0; - - /* - * How many pages application needs - */ - npages = size / PAGE_SIZE; - - /* Do we need one more page */ - if(size % PAGE_SIZE) - npages++; - - order = mega_get_order(npages); - - _tv = (void *)__get_free_pages(GFP_DMA, order); - - if( _tv != NULL ) { - memset(_tv, 0, size); - *(dma_addr) = virt_to_bus(_tv); - } - - return _tv; -} - -/* - * int mega_get_order(int) - * - * returns the order to be used as 2nd argument to __get_free_pages() - which - * return pages equal to pow(2, order) - AM - */ -int -mega_get_order(int n) -{ - int i = 0; - - while( pow_2(i++) < n ) - ; /* null statement */ - - return i-1; -} - -/* - * int pow_2(int) - * - * calculates pow(2, i) - */ -int -pow_2(int i) -{ - unsigned int v = 1; - - while(i--) - v <<= 1; - - return v; -} - -void -dma_free_consistent(void *dev, size_t size, void *vaddr, dma_addr_t dma_addr) -{ - int npages; - int order = 0; - - npages = size / PAGE_SIZE; - - if(size % PAGE_SIZE) - npages++; - - if (npages == 1) - order = 0; - else if (npages == 2) - order = 1; - else if (npages <= 4) - order = 2; - else - order = 3; - - free_pages((unsigned long)vaddr, order); - -} -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -static -#endif /* LINUX VERSION 2.4.XX */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) || defined(MODULE) -Scsi_Host_Template driver_template = MEGARAID; - -#include "scsi_module.c.inc" -#endif /* LINUX VERSION 2.4.XX || MODULE */ - -/* vi: set ts=4: */ diff --git a/xen/drivers/scsi/megaraid.h b/xen/drivers/scsi/megaraid.h deleted file mode 100644 index 48e7dd6a9f..0000000000 --- a/xen/drivers/scsi/megaraid.h +++ /dev/null @@ -1,1049 +0,0 @@ -#ifndef __MEGARAID_H__ -#define __MEGARAID_H__ - -#include - -/* - * For state flag. Do not use LSB(8 bits) which are - * reserved for storing info about channels. - */ -#define IN_ISR 0x80000000L -#define IN_ABORT 0x40000000L -#define IN_RESET 0x20000000L -#define IN_QUEUE 0x10000000L -#define BOARD_QUARTZ 0x08000000L -#define BOARD_40LD 0x04000000L -#define BOARD_64BIT 0x02000000L - -#define SCB_FREE 0x0 -#define SCB_ACTIVE 0x1 -#define SCB_WAITQ 0x2 -#define SCB_ISSUED 0x3 -#define SCB_COMPLETE 0x4 -#define SCB_ABORTED 0x5 -#define SCB_RESET 0x6 - -#define M_RD_CRLFSTR "\n" -#define M_RD_IOCTL_CMD 0x80 -#define M_RD_IOCTL_CMD_NEW 0x81 -#define M_RD_DRIVER_IOCTL_INTERFACE 0x82 - -#define MEGARAID_VERSION "v1.18d (Release Date: Wed Aug 7 18:51:51 EDT 2002)\n" - -#define MEGARAID_IOCTL_VERSION 114 - -/* Methods */ -#define GET_DRIVER_INFO 0x1 - -#define MEGA_CMD_TIMEOUT 10 - -/* Feel free to fiddle with these.. max values are: - SGLIST 0..26 - COMMANDS 0..253 - CMDPERLUN 0..63 -*/ - -#define MAX_SGLIST 0x1A -#define MAX_COMMANDS 127 -#define MAX_CMD_PER_LUN 63 -#define MAX_FIRMWARE_STATUS 46 - -#define MAX_LOGICAL_DRIVES 8 -#define MAX_CHANNEL 5 -#define MAX_TARGET 15 -#define MAX_PHYSICAL_DRIVES MAX_CHANNEL*MAX_TARGET - -#define INQUIRY_DATA_SIZE 0x24 -#define MAX_CDB_LEN 0x0A -#define MAX_REQ_SENSE_LEN 0x20 - -#define INTR_VALID 0x40 - -/* Direction Macros for MBOX Data direction */ -#define TO_DEVICE 0x0 -#define FROM_DEVICE 0x1 -#define FROMTO_DEVICE 0x2 - -/* Mailbox commands */ -#define MEGA_MBOXCMD_LREAD 0x01 -#define MEGA_MBOXCMD_LWRITE 0x02 -#define MEGA_MBOXCMD_LREAD64 0xA7 -#define MEGA_MBOXCMD_LWRITE64 0xA8 -#define MEGA_MBOXCMD_PASSTHRU 0x03 -#define MEGA_MBOXCMD_EXTPASSTHRU 0xE3 -#define MEGA_MBOXCMD_PASSTHRU64 0xC3 -#define MEGA_MBOXCMD_ADAPTERINQ 0x05 - - -/* Offsets into Mailbox */ -#define COMMAND_PORT 0x00 -#define COMMAND_ID_PORT 0x01 -#define SG_LIST_PORT0 0x08 -#define SG_LIST_PORT1 0x09 -#define SG_LIST_PORT2 0x0a -#define SG_LIST_PORT3 0x0b -#define SG_ELEMENT_PORT 0x0d -#define NO_FIRED_PORT 0x0f - -/* I/O Port offsets */ -#define I_CMD_PORT 0x00 -#define I_ACK_PORT 0x00 -#define I_TOGGLE_PORT 0x01 -#define INTR_PORT 0x0a - -#define MAILBOX_SIZE (sizeof(mega_mailbox)-16) -#define MBOX_BUSY_PORT 0x00 -#define MBOX_PORT0 0x04 -#define MBOX_PORT1 0x05 -#define MBOX_PORT2 0x06 -#define MBOX_PORT3 0x07 -#define ENABLE_MBOX_REGION 0x0B - -/* I/O Port Values */ -#define ISSUE_BYTE 0x10 -#define ACK_BYTE 0x08 -#define ENABLE_INTR_BYTE 0xc0 -#define DISABLE_INTR_BYTE 0x00 -#define VALID_INTR_BYTE 0x40 -#define MBOX_BUSY_BYTE 0x10 -#define ENABLE_MBOX_BYTE 0x00 - -/* Setup some port macros here */ -#define WRITE_MAILBOX(base,offset,value) *(base+offset)=value -#define READ_MAILBOX(base,offset) *(base+offset) - -#define WRITE_PORT(base,offset,value) outb_p(value,base+offset) -#define READ_PORT(base,offset) inb_p(base+offset) - -#define ISSUE_COMMAND(base) WRITE_PORT(base,I_CMD_PORT,ISSUE_BYTE) -#define CLEAR_INTR(base) WRITE_PORT(base,I_ACK_PORT,ACK_BYTE) -#define ENABLE_INTR(base) WRITE_PORT(base,I_TOGGLE_PORT,ENABLE_INTR_BYTE) -#define DISABLE_INTR(base) WRITE_PORT(base,I_TOGGLE_PORT,DISABLE_INTR_BYTE) - -#ifndef PCI_VENDOR_ID_LSI_LOGIC -#define PCI_VENDOR_ID_LSI_LOGIC 0x1000 -#endif - -/* Define AMI's PCI codes */ -#ifndef PCI_VENDOR_ID_AMI -#define PCI_VENDOR_ID_AMI 0x101E -#endif - -#ifndef PCI_DEVICE_ID_AMI_MEGARAID -#define PCI_DEVICE_ID_AMI_MEGARAID 0x9010 -#endif - -#ifndef PCI_DEVICE_ID_AMI_MEGARAID2 -#define PCI_DEVICE_ID_AMI_MEGARAID2 0x9060 -#endif - -#ifndef PCI_DEVICE_ID_AMI_MEGARAID3 -#define PCI_DEVICE_ID_AMI_MEGARAID3 0x1960 -#endif - -#define PCI_VENDOR_ID_DISCOVERY 0x1028 -#define PCI_DEVICE_ID_DISCOVERY 0x000E - -#define PCI_VENDOR_ID_PERC4_DI_YSTONE 0x1028 -#define PCI_DEVICE_ID_PERC4_DI_YSTONE 0x000F - -#define PCI_VENDOR_ID_PERC4_QC_VERDE 0x1000 -#define PCI_DEVICE_ID_PERC4_QC_VERDE 0x0407 - -/* Special Adapter Commands */ -#define FW_FIRE_WRITE 0x2C -#define FW_FIRE_FLASH 0x2D - -#define FC_NEW_CONFIG 0xA1 -#define DCMD_FC_CMD 0xA1 -#define DCMD_FC_PROCEED 0x02 -#define DCMD_DELETE_LOGDRV 0x03 -#define DCMD_FC_READ_NVRAM_CONFIG 0x04 -#define DCMD_FC_READ_NVRAM_CONFIG_64 0xC0 -#define DCMD_FC_READ_FINAL_CONFIG 0x05 -#define DCMD_GET_DISK_CONFIG 0x06 -#define DCMD_GET_DISK_CONFIG_64 0xC2 -#define DCMD_CHANGE_LDNO 0x07 -#define DCMD_COMPACT_CONFIG 0x08 -#define DCMD_DELETE_DRIVEGROUP 0x09 -#define DCMD_GET_LOOPID_INFO 0x0A -#define DCMD_CHANGE_LOOPID 0x0B -#define DCMD_GET_NUM_SCSI_CHANS 0x0C -#define DCMD_WRITE_CONFIG 0x0D -#define DCMD_WRITE_CONFIG_64 0xC1 - -#define NC_SUBOP_PRODUCT_INFO 0x0E -#define NC_SUBOP_ENQUIRY3 0x0F -#define ENQ3_GET_SOLICITED_NOTIFY_ONLY 0x01 -#define ENQ3_GET_SOLICITED_FULL 0x02 -#define ENQ3_GET_UNSOLICITED 0x03 - -#define PCI_CONF_BASE_ADDR_OFFSET 0x10 -#define PCI_CONF_IRQ_OFFSET 0x3c -#define PCI_CONF_AMISIG 0xa0 -#define PCI_CONF_AMISIG64 0xa4 - -/* Sub-System Vendor ID sorted on alphabetical order*/ -#define LSI_SUBSYS_ID 0x1000 -#define AMI_SUBSYS_ID 0x101E -#define DELL_SUBSYS_ID 0x1028 -#define HP_SUBSYS_ID 0x103C - -#define AMI_SIGNATURE 0x3344 -#define AMI_SIGNATURE_471 0xCCCC -#define AMI_64BIT_SIGNATURE 0x0299 - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) /*0x20100 */ -#define MEGARAID \ - { NULL, /* Next */\ - NULL, /* Usage Count Pointer */\ - NULL, /* proc Directory Entry */\ - megaraid_proc_info, /* proc Info Function */\ - "MegaRAID", /* Driver Name */\ - megaraid_detect, /* Detect Host Adapter */\ - megaraid_release, /* Release Host Adapter */\ - megaraid_info, /* Driver Info Function */\ - megaraid_command, /* Command Function */\ - megaraid_queue, /* Queue Command Function */\ - megaraid_abort, /* Abort Command Function */\ - megaraid_reset, /* Reset Command Function */\ - NULL, /* Slave Attach Function */\ - megaraid_biosparam, /* Disk BIOS Parameters */\ - MAX_COMMANDS, /* # of cmds that can be\ - outstanding at any time */\ - 7, /* HBA Target ID */\ - MAX_SGLIST, /* Scatter/Gather Table Size */\ - MAX_CMD_PER_LUN, /* SCSI Commands per LUN */\ - 0, /* Present */\ - 0, /* Default Unchecked ISA DMA */\ - ENABLE_CLUSTERING } /* Enable Clustering */ -#else -#define MEGARAID \ - {\ - name: "MegaRAID", /* Driver Name */\ - detect: megaraid_detect, /* Detect Host Adapter */\ - release: megaraid_release, /* Release Host Adapter */\ - info: megaraid_info, /* Driver Info Function */\ - command: NULL, /* XEN KILLED */\ - queuecommand: megaraid_queue, /* Queue Command Function */\ - abort: megaraid_abort, /* Abort Command Function */\ - reset: megaraid_reset, /* Reset Command Function */\ - bios_param: megaraid_biosparam, /* Disk BIOS Parameters */\ - can_queue: MAX_COMMANDS, /* Can Queue */\ - this_id: 7, /* HBA Target ID */\ - sg_tablesize: MAX_SGLIST, /* Scatter/Gather Table Size */\ - cmd_per_lun: MAX_CMD_PER_LUN, /* SCSI Commands per LUN */\ - present: 0, /* Present */\ - unchecked_isa_dma: 0, /* Default Unchecked ISA DMA */\ - use_clustering: ENABLE_CLUSTERING, /* Enable Clustering */\ - use_new_eh_code: 1, /* Uses new error handling code */\ - } -#endif -// XEN: REMOVED command: megaraid_command, /* Command Function */ -// XEN: REMOVED proc_info: megaraid_proc_info, /* /proc driver info */ -// XEN: REMOVED highmem_io: 1, /* enable HIGHMEM I/O */ - - -/*********************************************************************** - * Structure Declarations for the Firmware supporting 40 Logical Drives - * and 256 Physical Drives. - ***********************************************************************/ - -#define FC_MAX_LOGICAL_DRIVES 40 -#define FC_MAX_LOG_DEVICES FC_MAX_LOGICAL_DRIVES -#define FC_MAX_SPAN_DEPTH 8 -#define FC_MAX_ROW_SIZE 32 - -#define FC_MAX_CHANNELS 16 -#define FC_MAX_TARGETS_PER_CHANNEL 16 -#define FC_MAX_PHYSICAL_DEVICES 256 - -/******************************************** - * PRODUCT_INFO - ********************************************/ - -#define SIG_40LOG_32STR_8SPN 0x00282008 - -/* - * Utilities declare this strcture size as 1024 bytes. So more fields can - * be added in future. - */ - -struct MRaidProductInfo { - u32 DataSize; /* current size in bytes (not including resvd) */ - u32 ConfigSignature; - /* Current value is 0x00282008 - * 0x28=MAX_LOGICAL_DRIVES, - * 0x20=Number of stripes and - * 0x08=Number of spans */ - u8 FwVer[16]; /* printable ASCI string */ - u8 BiosVer[16]; /* printable ASCI string */ - u8 ProductName[80]; /* printable ASCI string */ - - u8 MaxConcCmds; /* Max. concurrent commands supported */ - u8 SCSIChanPresent; /* Number of SCSI Channels detected */ - u8 FCLoopPresent; /* Number of Fibre Loops detected */ - u8 memType; /* EDO, FPM, SDRAM etc */ - - u32 signature; - u16 DramSize; /* In terms of MB */ - u16 subSystemID; - - u16 subSystemVendorID; - u8 numNotifyCounters; - u8 pad1k[889]; /* 135 + 889 resvd = 1024 total size */ -} __attribute__ ((packed)); -typedef struct MRaidProductInfo megaRaidProductInfo; - -/******************************************** - * Standard ENQUIRY - ********************************************/ -struct FC_ADP_INFO { - u8 MaxConcCmds; /* Max. concurrent commands supported. */ - u8 RbldRate; /* Rebuild Rate. Varies from 0%-100% */ - u8 MaxTargPerChan; /* Max. Targets supported per chan. */ - u8 ChanPresent; /* No. of Chans present on this adapter. */ - u8 FwVer[4]; /* Firmware version. */ - u16 AgeOfFlash; /* No. of times FW has been downloaded. */ - u8 ChipSetValue; /* Contents of 0xC0000832 */ - u8 DramSize; /* In terms of MB */ - u8 CacheFlushInterval; /* In terms of Seconds */ - u8 BiosVersion[4]; - u8 BoardType; - u8 sense_alert; - u8 write_config_count; /* Increase with evry configuration change */ - u8 drive_inserted_count;/* Increase with every drive inserted */ - u8 inserted_drive; /* Channel: Id of inserted drive */ - u8 battery_status; - /* - BIT 0 : battery module missing - BIT 1 : VBAD - BIT 2 : temp high - BIT 3 : battery pack missing - BIT 4,5 : 00 - charge complete - 01 - fast charge in prog - 10 - fast charge fail - 11 - undefined - BIt 6 : counter > 1000 - Bit 7 : undefined - */ - u8 dec_fault_bus_info; /* was resvd */ -} __attribute__ ((packed)); - -struct FC_LDRV_INFO { - u8 NumLDrv; /* No. of Log. Drvs configured. */ - u8 recon_state[FC_MAX_LOGICAL_DRIVES / 8]; - /* bit field for State of reconstruct */ - u16 LDrvOpStatus[FC_MAX_LOGICAL_DRIVES / 8]; - /* bit field Status of Long Operations. */ - - u32 LDrvSize[FC_MAX_LOGICAL_DRIVES]; /* Size of each log. Drv. */ - u8 LDrvProp[FC_MAX_LOGICAL_DRIVES]; - u8 LDrvState[FC_MAX_LOGICAL_DRIVES]; /* State of Logical Drives. */ -} __attribute__ ((packed)); - -#define PREVSTAT_MASK 0xf0 -#define CURRSTAT_MASK 0x0f - -struct FC_PDRV_INFO { - u8 PDrvState[FC_MAX_PHYSICAL_DEVICES]; /* State of Phys Drvs. */ -} __attribute__ ((packed)); - -struct FC_AdapterInq { - struct FC_ADP_INFO AdpInfo; - struct FC_LDRV_INFO LogdrvInfo; - struct FC_PDRV_INFO PhysdrvInfo; -} __attribute__ ((packed)); - -typedef struct FC_AdapterInq mega_RAIDINQ_FC; - -/******************************************** - * NOTIFICATION - ********************************************/ - -#define MAX_NOTIFY_SIZE 0x80 -#define CUR_NOTIFY_SIZE sizeof(struct MegaRAID_Notify) - -/* - * Utilities declare this strcture size as ?? bytes. So more fields can - * be added in future. - */ -struct MegaRAID_Notify { - u32 globalCounter; /* Any change increments this counter */ - - u8 paramCounter; /* Indicates any params changed */ - u8 paramId; /* Param modified - defined below */ - u16 paramVal; /* New val of last param modified */ - - u8 writeConfigCounter; /* write config occurred */ - u8 writeConfigRsvd[3]; - - u8 ldrvOpCounter; /* Indicates ldrv op started/completed */ - u8 ldrvOpId; /* ldrv num */ - u8 ldrvOpCmd; /* ldrv operation - defined below */ - u8 ldrvOpStatus; /* status of the operation */ - - u8 ldrvStateCounter; /* Indicates change of ldrv state */ - u8 ldrvStateId; /* ldrv num */ - u8 ldrvStateNew; /* New state */ - u8 ldrvStateOld; /* old state */ - - u8 pdrvStateCounter; /* Indicates change of ldrv state */ - u8 pdrvStateId; /* pdrv id */ - u8 pdrvStateNew; /* New state */ - u8 pdrvStateOld; /* old state */ - - u8 pdrvFmtCounter; /* Indicates pdrv format started/over */ - u8 pdrvFmtId; /* pdrv id */ - u8 pdrvFmtVal; /* format started/over */ - u8 pdrvFmtRsvd; - - u8 targXferCounter; /* Indicates SCSI-2 Xfer rate change */ - u8 targXferId; /* pdrv Id */ - u8 targXferVal; /* new Xfer params of last pdrv */ - u8 targXferRsvd; - - u8 fcLoopIdChgCounter; /* Indicates loopid changed */ - u8 fcLoopIdPdrvId; /* pdrv id */ - u8 fcLoopId0; /* loopid on fc loop 0 */ - u8 fcLoopId1; /* loopid on fc loop 1 */ - - u8 fcLoopStateCounter; /* Indicates loop state changed */ - u8 fcLoopState0; /* state of fc loop 0 */ - u8 fcLoopState1; /* state of fc loop 1 */ - u8 fcLoopStateRsvd; -} __attribute__ ((packed)); - -/******************************************** - * PARAM IDs in Notify struct - ********************************************/ -#define PARAM_RBLD_RATE 0x01 - /*-------------------------------------- - * Param val = - * byte 0: new rbld rate - *--------------------------------------*/ -#define PARAM_CACHE_FLUSH_INTERVAL 0x02 - /*-------------------------------------- - * Param val = - * byte 0: new cache flush interval - *--------------------------------------*/ -#define PARAM_SENSE_ALERT 0x03 - /*-------------------------------------- - * Param val = - * byte 0: last pdrv id causing chkcond - *--------------------------------------*/ -#define PARAM_DRIVE_INSERTED 0x04 - /*-------------------------------------- - * Param val = - * byte 0: last pdrv id inserted - *--------------------------------------*/ -#define PARAM_BATTERY_STATUS 0x05 - /*-------------------------------------- - * Param val = - * byte 0: battery status - *--------------------------------------*/ - -/******************************************** - * Ldrv operation cmd in Notify struct - ********************************************/ -#define LDRV_CMD_CHKCONSISTANCY 0x01 -#define LDRV_CMD_INITIALIZE 0x02 -#define LDRV_CMD_RECONSTRUCTION 0x03 - -/******************************************** - * Ldrv operation status in Notify struct - ********************************************/ -#define LDRV_OP_SUCCESS 0x00 -#define LDRV_OP_FAILED 0x01 -#define LDRV_OP_ABORTED 0x02 -#define LDRV_OP_CORRECTED 0x03 -#define LDRV_OP_STARTED 0x04 - -/******************************************** - * Raid Logical drive states. - ********************************************/ -#define RDRV_OFFLINE 0 -#define RDRV_DEGRADED 1 -#define RDRV_OPTIMAL 2 -#define RDRV_DELETED 3 - -/******************************************* - * Physical drive states. - *******************************************/ -#define PDRV_UNCNF 0 -#define PDRV_ONLINE 3 -#define PDRV_FAILED 4 -#define PDRV_RBLD 5 - -/******************************************* - * Formal val in Notify struct - *******************************************/ -#define PDRV_FMT_START 0x01 -#define PDRV_FMT_OVER 0x02 - -/******************************************** - * FC Loop State in Notify Struct - ********************************************/ -#define ENQ_FCLOOP_FAILED 0 -#define ENQ_FCLOOP_ACTIVE 1 -#define ENQ_FCLOOP_TRANSIENT 2 - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -#define M_RD_DMA_TYPE_NONE 0xFFFF -#define M_RD_PTHRU_WITH_BULK_DATA 0x0001 -#define M_RD_PTHRU_WITH_SGLIST 0x0002 -#define M_RD_BULK_DATA_ONLY 0x0004 -#define M_RD_SGLIST_ONLY 0x0008 -#define M_RD_EPTHRU_WITH_BULK_DATA 0x0010 -#endif -/******************************************** - * ENQUIRY3 - ********************************************/ -/* - * Utilities declare this strcture size as 1024 bytes. So more fields can - * be added in future. - */ -struct MegaRAID_Enquiry3 { - u32 dataSize; /* current size in bytes (not including resvd) */ - - struct MegaRAID_Notify notify; - - u8 notifyRsvd[MAX_NOTIFY_SIZE - CUR_NOTIFY_SIZE]; - - u8 rbldRate; /* Rebuild rate (0% - 100%) */ - u8 cacheFlushInterval; /* In terms of Seconds */ - u8 senseAlert; - u8 driveInsertedCount; /* drive insertion count */ - - u8 batteryStatus; - u8 numLDrv; /* No. of Log Drives configured */ - u8 reconState[FC_MAX_LOGICAL_DRIVES / 8]; /* State of reconstruct */ - u16 lDrvOpStatus[FC_MAX_LOGICAL_DRIVES / 8]; /* log. Drv Status */ - - u32 lDrvSize[FC_MAX_LOGICAL_DRIVES]; /* Size of each log. Drv */ - u8 lDrvProp[FC_MAX_LOGICAL_DRIVES]; - u8 lDrvState[FC_MAX_LOGICAL_DRIVES]; /* State of Logical Drives */ - u8 pDrvState[FC_MAX_PHYSICAL_DEVICES]; /* State of Phys. Drvs. */ - u16 physDrvFormat[FC_MAX_PHYSICAL_DEVICES / 16]; - - u8 targXfer[80]; /* phys device transfer rate */ - u8 pad1k[263]; /* 761 + 263reserved = 1024 bytes total size */ -} __attribute__ ((packed)); -typedef struct MegaRAID_Enquiry3 mega_Enquiry3; - -/* Structures */ -typedef struct _mega_ADP_INFO { - u8 MaxConcCmds; - u8 RbldRate; - u8 MaxTargPerChan; - u8 ChanPresent; - u8 FwVer[4]; - u16 AgeOfFlash; - u8 ChipSetValue; - u8 DramSize; - u8 CacheFlushInterval; - u8 BiosVer[4]; - u8 resvd[7]; -} mega_ADP_INFO; - -typedef struct _mega_LDRV_INFO { - u8 NumLDrv; - u8 resvd[3]; - u32 LDrvSize[MAX_LOGICAL_DRIVES]; - u8 LDrvProp[MAX_LOGICAL_DRIVES]; - u8 LDrvState[MAX_LOGICAL_DRIVES]; -} mega_LDRV_INFO; - -typedef struct _mega_PDRV_INFO { - u8 PDrvState[MAX_PHYSICAL_DRIVES]; - u8 resvd; -} mega_PDRV_INFO; - -/* RAID inquiry: Mailbox command 0x5*/ -typedef struct _mega_RAIDINQ { - mega_ADP_INFO AdpInfo; - mega_LDRV_INFO LogdrvInfo; - mega_PDRV_INFO PhysdrvInfo; -} mega_RAIDINQ; - -/* Passthrough command: Mailbox command 0x3*/ -typedef struct mega_passthru { - u8 timeout:3; /* 0=6sec/1=60sec/2=10min/3=3hrs */ - u8 ars:1; - u8 reserved:3; - u8 islogical:1; - u8 logdrv; /* if islogical == 1 */ - u8 channel; /* if islogical == 0 */ - u8 target; /* if islogical == 0 */ - u8 queuetag; /* unused */ - u8 queueaction; /* unused */ - u8 cdb[MAX_CDB_LEN]; - u8 cdblen; - u8 reqsenselen; - u8 reqsensearea[MAX_REQ_SENSE_LEN]; - u8 numsgelements; - u8 scsistatus; - u32 dataxferaddr; - u32 dataxferlen; -} mega_passthru; - -/* - * Extended passthru: support CDB > 10 bytes - */ -typedef struct { - u8 timeout:3; /* 0=6sec/1=60sec/2=10min/3=3hrs */ - u8 ars:1; - u8 rsvd1:1; - u8 cd_rom:1; - u8 rsvd2:1; - u8 islogical:1; - - u8 logdrv; /* if islogical == 1 */ - u8 channel; /* if islogical == 0 */ - u8 target; /* if islogical == 0 */ - - u8 queuetag; /* unused */ - u8 queueaction; /* unused */ - - u8 cdblen; - u8 rsvd3; - u8 cdb[16]; - - u8 numsgelements; - u8 status; - u8 reqsenselen; - u8 reqsensearea[MAX_REQ_SENSE_LEN]; - u8 rsvd4; - - u32 dataxferaddr; - u32 dataxferlen; -}mega_ext_passthru; - -struct _mega_mailbox { - /* 0x0 */ u8 cmd; - /* 0x1 */ u8 cmdid; - /* 0x2 */ u16 numsectors; - /* 0x4 */ u32 lba; - /* 0x8 */ u32 xferaddr; - /* 0xC */ u8 logdrv; - /* 0xD */ u8 numsgelements; - /* 0xE */ u8 resvd; - /* 0xF */ u8 busy; - /* 0x10 */ u8 numstatus; - /* 0x11 */ u8 status; - /* 0x12 */ u8 completed[46]; - volatile u8 mraid_poll; - volatile u8 mraid_ack; - u8 pad[16]; /* for alignment purposes */ -} __attribute__ ((packed)); -typedef struct _mega_mailbox mega_mailbox; - -typedef struct { - u32 xferSegment_lo; - u32 xferSegment_hi; - mega_mailbox mailbox; -} mega_mailbox64; - -typedef struct _mega_ioctl_mbox { - /* 0x0 */ u8 cmd; - /* 0x1 */ u8 cmdid; - /* 0x2 */ u8 channel; - /* 0x3 */ u8 param; - /* 0x4 */ u8 pad[4]; - /* 0x8 */ u32 xferaddr; - /* 0xC */ u8 logdrv; - /* 0xD */ u8 numsgelements; - /* 0xE */ u8 resvd; - /* 0xF */ u8 busy; - /* 0x10 */ u8 numstatus; - /* 0x11 */ u8 status; - /* 0x12 */ u8 completed[46]; - u8 mraid_poll; - u8 mraid_ack; - u8 malign[16]; -} mega_ioctl_mbox; - -typedef struct _mega_64sglist32 { - u64 address; - u32 length; -} __attribute__ ((packed)) mega_64sglist; - -typedef struct _mega_sglist { - u32 address; - u32 length; -} mega_sglist; - -/* Queued command data */ -typedef struct _mega_scb mega_scb; - -struct _mega_scb { - int idx; - u32 state; - u32 isrcount; - u8 mboxData[16]; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - u32 dma_type; - dma_addr_t dma_h_bulkdata; /*Dma handle for bulk data transfter */ - u32 dma_direction; /*Dma direction */ - dma_addr_t dma_h_sgdata; /*Dma handle for the sglist structure */ - dma_addr_t dma_h_sglist[MAX_SGLIST]; /*Dma handle for all SGL elements */ - u8 sglist_count; - dma_addr_t dma_sghandle64; - dma_addr_t dma_passthruhandle64; - dma_addr_t dma_ext_passthruhandle64; - dma_addr_t dma_bounce_buffer; - u8 *bounce_buffer; -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - mega_passthru *pthru; - mega_ext_passthru *epthru; -#else - mega_passthru pthru; - mega_ext_passthru epthru; -#endif - - Scsi_Cmnd *SCpnt; - mega_sglist *sgList; - mega_64sglist *sg64List; -#if 0 - struct semaphore ioctl_sem; -#endif - void *buff_ptr; - u32 iDataSize; - mega_scb *next; -}; - -/* internal locking by the queue manipulting routines */ -#define INTERNAL_LOCK 0 -/* external locking by the queue manipulting routines */ -#define EXTERNAL_LOCK 1 -#define NO_LOCK 2 -#define INTR_ENB 0 /* do not disable interrupt while manipulating */ -#define INTR_DIS 1 /* disable interrupt while manipulating */ - -#define NVIRT_CHAN 4 /* # of virtual channels to represent 60 logical - drives */ - -/* Per-controller data */ -typedef struct _mega_host_config { - u8 numldrv; - u32 flag; - -#ifdef __LP64__ - u64 base; -#else - u32 base; -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - dma_addr_t dma_handle64, adjdmahandle64; - struct pci_dev *dev; -#endif - - mega_scb *qFreeH; - mega_scb *qFreeT; - spinlock_t lock_free; - - mega_scb *qPendingH; - mega_scb *qPendingT; - spinlock_t lock_pend; - - Scsi_Cmnd *qCompletedH; - Scsi_Cmnd *qCompletedT; - spinlock_t lock_scsicmd; - - u32 qFcnt; - u32 qPcnt; - u32 qCcnt; - - unsigned long nReads[FC_MAX_LOGICAL_DRIVES]; - unsigned long nReadBlocks[FC_MAX_LOGICAL_DRIVES]; - unsigned long nWrites[FC_MAX_LOGICAL_DRIVES]; - unsigned long nWriteBlocks[FC_MAX_LOGICAL_DRIVES]; - unsigned long nInterrupts; - /* Host adapter parameters */ - u8 fwVer[7]; - u8 biosVer[7]; - - struct Scsi_Host *host; - - volatile mega_mailbox64 *mbox64; /* ptr to beginning of 64-bit mailbox */ - volatile mega_mailbox *mbox; /* ptr to beginning of standard mailbox */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -/* ptr to beginning of standard mailbox */ - volatile mega_mailbox64 *mailbox64ptr; -#else - volatile mega_mailbox64 mailbox64; -#endif - - volatile u8 mega_buffer[2 * 1024L]; - volatile megaRaidProductInfo productInfo; - - u8 max_cmds; - mega_scb scbList[MAX_COMMANDS]; - -#if XEN_KILLED -#define PROCBUFSIZE 4096 - char procbuf[PROCBUFSIZE]; - int procidx; - struct proc_dir_entry *controller_proc_dir_entry; - struct proc_dir_entry *proc_read, *proc_stat, *proc_status, *proc_mbox; -#endif - - int support_ext_cdb; - - u8 boot_ldrv_enabled; /* boot from logical drive */ - u8 boot_ldrv; /* boot logical drive */ - u8 boot_pdrv_enabled; /* boot from physical drive */ - u8 boot_pdrv_ch; /* boot physical drive channel */ - u8 boot_pdrv_tgt; /* boot physical drive target */ - - int support_random_del; /* Do we support random deletion of logdrvs */ - int read_ldidmap; /* set after logical drive deltion. The logical - drive number must be read from the map */ -#if XEN_KILLED_DELLOGDRV - int quiescent; /* a stage reached when delete logical drive needs to - be done. Stop sending requests to the hba till - delete operation is completed */ - - mega_scb *int_qh; /* commands are queued in the internal queue */ - mega_scb *int_qt; /* while the hba is quiescent */ - int int_qlen; -#endif - char logdrv_chan[MAX_CHANNEL+NVIRT_CHAN]; /* logical drive are on - what channels. */ - int mega_ch_class; -} mega_host_config; - -typedef struct _driver_info { - int size; - ulong version; -} mega_driver_info; - -/* - * User ioctl structure. - * This structure will be used for Traditional Method ioctl interface - * commands (M_RD_IOCTL_CMD),Alternate Buffer Method (M_RD_IOCTL_CMD_NEW) - * ioctl commands and the Driver ioctls(M_RD_DRIVER_IOCTL_INTERFACE). - * The Driver ioctl interface handles the commands at - * the driver level, without being sent to the card. - */ -#define MEGADEVIOC 0x84 - -/* system call imposed limit. Change accordingly */ -#define IOCTL_MAX_DATALEN 4096 - -#pragma pack(1) -struct uioctl_t { - u32 inlen; - u32 outlen; - union { - u8 fca[16]; - struct { - u8 opcode; - u8 subopcode; - u16 adapno; -#if BITS_PER_LONG == 32 - u8 *buffer; - u8 pad[4]; -#endif -#if BITS_PER_LONG == 64 - u8 *buffer; -#endif - u32 length; - } fcs; - } ui; - u8 mbox[18]; /* 16 bytes + 2 status bytes */ - mega_passthru pthru; -#if BITS_PER_LONG == 32 - char *data; /* buffer <= 4096 for 0x80 commands */ - char pad[4]; -#endif -#if BITS_PER_LONG == 64 - char *data; -#endif -}; -#pragma pack() - -/* - * struct mcontroller is used to pass information about the controllers in the - * system. Its upto the application how to use the information. We are passing - * as much info about the cards as possible and useful. Before issuing the - * call to find information about the cards, the applicaiton needs to issue a - * ioctl first to find out the number of controllers in the system. - */ -#define MAX_CONTROLLERS 32 - -struct mcontroller { - u64 base; - u8 irq; - u8 numldrv; - u8 pcibus; - u16 pcidev; - u8 pcifun; - u16 pciid; - u16 pcivendor; - u8 pcislot; - u32 uid; -}; - -struct mbox_passthru { - u8 cmd; - u8 cmdid; - u16 pad1; - u32 pad2; - u32 dataxferaddr; - u8 pad3; - u8 pad4; - u8 rsvd; - u8 mboxbusy; - u8 nstatus; - u8 status; -}; - -/* - * Defines for Driver IOCTL interface, Op-code:M_RD_DRIVER_IOCTL_INTERFACE - */ -#define MEGAIOC_MAGIC 'm' -#define MEGAIOCCMD _IOWR(MEGAIOC_MAGIC, 0) /* Mega IOCTL command */ - -#define MEGAIOC_QNADAP 'm' /* Query # of adapters */ -#define MEGAIOC_QDRVRVER 'e' /* Query driver version */ -#define MEGAIOC_QADAPINFO 'g' /* Query adapter information */ -#define MKADAP(adapno) (MEGAIOC_MAGIC << 8 | (adapno) ) -#define GETADAP(mkadap) ( (mkadap) ^ MEGAIOC_MAGIC << 8 ) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) /*0x20300 */ -extern struct proc_dir_entry proc_scsi_megaraid; -#endif - -/* For Host Re-Ordering */ -#define MAX_CONTROLLERS 32 - -struct mega_hbas { - int is_bios_enabled; - mega_host_config *hostdata_addr; -}; - -#define IS_BIOS_ENABLED 0x62 -#define GET_BIOS 0x01 -#define CHNL_CLASS 0xA9 -#define GET_CHNL_CLASS 0x00 -#define SET_CHNL_CLASS 0x01 -#define CH_RAID 0x01 -#define CH_SCSI 0x00 - - -#define BIOS_PVT_DATA 0x40 -#define GET_BIOS_PVT_DATA 0x00 - -#pragma pack(1) -struct private_bios_data { - u8 geometry:4; /* - * bits 0-3 - BIOS geometry - * 0x0001 - 1GB - * 0x0010 - 2GB - * 0x1000 - 8GB - * Others values are invalid - */ - u8 unused:4; /* bits 4-7 are unused */ - u8 boot_drv; /* - * logical/physical drive set as boot drive - * 0..7 - for 8LD cards - * 0..39 - for 40LD cards - */ - u8 rsvd[12]; - u16 cksum; /* 0-(sum of first 13 bytes of this structure) */ -}; -#pragma pack() - -/* - * Command for random deletion of logical drives - */ -#define FC_DEL_LOGDRV 0xA4 /* f/w command */ -#define OP_SUP_DEL_LOGDRV 0x2A /* is feature supported */ -#define OP_GET_LDID_MAP 0x18 /* get logdrv id and logdrv number map */ -#define OP_DEL_LOGDRV 0x1C /* delete logical drive */ - -/*================================================================ - * - * Function prototypes - * - *================================================================ - */ -const char *megaraid_info (struct Scsi_Host *); -int megaraid_detect (Scsi_Host_Template *); -int megaraid_release (struct Scsi_Host *); -int megaraid_command (Scsi_Cmnd *); -int megaraid_abort (Scsi_Cmnd *); -int megaraid_reset (Scsi_Cmnd *, unsigned int); -int megaraid_queue (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); -int megaraid_biosparam (Disk *, kdev_t, int *); -#if 0 -int megaraid_proc_info (char *buffer, char **start, off_t offset, - int length, int hostno, int inout); -#endif -static int megaIssueCmd (mega_host_config * megaCfg, u_char * mboxData, - mega_scb * scb, int intr); -static int mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb, - u32 * buffer, u32 * length); -static int mega_busyWaitMbox (mega_host_config *); -static int mega_runpendq (mega_host_config *); -static void mega_rundoneq (mega_host_config *); -static void mega_cmd_done (mega_host_config *, mega_scb *, int); -static inline void mega_freeSgList (mega_host_config * megaCfg); -static void mega_Convert8ldTo40ld (mega_RAIDINQ * inquiry, - mega_Enquiry3 * enquiry3, - megaRaidProductInfo * productInfo); - -#if 0 -static int megaraid_reboot_notify (struct notifier_block *, - unsigned long, void *); -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt); -static void mega_build_kernel_sg (char *barea, ulong xfersize, mega_scb * pScb, - mega_ioctl_mbox * mbox); -#endif - -#if 0 -static int megadev_open (struct inode *, struct file *); -static int megadev_ioctl_entry (struct inode *, struct file *, - unsigned int, unsigned long); -static int megadev_ioctl (struct inode *, struct file *, - unsigned int, unsigned long); -#endif -static mega_scb *megadev_doioctl (mega_host_config *, Scsi_Cmnd *); -#if 0 -static int megadev_close (struct inode *, struct file *); -static void megadev_ioctl_done (Scsi_Cmnd *); -#endif -static int mega_init_scb (mega_host_config *); -static void enq_scb_freelist (mega_host_config *, mega_scb *, - int lock, int intr); - -static int mega_is_bios_enabled (mega_host_config *); -static void mega_reorder_hosts (void); -static void mega_swap_hosts (struct Scsi_Host *, struct Scsi_Host *); - -#if 0 -static void mega_create_proc_entry (int index, struct proc_dir_entry *); -#endif -static int mega_support_ext_cdb(mega_host_config *); -static mega_passthru* mega_prepare_passthru(mega_host_config *, mega_scb *, - Scsi_Cmnd *, int, int); -static mega_ext_passthru* mega_prepare_extpassthru(mega_host_config *, - mega_scb *, Scsi_Cmnd *, int, int); -static void mega_enum_raid_scsi(mega_host_config *); -static int mega_partsize(Disk *, kdev_t, int *); -static void mega_get_boot_drv(mega_host_config *); -static int mega_get_ldrv_num(mega_host_config *, Scsi_Cmnd *, int); -static int mega_support_random_del(mega_host_config *); -/*static int mega_del_logdrv(mega_host_config *, int);*/ -/*static int mega_do_del_logdrv(mega_host_config *, int);*/ - -#endif - -/* vi: set ts=4: */ diff --git a/xen/drivers/scsi/scsi.c b/xen/drivers/scsi/scsi.c deleted file mode 100644 index 7b586ca7e1..0000000000 --- a/xen/drivers/scsi/scsi.c +++ /dev/null @@ -1,2970 +0,0 @@ -/* - * scsi.c Copyright (C) 1992 Drew Eckhardt - * Copyright (C) 1993, 1994, 1995, 1999 Eric Youngdale - * - * generic mid-level SCSI driver - * Initial versions: Drew Eckhardt - * Subsequent revisions: Eric Youngdale - * - * - * - * Bug correction thanks go to : - * Rik Faith - * Tommy Thorn - * Thomas Wuensche - * - * Modified by Eric Youngdale eric@andante.org or ericy@gnu.ai.mit.edu to - * add scatter-gather, multiple outstanding request, and other - * enhancements. - * - * Native multichannel, wide scsi, /proc/scsi and hot plugging - * support added by Michael Neuffer - * - * Added request_module("scsi_hostadapter") for kerneld: - * (Put an "alias scsi_hostadapter your_hostadapter" in /etc/modules.conf) - * Bjorn Ekwall - * (changed to kmod) - * - * Major improvements to the timeout, abort, and reset processing, - * as well as performance modifications for large queue depths by - * Leonard N. Zubkoff - * - * Converted cli() code to spinlocks, Ingo Molnar - * - * Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli - * - * out_of_space hacks, D. Gilbert (dpg) 990608 - */ - -#define REVISION "Revision: 1.00" -#define VERSION "Id: scsi.c 1.00 2000/09/26" - -#include -#include - -#include -#include -#include -#include -#include -/*#include */ -#include -#include -#include -#include -/*#include */ -/*#include */ - -/* for xen scsi_probe() stuff... maybe punt somewhere else? */ -#include -#include - -#define __KERNEL_SYSCALLS__ - -/*#include */ -#include - -#include -#include -#include -#include - -#include "scsi.h" -#include "hosts.h" -#include "constants.h" - -#ifdef CONFIG_KMOD -#include -#endif - -#undef USE_STATIC_SCSI_MEMORY - -struct proc_dir_entry *proc_scsi; - -#ifdef CONFIG_PROC_FS -static int scsi_proc_info(char *buffer, char **start, off_t offset, int length); -static void scsi_dump_status(int level); -#endif - -/* - static const char RCSid[] = "$Header: /vger/u4/cvs/linux/drivers/scsi/scsi.c,v 1.38 1997/01/19 23:07:18 davem Exp $"; - */ - -/* - * Definitions and constants. - */ - -#define MIN_RESET_DELAY (2*HZ) - -/* Do not call reset on error if we just did a reset within 15 sec. */ -#define MIN_RESET_PERIOD (15*HZ) - -/* - * Macro to determine the size of SCSI command. This macro takes vendor - * unique commands into account. SCSI commands in groups 6 and 7 are - * vendor unique and we will depend upon the command length being - * supplied correctly in cmd_len. - */ -#define CDB_SIZE(SCpnt) ((((SCpnt->cmnd[0] >> 5) & 7) < 6) ? \ - COMMAND_SIZE(SCpnt->cmnd[0]) : SCpnt->cmd_len) - -/* - * Data declarations. - */ -unsigned long scsi_pid; -Scsi_Cmnd *last_cmnd; -/* Command group 3 is reserved and should never be used. */ -const unsigned char scsi_command_size[8] = -{ - 6, 10, 10, 12, - 16, 12, 10, 10 -}; -static unsigned long serial_number; -static Scsi_Cmnd *scsi_bh_queue_head; -static Scsi_Cmnd *scsi_bh_queue_tail; - -/* - * Note - the initial logging level can be set here to log events at boot time. - * After the system is up, you may enable logging via the /proc interface. - */ -unsigned int scsi_logging_level; - -const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] = -{ - "Direct-Access ", - "Sequential-Access", - "Printer ", - "Processor ", - "WORM ", - "CD-ROM ", - "Scanner ", - "Optical Device ", - "Medium Changer ", - "Communications ", - "Unknown ", - "Unknown ", - "Unknown ", - "Enclosure ", -}; - -/* - * These are the interface to the old error handling code. It should go away - * someday soon. - */ -extern void scsi_old_done(Scsi_Cmnd * SCpnt); -extern void scsi_old_times_out(Scsi_Cmnd * SCpnt); -extern int scsi_old_reset(Scsi_Cmnd *SCpnt, unsigned int flag); - -/* - * Private interface into the new error handling code. - */ -extern int scsi_new_reset(Scsi_Cmnd *SCpnt, unsigned int flag); - -/* - * Function: scsi_initialize_queue() - * - * Purpose: Selects queue handler function for a device. - * - * Arguments: SDpnt - device for which we need a handler function. - * - * Returns: Nothing - * - * Lock status: No locking assumed or required. - * - * Notes: Most devices will end up using scsi_request_fn for the - * handler function (at least as things are done now). - * The "block" feature basically ensures that only one of - * the blocked hosts is active at one time, mainly to work around - * buggy DMA chipsets where the memory gets starved. - * For this case, we have a special handler function, which - * does some checks and ultimately calls scsi_request_fn. - * - * The single_lun feature is a similar special case. - * - * We handle these things by stacking the handlers. The - * special case handlers simply check a few conditions, - * and return if they are not supposed to do anything. - * In the event that things are OK, then they call the next - * handler in the list - ultimately they call scsi_request_fn - * to do the dirty deed. - */ -void scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt) { - blk_init_queue(&SDpnt->request_queue, scsi_request_fn); - blk_queue_headactive(&SDpnt->request_queue, 0); - SDpnt->request_queue.queuedata = (void *) SDpnt; -} - -#ifdef MODULE -MODULE_PARM(scsi_logging_level, "i"); -MODULE_PARM_DESC(scsi_logging_level, "SCSI logging level; should be zero or nonzero"); - -#else -static int __init scsi_logging_setup(char *str) -{ -#if 0 - int tmp; - - if (get_option(&str, &tmp) == 1) { - scsi_logging_level = (tmp ? ~0 : 0); - return 1; - } else { - printk(KERN_INFO "scsi_logging_setup : usage scsi_logging_level=n " - "(n should be 0 or non-zero)\n"); - return 0; - } -#else - return 0; -#endif - -} -__setup("scsi_logging=", scsi_logging_setup); - -#endif - -/* - * Issue a command and wait for it to complete - */ - -static void scsi_wait_done(Scsi_Cmnd * SCpnt) -{ - struct request *req; - - req = &SCpnt->request; - req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */ - -#if 0 - if (req->waiting != NULL) { - complete(req->waiting); - } -#else - /* XXX SMH: just use a flag to signal completion; caller spins */ - if (*(int *)(req->waiting) != 0) { -// printk("scsi_wait_done: flipping wait status on req %p\n", req); - *(int *)(req->waiting) = 0; - } -#endif - -} - -/* - * This lock protects the freelist for all devices on the system. - * We could make this finer grained by having a single lock per - * device if it is ever found that there is excessive contention - * on this lock. - */ -static spinlock_t device_request_lock = SPIN_LOCK_UNLOCKED; - -/* - * Used to protect insertion into and removal from the queue of - * commands to be processed by the bottom half handler. - */ -static spinlock_t scsi_bhqueue_lock = SPIN_LOCK_UNLOCKED; - -/* - * Function: scsi_allocate_request - * - * Purpose: Allocate a request descriptor. - * - * Arguments: device - device for which we want a request - * - * Lock status: No locks assumed to be held. This function is SMP-safe. - * - * Returns: Pointer to request block. - * - * Notes: With the new queueing code, it becomes important - * to track the difference between a command and a - * request. A request is a pending item in the queue that - * has not yet reached the top of the queue. - */ - -Scsi_Request *scsi_allocate_request(Scsi_Device * device) -{ - Scsi_Request *SRpnt = NULL; - - if (!device) - panic("No device passed to scsi_allocate_request().\n"); - - SRpnt = (Scsi_Request *) kmalloc(sizeof(Scsi_Request), GFP_ATOMIC); - if( SRpnt == NULL ) - { - return NULL; - } - - memset(SRpnt, 0, sizeof(Scsi_Request)); - SRpnt->sr_device = device; - SRpnt->sr_host = device->host; - SRpnt->sr_magic = SCSI_REQ_MAGIC; - SRpnt->sr_data_direction = SCSI_DATA_UNKNOWN; - - return SRpnt; -} - -/* - * Function: scsi_release_request - * - * Purpose: Release a request descriptor. - * - * Arguments: device - device for which we want a request - * - * Lock status: No locks assumed to be held. This function is SMP-safe. - * - * Returns: Pointer to request block. - * - * Notes: With the new queueing code, it becomes important - * to track the difference between a command and a - * request. A request is a pending item in the queue that - * has not yet reached the top of the queue. We still need - * to free a request when we are done with it, of course. - */ -void scsi_release_request(Scsi_Request * req) -{ - if( req->sr_command != NULL ) - { - scsi_release_command(req->sr_command); - req->sr_command = NULL; - } - - kfree(req); -} - -/* - * Function: scsi_allocate_device - * - * Purpose: Allocate a command descriptor. - * - * Arguments: device - device for which we want a command descriptor - * wait - 1 if we should wait in the event that none - * are available. - * interruptible - 1 if we should unblock and return NULL - * in the event that we must wait, and a signal - * arrives. - * - * Lock status: No locks assumed to be held. This function is SMP-safe. - * - * Returns: Pointer to command descriptor. - * - * Notes: Prior to the new queue code, this function was not SMP-safe. - * - * If the wait flag is true, and we are waiting for a free - * command block, this function will interrupt and return - * NULL in the event that a signal arrives that needs to - * be handled. - * - * This function is deprecated, and drivers should be - * rewritten to use Scsi_Request instead of Scsi_Cmnd. - */ - -Scsi_Cmnd *scsi_allocate_device(Scsi_Device * device, int wait, - int interruptable) -{ - struct Scsi_Host *host; - Scsi_Cmnd *SCpnt = NULL; - Scsi_Device *SDpnt; - unsigned long flags; - - if (!device) - panic("No device passed to scsi_allocate_device().\n"); - - host = device->host; - - spin_lock_irqsave(&device_request_lock, flags); - - while (1 == 1) { - SCpnt = NULL; - if (!device->device_blocked) { - if (device->single_lun) { - /* - * FIXME(eric) - this is not at all optimal. Given that - * single lun devices are rare and usually slow - * (i.e. CD changers), this is good enough for now, but - * we may want to come back and optimize this later. - * - * Scan through all of the devices attached to this - * host, and see if any are active or not. If so, - * we need to defer this command. - * - * We really need a busy counter per device. This would - * allow us to more easily figure out whether we should - * do anything here or not. - */ - for (SDpnt = host->host_queue; - SDpnt; - SDpnt = SDpnt->next) { - /* - * Only look for other devices on the same bus - * with the same target ID. - */ - if (SDpnt->channel != device->channel - || SDpnt->id != device->id - || SDpnt == device) { - continue; - } - if( atomic_read(&SDpnt->device_active) != 0) - { - break; - } - } - if (SDpnt) { - /* - * Some other device in this cluster is busy. - * If asked to wait, we need to wait, otherwise - * return NULL. - */ - SCpnt = NULL; - goto busy; - } - } - /* - * Now we can check for a free command block for this device. - */ - for (SCpnt = device->device_queue; SCpnt; SCpnt = SCpnt->next) { - if (SCpnt->request.rq_status == RQ_INACTIVE) - break; - } - } - /* - * If we couldn't find a free command block, and we have been - * asked to wait, then do so. - */ - if (SCpnt) { - break; - } - busy: - /* - * If we have been asked to wait for a free block, then - * wait here. - */ - if (wait) { - printk("XXX smh: scsi cannot wait for free cmd block.\n"); - BUG(); -#if 0 - DECLARE_WAITQUEUE(wait, current); - - /* - * We need to wait for a free commandblock. We need to - * insert ourselves into the list before we release the - * lock. This way if a block were released the same - * microsecond that we released the lock, the call - * to schedule() wouldn't block (well, it might switch, - * but the current task will still be schedulable. - */ - add_wait_queue(&device->scpnt_wait, &wait); - if( interruptable ) { - set_current_state(TASK_INTERRUPTIBLE); - } else { - set_current_state(TASK_UNINTERRUPTIBLE); - } - - spin_unlock_irqrestore(&device_request_lock, flags); - - /* - * This should block until a device command block - * becomes available. - */ - schedule(); - - spin_lock_irqsave(&device_request_lock, flags); - - remove_wait_queue(&device->scpnt_wait, &wait); - /* - * FIXME - Isn't this redundant?? Someone - * else will have forced the state back to running. - */ - set_current_state(TASK_RUNNING); - /* - * In the event that a signal has arrived that we need - * to consider, then simply return NULL. Everyone - * that calls us should be prepared for this - * possibility, and pass the appropriate code back - * to the user. - */ - if( interruptable ) { - if (signal_pending(current)) { - spin_unlock_irqrestore(&device_request_lock, flags); - return NULL; - } - } -#endif - } else { - spin_unlock_irqrestore(&device_request_lock, flags); - return NULL; - } - } - - SCpnt->request.rq_status = RQ_SCSI_BUSY; - SCpnt->request.waiting = NULL; /* And no one is waiting for this - * to complete */ - atomic_inc(&SCpnt->host->host_active); - atomic_inc(&SCpnt->device->device_active); - - SCpnt->buffer = NULL; - SCpnt->bufflen = 0; - SCpnt->request_buffer = NULL; - SCpnt->request_bufflen = 0; - - SCpnt->use_sg = 0; /* Reset the scatter-gather flag */ - SCpnt->old_use_sg = 0; - SCpnt->transfersize = 0; /* No default transfer size */ - SCpnt->cmd_len = 0; - - SCpnt->sc_data_direction = SCSI_DATA_UNKNOWN; - SCpnt->sc_request = NULL; - SCpnt->sc_magic = SCSI_CMND_MAGIC; - - SCpnt->result = 0; - SCpnt->underflow = 0; /* Do not flag underflow conditions */ - SCpnt->old_underflow = 0; - SCpnt->resid = 0; - SCpnt->state = SCSI_STATE_INITIALIZING; - SCpnt->owner = SCSI_OWNER_HIGHLEVEL; - - spin_unlock_irqrestore(&device_request_lock, flags); - - SCSI_LOG_MLQUEUE(5, printk("Activating command for device %d (%d)\n", - SCpnt->target, - atomic_read(&SCpnt->host->host_active))); - - return SCpnt; -} - -inline void __scsi_release_command(Scsi_Cmnd * SCpnt) -{ - unsigned long flags; - Scsi_Device * SDpnt; - - spin_lock_irqsave(&device_request_lock, flags); - - SDpnt = SCpnt->device; - - SCpnt->request.rq_status = RQ_INACTIVE; - SCpnt->state = SCSI_STATE_UNUSED; - SCpnt->owner = SCSI_OWNER_NOBODY; - atomic_dec(&SCpnt->host->host_active); - atomic_dec(&SDpnt->device_active); - - SCSI_LOG_MLQUEUE(5, printk( - "Deactivating command for device %d (active=%d, failed=%d)\n", - SCpnt->target, - atomic_read(&SCpnt->host->host_active), - SCpnt->host->host_failed)); - if (SCpnt->host->host_failed != 0) { - SCSI_LOG_ERROR_RECOVERY(5, printk("Error handler thread %d %d\n", - SCpnt->host->in_recovery, - SCpnt->host->eh_active)); - } - /* - * If the host is having troubles, then look to see if this was the last - * command that might have failed. If so, wake up the error handler. - */ - if (SCpnt->host->in_recovery - && !SCpnt->host->eh_active - && SCpnt->host->host_busy == SCpnt->host->host_failed) { -#if 0 - SCSI_LOG_ERROR_RECOVERY(5, printk( - "Waking error handler thread (%d)\n", - atomic_read(&SCpnt->host->eh_wait->count))); - up(SCpnt->host->eh_wait); -#endif - } - - spin_unlock_irqrestore(&device_request_lock, flags); - -#if 0 - /* - * Wake up anyone waiting for this device. Do this after we - * have released the lock, as they will need it as soon as - * they wake up. - */ - wake_up(&SDpnt->scpnt_wait); -#endif - -} - -/* - * Function: scsi_release_command - * - * Purpose: Release a command block. - * - * Arguments: SCpnt - command block we are releasing. - * - * Notes: The command block can no longer be used by the caller once - * this funciton is called. This is in effect the inverse - * of scsi_allocate_device. Note that we also must perform - * a couple of additional tasks. We must first wake up any - * processes that might have blocked waiting for a command - * block, and secondly we must hit the queue handler function - * to make sure that the device is busy. Note - there is an - * option to not do this - there were instances where we could - * recurse too deeply and blow the stack if this happened - * when we were indirectly called from the request function - * itself. - * - * The idea is that a lot of the mid-level internals gunk - * gets hidden in this function. Upper level drivers don't - * have any chickens to wave in the air to get things to - * work reliably. - * - * This function is deprecated, and drivers should be - * rewritten to use Scsi_Request instead of Scsi_Cmnd. - */ -void scsi_release_command(Scsi_Cmnd * SCpnt) -{ - request_queue_t *q; - Scsi_Device * SDpnt; - - SDpnt = SCpnt->device; - - __scsi_release_command(SCpnt); - - /* - * Finally, hit the queue request function to make sure that - * the device is actually busy if there are requests present. - * This won't block - if the device cannot take any more, life - * will go on. - */ - q = &SDpnt->request_queue; - scsi_queue_next_request(q, NULL); -} - -/* - * Function: scsi_dispatch_command - * - * Purpose: Dispatch a command to the low-level driver. - * - * Arguments: SCpnt - command block we are dispatching. - * - * Notes: - */ -int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt) -{ -#ifdef DEBUG_DELAY - unsigned long clock; -#endif - struct Scsi_Host *host; - int rtn = 0; - unsigned long flags = 0; - unsigned long timeout; - - ASSERT_LOCK(&io_request_lock, 0); - -#if DEBUG - unsigned long *ret = 0; -#ifdef __mips__ - __asm__ __volatile__("move\t%0,$31":"=r"(ret)); -#else - ret = __builtin_return_address(0); -#endif -#endif - - host = SCpnt->host; - - /* Assign a unique nonzero serial_number. */ - if (++serial_number == 0) - serial_number = 1; - SCpnt->serial_number = serial_number; - SCpnt->pid = scsi_pid++; - - /* - * We will wait MIN_RESET_DELAY clock ticks after the last reset so - * we can avoid the drive not being ready. - */ - timeout = host->last_reset + MIN_RESET_DELAY; - - if (host->resetting && time_before(jiffies, timeout)) { - int ticks_remaining = timeout - jiffies; - /* - * NOTE: This may be executed from within an interrupt - * handler! This is bad, but for now, it'll do. The irq - * level of the interrupt handler has been masked out by the - * platform dependent interrupt handling code already, so the - * sti() here will not cause another call to the SCSI host's - * interrupt handler (assuming there is one irq-level per - * host). - */ - while (--ticks_remaining >= 0) - mdelay(1 + 999 / HZ); - host->resetting = 0; - } - if (host->hostt->use_new_eh_code) { - scsi_add_timer(SCpnt, SCpnt->timeout_per_command, scsi_times_out); - } else { - scsi_add_timer(SCpnt, SCpnt->timeout_per_command, - scsi_old_times_out); - } - - /* - * We will use a queued command if possible, otherwise we will emulate the - * queuing and calling of completion function ourselves. - */ - SCSI_LOG_MLQUEUE(3, printk( - "scsi_dispatch_cmnd (host = %d, channel = %d, target = %d, " - "command = %p, buffer = %p, \nbufflen = %d, done = %p)\n", - SCpnt->host->host_no, SCpnt->channel, SCpnt->target, SCpnt->cmnd, - SCpnt->buffer, SCpnt->bufflen, SCpnt->done)); - - SCpnt->state = SCSI_STATE_QUEUED; - SCpnt->owner = SCSI_OWNER_LOWLEVEL; - if (host->can_queue) { - SCSI_LOG_MLQUEUE(3, printk("queuecommand : routine at %p\n", - host->hostt->queuecommand)); - /* - * Use the old error handling code if we haven't converted the driver - * to use the new one yet. Note - only the new queuecommand variant - * passes a meaningful return value. - */ - if (host->hostt->use_new_eh_code) { - /* - * Before we queue this command, check if the command - * length exceeds what the host adapter can handle. - */ - if (CDB_SIZE(SCpnt) <= SCpnt->host->max_cmd_len) { - spin_lock_irqsave(&io_request_lock, flags); - rtn = host->hostt->queuecommand(SCpnt, scsi_done); - spin_unlock_irqrestore(&io_request_lock, flags); - if (rtn != 0) { - scsi_delete_timer(SCpnt); - scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_HOST_BUSY); - SCSI_LOG_MLQUEUE(3, printk( - "queuecommand : request rejected\n")); - } - } else { - SCSI_LOG_MLQUEUE(3, printk( - "queuecommand : command too long.\n")); - SCpnt->result = (DID_ABORT << 16); - spin_lock_irqsave(&io_request_lock, flags); - scsi_done(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); - rtn = 1; - } - } else { - /* - * Before we queue this command, check if the command - * length exceeds what the host adapter can handle. - */ - if (CDB_SIZE(SCpnt) <= SCpnt->host->max_cmd_len) { - spin_lock_irqsave(&io_request_lock, flags); - host->hostt->queuecommand(SCpnt, scsi_old_done); - spin_unlock_irqrestore(&io_request_lock, flags); - } else { - SCSI_LOG_MLQUEUE(3, printk( - "queuecommand : command too long.\n")); - SCpnt->result = (DID_ABORT << 16); - spin_lock_irqsave(&io_request_lock, flags); - scsi_old_done(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); - rtn = 1; - } - - } - } else { - int temp; - - SCSI_LOG_MLQUEUE(3, printk( - "command() : routine at %p\n", host->hostt->command)); - spin_lock_irqsave(&io_request_lock, flags); - temp = host->hostt->command(SCpnt); - SCpnt->result = temp; -#ifdef DEBUG_DELAY - spin_unlock_irqrestore(&io_request_lock, flags); - clock = jiffies + 4 * HZ; - while (time_before(jiffies, clock)) { - barrier(); - cpu_relax(); - } - printk("done(host = %d, result = %04x) : routine at %p\n", - host->host_no, temp, host->hostt->command); - spin_lock_irqsave(&io_request_lock, flags); -#endif - if (host->hostt->use_new_eh_code) { - scsi_done(SCpnt); - } else { - scsi_old_done(SCpnt); - } - spin_unlock_irqrestore(&io_request_lock, flags); - } - SCSI_LOG_MLQUEUE(3, printk("leaving scsi_dispatch_cmnd()\n")); - return rtn; -} - -#ifdef DEVFS_MUST_DIE -devfs_handle_t scsi_devfs_handle; -#endif - -/* - * scsi_do_cmd sends all the commands out to the low-level driver. It - * handles the specifics required for each low level driver - ie queued - * or non queued. It also prevents conflicts when different high level - * drivers go for the same host at the same time. - */ - -void scsi_wait_req (Scsi_Request * SRpnt, const void *cmnd , - void *buffer, unsigned bufflen, - int timeout, int retries) -{ -#if 0 - DECLARE_COMPLETION(wait); -#else - int wait = 1; - int usecs = 0; -#endif - - - request_queue_t *q = &SRpnt->sr_device->request_queue; - -#if 0 - SRpnt->sr_request.waiting = &wait; -#else - SRpnt->sr_request.waiting = (void *)&wait; -#endif - - - SRpnt->sr_request.rq_status = RQ_SCSI_BUSY; - scsi_do_req (SRpnt, (void *) cmnd, - buffer, bufflen, scsi_wait_done, timeout, retries); - generic_unplug_device(q); - - -#if 0 - wait_for_completion(&wait); - SRpnt->sr_request.waiting = NULL; -#else - - /* XXX SMH: in 'standard' driver we think everythings ok here since - we've waited on &wait -- hence we deallocate the command structure - if it hasn't been done already. This is not the correct behaviour - in xen ... hmm .. how to fix? */ - while(wait) { - do_softirq(); /* XXX KAF: this is safe, and necessary!! */ - udelay(500); - usecs += 500; - if(usecs > 1000000) { - printk("scsi_wait_req: still waiting...!\n"); - usecs = 0; - } - } -#endif - - - if( SRpnt->sr_command != NULL ) - { - scsi_release_command(SRpnt->sr_command); - SRpnt->sr_command = NULL; - } - -} - -/* - * Function: scsi_do_req - * - * Purpose: Queue a SCSI request - * - * Arguments: SRpnt - command descriptor. - * cmnd - actual SCSI command to be performed. - * buffer - data buffer. - * bufflen - size of data buffer. - * done - completion function to be run. - * timeout - how long to let it run before timeout. - * retries - number of retries we allow. - * - * Lock status: With the new queueing code, this is SMP-safe, and no locks - * need be held upon entry. The old queueing code the lock was - * assumed to be held upon entry. - * - * Returns: Nothing. - * - * Notes: Prior to the new queue code, this function was not SMP-safe. - * Also, this function is now only used for queueing requests - * for things like ioctls and character device requests - this - * is because we essentially just inject a request into the - * queue for the device. Normal block device handling manipulates - * the queue directly. - */ -void scsi_do_req(Scsi_Request * SRpnt, const void *cmnd, - void *buffer, unsigned bufflen, void (*done) (Scsi_Cmnd *), - int timeout, int retries) -{ - Scsi_Device * SDpnt = SRpnt->sr_device; - struct Scsi_Host *host = SDpnt->host; - - ASSERT_LOCK(&io_request_lock, 0); - - SCSI_LOG_MLQUEUE(4, - { - int i; - int target = SDpnt->id; - int size = COMMAND_SIZE(((const unsigned char *)cmnd)[0]); - printk("scsi_do_req (host = %d, channel = %d target = %d, " - "buffer =%p, bufflen = %d, done = %p, timeout = %d, " - "retries = %d)\n" - "command : ", host->host_no, SDpnt->channel, target, buffer, - bufflen, done, timeout, retries); - for (i = 0; i < size; ++i) - printk("%02x ", ((unsigned char *) cmnd)[i]); - printk("\n"); - }); - - if (!host) { - panic("Invalid or not present host.\n"); - } - - /* - * If the upper level driver is reusing these things, then - * we should release the low-level block now. Another one will - * be allocated later when this request is getting queued. - */ - if( SRpnt->sr_command != NULL ) - { - scsi_release_command(SRpnt->sr_command); - SRpnt->sr_command = NULL; - } - - /* - * We must prevent reentrancy to the lowlevel host driver. - * This prevents it - we enter a loop until the host we want - * to talk to is not busy. Race conditions are prevented, as - * interrupts are disabled in between the time we check for - * the host being not busy, and the time we mark it busy - * ourselves. */ - - - /* - * Our own function scsi_done (which marks the host as not - * busy, disables the timeout counter, etc) will be called by - * us or by the scsi_hosts[host].queuecommand() function needs - * to also call the completion function for the high level - * driver. */ - - memcpy((void *) SRpnt->sr_cmnd, (const void *) cmnd, - sizeof(SRpnt->sr_cmnd)); - - SRpnt->sr_bufflen = bufflen; - SRpnt->sr_buffer = buffer; - SRpnt->sr_allowed = retries; - SRpnt->sr_done = done; - SRpnt->sr_timeout_per_command = timeout; - - if (SRpnt->sr_cmd_len == 0) - SRpnt->sr_cmd_len = COMMAND_SIZE(SRpnt->sr_cmnd[0]); - - /* - * At this point, we merely set up the command, stick it in the normal - * request queue, and return. Eventually that request will come to the - * top of the list, and will be dispatched. - */ - scsi_insert_special_req(SRpnt, 0); - - SCSI_LOG_MLQUEUE(3, printk("Leaving scsi_do_req()\n")); -} - -/* - * Function: scsi_init_cmd_from_req - * - * Purpose: Queue a SCSI command - * Purpose: Initialize a Scsi_Cmnd from a Scsi_Request - * - * Arguments: SCpnt - command descriptor. - * SRpnt - Request from the queue. - * - * Lock status: None needed. - * - * Returns: Nothing. - * - * Notes: Mainly transfer data from the request structure to the - * command structure. The request structure is allocated - * using the normal memory allocator, and requests can pile - * up to more or less any depth. The command structure represents - * a consumable resource, as these are allocated into a pool - * when the SCSI subsystem initializes. The preallocation is - * required so that in low-memory situations a disk I/O request - * won't cause the memory manager to try and write out a page. - * The request structure is generally used by ioctls and character - * devices. - */ -void scsi_init_cmd_from_req(Scsi_Cmnd * SCpnt, Scsi_Request * SRpnt) -{ - struct Scsi_Host *host = SCpnt->host; - - ASSERT_LOCK(&io_request_lock, 0); - - SCpnt->owner = SCSI_OWNER_MIDLEVEL; - SRpnt->sr_command = SCpnt; - - if (!host) { - panic("Invalid or not present host.\n"); - } - - SCpnt->cmd_len = SRpnt->sr_cmd_len; - SCpnt->use_sg = SRpnt->sr_use_sg; - - memcpy((void *) &SCpnt->request, (const void *) &SRpnt->sr_request, - sizeof(SRpnt->sr_request)); - memcpy((void *) SCpnt->data_cmnd, (const void *) SRpnt->sr_cmnd, - sizeof(SCpnt->data_cmnd)); - SCpnt->reset_chain = NULL; - SCpnt->serial_number = 0; - SCpnt->serial_number_at_timeout = 0; - SCpnt->bufflen = SRpnt->sr_bufflen; - SCpnt->buffer = SRpnt->sr_buffer; - SCpnt->flags = 0; - SCpnt->retries = 0; - SCpnt->allowed = SRpnt->sr_allowed; - SCpnt->done = SRpnt->sr_done; - SCpnt->timeout_per_command = SRpnt->sr_timeout_per_command; - - SCpnt->sc_data_direction = SRpnt->sr_data_direction; - - SCpnt->sglist_len = SRpnt->sr_sglist_len; - SCpnt->underflow = SRpnt->sr_underflow; - - SCpnt->sc_request = SRpnt; - - memcpy((void *) SCpnt->cmnd, (const void *) SRpnt->sr_cmnd, - sizeof(SCpnt->cmnd)); - /* Zero the sense buffer. Some host adapters automatically request - * sense on error. 0 is not a valid sense code. - */ - memset((void *) SCpnt->sense_buffer, 0, sizeof SCpnt->sense_buffer); - SCpnt->request_buffer = SRpnt->sr_buffer; - SCpnt->request_bufflen = SRpnt->sr_bufflen; - SCpnt->old_use_sg = SCpnt->use_sg; - if (SCpnt->cmd_len == 0) - SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]); - SCpnt->old_cmd_len = SCpnt->cmd_len; - SCpnt->sc_old_data_direction = SCpnt->sc_data_direction; - SCpnt->old_underflow = SCpnt->underflow; - - /* Start the timer ticking. */ - - SCpnt->internal_timeout = NORMAL_TIMEOUT; - SCpnt->abort_reason = 0; - SCpnt->result = 0; - - SCSI_LOG_MLQUEUE(3, printk("Leaving scsi_init_cmd_from_req()\n")); -} - -/* - * Function: scsi_do_cmd - * - * Purpose: Queue a SCSI command - * - * Arguments: SCpnt - command descriptor. - * cmnd - actual SCSI command to be performed. - * buffer - data buffer. - * bufflen - size of data buffer. - * done - completion function to be run. - * timeout - how long to let it run before timeout. - * retries - number of retries we allow. - * - * Lock status: With the new queueing code, this is SMP-safe, and no locks - * need be held upon entry. The old queueing code the lock was - * assumed to be held upon entry. - * - * Returns: Nothing. - * - * Notes: Prior to the new queue code, this function was not SMP-safe. - * Also, this function is now only used for queueing requests - * for things like ioctls and character device requests - this - * is because we essentially just inject a request into the - * queue for the device. Normal block device handling manipulates - * the queue directly. - */ -void scsi_do_cmd(Scsi_Cmnd * SCpnt, const void *cmnd, - void *buffer, unsigned bufflen, void (*done) (Scsi_Cmnd *), - int timeout, int retries) -{ - struct Scsi_Host *host = SCpnt->host; - - ASSERT_LOCK(&io_request_lock, 0); - - SCpnt->pid = scsi_pid++; - SCpnt->owner = SCSI_OWNER_MIDLEVEL; - - SCSI_LOG_MLQUEUE(4, - { - int i; - int target = SCpnt->target; - int size = COMMAND_SIZE(((const unsigned char *)cmnd)[0]); - printk("scsi_do_cmd (host = %d, channel = %d target = %d, " - "buffer =%p, bufflen = %d, done = %p, timeout = %d, " - "retries = %d)\n" - "command : ", host->host_no, SCpnt->channel, target, buffer, - bufflen, done, timeout, retries); - for (i = 0; i < size; ++i) - printk("%02x ", ((unsigned char *) cmnd)[i]); - printk("\n"); - }); - - if (!host) { - panic("Invalid or not present host.\n"); - } - /* - * We must prevent reentrancy to the lowlevel host driver. This prevents - * it - we enter a loop until the host we want to talk to is not busy. - * Race conditions are prevented, as interrupts are disabled in between the - * time we check for the host being not busy, and the time we mark it busy - * ourselves. - */ - - - /* - * Our own function scsi_done (which marks the host as not busy, disables - * the timeout counter, etc) will be called by us or by the - * scsi_hosts[host].queuecommand() function needs to also call - * the completion function for the high level driver. - */ - - memcpy((void *) SCpnt->data_cmnd, (const void *) cmnd, - sizeof(SCpnt->data_cmnd)); - SCpnt->reset_chain = NULL; - SCpnt->serial_number = 0; - SCpnt->serial_number_at_timeout = 0; - SCpnt->bufflen = bufflen; - SCpnt->buffer = buffer; - SCpnt->flags = 0; - SCpnt->retries = 0; - SCpnt->allowed = retries; - SCpnt->done = done; - SCpnt->timeout_per_command = timeout; - - memcpy((void *) SCpnt->cmnd, (const void *) cmnd, - sizeof(SCpnt->cmnd)); - /* Zero the sense buffer. Some host adapters automatically request - * sense on error. 0 is not a valid sense code. - */ - memset((void *) SCpnt->sense_buffer, 0, sizeof SCpnt->sense_buffer); - SCpnt->request_buffer = buffer; - SCpnt->request_bufflen = bufflen; - SCpnt->old_use_sg = SCpnt->use_sg; - if (SCpnt->cmd_len == 0) - SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]); - SCpnt->old_cmd_len = SCpnt->cmd_len; - SCpnt->sc_old_data_direction = SCpnt->sc_data_direction; - SCpnt->old_underflow = SCpnt->underflow; - - /* Start the timer ticking. */ - - SCpnt->internal_timeout = NORMAL_TIMEOUT; - SCpnt->abort_reason = 0; - SCpnt->result = 0; - - /* - * At this point, we merely set up the command, stick it in the normal - * request queue, and return. Eventually that request will come to the - * top of the list, and will be dispatched. - */ - scsi_insert_special_cmd(SCpnt, 0); - - SCSI_LOG_MLQUEUE(3, printk("Leaving scsi_do_cmd()\n")); -} - -/* - * This function is the mid-level interrupt routine, which decides how - * to handle error conditions. Each invocation of this function must - * do one and *only* one of the following: - * - * 1) Insert command in BH queue. - * 2) Activate error handler for host. - * - * FIXME(eric) - I am concerned about stack overflow (still). An - * interrupt could come while we are processing the bottom queue, - * which would cause another command to be stuffed onto the bottom - * queue, and it would in turn be processed as that interrupt handler - * is returning. Given a sufficiently steady rate of returning - * commands, this could cause the stack to overflow. I am not sure - * what is the most appropriate solution here - we should probably - * keep a depth count, and not process any commands while we still - * have a bottom handler active higher in the stack. - * - * There is currently code in the bottom half handler to monitor - * recursion in the bottom handler and report if it ever happens. If - * this becomes a problem, it won't be hard to engineer something to - * deal with it so that only the outer layer ever does any real - * processing. - */ -void scsi_done(Scsi_Cmnd * SCpnt) -{ - unsigned long flags; - int tstatus; - - /* - * We don't have to worry about this one timing out any more. - */ - tstatus = scsi_delete_timer(SCpnt); - - /* - * If we are unable to remove the timer, it means that the command - * has already timed out. In this case, we have no choice but to - * let the timeout function run, as we have no idea where in fact - * that function could really be. It might be on another processor, - * etc, etc. - */ - if (!tstatus) { - SCpnt->done_late = 1; - return; - } - /* Set the serial numbers back to zero */ - SCpnt->serial_number = 0; - - /* - * First, see whether this command already timed out. If so, we ignore - * the response. We treat it as if the command never finished. - * - * Since serial_number is now 0, the error handler cound detect this - * situation and avoid to call the low level driver abort routine. - * (DB) - * - * FIXME(eric) - I believe that this test is now redundant, due to - * the test of the return status of del_timer(). - */ - if (SCpnt->state == SCSI_STATE_TIMEOUT) { - SCSI_LOG_MLCOMPLETE(1, printk("Ignoring completion of %p due to timeout status", SCpnt)); - return; - } - spin_lock_irqsave(&scsi_bhqueue_lock, flags); - - SCpnt->serial_number_at_timeout = 0; - SCpnt->state = SCSI_STATE_BHQUEUE; - SCpnt->owner = SCSI_OWNER_BH_HANDLER; - SCpnt->bh_next = NULL; - - /* - * Next, put this command in the BH queue. - * - * We need a spinlock here, or compare and exchange if we can reorder incoming - * Scsi_Cmnds, as it happens pretty often scsi_done is called multiple times - * before bh is serviced. -jj - * - * We already have the io_request_lock here, since we are called from the - * interrupt handler or the error handler. (DB) - * - * This may be true at the moment, but I would like to wean all of the low - * level drivers away from using io_request_lock. Technically they should - * all use their own locking. I am adding a small spinlock to protect - * this datastructure to make it safe for that day. (ERY) - */ - if (!scsi_bh_queue_head) { - scsi_bh_queue_head = SCpnt; - scsi_bh_queue_tail = SCpnt; - } else { - scsi_bh_queue_tail->bh_next = SCpnt; - scsi_bh_queue_tail = SCpnt; - } - - spin_unlock_irqrestore(&scsi_bhqueue_lock, flags); - /* - * Mark the bottom half handler to be run. - */ - mark_bh(SCSI_BH); -} - -/* - * Procedure: scsi_bottom_half_handler - * - * Purpose: Called after we have finished processing interrupts, it - * performs post-interrupt handling for commands that may - * have completed. - * - * Notes: This is called with all interrupts enabled. This should reduce - * interrupt latency, stack depth, and reentrancy of the low-level - * drivers. - * - * The io_request_lock is required in all the routine. There was a subtle - * race condition when scsi_done is called after a command has already - * timed out but before the time out is processed by the error handler. - * (DB) - * - * I believe I have corrected this. We simply monitor the return status of - * del_timer() - if this comes back as 0, it means that the timer has fired - * and that a timeout is in progress. I have modified scsi_done() such - * that in this instance the command is never inserted in the bottom - * half queue. Thus the only time we hold the lock here is when - * we wish to atomically remove the contents of the queue. - */ -void scsi_bottom_half_handler(void) -{ - Scsi_Cmnd *SCpnt; - Scsi_Cmnd *SCnext; - unsigned long flags; - - - while (1 == 1) { - spin_lock_irqsave(&scsi_bhqueue_lock, flags); - SCpnt = scsi_bh_queue_head; - scsi_bh_queue_head = NULL; - spin_unlock_irqrestore(&scsi_bhqueue_lock, flags); - - if (SCpnt == NULL) { - return; - } - SCnext = SCpnt->bh_next; - - for (; SCpnt; SCpnt = SCnext) { - SCnext = SCpnt->bh_next; - - switch (scsi_decide_disposition(SCpnt)) { - case SUCCESS: - /* - * Add to BH queue. - */ - SCSI_LOG_MLCOMPLETE(3, - printk("Command finished %d %d 0x%x\n", - SCpnt->host->host_busy, - SCpnt->host->host_failed, - SCpnt->result)); - - scsi_finish_command(SCpnt); - break; - case NEEDS_RETRY: - /* - * We only come in here if we want to retry a command. - * The test to see whether the command should be - * retried should be keeping track of the number of - * tries, so we don't end up looping, of course. */ - SCSI_LOG_MLCOMPLETE(3, - printk("Command needs retry %d %d 0x%x\n", - SCpnt->host->host_busy, - SCpnt->host->host_failed, - SCpnt->result)); - - scsi_retry_command(SCpnt); - break; - case ADD_TO_MLQUEUE: - /* - * This typically happens for a QUEUE_FULL message - - * typically only when the queue depth is only - * approximate for a given device. Adding a command - * to the queue for the device will prevent further commands - * from being sent to the device, so we shouldn't end up - * with tons of things being sent down that shouldn't be. - */ - SCSI_LOG_MLCOMPLETE(3, printk( - "Cmnd rejected as device queue full, put on ml queue %p\n", - SCpnt)); - scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_DEVICE_BUSY); - break; - default: - /* - * Here we have a fatal error of some sort. Turn it over to - * the error handler. - */ - SCSI_LOG_MLCOMPLETE(3, printk( - "Command failed %p %x active=%d busy=%d failed=%d\n", - SCpnt, SCpnt->result, - atomic_read(&SCpnt->host->host_active), - SCpnt->host->host_busy, - SCpnt->host->host_failed)); - - /* - * Dump the sense information too. - */ - if ((status_byte(SCpnt->result) & CHECK_CONDITION) != 0) { - SCSI_LOG_MLCOMPLETE(3, print_sense("bh", SCpnt)); - } - if (SCpnt->host->eh_wait != NULL) { - SCpnt->host->host_failed++; - SCpnt->owner = SCSI_OWNER_ERROR_HANDLER; - SCpnt->state = SCSI_STATE_FAILED; - SCpnt->host->in_recovery = 1; - /* - * If the host is having troubles, then look to - * see if this was the last command that might - * have failed. If so, wake up the error handler. */ - if (SCpnt->host->host_busy == SCpnt->host->host_failed) { -#if 0 - SCSI_LOG_ERROR_RECOVERY(5, printk( - "Waking error handler thread (%d)\n", - atomic_read(&SCpnt->host->eh_wait->count))); - up(SCpnt->host->eh_wait); -#endif - } - } else { - /* - * We only get here if the error recovery thread has died. - */ - printk("scsi_bh: error finish\n"); - scsi_finish_command(SCpnt); - } - } - } /* for(; SCpnt...) */ - - } /* while(1==1) */ - -} - -/* - * Function: scsi_retry_command - * - * Purpose: Send a command back to the low level to be retried. - * - * Notes: This command is always executed in the context of the - * bottom half handler, or the error handler thread. Low - * level drivers should not become re-entrant as a result of - * this. - */ -int scsi_retry_command(Scsi_Cmnd * SCpnt) -{ - memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd, - sizeof(SCpnt->data_cmnd)); - SCpnt->request_buffer = SCpnt->buffer; - SCpnt->request_bufflen = SCpnt->bufflen; - SCpnt->use_sg = SCpnt->old_use_sg; - SCpnt->cmd_len = SCpnt->old_cmd_len; - SCpnt->sc_data_direction = SCpnt->sc_old_data_direction; - SCpnt->underflow = SCpnt->old_underflow; - - /* - * Zero the sense information from the last time we tried - * this command. - */ - memset((void *) SCpnt->sense_buffer, 0, sizeof SCpnt->sense_buffer); - - return scsi_dispatch_cmd(SCpnt); -} - -/* - * Function: scsi_finish_command - * - * Purpose: Pass command off to upper layer for finishing of I/O - * request, waking processes that are waiting on results, - * etc. - */ -void scsi_finish_command(Scsi_Cmnd * SCpnt) -{ - struct Scsi_Host *host; - Scsi_Device *device; - Scsi_Request * SRpnt; - unsigned long flags; - - ASSERT_LOCK(&io_request_lock, 0); - - host = SCpnt->host; - device = SCpnt->device; - - /* - * We need to protect the decrement, as otherwise a race condition - * would exist. Fiddling with SCpnt isn't a problem as the - * design only allows a single SCpnt to be active in only - * one execution context, but the device and host structures are - * shared. - */ - spin_lock_irqsave(&io_request_lock, flags); - host->host_busy--; /* Indicate that we are free */ - device->device_busy--; /* Decrement device usage counter. */ - spin_unlock_irqrestore(&io_request_lock, flags); - - /* - * Clear the flags which say that the device/host is no longer - * capable of accepting new commands. These are set in scsi_queue.c - * for both the queue full condition on a device, and for a - * host full condition on the host. - */ - host->host_blocked = FALSE; - device->device_blocked = FALSE; - - /* - * If we have valid sense information, then some kind of recovery - * must have taken place. Make a note of this. - */ - if (scsi_sense_valid(SCpnt)) { - SCpnt->result |= (DRIVER_SENSE << 24); - } - SCSI_LOG_MLCOMPLETE(3, printk( - "Notifying upper driver of completion for device %d %x\n", - SCpnt->device->id, SCpnt->result)); - - SCpnt->owner = SCSI_OWNER_HIGHLEVEL; - SCpnt->state = SCSI_STATE_FINISHED; - - /* We can get here with use_sg=0, causing a panic in the - upper level (DB) */ - SCpnt->use_sg = SCpnt->old_use_sg; - - /* - * If there is an associated request structure, copy the data over - * before we call the * completion function. - */ - SRpnt = SCpnt->sc_request; - - if( SRpnt != NULL ) { - if(!SRpnt->sr_command) { - printk("scsi_finish_command: SRpnt=%p, SRpnt->sr_command=%p\n", - SRpnt, SRpnt->sr_command); - printk("SRpnt->freeaddr = %p\n", SRpnt->freeaddr); - BUG(); - } - SRpnt->sr_result = SRpnt->sr_command->result; - if( SRpnt->sr_result != 0 ) { - memcpy(SRpnt->sr_sense_buffer, - SRpnt->sr_command->sense_buffer, - sizeof(SRpnt->sr_sense_buffer)); - } - } - - SCpnt->done(SCpnt); -} - -static int scsi_register_host(Scsi_Host_Template *); -static int scsi_unregister_host(Scsi_Host_Template *); - -/* - * Function: scsi_release_commandblocks() - * - * Purpose: Release command blocks associated with a device. - * - * Arguments: SDpnt - device - * - * Returns: Nothing - * - * Lock status: No locking assumed or required. - * - * Notes: - */ -void scsi_release_commandblocks(Scsi_Device * SDpnt) -{ - Scsi_Cmnd *SCpnt, *SCnext; - unsigned long flags; - - spin_lock_irqsave(&device_request_lock, flags); - for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCnext) { - SDpnt->device_queue = SCnext = SCpnt->next; - kfree((char *) SCpnt); - } - SDpnt->has_cmdblocks = 0; - SDpnt->queue_depth = 0; - spin_unlock_irqrestore(&device_request_lock, flags); -} - -/* - * Function: scsi_build_commandblocks() - * - * Purpose: Allocate command blocks associated with a device. - * - * Arguments: SDpnt - device - * - * Returns: Nothing - * - * Lock status: No locking assumed or required. - * - * Notes: - */ -void scsi_build_commandblocks(Scsi_Device * SDpnt) -{ - unsigned long flags; - struct Scsi_Host *host = SDpnt->host; - int j; - Scsi_Cmnd *SCpnt; - - spin_lock_irqsave(&device_request_lock, flags); - - if (SDpnt->queue_depth == 0) - { - SDpnt->queue_depth = host->cmd_per_lun; - if (SDpnt->queue_depth == 0) - SDpnt->queue_depth = 1; /* live to fight another day */ - } - SDpnt->device_queue = NULL; - - for (j = 0; j < SDpnt->queue_depth; j++) { - SCpnt = (Scsi_Cmnd *) - kmalloc(sizeof(Scsi_Cmnd), - GFP_ATOMIC | - (host->unchecked_isa_dma ? GFP_DMA : 0)); - if (NULL == SCpnt) - break; /* If not, the next line will oops ... */ - memset(SCpnt, 0, sizeof(Scsi_Cmnd)); - SCpnt->host = host; - SCpnt->device = SDpnt; - SCpnt->target = SDpnt->id; - SCpnt->lun = SDpnt->lun; - SCpnt->channel = SDpnt->channel; - SCpnt->request.rq_status = RQ_INACTIVE; - SCpnt->use_sg = 0; - SCpnt->old_use_sg = 0; - SCpnt->old_cmd_len = 0; - SCpnt->underflow = 0; - SCpnt->old_underflow = 0; - SCpnt->transfersize = 0; - SCpnt->resid = 0; - SCpnt->serial_number = 0; - SCpnt->serial_number_at_timeout = 0; - SCpnt->host_scribble = NULL; - SCpnt->next = SDpnt->device_queue; - SDpnt->device_queue = SCpnt; - SCpnt->state = SCSI_STATE_UNUSED; - SCpnt->owner = SCSI_OWNER_NOBODY; - } - if (j < SDpnt->queue_depth) { /* low on space (D.Gilbert 990424) */ - printk(KERN_WARNING "scsi_build_commandblocks: want=%d, space for=%d blocks\n", - SDpnt->queue_depth, j); - SDpnt->queue_depth = j; - SDpnt->has_cmdblocks = (0 != j); - } else { - SDpnt->has_cmdblocks = 1; - } - spin_unlock_irqrestore(&device_request_lock, flags); -} - -void __init scsi_host_no_insert(char *str, int n) -{ - Scsi_Host_Name *shn, *shn2; - int len; - - len = strlen(str); - if (len && (shn = (Scsi_Host_Name *) kmalloc(sizeof(Scsi_Host_Name), GFP_ATOMIC))) { - if ((shn->name = kmalloc(len+1, GFP_ATOMIC))) { - strncpy(shn->name, str, len); - shn->name[len] = 0; - shn->host_no = n; - shn->host_registered = 0; - shn->loaded_as_module = 1; /* numbers shouldn't be freed in any case */ - shn->next = NULL; - if (scsi_host_no_list) { - for (shn2 = scsi_host_no_list;shn2->next;shn2 = shn2->next) - ; - shn2->next = shn; - } - else - scsi_host_no_list = shn; - max_scsi_hosts = n+1; - } - else - kfree((char *) shn); - } -} - -#ifdef CONFIG_PROC_FS -static int scsi_proc_info(char *buffer, char **start, off_t offset, int length) -{ - Scsi_Device *scd; - struct Scsi_Host *HBA_ptr; - int size, len = 0; - off_t begin = 0; - off_t pos = 0; - - /* - * First, see if there are any attached devices or not. - */ - for (HBA_ptr = scsi_hostlist; HBA_ptr; HBA_ptr = HBA_ptr->next) { - if (HBA_ptr->host_queue != NULL) { - break; - } - } - size = sprintf(buffer + len, "Attached devices: %s\n", (HBA_ptr) ? "" : "none"); - len += size; - pos = begin + len; - for (HBA_ptr = scsi_hostlist; HBA_ptr; HBA_ptr = HBA_ptr->next) { -#if 0 - size += sprintf(buffer + len, "scsi%2d: %s\n", (int) HBA_ptr->host_no, - HBA_ptr->hostt->procname); - len += size; - pos = begin + len; -#endif - for (scd = HBA_ptr->host_queue; scd; scd = scd->next) { - proc_print_scsidevice(scd, buffer, &size, len); - len += size; - pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - goto stop_output; - } - } - -stop_output: - *start = buffer + (offset - begin); /* Start of wanted data */ - len -= (offset - begin); /* Start slop */ - if (len > length) - len = length; /* Ending slop */ - return (len); -} - -static int proc_scsi_gen_write(struct file * file, const char * buf, - unsigned long length, void *data) -{ - struct Scsi_Device_Template *SDTpnt; - Scsi_Device *scd; - struct Scsi_Host *HBA_ptr; - char *p; - int host, channel, id, lun; - char * buffer; - int err; - - if (!buf || length>PAGE_SIZE) - return -EINVAL; - - if (!(buffer = (char *) __get_free_page(GFP_KERNEL))) - return -ENOMEM; - if(copy_from_user(buffer, buf, length)) - { - err =-EFAULT; - goto out; - } - - err = -EINVAL; - - if (length < PAGE_SIZE) - buffer[length] = '\0'; - else if (buffer[PAGE_SIZE-1]) - goto out; - - if (length < 11 || strncmp("scsi", buffer, 4)) - goto out; - - /* - * Usage: echo "scsi dump #N" > /proc/scsi/scsi - * to dump status of all scsi commands. The number is used to specify the level - * of detail in the dump. - */ - if (!strncmp("dump", buffer + 5, 4)) { - unsigned int level; - - p = buffer + 10; - - if (*p == '\0') - goto out; - - level = simple_strtoul(p, NULL, 0); - scsi_dump_status(level); - } - /* - * Usage: echo "scsi log token #N" > /proc/scsi/scsi - * where token is one of [error,scan,mlqueue,mlcomplete,llqueue, - * llcomplete,hlqueue,hlcomplete] - */ -#ifdef CONFIG_SCSI_LOGGING /* { */ - - if (!strncmp("log", buffer + 5, 3)) { - char *token; - unsigned int level; - - p = buffer + 9; - token = p; - while (*p != ' ' && *p != '\t' && *p != '\0') { - p++; - } - - if (*p == '\0') { - if (strncmp(token, "all", 3) == 0) { - /* - * Turn on absolutely everything. - */ - scsi_logging_level = ~0; - } else if (strncmp(token, "none", 4) == 0) { - /* - * Turn off absolutely everything. - */ - scsi_logging_level = 0; - } else { - goto out; - } - } else { - *p++ = '\0'; - - level = simple_strtoul(p, NULL, 0); - - /* - * Now figure out what to do with it. - */ - if (strcmp(token, "error") == 0) { - SCSI_SET_ERROR_RECOVERY_LOGGING(level); - } else if (strcmp(token, "timeout") == 0) { - SCSI_SET_TIMEOUT_LOGGING(level); - } else if (strcmp(token, "scan") == 0) { - SCSI_SET_SCAN_BUS_LOGGING(level); - } else if (strcmp(token, "mlqueue") == 0) { - SCSI_SET_MLQUEUE_LOGGING(level); - } else if (strcmp(token, "mlcomplete") == 0) { - SCSI_SET_MLCOMPLETE_LOGGING(level); - } else if (strcmp(token, "llqueue") == 0) { - SCSI_SET_LLQUEUE_LOGGING(level); - } else if (strcmp(token, "llcomplete") == 0) { - SCSI_SET_LLCOMPLETE_LOGGING(level); - } else if (strcmp(token, "hlqueue") == 0) { - SCSI_SET_HLQUEUE_LOGGING(level); - } else if (strcmp(token, "hlcomplete") == 0) { - SCSI_SET_HLCOMPLETE_LOGGING(level); - } else if (strcmp(token, "ioctl") == 0) { - SCSI_SET_IOCTL_LOGGING(level); - } else { - goto out; - } - } - - printk(KERN_INFO "scsi logging level set to 0x%8.8x\n", scsi_logging_level); - } -#endif /* CONFIG_SCSI_LOGGING */ /* } */ - - /* - * Usage: echo "scsi add-single-device 0 1 2 3" >/proc/scsi/scsi - * with "0 1 2 3" replaced by your "Host Channel Id Lun". - * Consider this feature BETA. - * CAUTION: This is not for hotplugging your peripherals. As - * SCSI was not designed for this you could damage your - * hardware ! - * However perhaps it is legal to switch on an - * already connected device. It is perhaps not - * guaranteed this device doesn't corrupt an ongoing data transfer. - */ - if (!strncmp("add-single-device", buffer + 5, 17)) { - p = buffer + 23; - - host = simple_strtoul(p, &p, 0); - channel = simple_strtoul(p + 1, &p, 0); - id = simple_strtoul(p + 1, &p, 0); - lun = simple_strtoul(p + 1, &p, 0); - - printk(KERN_INFO "scsi singledevice %d %d %d %d\n", host, channel, - id, lun); - - for (HBA_ptr = scsi_hostlist; HBA_ptr; HBA_ptr = HBA_ptr->next) { - if (HBA_ptr->host_no == host) { - break; - } - } - err = -ENXIO; - if (!HBA_ptr) - goto out; - - for (scd = HBA_ptr->host_queue; scd; scd = scd->next) { - if ((scd->channel == channel - && scd->id == id - && scd->lun == lun)) { - break; - } - } - - err = -ENOSYS; - if (scd) - goto out; /* We do not yet support unplugging */ - - scan_scsis(HBA_ptr, 1, channel, id, lun); - - /* FIXME (DB) This assumes that the queue_depth routines can be used - in this context as well, while they were all designed to be - called only once after the detect routine. (DB) */ - /* queue_depth routine moved to inside scan_scsis(,1,,,) so - it is called before build_commandblocks() */ - - err = length; - goto out; - } - /* - * Usage: echo "scsi remove-single-device 0 1 2 3" >/proc/scsi/scsi - * with "0 1 2 3" replaced by your "Host Channel Id Lun". - * - * Consider this feature pre-BETA. - * - * CAUTION: This is not for hotplugging your peripherals. As - * SCSI was not designed for this you could damage your - * hardware and thoroughly confuse the SCSI subsystem. - * - */ - else if (!strncmp("remove-single-device", buffer + 5, 20)) { - p = buffer + 26; - - host = simple_strtoul(p, &p, 0); - channel = simple_strtoul(p + 1, &p, 0); - id = simple_strtoul(p + 1, &p, 0); - lun = simple_strtoul(p + 1, &p, 0); - - - for (HBA_ptr = scsi_hostlist; HBA_ptr; HBA_ptr = HBA_ptr->next) { - if (HBA_ptr->host_no == host) { - break; - } - } - err = -ENODEV; - if (!HBA_ptr) - goto out; - - for (scd = HBA_ptr->host_queue; scd; scd = scd->next) { - if ((scd->channel == channel - && scd->id == id - && scd->lun == lun)) { - break; - } - } - - if (scd == NULL) - goto out; /* there is no such device attached */ - - err = -EBUSY; - if (scd->access_count) - goto out; - - SDTpnt = scsi_devicelist; - while (SDTpnt != NULL) { - if (SDTpnt->detach) - (*SDTpnt->detach) (scd); - SDTpnt = SDTpnt->next; - } - - if (scd->attached == 0) { - /* - * Nobody is using this device any more. - * Free all of the command structures. - */ - if (HBA_ptr->hostt->revoke) - HBA_ptr->hostt->revoke(scd); -#ifdef DEVFS_MUST_DIE - devfs_unregister (scd->de); -#endif - scsi_release_commandblocks(scd); - - /* Now we can remove the device structure */ - if (scd->next != NULL) - scd->next->prev = scd->prev; - - if (scd->prev != NULL) - scd->prev->next = scd->next; - - if (HBA_ptr->host_queue == scd) { - HBA_ptr->host_queue = scd->next; - } - blk_cleanup_queue(&scd->request_queue); - kfree((char *) scd); - } else { - goto out; - } - err = 0; - } -out: - - free_page((unsigned long) buffer); - return err; -} -#endif - -/* - * This entry point should be called by a driver if it is trying - * to add a low level scsi driver to the system. - */ -static int scsi_register_host(Scsi_Host_Template * tpnt) -{ - int pcount; - struct Scsi_Host *shpnt; - Scsi_Device *SDpnt; - struct Scsi_Device_Template *sdtpnt; - const char *name; - unsigned long flags; - int out_of_space = 0; - - if (tpnt->next || !tpnt->detect) - return 1; /* Must be already loaded, or - * no detect routine available - */ - - /* If max_sectors isn't set, default to max */ - if (!tpnt->max_sectors) - tpnt->max_sectors = MAX_SECTORS; - - pcount = next_scsi_host; - - MOD_INC_USE_COUNT; - - /* The detect routine must carefully spinunlock/spinlock if - it enables interrupts, since all interrupt handlers do - spinlock as well. - All lame drivers are going to fail due to the following - spinlock. For the time beeing let's use it only for drivers - using the new scsi code. NOTE: the detect routine could - redefine the value tpnt->use_new_eh_code. (DB, 13 May 1998) */ - - if (tpnt->use_new_eh_code) { - spin_lock_irqsave(&io_request_lock, flags); - tpnt->present = tpnt->detect(tpnt); - spin_unlock_irqrestore(&io_request_lock, flags); - } else - tpnt->present = tpnt->detect(tpnt); - - if (tpnt->present) { - if (pcount == next_scsi_host) { - if (tpnt->present > 1) { - printk(KERN_ERR "scsi: Failure to register low-level " - "scsi driver"); - scsi_unregister_host(tpnt); - return 1; - } - /* - * The low-level driver failed to register a driver. - * We can do this now. - */ - if(scsi_register(tpnt, 0)==NULL) - { - printk(KERN_ERR "scsi: register failed.\n"); - scsi_unregister_host(tpnt); - return 1; - } - } - tpnt->next = scsi_hosts; /* Add to the linked list */ - scsi_hosts = tpnt; - - /* Add the new driver to /proc/scsi */ -#ifdef CONFIG_PROC_FS - build_proc_dir_entries(tpnt); -#endif - - -#if 0 - /* - * Add the kernel threads for each host adapter that will - * handle error correction. - */ - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - if (shpnt->hostt == tpnt && shpnt->hostt->use_new_eh_code) { - DECLARE_MUTEX_LOCKED(sem); - - shpnt->eh_notify = &sem; - kernel_thread((int (*)(void *)) scsi_error_handler, - (void *) shpnt, 0); - - /* - * Now wait for the kernel error thread to initialize itself - * as it might be needed when we scan the bus. - */ - down(&sem); - shpnt->eh_notify = NULL; - } - } -#endif - - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - if (shpnt->hostt == tpnt) { - if (tpnt->info) { - name = tpnt->info(shpnt); - } else { - name = tpnt->name; - } - printk(KERN_INFO "scsi%d : %s\n", /* And print a little message */ - shpnt->host_no, name); - } - } - - /* The next step is to call scan_scsis here. This generates the - * Scsi_Devices entries - */ - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - if (shpnt->hostt == tpnt) { - scan_scsis(shpnt, 0, 0, 0, 0); - if (shpnt->select_queue_depths != NULL) { - (shpnt->select_queue_depths) (shpnt, shpnt->host_queue); - } - } - } - - for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) { - if (sdtpnt->init && sdtpnt->dev_noticed) - (*sdtpnt->init) (); - } - - /* - * Next we create the Scsi_Cmnd structures for this host - */ - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next) - if (SDpnt->host->hostt == tpnt) { - for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if (sdtpnt->attach) - (*sdtpnt->attach) (SDpnt); - if (SDpnt->attached) { - scsi_build_commandblocks(SDpnt); - if (0 == SDpnt->has_cmdblocks) - out_of_space = 1; - } - } - } - - /* - * Now that we have all of the devices, resize the DMA pool, - * as required. */ - if (!out_of_space) - scsi_resize_dma_pool(); - - - /* This does any final handling that is required. */ - for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) { - if (sdtpnt->finish && sdtpnt->nr_dev) { - (*sdtpnt->finish) (); - } - } - } -#if defined(USE_STATIC_SCSI_MEMORY) - printk("SCSI memory: total %ldKb, used %ldKb, free %ldKb.\n", - (scsi_memory_upper_value - scsi_memory_lower_value) / 1024, - (scsi_init_memory_start - scsi_memory_lower_value) / 1024, - (scsi_memory_upper_value - scsi_init_memory_start) / 1024); -#endif - - if (out_of_space) { - scsi_unregister_host(tpnt); /* easiest way to clean up?? */ - return 1; - } else - return 0; -} - - -/* - * Similarly, this entry point should be called by a loadable module if it - * is trying to remove a low level scsi driver from the system. - */ -static int scsi_unregister_host(Scsi_Host_Template * tpnt) -{ - int online_status; - int pcount0, pcount; - Scsi_Cmnd *SCpnt; - Scsi_Device *SDpnt; - Scsi_Device *SDpnt1; - struct Scsi_Device_Template *sdtpnt; - struct Scsi_Host *sh1; - struct Scsi_Host *shpnt; - char name[10]; /* host_no>=10^9? I don't think so. */ - -#if 0 - /* get the big kernel lock, so we don't race with open() */ - lock_kernel(); -#endif - - /* - * First verify that this host adapter is completely free with no pending - * commands - */ - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - for (SDpnt = shpnt->host_queue; SDpnt; - SDpnt = SDpnt->next) { - if (SDpnt->host->hostt == tpnt - && SDpnt->host->hostt->module - && GET_USE_COUNT(SDpnt->host->hostt->module)) - goto err_out; - /* - * FIXME(eric) - We need to find a way to notify the - * low level driver that we are shutting down - via the - * special device entry that still needs to get added. - * - * Is detach interface below good enough for this? - */ - } - } - - /* - * FIXME(eric) put a spinlock on this. We force all of the devices offline - * to help prevent race conditions where other hosts/processors could try and - * get in and queue a command. - */ - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - for (SDpnt = shpnt->host_queue; SDpnt; - SDpnt = SDpnt->next) { - if (SDpnt->host->hostt == tpnt) - SDpnt->online = FALSE; - - } - } - - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - if (shpnt->hostt != tpnt) { - continue; - } - for (SDpnt = shpnt->host_queue; SDpnt; - SDpnt = SDpnt->next) { - /* - * Loop over all of the commands associated with the device. If any of - * them are busy, then set the state back to inactive and bail. - */ - for (SCpnt = SDpnt->device_queue; SCpnt; - SCpnt = SCpnt->next) { - online_status = SDpnt->online; - SDpnt->online = FALSE; - if (SCpnt->request.rq_status != RQ_INACTIVE) { - printk(KERN_ERR "SCSI device not inactive - rq_status=%d, target=%d, pid=%ld, state=%d, owner=%d.\n", - SCpnt->request.rq_status, SCpnt->target, SCpnt->pid, - SCpnt->state, SCpnt->owner); - for (SDpnt1 = shpnt->host_queue; SDpnt1; - SDpnt1 = SDpnt1->next) { - for (SCpnt = SDpnt1->device_queue; SCpnt; - SCpnt = SCpnt->next) - if (SCpnt->request.rq_status == RQ_SCSI_DISCONNECTING) - SCpnt->request.rq_status = RQ_INACTIVE; - } - SDpnt->online = online_status; - printk(KERN_ERR "Device busy???\n"); - goto err_out; - } - /* - * No, this device is really free. Mark it as such, and - * continue on. - */ - SCpnt->state = SCSI_STATE_DISCONNECTING; - SCpnt->request.rq_status = RQ_SCSI_DISCONNECTING; /* Mark as busy */ - } - } - } - /* Next we detach the high level drivers from the Scsi_Device structures */ - - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - if (shpnt->hostt != tpnt) { - continue; - } - for (SDpnt = shpnt->host_queue; SDpnt; - SDpnt = SDpnt->next) { - for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if (sdtpnt->detach) - (*sdtpnt->detach) (SDpnt); - - /* If something still attached, punt */ - if (SDpnt->attached) { - printk(KERN_ERR "Attached usage count = %d\n", SDpnt->attached); - goto err_out; - } -#ifdef DEVFS_MUST_DIE - devfs_unregister (SDpnt->de); -#endif - } - } - -#if 0 - /* - * Next, kill the kernel error recovery thread for this host. - */ - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - if (shpnt->hostt == tpnt - && shpnt->hostt->use_new_eh_code - && shpnt->ehandler != NULL) { - DECLARE_MUTEX_LOCKED(sem); - - shpnt->eh_notify = &sem; - send_sig(SIGHUP, shpnt->ehandler, 1); - down(&sem); - shpnt->eh_notify = NULL; - } - } -#endif - - /* Next we free up the Scsi_Cmnd structures for this host */ - - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - if (shpnt->hostt != tpnt) { - continue; - } - for (SDpnt = shpnt->host_queue; SDpnt; - SDpnt = shpnt->host_queue) { - scsi_release_commandblocks(SDpnt); - - blk_cleanup_queue(&SDpnt->request_queue); - /* Next free up the Scsi_Device structures for this host */ - shpnt->host_queue = SDpnt->next; - kfree((char *) SDpnt); - - } - } - - /* Next we go through and remove the instances of the individual hosts - * that were detected */ - - pcount0 = next_scsi_host; - for (shpnt = scsi_hostlist; shpnt; shpnt = sh1) { - sh1 = shpnt->next; - if (shpnt->hostt != tpnt) - continue; - pcount = next_scsi_host; - /* Remove the /proc/scsi directory entry */ - sprintf(name,"%d",shpnt->host_no); -#ifdef CONFIG_PROC_FS - remove_proc_entry(name, tpnt->proc_dir); -#endif - if (tpnt->release) - (*tpnt->release) (shpnt); - else { - /* This is the default case for the release function. - * It should do the right thing for most correctly - * written host adapters. - */ - if (shpnt->irq) - free_irq(shpnt->irq, NULL); - -#if 0 - if (shpnt->dma_channel != 0xff) - free_dma(shpnt->dma_channel); -#endif - if (shpnt->io_port && shpnt->n_io_port) - release_region(shpnt->io_port, shpnt->n_io_port); - } - if (pcount == next_scsi_host) - scsi_unregister(shpnt); - tpnt->present--; - } - - /* - * If there are absolutely no more hosts left, it is safe - * to completely nuke the DMA pool. The resize operation will - * do the right thing and free everything. - */ - if (!scsi_hosts) - scsi_resize_dma_pool(); - - if (pcount0 != next_scsi_host) - printk(KERN_INFO "scsi : %d host%s left.\n", next_scsi_host, - (next_scsi_host == 1) ? "" : "s"); - -#if defined(USE_STATIC_SCSI_MEMORY) - printk("SCSI memory: total %ldKb, used %ldKb, free %ldKb.\n", - (scsi_memory_upper_value - scsi_memory_lower_value) / 1024, - (scsi_init_memory_start - scsi_memory_lower_value) / 1024, - (scsi_memory_upper_value - scsi_init_memory_start) / 1024); -#endif - - /* - * Remove it from the linked list and /proc if all - * hosts were successfully removed (ie preset == 0) - */ - if (!tpnt->present) { - Scsi_Host_Template **SHTp = &scsi_hosts; - Scsi_Host_Template *SHT; - - while ((SHT = *SHTp) != NULL) { - if (SHT == tpnt) { - *SHTp = SHT->next; -#ifdef CONFIG_PROC_FS - remove_proc_entry(tpnt->proc_name, proc_scsi); -#endif - break; - } - SHTp = &SHT->next; - } - } - MOD_DEC_USE_COUNT; - -#if 0 - unlock_kernel(); -#endif - return 0; - -err_out: - -#if 0 - unlock_kernel(); -#endif - return -1; -} - -static int scsi_unregister_device(struct Scsi_Device_Template *tpnt); - -/* - * This entry point should be called by a loadable module if it is trying - * add a high level scsi driver to the system. - */ -static int scsi_register_device_module(struct Scsi_Device_Template *tpnt) -{ - Scsi_Device *SDpnt; - struct Scsi_Host *shpnt; - int out_of_space = 0; - - if (tpnt->next) - return 1; - - scsi_register_device(tpnt); - /* - * First scan the devices that we know about, and see if we notice them. - */ - - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - for (SDpnt = shpnt->host_queue; SDpnt; - SDpnt = SDpnt->next) { - if (tpnt->detect) - SDpnt->detected = (*tpnt->detect) (SDpnt); - } - } - - /* - * If any of the devices would match this driver, then perform the - * init function. - */ - if (tpnt->init && tpnt->dev_noticed) { - if ((*tpnt->init) ()) { - for (shpnt = scsi_hostlist; shpnt; - shpnt = shpnt->next) { - for (SDpnt = shpnt->host_queue; SDpnt; - SDpnt = SDpnt->next) { - SDpnt->detected = 0; - } - } - scsi_deregister_device(tpnt); - return 1; - } - } - - /* - * Now actually connect the devices to the new driver. - */ - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - for (SDpnt = shpnt->host_queue; SDpnt; - SDpnt = SDpnt->next) { - SDpnt->attached += SDpnt->detected; - SDpnt->detected = 0; - if (tpnt->attach) - (*tpnt->attach) (SDpnt); - /* - * If this driver attached to the device, and don't have any - * command blocks for this device, allocate some. - */ - if (SDpnt->attached && SDpnt->has_cmdblocks == 0) { - SDpnt->online = TRUE; - scsi_build_commandblocks(SDpnt); - if (0 == SDpnt->has_cmdblocks) - out_of_space = 1; - } - } - } - - /* - * This does any final handling that is required. - */ - if (tpnt->finish && tpnt->nr_dev) - (*tpnt->finish) (); - if (!out_of_space) - scsi_resize_dma_pool(); - MOD_INC_USE_COUNT; - - if (out_of_space) { - scsi_unregister_device(tpnt); /* easiest way to clean up?? */ - return 1; - } else - return 0; -} - -static int scsi_unregister_device(struct Scsi_Device_Template *tpnt) -{ - Scsi_Device *SDpnt; - struct Scsi_Host *shpnt; - -#if 0 - lock_kernel(); -#endif - /* - * If we are busy, this is not going to fly. - */ - if (GET_USE_COUNT(tpnt->module) != 0) - goto error_out; - - /* - * Next, detach the devices from the driver. - */ - - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - for (SDpnt = shpnt->host_queue; SDpnt; - SDpnt = SDpnt->next) { - if (tpnt->detach) - (*tpnt->detach) (SDpnt); - if (SDpnt->attached == 0) { - SDpnt->online = FALSE; - - /* - * Nobody is using this device any more. Free all of the - * command structures. - */ - scsi_release_commandblocks(SDpnt); - } - } - } - /* - * Extract the template from the linked list. - */ - scsi_deregister_device(tpnt); - - MOD_DEC_USE_COUNT; -#if 0 - unlock_kernel(); -#endif - - /* - * Final cleanup for the driver is done in the driver sources in the - * cleanup function. - */ - return 0; -error_out: -#if 0 - unlock_kernel(); -#endif - return -1; -} - - -/* This function should be called by drivers which needs to register - * with the midlevel scsi system. As of 2.4.0-test9pre3 this is our - * main device/hosts register function /mathiasen - */ -int scsi_register_module(int module_type, void *ptr) -{ - switch (module_type) { - case MODULE_SCSI_HA: - return scsi_register_host((Scsi_Host_Template *) ptr); - - /* Load upper level device handler of some kind */ - case MODULE_SCSI_DEV: -#ifdef CONFIG_KMOD - if (scsi_hosts == NULL) - request_module("scsi_hostadapter"); -#endif - return scsi_register_device_module((struct Scsi_Device_Template *) ptr); - /* The rest of these are not yet implemented */ - - /* Load constants.o */ - case MODULE_SCSI_CONST: - - /* Load specialized ioctl handler for some device. Intended for - * cdroms that have non-SCSI2 audio command sets. */ - case MODULE_SCSI_IOCTL: - - default: - return 1; - } -} - -/* Reverse the actions taken above - */ -int scsi_unregister_module(int module_type, void *ptr) -{ - int retval = 0; - - switch (module_type) { - case MODULE_SCSI_HA: - retval = scsi_unregister_host((Scsi_Host_Template *) ptr); - break; - case MODULE_SCSI_DEV: - retval = scsi_unregister_device((struct Scsi_Device_Template *)ptr); - break; - /* The rest of these are not yet implemented. */ - case MODULE_SCSI_CONST: - case MODULE_SCSI_IOCTL: - break; - default:; - } - return retval; -} - -#ifdef CONFIG_PROC_FS -/* - * Function: scsi_dump_status - * - * Purpose: Brain dump of scsi system, used for problem solving. - * - * Arguments: level - used to indicate level of detail. - * - * Notes: The level isn't used at all yet, but we need to find some way - * of sensibly logging varying degrees of information. A quick one-line - * display of each command, plus the status would be most useful. - * - * This does depend upon CONFIG_SCSI_LOGGING - I do want some way of turning - * it all off if the user wants a lean and mean kernel. It would probably - * also be useful to allow the user to specify one single host to be dumped. - * A second argument to the function would be useful for that purpose. - * - * FIXME - some formatting of the output into tables would be very handy. - */ -static void scsi_dump_status(int level) -{ -#ifdef CONFIG_SCSI_LOGGING /* { */ - int i; - struct Scsi_Host *shpnt; - Scsi_Cmnd *SCpnt; - Scsi_Device *SDpnt; - printk(KERN_INFO "Dump of scsi host parameters:\n"); - i = 0; - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - printk(KERN_INFO " %d %d %d : %d %d\n", - shpnt->host_failed, - shpnt->host_busy, - atomic_read(&shpnt->host_active), - shpnt->host_blocked, - shpnt->host_self_blocked); - } - - printk(KERN_INFO "\n\n"); - printk(KERN_INFO "Dump of scsi command parameters:\n"); - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - printk(KERN_INFO "h:c:t:l (dev sect nsect cnumsec sg) (ret all flg) (to/cmd to ito) cmd snse result\n"); - for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next) { - for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) { - /* (0) h:c:t:l (dev sect nsect cnumsec sg) (ret all flg) (to/cmd to ito) cmd snse result %d %x */ - printk(KERN_INFO "(%3d) %2d:%1d:%2d:%2d (%6s %4ld %4ld %4ld %4x %1d) (%1d %1d 0x%2x) (%4d %4d %4d) 0x%2.2x 0x%2.2x 0x%8.8x\n", - i++, - - SCpnt->host->host_no, - SCpnt->channel, - SCpnt->target, - SCpnt->lun, - - kdevname(SCpnt->request.rq_dev), - SCpnt->request.sector, - SCpnt->request.nr_sectors, - SCpnt->request.current_nr_sectors, - SCpnt->request.rq_status, - SCpnt->use_sg, - - SCpnt->retries, - SCpnt->allowed, - SCpnt->flags, - - SCpnt->timeout_per_command, - SCpnt->timeout, - SCpnt->internal_timeout, - - SCpnt->cmnd[0], - SCpnt->sense_buffer[2], - SCpnt->result); - } - } - } - - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next) { - /* Now dump the request lists for each block device */ - printk(KERN_INFO "Dump of pending block device requests\n"); - for (i = 0; i < MAX_BLKDEV; i++) { - struct list_head * queue_head; - - queue_head = &blk_dev[i].request_queue.queue_head; - if (!list_empty(queue_head)) { - struct request *req; - struct list_head * entry; - - printk(KERN_INFO "%d: ", i); - entry = queue_head->next; - do { - req = blkdev_entry_to_request(entry); - printk("(%s %d %ld %ld %ld) ", - kdevname(req->rq_dev), - req->cmd, - req->sector, - req->nr_sectors, - req->current_nr_sectors); - } while ((entry = entry->next) != queue_head); - printk("\n"); - } - } - } - } -#endif /* CONFIG_SCSI_LOGGING */ /* } */ -} -#endif /* CONFIG_PROC_FS */ - -static int __init scsi_host_no_init (char *str) -{ - static int next_no = 0; - char *temp; - - while (str) { - temp = str; - while (*temp && (*temp != ':') && (*temp != ',')) - temp++; - if (!*temp) - temp = NULL; - else - *temp++ = 0; - scsi_host_no_insert(str, next_no); - str = temp; - next_no++; - } - return 1; -} - -static char *scsihosts; - -MODULE_PARM(scsihosts, "s"); -MODULE_DESCRIPTION("SCSI core"); -MODULE_LICENSE("GPL"); - -#ifndef MODULE -int __init scsi_setup(char *str) -{ - scsihosts = str; - return 1; -} - -__setup("scsihosts=", scsi_setup); -#endif - -static int __init init_scsi(void) -{ -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *generic; -#endif - - printk(KERN_INFO "SCSI subsystem driver " REVISION "\n"); - - if( scsi_init_minimal_dma_pool() != 0 ) - { - return 1; - } - -#ifdef CONFIG_PROC_FS - /* - * This makes /proc/scsi and /proc/scsi/scsi visible. - */ - proc_scsi = proc_mkdir("scsi", 0); - if (!proc_scsi) { - printk (KERN_ERR "cannot init /proc/scsi\n"); - return -ENOMEM; - } - generic = create_proc_info_entry ("scsi/scsi", 0, 0, scsi_proc_info); - if (!generic) { - printk (KERN_ERR "cannot init /proc/scsi/scsi\n"); - remove_proc_entry("scsi", 0); - return -ENOMEM; - } - generic->write_proc = proc_scsi_gen_write; -#endif - -#ifdef DEVFS_MUST_DIE - scsi_devfs_handle = devfs_mk_dir (NULL, "scsi", NULL); -#endif - if (scsihosts) - printk(KERN_INFO "scsi: host order: %s\n", scsihosts); - scsi_host_no_init (scsihosts); - /* - * This is where the processing takes place for most everything - * when commands are completed. - */ - init_bh(SCSI_BH, scsi_bottom_half_handler); - - return 0; -} - - - -static void __exit exit_scsi(void) -{ - Scsi_Host_Name *shn, *shn2 = NULL; - - remove_bh(SCSI_BH); - -#ifdef DEVFS_MUST_DIE - devfs_unregister (scsi_devfs_handle); -#endif - for (shn = scsi_host_no_list;shn;shn = shn->next) { - if (shn->name) - kfree(shn->name); - if (shn2) - kfree (shn2); - shn2 = shn; - } - if (shn2) - kfree (shn2); - -#ifdef CONFIG_PROC_FS - /* No, we're not here anymore. Don't show the /proc/scsi files. */ - remove_proc_entry ("scsi/scsi", 0); - remove_proc_entry ("scsi", 0); -#endif - - /* - * Free up the DMA pool. - */ - scsi_resize_dma_pool(); - -} - -module_init(init_scsi); -module_exit(exit_scsi); - -/* - * Function: scsi_get_host_dev() - * - * Purpose: Create a Scsi_Device that points to the host adapter itself. - * - * Arguments: SHpnt - Host that needs a Scsi_Device - * - * Lock status: None assumed. - * - * Returns: The Scsi_Device or NULL - * - * Notes: - */ -Scsi_Device * scsi_get_host_dev(struct Scsi_Host * SHpnt) -{ - Scsi_Device * SDpnt; - - /* - * Attach a single Scsi_Device to the Scsi_Host - this should - * be made to look like a "pseudo-device" that points to the - * HA itself. For the moment, we include it at the head of - * the host_queue itself - I don't think we want to show this - * to the HA in select_queue_depths(), as this would probably confuse - * matters. - * Note - this device is not accessible from any high-level - * drivers (including generics), which is probably not - * optimal. We can add hooks later to attach - */ - SDpnt = (Scsi_Device *) kmalloc(sizeof(Scsi_Device), - GFP_ATOMIC); - if(SDpnt == NULL) - return NULL; - - memset(SDpnt, 0, sizeof(Scsi_Device)); - - SDpnt->host = SHpnt; - SDpnt->id = SHpnt->this_id; - SDpnt->type = -1; - SDpnt->queue_depth = 1; - - scsi_build_commandblocks(SDpnt); - - scsi_initialize_queue(SDpnt, SHpnt); - - SDpnt->online = TRUE; - -#if 0 - /* - * Initialize the object that we will use to wait for command blocks. - */ - init_waitqueue_head(&SDpnt->scpnt_wait); -#endif - return SDpnt; -} - -/* - * Function: scsi_free_host_dev() - * - * Purpose: Create a Scsi_Device that points to the host adapter itself. - * - * Arguments: SHpnt - Host that needs a Scsi_Device - * - * Lock status: None assumed. - * - * Returns: Nothing - * - * Notes: - */ -void scsi_free_host_dev(Scsi_Device * SDpnt) -{ - if( (unsigned char) SDpnt->id != (unsigned char) SDpnt->host->this_id ) - { - panic("Attempt to delete wrong device\n"); - } - - blk_cleanup_queue(&SDpnt->request_queue); - - /* - * We only have a single SCpnt attached to this device. Free - * it now. - */ - scsi_release_commandblocks(SDpnt); - kfree(SDpnt); -} - -/* - * Function: scsi_reset_provider_done_command - * - * Purpose: Dummy done routine. - * - * Notes: Some low level drivers will call scsi_done and end up here, - * others won't bother. - * We don't want the bogus command used for the bus/device - * reset to find its way into the mid-layer so we intercept - * it here. - */ -static void -scsi_reset_provider_done_command(Scsi_Cmnd *SCpnt) -{ -} - -/* - * Function: scsi_reset_provider - * - * Purpose: Send requested reset to a bus or device at any phase. - * - * Arguments: device - device to send reset to - * flag - reset type (see scsi.h) - * - * Returns: SUCCESS/FAILURE. - * - * Notes: This is used by the SCSI Generic driver to provide - * Bus/Device reset capability. - */ -int -scsi_reset_provider(Scsi_Device *dev, int flag) -{ - Scsi_Cmnd SC, *SCpnt = &SC; - int rtn; - - memset(&SCpnt->eh_timeout, 0, sizeof(SCpnt->eh_timeout)); - SCpnt->host = dev->host; - SCpnt->device = dev; - SCpnt->target = dev->id; - SCpnt->lun = dev->lun; - SCpnt->channel = dev->channel; - SCpnt->request.rq_status = RQ_SCSI_BUSY; - SCpnt->request.waiting = NULL; - SCpnt->use_sg = 0; - SCpnt->old_use_sg = 0; - SCpnt->old_cmd_len = 0; - SCpnt->underflow = 0; - SCpnt->transfersize = 0; - SCpnt->resid = 0; - SCpnt->serial_number = 0; - SCpnt->serial_number_at_timeout = 0; - SCpnt->host_scribble = NULL; - SCpnt->next = NULL; - SCpnt->state = SCSI_STATE_INITIALIZING; - SCpnt->owner = SCSI_OWNER_MIDLEVEL; - - memset(&SCpnt->cmnd, '\0', sizeof(SCpnt->cmnd)); - - SCpnt->scsi_done = scsi_reset_provider_done_command; - SCpnt->done = NULL; - SCpnt->reset_chain = NULL; - - SCpnt->buffer = NULL; - SCpnt->bufflen = 0; - SCpnt->request_buffer = NULL; - SCpnt->request_bufflen = 0; - - SCpnt->internal_timeout = NORMAL_TIMEOUT; - SCpnt->abort_reason = DID_ABORT; - - SCpnt->cmd_len = 0; - - SCpnt->sc_data_direction = SCSI_DATA_UNKNOWN; - SCpnt->sc_request = NULL; - SCpnt->sc_magic = SCSI_CMND_MAGIC; - - /* - * Sometimes the command can get back into the timer chain, - * so use the pid as an identifier. - */ - SCpnt->pid = 0; - - if (dev->host->hostt->use_new_eh_code) { - rtn = scsi_new_reset(SCpnt, flag); - } else { - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - rtn = scsi_old_reset(SCpnt, flag); - spin_unlock_irqrestore(&io_request_lock, flags); - rtn= 0; - } - - scsi_delete_timer(SCpnt); - return rtn; -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/xen/drivers/scsi/scsi.h b/xen/drivers/scsi/scsi.h deleted file mode 100644 index 60c63ea3b5..0000000000 --- a/xen/drivers/scsi/scsi.h +++ /dev/null @@ -1,899 +0,0 @@ -/* - * scsi.h Copyright (C) 1992 Drew Eckhardt - * Copyright (C) 1993, 1994, 1995, 1998, 1999 Eric Youngdale - * generic SCSI package header file by - * Initial versions: Drew Eckhardt - * Subsequent revisions: Eric Youngdale - * - * - * - * Modified by Eric Youngdale eric@andante.org to - * add scatter-gather, multiple outstanding request, and other - * enhancements. - */ - -#ifndef _SCSI_H -#define _SCSI_H - -#include /* for CONFIG_SCSI_LOGGING */ -#include -/*#include */ - -/* - * Some of the public constants are being moved to this file. - * We include it here so that what came from where is transparent. - */ -#include - -/*#include */ - -#include -#include -#include - -/* - * These are the values that the SCpnt->sc_data_direction and - * SRpnt->sr_data_direction can take. These need to be set - * The SCSI_DATA_UNKNOWN value is essentially the default. - * In the event that the command creator didn't bother to - * set a value, you will see SCSI_DATA_UNKNOWN. - */ -#define SCSI_DATA_UNKNOWN 0 -#define SCSI_DATA_WRITE 1 -#define SCSI_DATA_READ 2 -#define SCSI_DATA_NONE 3 - -#ifdef CONFIG_PCI -#include -#if ((SCSI_DATA_UNKNOWN == PCI_DMA_BIDIRECTIONAL) && (SCSI_DATA_WRITE == PCI_DMA_TODEVICE) && (SCSI_DATA_READ == PCI_DMA_FROMDEVICE) && (SCSI_DATA_NONE == PCI_DMA_NONE)) -#define scsi_to_pci_dma_dir(scsi_dir) ((int)(scsi_dir)) -#else -extern __inline__ int scsi_to_pci_dma_dir(unsigned char scsi_dir) -{ - if (scsi_dir == SCSI_DATA_UNKNOWN) - return PCI_DMA_BIDIRECTIONAL; - if (scsi_dir == SCSI_DATA_WRITE) - return PCI_DMA_TODEVICE; - if (scsi_dir == SCSI_DATA_READ) - return PCI_DMA_FROMDEVICE; - return PCI_DMA_NONE; -} -#endif -#endif - -#if defined(CONFIG_SBUS) && !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X) -#include -#if ((SCSI_DATA_UNKNOWN == SBUS_DMA_BIDIRECTIONAL) && (SCSI_DATA_WRITE == SBUS_DMA_TODEVICE) && (SCSI_DATA_READ == SBUS_DMA_FROMDEVICE) && (SCSI_DATA_NONE == SBUS_DMA_NONE)) -#define scsi_to_sbus_dma_dir(scsi_dir) ((int)(scsi_dir)) -#else -extern __inline__ int scsi_to_sbus_dma_dir(unsigned char scsi_dir) -{ - if (scsi_dir == SCSI_DATA_UNKNOWN) - return SBUS_DMA_BIDIRECTIONAL; - if (scsi_dir == SCSI_DATA_WRITE) - return SBUS_DMA_TODEVICE; - if (scsi_dir == SCSI_DATA_READ) - return SBUS_DMA_FROMDEVICE; - return SBUS_DMA_NONE; -} -#endif -#endif - -/* - * Some defs, in case these are not defined elsewhere. - */ -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#define MAX_SCSI_DEVICE_CODE 14 -extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE]; - -#ifdef DEBUG -#define SCSI_TIMEOUT (5*HZ) -#else -#define SCSI_TIMEOUT (2*HZ) -#endif - -/* - * Used for debugging the new queueing code. We want to make sure - * that the lock state is consistent with design. Only do this in - * the user space simulator. - */ -#define ASSERT_LOCK(_LOCK, _COUNT) - -#if defined(CONFIG_SMP) && defined(CONFIG_USER_DEBUG) -#undef ASSERT_LOCK -#define ASSERT_LOCK(_LOCK,_COUNT) \ - { if( (_LOCK)->lock != _COUNT ) \ - panic("Lock count inconsistent %s %d\n", __FILE__, __LINE__); \ - } -#endif - -/* - * Use these to separate status msg and our bytes - * - * These are set by: - * - * status byte = set from target device - * msg_byte = return status from host adapter itself. - * host_byte = set by low-level driver to indicate status. - * driver_byte = set by mid-level. - */ -#define status_byte(result) (((result) >> 1) & 0x1f) -#define msg_byte(result) (((result) >> 8) & 0xff) -#define host_byte(result) (((result) >> 16) & 0xff) -#define driver_byte(result) (((result) >> 24) & 0xff) -#define suggestion(result) (driver_byte(result) & SUGGEST_MASK) - -#define sense_class(sense) (((sense) >> 4) & 0x7) -#define sense_error(sense) ((sense) & 0xf) -#define sense_valid(sense) ((sense) & 0x80); - -#define NEEDS_RETRY 0x2001 -#define SUCCESS 0x2002 -#define FAILED 0x2003 -#define QUEUED 0x2004 -#define SOFT_ERROR 0x2005 -#define ADD_TO_MLQUEUE 0x2006 - -/* - * These are the values that scsi_cmd->state can take. - */ -#define SCSI_STATE_TIMEOUT 0x1000 -#define SCSI_STATE_FINISHED 0x1001 -#define SCSI_STATE_FAILED 0x1002 -#define SCSI_STATE_QUEUED 0x1003 -#define SCSI_STATE_UNUSED 0x1006 -#define SCSI_STATE_DISCONNECTING 0x1008 -#define SCSI_STATE_INITIALIZING 0x1009 -#define SCSI_STATE_BHQUEUE 0x100a -#define SCSI_STATE_MLQUEUE 0x100b - -/* - * These are the values that the owner field can take. - * They are used as an indication of who the command belongs to. - */ -#define SCSI_OWNER_HIGHLEVEL 0x100 -#define SCSI_OWNER_MIDLEVEL 0x101 -#define SCSI_OWNER_LOWLEVEL 0x102 -#define SCSI_OWNER_ERROR_HANDLER 0x103 -#define SCSI_OWNER_BH_HANDLER 0x104 -#define SCSI_OWNER_NOBODY 0x105 - -#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7] - -#define IDENTIFY_BASE 0x80 -#define IDENTIFY(can_disconnect, lun) (IDENTIFY_BASE |\ - ((can_disconnect) ? 0x40 : 0) |\ - ((lun) & 0x07)) - - -/* - * This defines the scsi logging feature. It is a means by which the - * user can select how much information they get about various goings on, - * and it can be really useful for fault tracing. The logging word is divided - * into 8 nibbles, each of which describes a loglevel. The division of things - * is somewhat arbitrary, and the division of the word could be changed if it - * were really needed for any reason. The numbers below are the only place where these - * are specified. For a first go-around, 3 bits is more than enough, since this - * gives 8 levels of logging (really 7, since 0 is always off). Cutting to 2 bits - * might be wise at some point. - */ - -#define SCSI_LOG_ERROR_SHIFT 0 -#define SCSI_LOG_TIMEOUT_SHIFT 3 -#define SCSI_LOG_SCAN_SHIFT 6 -#define SCSI_LOG_MLQUEUE_SHIFT 9 -#define SCSI_LOG_MLCOMPLETE_SHIFT 12 -#define SCSI_LOG_LLQUEUE_SHIFT 15 -#define SCSI_LOG_LLCOMPLETE_SHIFT 18 -#define SCSI_LOG_HLQUEUE_SHIFT 21 -#define SCSI_LOG_HLCOMPLETE_SHIFT 24 -#define SCSI_LOG_IOCTL_SHIFT 27 - -#define SCSI_LOG_ERROR_BITS 3 -#define SCSI_LOG_TIMEOUT_BITS 3 -#define SCSI_LOG_SCAN_BITS 3 -#define SCSI_LOG_MLQUEUE_BITS 3 -#define SCSI_LOG_MLCOMPLETE_BITS 3 -#define SCSI_LOG_LLQUEUE_BITS 3 -#define SCSI_LOG_LLCOMPLETE_BITS 3 -#define SCSI_LOG_HLQUEUE_BITS 3 -#define SCSI_LOG_HLCOMPLETE_BITS 3 -#define SCSI_LOG_IOCTL_BITS 3 - -#if CONFIG_SCSI_LOGGING - -#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) \ -{ \ - unsigned int mask; \ - \ - mask = (1 << (BITS)) - 1; \ - if( ((scsi_logging_level >> (SHIFT)) & mask) > (LEVEL) ) \ - { \ - (CMD); \ - } \ -} - -#define SCSI_SET_LOGGING(SHIFT, BITS, LEVEL) \ -{ \ - unsigned int mask; \ - \ - mask = ((1 << (BITS)) - 1) << SHIFT; \ - scsi_logging_level = ((scsi_logging_level & ~mask) \ - | ((LEVEL << SHIFT) & mask)); \ -} - - - -#else - -/* - * With no logging enabled, stub these out so they don't do anything. - */ -#define SCSI_SET_LOGGING(SHIFT, BITS, LEVEL) - -#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) -#endif - -/* - * These are the macros that are actually used throughout the code to - * log events. If logging isn't enabled, they are no-ops and will be - * completely absent from the user's code. - * - * The 'set' versions of the macros are really intended to only be called - * from the /proc filesystem, and in production kernels this will be about - * all that is ever used. It could be useful in a debugging environment to - * bump the logging level when certain strange events are detected, however. - */ -#define SCSI_LOG_ERROR_RECOVERY(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_ERROR_SHIFT, SCSI_LOG_ERROR_BITS, LEVEL,CMD); -#define SCSI_LOG_TIMEOUT(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_TIMEOUT_SHIFT, SCSI_LOG_TIMEOUT_BITS, LEVEL,CMD); -#define SCSI_LOG_SCAN_BUS(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_SCAN_SHIFT, SCSI_LOG_SCAN_BITS, LEVEL,CMD); -#define SCSI_LOG_MLQUEUE(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_MLQUEUE_SHIFT, SCSI_LOG_MLQUEUE_BITS, LEVEL,CMD); -#define SCSI_LOG_MLCOMPLETE(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_MLCOMPLETE_SHIFT, SCSI_LOG_MLCOMPLETE_BITS, LEVEL,CMD); -#define SCSI_LOG_LLQUEUE(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_LLQUEUE_SHIFT, SCSI_LOG_LLQUEUE_BITS, LEVEL,CMD); -#define SCSI_LOG_LLCOMPLETE(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_LLCOMPLETE_SHIFT, SCSI_LOG_LLCOMPLETE_BITS, LEVEL,CMD); -#define SCSI_LOG_HLQUEUE(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_HLQUEUE_SHIFT, SCSI_LOG_HLQUEUE_BITS, LEVEL,CMD); -#define SCSI_LOG_HLCOMPLETE(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_HLCOMPLETE_SHIFT, SCSI_LOG_HLCOMPLETE_BITS, LEVEL,CMD); -#define SCSI_LOG_IOCTL(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL,CMD); - - -#define SCSI_SET_ERROR_RECOVERY_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_ERROR_SHIFT, SCSI_LOG_ERROR_BITS, LEVEL); -#define SCSI_SET_TIMEOUT_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_TIMEOUT_SHIFT, SCSI_LOG_TIMEOUT_BITS, LEVEL); -#define SCSI_SET_SCAN_BUS_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_SCAN_SHIFT, SCSI_LOG_SCAN_BITS, LEVEL); -#define SCSI_SET_MLQUEUE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_MLQUEUE_SHIFT, SCSI_LOG_MLQUEUE_BITS, LEVEL); -#define SCSI_SET_MLCOMPLETE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_MLCOMPLETE_SHIFT, SCSI_LOG_MLCOMPLETE_BITS, LEVEL); -#define SCSI_SET_LLQUEUE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_LLQUEUE_SHIFT, SCSI_LOG_LLQUEUE_BITS, LEVEL); -#define SCSI_SET_LLCOMPLETE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_LLCOMPLETE_SHIFT, SCSI_LOG_LLCOMPLETE_BITS, LEVEL); -#define SCSI_SET_HLQUEUE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_HLQUEUE_SHIFT, SCSI_LOG_HLQUEUE_BITS, LEVEL); -#define SCSI_SET_HLCOMPLETE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_HLCOMPLETE_SHIFT, SCSI_LOG_HLCOMPLETE_BITS, LEVEL); -#define SCSI_SET_IOCTL_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL); - -/* - * the return of the status word will be in the following format : - * The low byte is the status returned by the SCSI command, - * with vendor specific bits masked. - * - * The next byte is the message which followed the SCSI status. - * This allows a stos to be used, since the Intel is a little - * endian machine. - * - * The final byte is a host return code, which is one of the following. - * - * IE - * lsb msb - * status msg host code - * - * Our errors returned by OUR driver, NOT SCSI message. Or'd with - * SCSI message passed back to driver . - */ - - -#define DID_OK 0x00 /* NO error */ -#define DID_NO_CONNECT 0x01 /* Couldn't connect before timeout period */ -#define DID_BUS_BUSY 0x02 /* BUS stayed busy through time out period */ -#define DID_TIME_OUT 0x03 /* TIMED OUT for other reason */ -#define DID_BAD_TARGET 0x04 /* BAD target. */ -#define DID_ABORT 0x05 /* Told to abort for some other reason */ -#define DID_PARITY 0x06 /* Parity error */ -#define DID_ERROR 0x07 /* Internal error */ -#define DID_RESET 0x08 /* Reset by somebody. */ -#define DID_BAD_INTR 0x09 /* Got an interrupt we weren't expecting. */ -#define DID_PASSTHROUGH 0x0a /* Force command past mid-layer */ -#define DID_SOFT_ERROR 0x0b /* The low level driver just wish a retry */ -#define DRIVER_OK 0x00 /* Driver status */ - -/* - * These indicate the error that occurred, and what is available. - */ - -#define DRIVER_BUSY 0x01 -#define DRIVER_SOFT 0x02 -#define DRIVER_MEDIA 0x03 -#define DRIVER_ERROR 0x04 - -#define DRIVER_INVALID 0x05 -#define DRIVER_TIMEOUT 0x06 -#define DRIVER_HARD 0x07 -#define DRIVER_SENSE 0x08 - -#define SUGGEST_RETRY 0x10 -#define SUGGEST_ABORT 0x20 -#define SUGGEST_REMAP 0x30 -#define SUGGEST_DIE 0x40 -#define SUGGEST_SENSE 0x80 -#define SUGGEST_IS_OK 0xff - -#define DRIVER_MASK 0x0f -#define SUGGEST_MASK 0xf0 - -#define MAX_COMMAND_SIZE 16 -#define SCSI_SENSE_BUFFERSIZE 64 - -/* - * SCSI command sets - */ - -#define SCSI_UNKNOWN 0 -#define SCSI_1 1 -#define SCSI_1_CCS 2 -#define SCSI_2 3 -#define SCSI_3 4 - -/* - * Every SCSI command starts with a one byte OP-code. - * The next byte's high three bits are the LUN of the - * device. Any multi-byte quantities are stored high byte - * first, and may have a 5 bit MSB in the same byte - * as the LUN. - */ - -/* - * As the scsi do command functions are intelligent, and may need to - * redo a command, we need to keep track of the last command - * executed on each one. - */ - -#define WAS_RESET 0x01 -#define WAS_TIMEDOUT 0x02 -#define WAS_SENSE 0x04 -#define IS_RESETTING 0x08 -#define IS_ABORTING 0x10 -#define ASKED_FOR_SENSE 0x20 -#define SYNC_RESET 0x40 - -#if defined(__mc68000__) || defined(CONFIG_APUS) -#include -#define CONTIGUOUS_BUFFERS(X,Y) \ - (virt_to_phys((X)->b_data+(X)->b_size-1)+1==virt_to_phys((Y)->b_data)) -#else -#define CONTIGUOUS_BUFFERS(X,Y) ((X->b_data+X->b_size) == Y->b_data) -#endif - - -/* - * This is the crap from the old error handling code. We have it in a special - * place so that we can more easily delete it later on. - */ -#include "scsi_obsolete.h" - -/* - * Add some typedefs so that we can prototyope a bunch of the functions. - */ -typedef struct scsi_device Scsi_Device; -typedef struct scsi_cmnd Scsi_Cmnd; -typedef struct scsi_request Scsi_Request; - -#define SCSI_CMND_MAGIC 0xE25C23A5 -#define SCSI_REQ_MAGIC 0x75F6D354 - -/* - * Here is where we prototype most of the mid-layer. - */ - -/* - * Initializes all SCSI devices. This scans all scsi busses. - */ - -extern unsigned int scsi_logging_level; /* What do we log? */ -extern unsigned int scsi_dma_free_sectors; /* How much room do we have left */ -extern unsigned int scsi_need_isa_buffer; /* True if some devices need indirection - * buffers */ -extern volatile int in_scan_scsis; -extern const unsigned char scsi_command_size[8]; - - -/* - * These are the error handling functions defined in scsi_error.c - */ -extern void scsi_times_out(Scsi_Cmnd * SCpnt); -extern void scsi_add_timer(Scsi_Cmnd * SCset, int timeout, - void (*complete) (Scsi_Cmnd *)); -extern int scsi_delete_timer(Scsi_Cmnd * SCset); -extern void scsi_error_handler(void *host); -extern int scsi_sense_valid(Scsi_Cmnd *); -extern int scsi_decide_disposition(Scsi_Cmnd * SCpnt); -extern int scsi_block_when_processing_errors(Scsi_Device *); -extern void scsi_sleep(int); - -/* - * Prototypes for functions in scsicam.c - */ -extern int scsi_partsize(struct buffer_head *bh, unsigned long capacity, - unsigned int *cyls, unsigned int *hds, - unsigned int *secs); - -/* - * Prototypes for functions in scsi_dma.c - */ -void scsi_resize_dma_pool(void); -int scsi_init_minimal_dma_pool(void); -void *scsi_malloc(unsigned int); -int scsi_free(void *, unsigned int); - -/* - * Prototypes for functions in scsi_merge.c - */ -extern void recount_segments(Scsi_Cmnd * SCpnt); -extern void initialize_merge_fn(Scsi_Device * SDpnt); - -/* - * Prototypes for functions in scsi_queue.c - */ -extern int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason); - -/* - * Prototypes for functions in scsi_lib.c - */ -extern int scsi_maybe_unblock_host(Scsi_Device * SDpnt); -extern Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate, - int sectors); -extern struct Scsi_Device_Template *scsi_get_request_dev(struct request *); -extern int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt); -extern int scsi_insert_special_cmd(Scsi_Cmnd * SCpnt, int); -extern void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors, - int block_sectors); -extern void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt); -extern void scsi_request_fn(request_queue_t * q); -extern int scsi_starvation_completion(Scsi_Device * SDpnt); - -/* - * Prototypes for functions in scsi.c - */ -extern int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt); -extern void scsi_bottom_half_handler(void); -extern void scsi_release_commandblocks(Scsi_Device * SDpnt); -extern void scsi_build_commandblocks(Scsi_Device * SDpnt); -extern void scsi_done(Scsi_Cmnd * SCpnt); -extern void scsi_finish_command(Scsi_Cmnd *); -extern int scsi_retry_command(Scsi_Cmnd *); -extern Scsi_Cmnd *scsi_allocate_device(Scsi_Device *, int, int); -extern void __scsi_release_command(Scsi_Cmnd *); -extern void scsi_release_command(Scsi_Cmnd *); -extern void scsi_do_cmd(Scsi_Cmnd *, const void *cmnd, - void *buffer, unsigned bufflen, - void (*done) (struct scsi_cmnd *), - int timeout, int retries); -extern int scsi_dev_init(void); - -/* - * Newer request-based interfaces. - */ -extern Scsi_Request *scsi_allocate_request(Scsi_Device *); -extern void scsi_release_request(Scsi_Request *); -extern void scsi_wait_req(Scsi_Request *, const void *cmnd, - void *buffer, unsigned bufflen, - int timeout, int retries); - -extern void scsi_do_req(Scsi_Request *, const void *cmnd, - void *buffer, unsigned bufflen, - void (*done) (struct scsi_cmnd *), - int timeout, int retries); -extern int scsi_insert_special_req(Scsi_Request * SRpnt, int); -extern void scsi_init_cmd_from_req(Scsi_Cmnd *, Scsi_Request *); - - -/* - * Prototypes for functions/data in hosts.c - */ -extern int max_scsi_hosts; - -/* - * Prototypes for functions in scsi_proc.c - */ -extern void proc_print_scsidevice(Scsi_Device *, char *, int *, int); -extern struct proc_dir_entry *proc_scsi; - -/* - * Prototypes for functions in constants.c - */ -extern void print_command(unsigned char *); -extern void print_sense(const char *, Scsi_Cmnd *); -extern void print_req_sense(const char *, Scsi_Request *); -extern void print_driverbyte(int scsiresult); -extern void print_hostbyte(int scsiresult); -extern void print_status (int status); - -/* - * The scsi_device struct contains what we know about each given scsi - * device. - * - * FIXME(eric) - one of the great regrets that I have is that I failed to define - * these structure elements as something like sdev_foo instead of foo. This would - * make it so much easier to grep through sources and so forth. I propose that - * all new elements that get added to these structures follow this convention. - * As time goes on and as people have the stomach for it, it should be possible to - * go back and retrofit at least some of the elements here with with the prefix. - */ - -struct scsi_device { -/* private: */ - /* - * This information is private to the scsi mid-layer. Wrapping it in a - * struct private is a way of marking it in a sort of C++ type of way. - */ - struct scsi_device *next; /* Used for linked list */ - struct scsi_device *prev; /* Used for linked list */ -#if 0 - wait_queue_head_t scpnt_wait; /* Used to wait if - device is busy */ -#endif - - struct Scsi_Host *host; - request_queue_t request_queue; - atomic_t device_active; /* commands checked out for device */ - volatile unsigned short device_busy; /* commands actually active on low-level */ - int (*scsi_init_io_fn) (Scsi_Cmnd *); /* Used to initialize - new request */ - Scsi_Cmnd *device_queue; /* queue of SCSI Command structures */ - -/* public: */ - unsigned int id, lun, channel; - - unsigned int manufacturer; /* Manufacturer of device, for using - * vendor-specific cmd's */ - unsigned sector_size; /* size in bytes */ - - int attached; /* # of high level drivers attached to this */ - int detected; /* Delta attached - don't use in drivers! */ - int access_count; /* Count of open channels/mounts */ - - void *hostdata; /* available to low-level driver */ -#if 0 - devfs_handle_t de; /* directory for the device */ -#endif - char type; - char scsi_level; - char vendor[8], model[16], rev[4]; - unsigned char current_tag; /* current tag */ - unsigned char sync_min_period; /* Not less than this period */ - unsigned char sync_max_offset; /* Not greater than this offset */ - unsigned char queue_depth; /* How deep a queue to use */ - - unsigned online:1; - unsigned writeable:1; - unsigned removable:1; - unsigned random:1; - unsigned has_cmdblocks:1; - unsigned changed:1; /* Data invalid due to media change */ - unsigned busy:1; /* Used to prevent races */ - unsigned lockable:1; /* Able to prevent media removal */ - unsigned borken:1; /* Tell the Seagate driver to be - * painfully slow on this device */ - unsigned tagged_supported:1; /* Supports SCSI-II tagged queuing */ - unsigned tagged_queue:1; /* SCSI-II tagged queuing enabled */ - unsigned disconnect:1; /* can disconnect */ - unsigned soft_reset:1; /* Uses soft reset option */ - unsigned sync:1; /* Negotiate for sync transfers */ - unsigned wide:1; /* Negotiate for WIDE transfers */ - unsigned single_lun:1; /* Indicates we should only allow I/O to - * one of the luns for the device at a - * time. */ - unsigned was_reset:1; /* There was a bus reset on the bus for - * this device */ - unsigned expecting_cc_ua:1; /* Expecting a CHECK_CONDITION/UNIT_ATTN - * because we did a bus reset. */ - unsigned device_blocked:1; /* Device returned QUEUE_FULL. */ - unsigned ten:1; /* support ten byte read / write */ - unsigned remap:1; /* support remapping */ - unsigned starved:1; /* unable to process commands because - host busy */ - - // Flag to allow revalidate to succeed in sd_open - int allow_revalidate; -}; - - -/* - * The Scsi_Cmnd structure is used by scsi.c internally, and for communication - * with low level drivers that support multiple outstanding commands. - */ -typedef struct scsi_pointer { - char *ptr; /* data pointer */ - int this_residual; /* left in this buffer */ - struct scatterlist *buffer; /* which buffer */ - int buffers_residual; /* how many buffers left */ - - dma_addr_t dma_handle; - - volatile int Status; - volatile int Message; - volatile int have_data_in; - volatile int sent_command; - volatile int phase; -} Scsi_Pointer; - -/* - * This is essentially a slimmed down version of Scsi_Cmnd. The point of - * having this is that requests that are injected into the queue as result - * of things like ioctls and character devices shouldn't be using a - * Scsi_Cmnd until such a time that the command is actually at the head - * of the queue and being sent to the driver. - */ -struct scsi_request { - int sr_magic; - int sr_result; /* Status code from lower level driver */ - unsigned char sr_sense_buffer[SCSI_SENSE_BUFFERSIZE]; - /* obtained by REQUEST SENSE when CHECK CONDITION is received - on original command (auto-sense) */ - - struct Scsi_Host *sr_host; - Scsi_Device *sr_device; - Scsi_Cmnd *sr_command; -#define SMHHACK -#ifdef SMHHACK - void *freeaddr; -#endif - struct request sr_request; /* A copy of the command we are - working on */ - unsigned sr_bufflen; /* Size of data buffer */ - void *sr_buffer; /* Data buffer */ - int sr_allowed; - unsigned char sr_data_direction; - unsigned char sr_cmd_len; - unsigned char sr_cmnd[MAX_COMMAND_SIZE]; - void (*sr_done) (struct scsi_cmnd *); /* Mid-level done function */ - int sr_timeout_per_command; - unsigned short sr_use_sg; /* Number of pieces of scatter-gather */ - unsigned short sr_sglist_len; /* size of malloc'd scatter-gather list */ - unsigned sr_underflow; /* Return error if less than - this amount is transferred */ -}; - -/* - * FIXME(eric) - one of the great regrets that I have is that I failed - * to define these structure elements as something like sc_foo instead - * of foo. This would make it so much easier to grep through sources - * and so forth. I propose that all new elements that get added to - * these structures follow this convention. As time goes on and as - * people have the stomach for it, it should be possible to go back - * and retrofit at least some of the elements here with with the - * prefix. -*/ - -struct scsi_cmnd { - int sc_magic; -/* private: */ - /* - * This information is private to the scsi mid-layer. Wrapping it in a - * struct private is a way of marking it in a sort of C++ type of way. - */ - struct Scsi_Host *host; - unsigned short state; - unsigned short owner; - Scsi_Device *device; - Scsi_Request *sc_request; - struct scsi_cmnd *next; - struct scsi_cmnd *reset_chain; - - int eh_state; /* Used for state tracking in error handlr */ - void (*done) (struct scsi_cmnd *); /* Mid-level done function */ - /* - A SCSI Command is assigned a nonzero serial_number when internal_cmnd - passes it to the driver's queue command function. The serial_number - is cleared when scsi_done is entered indicating that the command has - been completed. If a timeout occurs, the serial number at the moment - of timeout is copied into serial_number_at_timeout. By subsequently - comparing the serial_number and serial_number_at_timeout fields - during abort or reset processing, we can detect whether the command - has already completed. This also detects cases where the command has - completed and the SCSI Command structure has already being reused - for another command, so that we can avoid incorrectly aborting or - resetting the new command. - */ - - unsigned long serial_number; - unsigned long serial_number_at_timeout; - - int retries; - int allowed; - int timeout_per_command; - int timeout_total; - int timeout; - - /* - * We handle the timeout differently if it happens when a reset, - * abort, etc are in process. - */ - unsigned volatile char internal_timeout; - struct scsi_cmnd *bh_next; /* To enumerate the commands waiting - to be processed. */ - -/* public: */ - - unsigned int target; - unsigned int lun; - unsigned int channel; - unsigned char cmd_len; - unsigned char old_cmd_len; - unsigned char sc_data_direction; - unsigned char sc_old_data_direction; - - /* These elements define the operation we are about to perform */ - unsigned char cmnd[MAX_COMMAND_SIZE]; - unsigned request_bufflen; /* Actual request size */ - - struct timer_list eh_timeout; /* Used to time out the command. */ - void *request_buffer; /* Actual requested buffer */ - void **bounce_buffers; /* Array of bounce buffers when - using scatter-gather */ - - /* These elements define the operation we ultimately want to perform */ - unsigned char data_cmnd[MAX_COMMAND_SIZE]; - unsigned short old_use_sg; /* We save use_sg here when requesting - * sense info */ - unsigned short use_sg; /* Number of pieces of scatter-gather */ - unsigned short sglist_len; /* size of malloc'd scatter-gather list */ - unsigned short abort_reason; /* If the mid-level code requests an - * abort, this is the reason. */ - unsigned bufflen; /* Size of data buffer */ - void *buffer; /* Data buffer */ - - unsigned underflow; /* Return error if less than - this amount is transferred */ - unsigned old_underflow; /* save underflow here when reusing the - * command for error handling */ - - unsigned transfersize; /* How much we are guaranteed to - transfer with each SCSI transfer - (ie, between disconnect / - reconnects. Probably == sector - size */ - - int resid; /* Number of bytes requested to be - transferred less actual number - transferred (0 if not supported) */ - - struct request request; /* A copy of the command we are - working on */ - - unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE]; - /* obtained by REQUEST SENSE when CHECK CONDITION is - * received on original command (auto-sense) */ - - unsigned flags; - - /* - * Used to indicate that a command which has timed out also - * completed normally. Typically the completion function will - * do nothing but set this flag in this instance because the - * timeout handler is already running. - */ - unsigned done_late:1; - - /* Low-level done function - can be used by low-level driver to point - * to completion function. Not used by mid/upper level code. */ - void (*scsi_done) (struct scsi_cmnd *); - - /* - * The following fields can be written to by the host specific code. - * Everything else should be left alone. - */ - - Scsi_Pointer SCp; /* Scratchpad used by some host adapters */ - - unsigned char *host_scribble; - - /* The host adapter is allowed to call scsi_malloc and get some - * memory and hang it here. The host adapter is also expected to - * call scsi_free to release this memory. (The memory obtained - * by scsi_malloc is guaranteed to be at an address < 16Mb). */ - - - int result; /* Status code from lower level driver */ - - unsigned char tag; /* SCSI-II queued command tag */ - unsigned long pid; /* Process ID, starts at 0 */ -}; - -/* - * Flag bit for the internal_timeout array - */ -#define NORMAL_TIMEOUT 0 - -/* - * Definitions and prototypes used for scsi mid-level queue. - */ -#define SCSI_MLQUEUE_HOST_BUSY 0x1055 -#define SCSI_MLQUEUE_DEVICE_BUSY 0x1056 - -#if 0 -#define SCSI_SLEEP(QUEUE, CONDITION) { \ - if (CONDITION) { \ - DECLARE_WAITQUEUE(wait, current); \ - add_wait_queue(QUEUE, &wait); \ - for(;;) { \ - set_current_state(TASK_UNINTERRUPTIBLE); \ - if (CONDITION) { \ - if (in_interrupt()) \ - panic("scsi: trying to call schedule() in interrupt" \ - ", file %s, line %d.\n", __FILE__, __LINE__); \ - schedule(); \ - } \ - else \ - break; \ - } \ - remove_wait_queue(QUEUE, &wait);\ - current->state = TASK_RUNNING; \ - }; } -#else -#define SCSI_SLEEP(QUEUE, CONDITION) { printk("SCSI_SLEEP!\n"); BUG(); } -#endif - - - - -/* - * old style reset request from external source - * (private to sg.c and scsi_error.c, supplied by scsi_obsolete.c) - */ -#define SCSI_TRY_RESET_DEVICE 1 -#define SCSI_TRY_RESET_BUS 2 -#define SCSI_TRY_RESET_HOST 3 - -extern int scsi_reset_provider(Scsi_Device *, int); - -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/xen/drivers/scsi/scsi_dma.c b/xen/drivers/scsi/scsi_dma.c deleted file mode 100644 index 1649f7c641..0000000000 --- a/xen/drivers/scsi/scsi_dma.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * scsi_dma.c Copyright (C) 2000 Eric Youngdale - * - * mid-level SCSI DMA bounce buffer allocator - * - */ - -#define __NO_VERSION__ -#include -#include -#include - - -#include "scsi.h" -#include "hosts.h" -#include "constants.h" - -#ifdef CONFIG_KMOD -#include -#endif - -/* - * PAGE_SIZE must be a multiple of the sector size (512). True - * for all reasonably recent architectures (even the VAX...). - */ -#define SECTOR_SIZE 512 -#define SECTORS_PER_PAGE (PAGE_SIZE/SECTOR_SIZE) - -#if SECTORS_PER_PAGE <= 8 -typedef unsigned char FreeSectorBitmap; -#elif SECTORS_PER_PAGE <= 32 -typedef unsigned int FreeSectorBitmap; -#else -#error You lose. -#endif - -/* - * Used for access to internal allocator used for DMA safe buffers. - */ -static spinlock_t allocator_request_lock = SPIN_LOCK_UNLOCKED; - -static FreeSectorBitmap *dma_malloc_freelist = NULL; -static int need_isa_bounce_buffers; -static unsigned int dma_sectors = 0; -unsigned int scsi_dma_free_sectors = 0; -unsigned int scsi_need_isa_buffer = 0; -static unsigned char **dma_malloc_pages = NULL; - -/* - * Function: scsi_malloc - * - * Purpose: Allocate memory from the DMA-safe pool. - * - * Arguments: len - amount of memory we need. - * - * Lock status: No locks assumed to be held. This function is SMP-safe. - * - * Returns: Pointer to memory block. - * - * Notes: Prior to the new queue code, this function was not SMP-safe. - * This function can only allocate in units of sectors - * (i.e. 512 bytes). - * - * We cannot use the normal system allocator becuase we need - * to be able to guarantee that we can process a complete disk - * I/O request without touching the system allocator. Think - * about it - if the system were heavily swapping, and tried to - * write out a block of memory to disk, and the SCSI code needed - * to allocate more memory in order to be able to write the - * data to disk, you would wedge the system. - */ -void *scsi_malloc(unsigned int len) -{ - unsigned int nbits, mask; - unsigned long flags; - - int i, j; - if (len % SECTOR_SIZE != 0 || len > PAGE_SIZE) - return NULL; - - nbits = len >> 9; - mask = (1 << nbits) - 1; - - spin_lock_irqsave(&allocator_request_lock, flags); - - for (i = 0; i < dma_sectors / SECTORS_PER_PAGE; i++) - for (j = 0; j <= SECTORS_PER_PAGE - nbits; j++) { - if ((dma_malloc_freelist[i] & (mask << j)) == 0) { - dma_malloc_freelist[i] |= (mask << j); - scsi_dma_free_sectors -= nbits; -#ifdef DEBUG - SCSI_LOG_MLQUEUE(3, printk("SMalloc: %d %p [From:%p]\n", len, dma_malloc_pages[i] + (j << 9))); - printk("SMalloc: %d %p [From:%p]\n", len, dma_malloc_pages[i] + (j << 9)); -#endif - spin_unlock_irqrestore(&allocator_request_lock, flags); - return (void *) ((unsigned long) dma_malloc_pages[i] + (j << 9)); - } - } - spin_unlock_irqrestore(&allocator_request_lock, flags); - return NULL; /* Nope. No more */ -} - -/* - * Function: scsi_free - * - * Purpose: Free memory into the DMA-safe pool. - * - * Arguments: ptr - data block we are freeing. - * len - size of block we are freeing. - * - * Lock status: No locks assumed to be held. This function is SMP-safe. - * - * Returns: Nothing - * - * Notes: This function *must* only be used to free memory - * allocated from scsi_malloc(). - * - * Prior to the new queue code, this function was not SMP-safe. - * This function can only allocate in units of sectors - * (i.e. 512 bytes). - */ -int scsi_free(void *obj, unsigned int len) -{ - unsigned int page, sector, nbits, mask; - unsigned long flags; - -#ifdef DEBUG - unsigned long ret = 0; - -#ifdef __mips__ - __asm__ __volatile__("move\t%0,$31":"=r"(ret)); -#else - ret = __builtin_return_address(0); -#endif - printk("scsi_free %p %d\n", obj, len); - SCSI_LOG_MLQUEUE(3, printk("SFree: %p %d\n", obj, len)); -#endif - - spin_lock_irqsave(&allocator_request_lock, flags); - - for (page = 0; page < dma_sectors / SECTORS_PER_PAGE; page++) { - unsigned long page_addr = (unsigned long) dma_malloc_pages[page]; - if ((unsigned long) obj >= page_addr && - (unsigned long) obj < page_addr + PAGE_SIZE) { - sector = (((unsigned long) obj) - page_addr) >> 9; - - nbits = len >> 9; - mask = (1 << nbits) - 1; - - if (sector + nbits > SECTORS_PER_PAGE) - panic("scsi_free:Bad memory alignment"); - - if ((dma_malloc_freelist[page] & - (mask << sector)) != (mask << sector)) { -#ifdef DEBUG - printk("scsi_free(obj=%p, len=%d) called from %08lx\n", - obj, len, ret); -#endif - panic("scsi_free:Trying to free unused memory"); - } - scsi_dma_free_sectors += nbits; - dma_malloc_freelist[page] &= ~(mask << sector); - spin_unlock_irqrestore(&allocator_request_lock, flags); - return 0; - } - } - panic("scsi_free:Bad offset"); - return -1; -} - - -/* - * Function: scsi_resize_dma_pool - * - * Purpose: Ensure that the DMA pool is sufficiently large to be - * able to guarantee that we can always process I/O requests - * without calling the system allocator. - * - * Arguments: None. - * - * Lock status: No locks assumed to be held. This function is SMP-safe. - * - * Returns: Nothing - * - * Notes: Prior to the new queue code, this function was not SMP-safe. - * Go through the device list and recompute the most appropriate - * size for the dma pool. Then grab more memory (as required). - */ -void scsi_resize_dma_pool(void) -{ - int i, k; - unsigned long size; - unsigned long flags; - struct Scsi_Host *shpnt; - struct Scsi_Host *host = NULL; - Scsi_Device *SDpnt; - FreeSectorBitmap *new_dma_malloc_freelist = NULL; - unsigned int new_dma_sectors = 0; - unsigned int new_need_isa_buffer = 0; - unsigned char **new_dma_malloc_pages = NULL; - int out_of_space = 0; - - spin_lock_irqsave(&allocator_request_lock, flags); - - if (!scsi_hostlist) { - /* - * Free up the DMA pool. - */ - if (scsi_dma_free_sectors != dma_sectors) - panic("SCSI DMA pool memory leak %d %d\n", - scsi_dma_free_sectors, dma_sectors); - - for (i = 0; i < dma_sectors / SECTORS_PER_PAGE; i++) - free_pages((unsigned long) dma_malloc_pages[i], 0); - if (dma_malloc_pages) - kfree((char *) dma_malloc_pages); - dma_malloc_pages = NULL; - if (dma_malloc_freelist) - kfree((char *) dma_malloc_freelist); - dma_malloc_freelist = NULL; - dma_sectors = 0; - scsi_dma_free_sectors = 0; - spin_unlock_irqrestore(&allocator_request_lock, flags); - return; - } - /* Next, check to see if we need to extend the DMA buffer pool */ - - new_dma_sectors = 2 * SECTORS_PER_PAGE; /* Base value we use */ - -#if 0 - if (__pa(high_memory) - 1 > ISA_DMA_THRESHOLD) - need_isa_bounce_buffers = 1; - else -#endif - need_isa_bounce_buffers = 0; - - if (scsi_devicelist) - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) - new_dma_sectors += SECTORS_PER_PAGE; /* Increment for each host */ - - for (host = scsi_hostlist; host; host = host->next) { - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) { - /* - * sd and sr drivers allocate scatterlists. - * sr drivers may allocate for each command 1x2048 or 2x1024 extra - * buffers for 2k sector size and 1k fs. - * sg driver allocates buffers < 4k. - * st driver does not need buffers from the dma pool. - * estimate 4k buffer/command for devices of unknown type (should panic). - */ - if (SDpnt->type == TYPE_WORM || SDpnt->type == TYPE_ROM || - SDpnt->type == TYPE_DISK || SDpnt->type == TYPE_MOD) { - int nents = host->sg_tablesize; -#ifdef DMA_CHUNK_SIZE - /* If the architecture does DMA sg merging, make sure - we count with at least 64 entries even for HBAs - which handle very few sg entries. */ - if (nents < 64) nents = 64; -#endif - new_dma_sectors += ((nents * - sizeof(struct scatterlist) + 511) >> 9) * - SDpnt->queue_depth; - if (SDpnt->type == TYPE_WORM || SDpnt->type == TYPE_ROM) - new_dma_sectors += (2048 >> 9) * SDpnt->queue_depth; - } else if (SDpnt->type == TYPE_SCANNER || - SDpnt->type == TYPE_PRINTER || - SDpnt->type == TYPE_PROCESSOR || - SDpnt->type == TYPE_COMM || - SDpnt->type == TYPE_MEDIUM_CHANGER || - SDpnt->type == TYPE_ENCLOSURE) { - new_dma_sectors += (4096 >> 9) * SDpnt->queue_depth; - } else { - if (SDpnt->type != TYPE_TAPE) { - printk("resize_dma_pool: unknown device type %d\n", SDpnt->type); - new_dma_sectors += (4096 >> 9) * SDpnt->queue_depth; - } - } - - if (host->unchecked_isa_dma && - need_isa_bounce_buffers && - SDpnt->type != TYPE_TAPE) { - new_dma_sectors += (PAGE_SIZE >> 9) * host->sg_tablesize * - SDpnt->queue_depth; - new_need_isa_buffer++; - } - } - } - -#ifdef DEBUG_INIT - printk("resize_dma_pool: needed dma sectors = %d\n", new_dma_sectors); -#endif - - /* limit DMA memory to 32MB: */ - new_dma_sectors = (new_dma_sectors + 15) & 0xfff0; - - /* - * We never shrink the buffers - this leads to - * race conditions that I would rather not even think - * about right now. - */ -#if 0 /* Why do this? No gain and risks out_of_space */ - if (new_dma_sectors < dma_sectors) - new_dma_sectors = dma_sectors; -#endif - if (new_dma_sectors <= dma_sectors) { - spin_unlock_irqrestore(&allocator_request_lock, flags); - return; /* best to quit while we are in front */ - } - - for (k = 0; k < 20; ++k) { /* just in case */ - out_of_space = 0; - size = (new_dma_sectors / SECTORS_PER_PAGE) * - sizeof(FreeSectorBitmap); - new_dma_malloc_freelist = (FreeSectorBitmap *) - kmalloc(size, GFP_ATOMIC); - if (new_dma_malloc_freelist) { - memset(new_dma_malloc_freelist, 0, size); - size = (new_dma_sectors / SECTORS_PER_PAGE) * - sizeof(*new_dma_malloc_pages); - new_dma_malloc_pages = (unsigned char **) - kmalloc(size, GFP_ATOMIC); - if (!new_dma_malloc_pages) { - size = (new_dma_sectors / SECTORS_PER_PAGE) * - sizeof(FreeSectorBitmap); - kfree((char *) new_dma_malloc_freelist); - out_of_space = 1; - } else { - memset(new_dma_malloc_pages, 0, size); - } - } else - out_of_space = 1; - - if ((!out_of_space) && (new_dma_sectors > dma_sectors)) { - for (i = dma_sectors / SECTORS_PER_PAGE; - i < new_dma_sectors / SECTORS_PER_PAGE; i++) { - new_dma_malloc_pages[i] = (unsigned char *) - __get_free_pages(GFP_ATOMIC | GFP_DMA, 0); - if (!new_dma_malloc_pages[i]) - break; - } - if (i != new_dma_sectors / SECTORS_PER_PAGE) { /* clean up */ - int k = i; - - out_of_space = 1; - for (i = 0; i < k; ++i) - free_pages((unsigned long) new_dma_malloc_pages[i], 0); - } - } - if (out_of_space) { /* try scaling down new_dma_sectors request */ - printk("scsi::resize_dma_pool: WARNING, dma_sectors=%u, " - "wanted=%u, scaling\n", dma_sectors, new_dma_sectors); - if (new_dma_sectors < (8 * SECTORS_PER_PAGE)) - break; /* pretty well hopeless ... */ - new_dma_sectors = (new_dma_sectors * 3) / 4; - new_dma_sectors = (new_dma_sectors + 15) & 0xfff0; - if (new_dma_sectors <= dma_sectors) - break; /* stick with what we have got */ - } else - break; /* found space ... */ - } /* end of for loop */ - if (out_of_space) { - spin_unlock_irqrestore(&allocator_request_lock, flags); - scsi_need_isa_buffer = new_need_isa_buffer; /* some useful info */ - printk(" WARNING, not enough memory, pool not expanded\n"); - return; - } - /* When we dick with the actual DMA list, we need to - * protect things - */ - if (dma_malloc_freelist) { - size = (dma_sectors / SECTORS_PER_PAGE) * sizeof(FreeSectorBitmap); - memcpy(new_dma_malloc_freelist, dma_malloc_freelist, size); - kfree((char *) dma_malloc_freelist); - } - dma_malloc_freelist = new_dma_malloc_freelist; - - if (dma_malloc_pages) { - size = (dma_sectors / SECTORS_PER_PAGE) * sizeof(*dma_malloc_pages); - memcpy(new_dma_malloc_pages, dma_malloc_pages, size); - kfree((char *) dma_malloc_pages); - } - scsi_dma_free_sectors += new_dma_sectors - dma_sectors; - dma_malloc_pages = new_dma_malloc_pages; - dma_sectors = new_dma_sectors; - scsi_need_isa_buffer = new_need_isa_buffer; - - spin_unlock_irqrestore(&allocator_request_lock, flags); - -#ifdef DEBUG_INIT - printk("resize_dma_pool: dma free sectors = %d\n", scsi_dma_free_sectors); - printk("resize_dma_pool: dma sectors = %d\n", dma_sectors); - printk("resize_dma_pool: need isa buffers = %d\n", scsi_need_isa_buffer); -#endif -} - -/* - * Function: scsi_init_minimal_dma_pool - * - * Purpose: Allocate a minimal (1-page) DMA pool. - * - * Arguments: None. - * - * Lock status: No locks assumed to be held. This function is SMP-safe. - * - * Returns: Nothing - * - * Notes: - */ -int scsi_init_minimal_dma_pool(void) -{ - unsigned long size; - unsigned long flags; - int has_space = 0; - - spin_lock_irqsave(&allocator_request_lock, flags); - - dma_sectors = PAGE_SIZE / SECTOR_SIZE; - scsi_dma_free_sectors = dma_sectors; - /* - * Set up a minimal DMA buffer list - this will be used during scan_scsis - * in some cases. - */ - - /* One bit per sector to indicate free/busy */ - size = (dma_sectors / SECTORS_PER_PAGE) * sizeof(FreeSectorBitmap); - dma_malloc_freelist = (FreeSectorBitmap *) - kmalloc(size, GFP_ATOMIC); - if (dma_malloc_freelist) { - memset(dma_malloc_freelist, 0, size); - /* One pointer per page for the page list */ - dma_malloc_pages = (unsigned char **) kmalloc( - (dma_sectors / SECTORS_PER_PAGE) * sizeof(*dma_malloc_pages), - GFP_ATOMIC); - if (dma_malloc_pages) { - memset(dma_malloc_pages, 0, size); - dma_malloc_pages[0] = (unsigned char *) - __get_free_pages(GFP_ATOMIC | GFP_DMA, 0); - if (dma_malloc_pages[0]) - has_space = 1; - } - } - if (!has_space) { - if (dma_malloc_freelist) { - kfree((char *) dma_malloc_freelist); - if (dma_malloc_pages) - kfree((char *) dma_malloc_pages); - } - spin_unlock_irqrestore(&allocator_request_lock, flags); - printk("scsi::init_module: failed, out of memory\n"); - return 1; - } - - spin_unlock_irqrestore(&allocator_request_lock, flags); - return 0; -} diff --git a/xen/drivers/scsi/scsi_error.c b/xen/drivers/scsi/scsi_error.c deleted file mode 100644 index 1313e4785f..0000000000 --- a/xen/drivers/scsi/scsi_error.c +++ /dev/null @@ -1,2063 +0,0 @@ -/* - * scsi_error.c Copyright (C) 1997 Eric Youngdale - * - * SCSI error/timeout handling - * Initial versions: Eric Youngdale. Based upon conversations with - * Leonard Zubkoff and David Miller at Linux Expo, - * ideas originating from all over the place. - * - */ - -#define __NO_VERSION__ -#include - -#include -#include -/*#include */ -#include -#include -#include -/*#include */ -#include -#include -#include -/*#include */ - -#define __KERNEL_SYSCALLS__ - -/*#include */ - -#include -#include -#include - -#include "scsi.h" -#include "hosts.h" -#include "constants.h" - -/* - * We must always allow SHUTDOWN_SIGS. Even if we are not a module, - * the host drivers that we are using may be loaded as modules, and - * when we unload these, we need to ensure that the error handler thread - * can be shut down. - * - * Note - when we unload a module, we send a SIGHUP. We mustn't - * enable SIGTERM, as this is how the init shuts things down when you - * go to single-user mode. For that matter, init also sends SIGKILL, - * so we mustn't enable that one either. We use SIGHUP instead. Other - * options would be SIGPWR, I suppose. - */ -#define SHUTDOWN_SIGS (sigmask(SIGHUP)) - -#ifdef DEBUG -#define SENSE_TIMEOUT SCSI_TIMEOUT -#define ABORT_TIMEOUT SCSI_TIMEOUT -#define RESET_TIMEOUT SCSI_TIMEOUT -#else -#define SENSE_TIMEOUT (10*HZ) -#define RESET_TIMEOUT (2*HZ) -#define ABORT_TIMEOUT (15*HZ) -#endif - -#define STATIC - -/* - * These should *probably* be handled by the host itself. - * Since it is allowed to sleep, it probably should. - */ -#define BUS_RESET_SETTLE_TIME 5*HZ -#define HOST_RESET_SETTLE_TIME 10*HZ - - -static const char RCSid[] = "$Header: /mnt/ide/home/eric/CVSROOT/linux/drivers/scsi/scsi_error.c,v 1.10 1997/12/08 04:50:35 eric Exp $"; - -STATIC int scsi_check_sense(Scsi_Cmnd * SCpnt); -STATIC int scsi_request_sense(Scsi_Cmnd *); -STATIC void scsi_send_eh_cmnd(Scsi_Cmnd * SCpnt, int timeout); -STATIC int scsi_try_to_abort_command(Scsi_Cmnd *, int); -STATIC int scsi_test_unit_ready(Scsi_Cmnd *); -STATIC int scsi_try_bus_device_reset(Scsi_Cmnd *, int timeout); -STATIC int scsi_try_bus_reset(Scsi_Cmnd *); -STATIC int scsi_try_host_reset(Scsi_Cmnd *); -STATIC int scsi_unit_is_ready(Scsi_Cmnd *); -STATIC void scsi_eh_action_done(Scsi_Cmnd *, int); -STATIC int scsi_eh_retry_command(Scsi_Cmnd *); -STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt); -STATIC void scsi_restart_operations(struct Scsi_Host *); -STATIC void scsi_eh_finish_command(Scsi_Cmnd ** SClist, Scsi_Cmnd * SCpnt); - - -/* - * Function: scsi_add_timer() - * - * Purpose: Start timeout timer for a single scsi command. - * - * Arguments: SCset - command that is about to start running. - * timeout - amount of time to allow this command to run. - * complete - timeout function to call if timer isn't - * canceled. - * - * Returns: Nothing - * - * Notes: This should be turned into an inline function. - * - * More Notes: Each scsi command has it's own timer, and as it is added to - * the queue, we set up the timer. When the command completes, - * we cancel the timer. Pretty simple, really, especially - * compared to the old way of handling this crap. - */ -void scsi_add_timer(Scsi_Cmnd * SCset, - int timeout, - void (*complete) (Scsi_Cmnd *)) -{ - - /* - * If the clock was already running for this command, then - * first delete the timer. The timer handling code gets rather - * confused if we don't do this. - */ - if (SCset->eh_timeout.function != NULL) { - del_timer(&SCset->eh_timeout); - } - SCset->eh_timeout.data = (unsigned long) SCset; - SCset->eh_timeout.expires = jiffies + timeout; - SCset->eh_timeout.function = (void (*)(unsigned long)) complete; - - SCset->done_late = 0; - - SCSI_LOG_ERROR_RECOVERY(5, printk("Adding timer for command %p at %d (%p)\n", SCset, timeout, complete)); - - add_timer(&SCset->eh_timeout); - -} - -/* - * Function: scsi_delete_timer() - * - * Purpose: Delete/cancel timer for a given function. - * - * Arguments: SCset - command that we are canceling timer for. - * - * Returns: 1 if we were able to detach the timer. 0 if we - * blew it, and the timer function has already started - * to run. - * - * Notes: This should be turned into an inline function. - */ -int scsi_delete_timer(Scsi_Cmnd * SCset) -{ - int rtn; - - rtn = del_timer(&SCset->eh_timeout); - - SCSI_LOG_ERROR_RECOVERY(5, printk("Clearing timer for command %p %d\n", SCset, rtn)); - - SCset->eh_timeout.data = (unsigned long) NULL; - SCset->eh_timeout.function = NULL; - - return rtn; -} - -/* - * Function: scsi_times_out() - * - * Purpose: Timeout function for normal scsi commands.. - * - * Arguments: SCpnt - command that is timing out. - * - * Returns: Nothing. - * - * Notes: We do not need to lock this. There is the potential for - * a race only in that the normal completion handling might - * run, but if the normal completion function determines - * that the timer has already fired, then it mustn't do - * anything. - */ -void scsi_times_out(Scsi_Cmnd * SCpnt) -{ - /* - * Notify the low-level code that this operation failed and we are - * reposessing the command. - */ -#ifdef ERIC_neverdef - /* - * FIXME(eric) - * Allow the host adapter to push a queue ordering tag - * out to the bus to force the command in question to complete. - * If the host wants to do this, then we just restart the timer - * for the command. Before we really do this, some real thought - * as to the optimum way to handle this should be done. We *do* - * need to force ordering every so often to ensure that all requests - * do eventually complete, but I am not sure if this is the best way - * to actually go about it. - * - * Better yet, force a sync here, but don't block since we are in an - * interrupt. - */ - if (SCpnt->host->hostt->eh_ordered_queue_tag) { - if ((*SCpnt->host->hostt->eh_ordered_queue_tag) (SCpnt)) { - scsi_add_timer(SCpnt, SCpnt->internal_timeout, - scsi_times_out); - return; - } - } - /* - * FIXME(eric) - add a second special interface to handle this - * case. Ideally that interface can also be used to request - * a queu - */ - if (SCpnt->host->can_queue) { - SCpnt->host->hostt->queuecommand(SCpnt, NULL); - } -#endif - - /* Set the serial_number_at_timeout to the current serial_number */ - SCpnt->serial_number_at_timeout = SCpnt->serial_number; - - SCpnt->eh_state = FAILED; - SCpnt->state = SCSI_STATE_TIMEOUT; - SCpnt->owner = SCSI_OWNER_ERROR_HANDLER; - - SCpnt->host->in_recovery = 1; - SCpnt->host->host_failed++; - - SCSI_LOG_TIMEOUT(3, printk("Command timed out active=%d busy=%d failed=%d\n", - atomic_read(&SCpnt->host->host_active), - SCpnt->host->host_busy, - SCpnt->host->host_failed)); - -#if 0 - /* - * If the host is having troubles, then look to see if this was the last - * command that might have failed. If so, wake up the error handler. - */ - if( SCpnt->host->eh_wait == NULL ) { - panic("Error handler thread not present at %p %p %s %d", - SCpnt, SCpnt->host, __FILE__, __LINE__); - } - if (SCpnt->host->host_busy == SCpnt->host->host_failed) { - up(SCpnt->host->eh_wait); - } -#endif -} - -/* - * Function scsi_block_when_processing_errors - * - * Purpose: Prevent more commands from being queued while error recovery - * is taking place. - * - * Arguments: SDpnt - device on which we are performing recovery. - * - * Returns: FALSE The device was taken offline by error recovery. - * TRUE OK to proceed. - * - * Notes: We block until the host is out of error recovery, and then - * check to see whether the host or the device is offline. - */ -int scsi_block_when_processing_errors(Scsi_Device * SDpnt) -{ - - SCSI_SLEEP(&SDpnt->host->host_wait, SDpnt->host->in_recovery); - - SCSI_LOG_ERROR_RECOVERY(5, printk("Open returning %d\n", SDpnt->online)); - - return SDpnt->online; -} - -/* - * Function: scsi_eh_times_out() - * - * Purpose: Timeout function for error handling. - * - * Arguments: SCpnt - command that is timing out. - * - * Returns: Nothing. - * - * Notes: During error handling, the kernel thread will be sleeping - * waiting for some action to complete on the device. Our only - * job is to record that it timed out, and to wake up the - * thread. - */ -STATIC -void scsi_eh_times_out(Scsi_Cmnd * SCpnt) -{ - SCpnt->eh_state = SCSI_STATE_TIMEOUT; - SCSI_LOG_ERROR_RECOVERY(5, printk("In scsi_eh_times_out %p\n", SCpnt)); - -#if 0 - if (SCpnt->host->eh_action != NULL) - up(SCpnt->host->eh_action); - else -#endif - printk("Missing scsi error handler thread\n"); -} - - -/* - * Function: scsi_eh_done() - * - * Purpose: Completion function for error handling. - * - * Arguments: SCpnt - command that is timing out. - * - * Returns: Nothing. - * - * Notes: During error handling, the kernel thread will be sleeping - * waiting for some action to complete on the device. Our only - * job is to record that the action completed, and to wake up the - * thread. - */ -STATIC -void scsi_eh_done(Scsi_Cmnd * SCpnt) -{ - int rtn; - - /* - * If the timeout handler is already running, then just set the - * flag which says we finished late, and return. We have no - * way of stopping the timeout handler from running, so we must - * always defer to it. - */ - rtn = del_timer(&SCpnt->eh_timeout); - if (!rtn) { - SCpnt->done_late = 1; - return; - } - - SCpnt->request.rq_status = RQ_SCSI_DONE; - - SCpnt->owner = SCSI_OWNER_ERROR_HANDLER; - SCpnt->eh_state = SUCCESS; - - SCSI_LOG_ERROR_RECOVERY(5, printk("In eh_done %p result:%x\n", SCpnt, - SCpnt->result)); - -#if 0 - if (SCpnt->host->eh_action != NULL) - up(SCpnt->host->eh_action); -#endif -} - -/* - * Function: scsi_eh_action_done() - * - * Purpose: Completion function for error handling. - * - * Arguments: SCpnt - command that is timing out. - * answer - boolean that indicates whether operation succeeded. - * - * Returns: Nothing. - * - * Notes: This callback is only used for abort and reset operations. - */ -STATIC -void scsi_eh_action_done(Scsi_Cmnd * SCpnt, int answer) -{ - SCpnt->request.rq_status = RQ_SCSI_DONE; - - SCpnt->owner = SCSI_OWNER_ERROR_HANDLER; - SCpnt->eh_state = (answer ? SUCCESS : FAILED); -#if 0 - if (SCpnt->host->eh_action != NULL) - up(SCpnt->host->eh_action); -#endif -} - -/* - * Function: scsi_sense_valid() - * - * Purpose: Determine whether a host has automatically obtained sense - * information or not. If we have it, then give a recommendation - * as to what we should do next. - */ -int scsi_sense_valid(Scsi_Cmnd * SCpnt) -{ - if (((SCpnt->sense_buffer[0] & 0x70) >> 4) != 7) { - return FALSE; - } - return TRUE; -} - -/* - * Function: scsi_eh_retry_command() - * - * Purpose: Retry the original command - * - * Returns: SUCCESS - we were able to get the sense data. - * FAILED - we were not able to get the sense data. - * - * Notes: This function will *NOT* return until the command either - * times out, or it completes. - */ -STATIC int scsi_eh_retry_command(Scsi_Cmnd * SCpnt) -{ - memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd, - sizeof(SCpnt->data_cmnd)); - SCpnt->request_buffer = SCpnt->buffer; - SCpnt->request_bufflen = SCpnt->bufflen; - SCpnt->use_sg = SCpnt->old_use_sg; - SCpnt->cmd_len = SCpnt->old_cmd_len; - SCpnt->sc_data_direction = SCpnt->sc_old_data_direction; - SCpnt->underflow = SCpnt->old_underflow; - - scsi_send_eh_cmnd(SCpnt, SCpnt->timeout_per_command); - - /* - * Hey, we are done. Let's look to see what happened. - */ - return SCpnt->eh_state; -} - -/* - * Function: scsi_request_sense() - * - * Purpose: Request sense data from a particular target. - * - * Returns: SUCCESS - we were able to get the sense data. - * FAILED - we were not able to get the sense data. - * - * Notes: Some hosts automatically obtain this information, others - * require that we obtain it on our own. - * - * This function will *NOT* return until the command either - * times out, or it completes. - */ -STATIC int scsi_request_sense(Scsi_Cmnd * SCpnt) -{ - static unsigned char generic_sense[6] = - {REQUEST_SENSE, 0, 0, 0, 255, 0}; - unsigned char scsi_result0[256], *scsi_result = NULL; - int saved_result; - - ASSERT_LOCK(&io_request_lock, 0); - - memcpy((void *) SCpnt->cmnd, (void *) generic_sense, - sizeof(generic_sense)); - - if (SCpnt->device->scsi_level <= SCSI_2) - SCpnt->cmnd[1] = SCpnt->lun << 5; - - scsi_result = (!SCpnt->host->hostt->unchecked_isa_dma) - ? &scsi_result0[0] : kmalloc(512, GFP_ATOMIC | GFP_DMA); - - if (scsi_result == NULL) { - printk("cannot allocate scsi_result in scsi_request_sense.\n"); - return FAILED; - } - /* - * Zero the sense buffer. Some host adapters automatically always request - * sense, so it is not a good idea that SCpnt->request_buffer and - * SCpnt->sense_buffer point to the same address (DB). - * 0 is not a valid sense code. - */ - memset((void *) SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); - memset((void *) scsi_result, 0, 256); - - saved_result = SCpnt->result; - SCpnt->request_buffer = scsi_result; - SCpnt->request_bufflen = 256; - SCpnt->use_sg = 0; - SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]); - SCpnt->sc_data_direction = SCSI_DATA_READ; - SCpnt->underflow = 0; - - scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT); - - /* Last chance to have valid sense data */ - if (!scsi_sense_valid(SCpnt)) - memcpy((void *) SCpnt->sense_buffer, - SCpnt->request_buffer, - sizeof(SCpnt->sense_buffer)); - - if (scsi_result != &scsi_result0[0] && scsi_result != NULL) - kfree(scsi_result); - - /* - * When we eventually call scsi_finish, we really wish to complete - * the original request, so let's restore the original data. (DB) - */ - memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd, - sizeof(SCpnt->data_cmnd)); - SCpnt->result = saved_result; - SCpnt->request_buffer = SCpnt->buffer; - SCpnt->request_bufflen = SCpnt->bufflen; - SCpnt->use_sg = SCpnt->old_use_sg; - SCpnt->cmd_len = SCpnt->old_cmd_len; - SCpnt->sc_data_direction = SCpnt->sc_old_data_direction; - SCpnt->underflow = SCpnt->old_underflow; - - /* - * Hey, we are done. Let's look to see what happened. - */ - return SCpnt->eh_state; -} - -/* - * Function: scsi_test_unit_ready() - * - * Purpose: Run test unit ready command to see if the device is talking to us or not. - * - */ -STATIC int scsi_test_unit_ready(Scsi_Cmnd * SCpnt) -{ - static unsigned char tur_command[6] = - {TEST_UNIT_READY, 0, 0, 0, 0, 0}; - - memcpy((void *) SCpnt->cmnd, (void *) tur_command, - sizeof(tur_command)); - - if (SCpnt->device->scsi_level <= SCSI_2) - SCpnt->cmnd[1] = SCpnt->lun << 5; - - /* - * Zero the sense buffer. The SCSI spec mandates that any - * untransferred sense data should be interpreted as being zero. - */ - memset((void *) SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); - - SCpnt->request_buffer = NULL; - SCpnt->request_bufflen = 0; - SCpnt->use_sg = 0; - SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]); - SCpnt->underflow = 0; - SCpnt->sc_data_direction = SCSI_DATA_NONE; - - scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT); - - /* - * When we eventually call scsi_finish, we really wish to complete - * the original request, so let's restore the original data. (DB) - */ - memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd, - sizeof(SCpnt->data_cmnd)); - SCpnt->request_buffer = SCpnt->buffer; - SCpnt->request_bufflen = SCpnt->bufflen; - SCpnt->use_sg = SCpnt->old_use_sg; - SCpnt->cmd_len = SCpnt->old_cmd_len; - SCpnt->sc_data_direction = SCpnt->sc_old_data_direction; - SCpnt->underflow = SCpnt->old_underflow; - - /* - * Hey, we are done. Let's look to see what happened. - */ - SCSI_LOG_ERROR_RECOVERY(3, - printk("scsi_test_unit_ready: SCpnt %p eh_state %x\n", - SCpnt, SCpnt->eh_state)); - return SCpnt->eh_state; -} - -/* - * This would normally need to get the IO request lock, - * but as it doesn't actually touch anything that needs - * to be locked we can avoid the lock here.. - */ -STATIC -void scsi_sleep_done(struct semaphore *sem) -{ -#if 0 - if (sem != NULL) { - up(sem); - } -#endif -} - -void scsi_sleep(int timeout) -{ -#if 0 - DECLARE_MUTEX_LOCKED(sem); -#endif - struct timer_list timer; - - init_timer(&timer); -#if 0 - timer.data = (unsigned long) &sem; -#else - timer.data = 0xDEADBEEF; -#endif - timer.expires = jiffies + timeout; - timer.function = (void (*)(unsigned long)) scsi_sleep_done; - - SCSI_LOG_ERROR_RECOVERY(5, printk("Sleeping for timer tics %d\n", timeout)); - - add_timer(&timer); - -#if 0 - down(&sem); -#endif - del_timer(&timer); -} - -/* - * Function: scsi_send_eh_cmnd - * - * Purpose: Send a command out to a device as part of error recovery. - * - * Notes: The initialization of the structures is quite a bit different - * in this case, and furthermore, there is a different completion - * handler. - */ -STATIC void scsi_send_eh_cmnd(Scsi_Cmnd * SCpnt, int timeout) -{ - unsigned long flags; - struct Scsi_Host *host; - - ASSERT_LOCK(&io_request_lock, 0); - - host = SCpnt->host; - - retry: - /* - * We will use a queued command if possible, otherwise we will emulate the - * queuing and calling of completion function ourselves. - */ - SCpnt->owner = SCSI_OWNER_LOWLEVEL; - - if (host->can_queue) { -#if 0 - DECLARE_MUTEX_LOCKED(sem); -#endif - - SCpnt->eh_state = SCSI_STATE_QUEUED; - - scsi_add_timer(SCpnt, timeout, scsi_eh_times_out); - -#if 0 - /* - * Set up the semaphore so we wait for the command to complete. - */ - SCpnt->host->eh_action = &sem; -#endif - SCpnt->request.rq_status = RQ_SCSI_BUSY; - - spin_lock_irqsave(&io_request_lock, flags); - host->hostt->queuecommand(SCpnt, scsi_eh_done); - spin_unlock_irqrestore(&io_request_lock, flags); - -#if 0 - down(&sem); -#endif - - SCpnt->host->eh_action = NULL; - - /* - * See if timeout. If so, tell the host to forget about it. - * In other words, we don't want a callback any more. - */ - if (SCpnt->eh_state == SCSI_STATE_TIMEOUT) { - SCpnt->owner = SCSI_OWNER_LOWLEVEL; - - /* - * As far as the low level driver is - * concerned, this command is still active, so - * we must give the low level driver a chance - * to abort it. (DB) - * - * FIXME(eric) - we are not tracking whether we could - * abort a timed out command or not. Not sure how - * we should treat them differently anyways. - */ - spin_lock_irqsave(&io_request_lock, flags); - if (SCpnt->host->hostt->eh_abort_handler) - SCpnt->host->hostt->eh_abort_handler(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); - - SCpnt->request.rq_status = RQ_SCSI_DONE; - SCpnt->owner = SCSI_OWNER_ERROR_HANDLER; - - SCpnt->eh_state = FAILED; - } - SCSI_LOG_ERROR_RECOVERY(5, printk("send_eh_cmnd: %p eh_state:%x\n", - SCpnt, SCpnt->eh_state)); - } else { - int temp; - - /* - * We damn well had better never use this code. There is no timeout - * protection here, since we would end up waiting in the actual low - * level driver, we don't know how to wake it up. - */ - spin_lock_irqsave(&io_request_lock, flags); - temp = host->hostt->command(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); - - SCpnt->result = temp; - /* Fall through to code below to examine status. */ - SCpnt->eh_state = SUCCESS; - } - - /* - * Now examine the actual status codes to see whether the command actually - * did complete normally. - */ - if (SCpnt->eh_state == SUCCESS) { - int ret = scsi_eh_completed_normally(SCpnt); - SCSI_LOG_ERROR_RECOVERY(3, - printk("scsi_send_eh_cmnd: scsi_eh_completed_normally %x\n", ret)); - switch (ret) { - case SUCCESS: - SCpnt->eh_state = SUCCESS; - break; - case NEEDS_RETRY: - goto retry; - case FAILED: - default: - SCpnt->eh_state = FAILED; - break; - } - } else { - SCpnt->eh_state = FAILED; - } -} - -/* - * Function: scsi_unit_is_ready() - * - * Purpose: Called after TEST_UNIT_READY is run, to test to see if - * the unit responded in a way that indicates it is ready. - */ -STATIC int scsi_unit_is_ready(Scsi_Cmnd * SCpnt) -{ - if (SCpnt->result) { - if (((driver_byte(SCpnt->result) & DRIVER_SENSE) || - (status_byte(SCpnt->result) & CHECK_CONDITION)) && - ((SCpnt->sense_buffer[0] & 0x70) >> 4) == 7) { - if (((SCpnt->sense_buffer[2] & 0xf) != NOT_READY) && - ((SCpnt->sense_buffer[2] & 0xf) != UNIT_ATTENTION) && - ((SCpnt->sense_buffer[2] & 0xf) != ILLEGAL_REQUEST)) { - return 0; - } - } - } - return 1; -} - -/* - * Function: scsi_eh_finish_command - * - * Purpose: Handle a command that we are finished with WRT error handling. - * - * Arguments: SClist - pointer to list into which we are putting completed commands. - * SCpnt - command that is completing - * - * Notes: We don't want to use the normal command completion while we are - * are still handling errors - it may cause other commands to be queued, - * and that would disturb what we are doing. Thus we really want to keep - * a list of pending commands for final completion, and once we - * are ready to leave error handling we handle completion for real. - */ -STATIC void scsi_eh_finish_command(Scsi_Cmnd ** SClist, Scsi_Cmnd * SCpnt) -{ - SCpnt->state = SCSI_STATE_BHQUEUE; - SCpnt->bh_next = *SClist; - /* - * Set this back so that the upper level can correctly free up - * things. - */ - SCpnt->use_sg = SCpnt->old_use_sg; - SCpnt->sc_data_direction = SCpnt->sc_old_data_direction; - SCpnt->underflow = SCpnt->old_underflow; - *SClist = SCpnt; -} - -/* - * Function: scsi_try_to_abort_command - * - * Purpose: Ask host adapter to abort a running command. - * - * Returns: FAILED Operation failed or not supported. - * SUCCESS Succeeded. - * - * Notes: This function will not return until the user's completion - * function has been called. There is no timeout on this - * operation. If the author of the low-level driver wishes - * this operation to be timed, they can provide this facility - * themselves. Helper functions in scsi_error.c can be supplied - * to make this easier to do. - * - * Notes: It may be possible to combine this with all of the reset - * handling to eliminate a lot of code duplication. I don't - * know what makes more sense at the moment - this is just a - * prototype. - */ -STATIC int scsi_try_to_abort_command(Scsi_Cmnd * SCpnt, int timeout) -{ - int rtn; - unsigned long flags; - - SCpnt->eh_state = FAILED; /* Until we come up with something better */ - - if (SCpnt->host->hostt->eh_abort_handler == NULL) { - return FAILED; - } - /* - * scsi_done was called just after the command timed out and before - * we had a chance to process it. (DB) - */ - if (SCpnt->serial_number == 0) - return SUCCESS; - - SCpnt->owner = SCSI_OWNER_LOWLEVEL; - - spin_lock_irqsave(&io_request_lock, flags); - rtn = SCpnt->host->hostt->eh_abort_handler(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); - return rtn; -} - -/* - * Function: scsi_try_bus_device_reset - * - * Purpose: Ask host adapter to perform a bus device reset for a given - * device. - * - * Returns: FAILED Operation failed or not supported. - * SUCCESS Succeeded. - * - * Notes: There is no timeout for this operation. If this operation is - * unreliable for a given host, then the host itself needs to put a - * timer on it, and set the host back to a consistent state prior - * to returning. - */ -STATIC int scsi_try_bus_device_reset(Scsi_Cmnd * SCpnt, int timeout) -{ - unsigned long flags; - int rtn; - - SCpnt->eh_state = FAILED; /* Until we come up with something better */ - - if (SCpnt->host->hostt->eh_device_reset_handler == NULL) { - return FAILED; - } - SCpnt->owner = SCSI_OWNER_LOWLEVEL; - - spin_lock_irqsave(&io_request_lock, flags); - rtn = SCpnt->host->hostt->eh_device_reset_handler(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); - - if (rtn == SUCCESS) - SCpnt->eh_state = SUCCESS; - - return SCpnt->eh_state; -} - -/* - * Function: scsi_try_bus_reset - * - * Purpose: Ask host adapter to perform a bus reset for a host. - * - * Returns: FAILED Operation failed or not supported. - * SUCCESS Succeeded. - * - * Notes: - */ -STATIC int scsi_try_bus_reset(Scsi_Cmnd * SCpnt) -{ - unsigned long flags; - int rtn; - - SCpnt->eh_state = FAILED; /* Until we come up with something better */ - SCpnt->owner = SCSI_OWNER_LOWLEVEL; - SCpnt->serial_number_at_timeout = SCpnt->serial_number; - - if (SCpnt->host->hostt->eh_bus_reset_handler == NULL) { - return FAILED; - } - - spin_lock_irqsave(&io_request_lock, flags); - rtn = SCpnt->host->hostt->eh_bus_reset_handler(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); - - if (rtn == SUCCESS) - SCpnt->eh_state = SUCCESS; - - /* - * If we had a successful bus reset, mark the command blocks to expect - * a condition code of unit attention. - */ - scsi_sleep(BUS_RESET_SETTLE_TIME); - if (SCpnt->eh_state == SUCCESS) { - Scsi_Device *SDloop; - for (SDloop = SCpnt->host->host_queue; SDloop; SDloop = SDloop->next) { - if (SCpnt->channel == SDloop->channel) { - SDloop->was_reset = 1; - SDloop->expecting_cc_ua = 1; - } - } - } - return SCpnt->eh_state; -} - -/* - * Function: scsi_try_host_reset - * - * Purpose: Ask host adapter to reset itself, and the bus. - * - * Returns: FAILED Operation failed or not supported. - * SUCCESS Succeeded. - * - * Notes: - */ -STATIC int scsi_try_host_reset(Scsi_Cmnd * SCpnt) -{ - unsigned long flags; - int rtn; - - SCpnt->eh_state = FAILED; /* Until we come up with something better */ - SCpnt->owner = SCSI_OWNER_LOWLEVEL; - SCpnt->serial_number_at_timeout = SCpnt->serial_number; - - if (SCpnt->host->hostt->eh_host_reset_handler == NULL) { - return FAILED; - } - spin_lock_irqsave(&io_request_lock, flags); - rtn = SCpnt->host->hostt->eh_host_reset_handler(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); - - if (rtn == SUCCESS) - SCpnt->eh_state = SUCCESS; - - /* - * If we had a successful host reset, mark the command blocks to expect - * a condition code of unit attention. - */ - scsi_sleep(HOST_RESET_SETTLE_TIME); - if (SCpnt->eh_state == SUCCESS) { - Scsi_Device *SDloop; - for (SDloop = SCpnt->host->host_queue; SDloop; SDloop = SDloop->next) { - SDloop->was_reset = 1; - SDloop->expecting_cc_ua = 1; - } - } - return SCpnt->eh_state; -} - -/* - * Function: scsi_decide_disposition - * - * Purpose: Examine a command block that has come back from the low-level - * and figure out what to do next. - * - * Returns: SUCCESS - pass on to upper level. - * FAILED - pass on to error handler thread. - * RETRY - command should be retried. - * SOFTERR - command succeeded, but we need to log - * a soft error. - * - * Notes: This is *ONLY* called when we are examining the status - * after sending out the actual data command. Any commands - * that are queued for error recovery (i.e. TEST_UNIT_READY) - * do *NOT* come through here. - * - * NOTE - When this routine returns FAILED, it means the error - * handler thread is woken. In cases where the error code - * indicates an error that doesn't require the error handler - * thread (i.e. we don't need to abort/reset), then this function - * should return SUCCESS. - */ -int scsi_decide_disposition(Scsi_Cmnd * SCpnt) -{ - int rtn; - - /* - * If the device is offline, then we clearly just pass the result back - * up to the top level. - */ - if (SCpnt->device->online == FALSE) { - SCSI_LOG_ERROR_RECOVERY(5, printk("scsi_error.c: device offline - report as SUCCESS\n")); - return SUCCESS; - } - /* - * First check the host byte, to see if there is anything in there - * that would indicate what we need to do. - */ - - switch (host_byte(SCpnt->result)) { - case DID_PASSTHROUGH: - /* - * No matter what, pass this through to the upper layer. - * Nuke this special code so that it looks like we are saying - * DID_OK. - */ - SCpnt->result &= 0xff00ffff; - return SUCCESS; - case DID_OK: - /* - * Looks good. Drop through, and check the next byte. - */ - break; - case DID_NO_CONNECT: - case DID_BAD_TARGET: - case DID_ABORT: - /* - * Note - this means that we just report the status back to the - * top level driver, not that we actually think that it indicates - * success. - */ - return SUCCESS; - /* - * When the low level driver returns DID_SOFT_ERROR, - * it is responsible for keeping an internal retry counter - * in order to avoid endless loops (DB) - * - * Actually this is a bug in this function here. We should - * be mindful of the maximum number of retries specified - * and not get stuck in a loop. - */ - case DID_SOFT_ERROR: - goto maybe_retry; - - case DID_ERROR: - if (msg_byte(SCpnt->result) == COMMAND_COMPLETE && - status_byte(SCpnt->result) == RESERVATION_CONFLICT) - /* - * execute reservation conflict processing code - * lower down - */ - break; - /* FALLTHROUGH */ - - case DID_BUS_BUSY: - case DID_PARITY: - goto maybe_retry; - case DID_TIME_OUT: - /* - * When we scan the bus, we get timeout messages for - * these commands if there is no device available. - * Other hosts report DID_NO_CONNECT for the same thing. - */ - if ((SCpnt->cmnd[0] == TEST_UNIT_READY || - SCpnt->cmnd[0] == INQUIRY)) { - return SUCCESS; - } else { - return FAILED; - } - case DID_RESET: - /* - * In the normal case where we haven't initiated a reset, this is - * a failure. - */ - if (SCpnt->flags & IS_RESETTING) { - SCpnt->flags &= ~IS_RESETTING; - goto maybe_retry; - } - return SUCCESS; - default: - return FAILED; - } - - /* - * Next, check the message byte. - */ - if (msg_byte(SCpnt->result) != COMMAND_COMPLETE) { - return FAILED; - } - /* - * Now, check the status byte to see if this indicates anything special. - */ - switch (status_byte(SCpnt->result)) { - case QUEUE_FULL: - /* - * The case of trying to send too many commands to a tagged queueing - * device. - */ - return ADD_TO_MLQUEUE; - case GOOD: - case COMMAND_TERMINATED: - return SUCCESS; - case CHECK_CONDITION: - rtn = scsi_check_sense(SCpnt); - if (rtn == NEEDS_RETRY) { - goto maybe_retry; - } - return rtn; - case CONDITION_GOOD: - case INTERMEDIATE_GOOD: - case INTERMEDIATE_C_GOOD: - /* - * Who knows? FIXME(eric) - */ - return SUCCESS; - case BUSY: - goto maybe_retry; - - case RESERVATION_CONFLICT: - printk("scsi%d (%d,%d,%d) : RESERVATION CONFLICT\n", - SCpnt->host->host_no, SCpnt->channel, - SCpnt->device->id, SCpnt->device->lun); - return SUCCESS; /* causes immediate I/O error */ - default: - return FAILED; - } - return FAILED; - - maybe_retry: - - if ((++SCpnt->retries) < SCpnt->allowed) { - return NEEDS_RETRY; - } else { - /* - * No more retries - report this one back to upper level. - */ - return SUCCESS; - } -} - -/* - * Function: scsi_eh_completed_normally - * - * Purpose: Examine a command block that has come back from the low-level - * and figure out what to do next. - * - * Returns: SUCCESS - pass on to upper level. - * FAILED - pass on to error handler thread. - * RETRY - command should be retried. - * SOFTERR - command succeeded, but we need to log - * a soft error. - * - * Notes: This is *ONLY* called when we are examining the status - * of commands queued during error recovery. The main - * difference here is that we don't allow for the possibility - * of retries here, and we are a lot more restrictive about what - * we consider acceptable. - */ -STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt) -{ - /* - * First check the host byte, to see if there is anything in there - * that would indicate what we need to do. - */ - if (host_byte(SCpnt->result) == DID_RESET) { - if (SCpnt->flags & IS_RESETTING) { - /* - * OK, this is normal. We don't know whether in fact the - * command in question really needs to be rerun or not - - * if this was the original data command then the answer is yes, - * otherwise we just flag it as success. - */ - SCpnt->flags &= ~IS_RESETTING; - return NEEDS_RETRY; - } - /* - * Rats. We are already in the error handler, so we now get to try - * and figure out what to do next. If the sense is valid, we have - * a pretty good idea of what to do. If not, we mark it as failed. - */ - return scsi_check_sense(SCpnt); - } - if (host_byte(SCpnt->result) != DID_OK) { - return FAILED; - } - /* - * Next, check the message byte. - */ - if (msg_byte(SCpnt->result) != COMMAND_COMPLETE) { - return FAILED; - } - /* - * Now, check the status byte to see if this indicates anything special. - */ - switch (status_byte(SCpnt->result)) { - case GOOD: - case COMMAND_TERMINATED: - return SUCCESS; - case CHECK_CONDITION: - return scsi_check_sense(SCpnt); - case CONDITION_GOOD: - case INTERMEDIATE_GOOD: - case INTERMEDIATE_C_GOOD: - /* - * Who knows? FIXME(eric) - */ - return SUCCESS; - case BUSY: - case QUEUE_FULL: - case RESERVATION_CONFLICT: - default: - return FAILED; - } - return FAILED; -} - -/* - * Function: scsi_check_sense - * - * Purpose: Examine sense information - give suggestion as to what - * we should do with it. - */ -STATIC int scsi_check_sense(Scsi_Cmnd * SCpnt) -{ - if (!scsi_sense_valid(SCpnt)) { - return FAILED; - } - if (SCpnt->sense_buffer[2] & 0xe0) - return SUCCESS; - - switch (SCpnt->sense_buffer[2] & 0xf) { - case NO_SENSE: - return SUCCESS; - case RECOVERED_ERROR: - return /* SOFT_ERROR */ SUCCESS; - - case ABORTED_COMMAND: - return NEEDS_RETRY; - case NOT_READY: - case UNIT_ATTENTION: - /* - * If we are expecting a CC/UA because of a bus reset that we - * performed, treat this just as a retry. Otherwise this is - * information that we should pass up to the upper-level driver - * so that we can deal with it there. - */ - if (SCpnt->device->expecting_cc_ua) { - SCpnt->device->expecting_cc_ua = 0; - return NEEDS_RETRY; - } - /* - * If the device is in the process of becoming ready, we - * should retry. - */ - if ((SCpnt->sense_buffer[12] == 0x04) && - (SCpnt->sense_buffer[13] == 0x01)) { - return NEEDS_RETRY; - } - return SUCCESS; - - /* these three are not supported */ - case COPY_ABORTED: - case VOLUME_OVERFLOW: - case MISCOMPARE: - return SUCCESS; - - case MEDIUM_ERROR: - return NEEDS_RETRY; - - case ILLEGAL_REQUEST: - case BLANK_CHECK: - case DATA_PROTECT: - case HARDWARE_ERROR: - default: - return SUCCESS; - } -} - - -/* - * Function: scsi_restart_operations - * - * Purpose: Restart IO operations to the specified host. - * - * Arguments: host - host that we are restarting - * - * Lock status: Assumed that locks are not held upon entry. - * - * Returns: Nothing - * - * Notes: When we entered the error handler, we blocked all further - * I/O to this device. We need to 'reverse' this process. - */ -STATIC void scsi_restart_operations(struct Scsi_Host *host) -{ - Scsi_Device *SDpnt; - unsigned long flags; - - ASSERT_LOCK(&io_request_lock, 0); - - /* - * Next free up anything directly waiting upon the host. This will be - * requests for character device operations, and also for ioctls to queued - * block devices. - */ - SCSI_LOG_ERROR_RECOVERY(5, printk("scsi_error.c: Waking up host to restart\n")); -#if 0 - wake_up(&host->host_wait); -#endif - - /* - * Finally we need to re-initiate requests that may be pending. We will - * have had everything blocked while error handling is taking place, and - * now that error recovery is done, we will need to ensure that these - * requests are started. - */ - spin_lock_irqsave(&io_request_lock, flags); - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) { - request_queue_t *q; - if ((host->can_queue > 0 && (host->host_busy >= host->can_queue)) - || (host->host_blocked) - || (host->host_self_blocked) - || (SDpnt->device_blocked)) { - break; - } - q = &SDpnt->request_queue; - q->request_fn(q); - } - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * Function: scsi_unjam_host - * - * Purpose: Attempt to fix a host which has a command that failed for - * some reason. - * - * Arguments: host - host that needs unjamming. - * - * Returns: Nothing - * - * Notes: When we come in here, we *know* that all commands on the - * bus have either completed, failed or timed out. We also - * know that no further commands are being sent to the host, - * so things are relatively quiet and we have freedom to - * fiddle with things as we wish. - * - * Additional note: This is only the *default* implementation. It is possible - * for individual drivers to supply their own version of this - * function, and if the maintainer wishes to do this, it is - * strongly suggested that this function be taken as a template - * and modified. This function was designed to correctly handle - * problems for about 95% of the different cases out there, and - * it should always provide at least a reasonable amount of error - * recovery. - * - * Note3: Any command marked 'FAILED' or 'TIMEOUT' must eventually - * have scsi_finish_command() called for it. We do all of - * the retry stuff here, so when we restart the host after we - * return it should have an empty queue. - */ -STATIC int scsi_unjam_host(struct Scsi_Host *host) -{ - int devices_failed; - int numfailed; - int ourrtn; - int rtn = FALSE; - int result; - Scsi_Cmnd *SCloop; - Scsi_Cmnd *SCpnt; - Scsi_Device *SDpnt; - Scsi_Device *SDloop; - Scsi_Cmnd *SCdone; - int timed_out; - - ASSERT_LOCK(&io_request_lock, 0); - - SCdone = NULL; - - /* - * First, protect against any sort of race condition. If any of the outstanding - * commands are in states that indicate that we are not yet blocked (i.e. we are - * not in a quiet state) then we got woken up in error. If we ever end up here, - * we need to re-examine some of the assumptions. - */ - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) { - for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) { - if (SCpnt->state == SCSI_STATE_FAILED - || SCpnt->state == SCSI_STATE_TIMEOUT - || SCpnt->state == SCSI_STATE_INITIALIZING - || SCpnt->state == SCSI_STATE_UNUSED) { - continue; - } - /* - * Rats. Something is still floating around out there. This could - * be the result of the fact that the upper level drivers are still frobbing - * commands that might have succeeded. There are two outcomes. One is that - * the command block will eventually be freed, and the other one is that - * the command will be queued and will be finished along the way. - */ - SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler prematurely woken - commands still active (%p %x %d)\n", SCpnt, SCpnt->state, SCpnt->target)); - -/* - * panic("SCSI Error handler woken too early\n"); - * - * This is no longer a problem, since now the code cares only about - * SCSI_STATE_TIMEOUT and SCSI_STATE_FAILED. - * Other states are useful only to release active commands when devices are - * set offline. If (host->host_active == host->host_busy) we can safely assume - * that there are no commands in state other then TIMEOUT od FAILED. (DB) - * - * FIXME: - * It is not easy to release correctly commands according to their state when - * devices are set offline, when the state is neither TIMEOUT nor FAILED. - * When a device is set offline, we can have some command with - * rq_status=RQ_SCSY_BUSY, owner=SCSI_STATE_HIGHLEVEL, - * state=SCSI_STATE_INITIALIZING and the driver module cannot be released. - * (DB, 17 May 1998) - */ - } - } - - /* - * Next, see if we need to request sense information. if so, - * then get it now, so we have a better idea of what to do. - * FIXME(eric) this has the unfortunate side effect that if a host - * adapter does not automatically request sense information, that we end - * up shutting it down before we request it. All hosts should be doing this - * anyways, so for now all I have to say is tough noogies if you end up in here. - * On second thought, this is probably a good idea. We *really* want to give - * authors an incentive to automatically request this. - */ - SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Checking to see if we need to request sense\n")); - - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) { - for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) { - if (SCpnt->state != SCSI_STATE_FAILED || scsi_sense_valid(SCpnt)) { - continue; - } - SCSI_LOG_ERROR_RECOVERY(2, printk("scsi_unjam_host: Requesting sense for %d\n", - SCpnt->target)); - rtn = scsi_request_sense(SCpnt); - if (rtn != SUCCESS) { - continue; - } - SCSI_LOG_ERROR_RECOVERY(3, printk("Sense requested for %p - result %x\n", - SCpnt, SCpnt->result)); - SCSI_LOG_ERROR_RECOVERY(3, print_sense("bh", SCpnt)); - - result = scsi_decide_disposition(SCpnt); - - /* - * If the result was normal, then just pass it along to the - * upper level. - */ - if (result == SUCCESS) { - SCpnt->host->host_failed--; - scsi_eh_finish_command(&SCdone, SCpnt); - } - if (result != NEEDS_RETRY) { - continue; - } - /* - * We only come in here if we want to retry a - * command. The test to see whether the command - * should be retried should be keeping track of the - * number of tries, so we don't end up looping, of - * course. - */ - SCpnt->state = NEEDS_RETRY; - rtn = scsi_eh_retry_command(SCpnt); - if (rtn != SUCCESS) { - continue; - } - /* - * We eventually hand this one back to the top level. - */ - SCpnt->host->host_failed--; - scsi_eh_finish_command(&SCdone, SCpnt); - } - } - - /* - * Go through the list of commands and figure out where we stand and how bad things - * really are. - */ - numfailed = 0; - timed_out = 0; - devices_failed = 0; - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) { - unsigned int device_error = 0; - - for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) { - if (SCpnt->state == SCSI_STATE_FAILED) { - SCSI_LOG_ERROR_RECOVERY(5, printk("Command to ID %d failed\n", - SCpnt->target)); - numfailed++; - device_error++; - } - if (SCpnt->state == SCSI_STATE_TIMEOUT) { - SCSI_LOG_ERROR_RECOVERY(5, printk("Command to ID %d timedout\n", - SCpnt->target)); - timed_out++; - device_error++; - } - } - if (device_error > 0) { - devices_failed++; - } - } - - SCSI_LOG_ERROR_RECOVERY(2, printk("Total of %d+%d commands on %d devices require eh work\n", - numfailed, timed_out, devices_failed)); - - if (host->host_failed == 0) { - ourrtn = TRUE; - goto leave; - } - /* - * Next, try and see whether or not it makes sense to try and abort - * the running command. This only works out to be the case if we have - * one command that has timed out. If the command simply failed, it - * makes no sense to try and abort the command, since as far as the - * host adapter is concerned, it isn't running. - */ - - SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Checking to see if we want to try abort\n")); - - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) { - for (SCloop = SDpnt->device_queue; SCloop; SCloop = SCloop->next) { - if (SCloop->state != SCSI_STATE_TIMEOUT) { - continue; - } - rtn = scsi_try_to_abort_command(SCloop, ABORT_TIMEOUT); - if (rtn == SUCCESS) { - rtn = scsi_test_unit_ready(SCloop); - - if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) { - rtn = scsi_eh_retry_command(SCloop); - - if (rtn == SUCCESS) { - SCloop->host->host_failed--; - scsi_eh_finish_command(&SCdone, SCloop); - } - } - } - } - } - - /* - * If we have corrected all of the problems, then we are done. - */ - if (host->host_failed == 0) { - ourrtn = TRUE; - goto leave; - } - /* - * Either the abort wasn't appropriate, or it didn't succeed. - * Now try a bus device reset. Still, look to see whether we have - * multiple devices that are jammed or not - if we have multiple devices, - * it makes no sense to try BUS_DEVICE_RESET - we really would need - * to try a BUS_RESET instead. - * - * Does this make sense - should we try BDR on each device individually? - * Yes, definitely. - */ - SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Checking to see if we want to try BDR\n")); - - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) { - for (SCloop = SDpnt->device_queue; SCloop; SCloop = SCloop->next) { - if (SCloop->state == SCSI_STATE_FAILED - || SCloop->state == SCSI_STATE_TIMEOUT) { - break; - } - } - - if (SCloop == NULL) { - continue; - } - /* - * OK, we have a device that is having problems. Try and send - * a bus device reset to it. - * - * FIXME(eric) - make sure we handle the case where multiple - * commands to the same device have failed. They all must - * get properly restarted. - */ - rtn = scsi_try_bus_device_reset(SCloop, RESET_TIMEOUT); - - if (rtn == SUCCESS) { - rtn = scsi_test_unit_ready(SCloop); - - if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) { - rtn = scsi_eh_retry_command(SCloop); - - if (rtn == SUCCESS) { - SCloop->host->host_failed--; - scsi_eh_finish_command(&SCdone, SCloop); - } - } - } - } - - if (host->host_failed == 0) { - ourrtn = TRUE; - goto leave; - } - /* - * If we ended up here, we have serious problems. The only thing left - * to try is a full bus reset. If someone has grabbed the bus and isn't - * letting go, then perhaps this will help. - */ - SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Try hard bus reset\n")); - - /* - * We really want to loop over the various channels, and do this on - * a channel by channel basis. We should also check to see if any - * of the failed commands are on soft_reset devices, and if so, skip - * the reset. - */ - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) { - next_device: - for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) { - if (SCpnt->state != SCSI_STATE_FAILED - && SCpnt->state != SCSI_STATE_TIMEOUT) { - continue; - } - /* - * We have a failed command. Make sure there are no other failed - * commands on the same channel that are timed out and implement a - * soft reset. - */ - for (SDloop = host->host_queue; SDloop; SDloop = SDloop->next) { - for (SCloop = SDloop->device_queue; SCloop; SCloop = SCloop->next) { - if (SCloop->channel != SCpnt->channel) { - continue; - } - if (SCloop->state != SCSI_STATE_FAILED - && SCloop->state != SCSI_STATE_TIMEOUT) { - continue; - } - if (SDloop->soft_reset && SCloop->state == SCSI_STATE_TIMEOUT) { - /* - * If this device uses the soft reset option, and this - * is one of the devices acting up, then our only - * option is to wait a bit, since the command is - * supposedly still running. - * - * FIXME(eric) - right now we will just end up falling - * through to the 'take device offline' case. - * - * FIXME(eric) - It is possible that the command completed - * *after* the error recovery procedure started, and if this - * is the case, we are worrying about nothing here. - */ - - scsi_sleep(1 * HZ); - goto next_device; - } - } - } - - /* - * We now know that we are able to perform a reset for the - * bus that SCpnt points to. There are no soft-reset devices - * with outstanding timed out commands. - */ - rtn = scsi_try_bus_reset(SCpnt); - if (rtn == SUCCESS) { - for (SDloop = host->host_queue; SDloop; SDloop = SDloop->next) { - for (SCloop = SDloop->device_queue; SCloop; SCloop = SCloop->next) { - if (SCloop->channel != SCpnt->channel) { - continue; - } - if (SCloop->state != SCSI_STATE_FAILED - && SCloop->state != SCSI_STATE_TIMEOUT) { - continue; - } - rtn = scsi_test_unit_ready(SCloop); - - if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) { - rtn = scsi_eh_retry_command(SCloop); - - if (rtn == SUCCESS) { - SCpnt->host->host_failed--; - scsi_eh_finish_command(&SCdone, SCloop); - } - } - /* - * If the bus reset worked, but we are still unable to - * talk to the device, take it offline. - * FIXME(eric) - is this really the correct thing to do? - */ - if (rtn != SUCCESS) { - printk(KERN_INFO "scsi: device set offline - not ready or command retry failed after bus reset: host %d channel %d id %d lun %d\n", SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun); - - SDloop->online = FALSE; - SDloop->host->host_failed--; - scsi_eh_finish_command(&SCdone, SCloop); - } - } - } - } - } - } - - if (host->host_failed == 0) { - ourrtn = TRUE; - goto leave; - } - /* - * If we ended up here, we have serious problems. The only thing left - * to try is a full host reset - perhaps the firmware on the device - * crashed, or something like that. - * - * It is assumed that a succesful host reset will cause *all* information - * about the command to be flushed from both the host adapter *and* the - * device. - * - * FIXME(eric) - it isn't clear that devices that implement the soft reset - * option can ever be cleared except via cycling the power. The problem is - * that sending the host reset command will cause the host to forget - * about the pending command, but the device won't forget. For now, we - * skip the host reset option if any of the failed devices are configured - * to use the soft reset option. - */ - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) { - next_device2: - for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) { - if (SCpnt->state != SCSI_STATE_FAILED - && SCpnt->state != SCSI_STATE_TIMEOUT) { - continue; - } - if (SDpnt->soft_reset && SCpnt->state == SCSI_STATE_TIMEOUT) { - /* - * If this device uses the soft reset option, and this - * is one of the devices acting up, then our only - * option is to wait a bit, since the command is - * supposedly still running. - * - * FIXME(eric) - right now we will just end up falling - * through to the 'take device offline' case. - */ - SCSI_LOG_ERROR_RECOVERY(3, - printk("scsi_unjam_host: Unable to try hard host reset\n")); - - /* - * Due to the spinlock, we will never get out of this - * loop without a proper wait. (DB) - */ - scsi_sleep(1 * HZ); - - goto next_device2; - } - SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Try hard host reset\n")); - - /* - * FIXME(eric) - we need to obtain a valid SCpnt to perform this call. - */ - rtn = scsi_try_host_reset(SCpnt); - if (rtn == SUCCESS) { - /* - * FIXME(eric) we assume that all commands are flushed from the - * controller. We should get a DID_RESET for all of the commands - * that were pending. We should ignore these so that we can - * guarantee that we are in a consistent state. - * - * I believe this to be the case right now, but this needs to be - * tested. - */ - for (SDloop = host->host_queue; SDloop; SDloop = SDloop->next) { - for (SCloop = SDloop->device_queue; SCloop; SCloop = SCloop->next) { - if (SCloop->state != SCSI_STATE_FAILED - && SCloop->state != SCSI_STATE_TIMEOUT) { - continue; - } - rtn = scsi_test_unit_ready(SCloop); - - if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) { - rtn = scsi_eh_retry_command(SCloop); - - if (rtn == SUCCESS) { - SCpnt->host->host_failed--; - scsi_eh_finish_command(&SCdone, SCloop); - } - } - if (rtn != SUCCESS) { - printk(KERN_INFO "scsi: device set offline - not ready or command retry failed after host reset: host %d channel %d id %d lun %d\n", SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun); - SDloop->online = FALSE; - SDloop->host->host_failed--; - scsi_eh_finish_command(&SCdone, SCloop); - } - } - } - } - } - } - - /* - * If we solved all of the problems, then let's rev up the engines again. - */ - if (host->host_failed == 0) { - ourrtn = TRUE; - goto leave; - } - /* - * If the HOST RESET failed, then for now we assume that the entire host - * adapter is too hosed to be of any use. For our purposes, however, it is - * easier to simply take the devices offline that correspond to commands - * that failed. - */ - SCSI_LOG_ERROR_RECOVERY(1, printk("scsi_unjam_host: Take device offline\n")); - - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) { - for (SCloop = SDpnt->device_queue; SCloop; SCloop = SCloop->next) { - if (SCloop->state == SCSI_STATE_FAILED || SCloop->state == SCSI_STATE_TIMEOUT) { - SDloop = SCloop->device; - if (SDloop->online == TRUE) { - printk(KERN_INFO "scsi: device set offline - command error recover failed: host %d channel %d id %d lun %d\n", SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun); - SDloop->online = FALSE; - } - - /* - * This should pass the failure up to the top level driver, and - * it will have to try and do something intelligent with it. - */ - SCloop->host->host_failed--; - - if (SCloop->state == SCSI_STATE_TIMEOUT) { - SCloop->result |= (DRIVER_TIMEOUT << 24); - } - SCSI_LOG_ERROR_RECOVERY(3, printk("Finishing command for device %d %x\n", - SDloop->id, SCloop->result)); - - scsi_eh_finish_command(&SCdone, SCloop); - } - } - } - - if (host->host_failed != 0) { - panic("scsi_unjam_host: Miscount of number of failed commands.\n"); - } - SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Returning\n")); - - ourrtn = FALSE; - - leave: - - /* - * We should have a list of commands that we 'finished' during the course of - * error recovery. This should be the same as the list of commands that timed out - * or failed. We are currently holding these things in a linked list - we didn't - * put them in the bottom half queue because we wanted to keep things quiet while - * we were working on recovery, and passing them up to the top level could easily - * cause the top level to try and queue something else again. - * - * Start by marking that the host is no longer in error recovery. - */ - host->in_recovery = 0; - - /* - * Take the list of commands, and stick them in the bottom half queue. - * The current implementation of scsi_done will do this for us - if need - * be we can create a special version of this function to do the - * same job for us. - */ - for (SCpnt = SCdone; SCpnt != NULL; SCpnt = SCdone) { - SCdone = SCpnt->bh_next; - SCpnt->bh_next = NULL; - /* - * Oh, this is a vile hack. scsi_done() expects a timer - * to be running on the command. If there isn't, it assumes - * that the command has actually timed out, and a timer - * handler is running. That may well be how we got into - * this fix, but right now things are stable. We add - * a timer back again so that we can report completion. - * scsi_done() will immediately remove said timer from - * the command, and then process it. - */ - scsi_add_timer(SCpnt, 100, scsi_eh_times_out); - scsi_done(SCpnt); - } - - return (ourrtn); -} - - -/* - * Function: scsi_error_handler - * - * Purpose: Handle errors/timeouts of scsi commands, try and clean up - * and unjam the bus, and restart things. - * - * Arguments: host - host for which we are running. - * - * Returns: Never returns. - * - * Notes: This is always run in the context of a kernel thread. The - * idea is that we start this thing up when the kernel starts - * up (one per host that we detect), and it immediately goes to - * sleep and waits for some event (i.e. failure). When this - * takes place, we have the job of trying to unjam the bus - * and restarting things. - * - */ -void scsi_error_handler(void *data) -{ - struct Scsi_Host *host = (struct Scsi_Host *) data; - int rtn; -#if 0 - DECLARE_MUTEX_LOCKED(sem); - - /* - * We only listen to signals if the HA was loaded as a module. - * If the HA was compiled into the kernel, then we don't listen - * to any signals. - */ - if( host->loaded_as_module ) { - siginitsetinv(¤t->blocked, SHUTDOWN_SIGS); - } else { - siginitsetinv(¤t->blocked, 0); - } - - lock_kernel(); - - /* - * Flush resources - */ - - daemonize(); - reparent_to_init(); - - /* - * Set the name of this process. - */ - - sprintf(current->comm, "scsi_eh_%d", host->host_no); - - host->eh_wait = &sem; -#else - host->eh_wait = (void *)0xDEADBEEF; -#endif - host->ehandler = current; - -#if 0 - unlock_kernel(); -#endif - - /* - * Wake up the thread that created us. - */ -#if 0 - SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent %d\n", host->eh_notify->count.counter)); - - up(host->eh_notify); -#endif - - while (1) { - /* - * If we get a signal, it means we are supposed to go - * away and die. This typically happens if the user is - * trying to unload a module. - */ - SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler sleeping\n")); - -#if 0 - /* - * Note - we always use down_interruptible with the semaphore - * even if the module was loaded as part of the kernel. The - * reason is that down() will cause this thread to be counted - * in the load average as a running process, and down - * interruptible doesn't. Given that we need to allow this - * thread to die if the driver was loaded as a module, using - * semaphores isn't unreasonable. - */ - down_interruptible(&sem); -#endif - if( host->loaded_as_module ) { - if (signal_pending(current)) - break; - } - - SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler waking up\n")); - - host->eh_active = 1; - - /* - * We have a host that is failing for some reason. Figure out - * what we need to do to get it up and online again (if we can). - * If we fail, we end up taking the thing offline. - */ - if (host->hostt->eh_strategy_handler != NULL) { - rtn = host->hostt->eh_strategy_handler(host); - } else { - rtn = scsi_unjam_host(host); - } - - host->eh_active = 0; - - /* - * Note - if the above fails completely, the action is to take - * individual devices offline and flush the queue of any - * outstanding requests that may have been pending. When we - * restart, we restart any I/O to any other devices on the bus - * which are still online. - */ - scsi_restart_operations(host); - - } - - SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler exiting\n")); - - /* - * Make sure that nobody tries to wake us up again. - */ - host->eh_wait = NULL; - - /* - * Knock this down too. From this point on, the host is flying - * without a pilot. If this is because the module is being unloaded, - * that's fine. If the user sent a signal to this thing, we are - * potentially in real danger. - */ - host->in_recovery = 0; - host->eh_active = 0; - host->ehandler = NULL; - -#if 0 - /* - * If anyone is waiting for us to exit (i.e. someone trying to unload - * a driver), then wake up that process to let them know we are on - * the way out the door. This may be overkill - I *think* that we - * could probably just unload the driver and send the signal, and when - * the error handling thread wakes up that it would just exit without - * needing to touch any memory associated with the driver itself. - */ - if (host->eh_notify != NULL) - up(host->eh_notify); -#endif -} - -/* - * Function: scsi_new_reset - * - * Purpose: Send requested reset to a bus or device at any phase. - * - * Arguments: SCpnt - command ptr to send reset with (usually a dummy) - * flag - reset type (see scsi.h) - * - * Returns: SUCCESS/FAILURE. - * - * Notes: This is used by the SCSI Generic driver to provide - * Bus/Device reset capability. - */ -int -scsi_new_reset(Scsi_Cmnd *SCpnt, int flag) -{ - int rtn; - - switch(flag) { - case SCSI_TRY_RESET_DEVICE: - rtn = scsi_try_bus_device_reset(SCpnt, 0); - if (rtn == SUCCESS) - break; - /* FALLTHROUGH */ - case SCSI_TRY_RESET_BUS: - rtn = scsi_try_bus_reset(SCpnt); - if (rtn == SUCCESS) - break; - /* FALLTHROUGH */ - case SCSI_TRY_RESET_HOST: - rtn = scsi_try_host_reset(SCpnt); - break; - default: - rtn = FAILED; - } - - return rtn; -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/xen/drivers/scsi/scsi_ioctl.c b/xen/drivers/scsi/scsi_ioctl.c deleted file mode 100644 index cd8d25ba5b..0000000000 --- a/xen/drivers/scsi/scsi_ioctl.c +++ /dev/null @@ -1,538 +0,0 @@ -/* - * Changes: - * Arnaldo Carvalho de Melo 08/23/2000 - * - get rid of some verify_areas and use __copy*user and __get/put_user - * for the ones that remain - */ -#define __NO_VERSION__ -#include - -#include -#include -#include -#include - -/* #include */ -/* #include */ -/* #include */ -#include -/* #include */ -/* #include */ - -#include -#include "scsi.h" -#include "hosts.h" -#include - -#define NORMAL_RETRIES 5 -#define IOCTL_NORMAL_TIMEOUT (10 * HZ) -#define FORMAT_UNIT_TIMEOUT (2 * 60 * 60 * HZ) -#define START_STOP_TIMEOUT (60 * HZ) -#define MOVE_MEDIUM_TIMEOUT (5 * 60 * HZ) -#define READ_ELEMENT_STATUS_TIMEOUT (5 * 60 * HZ) -#define READ_DEFECT_DATA_TIMEOUT (60 * HZ ) /* ZIP-250 on parallel port takes as long! */ - -#define MAX_BUF PAGE_SIZE - -/* - * If we are told to probe a host, we will return 0 if the host is not - * present, 1 if the host is present, and will return an identifying - * string at *arg, if arg is non null, filling to the length stored at - * (int *) arg - */ - -static int ioctl_probe(struct Scsi_Host *host, void *buffer) -{ - unsigned int len, slen; - const char *string; - int temp = host->hostt->present; - - if (temp && buffer) { - if (get_user(len, (unsigned int *) buffer)) - return -EFAULT; - - if (host->hostt->info) - string = host->hostt->info(host); - else - string = host->hostt->name; - if (string) { - slen = strlen(string); - if (len > slen) - len = slen + 1; - if (copy_to_user(buffer, string, len)) - return -EFAULT; - } - } - return temp; -} - -/* - - * The SCSI_IOCTL_SEND_COMMAND ioctl sends a command out to the SCSI host. - * The IOCTL_NORMAL_TIMEOUT and NORMAL_RETRIES variables are used. - * - * dev is the SCSI device struct ptr, *(int *) arg is the length of the - * input data, if any, not including the command string & counts, - * *((int *)arg + 1) is the output buffer size in bytes. - * - * *(char *) ((int *) arg)[2] the actual command byte. - * - * Note that if more than MAX_BUF bytes are requested to be transferred, - * the ioctl will fail with error EINVAL. MAX_BUF can be increased in - * the future by increasing the size that scsi_malloc will accept. - * - * This size *does not* include the initial lengths that were passed. - * - * The SCSI command is read from the memory location immediately after the - * length words, and the input data is right after the command. The SCSI - * routines know the command size based on the opcode decode. - * - * The output area is then filled in starting from the command byte. - */ - -static int ioctl_internal_command(Scsi_Device * dev, char *cmd, - int timeout, int retries) -{ - int result; - Scsi_Request *SRpnt; - Scsi_Device *SDpnt; - - - SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", cmd[0])); - if (NULL == (SRpnt = scsi_allocate_request(dev))) { - printk("SCSI internal ioctl failed, no memory\n"); - return -ENOMEM; - } - - SRpnt->sr_data_direction = SCSI_DATA_NONE; - scsi_wait_req(SRpnt, cmd, NULL, 0, timeout, retries); - - SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", SRpnt->sr_result)); - - if (driver_byte(SRpnt->sr_result) != 0) - switch (SRpnt->sr_sense_buffer[2] & 0xf) { - case ILLEGAL_REQUEST: - if (cmd[0] == ALLOW_MEDIUM_REMOVAL) - dev->lockable = 0; - else - printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n"); - break; - case NOT_READY: /* This happens if there is no disc in drive */ - if (dev->removable && (cmd[0] != TEST_UNIT_READY)) { - printk(KERN_INFO "Device not ready. Make sure there is a disc in the drive.\n"); - break; - } - case UNIT_ATTENTION: - if (dev->removable) { - dev->changed = 1; - SRpnt->sr_result = 0; /* This is no longer considered an error */ - /* gag this error, VFS will log it anyway /axboe */ - /* printk(KERN_INFO "Disc change detected.\n"); */ - break; - }; - default: /* Fall through for non-removable media */ - printk("SCSI error: host %d id %d lun %d return code = %x\n", - dev->host->host_no, - dev->id, - dev->lun, - SRpnt->sr_result); - printk("\tSense class %x, sense error %x, extended sense %x\n", - sense_class(SRpnt->sr_sense_buffer[0]), - sense_error(SRpnt->sr_sense_buffer[0]), - SRpnt->sr_sense_buffer[2] & 0xf); - - }; - - result = SRpnt->sr_result; - - SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n")); - SDpnt = SRpnt->sr_device; - scsi_release_request(SRpnt); - SRpnt = NULL; - - return result; -} - -/* - * This interface is depreciated - users should use the scsi generic (sg) - * interface instead, as this is a more flexible approach to performing - * generic SCSI commands on a device. - * - * The structure that we are passed should look like: - * - * struct sdata { - * unsigned int inlen; [i] Length of data to be written to device - * unsigned int outlen; [i] Length of data to be read from device - * unsigned char cmd[x]; [i] SCSI command (6 <= x <= 12). - * [o] Data read from device starts here. - * [o] On error, sense buffer starts here. - * unsigned char wdata[y]; [i] Data written to device starts here. - * }; - * Notes: - * - The SCSI command length is determined by examining the 1st byte - * of the given command. There is no way to override this. - * - Data transfers are limited to PAGE_SIZE (4K on i386, 8K on alpha). - * - The length (x + y) must be at least OMAX_SB_LEN bytes long to - * accomodate the sense buffer when an error occurs. - * The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that - * old code will not be surprised. - * - If a Unix error occurs (e.g. ENOMEM) then the user will receive - * a negative return and the Unix error code in 'errno'. - * If the SCSI command succeeds then 0 is returned. - * Positive numbers returned are the compacted SCSI error codes (4 - * bytes in one int) where the lowest byte is the SCSI status. - * See the drivers/scsi/scsi.h file for more information on this. - * - */ -#define OMAX_SB_LEN 16 /* Old sense buffer length */ - -int scsi_ioctl_send_command(Scsi_Device * dev, Scsi_Ioctl_Command * sic) -{ - char *buf; - unsigned char cmd[MAX_COMMAND_SIZE]; - char *cmd_in; - Scsi_Request *SRpnt; - Scsi_Device *SDpnt; - unsigned char opcode; - unsigned int inlen, outlen, cmdlen; - unsigned int needed, buf_needed; - int timeout, retries, result; - int data_direction; - - if (!sic) - return -EINVAL; - /* - * Verify that we can read at least this much. - */ - if (verify_area(VERIFY_READ, sic, sizeof(Scsi_Ioctl_Command))) - return -EFAULT; - - if(__get_user(inlen, &sic->inlen)) - return -EFAULT; - - if(__get_user(outlen, &sic->outlen)) - return -EFAULT; - - /* - * We do not transfer more than MAX_BUF with this interface. - * If the user needs to transfer more data than this, they - * should use scsi_generics (sg) instead. - */ - if (inlen > MAX_BUF) - return -EINVAL; - if (outlen > MAX_BUF) - return -EINVAL; - - cmd_in = sic->data; - if(get_user(opcode, cmd_in)) - return -EFAULT; - - needed = buf_needed = (inlen > outlen ? inlen : outlen); - if (buf_needed) { - buf_needed = (buf_needed + 511) & ~511; - if (buf_needed > MAX_BUF) - buf_needed = MAX_BUF; - buf = (char *) scsi_malloc(buf_needed); - if (!buf) - return -ENOMEM; - memset(buf, 0, buf_needed); - if( inlen == 0 ) { - data_direction = SCSI_DATA_READ; - } else if (outlen == 0 ) { - data_direction = SCSI_DATA_WRITE; - } else { - /* - * Can this ever happen? - */ - data_direction = SCSI_DATA_UNKNOWN; - } - - } else { - buf = NULL; - data_direction = SCSI_DATA_NONE; - } - - /* - * Obtain the command from the user's address space. - */ - cmdlen = COMMAND_SIZE(opcode); - - result = -EFAULT; - - if (verify_area(VERIFY_READ, cmd_in, cmdlen + inlen)) - goto error; - - if(__copy_from_user(cmd, cmd_in, cmdlen)) - goto error; - - /* - * Obtain the data to be sent to the device (if any). - */ - - if(copy_from_user(buf, cmd_in + cmdlen, inlen)) - goto error; - - /* - * Set the lun field to the correct value. - */ - if (dev->scsi_level <= SCSI_2) - cmd[1] = (cmd[1] & 0x1f) | (dev->lun << 5); - - switch (opcode) { - case FORMAT_UNIT: - timeout = FORMAT_UNIT_TIMEOUT; - retries = 1; - break; - case START_STOP: - timeout = START_STOP_TIMEOUT; - retries = NORMAL_RETRIES; - break; - case MOVE_MEDIUM: - timeout = MOVE_MEDIUM_TIMEOUT; - retries = NORMAL_RETRIES; - break; - case READ_ELEMENT_STATUS: - timeout = READ_ELEMENT_STATUS_TIMEOUT; - retries = NORMAL_RETRIES; - break; - case READ_DEFECT_DATA: - timeout = READ_DEFECT_DATA_TIMEOUT; - retries = 1; - break; - default: - timeout = IOCTL_NORMAL_TIMEOUT; - retries = NORMAL_RETRIES; - break; - } - -#ifndef DEBUG_NO_CMD - - - SRpnt = scsi_allocate_request(dev); - if( SRpnt == NULL ) - { - result = -EINTR; - goto error; - } - - SRpnt->sr_data_direction = data_direction; - scsi_wait_req(SRpnt, cmd, buf, needed, timeout, retries); - - /* - * If there was an error condition, pass the info back to the user. - */ - - result = SRpnt->sr_result; - - if (SRpnt->sr_result) { - int sb_len = sizeof(SRpnt->sr_sense_buffer); - - sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len; - if (copy_to_user(cmd_in, SRpnt->sr_sense_buffer, sb_len)) - result = -EFAULT; - } else { - if (copy_to_user(cmd_in, buf, outlen)) - result = -EFAULT; - } - - SDpnt = SRpnt->sr_device; - scsi_release_request(SRpnt); - SRpnt = NULL; - -error: - if (buf) - scsi_free(buf, buf_needed); - - - return result; -#else - { - int i; - printk("scsi_ioctl : device %d. command = ", dev->id); - for (i = 0; i < cmdlen; ++i) - printk("%02x ", cmd[i]); - printk("\nbuffer ="); - for (i = 0; i < 20; ++i) - printk("%02x ", buf[i]); - printk("\n"); - printk("inlen = %d, outlen = %d, cmdlen = %d\n", - inlen, outlen, cmdlen); - printk("buffer = %d, cmd_in = %d\n", buffer, cmd_in); - } - return 0; -#endif -} - -/* - * The scsi_ioctl_get_pci() function places into arg the value - * pci_dev::slot_name (8 characters) for the PCI device (if any). - * Returns: 0 on success - * -ENXIO if there isn't a PCI device pointer - * (could be because the SCSI driver hasn't been - * updated yet, or because it isn't a SCSI - * device) - * any copy_to_user() error on failure there - */ -static int -scsi_ioctl_get_pci(Scsi_Device * dev, void *arg) -{ - - if (!dev->host->pci_dev) - return -ENXIO; - if(copy_to_user(arg, dev->host->pci_dev->slot_name, - sizeof(dev->host->pci_dev->slot_name))) - return -EFAULT; - return 0; -} - - -/* - * the scsi_ioctl() function differs from most ioctls in that it does - * not take a major/minor number as the dev field. Rather, it takes - * a pointer to a scsi_devices[] element, a structure. - */ -int scsi_ioctl(Scsi_Device * dev, int cmd, void *arg) -{ - char scsi_cmd[MAX_COMMAND_SIZE]; - char cmd_byte1; - - /* No idea how this happens.... */ - if (!dev) - return -ENXIO; - - /* - * If we are in the middle of error recovery, don't let anyone - * else try and use this device. Also, if error recovery fails, it - * may try and take the device offline, in which case all further - * access to the device is prohibited. - */ - if (!scsi_block_when_processing_errors(dev)) { - return -ENODEV; - } - cmd_byte1 = (dev->scsi_level <= SCSI_2) ? (dev->lun << 5) : 0; - - switch (cmd) { - case SCSI_IOCTL_GET_IDLUN: - if (verify_area(VERIFY_WRITE, arg, sizeof(Scsi_Idlun))) - return -EFAULT; - - __put_user((dev->id & 0xff) - + ((dev->lun & 0xff) << 8) - + ((dev->channel & 0xff) << 16) - + ((dev->host->host_no & 0xff) << 24), - &((Scsi_Idlun *) arg)->dev_id); - __put_user(dev->host->unique_id, &((Scsi_Idlun *) arg)->host_unique_id); - return 0; - case SCSI_IOCTL_GET_BUS_NUMBER: - return put_user(dev->host->host_no, (int *) arg); - case SCSI_IOCTL_TAGGED_ENABLE: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (!dev->tagged_supported) - return -EINVAL; - dev->tagged_queue = 1; - dev->current_tag = 1; - return 0; - case SCSI_IOCTL_TAGGED_DISABLE: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (!dev->tagged_supported) - return -EINVAL; - dev->tagged_queue = 0; - dev->current_tag = 0; - return 0; - case SCSI_IOCTL_PROBE_HOST: - return ioctl_probe(dev->host, arg); - case SCSI_IOCTL_SEND_COMMAND: - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) - return -EACCES; - return scsi_ioctl_send_command((Scsi_Device *) dev, - (Scsi_Ioctl_Command *) arg); - case SCSI_IOCTL_DOORLOCK: - if (!dev->removable || !dev->lockable) - return 0; - scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL; - scsi_cmd[1] = cmd_byte1; - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; - scsi_cmd[4] = SCSI_REMOVAL_PREVENT; - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, - IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES); - break; - case SCSI_IOCTL_DOORUNLOCK: - if (!dev->removable || !dev->lockable) - return 0; - scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL; - scsi_cmd[1] = cmd_byte1; - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; - scsi_cmd[4] = SCSI_REMOVAL_ALLOW; - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, - IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES); - case SCSI_IOCTL_TEST_UNIT_READY: - scsi_cmd[0] = TEST_UNIT_READY; - scsi_cmd[1] = cmd_byte1; - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; - scsi_cmd[4] = 0; - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, - IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES); - break; - case SCSI_IOCTL_START_UNIT: - scsi_cmd[0] = START_STOP; - scsi_cmd[1] = cmd_byte1; - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; - scsi_cmd[4] = 1; - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, - START_STOP_TIMEOUT, NORMAL_RETRIES); - break; - case SCSI_IOCTL_STOP_UNIT: - scsi_cmd[0] = START_STOP; - scsi_cmd[1] = cmd_byte1; - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; - scsi_cmd[4] = 0; - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, - START_STOP_TIMEOUT, NORMAL_RETRIES); - break; - case SCSI_IOCTL_GET_PCI: - return scsi_ioctl_get_pci(dev, arg); - break; - default: - if (dev->host->hostt->ioctl) - return dev->host->hostt->ioctl(dev, cmd, arg); - return -EINVAL; - } - return -EINVAL; -} - -/* - * Just like scsi_ioctl, only callable from kernel space with no - * fs segment fiddling. - */ - -int kernel_scsi_ioctl(Scsi_Device * dev, int cmd, void *arg) -{ - mm_segment_t oldfs; - int tmp; - oldfs = get_fs(); - set_fs(get_ds()); - tmp = scsi_ioctl(dev, cmd, arg); - set_fs(oldfs); - return tmp; -} - -/* - * Overrides for Emacs so that we almost follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/xen/drivers/scsi/scsi_lib.c b/xen/drivers/scsi/scsi_lib.c deleted file mode 100644 index 748d5da730..0000000000 --- a/xen/drivers/scsi/scsi_lib.c +++ /dev/null @@ -1,1210 +0,0 @@ -/* - * scsi_lib.c Copyright (C) 1999 Eric Youngdale - * - * SCSI queueing library. - * Initial versions: Eric Youngdale (eric@andante.org). - * Based upon conversations with large numbers - * of people at Linux Expo. - */ - -/* - * The fundamental purpose of this file is to contain a library of utility - * routines that can be used by low-level drivers. Ultimately the idea - * is that there should be a sufficiently rich number of functions that it - * would be possible for a driver author to fashion a queueing function for - * a low-level driver if they wished. Note however that this file also - * contains the "default" versions of these functions, as we don't want to - * go through and retrofit queueing functions into all 30 some-odd drivers. - */ - -#define __NO_VERSION__ -#include - -#include -#include -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -#include -/* #include */ -/* #include */ -/* #include */ -/* #include */ - - -#define __KERNEL_SYSCALLS__ - -/* #include */ - -#include -#include -#include - -#include "scsi.h" -#include "hosts.h" -#include "constants.h" -#include - -#define SPECIAL XEN_BLOCK_SPECIAL - -/* - * This entire source file deals with the new queueing code. - */ - -/* - * Function: __scsi_insert_special() - * - * Purpose: worker for scsi_insert_special_*() - * - * Arguments: q - request queue where request should be inserted - * rq - request to be inserted - * data - private data - * at_head - insert request at head or tail of queue - * - * Lock status: Assumed that io_request_lock is not held upon entry. - * - * Returns: Nothing - */ -static void __scsi_insert_special(request_queue_t *q, struct request *rq, - void *data, int at_head) -{ - unsigned long flags; - - ASSERT_LOCK(&io_request_lock, 0); - - rq->cmd = SPECIAL; - rq->special = data; - rq->q = NULL; - rq->nr_segments = 0; - rq->elevator_sequence = 0; - - /* - * We have the option of inserting the head or the tail of the queue. - * Typically we use the tail for new ioctls and so forth. We use the - * head of the queue for things like a QUEUE_FULL message from a - * device, or a host that is unable to accept a particular command. - */ - spin_lock_irqsave(&io_request_lock, flags); - - if (at_head) - list_add(&rq->queue, &q->queue_head); - else - list_add_tail(&rq->queue, &q->queue_head); - - q->request_fn(q); - spin_unlock_irqrestore(&io_request_lock, flags); -} - - -/* - * Function: scsi_insert_special_cmd() - * - * Purpose: Insert pre-formed command into request queue. - * - * Arguments: SCpnt - command that is ready to be queued. - * at_head - boolean. True if we should insert at head - * of queue, false if we should insert at tail. - * - * Lock status: Assumed that lock is not held upon entry. - * - * Returns: Nothing - * - * Notes: This function is called from character device and from - * ioctl types of functions where the caller knows exactly - * what SCSI command needs to be issued. The idea is that - * we merely inject the command into the queue (at the head - * for now), and then call the queue request function to actually - * process it. - */ -int scsi_insert_special_cmd(Scsi_Cmnd * SCpnt, int at_head) -{ - request_queue_t *q = &SCpnt->device->request_queue; - - __scsi_insert_special(q, &SCpnt->request, SCpnt, at_head); - return 0; -} - -/* - * Function: scsi_insert_special_req() - * - * Purpose: Insert pre-formed request into request queue. - * - * Arguments: SRpnt - request that is ready to be queued. - * at_head - boolean. True if we should insert at head - * of queue, false if we should insert at tail. - * - * Lock status: Assumed that lock is not held upon entry. - * - * Returns: Nothing - * - * Notes: This function is called from character device and from - * ioctl types of functions where the caller knows exactly - * what SCSI command needs to be issued. The idea is that - * we merely inject the command into the queue (at the head - * for now), and then call the queue request function to actually - * process it. - */ -int scsi_insert_special_req(Scsi_Request * SRpnt, int at_head) -{ - request_queue_t *q = &SRpnt->sr_device->request_queue; - - __scsi_insert_special(q, &SRpnt->sr_request, SRpnt, at_head); - return 0; -} - -/* - * Function: scsi_init_cmd_errh() - * - * Purpose: Initialize SCpnt fields related to error handling. - * - * Arguments: SCpnt - command that is ready to be queued. - * - * Returns: Nothing - * - * Notes: This function has the job of initializing a number of - * fields related to error handling. Typically this will - * be called once for each command, as required. - */ -int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt) -{ - ASSERT_LOCK(&io_request_lock, 0); - - SCpnt->owner = SCSI_OWNER_MIDLEVEL; - SCpnt->reset_chain = NULL; - SCpnt->serial_number = 0; - SCpnt->serial_number_at_timeout = 0; - SCpnt->flags = 0; - SCpnt->retries = 0; - - SCpnt->abort_reason = 0; - - memset((void *) SCpnt->sense_buffer, 0, sizeof SCpnt->sense_buffer); - - if (SCpnt->cmd_len == 0) - SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]); - - /* - * We need saved copies of a number of fields - this is because - * error handling may need to overwrite these with different values - * to run different commands, and once error handling is complete, - * we will need to restore these values prior to running the actual - * command. - */ - SCpnt->old_use_sg = SCpnt->use_sg; - SCpnt->old_cmd_len = SCpnt->cmd_len; - SCpnt->sc_old_data_direction = SCpnt->sc_data_direction; - SCpnt->old_underflow = SCpnt->underflow; - memcpy((void *) SCpnt->data_cmnd, - (const void *) SCpnt->cmnd, sizeof(SCpnt->cmnd)); - SCpnt->buffer = SCpnt->request_buffer; - SCpnt->bufflen = SCpnt->request_bufflen; - - SCpnt->reset_chain = NULL; - - SCpnt->internal_timeout = NORMAL_TIMEOUT; - SCpnt->abort_reason = 0; - - return 1; -} - -/* - * Function: scsi_queue_next_request() - * - * Purpose: Handle post-processing of completed commands. - * - * Arguments: SCpnt - command that may need to be requeued. - * - * Returns: Nothing - * - * Notes: After command completion, there may be blocks left - * over which weren't finished by the previous command - * this can be for a number of reasons - the main one is - * that a medium error occurred, and the sectors after - * the bad block need to be re-read. - * - * If SCpnt is NULL, it means that the previous command - * was completely finished, and we should simply start - * a new command, if possible. - * - * This is where a lot of special case code has begun to - * accumulate. It doesn't really affect readability or - * anything, but it might be considered architecturally - * inelegant. If more of these special cases start to - * accumulate, I am thinking along the lines of implementing - * an atexit() like technology that gets run when commands - * complete. I am not convinced that it is worth the - * added overhead, however. Right now as things stand, - * there are simple conditional checks, and most hosts - * would skip past. - * - * Another possible solution would be to tailor different - * handler functions, sort of like what we did in scsi_merge.c. - * This is probably a better solution, but the number of different - * permutations grows as 2**N, and if too many more special cases - * get added, we start to get screwed. - */ -void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt) -{ - int all_clear; - unsigned long flags; - Scsi_Device *SDpnt; - struct Scsi_Host *SHpnt; - - ASSERT_LOCK(&io_request_lock, 0); - - spin_lock_irqsave(&io_request_lock, flags); - if (SCpnt != NULL) { - - /* - * For some reason, we are not done with this request. - * This happens for I/O errors in the middle of the request, - * in which case we need to request the blocks that come after - * the bad sector. - */ - SCpnt->request.special = (void *) SCpnt; - list_add(&SCpnt->request.queue, &q->queue_head); - } - - /* - * Just hit the requeue function for the queue. - */ - q->request_fn(q); - - SDpnt = (Scsi_Device *) q->queuedata; - SHpnt = SDpnt->host; - - /* - * If this is a single-lun device, and we are currently finished - * with this device, then see if we need to get another device - * started. FIXME(eric) - if this function gets too cluttered - * with special case code, then spin off separate versions and - * use function pointers to pick the right one. - */ - if (SDpnt->single_lun - && list_empty(&q->queue_head) - && SDpnt->device_busy == 0) { - request_queue_t *q; - - for (SDpnt = SHpnt->host_queue; - SDpnt; - SDpnt = SDpnt->next) { - if (((SHpnt->can_queue > 0) - && (SHpnt->host_busy >= SHpnt->can_queue)) - || (SHpnt->host_blocked) - || (SHpnt->host_self_blocked) - || (SDpnt->device_blocked)) { - break; - } - q = &SDpnt->request_queue; - q->request_fn(q); - } - } - - /* - * Now see whether there are other devices on the bus which - * might be starved. If so, hit the request function. If we - * don't find any, then it is safe to reset the flag. If we - * find any device that it is starved, it isn't safe to reset the - * flag as the queue function releases the lock and thus some - * other device might have become starved along the way. - */ - all_clear = 1; - if (SHpnt->some_device_starved) { - for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) { - request_queue_t *q; - if ((SHpnt->can_queue > 0 &&(SHpnt->host_busy >= SHpnt->can_queue)) - || (SHpnt->host_blocked) - || (SHpnt->host_self_blocked)) { - break; - } - if (SDpnt->device_blocked || !SDpnt->starved) { - continue; - } - q = &SDpnt->request_queue; - q->request_fn(q); - all_clear = 0; - } - if (SDpnt == NULL && all_clear) { - SHpnt->some_device_starved = 0; - } - } - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * Function: scsi_end_request() - * - * Purpose: Post-processing of completed commands called from interrupt - * handler or a bottom-half handler. - * - * Arguments: SCpnt - command that is complete. - * uptodate - 1 if I/O indicates success, 0 for I/O error. - * sectors - number of sectors we want to mark. - * requeue - indicates whether we should requeue leftovers. - * frequeue - indicates that if we release the command block - * that the queue request function should be called. - * - * Lock status: Assumed that lock is not held upon entry. - * - * Returns: Nothing - * - * Notes: This is called for block device requests in order to - * mark some number of sectors as complete. - * - * We are guaranteeing that the request queue will be goosed - * at some point during this call. - */ -static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt, - int uptodate, - int sectors, - int requeue, - int frequeue) -{ - struct request *req; - struct buffer_head *bh; - Scsi_Device * SDpnt; - int nsect; - - ASSERT_LOCK(&io_request_lock, 0); - - req = &SCpnt->request; - req->errors = 0; - if (!uptodate) { - printk(" I/O error: dev %s, sector %lu\n", - kdevname(req->rq_dev), req->sector); - } - do { - if ((bh = req->bh) != NULL) { - nsect = bh->b_size >> 9; - blk_finished_io(nsect); - req->bh = bh->b_reqnext; - bh->b_reqnext = NULL; - sectors -= nsect; - bh->b_end_io(bh, uptodate); - if ((bh = req->bh) != NULL) { - req->hard_sector += nsect; - req->hard_nr_sectors -= nsect; - req->sector += nsect; - req->nr_sectors -= nsect; - - req->current_nr_sectors = bh->b_size >> 9; - if (req->nr_sectors < req->current_nr_sectors) { - req->nr_sectors = req->current_nr_sectors; - printk("scsi_end_request: buffer-list destroyed\n"); - } - } - } - } while (sectors && bh); - - /* - * If there are blocks left over at the end, set up the command - * to queue the remainder of them. - */ - if (req->bh) { - request_queue_t *q; - - if( !requeue ) - { - return SCpnt; - } - - q = &SCpnt->device->request_queue; - - req->buffer = bh->b_data; - /* - * Bleah. Leftovers again. Stick the leftovers in - * the front of the queue, and goose the queue again. - */ - scsi_queue_next_request(q, SCpnt); - return SCpnt; - } -#if 0 - /* - * This request is done. If there is someone blocked waiting for this - * request, wake them up. Typically used to wake up processes trying - * to swap a page into memory. - */ - if (req->waiting != NULL) { - complete(req->waiting); - } -#else - /* XXX SMH: we're done -- flip the flag for the spinner :-| */ - if(req->waiting && (*(int *)(req->waiting) != 0)) { - printk("__scsi_end_request: flipping wait status on req %p\n", req); - *(int *)(req->waiting) = 0; - } // else printk("__scsi_end_request: no-one to notify!!\n"); -#endif - req_finished_io(req); - add_blkdev_randomness(MAJOR(req->rq_dev)); - - SDpnt = SCpnt->device; - - /* - * This will goose the queue request function at the end, so we don't - * need to worry about launching another command. - */ - __scsi_release_command(SCpnt); - - if( frequeue ) { - request_queue_t *q; - - q = &SDpnt->request_queue; - scsi_queue_next_request(q, NULL); - } - return NULL; -} - -/* - * Function: scsi_end_request() - * - * Purpose: Post-processing of completed commands called from interrupt - * handler or a bottom-half handler. - * - * Arguments: SCpnt - command that is complete. - * uptodate - 1 if I/O indicates success, 0 for I/O error. - * sectors - number of sectors we want to mark. - * - * Lock status: Assumed that lock is not held upon entry. - * - * Returns: Nothing - * - * Notes: This is called for block device requests in order to - * mark some number of sectors as complete. - * - * We are guaranteeing that the request queue will be goosed - * at some point during this call. - */ -Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors) -{ - return __scsi_end_request(SCpnt, uptodate, sectors, 1, 1); -} - -/* - * Function: scsi_release_buffers() - * - * Purpose: Completion processing for block device I/O requests. - * - * Arguments: SCpnt - command that we are bailing. - * - * Lock status: Assumed that no lock is held upon entry. - * - * Returns: Nothing - * - * Notes: In the event that an upper level driver rejects a - * command, we must release resources allocated during - * the __init_io() function. Primarily this would involve - * the scatter-gather table, and potentially any bounce - * buffers. - */ -static void scsi_release_buffers(Scsi_Cmnd * SCpnt) -{ - ASSERT_LOCK(&io_request_lock, 0); - - /* - * Free up any indirection buffers we allocated for DMA purposes. - */ - if (SCpnt->use_sg) { - struct scatterlist *sgpnt; - void **bbpnt; - int i; - - sgpnt = (struct scatterlist *) SCpnt->request_buffer; - bbpnt = SCpnt->bounce_buffers; - - if (bbpnt) { - for (i = 0; i < SCpnt->use_sg; i++) { - if (bbpnt[i]) - scsi_free(sgpnt[i].address, sgpnt[i].length); - } - } - scsi_free(SCpnt->request_buffer, SCpnt->sglist_len); - } else { - if (SCpnt->request_buffer != SCpnt->request.buffer) { - scsi_free(SCpnt->request_buffer, SCpnt->request_bufflen); - } - } - - /* - * Zero these out. They now point to freed memory, and it is - * dangerous to hang onto the pointers. - */ - SCpnt->buffer = NULL; - SCpnt->bufflen = 0; - SCpnt->request_buffer = NULL; - SCpnt->request_bufflen = 0; -} - -/* - * Function: scsi_io_completion() - * - * Purpose: Completion processing for block device I/O requests. - * - * Arguments: SCpnt - command that is finished. - * - * Lock status: Assumed that no lock is held upon entry. - * - * Returns: Nothing - * - * Notes: This function is matched in terms of capabilities to - * the function that created the scatter-gather list. - * In other words, if there are no bounce buffers - * (the normal case for most drivers), we don't need - * the logic to deal with cleaning up afterwards. - */ -void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors, - int block_sectors) -{ - int result = SCpnt->result; - int this_count = SCpnt->bufflen >> 9; - request_queue_t *q = &SCpnt->device->request_queue; - - // printk("scsi_io_completion entered.\n"); - /* - * We must do one of several things here: - * - * Call scsi_end_request. This will finish off the specified - * number of sectors. If we are done, the command block will - * be released, and the queue function will be goosed. If we - * are not done, then scsi_end_request will directly goose - * the queue. - * - * We can just use scsi_queue_next_request() here. This - * would be used if we just wanted to retry, for example. - * - */ - ASSERT_LOCK(&io_request_lock, 0); - - /* - * Free up any indirection buffers we allocated for DMA purposes. - * For the case of a READ, we need to copy the data out of the - * bounce buffer and into the real buffer. - */ - if (SCpnt->use_sg) { - struct scatterlist *sgpnt; - void **bbpnt; - int i; - - sgpnt = (struct scatterlist *) SCpnt->buffer; - bbpnt = SCpnt->bounce_buffers; - - if (bbpnt) { - for (i = 0; i < SCpnt->use_sg; i++) { - if (bbpnt[i]) { - if (SCpnt->request.cmd == READ) { - memcpy(bbpnt[i], - sgpnt[i].address, - sgpnt[i].length); - } - scsi_free(sgpnt[i].address, sgpnt[i].length); - } - } - } - scsi_free(SCpnt->buffer, SCpnt->sglist_len); - } else { - if (SCpnt->buffer != SCpnt->request.buffer) { - if (SCpnt->request.cmd == READ) { - memcpy(SCpnt->request.buffer, SCpnt->buffer, - SCpnt->bufflen); - } - scsi_free(SCpnt->buffer, SCpnt->bufflen); - } - } - - /* - * Zero these out. They now point to freed memory, and it is - * dangerous to hang onto the pointers. - */ - SCpnt->buffer = NULL; - SCpnt->bufflen = 0; - SCpnt->request_buffer = NULL; - SCpnt->request_bufflen = 0; - - /* - * Next deal with any sectors which we were able to correctly - * handle. - */ - if (good_sectors > 0) { - SCSI_LOG_HLCOMPLETE(1, printk("%ld sectors total, %d sectors done.\n", - SCpnt->request.nr_sectors, - good_sectors)); - SCSI_LOG_HLCOMPLETE(1, printk("use_sg is %d\n ", SCpnt->use_sg)); - - SCpnt->request.errors = 0; - /* - * If multiple sectors are requested in one buffer, then - * they will have been finished off by the first command. - * If not, then we have a multi-buffer command. - * - * If block_sectors != 0, it means we had a medium error - * of some sort, and that we want to mark some number of - * sectors as not uptodate. Thus we want to inhibit - * requeueing right here - we will requeue down below - * when we handle the bad sectors. - */ - SCpnt = __scsi_end_request(SCpnt, - 1, - good_sectors, - result == 0, - 1); - - /* - * If the command completed without error, then either finish off the - * rest of the command, or start a new one. - */ - if (result == 0 || SCpnt == NULL ) { - return; - } - } - /* - * Now, if we were good little boys and girls, Santa left us a request - * sense buffer. We can extract information from this, so we - * can choose a block to remap, etc. - */ - if (driver_byte(result) != 0) { - if (suggestion(result) == SUGGEST_REMAP) { -#ifdef REMAP - /* - * Not yet implemented. A read will fail after being remapped, - * a write will call the strategy routine again. - */ - if (SCpnt->device->remap) { - result = 0; - } -#endif - } - if ((SCpnt->sense_buffer[0] & 0x7f) == 0x70) { - /* - * If the device is in the process of becoming ready, - * retry. - */ - if (SCpnt->sense_buffer[12] == 0x04 && - SCpnt->sense_buffer[13] == 0x01) { - scsi_queue_next_request(q, SCpnt); - return; - } - if ((SCpnt->sense_buffer[2] & 0xf) == UNIT_ATTENTION) { - if (SCpnt->device->removable) { - /* detected disc change. set a bit - * and quietly refuse further access. - */ - SCpnt->device->changed = 1; - SCpnt = scsi_end_request(SCpnt, 0, this_count); - return; - } else { - /* - * Must have been a power glitch, or a - * bus reset. Could not have been a - * media change, so we just retry the - * request and see what happens. - */ - scsi_queue_next_request(q, SCpnt); - return; - } - } - } - /* If we had an ILLEGAL REQUEST returned, then we may have - * performed an unsupported command. The only thing this should be - * would be a ten byte read where only a six byte read was supported. - * Also, on a system where READ CAPACITY failed, we have have read - * past the end of the disk. - */ - - switch (SCpnt->sense_buffer[2]) { - case ILLEGAL_REQUEST: - if (SCpnt->device->ten) { - SCpnt->device->ten = 0; - /* - * This will cause a retry with a 6-byte - * command. - */ - scsi_queue_next_request(q, SCpnt); - result = 0; - } else { - SCpnt = scsi_end_request(SCpnt, 0, this_count); - return; - } - break; - case NOT_READY: - printk(KERN_INFO "Device %s not ready.\n", - kdevname(SCpnt->request.rq_dev)); - SCpnt = scsi_end_request(SCpnt, 0, this_count); - return; - break; - case MEDIUM_ERROR: - case VOLUME_OVERFLOW: - printk("scsi%d: ERROR on channel %d, id %d, lun %d, CDB: ", - SCpnt->host->host_no, (int) SCpnt->channel, - (int) SCpnt->target, (int) SCpnt->lun); - print_command(SCpnt->cmnd); - print_sense("sd", SCpnt); - SCpnt = scsi_end_request(SCpnt, 0, block_sectors); - return; - default: - break; - } - } /* driver byte != 0 */ - if (host_byte(result) == DID_RESET) { - /* - * Third party bus reset or reset for error - * recovery reasons. Just retry the request - * and see what happens. - */ - scsi_queue_next_request(q, SCpnt); - return; - } - if (result) { - struct Scsi_Device_Template *STpnt; - - STpnt = scsi_get_request_dev(&SCpnt->request); - printk("SCSI %s error : host %d channel %d id %d lun %d return code = %x\n", - (STpnt ? STpnt->name : "device"), - SCpnt->device->host->host_no, - SCpnt->device->channel, - SCpnt->device->id, - SCpnt->device->lun, result); - - if (driver_byte(result) & DRIVER_SENSE) - print_sense("sd", SCpnt); - /* - * Mark a single buffer as not uptodate. Queue the remainder. - * We sometimes get this cruft in the event that a medium error - * isn't properly reported. - */ - SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.current_nr_sectors); - return; - } -} - -/* - * Function: scsi_get_request_dev() - * - * Purpose: Find the upper-level driver that is responsible for this - * request - * - * Arguments: request - I/O request we are preparing to queue. - * - * Lock status: No locks assumed to be held, but as it happens the - * io_request_lock is held when this is called. - * - * Returns: Nothing - * - * Notes: The requests in the request queue may have originated - * from any block device driver. We need to find out which - * one so that we can later form the appropriate command. - */ -struct Scsi_Device_Template *scsi_get_request_dev(struct request *req) -{ - struct Scsi_Device_Template *spnt; - kdev_t dev = req->rq_dev; - int major = MAJOR(dev); - - ASSERT_LOCK(&io_request_lock, 1); - - for (spnt = scsi_devicelist; spnt; spnt = spnt->next) { - /* - * Search for a block device driver that supports this - * major. - */ - if (spnt->blk && spnt->major == major) { - return spnt; - } - /* - * I am still not entirely satisfied with this solution, - * but it is good enough for now. Disks have a number of - * major numbers associated with them, the primary - * 8, which we test above, and a secondary range of 7 - * different consecutive major numbers. If this ever - * becomes insufficient, then we could add another function - * to the structure, and generalize this completely. - */ - if( spnt->min_major != 0 - && spnt->max_major != 0 - && major >= spnt->min_major - && major <= spnt->max_major ) - { - return spnt; - } - } - return NULL; -} - -/* - * Function: scsi_request_fn() - * - * Purpose: Generic version of request function for SCSI hosts. - * - * Arguments: q - Pointer to actual queue. - * - * Returns: Nothing - * - * Lock status: IO request lock assumed to be held when called. - * - * Notes: The theory is that this function is something which individual - * drivers could also supply if they wished to. The problem - * is that we have 30 some odd low-level drivers in the kernel - * tree already, and it would be most difficult to retrofit - * this crap into all of them. Thus this function has the job - * of acting as a generic queue manager for all of those existing - * drivers. - */ -void scsi_request_fn(request_queue_t * q) -{ - struct request *req; - Scsi_Cmnd *SCpnt; - Scsi_Request *SRpnt; - Scsi_Device *SDpnt; - struct Scsi_Host *SHpnt; - struct Scsi_Device_Template *STpnt; - - ASSERT_LOCK(&io_request_lock, 1); - - SDpnt = (Scsi_Device *) q->queuedata; - if (!SDpnt) { - panic("Missing device"); - } - SHpnt = SDpnt->host; - - /* - * To start with, we keep looping until the queue is empty, or until - * the host is no longer able to accept any more requests. - */ - while (1 == 1) { - /* - * Check this again - each time we loop through we will have - * released the lock and grabbed it again, so each time - * we need to check to see if the queue is plugged or not. - */ - if (SHpnt->in_recovery || q->plugged) - return; - - /* - * If the device cannot accept another request, then quit. - */ - if (SDpnt->device_blocked) { - break; - } - if ((SHpnt->can_queue > 0 && (SHpnt->host_busy >= SHpnt->can_queue)) - || (SHpnt->host_blocked) - || (SHpnt->host_self_blocked)) { - /* - * If we are unable to process any commands at all for - * this device, then we consider it to be starved. - * What this means is that there are no outstanding - * commands for this device and hence we need a - * little help getting it started again - * once the host isn't quite so busy. - */ - if (SDpnt->device_busy == 0) { - SDpnt->starved = 1; - SHpnt->some_device_starved = 1; - } - break; - } else { - SDpnt->starved = 0; - } - - /* - * FIXME(eric) - * I am not sure where the best place to do this is. We need - * to hook in a place where we are likely to come if in user - * space. Technically the error handling thread should be - * doing this crap, but the error handler isn't used by - * most hosts. - */ - if (SDpnt->was_reset) { - /* - * We need to relock the door, but we might - * be in an interrupt handler. Only do this - * from user space, since we do not want to - * sleep from an interrupt. - * - * FIXME(eric) - have the error handler thread do - * this work. - */ - SDpnt->was_reset = 0; - if (SDpnt->removable && !in_interrupt()) { - spin_unlock_irq(&io_request_lock); - scsi_ioctl(SDpnt, SCSI_IOCTL_DOORLOCK, 0); - spin_lock_irq(&io_request_lock); - continue; - } - } - - /* - * If we couldn't find a request that could be queued, then we - * can also quit. - */ - if (list_empty(&q->queue_head)) - break; - - /* - * Loop through all of the requests in this queue, and find - * one that is queueable. - */ - req = blkdev_entry_next_request(&q->queue_head); - - /* - * Find the actual device driver associated with this command. - * The SPECIAL requests are things like character device or - * ioctls, which did not originate from ll_rw_blk. Note that - * the special field is also used to indicate the SCpnt for - * the remainder of a partially fulfilled request that can - * come up when there is a medium error. We have to treat - * these two cases differently. We differentiate by looking - * at request.cmd, as this tells us the real story. - */ - if (req->cmd == SPECIAL) { - STpnt = NULL; - SCpnt = (Scsi_Cmnd *) req->special; - SRpnt = (Scsi_Request *) req->special; - - if( SRpnt->sr_magic == SCSI_REQ_MAGIC ) { - SCpnt = scsi_allocate_device(SRpnt->sr_device, - FALSE, FALSE); - if( !SCpnt ) { - break; - } - scsi_init_cmd_from_req(SCpnt, SRpnt); - } - - } else { - SRpnt = NULL; - STpnt = scsi_get_request_dev(req); - if (!STpnt) { - panic("Unable to find device associated with request"); - } - /* - * Now try and find a command block that we can use. - */ - if( req->special != NULL ) { - SCpnt = (Scsi_Cmnd *) req->special; - /* - * We need to recount the number of - * scatter-gather segments here - the - * normal case code assumes this to be - * correct, as it would be a performance - * lose to always recount. Handling - * errors is always unusual, of course. - */ - recount_segments(SCpnt); - } else { - SCpnt = scsi_allocate_device(SDpnt, FALSE, FALSE); - } - /* - * If so, we are ready to do something. Bump the count - * while the queue is locked and then break out of the - * loop. Otherwise loop around and try another request. - */ - if (!SCpnt) { - break; - } - } - - /* - * Now bump the usage count for both the host and the - * device. - */ - SHpnt->host_busy++; - SDpnt->device_busy++; - - /* - * Finally, before we release the lock, we copy the - * request to the command block, and remove the - * request from the request list. Note that we always - * operate on the queue head - there is absolutely no - * reason to search the list, because all of the commands - * in this queue are for the same device. - */ - blkdev_dequeue_request(req); - - if (req != &SCpnt->request && req != &SRpnt->sr_request ) { - memcpy(&SCpnt->request, req, sizeof(struct request)); - - /* - * We have copied the data out of the request block - - * it is now in a field in SCpnt. Release the request - * block. - */ - blkdev_release_request(req); - } - /* - * Now it is finally safe to release the lock. We are - * not going to noodle the request list until this - * request has been queued and we loop back to queue - * another. - */ - req = NULL; - spin_unlock_irq(&io_request_lock); - - if (SCpnt->request.cmd != SPECIAL) { - /* - * This will do a couple of things: - * 1) Fill in the actual SCSI command. - * 2) Fill in any other upper-level specific fields - * (timeout). - * - * If this returns 0, it means that the request failed - * (reading past end of disk, reading offline device, - * etc). This won't actually talk to the device, but - * some kinds of consistency checking may cause the - * request to be rejected immediately. - */ - if (STpnt == NULL) { - STpnt = scsi_get_request_dev(req); - } - /* - * This sets up the scatter-gather table (allocating if - * required). Hosts that need bounce buffers will also - * get those allocated here. - */ - if (!SDpnt->scsi_init_io_fn(SCpnt)) { - printk("scsi_request_fn: scsi_init_io_fn failed :-(\n"); - SCpnt = __scsi_end_request(SCpnt, 0, - SCpnt->request.nr_sectors, 0, 0); - if( SCpnt != NULL ) - { - panic("Should not have leftover blocks\n"); - } - spin_lock_irq(&io_request_lock); - SHpnt->host_busy--; - SDpnt->device_busy--; - continue; - } - /* - * Initialize the actual SCSI command for this request. - */ - if (!STpnt->init_command(SCpnt)) { - printk("scsi_request_fn: init_command failed :-(\n"); - scsi_release_buffers(SCpnt); - SCpnt = __scsi_end_request(SCpnt, 0, - SCpnt->request.nr_sectors, 0, 0); - if( SCpnt != NULL ) - { - panic("Should not have leftover blocks\n"); - } - spin_lock_irq(&io_request_lock); - SHpnt->host_busy--; - SDpnt->device_busy--; - continue; - } - } - /* - * Finally, initialize any error handling parameters, and set up - * the timers for timeouts. - */ - scsi_init_cmd_errh(SCpnt); - - /* - * Dispatch the command to the low-level driver. - */ - scsi_dispatch_cmd(SCpnt); - - /* - * Now we need to grab the lock again. We are about to mess - * with the request queue and try to find another command. - */ - spin_lock_irq(&io_request_lock); - } -} - -/* - * Function: scsi_block_requests() - * - * Purpose: Utility function used by low-level drivers to prevent further - * commands from being queued to the device. - * - * Arguments: SHpnt - Host in question - * - * Returns: Nothing - * - * Lock status: No locks are assumed held. - * - * Notes: There is no timer nor any other means by which the requests - * get unblocked other than the low-level driver calling - * scsi_unblock_requests(). - */ -void scsi_block_requests(struct Scsi_Host * SHpnt) -{ - SHpnt->host_self_blocked = TRUE; -} - -/* - * Function: scsi_unblock_requests() - * - * Purpose: Utility function used by low-level drivers to allow further - * commands from being queued to the device. - * - * Arguments: SHpnt - Host in question - * - * Returns: Nothing - * - * Lock status: No locks are assumed held. - * - * Notes: There is no timer nor any other means by which the requests - * get unblocked other than the low-level driver calling - * scsi_unblock_requests(). - * - * This is done as an API function so that changes to the - * internals of the scsi mid-layer won't require wholesale - * changes to drivers that use this feature. - */ -void scsi_unblock_requests(struct Scsi_Host * SHpnt) -{ - Scsi_Device *SDloop; - - SHpnt->host_self_blocked = FALSE; - /* Now that we are unblocked, try to start the queues. */ - for (SDloop = SHpnt->host_queue; SDloop; SDloop = SDloop->next) - scsi_queue_next_request(&SDloop->request_queue, NULL); -} - -/* - * Function: scsi_report_bus_reset() - * - * Purpose: Utility function used by low-level drivers to report that - * they have observed a bus reset on the bus being handled. - * - * Arguments: SHpnt - Host in question - * channel - channel on which reset was observed. - * - * Returns: Nothing - * - * Lock status: No locks are assumed held. - * - * Notes: This only needs to be called if the reset is one which - * originates from an unknown location. Resets originated - * by the mid-level itself don't need to call this, but there - * should be no harm. - * - * The main purpose of this is to make sure that a CHECK_CONDITION - * is properly treated. - */ -void scsi_report_bus_reset(struct Scsi_Host * SHpnt, int channel) -{ - Scsi_Device *SDloop; - for (SDloop = SHpnt->host_queue; SDloop; SDloop = SDloop->next) { - if (channel == SDloop->channel) { - SDloop->was_reset = 1; - SDloop->expecting_cc_ua = 1; - } - } -} - -/* - * FIXME(eric) - these are empty stubs for the moment. I need to re-implement - * host blocking from scratch. The theory is that hosts that wish to block - * will register/deregister using these functions instead of the old way - * of setting the wish_block flag. - * - * The details of the implementation remain to be settled, however the - * stubs are here now so that the actual drivers will properly compile. - */ -void scsi_register_blocked_host(struct Scsi_Host * SHpnt) -{ -} - -void scsi_deregister_blocked_host(struct Scsi_Host * SHpnt) -{ -} diff --git a/xen/drivers/scsi/scsi_merge.c b/xen/drivers/scsi/scsi_merge.c deleted file mode 100644 index 89207e99ed..0000000000 --- a/xen/drivers/scsi/scsi_merge.c +++ /dev/null @@ -1,1182 +0,0 @@ -/* - * scsi_merge.c Copyright (C) 1999 Eric Youngdale - * - * SCSI queueing library. - * Initial versions: Eric Youngdale (eric@andante.org). - * Based upon conversations with large numbers - * of people at Linux Expo. - * Support for dynamic DMA mapping: Jakub Jelinek (jakub@redhat.com). - */ - -/* - * This file contains queue management functions that are used by SCSI. - * Typically this is used for several purposes. First, we need to ensure - * that commands do not grow so large that they cannot be handled all at - * once by a host adapter. The various flavors of merge functions included - * here serve this purpose. - * - * Note that it would be quite trivial to allow the low-level driver the - * flexibility to define it's own queue handling functions. For the time - * being, the hooks are not present. Right now we are just using the - * data in the host template as an indicator of how we should be handling - * queues, and we select routines that are optimized for that purpose. - * - * Some hosts do not impose any restrictions on the size of a request. - * In such cases none of the merge functions in this file are called, - * and we allow ll_rw_blk to merge requests in the default manner. - * This isn't guaranteed to be optimal, but it should be pretty darned - * good. If someone comes up with ideas of better ways of managing queues - * to improve on the default behavior, then certainly fit it into this - * scheme in whatever manner makes the most sense. Please note that - * since each device has it's own queue, we have considerable flexibility - * in queue management. - */ - -#define __NO_VERSION__ -#include -#include - -#include -#include -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -#include -/* #include */ -/* #include */ -/* #include */ - - -#define __KERNEL_SYSCALLS__ - -/* #include */ - -#include -#include -#include -#include - -#include "scsi.h" -#include "hosts.h" -#include "constants.h" -#include - -/* - * This means that bounce buffers cannot be allocated in chunks > PAGE_SIZE. - * Ultimately we should get away from using a dedicated DMA bounce buffer - * pool, and we should instead try and use kmalloc() instead. If we can - * eliminate this pool, then this restriction would no longer be needed. - */ -#define DMA_SEGMENT_SIZE_LIMITED - -#ifdef CONFIG_SCSI_DEBUG_QUEUES -/* - * Enable a bunch of additional consistency checking. Turn this off - * if you are benchmarking. - */ -static int dump_stats(struct request *req, - int use_clustering, - int dma_host, - int segments) -{ - struct buffer_head *bh; - - /* - * Dump the information that we have. We know we have an - * inconsistency. - */ - printk("nr_segments is %x\n", req->nr_segments); - printk("counted segments is %x\n", segments); - printk("Flags %d %d\n", use_clustering, dma_host); - for (bh = req->bh; bh->b_reqnext != NULL; bh = bh->b_reqnext) - { - printk("Segment 0x%p, blocks %d, addr 0x%lx\n", - bh, - bh->b_size >> 9, - virt_to_phys(bh->b_data - 1)); - } - panic("Ththththaats all folks. Too dangerous to continue.\n"); -} - - -/* - * Simple sanity check that we will use for the first go around - * in order to ensure that we are doing the counting correctly. - * This can be removed for optimization. - */ -#define SANITY_CHECK(req, _CLUSTER, _DMA) \ - if( req->nr_segments != __count_segments(req, _CLUSTER, _DMA, NULL) ) \ - { \ - printk("Incorrect segment count at 0x%p", current_text_addr()); \ - dump_stats(req, _CLUSTER, _DMA, __count_segments(req, _CLUSTER, _DMA, NULL)); \ - } -#else -#define SANITY_CHECK(req, _CLUSTER, _DMA) -#endif - -static void dma_exhausted(Scsi_Cmnd * SCpnt, int i) -{ - int jj; - struct scatterlist *sgpnt; - void **bbpnt; - int consumed = 0; - - sgpnt = (struct scatterlist *) SCpnt->request_buffer; - bbpnt = SCpnt->bounce_buffers; - - /* - * Now print out a bunch of stats. First, start with the request - * size. - */ - printk("dma_free_sectors:%d\n", scsi_dma_free_sectors); - printk("use_sg:%d\ti:%d\n", SCpnt->use_sg, i); - printk("request_bufflen:%d\n", SCpnt->request_bufflen); - /* - * Now dump the scatter-gather table, up to the point of failure. - */ - for(jj=0; jj < SCpnt->use_sg; jj++) - { - printk("[%d]\tlen:%d\taddr:%p\tbounce:%p\n", - jj, - sgpnt[jj].length, - sgpnt[jj].address, - (bbpnt ? bbpnt[jj] : NULL)); - if (bbpnt && bbpnt[jj]) - consumed += sgpnt[jj].length; - } - printk("Total %d sectors consumed\n", consumed); - panic("DMA pool exhausted"); -} - -#define CLUSTERABLE_DEVICE(SH,SD) (SH->use_clustering) - -/* - * This entire source file deals with the new queueing code. - */ - -/* - * Function: __count_segments() - * - * Purpose: Prototype for queue merge function. - * - * Arguments: q - Queue for which we are merging request. - * req - request into which we wish to merge. - * use_clustering - 1 if this host wishes to use clustering - * dma_host - 1 if this host has ISA DMA issues (bus doesn't - * expose all of the address lines, so that DMA cannot - * be done from an arbitrary address). - * remainder - used to track the residual size of the last - * segment. Comes in handy when we want to limit the - * size of bounce buffer segments to PAGE_SIZE. - * - * Returns: Count of the number of SG segments for the request. - * - * Lock status: - * - * Notes: This is only used for diagnostic purposes. - */ -__inline static int __count_segments(struct request *req, - int use_clustering, - int dma_host, - int * remainder) -{ - int ret = 1; - int reqsize = 0; - struct buffer_head *bh; - struct buffer_head *bhnext; - - if( remainder != NULL ) { - reqsize = *remainder; - } - - /* - * Add in the size increment for the first buffer. - */ - bh = req->bh; -#ifdef DMA_SEGMENT_SIZE_LIMITED - if( reqsize + bh->b_size > PAGE_SIZE ) { - ret++; - reqsize = bh->b_size; - } else { - reqsize += bh->b_size; - } -#else - reqsize += bh->b_size; -#endif - - for (bh = req->bh, bhnext = bh->b_reqnext; - bhnext != NULL; - bh = bhnext, bhnext = bh->b_reqnext) { - if (use_clustering) { - /* - * See if we can do this without creating another - * scatter-gather segment. In the event that this is a - * DMA capable host, make sure that a segment doesn't span - * the DMA threshold boundary. - */ - if (dma_host && - virt_to_phys(bhnext->b_data) - 1 == ISA_DMA_THRESHOLD) { - ret++; - reqsize = bhnext->b_size; - } else if (CONTIGUOUS_BUFFERS(bh, bhnext)) { - /* - * This one is OK. Let it go. - */ -#ifdef DMA_SEGMENT_SIZE_LIMITED - /* Note scsi_malloc is only able to hand out - * chunks of memory in sizes of PAGE_SIZE or - * less. Thus we need to keep track of - * the size of the piece that we have - * seen so far, and if we have hit - * the limit of PAGE_SIZE, then we are - * kind of screwed and we need to start - * another segment. - */ - if( dma_host - && virt_to_phys(bh->b_data) - 1 >= ISA_DMA_THRESHOLD - && reqsize + bhnext->b_size > PAGE_SIZE ) - { - ret++; - reqsize = bhnext->b_size; - continue; - } -#endif - reqsize += bhnext->b_size; - continue; - } - ret++; - reqsize = bhnext->b_size; - } else { - ret++; - reqsize = bhnext->b_size; - } - } - if( remainder != NULL ) { - *remainder = reqsize; - } - return ret; -} - -/* - * Function: recount_segments() - * - * Purpose: Recount the number of scatter-gather segments for this request. - * - * Arguments: req - request that needs recounting. - * - * Returns: Count of the number of SG segments for the request. - * - * Lock status: Irrelevant. - * - * Notes: This is only used when we have partially completed requests - * and the bit that is leftover is of an indeterminate size. - * This can come up if you get a MEDIUM_ERROR, for example, - * as we will have "completed" all of the sectors up to and - * including the bad sector, and the leftover bit is what - * we have to do now. This tends to be a rare occurrence, so - * we aren't busting our butts to instantiate separate versions - * of this function for the 4 different flag values. We - * probably should, however. - */ -void -recount_segments(Scsi_Cmnd * SCpnt) -{ - struct request *req; - struct Scsi_Host *SHpnt; - Scsi_Device * SDpnt; - - req = &SCpnt->request; - SHpnt = SCpnt->host; - SDpnt = SCpnt->device; - - req->nr_segments = __count_segments(req, - CLUSTERABLE_DEVICE(SHpnt, SDpnt), - SHpnt->unchecked_isa_dma, NULL); -} - -#define MERGEABLE_BUFFERS(X,Y) \ -(((((long)(X)->b_data+(X)->b_size)|((long)(Y)->b_data)) & \ - (DMA_CHUNK_SIZE - 1)) == 0) - -#ifdef DMA_CHUNK_SIZE -static inline int scsi_new_mergeable(request_queue_t * q, - struct request * req, - struct Scsi_Host *SHpnt, - int max_segments) -{ - /* - * pci_map_sg will be able to merge these two - * into a single hardware sg entry, check if - * we'll have enough memory for the sg list. - * scsi.c allocates for this purpose - * min(64,sg_tablesize) entries. - */ - if (req->nr_segments >= max_segments || - req->nr_segments >= SHpnt->sg_tablesize) - return 0; - req->nr_segments++; - return 1; -} - -static inline int scsi_new_segment(request_queue_t * q, - struct request * req, - struct Scsi_Host *SHpnt, - int max_segments) -{ - /* - * pci_map_sg won't be able to map these two - * into a single hardware sg entry, so we have to - * check if things fit into sg_tablesize. - */ - if (req->nr_hw_segments >= SHpnt->sg_tablesize || - req->nr_segments >= SHpnt->sg_tablesize) - return 0; - req->nr_hw_segments++; - req->nr_segments++; - return 1; -} -#else -static inline int scsi_new_segment(request_queue_t * q, - struct request * req, - struct Scsi_Host *SHpnt, - int max_segments) -{ - if (req->nr_segments < SHpnt->sg_tablesize && - req->nr_segments < max_segments) { - /* - * This will form the start of a new segment. Bump the - * counter. - */ - req->nr_segments++; - return 1; - } else { - return 0; - } -} -#endif - -/* - * Function: __scsi_merge_fn() - * - * Purpose: Prototype for queue merge function. - * - * Arguments: q - Queue for which we are merging request. - * req - request into which we wish to merge. - * bh - Block which we may wish to merge into request - * use_clustering - 1 if this host wishes to use clustering - * dma_host - 1 if this host has ISA DMA issues (bus doesn't - * expose all of the address lines, so that DMA cannot - * be done from an arbitrary address). - * - * Returns: 1 if it is OK to merge the block into the request. 0 - * if it is not OK. - * - * Lock status: io_request_lock is assumed to be held here. - * - * Notes: Some drivers have limited scatter-gather table sizes, and - * thus they cannot queue an infinitely large command. This - * function is called from ll_rw_blk before it attempts to merge - * a new block into a request to make sure that the request will - * not become too large. - * - * This function is not designed to be directly called. Instead - * it should be referenced from other functions where the - * use_clustering and dma_host parameters should be integer - * constants. The compiler should thus be able to properly - * optimize the code, eliminating stuff that is irrelevant. - * It is more maintainable to do this way with a single function - * than to have 4 separate functions all doing roughly the - * same thing. - */ -__inline static int __scsi_back_merge_fn(request_queue_t * q, - struct request *req, - struct buffer_head *bh, - int max_segments, - int use_clustering, - int dma_host) -{ - unsigned int count; - unsigned int segment_size = 0; - Scsi_Device *SDpnt; - struct Scsi_Host *SHpnt; - - SDpnt = (Scsi_Device *) q->queuedata; - SHpnt = SDpnt->host; - -#ifdef DMA_CHUNK_SIZE - if (max_segments > 64) - max_segments = 64; -#endif - - if ((req->nr_sectors + (bh->b_size >> 9)) > SHpnt->max_sectors) - return 0; - - if (use_clustering) { - /* - * See if we can do this without creating another - * scatter-gather segment. In the event that this is a - * DMA capable host, make sure that a segment doesn't span - * the DMA threshold boundary. - */ - if (dma_host && - virt_to_phys(req->bhtail->b_data) - 1 == ISA_DMA_THRESHOLD) { - goto new_end_segment; - } - if (CONTIGUOUS_BUFFERS(req->bhtail, bh)) { -#ifdef DMA_SEGMENT_SIZE_LIMITED - if( dma_host - && virt_to_phys(bh->b_data) - 1 >= ISA_DMA_THRESHOLD ) { - segment_size = 0; - count = __count_segments(req, use_clustering, dma_host, &segment_size); - if( segment_size + bh->b_size > PAGE_SIZE ) { - goto new_end_segment; - } - } -#endif - /* - * This one is OK. Let it go. - */ - return 1; - } - } - new_end_segment: -#ifdef DMA_CHUNK_SIZE - if (MERGEABLE_BUFFERS(req->bhtail, bh)) - return scsi_new_mergeable(q, req, SHpnt, max_segments); -#endif - return scsi_new_segment(q, req, SHpnt, max_segments); -} - -__inline static int __scsi_front_merge_fn(request_queue_t * q, - struct request *req, - struct buffer_head *bh, - int max_segments, - int use_clustering, - int dma_host) -{ - unsigned int count; - unsigned int segment_size = 0; - Scsi_Device *SDpnt; - struct Scsi_Host *SHpnt; - - SDpnt = (Scsi_Device *) q->queuedata; - SHpnt = SDpnt->host; - -#ifdef DMA_CHUNK_SIZE - if (max_segments > 64) - max_segments = 64; -#endif - - if ((req->nr_sectors + (bh->b_size >> 9)) > SHpnt->max_sectors) - return 0; - - if (use_clustering) { - /* - * See if we can do this without creating another - * scatter-gather segment. In the event that this is a - * DMA capable host, make sure that a segment doesn't span - * the DMA threshold boundary. - */ - if (dma_host && - virt_to_phys(bh->b_data) - 1 == ISA_DMA_THRESHOLD) { - goto new_start_segment; - } - if (CONTIGUOUS_BUFFERS(bh, req->bh)) { -#ifdef DMA_SEGMENT_SIZE_LIMITED - if( dma_host - && virt_to_phys(bh->b_data) - 1 >= ISA_DMA_THRESHOLD ) { - segment_size = bh->b_size; - count = __count_segments(req, use_clustering, dma_host, &segment_size); - if( count != req->nr_segments ) { - goto new_start_segment; - } - } -#endif - /* - * This one is OK. Let it go. - */ - return 1; - } - } - new_start_segment: -#ifdef DMA_CHUNK_SIZE - if (MERGEABLE_BUFFERS(bh, req->bh)) - return scsi_new_mergeable(q, req, SHpnt, max_segments); -#endif - return scsi_new_segment(q, req, SHpnt, max_segments); -} - -/* - * Function: scsi_merge_fn_() - * - * Purpose: queue merge function. - * - * Arguments: q - Queue for which we are merging request. - * req - request into which we wish to merge. - * bh - Block which we may wish to merge into request - * - * Returns: 1 if it is OK to merge the block into the request. 0 - * if it is not OK. - * - * Lock status: io_request_lock is assumed to be held here. - * - * Notes: Optimized for different cases depending upon whether - * ISA DMA is in use and whether clustering should be used. - */ -#define MERGEFCT(_FUNCTION, _BACK_FRONT, _CLUSTER, _DMA) \ -static int _FUNCTION(request_queue_t * q, \ - struct request * req, \ - struct buffer_head * bh, \ - int max_segments) \ -{ \ - int ret; \ - SANITY_CHECK(req, _CLUSTER, _DMA); \ - ret = __scsi_ ## _BACK_FRONT ## _merge_fn(q, \ - req, \ - bh, \ - max_segments, \ - _CLUSTER, \ - _DMA); \ - return ret; \ -} - -/* Version with use_clustering 0 and dma_host 1 is not necessary, - * since the only use of dma_host above is protected by use_clustering. - */ -MERGEFCT(scsi_back_merge_fn_, back, 0, 0) -MERGEFCT(scsi_back_merge_fn_c, back, 1, 0) -MERGEFCT(scsi_back_merge_fn_dc, back, 1, 1) - -MERGEFCT(scsi_front_merge_fn_, front, 0, 0) -MERGEFCT(scsi_front_merge_fn_c, front, 1, 0) -MERGEFCT(scsi_front_merge_fn_dc, front, 1, 1) - -/* - * Function: __scsi_merge_requests_fn() - * - * Purpose: Prototype for queue merge function. - * - * Arguments: q - Queue for which we are merging request. - * req - request into which we wish to merge. - * next - 2nd request that we might want to combine with req - * use_clustering - 1 if this host wishes to use clustering - * dma_host - 1 if this host has ISA DMA issues (bus doesn't - * expose all of the address lines, so that DMA cannot - * be done from an arbitrary address). - * - * Returns: 1 if it is OK to merge the two requests. 0 - * if it is not OK. - * - * Lock status: io_request_lock is assumed to be held here. - * - * Notes: Some drivers have limited scatter-gather table sizes, and - * thus they cannot queue an infinitely large command. This - * function is called from ll_rw_blk before it attempts to merge - * a new block into a request to make sure that the request will - * not become too large. - * - * This function is not designed to be directly called. Instead - * it should be referenced from other functions where the - * use_clustering and dma_host parameters should be integer - * constants. The compiler should thus be able to properly - * optimize the code, eliminating stuff that is irrelevant. - * It is more maintainable to do this way with a single function - * than to have 4 separate functions all doing roughly the - * same thing. - */ -__inline static int __scsi_merge_requests_fn(request_queue_t * q, - struct request *req, - struct request *next, - int max_segments, - int use_clustering, - int dma_host) -{ - Scsi_Device *SDpnt; - struct Scsi_Host *SHpnt; - - /* - * First check if the either of the requests are re-queued - * requests. Can't merge them if they are. - */ - if (req->special || next->special) - return 0; - - SDpnt = (Scsi_Device *) q->queuedata; - SHpnt = SDpnt->host; - -#ifdef DMA_CHUNK_SIZE - if (max_segments > 64) - max_segments = 64; - - /* If it would not fit into prepared memory space for sg chain, - * then don't allow the merge. - */ - if (req->nr_segments + next->nr_segments - 1 > max_segments || - req->nr_segments + next->nr_segments - 1 > SHpnt->sg_tablesize) { - return 0; - } - if (req->nr_hw_segments + next->nr_hw_segments - 1 > SHpnt->sg_tablesize) { - return 0; - } -#else - /* - * If the two requests together are too large (even assuming that we - * can merge the boundary requests into one segment, then don't - * allow the merge. - */ - if (req->nr_segments + next->nr_segments - 1 > SHpnt->sg_tablesize) { - return 0; - } -#endif - - if ((req->nr_sectors + next->nr_sectors) > SHpnt->max_sectors) - return 0; - - /* - * The main question is whether the two segments at the boundaries - * would be considered one or two. - */ - if (use_clustering) { - /* - * See if we can do this without creating another - * scatter-gather segment. In the event that this is a - * DMA capable host, make sure that a segment doesn't span - * the DMA threshold boundary. - */ - if (dma_host && - virt_to_phys(req->bhtail->b_data) - 1 == ISA_DMA_THRESHOLD) { - goto dont_combine; - } -#ifdef DMA_SEGMENT_SIZE_LIMITED - /* - * We currently can only allocate scatter-gather bounce - * buffers in chunks of PAGE_SIZE or less. - */ - if (dma_host - && CONTIGUOUS_BUFFERS(req->bhtail, next->bh) - && virt_to_phys(req->bhtail->b_data) - 1 >= ISA_DMA_THRESHOLD ) - { - int segment_size = 0; - int count = 0; - - count = __count_segments(req, use_clustering, dma_host, &segment_size); - count += __count_segments(next, use_clustering, dma_host, &segment_size); - if( count != req->nr_segments + next->nr_segments ) { - goto dont_combine; - } - } -#endif - if (CONTIGUOUS_BUFFERS(req->bhtail, next->bh)) { - /* - * This one is OK. Let it go. - */ - req->nr_segments += next->nr_segments - 1; -#ifdef DMA_CHUNK_SIZE - req->nr_hw_segments += next->nr_hw_segments - 1; -#endif - return 1; - } - } - dont_combine: -#ifdef DMA_CHUNK_SIZE - if (req->nr_segments + next->nr_segments > max_segments || - req->nr_segments + next->nr_segments > SHpnt->sg_tablesize) { - return 0; - } - /* If dynamic DMA mapping can merge last segment in req with - * first segment in next, then the check for hw segments was - * done above already, so we can always merge. - */ - if (MERGEABLE_BUFFERS (req->bhtail, next->bh)) { - req->nr_hw_segments += next->nr_hw_segments - 1; - } else if (req->nr_hw_segments + next->nr_hw_segments > SHpnt->sg_tablesize) { - return 0; - } else { - req->nr_hw_segments += next->nr_hw_segments; - } - req->nr_segments += next->nr_segments; - return 1; -#else - /* - * We know that the two requests at the boundary should not be combined. - * Make sure we can fix something that is the sum of the two. - * A slightly stricter test than we had above. - */ - if (req->nr_segments + next->nr_segments > max_segments || - req->nr_segments + next->nr_segments > SHpnt->sg_tablesize) { - return 0; - } else { - /* - * This will form the start of a new segment. Bump the - * counter. - */ - req->nr_segments += next->nr_segments; - return 1; - } -#endif -} - -/* - * Function: scsi_merge_requests_fn_() - * - * Purpose: queue merge function. - * - * Arguments: q - Queue for which we are merging request. - * req - request into which we wish to merge. - * bh - Block which we may wish to merge into request - * - * Returns: 1 if it is OK to merge the block into the request. 0 - * if it is not OK. - * - * Lock status: io_request_lock is assumed to be held here. - * - * Notes: Optimized for different cases depending upon whether - * ISA DMA is in use and whether clustering should be used. - */ -#define MERGEREQFCT(_FUNCTION, _CLUSTER, _DMA) \ -static int _FUNCTION(request_queue_t * q, \ - struct request * req, \ - struct request * next, \ - int max_segments) \ -{ \ - int ret; \ - SANITY_CHECK(req, _CLUSTER, _DMA); \ - ret = __scsi_merge_requests_fn(q, req, next, max_segments, _CLUSTER, _DMA); \ - return ret; \ -} - -/* Version with use_clustering 0 and dma_host 1 is not necessary, - * since the only use of dma_host above is protected by use_clustering. - */ -MERGEREQFCT(scsi_merge_requests_fn_, 0, 0) -MERGEREQFCT(scsi_merge_requests_fn_c, 1, 0) -MERGEREQFCT(scsi_merge_requests_fn_dc, 1, 1) -/* - * Function: __init_io() - * - * Purpose: Prototype for io initialize function. - * - * Arguments: SCpnt - Command descriptor we wish to initialize - * sg_count_valid - 1 if the sg count in the req is valid. - * use_clustering - 1 if this host wishes to use clustering - * dma_host - 1 if this host has ISA DMA issues (bus doesn't - * expose all of the address lines, so that DMA cannot - * be done from an arbitrary address). - * - * Returns: 1 on success. - * - * Lock status: - * - * Notes: Only the SCpnt argument should be a non-constant variable. - * This function is designed in such a way that it will be - * invoked from a series of small stubs, each of which would - * be optimized for specific circumstances. - * - * The advantage of this is that hosts that don't do DMA - * get versions of the function that essentially don't have - * any of the DMA code. Same goes for clustering - in the - * case of hosts with no need for clustering, there is no point - * in a whole bunch of overhead. - * - * Finally, in the event that a host has set can_queue to SG_ALL - * implying that there is no limit to the length of a scatter - * gather list, the sg count in the request won't be valid - * (mainly because we don't need queue management functions - * which keep the tally uptodate. - */ -__inline static int __init_io(Scsi_Cmnd * SCpnt, - int sg_count_valid, - int use_clustering, - int dma_host) -{ - struct buffer_head * bh; - struct buffer_head * bhprev; - char * buff; - int count; - int i; - struct request * req; - int sectors; - struct scatterlist * sgpnt; - int this_count; - void ** bbpnt; - - // printk("scsi_merge.c: __init_io entered\n"); - /* - * FIXME(eric) - don't inline this - it doesn't depend on the - * integer flags. Come to think of it, I don't think this is even - * needed any more. Need to play with it and see if we hit the - * panic. If not, then don't bother. - */ - if (!SCpnt->request.bh) { - /* - * Case of page request (i.e. raw device), or unlinked buffer - * Typically used for swapping, but this isn't how we do - * swapping any more. - */ - panic("I believe this is dead code. If we hit this, I was wrong"); -#if 0 - SCpnt->request_bufflen = SCpnt->request.nr_sectors << 9; - SCpnt->request_buffer = SCpnt->request.buffer; - SCpnt->use_sg = 0; - /* - * FIXME(eric) - need to handle DMA here. - */ -#endif - return 1; - } - req = &SCpnt->request; - /* - * First we need to know how many scatter gather segments are needed. - */ - if (!sg_count_valid) { - count = __count_segments(req, use_clustering, dma_host, NULL); - } else { - count = req->nr_segments; - } - - /* - * If the dma pool is nearly empty, then queue a minimal request - * with a single segment. Typically this will satisfy a single - * buffer. - */ - if (dma_host && scsi_dma_free_sectors <= 10) { - this_count = SCpnt->request.current_nr_sectors; - goto single_segment; - } - /* - * Don't bother with scatter-gather if there is only one segment. - */ - if (count == 1) { - this_count = SCpnt->request.nr_sectors; - goto single_segment; - } - SCpnt->use_sg = count; - - /* - * Allocate the actual scatter-gather table itself. - */ - SCpnt->sglist_len = (SCpnt->use_sg * sizeof(struct scatterlist)); - - /* If we could potentially require ISA bounce buffers, allocate - * space for this array here. - */ - if (dma_host) - SCpnt->sglist_len += (SCpnt->use_sg * sizeof(void *)); - - /* scsi_malloc can only allocate in chunks of 512 bytes so - * round it up. - */ - SCpnt->sglist_len = (SCpnt->sglist_len + 511) & ~511; - - sgpnt = (struct scatterlist *) scsi_malloc(SCpnt->sglist_len); - - /* - * Now fill the scatter-gather table. - */ - if (!sgpnt) { - /* - * If we cannot allocate the scatter-gather table, then - * simply write the first buffer all by itself. - */ - printk("Warning - running *really* short on DMA buffers\n"); - this_count = SCpnt->request.current_nr_sectors; - goto single_segment; - } - /* - * Next, walk the list, and fill in the addresses and sizes of - * each segment. - */ - memset(sgpnt, 0, SCpnt->sglist_len); - SCpnt->request_buffer = (char *) sgpnt; - SCpnt->request_bufflen = 0; - bhprev = NULL; - - if (dma_host) - bbpnt = (void **) ((char *)sgpnt + - (SCpnt->use_sg * sizeof(struct scatterlist))); - else - bbpnt = NULL; - - SCpnt->bounce_buffers = bbpnt; - - for (count = 0, bh = SCpnt->request.bh; - bh; bh = bh->b_reqnext) { - if (use_clustering && bhprev != NULL) { - if (dma_host && - virt_to_phys(bhprev->b_data) - 1 == ISA_DMA_THRESHOLD) { - /* Nothing - fall through */ - } else if (CONTIGUOUS_BUFFERS(bhprev, bh)) { - /* - * This one is OK. Let it go. Note that we - * do not have the ability to allocate - * bounce buffer segments > PAGE_SIZE, so - * for now we limit the thing. - */ - if( dma_host ) { -#ifdef DMA_SEGMENT_SIZE_LIMITED - if( virt_to_phys(bh->b_data) - 1 < ISA_DMA_THRESHOLD - || sgpnt[count - 1].length + bh->b_size <= PAGE_SIZE ) { - sgpnt[count - 1].length += bh->b_size; - bhprev = bh; - continue; - } -#else - sgpnt[count - 1].length += bh->b_size; - bhprev = bh; - continue; -#endif - } else { - sgpnt[count - 1].length += bh->b_size; - SCpnt->request_bufflen += bh->b_size; - bhprev = bh; - continue; - } - } - } - count++; - sgpnt[count - 1].address = bh->b_data; - sgpnt[count - 1].page = NULL; - sgpnt[count - 1].length += bh->b_size; - if (!dma_host) { - SCpnt->request_bufflen += bh->b_size; - } - bhprev = bh; - } - - /* - * Verify that the count is correct. - */ - if (count != SCpnt->use_sg) { - printk("Incorrect number of segments after building list\n"); -#ifdef CONFIG_SCSI_DEBUG_QUEUES - dump_stats(req, use_clustering, dma_host, count); -#endif - } - if (!dma_host) { - return 1; - } - /* - * Now allocate bounce buffers, if needed. - */ - SCpnt->request_bufflen = 0; - for (i = 0; i < count; i++) { - sectors = (sgpnt[i].length >> 9); - SCpnt->request_bufflen += sgpnt[i].length; - if (virt_to_phys(sgpnt[i].address) + sgpnt[i].length - 1 > - ISA_DMA_THRESHOLD) { - if( scsi_dma_free_sectors - sectors <= 10 ) { - /* - * If this would nearly drain the DMA - * pool empty, then let's stop here. - * Don't make this request any larger. - * This is kind of a safety valve that - * we use - we could get screwed later - * on if we run out completely. - */ - SCpnt->request_bufflen -= sgpnt[i].length; - SCpnt->use_sg = i; - if (i == 0) { - goto big_trouble; - } - break; - } - - bbpnt[i] = sgpnt[i].address; - sgpnt[i].address = - (char *) scsi_malloc(sgpnt[i].length); - /* - * If we cannot allocate memory for this DMA bounce - * buffer, then queue just what we have done so far. - */ - if (sgpnt[i].address == NULL) { - printk("Warning - running low on DMA memory\n"); - SCpnt->request_bufflen -= sgpnt[i].length; - SCpnt->use_sg = i; - if (i == 0) { - goto big_trouble; - } - break; - } - if (SCpnt->request.cmd == WRITE) { - memcpy(sgpnt[i].address, bbpnt[i], - sgpnt[i].length); - } - } - } - return 1; - - big_trouble: - /* - * We come here in the event that we get one humongous - * request, where we need a bounce buffer, and the buffer is - * more than we can allocate in a single call to - * scsi_malloc(). In addition, we only come here when it is - * the 0th element of the scatter-gather table that gets us - * into this trouble. As a fallback, we fall back to - * non-scatter-gather, and ask for a single segment. We make - * a half-hearted attempt to pick a reasonably large request - * size mainly so that we don't thrash the thing with - * iddy-biddy requests. - */ - - /* - * The original number of sectors in the 0th element of the - * scatter-gather table. - */ - sectors = sgpnt[0].length >> 9; - - /* - * Free up the original scatter-gather table. Note that since - * it was the 0th element that got us here, we don't have to - * go in and free up memory from the other slots. - */ - SCpnt->request_bufflen = 0; - SCpnt->use_sg = 0; - scsi_free(SCpnt->request_buffer, SCpnt->sglist_len); - - /* - * Make an attempt to pick up as much as we reasonably can. - * Just keep adding sectors until the pool starts running kind of - * low. The limit of 30 is somewhat arbitrary - the point is that - * it would kind of suck if we dropped down and limited ourselves to - * single-block requests if we had hundreds of free sectors. - */ - if( scsi_dma_free_sectors > 30 ) { - for (this_count = 0, bh = SCpnt->request.bh; - bh; bh = bh->b_reqnext) { - if( scsi_dma_free_sectors - this_count < 30 - || this_count == sectors ) - { - break; - } - this_count += bh->b_size >> 9; - } - - } else { - /* - * Yow! Take the absolute minimum here. - */ - this_count = SCpnt->request.current_nr_sectors; - } - - /* - * Now drop through into the single-segment case. - */ - - single_segment: - /* - * Come here if for any reason we choose to do this as a single - * segment. Possibly the entire request, or possibly a small - * chunk of the entire request. - */ - bh = SCpnt->request.bh; - buff = SCpnt->request.buffer; - - if (dma_host) { - /* - * Allocate a DMA bounce buffer. If the allocation fails, fall - * back and allocate a really small one - enough to satisfy - * the first buffer. - */ - if (virt_to_phys(SCpnt->request.bh->b_data) - + (this_count << 9) - 1 > ISA_DMA_THRESHOLD) { - buff = (char *) scsi_malloc(this_count << 9); - if (!buff) { - printk("Warning - running low on DMA memory\n"); - this_count = SCpnt->request.current_nr_sectors; - buff = (char *) scsi_malloc(this_count << 9); - if (!buff) { - dma_exhausted(SCpnt, 0); - } - } - if (SCpnt->request.cmd == WRITE) - memcpy(buff, (char *) SCpnt->request.buffer, this_count << 9); - } - } - SCpnt->request_bufflen = this_count << 9; - SCpnt->request_buffer = buff; - SCpnt->use_sg = 0; - return 1; -} - -#define INITIO(_FUNCTION, _VALID, _CLUSTER, _DMA) \ -static int _FUNCTION(Scsi_Cmnd * SCpnt) \ -{ \ - return __init_io(SCpnt, _VALID, _CLUSTER, _DMA); \ -} - -/* - * ll_rw_blk.c now keeps track of the number of segments in - * a request. Thus we don't have to do it any more here. - * We always force "_VALID" to 1. Eventually clean this up - * and get rid of the extra argument. - */ -INITIO(scsi_init_io_v, 1, 0, 0) -INITIO(scsi_init_io_vd, 1, 0, 1) -INITIO(scsi_init_io_vc, 1, 1, 0) -INITIO(scsi_init_io_vdc, 1, 1, 1) - -/* - * Function: initialize_merge_fn() - * - * Purpose: Initialize merge function for a host - * - * Arguments: SHpnt - Host descriptor. - * - * Returns: Nothing. - * - * Lock status: - * - * Notes: - */ -void initialize_merge_fn(Scsi_Device * SDpnt) -{ - request_queue_t *q; - struct Scsi_Host *SHpnt; - SHpnt = SDpnt->host; - - q = &SDpnt->request_queue; - - /* - * If the host has already selected a merge manager, then don't - * pick a new one. - */ -#if 0 - if (q->back_merge_fn && q->front_merge_fn) - return; -#endif - /* - * If this host has an unlimited tablesize, then don't bother with a - * merge manager. The whole point of the operation is to make sure - * that requests don't grow too large, and this host isn't picky. - * - * Note that ll_rw_blk.c is effectively maintaining a segment - * count which is only valid if clustering is used, and it obviously - * doesn't handle the DMA case. In the end, it - * is simply easier to do it ourselves with our own functions - * rather than rely upon the default behavior of ll_rw_blk. - */ - if (!CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma == 0) { - q->back_merge_fn = scsi_back_merge_fn_; - q->front_merge_fn = scsi_front_merge_fn_; - q->merge_requests_fn = scsi_merge_requests_fn_; - SDpnt->scsi_init_io_fn = scsi_init_io_v; - } else if (!CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma != 0) { - q->back_merge_fn = scsi_back_merge_fn_; - q->front_merge_fn = scsi_front_merge_fn_; - q->merge_requests_fn = scsi_merge_requests_fn_; - SDpnt->scsi_init_io_fn = scsi_init_io_vd; - } else if (CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma == 0) { - q->back_merge_fn = scsi_back_merge_fn_c; - q->front_merge_fn = scsi_front_merge_fn_c; - q->merge_requests_fn = scsi_merge_requests_fn_c; - SDpnt->scsi_init_io_fn = scsi_init_io_vc; - } else if (CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma != 0) { - q->back_merge_fn = scsi_back_merge_fn_dc; - q->front_merge_fn = scsi_front_merge_fn_dc; - q->merge_requests_fn = scsi_merge_requests_fn_dc; - SDpnt->scsi_init_io_fn = scsi_init_io_vdc; - } -} diff --git a/xen/drivers/scsi/scsi_module.c.inc b/xen/drivers/scsi/scsi_module.c.inc deleted file mode 100644 index 30495f643b..0000000000 --- a/xen/drivers/scsi/scsi_module.c.inc +++ /dev/null @@ -1,55 +0,0 @@ -/* - * scsi_module.c Copyright (1994, 1995) Eric Youngdale. - * - * Support for loading low-level scsi drivers using the linux kernel loadable - * module interface. - * - * To use, the host adapter should first define and initialize the variable - * driver_template (datatype Scsi_Host_Template), and then include this file. - * This should also be wrapped in a #ifdef MODULE/#endif. - * - * The low -level driver must also define a release function which will - * free any irq assignments, release any dma channels, release any I/O - * address space that might be reserved, and otherwise clean up after itself. - * The idea is that the same driver should be able to be reloaded without - * any difficulty. This makes debugging new drivers easier, as you should - * be able to load the driver, test it, unload, modify and reload. - * - * One *very* important caveat. If the driver may need to do DMA on the - * ISA bus, you must have unchecked_isa_dma set in the device template, - * even if this might be changed during the detect routine. This is - * because the shpnt structure will be allocated in a special way so that - * it will be below the appropriate DMA limit - thus if your driver uses - * the hostdata field of shpnt, and the board must be able to access this - * via DMA, the shpnt structure must be in a DMA accessible region of - * memory. This comment would be relevant for something like the buslogic - * driver where there are many boards, only some of which do DMA onto the - * ISA bus. There is no convenient way of specifying whether the host - * needs to be in a ISA DMA accessible region of memory when you call - * scsi_register. - */ - -#include -#include - -extern int scsi_register_module(int, void *); -extern int scsi_unregister_module(int, void *); - -static int __init init_this_scsi_driver(void) -{ - driver_template.module = THIS_MODULE; - scsi_register_module(MODULE_SCSI_HA, &driver_template); - if (driver_template.present) - return 0; - - scsi_unregister_module(MODULE_SCSI_HA, &driver_template); - return -ENODEV; -} - -static void __exit exit_this_scsi_driver(void) -{ - scsi_unregister_module(MODULE_SCSI_HA, &driver_template); -} - -module_init(init_this_scsi_driver); -module_exit(exit_this_scsi_driver); diff --git a/xen/drivers/scsi/scsi_obsolete.c b/xen/drivers/scsi/scsi_obsolete.c deleted file mode 100644 index 9cb2d7f304..0000000000 --- a/xen/drivers/scsi/scsi_obsolete.c +++ /dev/null @@ -1,1160 +0,0 @@ -/* - * scsi_obsolete.c Copyright (C) 1992 Drew Eckhardt - * Copyright (C) 1993, 1994, 1995 Eric Youngdale - * - * generic mid-level SCSI driver - * Initial versions: Drew Eckhardt - * Subsequent revisions: Eric Youngdale - * - * - * - * Bug correction thanks go to : - * Rik Faith - * Tommy Thorn - * Thomas Wuensche - * - * Modified by Eric Youngdale eric@andante.org to - * add scatter-gather, multiple outstanding request, and other - * enhancements. - * - * Native multichannel, wide scsi, /proc/scsi and hot plugging - * support added by Michael Neuffer - * - * Major improvements to the timeout, abort, and reset processing, - * as well as performance modifications for large queue depths by - * Leonard N. Zubkoff - * - * Improved compatibility with 2.0 behaviour by Manfred Spraul - * - */ - -/* - *######################################################################### - *######################################################################### - *######################################################################### - *######################################################################### - * NOTE - NOTE - NOTE - NOTE - NOTE - NOTE - NOTE - * - *######################################################################### - *######################################################################### - *######################################################################### - *######################################################################### - * - * This file contains the 'old' scsi error handling. It is only present - * while the new error handling code is being debugged, and while the low - * level drivers are being converted to use the new code. Once the last - * driver uses the new code this *ENTIRE* file will be nuked. - */ - -#define __NO_VERSION__ -#include - -#include -#include -#include -#include -#include -#include -/*#include */ -#include -#include -#include - -#include -#include -#include - -#include "scsi.h" -#include "hosts.h" -#include "constants.h" - -#undef USE_STATIC_SCSI_MEMORY - -/* - static const char RCSid[] = "$Header: /mnt/ide/home/eric/CVSROOT/linux/drivers/scsi/scsi_obsolete.c,v 1.1 1997/05/18 23:27:21 eric Exp $"; - */ - - -#define INTERNAL_ERROR (panic ("Internal error in file %s, line %d.\n", __FILE__, __LINE__)) - - -static int scsi_abort(Scsi_Cmnd *, int code); -static int scsi_reset(Scsi_Cmnd *, unsigned int); - -extern void scsi_old_done(Scsi_Cmnd * SCpnt); -int update_timeout(Scsi_Cmnd *, int); -extern void scsi_old_times_out(Scsi_Cmnd * SCpnt); - -#define SCSI_BLOCK(HOST) (HOST->can_queue && HOST->host_busy >= HOST->can_queue) - -static unsigned char generic_sense[6] = -{REQUEST_SENSE, 0, 0, 0, 255, 0}; - -/* - * This is the number of clock ticks we should wait before we time out - * and abort the command. This is for where the scsi.c module generates - * the command, not where it originates from a higher level, in which - * case the timeout is specified there. - * - * ABORT_TIMEOUT and RESET_TIMEOUT are the timeouts for RESET and ABORT - * respectively. - */ - -#ifdef DEBUG_TIMEOUT -static void scsi_dump_status(void); -#endif - - -#ifdef DEBUG -#define SCSI_TIMEOUT (5*HZ) -#else -#define SCSI_TIMEOUT (2*HZ) -#endif - -#ifdef DEBUG -#define SENSE_TIMEOUT SCSI_TIMEOUT -#define ABORT_TIMEOUT SCSI_TIMEOUT -#define RESET_TIMEOUT SCSI_TIMEOUT -#else -#define SENSE_TIMEOUT (5*HZ/10) -#define RESET_TIMEOUT (5*HZ/10) -#define ABORT_TIMEOUT (5*HZ/10) -#endif - - -/* Do not call reset on error if we just did a reset within 15 sec. */ -#define MIN_RESET_PERIOD (15*HZ) - - - -/* - * Flag bits for the internal_timeout array - */ -#define IN_ABORT 1 -#define IN_RESET 2 -#define IN_RESET2 4 -#define IN_RESET3 8 - -/* - * This is our time out function, called when the timer expires for a - * given host adapter. It will attempt to abort the currently executing - * command, that failing perform a kernel panic. - */ - -void scsi_old_times_out(Scsi_Cmnd * SCpnt) -{ - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - - /* Set the serial_number_at_timeout to the current serial_number */ - SCpnt->serial_number_at_timeout = SCpnt->serial_number; - - switch (SCpnt->internal_timeout & (IN_ABORT | IN_RESET | IN_RESET2 | IN_RESET3)) { - case NORMAL_TIMEOUT: - { -#ifdef DEBUG_TIMEOUT - scsi_dump_status(); -#endif - } - - if (!scsi_abort(SCpnt, DID_TIME_OUT)) - break; - case IN_ABORT: - printk("SCSI host %d abort (pid %ld) timed out - resetting\n", - SCpnt->host->host_no, SCpnt->pid); - if (!scsi_reset(SCpnt, SCSI_RESET_ASYNCHRONOUS)) - break; - case IN_RESET: - case (IN_ABORT | IN_RESET): - /* This might be controversial, but if there is a bus hang, - * you might conceivably want the machine up and running - * esp if you have an ide disk. - */ - printk("SCSI host %d channel %d reset (pid %ld) timed out - " - "trying harder\n", - SCpnt->host->host_no, SCpnt->channel, SCpnt->pid); - SCpnt->internal_timeout &= ~IN_RESET; - SCpnt->internal_timeout |= IN_RESET2; - scsi_reset(SCpnt, - SCSI_RESET_ASYNCHRONOUS | SCSI_RESET_SUGGEST_BUS_RESET); - break; - case IN_RESET2: - case (IN_ABORT | IN_RESET2): - /* Obviously the bus reset didn't work. - * Let's try even harder and call for an HBA reset. - * Maybe the HBA itself crashed and this will shake it loose. - */ - printk("SCSI host %d reset (pid %ld) timed out - trying to shake it loose\n", - SCpnt->host->host_no, SCpnt->pid); - SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2); - SCpnt->internal_timeout |= IN_RESET3; - scsi_reset(SCpnt, - SCSI_RESET_ASYNCHRONOUS | SCSI_RESET_SUGGEST_HOST_RESET); - break; - - default: - printk("SCSI host %d reset (pid %ld) timed out again -\n", - SCpnt->host->host_no, SCpnt->pid); - printk("probably an unrecoverable SCSI bus or device hang.\n"); - break; - - } - spin_unlock_irqrestore(&io_request_lock, flags); - -} - -/* - * From what I can find in scsi_obsolete.c, this function is only called - * by scsi_old_done and scsi_reset. Both of these functions run with the - * io_request_lock already held, so we need do nothing here about grabbing - * any locks. - */ -static void scsi_request_sense(Scsi_Cmnd * SCpnt) -{ - SCpnt->flags |= WAS_SENSE | ASKED_FOR_SENSE; - update_timeout(SCpnt, SENSE_TIMEOUT); - - - memcpy((void *) SCpnt->cmnd, (void *) generic_sense, - sizeof(generic_sense)); - memset((void *) SCpnt->sense_buffer, 0, - sizeof(SCpnt->sense_buffer)); - - if (SCpnt->device->scsi_level <= SCSI_2) - SCpnt->cmnd[1] = SCpnt->lun << 5; - SCpnt->cmnd[4] = sizeof(SCpnt->sense_buffer); - - SCpnt->request_buffer = &SCpnt->sense_buffer; - SCpnt->request_bufflen = sizeof(SCpnt->sense_buffer); - SCpnt->use_sg = 0; - SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]); - SCpnt->result = 0; - SCpnt->sc_data_direction = SCSI_DATA_READ; - - /* - * Ugly, ugly. The newer interfaces all assume that the lock - * isn't held. Mustn't disappoint, or we deadlock the system. - */ - spin_unlock_irq(&io_request_lock); - scsi_dispatch_cmd(SCpnt); - spin_lock_irq(&io_request_lock); -} - - - - -static int check_sense(Scsi_Cmnd * SCpnt) -{ - /* If there is no sense information, request it. If we have already - * requested it, there is no point in asking again - the firmware must - * be confused. - */ - if (((SCpnt->sense_buffer[0] & 0x70) >> 4) != 7) { - if (!(SCpnt->flags & ASKED_FOR_SENSE)) - return SUGGEST_SENSE; - else - return SUGGEST_RETRY; - } - SCpnt->flags &= ~ASKED_FOR_SENSE; - -#ifdef DEBUG_INIT - printk("scsi%d, channel%d : ", SCpnt->host->host_no, SCpnt->channel); - print_sense("", SCpnt); - printk("\n"); -#endif - if (SCpnt->sense_buffer[2] & 0xe0) - return SUGGEST_ABORT; - - switch (SCpnt->sense_buffer[2] & 0xf) { - case NO_SENSE: - return 0; - case RECOVERED_ERROR: - return SUGGEST_IS_OK; - - case ABORTED_COMMAND: - return SUGGEST_RETRY; - case NOT_READY: - case UNIT_ATTENTION: - /* - * If we are expecting a CC/UA because of a bus reset that we - * performed, treat this just as a retry. Otherwise this is - * information that we should pass up to the upper-level driver - * so that we can deal with it there. - */ - if (SCpnt->device->expecting_cc_ua) { - SCpnt->device->expecting_cc_ua = 0; - return SUGGEST_RETRY; - } - return SUGGEST_ABORT; - - /* these three are not supported */ - case COPY_ABORTED: - case VOLUME_OVERFLOW: - case MISCOMPARE: - - case MEDIUM_ERROR: - return SUGGEST_REMAP; - case BLANK_CHECK: - case DATA_PROTECT: - case HARDWARE_ERROR: - case ILLEGAL_REQUEST: - default: - return SUGGEST_ABORT; - } -} - -/* This function is the mid-level interrupt routine, which decides how - * to handle error conditions. Each invocation of this function must - * do one and *only* one of the following: - * - * (1) Call last_cmnd[host].done. This is done for fatal errors and - * normal completion, and indicates that the handling for this - * request is complete. - * (2) Call internal_cmnd to requeue the command. This will result in - * scsi_done being called again when the retry is complete. - * (3) Call scsi_request_sense. This asks the host adapter/drive for - * more information about the error condition. When the information - * is available, scsi_done will be called again. - * (4) Call reset(). This is sort of a last resort, and the idea is that - * this may kick things loose and get the drive working again. reset() - * automatically calls scsi_request_sense, and thus scsi_done will be - * called again once the reset is complete. - * - * If none of the above actions are taken, the drive in question - * will hang. If more than one of the above actions are taken by - * scsi_done, then unpredictable behavior will result. - */ -void scsi_old_done(Scsi_Cmnd * SCpnt) -{ - int status = 0; - int exit = 0; - int checked; - int oldto; - struct Scsi_Host *host = SCpnt->host; - Scsi_Device * device = SCpnt->device; - int result = SCpnt->result; - SCpnt->serial_number = 0; - SCpnt->serial_number_at_timeout = 0; - oldto = update_timeout(SCpnt, 0); - -#ifdef DEBUG_TIMEOUT - if (result) - printk("Non-zero result in scsi_done %x %d:%d\n", - result, SCpnt->target, SCpnt->lun); -#endif - - /* If we requested an abort, (and we got it) then fix up the return - * status to say why - */ - if (host_byte(result) == DID_ABORT && SCpnt->abort_reason) - SCpnt->result = result = (result & 0xff00ffff) | - (SCpnt->abort_reason << 16); - - -#define CMD_FINISHED 0 -#define MAYREDO 1 -#define REDO 3 -#define PENDING 4 - -#ifdef DEBUG - printk("In scsi_done(host = %d, result = %06x)\n", host->host_no, result); -#endif - - if (SCpnt->flags & SYNC_RESET) { - /* - * The behaviou of scsi_reset(SYNC) was changed in 2.1.? . - * The scsi mid-layer does a REDO after every sync reset, the driver - * must not do that any more. In order to prevent old drivers from - * crashing, all scsi_done() calls during sync resets are ignored. - */ - printk("scsi%d: device driver called scsi_done() " - "for a synchronous reset.\n", SCpnt->host->host_no); - return; - } - if (SCpnt->flags & WAS_SENSE) { - SCpnt->use_sg = SCpnt->old_use_sg; - SCpnt->cmd_len = SCpnt->old_cmd_len; - SCpnt->sc_data_direction = SCpnt->sc_old_data_direction; - SCpnt->underflow = SCpnt->old_underflow; - } - switch (host_byte(result)) { - case DID_OK: - if (status_byte(result) && (SCpnt->flags & WAS_SENSE)) - /* Failed to obtain sense information */ - { - SCpnt->flags &= ~WAS_SENSE; -#if 0 /* This cannot possibly be correct. */ - SCpnt->internal_timeout &= ~SENSE_TIMEOUT; -#endif - - if (!(SCpnt->flags & WAS_RESET)) { - printk("scsi%d : channel %d target %d lun %d request sense" - " failed, performing reset.\n", - SCpnt->host->host_no, SCpnt->channel, SCpnt->target, - SCpnt->lun); - scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS); - status = REDO; - break; - } else { - exit = (DRIVER_HARD | SUGGEST_ABORT); - status = CMD_FINISHED; - } - } else - switch (msg_byte(result)) { - case COMMAND_COMPLETE: - switch (status_byte(result)) { - case GOOD: - if (SCpnt->flags & WAS_SENSE) { -#ifdef DEBUG - printk("In scsi_done, GOOD status, COMMAND COMPLETE, " - "parsing sense information.\n"); -#endif - SCpnt->flags &= ~WAS_SENSE; -#if 0 /* This cannot possibly be correct. */ - SCpnt->internal_timeout &= ~SENSE_TIMEOUT; -#endif - - switch (checked = check_sense(SCpnt)) { - case SUGGEST_SENSE: - case 0: -#ifdef DEBUG - printk("NO SENSE. status = REDO\n"); -#endif - update_timeout(SCpnt, oldto); - status = REDO; - break; - case SUGGEST_IS_OK: - break; - case SUGGEST_REMAP: -#ifdef DEBUG - printk("SENSE SUGGEST REMAP - status = CMD_FINISHED\n"); -#endif - status = CMD_FINISHED; - exit = DRIVER_SENSE | SUGGEST_ABORT; - break; - case SUGGEST_RETRY: -#ifdef DEBUG - printk("SENSE SUGGEST RETRY - status = MAYREDO\n"); -#endif - status = MAYREDO; - exit = DRIVER_SENSE | SUGGEST_RETRY; - break; - case SUGGEST_ABORT: -#ifdef DEBUG - printk("SENSE SUGGEST ABORT - status = CMD_FINISHED"); -#endif - status = CMD_FINISHED; - exit = DRIVER_SENSE | SUGGEST_ABORT; - break; - default: - printk("Internal error %s %d \n", __FILE__, - __LINE__); - } - } - /* end WAS_SENSE */ - else { -#ifdef DEBUG - printk("COMMAND COMPLETE message returned, " - "status = CMD_FINISHED. \n"); -#endif - exit = DRIVER_OK; - status = CMD_FINISHED; - } - break; - - case CHECK_CONDITION: - case COMMAND_TERMINATED: - switch (check_sense(SCpnt)) { - case 0: - update_timeout(SCpnt, oldto); - status = REDO; - break; - case SUGGEST_REMAP: - status = CMD_FINISHED; - exit = DRIVER_SENSE | SUGGEST_ABORT; - break; - case SUGGEST_RETRY: - status = MAYREDO; - exit = DRIVER_SENSE | SUGGEST_RETRY; - break; - case SUGGEST_ABORT: - status = CMD_FINISHED; - exit = DRIVER_SENSE | SUGGEST_ABORT; - break; - case SUGGEST_SENSE: - scsi_request_sense(SCpnt); - status = PENDING; - break; - } - break; - - case CONDITION_GOOD: - case INTERMEDIATE_GOOD: - case INTERMEDIATE_C_GOOD: - break; - - case BUSY: - case QUEUE_FULL: - update_timeout(SCpnt, oldto); - status = REDO; - break; - - case RESERVATION_CONFLICT: - /* - * Most HAs will return an error for - * this, so usually reservation - * conflicts will be processed under - * DID_ERROR code - */ - printk("scsi%d (%d,%d,%d) : RESERVATION CONFLICT\n", - SCpnt->host->host_no, SCpnt->channel, - SCpnt->device->id, SCpnt->device->lun); - status = CMD_FINISHED; /* returns I/O error */ - break; - - default: - printk("Internal error %s %d \n" - "status byte = %d \n", __FILE__, - __LINE__, status_byte(result)); - - } - break; - default: - panic("scsi: unsupported message byte %d received\n", - msg_byte(result)); - } - break; - case DID_TIME_OUT: -#ifdef DEBUG - printk("Host returned DID_TIME_OUT - "); -#endif - - if (SCpnt->flags & WAS_TIMEDOUT) { -#ifdef DEBUG - printk("Aborting\n"); -#endif - /* - Allow TEST_UNIT_READY and INQUIRY commands to timeout early - without causing resets. All other commands should be retried. - */ - if (SCpnt->cmnd[0] != TEST_UNIT_READY && - SCpnt->cmnd[0] != INQUIRY) - status = MAYREDO; - exit = (DRIVER_TIMEOUT | SUGGEST_ABORT); - } else { -#ifdef DEBUG - printk("Retrying.\n"); -#endif - SCpnt->flags |= WAS_TIMEDOUT; - SCpnt->internal_timeout &= ~IN_ABORT; - status = REDO; - } - break; - case DID_BUS_BUSY: - case DID_PARITY: - status = REDO; - break; - case DID_NO_CONNECT: -#ifdef DEBUG - printk("Couldn't connect.\n"); -#endif - exit = (DRIVER_HARD | SUGGEST_ABORT); - break; - case DID_ERROR: - if (msg_byte(result) == COMMAND_COMPLETE && - status_byte(result) == RESERVATION_CONFLICT) { - printk("scsi%d (%d,%d,%d) : RESERVATION CONFLICT\n", - SCpnt->host->host_no, SCpnt->channel, - SCpnt->device->id, SCpnt->device->lun); - status = CMD_FINISHED; /* returns I/O error */ - break; - } - status = MAYREDO; - exit = (DRIVER_HARD | SUGGEST_ABORT); - break; - case DID_BAD_TARGET: - case DID_ABORT: - exit = (DRIVER_INVALID | SUGGEST_ABORT); - break; - case DID_RESET: - if (SCpnt->flags & IS_RESETTING) { - SCpnt->flags &= ~IS_RESETTING; - status = REDO; - break; - } - if (msg_byte(result) == GOOD && - status_byte(result) == CHECK_CONDITION) { - switch (check_sense(SCpnt)) { - case 0: - update_timeout(SCpnt, oldto); - status = REDO; - break; - case SUGGEST_REMAP: - case SUGGEST_RETRY: - status = MAYREDO; - exit = DRIVER_SENSE | SUGGEST_RETRY; - break; - case SUGGEST_ABORT: - status = CMD_FINISHED; - exit = DRIVER_SENSE | SUGGEST_ABORT; - break; - case SUGGEST_SENSE: - scsi_request_sense(SCpnt); - status = PENDING; - break; - } - } else { - status = REDO; - exit = SUGGEST_RETRY; - } - break; - default: - exit = (DRIVER_ERROR | SUGGEST_DIE); - } - - switch (status) { - case CMD_FINISHED: - case PENDING: - break; - case MAYREDO: -#ifdef DEBUG - printk("In MAYREDO, allowing %d retries, have %d\n", - SCpnt->allowed, SCpnt->retries); -#endif - if ((++SCpnt->retries) < SCpnt->allowed) { - if ((SCpnt->retries >= (SCpnt->allowed >> 1)) - && !(SCpnt->host->resetting && time_before(jiffies, SCpnt->host->last_reset + MIN_RESET_PERIOD)) - && !(SCpnt->flags & WAS_RESET)) { - printk("scsi%d channel %d : resetting for second half of retries.\n", - SCpnt->host->host_no, SCpnt->channel); - scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS); - /* fall through to REDO */ - } - } else { - status = CMD_FINISHED; - break; - } - /* fall through to REDO */ - - case REDO: - - if (SCpnt->flags & WAS_SENSE) - scsi_request_sense(SCpnt); - else { - memcpy((void *) SCpnt->cmnd, - (void *) SCpnt->data_cmnd, - sizeof(SCpnt->data_cmnd)); - memset((void *) SCpnt->sense_buffer, 0, - sizeof(SCpnt->sense_buffer)); - SCpnt->request_buffer = SCpnt->buffer; - SCpnt->request_bufflen = SCpnt->bufflen; - SCpnt->use_sg = SCpnt->old_use_sg; - SCpnt->cmd_len = SCpnt->old_cmd_len; - SCpnt->sc_data_direction = SCpnt->sc_old_data_direction; - SCpnt->underflow = SCpnt->old_underflow; - SCpnt->result = 0; - /* - * Ugly, ugly. The newer interfaces all - * assume that the lock isn't held. Mustn't - * disappoint, or we deadlock the system. - */ - spin_unlock_irq(&io_request_lock); - scsi_dispatch_cmd(SCpnt); - spin_lock_irq(&io_request_lock); - } - break; - default: - INTERNAL_ERROR; - } - - if (status == CMD_FINISHED) { - Scsi_Request *SRpnt; -#ifdef DEBUG - printk("Calling done function - at address %p\n", SCpnt->done); -#endif - host->host_busy--; /* Indicate that we are free */ - device->device_busy--; /* Decrement device usage counter. */ - - SCpnt->result = result | ((exit & 0xff) << 24); - SCpnt->use_sg = SCpnt->old_use_sg; - SCpnt->cmd_len = SCpnt->old_cmd_len; - SCpnt->sc_data_direction = SCpnt->sc_old_data_direction; - SCpnt->underflow = SCpnt->old_underflow; - /* - * The upper layers assume the lock isn't held. We mustn't - * disappoint them. When the new error handling code is in - * use, the upper code is run from a bottom half handler, so - * it isn't an issue. - */ - spin_unlock_irq(&io_request_lock); - SRpnt = SCpnt->sc_request; - if( SRpnt != NULL ) { - SRpnt->sr_result = SRpnt->sr_command->result; - if( SRpnt->sr_result != 0 ) { - memcpy(SRpnt->sr_sense_buffer, - SRpnt->sr_command->sense_buffer, - sizeof(SRpnt->sr_sense_buffer)); - } - } - - SCpnt->done(SCpnt); - spin_lock_irq(&io_request_lock); - } -#undef CMD_FINISHED -#undef REDO -#undef MAYREDO -#undef PENDING -} - -/* - * The scsi_abort function interfaces with the abort() function of the host - * we are aborting, and causes the current command to not complete. The - * caller should deal with any error messages or status returned on the - * next call. - * - * This will not be called reentrantly for a given host. - */ - -/* - * Since we're nice guys and specified that abort() and reset() - * can be non-reentrant. The internal_timeout flags are used for - * this. - */ - - -static int scsi_abort(Scsi_Cmnd * SCpnt, int why) -{ - int oldto; - struct Scsi_Host *host = SCpnt->host; - - while (1) { - - /* - * Protect against races here. If the command is done, or we are - * on a different command forget it. - */ - if (SCpnt->serial_number != SCpnt->serial_number_at_timeout) { - return 0; - } - if (SCpnt->internal_timeout & IN_ABORT) { - spin_unlock_irq(&io_request_lock); - while (SCpnt->internal_timeout & IN_ABORT) - barrier(); - spin_lock_irq(&io_request_lock); - } else { - SCpnt->internal_timeout |= IN_ABORT; - oldto = update_timeout(SCpnt, ABORT_TIMEOUT); - - if ((SCpnt->flags & IS_RESETTING) && SCpnt->device->soft_reset) { - /* OK, this command must have died when we did the - * reset. The device itself must have lied. - */ - printk("Stale command on %d %d:%d appears to have died when" - " the bus was reset\n", - SCpnt->channel, SCpnt->target, SCpnt->lun); - } - if (!host->host_busy) { - SCpnt->internal_timeout &= ~IN_ABORT; - update_timeout(SCpnt, oldto); - return 0; - } - printk("scsi : aborting command due to timeout : pid %lu, scsi%d," - " channel %d, id %d, lun %d ", - SCpnt->pid, SCpnt->host->host_no, (int) SCpnt->channel, - (int) SCpnt->target, (int) SCpnt->lun); - print_command(SCpnt->cmnd); - if (SCpnt->serial_number != SCpnt->serial_number_at_timeout) - return 0; - SCpnt->abort_reason = why; - switch (host->hostt->abort(SCpnt)) { - /* We do not know how to abort. Try waiting another - * time increment and see if this helps. Set the - * WAS_TIMEDOUT flag set so we do not try this twice - */ - case SCSI_ABORT_BUSY: /* Tough call - returning 1 from - * this is too severe - */ - case SCSI_ABORT_SNOOZE: - if (why == DID_TIME_OUT) { - SCpnt->internal_timeout &= ~IN_ABORT; - if (SCpnt->flags & WAS_TIMEDOUT) { - return 1; /* Indicate we cannot handle this. - * We drop down into the reset handler - * and try again - */ - } else { - SCpnt->flags |= WAS_TIMEDOUT; - oldto = SCpnt->timeout_per_command; - update_timeout(SCpnt, oldto); - } - } - return 0; - case SCSI_ABORT_PENDING: - if (why != DID_TIME_OUT) { - update_timeout(SCpnt, oldto); - } - return 0; - case SCSI_ABORT_SUCCESS: - /* We should have already aborted this one. No - * need to adjust timeout - */ - SCpnt->internal_timeout &= ~IN_ABORT; - return 0; - case SCSI_ABORT_NOT_RUNNING: - SCpnt->internal_timeout &= ~IN_ABORT; - update_timeout(SCpnt, 0); - return 0; - case SCSI_ABORT_ERROR: - default: - SCpnt->internal_timeout &= ~IN_ABORT; - return 1; - } - } - } -} - - -/* Mark a single SCSI Device as having been reset. */ - -static inline void scsi_mark_device_reset(Scsi_Device * Device) -{ - Device->was_reset = 1; - Device->expecting_cc_ua = 1; -} - - -/* Mark all SCSI Devices on a specific Host as having been reset. */ - -void scsi_mark_host_reset(struct Scsi_Host *Host) -{ - Scsi_Cmnd *SCpnt; - Scsi_Device *SDpnt; - - for (SDpnt = Host->host_queue; SDpnt; SDpnt = SDpnt->next) { - for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) - scsi_mark_device_reset(SCpnt->device); - } -} - - -/* Mark all SCSI Devices on a specific Host Bus as having been reset. */ - -static void scsi_mark_bus_reset(struct Scsi_Host *Host, int channel) -{ - Scsi_Cmnd *SCpnt; - Scsi_Device *SDpnt; - - for (SDpnt = Host->host_queue; SDpnt; SDpnt = SDpnt->next) { - for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) - if (SCpnt->channel == channel) - scsi_mark_device_reset(SCpnt->device); - } -} - - -static int scsi_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) -{ - int temp; - Scsi_Cmnd *SCpnt1; - Scsi_Device *SDpnt; - struct Scsi_Host *host = SCpnt->host; - - printk("SCSI bus is being reset for host %d channel %d.\n", - host->host_no, SCpnt->channel); - -#if 0 - /* - * First of all, we need to make a recommendation to the low-level - * driver as to whether a BUS_DEVICE_RESET should be performed, - * or whether we should do a full BUS_RESET. There is no simple - * algorithm here - we basically use a series of heuristics - * to determine what we should do. - */ - SCpnt->host->suggest_bus_reset = FALSE; - - /* - * First see if all of the active devices on the bus have - * been jammed up so that we are attempting resets. If so, - * then suggest a bus reset. Forcing a bus reset could - * result in some race conditions, but no more than - * you would usually get with timeouts. We will cross - * that bridge when we come to it. - * - * This is actually a pretty bad idea, since a sequence of - * commands will often timeout together and this will cause a - * Bus Device Reset followed immediately by a SCSI Bus Reset. - * If all of the active devices really are jammed up, the - * Bus Device Reset will quickly timeout and scsi_times_out - * will follow up with a SCSI Bus Reset anyway. - */ - SCpnt1 = host->host_queue; - while (SCpnt1) { - if (SCpnt1->request.rq_status != RQ_INACTIVE - && (SCpnt1->flags & (WAS_RESET | IS_RESETTING)) == 0) - break; - SCpnt1 = SCpnt1->next; - } - if (SCpnt1 == NULL) { - reset_flags |= SCSI_RESET_SUGGEST_BUS_RESET; - } - /* - * If the code that called us is suggesting a hard reset, then - * definitely request it. This usually occurs because a - * BUS_DEVICE_RESET times out. - * - * Passing reset_flags along takes care of this automatically. - */ - if (reset_flags & SCSI_RESET_SUGGEST_BUS_RESET) { - SCpnt->host->suggest_bus_reset = TRUE; - } -#endif - - while (1) { - - /* - * Protect against races here. If the command is done, or we are - * on a different command forget it. - */ - if (reset_flags & SCSI_RESET_ASYNCHRONOUS) - if (SCpnt->serial_number != SCpnt->serial_number_at_timeout) { - return 0; - } - if (SCpnt->internal_timeout & IN_RESET) { - spin_unlock_irq(&io_request_lock); - while (SCpnt->internal_timeout & IN_RESET) - barrier(); - spin_lock_irq(&io_request_lock); - } else { - SCpnt->internal_timeout |= IN_RESET; - update_timeout(SCpnt, RESET_TIMEOUT); - - if (reset_flags & SCSI_RESET_SYNCHRONOUS) - SCpnt->flags |= SYNC_RESET; - if (host->host_busy) { - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) { - SCpnt1 = SDpnt->device_queue; - while (SCpnt1) { - if (SCpnt1->request.rq_status != RQ_INACTIVE) { -#if 0 - if (!(SCpnt1->flags & IS_RESETTING) && - !(SCpnt1->internal_timeout & IN_ABORT)) - scsi_abort(SCpnt1, DID_RESET); -#endif - SCpnt1->flags |= (WAS_RESET | IS_RESETTING); - } - SCpnt1 = SCpnt1->next; - } - } - - host->last_reset = jiffies; - host->resetting = 1; - /* - * I suppose that the host reset callback will not play - * with the resetting field. We have just set the resetting - * flag here. -arca - */ - temp = host->hostt->reset(SCpnt, reset_flags); - /* - This test allows the driver to introduce an additional bus - settle time delay by setting last_reset up to 20 seconds in - the future. In the normal case where the driver does not - modify last_reset, it must be assumed that the actual bus - reset occurred immediately prior to the return to this code, - and so last_reset must be updated to the current time, so - that the delay in internal_cmnd will guarantee at least a - MIN_RESET_DELAY bus settle time. - */ - if (host->last_reset - jiffies > 20UL * HZ) - host->last_reset = jiffies; - } else { - host->host_busy++; - host->last_reset = jiffies; - host->resetting = 1; - SCpnt->flags |= (WAS_RESET | IS_RESETTING); - /* - * I suppose that the host reset callback will not play - * with the resetting field. We have just set the resetting - * flag here. -arca - */ - temp = host->hostt->reset(SCpnt, reset_flags); - if (time_before(host->last_reset, jiffies) || - (time_after(host->last_reset, jiffies + 20 * HZ))) - host->last_reset = jiffies; - host->host_busy--; - } - if (reset_flags & SCSI_RESET_SYNCHRONOUS) - SCpnt->flags &= ~SYNC_RESET; - -#ifdef DEBUG - printk("scsi reset function returned %d\n", temp); -#endif - - /* - * Now figure out what we need to do, based upon - * what the low level driver said that it did. - * If the result is SCSI_RESET_SUCCESS, SCSI_RESET_PENDING, - * or SCSI_RESET_WAKEUP, then the low level driver did a - * bus device reset or bus reset, so we should go through - * and mark one or all of the devices on that bus - * as having been reset. - */ - switch (temp & SCSI_RESET_ACTION) { - case SCSI_RESET_SUCCESS: - if (temp & SCSI_RESET_HOST_RESET) - scsi_mark_host_reset(host); - else if (temp & SCSI_RESET_BUS_RESET) - scsi_mark_bus_reset(host, SCpnt->channel); - else - scsi_mark_device_reset(SCpnt->device); - SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2 | IN_RESET3); - return 0; - case SCSI_RESET_PENDING: - if (temp & SCSI_RESET_HOST_RESET) - scsi_mark_host_reset(host); - else if (temp & SCSI_RESET_BUS_RESET) - scsi_mark_bus_reset(host, SCpnt->channel); - else - scsi_mark_device_reset(SCpnt->device); - case SCSI_RESET_NOT_RUNNING: - return 0; - case SCSI_RESET_PUNT: - SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2 | IN_RESET3); - scsi_request_sense(SCpnt); - return 0; - case SCSI_RESET_WAKEUP: - if (temp & SCSI_RESET_HOST_RESET) - scsi_mark_host_reset(host); - else if (temp & SCSI_RESET_BUS_RESET) - scsi_mark_bus_reset(host, SCpnt->channel); - else - scsi_mark_device_reset(SCpnt->device); - SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2 | IN_RESET3); - scsi_request_sense(SCpnt); - /* - * If a bus reset was performed, we - * need to wake up each and every command - * that was active on the bus or if it was a HBA - * reset all active commands on all channels - */ - if (temp & SCSI_RESET_HOST_RESET) { - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) { - SCpnt1 = SDpnt->device_queue; - while (SCpnt1) { - if (SCpnt1->request.rq_status != RQ_INACTIVE - && SCpnt1 != SCpnt) - scsi_request_sense(SCpnt1); - SCpnt1 = SCpnt1->next; - } - } - } else if (temp & SCSI_RESET_BUS_RESET) { - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) { - SCpnt1 = SDpnt->device_queue; - while (SCpnt1) { - if (SCpnt1->request.rq_status != RQ_INACTIVE - && SCpnt1 != SCpnt - && SCpnt1->channel == SCpnt->channel) - scsi_request_sense(SCpnt); - SCpnt1 = SCpnt1->next; - } - } - } - return 0; - case SCSI_RESET_SNOOZE: - /* In this case, we set the timeout field to 0 - * so that this command does not time out any more, - * and we return 1 so that we get a message on the - * screen. - */ - SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2 | IN_RESET3); - update_timeout(SCpnt, 0); - /* If you snooze, you lose... */ - case SCSI_RESET_ERROR: - default: - return 1; - } - - return temp; - } - } -} - -/* - * The strategy is to cause the timer code to call scsi_times_out() - * when the soonest timeout is pending. - * The arguments are used when we are queueing a new command, because - * we do not want to subtract the time used from this time, but when we - * set the timer, we want to take this value into account. - */ - -int update_timeout(Scsi_Cmnd * SCset, int timeout) -{ - int rtn; - - /* - * We are using the new error handling code to actually register/deregister - * timers for timeout. - */ - - if (!timer_pending(&SCset->eh_timeout)) { - rtn = 0; - } else { - rtn = SCset->eh_timeout.expires - jiffies; - } - - if (timeout == 0) { - scsi_delete_timer(SCset); - } else { - scsi_add_timer(SCset, timeout, scsi_old_times_out); - } - - return rtn; -} - - -/* - * This function exports SCSI Bus, Device or Host reset capability - * and is for use with the SCSI generic driver. - */ -int -scsi_old_reset(Scsi_Cmnd *SCpnt, unsigned int flag) -{ - unsigned int old_flags = SCSI_RESET_SYNCHRONOUS; - - switch(flag) { - case SCSI_TRY_RESET_DEVICE: - /* no suggestion flags to add, device reset is default */ - break; - case SCSI_TRY_RESET_BUS: - old_flags |= SCSI_RESET_SUGGEST_BUS_RESET; - break; - case SCSI_TRY_RESET_HOST: - old_flags |= SCSI_RESET_SUGGEST_HOST_RESET; - break; - default: - return FAILED; - } - - if (scsi_reset(SCpnt, old_flags)) - return FAILED; - return SUCCESS; -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/xen/drivers/scsi/scsi_obsolete.h b/xen/drivers/scsi/scsi_obsolete.h deleted file mode 100644 index abeacb996e..0000000000 --- a/xen/drivers/scsi/scsi_obsolete.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * scsi_obsolete.h Copyright (C) 1997 Eric Youngdale - * - */ - -#ifndef _SCSI_OBSOLETE_H -#define _SCSI_OBSOLETE_H - -/* - * These are the return codes for the abort and reset functions. The mid-level - * code uses these to decide what to do next. Each of the low level abort - * and reset functions must correctly indicate what it has done. - * The descriptions are written from the point of view of the mid-level code, - * so that the return code is telling the mid-level drivers exactly what - * the low level driver has already done, and what remains to be done. - */ - -/* We did not do anything. - * Wait some more for this command to complete, and if this does not work, - * try something more serious. */ -#define SCSI_ABORT_SNOOZE 0 - -/* This means that we were able to abort the command. We have already - * called the mid-level done function, and do not expect an interrupt that - * will lead to another call to the mid-level done function for this command */ -#define SCSI_ABORT_SUCCESS 1 - -/* We called for an abort of this command, and we should get an interrupt - * when this succeeds. Thus we should not restore the timer for this - * command in the mid-level abort function. */ -#define SCSI_ABORT_PENDING 2 - -/* Unable to abort - command is currently on the bus. Grin and bear it. */ -#define SCSI_ABORT_BUSY 3 - -/* The command is not active in the low level code. Command probably - * finished. */ -#define SCSI_ABORT_NOT_RUNNING 4 - -/* Something went wrong. The low level driver will indicate the correct - * error condition when it calls scsi_done, so the mid-level abort function - * can simply wait until this comes through */ -#define SCSI_ABORT_ERROR 5 - -/* We do not know how to reset the bus, or we do not want to. Bummer. - * Anyway, just wait a little more for the command in question, and hope that - * it eventually finishes. If it never finishes, the SCSI device could - * hang, so use this with caution. */ -#define SCSI_RESET_SNOOZE 0 - -/* We do not know how to reset the bus, or we do not want to. Bummer. - * We have given up on this ever completing. The mid-level code will - * request sense information to decide how to proceed from here. */ -#define SCSI_RESET_PUNT 1 - -/* This means that we were able to reset the bus. We have restarted all of - * the commands that should be restarted, and we should be able to continue - * on normally from here. We do not expect any interrupts that will return - * DID_RESET to any of the other commands in the host_queue, and the mid-level - * code does not need to do anything special to keep the commands alive. - * If a hard reset was performed then all outstanding commands on the - * bus have been restarted. */ -#define SCSI_RESET_SUCCESS 2 - -/* We called for a reset of this bus, and we should get an interrupt - * when this succeeds. Each command should get its own status - * passed up to scsi_done, but this has not happened yet. - * If a hard reset was performed, then we expect an interrupt - * for *each* of the outstanding commands that will have the - * effect of restarting the commands. - */ -#define SCSI_RESET_PENDING 3 - -/* We did a reset, but do not expect an interrupt to signal DID_RESET. - * This tells the upper level code to request the sense info, and this - * should keep the command alive. */ -#define SCSI_RESET_WAKEUP 4 - -/* The command is not active in the low level code. Command probably - finished. */ -#define SCSI_RESET_NOT_RUNNING 5 - -/* Something went wrong, and we do not know how to fix it. */ -#define SCSI_RESET_ERROR 6 - -#define SCSI_RESET_SYNCHRONOUS 0x01 -#define SCSI_RESET_ASYNCHRONOUS 0x02 -#define SCSI_RESET_SUGGEST_BUS_RESET 0x04 -#define SCSI_RESET_SUGGEST_HOST_RESET 0x08 -/* - * This is a bitmask that is ored with one of the above codes. - * It tells the mid-level code that we did a hard reset. - */ -#define SCSI_RESET_BUS_RESET 0x100 -/* - * This is a bitmask that is ored with one of the above codes. - * It tells the mid-level code that we did a host adapter reset. - */ -#define SCSI_RESET_HOST_RESET 0x200 -/* - * Used to mask off bits and to obtain the basic action that was - * performed. - */ -#define SCSI_RESET_ACTION 0xff - -#endif /* SCSI_OBSOLETE_H */ diff --git a/xen/drivers/scsi/scsi_proc.c b/xen/drivers/scsi/scsi_proc.c deleted file mode 100644 index 9cc4213df7..0000000000 --- a/xen/drivers/scsi/scsi_proc.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * linux/drivers/scsi/scsi_proc.c - * - * The functions in this file provide an interface between - * the PROC file system and the SCSI device drivers - * It is mainly used for debugging, statistics and to pass - * information directly to the lowlevel driver. - * - * (c) 1995 Michael Neuffer neuffer@goofy.zdv.uni-mainz.de - * Version: 0.99.8 last change: 95/09/13 - * - * generic command parser provided by: - * Andreas Heilwagen - * - * generic_proc_info() support of xxxx_info() by: - * Michael A. Griffith - */ - -#include /* for CONFIG_PROC_FS */ -#define __NO_VERSION__ -#include - -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -#include - -#include - -#include "scsi.h" -#include "hosts.h" - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -#ifdef CONFIG_PROC_FS - -/* generic_proc_info - * Used if the driver currently has no own support for /proc/scsi - */ -int generic_proc_info(char *buffer, char **start, off_t offset, int length, - const char *(*info) (struct Scsi_Host *), - struct Scsi_Host *sh) -{ - int len, pos, begin; - - begin = 0; - if (info && sh) { - pos = len = sprintf(buffer, "%s\n", info(sh)); - } else { - pos = len = sprintf(buffer, - "The driver does not yet support the proc-fs\n"); - } - if (pos < offset) { - len = 0; - begin = pos; - } - *start = buffer + (offset - begin); /* Start of wanted data */ - len -= (offset - begin); - if (len > length) - len = length; - - return (len); -} - -/* dispatch_scsi_info is the central dispatcher - * It is the interface between the proc-fs and the SCSI subsystem code - */ -static int proc_scsi_read(char *buffer, char **start, off_t offset, - int length, int *eof, void *data) -{ - struct Scsi_Host *hpnt = data; - int n; - - if (hpnt->hostt->proc_info == NULL) - n = generic_proc_info(buffer, start, offset, length, - hpnt->hostt->info, hpnt); - else - n = (hpnt->hostt->proc_info(buffer, start, offset, - length, hpnt->host_no, 0)); - *eof = (nhostt->proc_info == NULL) - ret = -ENOSYS; - - if (count > PROC_BLOCK_SIZE) - return -EOVERFLOW; - - if (!(page = (char *) __get_free_page(GFP_KERNEL))) - return -ENOMEM; - if(copy_from_user(page, buf, count)) - { - free_page((ulong) page); - return -EFAULT; - } - - ret = hpnt->hostt->proc_info(page, &start, 0, count, - hpnt->host_no, 1); - - free_page((ulong) page); - return(ret); -} - -void build_proc_dir_entries(Scsi_Host_Template * tpnt) -{ - struct Scsi_Host *hpnt; - char name[10]; /* see scsi_unregister_host() */ - - tpnt->proc_dir = proc_mkdir(tpnt->proc_name, proc_scsi); - if (!tpnt->proc_dir) { - printk(KERN_ERR "Unable to proc_mkdir in scsi.c/build_proc_dir_entries"); - return; - } - tpnt->proc_dir->owner = tpnt->module; - - hpnt = scsi_hostlist; - while (hpnt) { - if (tpnt == hpnt->hostt) { - struct proc_dir_entry *p; - sprintf(name,"%d",hpnt->host_no); - p = create_proc_read_entry(name, - S_IFREG | S_IRUGO | S_IWUSR, - tpnt->proc_dir, - proc_scsi_read, - (void *)hpnt); - if (!p) - panic("Not enough memory to register SCSI HBA in /proc/scsi !\n"); - p->write_proc=proc_scsi_write; - p->owner = tpnt->module; - } - hpnt = hpnt->next; - } -} - -/* - * parseHandle *parseInit(char *buf, char *cmdList, int cmdNum); - * gets a pointer to a null terminated data buffer - * and a list of commands with blanks as delimiter - * in between. - * The commands have to be alphanumerically sorted. - * cmdNum has to contain the number of commands. - * On success, a pointer to a handle structure - * is returned, NULL on failure - * - * int parseOpt(parseHandle *handle, char **param); - * processes the next parameter. On success, the - * index of the appropriate command in the cmdList - * is returned, starting with zero. - * param points to the null terminated parameter string. - * On failure, -1 is returned. - * - * The databuffer buf may only contain pairs of commands - * options, separated by blanks: - * [ ]* - */ - -typedef struct { - char *buf, /* command buffer */ - *cmdList, /* command list */ - *bufPos, /* actual position */ - **cmdPos, /* cmdList index */ - cmdNum; /* cmd number */ -} parseHandle; - -inline int parseFree(parseHandle * handle) -{ /* free memory */ - kfree(handle->cmdPos); - kfree(handle); - - return -1; -} - -parseHandle *parseInit(char *buf, char *cmdList, int cmdNum) -{ - char *ptr; /* temp pointer */ - parseHandle *handle; /* new handle */ - - if (!buf || !cmdList) /* bad input ? */ - return NULL; - handle = (parseHandle *) kmalloc(sizeof(parseHandle), GFP_KERNEL); - if (!handle) - return NULL; /* out of memory */ - handle->cmdPos = (char **) kmalloc(sizeof(int) * cmdNum, GFP_KERNEL); - if (!handle->cmdPos) { - kfree(handle); - return NULL; /* out of memory */ - } - handle->buf = handle->bufPos = buf; /* init handle */ - handle->cmdList = cmdList; - handle->cmdNum = cmdNum; - - handle->cmdPos[cmdNum = 0] = cmdList; - for (ptr = cmdList; *ptr; ptr++) { /* scan command string */ - if (*ptr == ' ') { /* and insert zeroes */ - *ptr++ = 0; - handle->cmdPos[++cmdNum] = ptr++; - } - } - return handle; -} - -int parseOpt(parseHandle * handle, char **param) -{ - int cmdIndex = 0, cmdLen = 0; - char *startPos; - - if (!handle) /* invalid handle */ - return (parseFree(handle)); - /* skip spaces */ - for (; *(handle->bufPos) && *(handle->bufPos) == ' '; handle->bufPos++); - if (!*(handle->bufPos)) - return (parseFree(handle)); /* end of data */ - - startPos = handle->bufPos; /* store cmd start */ - for (; handle->cmdPos[cmdIndex][cmdLen] && *(handle->bufPos); handle->bufPos++) { /* no string end? */ - for (;;) { - if (*(handle->bufPos) == handle->cmdPos[cmdIndex][cmdLen]) - break; /* char matches ? */ - else if (memcmp(startPos, (char *) (handle->cmdPos[++cmdIndex]), cmdLen)) - return (parseFree(handle)); /* unknown command */ - - if (cmdIndex >= handle->cmdNum) - return (parseFree(handle)); /* unknown command */ - } - - cmdLen++; /* next char */ - } - - /* Get param. First skip all blanks, then insert zero after param */ - - for (; *(handle->bufPos) && *(handle->bufPos) == ' '; handle->bufPos++); - *param = handle->bufPos; - - for (; *(handle->bufPos) && *(handle->bufPos) != ' '; handle->bufPos++); - *(handle->bufPos++) = 0; - - return (cmdIndex); -} - -void proc_print_scsidevice(Scsi_Device * scd, char *buffer, int *size, int len) -{ - - int x, y = *size; - extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE]; - - y = sprintf(buffer + len, - "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n Vendor: ", - scd->host->host_no, scd->channel, scd->id, scd->lun); - for (x = 0; x < 8; x++) { - if (scd->vendor[x] >= 0x20) - y += sprintf(buffer + len + y, "%c", scd->vendor[x]); - else - y += sprintf(buffer + len + y, " "); - } - y += sprintf(buffer + len + y, " Model: "); - for (x = 0; x < 16; x++) { - if (scd->model[x] >= 0x20) - y += sprintf(buffer + len + y, "%c", scd->model[x]); - else - y += sprintf(buffer + len + y, " "); - } - y += sprintf(buffer + len + y, " Rev: "); - for (x = 0; x < 4; x++) { - if (scd->rev[x] >= 0x20) - y += sprintf(buffer + len + y, "%c", scd->rev[x]); - else - y += sprintf(buffer + len + y, " "); - } - y += sprintf(buffer + len + y, "\n"); - - y += sprintf(buffer + len + y, " Type: %s ", - scd->type < MAX_SCSI_DEVICE_CODE ? - scsi_device_types[(int) scd->type] : "Unknown "); - y += sprintf(buffer + len + y, " ANSI" - " SCSI revision: %02x", (scd->scsi_level - 1) ? scd->scsi_level - 1 : 1); - if (scd->scsi_level == 2) - y += sprintf(buffer + len + y, " CCS\n"); - else - y += sprintf(buffer + len + y, "\n"); - - *size = y; - return; -} - -#else /* if !CONFIG_PROC_FS */ - -void proc_print_scsidevice(Scsi_Device * scd, char *buffer, int *size, int len) -{ -} - -#endif /* CONFIG_PROC_FS */ - -/* - * Overrides for Emacs so that we get a uniform tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/xen/drivers/scsi/scsi_queue.c b/xen/drivers/scsi/scsi_queue.c deleted file mode 100644 index 01e5489e26..0000000000 --- a/xen/drivers/scsi/scsi_queue.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * scsi_queue.c Copyright (C) 1997 Eric Youngdale - * - * generic mid-level SCSI queueing. - * - * The point of this is that we need to track when hosts are unable to - * accept a command because they are busy. In addition, we track devices - * that cannot accept a command because of a QUEUE_FULL condition. In both - * of these cases, we enter the command in the queue. At some later point, - * we attempt to remove commands from the queue and retry them. - */ - -#define __NO_VERSION__ -#include - -#include -#include -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -#include -/* #include */ -/* #include */ -/* #include */ - -#define __KERNEL_SYSCALLS__ - -/*#include */ - -#include -#include -#include - -#include "scsi.h" -#include "hosts.h" -#include "constants.h" - -/* - * TODO: - * 1) Prevent multiple traversals of list to look for commands to - * queue. - * 2) Protect against multiple insertions of list at the same time. - * DONE: - * 1) Set state of scsi command to a new state value for ml queue. - * 2) Insert into queue when host rejects command. - * 3) Make sure status code is properly passed from low-level queue func - * so that internal_cmnd properly returns the right value. - * 4) Insert into queue when QUEUE_FULL. - * 5) Cull queue in bottom half handler. - * 6) Check usage count prior to queue insertion. Requeue if usage - * count is 0. - * 7) Don't send down any more commands if the host/device is busy. - */ - -static const char RCSid[] = "$Header: /mnt/ide/home/eric/CVSROOT/linux/drivers/scsi/scsi_queue.c,v 1.1 1997/10/21 11:16:38 eric Exp $"; - - -/* - * Function: scsi_mlqueue_insert() - * - * Purpose: Insert a command in the midlevel queue. - * - * Arguments: cmd - command that we are adding to queue. - * reason - why we are inserting command to queue. - * - * Lock status: Assumed that lock is not held upon entry. - * - * Returns: Nothing. - * - * Notes: We do this for one of two cases. Either the host is busy - * and it cannot accept any more commands for the time being, - * or the device returned QUEUE_FULL and can accept no more - * commands. - * Notes: This could be called either from an interrupt context or a - * normal process context. - */ -int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason) -{ - struct Scsi_Host *host; - unsigned long flags; - - SCSI_LOG_MLQUEUE(1, printk("Inserting command %p into mlqueue\n", cmd)); - - /* - * We are inserting the command into the ml queue. First, we - * cancel the timer, so it doesn't time out. - */ - scsi_delete_timer(cmd); - - host = cmd->host; - - /* - * Next, set the appropriate busy bit for the device/host. - */ - if (reason == SCSI_MLQUEUE_HOST_BUSY) { - /* - * Protect against race conditions. If the host isn't busy, - * assume that something actually completed, and that we should - * be able to queue a command now. Note that there is an implicit - * assumption that every host can always queue at least one command. - * If a host is inactive and cannot queue any commands, I don't see - * how things could possibly work anyways. - */ - if (host->host_busy == 0) { - if (scsi_retry_command(cmd) == 0) { - return 0; - } - } - host->host_blocked = TRUE; - } else { - /* - * Protect against race conditions. If the device isn't busy, - * assume that something actually completed, and that we should - * be able to queue a command now. Note that there is an implicit - * assumption that every host can always queue at least one command. - * If a host is inactive and cannot queue any commands, I don't see - * how things could possibly work anyways. - */ - if (cmd->device->device_busy == 0) { - if (scsi_retry_command(cmd) == 0) { - return 0; - } - } - cmd->device->device_blocked = TRUE; - } - - /* - * Register the fact that we own the thing for now. - */ - cmd->state = SCSI_STATE_MLQUEUE; - cmd->owner = SCSI_OWNER_MIDLEVEL; - cmd->bh_next = NULL; - - /* - * Decrement the counters, since these commands are no longer - * active on the host/device. - */ - spin_lock_irqsave(&io_request_lock, flags); - cmd->host->host_busy--; - cmd->device->device_busy--; - spin_unlock_irqrestore(&io_request_lock, flags); - - /* - * Insert this command at the head of the queue for it's device. - * It will go before all other commands that are already in the queue. - */ - scsi_insert_special_cmd(cmd, 1); - return 0; -} diff --git a/xen/drivers/scsi/scsi_scan.c b/xen/drivers/scsi/scsi_scan.c deleted file mode 100644 index dbcaa16993..0000000000 --- a/xen/drivers/scsi/scsi_scan.c +++ /dev/null @@ -1,906 +0,0 @@ -/* - * scsi_scan.c Copyright (C) 2000 Eric Youngdale - * - * Bus scan logic. - * - * This used to live in scsi.c, but that file was just a laundry basket - * full of misc stuff. This got separated out in order to make things - * clearer. - */ - -#define __NO_VERSION__ -#include -#include -#include - -#include - -#include "scsi.h" -#include "hosts.h" -#include "constants.h" - -#ifdef CONFIG_KMOD -#include -#endif - -/* - * Flags for irregular SCSI devices that need special treatment - */ -#define BLIST_NOLUN 0x001 /* Don't scan for LUNs */ -#define BLIST_FORCELUN 0x002 /* Known to have LUNs, force sanning */ -#define BLIST_BORKEN 0x004 /* Flag for broken handshaking */ -#define BLIST_KEY 0x008 /* Needs to be unlocked by special command */ -#define BLIST_SINGLELUN 0x010 /* LUNs should better not be used in parallel */ -#define BLIST_NOTQ 0x020 /* Buggy Tagged Command Queuing */ -#define BLIST_SPARSELUN 0x040 /* Non consecutive LUN numbering */ -#define BLIST_MAX5LUN 0x080 /* Avoid LUNS >= 5 */ -#define BLIST_ISDISK 0x100 /* Treat as (removable) disk */ -#define BLIST_ISROM 0x200 /* Treat as (removable) CD-ROM */ -#define BLIST_LARGELUN 0x400 /* LUNs larger than 7 despite reporting as SCSI 2 */ - -static void print_inquiry(unsigned char *data); -static int scan_scsis_single(unsigned int channel, unsigned int dev, - unsigned int lun, int lun0_scsi_level, - unsigned int *max_scsi_dev, unsigned int *sparse_lun, - Scsi_Device ** SDpnt, struct Scsi_Host *shpnt, - char *scsi_result); -static int find_lun0_scsi_level(unsigned int channel, unsigned int dev, - struct Scsi_Host *shpnt); - -struct dev_info { - const char *vendor; - const char *model; - const char *revision; /* Latest revision known to be bad. Not used yet */ - unsigned flags; -}; - -/* - * This is what was previously known as the blacklist. The concept - * has been expanded so that we can specify other types of things we - * need to be aware of. - */ -static struct dev_info device_list[] = -{ -/* The following devices are known not to tolerate a lun != 0 scan for - * one reason or another. Some will respond to all luns, others will - * lock up. - */ - {"Aashima", "IMAGERY 2400SP", "1.03", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ - {"CHINON", "CD-ROM CDS-431", "H42", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ - {"CHINON", "CD-ROM CDS-535", "Q14", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ - {"DENON", "DRD-25X", "V", BLIST_NOLUN}, /* Locks up if probed for lun != 0 */ - {"HITACHI", "DK312C", "CM81", BLIST_NOLUN}, /* Responds to all lun - dtg */ - {"HITACHI", "DK314C", "CR21", BLIST_NOLUN}, /* responds to all lun */ - {"IMS", "CDD521/10", "2.06", BLIST_NOLUN}, /* Locks-up when LUN>0 polled. */ - {"MAXTOR", "XT-3280", "PR02", BLIST_NOLUN}, /* Locks-up when LUN>0 polled. */ - {"MAXTOR", "XT-4380S", "B3C", BLIST_NOLUN}, /* Locks-up when LUN>0 polled. */ - {"MAXTOR", "MXT-1240S", "I1.2", BLIST_NOLUN}, /* Locks up when LUN>0 polled */ - {"MAXTOR", "XT-4170S", "B5A", BLIST_NOLUN}, /* Locks-up sometimes when LUN>0 polled. */ - {"MAXTOR", "XT-8760S", "B7B", BLIST_NOLUN}, /* guess what? */ - {"MEDIAVIS", "RENO CD-ROMX2A", "2.03", BLIST_NOLUN}, /*Responds to all lun */ - {"NEC", "CD-ROM DRIVE:841", "1.0", BLIST_NOLUN}, /* Locks-up when LUN>0 polled. */ - {"PHILIPS", "PCA80SC", "V4-2", BLIST_NOLUN}, /* Responds to all lun */ - {"RODIME", "RO3000S", "2.33", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ - {"SANYO", "CRD-250S", "1.20", BLIST_NOLUN}, /* causes failed REQUEST SENSE on lun 1 - * for aha152x controller, which causes - * SCSI code to reset bus.*/ - {"SEAGATE", "ST157N", "\004|j", BLIST_NOLUN}, /* causes failed REQUEST SENSE on lun 1 - * for aha152x controller, which causes - * SCSI code to reset bus.*/ - {"SEAGATE", "ST296", "921", BLIST_NOLUN}, /* Responds to all lun */ - {"SEAGATE", "ST1581", "6538", BLIST_NOLUN}, /* Responds to all lun */ - {"SONY", "CD-ROM CDU-541", "4.3d", BLIST_NOLUN}, - {"SONY", "CD-ROM CDU-55S", "1.0i", BLIST_NOLUN}, - {"SONY", "CD-ROM CDU-561", "1.7x", BLIST_NOLUN}, - {"SONY", "CD-ROM CDU-8012", "*", BLIST_NOLUN}, - {"TANDBERG", "TDC 3600", "U07", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ - {"TEAC", "CD-R55S", "1.0H", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ - {"TEAC", "CD-ROM", "1.06", BLIST_NOLUN}, /* causes failed REQUEST SENSE on lun 1 - * for seagate controller, which causes - * SCSI code to reset bus.*/ - {"TEAC", "MT-2ST/45S2-27", "RV M", BLIST_NOLUN}, /* Responds to all lun */ - {"TEXEL", "CD-ROM", "1.06", BLIST_NOLUN}, /* causes failed REQUEST SENSE on lun 1 - * for seagate controller, which causes - * SCSI code to reset bus.*/ - {"QUANTUM", "LPS525S", "3110", BLIST_NOLUN}, /* Locks sometimes if polled for lun != 0 */ - {"QUANTUM", "PD1225S", "3110", BLIST_NOLUN}, /* Locks sometimes if polled for lun != 0 */ - {"QUANTUM", "FIREBALL ST4.3S", "0F0C", BLIST_NOLUN}, /* Locks up when polled for lun != 0 */ - {"MEDIAVIS", "CDR-H93MV", "1.31", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ - {"SANKYO", "CP525", "6.64", BLIST_NOLUN}, /* causes failed REQ SENSE, extra reset */ - {"HP", "C1750A", "3226", BLIST_NOLUN}, /* scanjet iic */ - {"HP", "C1790A", "", BLIST_NOLUN}, /* scanjet iip */ - {"HP", "C2500A", "", BLIST_NOLUN}, /* scanjet iicx */ - {"HP", "A6188A", "*", BLIST_SPARSELUN}, /* HP Va7100 Array */ - {"HP", "A6189A", "*", BLIST_SPARSELUN}, /* HP Va7400 Array */ - {"HP", "A6189B", "*", BLIST_SPARSELUN}, /* HP Va7410 Array */ - {"HP", "OPEN-", "*", BLIST_SPARSELUN}, /* HP XP Arrays */ - {"YAMAHA", "CDR100", "1.00", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ - {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* Locks up if polled for lun != 0 - * extra reset */ - {"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ - {"YAMAHA", "CRW6416S", "1.0c", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ - {"MITSUMI", "CD-R CR-2201CS", "6119", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ - {"RELISYS", "Scorpio", "*", BLIST_NOLUN}, /* responds to all LUN */ - {"RELISYS", "VM3530+", "*", BLIST_NOLUN}, /* responds to all LUN */ - {"ACROSS", "", "*", BLIST_NOLUN}, /* responds to all LUN */ - {"MICROTEK", "ScanMaker II", "5.61", BLIST_NOLUN}, /* responds to all LUN */ - -/* - * Other types of devices that have special flags. - */ - {"SONY", "CD-ROM CDU-8001", "*", BLIST_BORKEN}, - {"TEXEL", "CD-ROM", "1.06", BLIST_BORKEN}, - {"IOMEGA", "Io20S *F", "*", BLIST_KEY}, - {"INSITE", "Floptical F*8I", "*", BLIST_KEY}, - {"INSITE", "I325VM", "*", BLIST_KEY}, - {"LASOUND","CDX7405","3.10", BLIST_MAX5LUN | BLIST_SINGLELUN}, - {"MICROP", "4110", "*", BLIST_NOTQ}, /* Buggy Tagged Queuing */ - {"NRC", "MBR-7", "*", BLIST_FORCELUN | BLIST_SINGLELUN}, - {"NRC", "MBR-7.4", "*", BLIST_FORCELUN | BLIST_SINGLELUN}, - {"REGAL", "CDC-4X", "*", BLIST_MAX5LUN | BLIST_SINGLELUN}, - {"NAKAMICH", "MJ-4.8S", "*", BLIST_FORCELUN | BLIST_SINGLELUN}, - {"NAKAMICH", "MJ-5.16S", "*", BLIST_FORCELUN | BLIST_SINGLELUN}, - {"PIONEER", "CD-ROM DRM-600", "*", BLIST_FORCELUN | BLIST_SINGLELUN}, - {"PIONEER", "CD-ROM DRM-602X", "*", BLIST_FORCELUN | BLIST_SINGLELUN}, - {"PIONEER", "CD-ROM DRM-604X", "*", BLIST_FORCELUN | BLIST_SINGLELUN}, - {"EMULEX", "MD21/S2 ESDI", "*", BLIST_SINGLELUN}, - {"CANON", "IPUBJD", "*", BLIST_SPARSELUN}, - {"nCipher", "Fastness Crypto", "*", BLIST_FORCELUN}, - {"DEC","HSG80","*", BLIST_FORCELUN}, - {"COMPAQ","LOGICAL VOLUME","*", BLIST_FORCELUN}, - {"COMPAQ","CR3500","*", BLIST_FORCELUN}, - {"NEC", "PD-1 ODX654P", "*", BLIST_FORCELUN | BLIST_SINGLELUN}, - {"MATSHITA", "PD-1", "*", BLIST_FORCELUN | BLIST_SINGLELUN}, - {"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN}, - {"TOSHIBA","CDROM","*", BLIST_ISROM}, - {"TOSHIBA","CD-ROM","*", BLIST_ISROM}, - {"MegaRAID", "LD", "*", BLIST_FORCELUN}, - {"DGC", "RAID", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, // Dell PV 650F (tgt @ LUN 0) - {"DGC", "DISK", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, // Dell PV 650F (no tgt @ LUN 0) - {"DELL", "PV660F", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"DELL", "PV660F PSEUDO", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"DELL", "PSEUDO DEVICE .", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, // Dell PV 530F - {"DELL", "PV530F", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, // Dell PV 530F - {"EMC", "SYMMETRIX", "*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN}, - {"HP", "A6189A", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, // HP VA7400, by Alar Aun - {"CMD", "CRA-7280", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, // CMD RAID Controller - {"CNSI", "G7324", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, // Chaparral G7324 RAID - {"CNSi", "G8324", "*", BLIST_SPARSELUN}, // Chaparral G8324 RAID - {"Zzyzx", "RocketStor 500S", "*", BLIST_SPARSELUN}, - {"Zzyzx", "RocketStor 2000", "*", BLIST_SPARSELUN}, - {"SONY", "TSL", "*", BLIST_FORCELUN}, // DDS3 & DDS4 autoloaders - {"DELL", "PERCRAID", "*", BLIST_FORCELUN}, - {"HP", "NetRAID-4M", "*", BLIST_FORCELUN}, - {"ADAPTEC", "AACRAID", "*", BLIST_FORCELUN}, - {"ADAPTEC", "Adaptec 5400S", "*", BLIST_FORCELUN}, - {"COMPAQ", "MSA1000", "*", BLIST_FORCELUN}, - {"HP", "C1557A", "*", BLIST_FORCELUN}, - {"IBM", "AuSaV1S2", "*", BLIST_FORCELUN}, - {"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"DDN", "SAN DataDirector", "*", BLIST_SPARSELUN}, - {"HITACHI", "DF400", "*", BLIST_SPARSELUN}, - {"HITACHI", "DF500", "*", BLIST_SPARSELUN}, - {"HITACHI", "DF600", "*", BLIST_SPARSELUN}, - - /* - * Must be at end of list... - */ - {NULL, NULL, NULL} -}; - -#define MAX_SCSI_LUNS 0xFFFFFFFF - -#ifdef CONFIG_SCSI_MULTI_LUN -static unsigned int max_scsi_luns = MAX_SCSI_LUNS; -#else -static unsigned int max_scsi_luns = 1; -#endif - -#ifdef MODULE - -MODULE_PARM(max_scsi_luns, "i"); -MODULE_PARM_DESC(max_scsi_luns, "last scsi LUN (should be between 1 and 2^32-1)"); - -#else - -static int __init scsi_luns_setup(char *str) -{ -#if 0 - unsigned int tmp; - - if (get_option(&str, &tmp) == 1) { - max_scsi_luns = tmp; - return 1; - } else { - printk("scsi_luns_setup : usage max_scsi_luns=n " - "(n should be between 1 and 2^32-1)\n"); - return 0; - } -#else - return 0; -#endif -} - -__setup("max_scsi_luns=", scsi_luns_setup); - -#endif - -static void print_inquiry(unsigned char *data) -{ - int i; - - printk(" Vendor: "); - for (i = 8; i < 16; i++) { - if (data[i] >= 0x20 && i < data[4] + 5) - printk("%c", data[i]); - else - printk(" "); - } - - printk(" Model: "); - for (i = 16; i < 32; i++) { - if (data[i] >= 0x20 && i < data[4] + 5) - printk("%c", data[i]); - else - printk(" "); - } - - printk(" Rev: "); - for (i = 32; i < 36; i++) { - if (data[i] >= 0x20 && i < data[4] + 5) - printk("%c", data[i]); - else - printk(" "); - } - - printk("\n"); - - i = data[0] & 0x1f; - - printk(" Type: %s ", - i < MAX_SCSI_DEVICE_CODE ? scsi_device_types[i] : "Unknown "); - printk(" ANSI SCSI revision: %02x", data[2] & 0x07); - if ((data[2] & 0x07) == 1 && (data[3] & 0x0f) == 1) - printk(" CCS\n"); - else - printk("\n"); -} - -static int get_device_flags(unsigned char *response_data) -{ - int i = 0; - unsigned char *pnt; - for (i = 0; 1; i++) { - if (device_list[i].vendor == NULL) - return 0; - pnt = &response_data[8]; - while (*pnt && *pnt == ' ') - pnt++; - if (memcmp(device_list[i].vendor, pnt, - strlen(device_list[i].vendor))) - continue; - pnt = &response_data[16]; - while (*pnt && *pnt == ' ') - pnt++; - if (memcmp(device_list[i].model, pnt, - strlen(device_list[i].model))) - continue; - return device_list[i].flags; - } - return 0; -} - -/* - * Detecting SCSI devices : - * We scan all present host adapter's busses, from ID 0 to ID (max_id). - * We use the INQUIRY command, determine device type, and pass the ID / - * lun address of all sequential devices to the tape driver, all random - * devices to the disk driver. - */ -void scan_scsis(struct Scsi_Host *shpnt, - uint hardcoded, - uint hchannel, - uint hid, - uint hlun) -{ - uint channel; - unsigned int dev; - unsigned int lun; - unsigned int max_dev_lun; - unsigned char *scsi_result; - unsigned char scsi_result0[256]; - Scsi_Device *SDpnt; - Scsi_Device *SDtail; - unsigned int sparse_lun; - int lun0_sl; - - scsi_result = NULL; - - SDpnt = (Scsi_Device *) kmalloc(sizeof(Scsi_Device), - GFP_ATOMIC); - if (SDpnt) { - memset(SDpnt, 0, sizeof(Scsi_Device)); - /* - * Register the queue for the device. All I/O requests will - * come in through here. We also need to register a pointer to - * ourselves, since the queue handler won't know what device - * the queue actually represents. We could look it up, but it - * is pointless work. - */ - scsi_initialize_queue(SDpnt, shpnt); - SDpnt->request_queue.queuedata = (void *) SDpnt; - /* Make sure we have something that is valid for DMA purposes */ - scsi_result = ((!shpnt->unchecked_isa_dma) - ? &scsi_result0[0] : kmalloc(512, GFP_DMA)); - } - - if (scsi_result == NULL) { - printk("Unable to obtain scsi_result buffer\n"); - goto leave; - } - /* - * We must chain ourself in the host_queue, so commands can time out - */ - SDpnt->queue_depth = 1; - SDpnt->host = shpnt; - SDpnt->online = TRUE; - - initialize_merge_fn(SDpnt); - -#if 0 - /* - * Initialize the object that we will use to wait for command blocks. - */ - init_waitqueue_head(&SDpnt->scpnt_wait); -#endif - - /* - * Next, hook the device to the host in question. - */ - SDpnt->prev = NULL; - SDpnt->next = NULL; - if (shpnt->host_queue != NULL) { - SDtail = shpnt->host_queue; - while (SDtail->next != NULL) - SDtail = SDtail->next; - - SDtail->next = SDpnt; - SDpnt->prev = SDtail; - } else { - shpnt->host_queue = SDpnt; - } - - /* - * We need to increment the counter for this one device so we can track - * when things are quiet. - */ - if (hardcoded == 1) { - Scsi_Device *oldSDpnt = SDpnt; - struct Scsi_Device_Template *sdtpnt; - channel = hchannel; - if (channel > shpnt->max_channel) - goto leave; - dev = hid; - if (dev >= shpnt->max_id) - goto leave; - lun = hlun; - if (lun >= shpnt->max_lun) - goto leave; - if ((0 == lun) || (lun > 7)) - lun0_sl = SCSI_3; /* actually don't care for 0 == lun */ - else - lun0_sl = find_lun0_scsi_level(channel, dev, shpnt); - scan_scsis_single(channel, dev, lun, lun0_sl, &max_dev_lun, - &sparse_lun, &SDpnt, shpnt, scsi_result); - if (SDpnt != oldSDpnt) { - - /* it could happen the blockdevice hasn't yet been inited */ - /* queue_depth() moved from scsi_proc_info() so that - it is called before scsi_build_commandblocks() */ - if (shpnt->select_queue_depths != NULL) - (shpnt->select_queue_depths)(shpnt, - shpnt->host_queue); - - for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if (sdtpnt->init && sdtpnt->dev_noticed) - (*sdtpnt->init) (); - - for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) { - if (sdtpnt->attach) { - (*sdtpnt->attach) (oldSDpnt); - if (oldSDpnt->attached) { - scsi_build_commandblocks(oldSDpnt); - if (0 == oldSDpnt->has_cmdblocks) { - printk("scan_scsis: DANGER, no command blocks\n"); - /* What to do now ?? */ - } - } - } - } - scsi_resize_dma_pool(); - - for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) { - if (sdtpnt->finish && sdtpnt->nr_dev) { - (*sdtpnt->finish) (); - } - } - } - } else { - /* Actual LUN. PC ordering is 0->n IBM/spec ordering is n->0 */ - int order_dev; - - for (channel = 0; channel <= shpnt->max_channel; channel++) { - for (dev = 0; dev < shpnt->max_id; ++dev) { - if (shpnt->reverse_ordering) - /* Shift to scanning 15,14,13... or 7,6,5,4, */ - order_dev = shpnt->max_id - dev - 1; - else - order_dev = dev; - - if (shpnt->this_id != order_dev) { - - /* - * We need the for so our continue, etc. work fine. We put this in - * a variable so that we can override it during the scan if we - * detect a device *KNOWN* to have multiple logical units. - */ - max_dev_lun = (max_scsi_luns < shpnt->max_lun ? - max_scsi_luns : shpnt->max_lun); - sparse_lun = 0; - for (lun = 0, lun0_sl = SCSI_2; lun < max_dev_lun; ++lun) { - /* don't probe further for luns > 7 for targets <= SCSI_2 */ - if ((lun0_sl < SCSI_3) && (lun > 7)) - break; - - if (!scan_scsis_single(channel, order_dev, lun, lun0_sl, - &max_dev_lun, &sparse_lun, &SDpnt, shpnt, - scsi_result) - && !sparse_lun) - break; /* break means don't probe further for luns!=0 */ - if (SDpnt && (0 == lun)) { - int bflags = get_device_flags (scsi_result); - if (bflags & BLIST_LARGELUN) - lun0_sl = SCSI_3; /* treat as SCSI 3 */ - else - lun0_sl = SDpnt->scsi_level; - } - } /* for lun ends */ - } /* if this_id != id ends */ - } /* for dev ends */ - } /* for channel ends */ - } /* if/else hardcoded */ - - leave: - - { /* Unchain SRpnt from host_queue */ - Scsi_Device *prev, *next; - Scsi_Device *dqptr; - - for (dqptr = shpnt->host_queue; dqptr != SDpnt; dqptr = dqptr->next) - continue; - if (dqptr) { - prev = dqptr->prev; - next = dqptr->next; - if (prev) - prev->next = next; - else - shpnt->host_queue = next; - if (next) - next->prev = prev; - } - } - - /* Last device block does not exist. Free memory. */ - if (SDpnt != NULL) { - blk_cleanup_queue(&SDpnt->request_queue); - kfree((char *) SDpnt); - } - - /* If we allocated a buffer so we could do DMA, free it now */ - if (scsi_result != &scsi_result0[0] && scsi_result != NULL) { - kfree(scsi_result); - } { - Scsi_Device *sdev; - Scsi_Cmnd *scmd; - - SCSI_LOG_SCAN_BUS(4, printk("Host status for host %p:\n", shpnt)); - for (sdev = shpnt->host_queue; sdev; sdev = sdev->next) { - SCSI_LOG_SCAN_BUS(4, printk("Device %d %p: ", sdev->id, sdev)); - for (scmd = sdev->device_queue; scmd; scmd = scmd->next) { - SCSI_LOG_SCAN_BUS(4, printk("%p ", scmd)); - } - SCSI_LOG_SCAN_BUS(4, printk("\n")); - } - } -} - -/* - * The worker for scan_scsis. - * Returning 0 means Please don't ask further for lun!=0, 1 means OK go on. - * Global variables used : scsi_devices(linked list) - */ -static int scan_scsis_single(unsigned int channel, unsigned int dev, - unsigned int lun, int lun0_scsi_level, - unsigned int *max_dev_lun, unsigned int *sparse_lun, - Scsi_Device ** SDpnt2, struct Scsi_Host *shpnt, - char *scsi_result) -{ - char devname[64]; - unsigned char scsi_cmd[MAX_COMMAND_SIZE]; - struct Scsi_Device_Template *sdtpnt; - Scsi_Device *SDtail, *SDpnt = *SDpnt2; - Scsi_Request * SRpnt; - int bflags, type = -1; -#ifdef DEVFS_MUST_DIE - extern devfs_handle_t scsi_devfs_handle; -#endif - int scsi_level; - - SDpnt->host = shpnt; - SDpnt->id = dev; - SDpnt->lun = lun; - SDpnt->channel = channel; - SDpnt->online = TRUE; - - scsi_build_commandblocks(SDpnt); - - /* Some low level driver could use device->type (DB) */ - SDpnt->type = -1; - - /* - * Assume that the device will have handshaking problems, and then fix - * this field later if it turns out it doesn't - */ - SDpnt->borken = 1; - SDpnt->was_reset = 0; - SDpnt->expecting_cc_ua = 0; - SDpnt->starved = 0; - - if (NULL == (SRpnt = scsi_allocate_request(SDpnt))) { - printk("scan_scsis_single: no memory\n"); - return 0; - } - - /* - * We used to do a TEST_UNIT_READY before the INQUIRY but that was - * not really necessary. Spec recommends using INQUIRY to scan for - * devices (and TEST_UNIT_READY to poll for media change). - Paul G. - */ - - SCSI_LOG_SCAN_BUS(3, printk("scsi: performing INQUIRY\n")); - /* - * Build an INQUIRY command block. - */ - scsi_cmd[0] = INQUIRY; - if ((lun > 0) && (lun0_scsi_level <= SCSI_2)) - scsi_cmd[1] = (lun << 5) & 0xe0; - else - scsi_cmd[1] = 0; /* SCSI_3 and higher, don't touch */ - scsi_cmd[2] = 0; - scsi_cmd[3] = 0; - scsi_cmd[4] = 255; - scsi_cmd[5] = 0; - SRpnt->sr_cmd_len = 0; - SRpnt->sr_data_direction = SCSI_DATA_READ; - - scsi_wait_req (SRpnt, (void *) scsi_cmd, - (void *) scsi_result, - 256, SCSI_TIMEOUT+4*HZ, 3); - - SCSI_LOG_SCAN_BUS(3, printk("scsi: INQUIRY %s with code 0x%x\n", - SRpnt->sr_result ? "failed" : "successful", SRpnt->sr_result)); - - /* - * Now that we don't do TEST_UNIT_READY anymore, we must be prepared - * for media change conditions here, so cannot require zero result. - */ - if (SRpnt->sr_result) { - if ((driver_byte(SRpnt->sr_result) & DRIVER_SENSE) != 0 && - (SRpnt->sr_sense_buffer[2] & 0xf) == UNIT_ATTENTION && - SRpnt->sr_sense_buffer[12] == 0x28 && - SRpnt->sr_sense_buffer[13] == 0) { - /* not-ready to ready transition - good */ - } else { - /* assume no peripheral if any other sort of error */ - scsi_release_request(SRpnt); - return 0; - } - } - - /* - * Check for SPARSELUN before checking the peripheral qualifier, - * so sparse lun devices are completely scanned. - */ - - /* - * Get any flags for this device. - */ - bflags = get_device_flags (scsi_result); - - if (bflags & BLIST_SPARSELUN) { - *sparse_lun = 1; - } - /* - * Check the peripheral qualifier field - this tells us whether LUNS - * are supported here or not. - */ - if ((scsi_result[0] >> 5) == 3) { - scsi_release_request(SRpnt); - return 0; /* assume no peripheral if any sort of error */ - } - /* The Toshiba ROM was "gender-changed" here as an inline hack. - This is now much more generic. - This is a mess: What we really want is to leave the scsi_result - alone, and just change the SDpnt structure. And the SDpnt is what - we want print_inquiry to print. -- REW - */ - if (bflags & BLIST_ISDISK) { - scsi_result[0] = TYPE_DISK; - scsi_result[1] |= 0x80; /* removable */ - } - - if (bflags & BLIST_ISROM) { - scsi_result[0] = TYPE_ROM; - scsi_result[1] |= 0x80; /* removable */ - } - - memcpy(SDpnt->vendor, scsi_result + 8, 8); - memcpy(SDpnt->model, scsi_result + 16, 16); - memcpy(SDpnt->rev, scsi_result + 32, 4); - - SDpnt->removable = (0x80 & scsi_result[1]) >> 7; - /* Use the peripheral qualifier field to determine online/offline */ - if (((scsi_result[0] >> 5) & 7) == 1) SDpnt->online = FALSE; - else SDpnt->online = TRUE; - SDpnt->lockable = SDpnt->removable; - SDpnt->changed = 0; - SDpnt->access_count = 0; - SDpnt->busy = 0; - SDpnt->has_cmdblocks = 0; - /* - * Currently, all sequential devices are assumed to be tapes, all random - * devices disk, with the appropriate read only flags set for ROM / WORM - * treated as RO. - */ - switch (type = (scsi_result[0] & 0x1f)) { - case TYPE_TAPE: - case TYPE_DISK: - case TYPE_PRINTER: - case TYPE_MOD: - case TYPE_PROCESSOR: - case TYPE_SCANNER: - case TYPE_MEDIUM_CHANGER: - case TYPE_ENCLOSURE: - case TYPE_COMM: - SDpnt->writeable = 1; - break; - case TYPE_WORM: - case TYPE_ROM: - SDpnt->writeable = 0; - break; - default: - printk("scsi: unknown type %d\n", type); - } - - SDpnt->device_blocked = FALSE; - SDpnt->device_busy = 0; - SDpnt->single_lun = 0; - SDpnt->soft_reset = - (scsi_result[7] & 1) && ((scsi_result[3] & 7) == 2); - SDpnt->random = (type == TYPE_TAPE) ? 0 : 1; - SDpnt->type = (type & 0x1f); - - print_inquiry(scsi_result); - - sprintf (devname, "host%d/bus%d/target%d/lun%d", - SDpnt->host->host_no, SDpnt->channel, SDpnt->id, SDpnt->lun); -#ifdef DEVFS_MUST_DIE - if (SDpnt->de) printk ("DEBUG: dir: \"%s\" already exists\n", devname); - else SDpnt->de = devfs_mk_dir (scsi_devfs_handle, devname, NULL); -#endif - - for (sdtpnt = scsi_devicelist; sdtpnt; - sdtpnt = sdtpnt->next) - if (sdtpnt->detect) - SDpnt->attached += - (*sdtpnt->detect) (SDpnt); - - SDpnt->scsi_level = scsi_result[2] & 0x07; - if (SDpnt->scsi_level >= 2 || - (SDpnt->scsi_level == 1 && - (scsi_result[3] & 0x0f) == 1)) - SDpnt->scsi_level++; - scsi_level = SDpnt->scsi_level; - - /* - * Accommodate drivers that want to sleep when they should be in a polling - * loop. - */ - SDpnt->disconnect = 0; - - - /* - * Set the tagged_queue flag for SCSI-II devices that purport to support - * tagged queuing in the INQUIRY data. - */ - SDpnt->tagged_queue = 0; - if ((SDpnt->scsi_level >= SCSI_2) && - (scsi_result[7] & 2) && - !(bflags & BLIST_NOTQ)) { - SDpnt->tagged_supported = 1; - SDpnt->current_tag = 0; - } - /* - * Some revisions of the Texel CD ROM drives have handshaking problems when - * used with the Seagate controllers. Before we know what type of device - * we're talking to, we assume it's borken and then change it here if it - * turns out that it isn't a TEXEL drive. - */ - if ((bflags & BLIST_BORKEN) == 0) - SDpnt->borken = 0; - - /* - * If we want to only allow I/O to one of the luns attached to this device - * at a time, then we set this flag. - */ - if (bflags & BLIST_SINGLELUN) - SDpnt->single_lun = 1; - - /* - * These devices need this "key" to unlock the devices so we can use it - */ - if ((bflags & BLIST_KEY) != 0) { - printk("Unlocked floptical drive.\n"); - SDpnt->lockable = 0; - scsi_cmd[0] = MODE_SENSE; - if (shpnt->max_lun <= 8) - scsi_cmd[1] = (lun << 5) & 0xe0; - else scsi_cmd[1] = 0; /* any other idea? */ - scsi_cmd[2] = 0x2e; - scsi_cmd[3] = 0; - scsi_cmd[4] = 0x2a; - scsi_cmd[5] = 0; - SRpnt->sr_cmd_len = 0; - SRpnt->sr_data_direction = SCSI_DATA_READ; - scsi_wait_req (SRpnt, (void *) scsi_cmd, - (void *) scsi_result, 0x2a, - SCSI_TIMEOUT, 3); - } - - scsi_release_request(SRpnt); - SRpnt = NULL; - - scsi_release_commandblocks(SDpnt); - - /* - * This device was already hooked up to the host in question, - * so at this point we just let go of it and it should be fine. We do need to - * allocate a new one and attach it to the host so that we can further scan the bus. - */ - SDpnt = (Scsi_Device *) kmalloc(sizeof(Scsi_Device), GFP_ATOMIC); - if (!SDpnt) { - printk("scsi: scan_scsis_single: Cannot malloc\n"); - return 0; - } - memset(SDpnt, 0, sizeof(Scsi_Device)); - - *SDpnt2 = SDpnt; - SDpnt->queue_depth = 1; - SDpnt->host = shpnt; - SDpnt->online = TRUE; - SDpnt->scsi_level = scsi_level; - - /* - * Register the queue for the device. All I/O requests will come - * in through here. We also need to register a pointer to - * ourselves, since the queue handler won't know what device - * the queue actually represents. We could look it up, but it - * is pointless work. - */ - scsi_initialize_queue(SDpnt, shpnt); - SDpnt->host = shpnt; - initialize_merge_fn(SDpnt); - - /* - * Mark this device as online, or otherwise we won't be able to do much with it. - */ - SDpnt->online = TRUE; - -#if 0 - /* - * Initialize the object that we will use to wait for command blocks. - */ - init_waitqueue_head(&SDpnt->scpnt_wait); -#endif - - /* - * Since we just found one device, there had damn well better be one in the list - * already. - */ - if (shpnt->host_queue == NULL) - panic("scan_scsis_single: Host queue == NULL\n"); - - SDtail = shpnt->host_queue; - while (SDtail->next) { - SDtail = SDtail->next; - } - - /* Add this device to the linked list at the end */ - SDtail->next = SDpnt; - SDpnt->prev = SDtail; - SDpnt->next = NULL; - - /* - * Some scsi devices cannot be polled for lun != 0 due to firmware bugs - */ - if (bflags & BLIST_NOLUN) - return 0; /* break; */ - - /* - * If this device is known to support sparse multiple units, override the - * other settings, and scan all of them. - */ - if (bflags & BLIST_SPARSELUN) { - *max_dev_lun = shpnt->max_lun; - *sparse_lun = 1; - return 1; - } - /* - * If this device is known to support multiple units, override the other - * settings, and scan all of them. - */ - if (bflags & BLIST_FORCELUN) { - /* - * Scanning MAX_SCSI_LUNS units would be a bad idea. - * Any better idea? - * I think we need REPORT LUNS in future to avoid scanning - * of unused LUNs. But, that is another item. - */ - if (*max_dev_lun < shpnt->max_lun) - *max_dev_lun = shpnt->max_lun; - else if ((max_scsi_luns >> 1) >= *max_dev_lun) - *max_dev_lun += shpnt->max_lun; - else *max_dev_lun = max_scsi_luns; - return 1; - } - /* - * REGAL CDC-4X: avoid hang after LUN 4 - */ - if (bflags & BLIST_MAX5LUN) { - *max_dev_lun = 5; - return 1; - } - - /* - * We assume the device can't handle lun!=0 if: - it reports scsi-0 - * (ANSI SCSI Revision 0) (old drives like MAXTOR XT-3280) or - it - * reports scsi-1 (ANSI SCSI Revision 1) and Response Data Format 0 - */ - if (((scsi_result[2] & 0x07) == 0) - || - ((scsi_result[2] & 0x07) == 1 && - (scsi_result[3] & 0x0f) == 0)) - return 0; - return 1; -} - -/* - * The worker for scan_scsis. - * Returns the scsi_level of lun0 on this host, channel and dev (if already - * known), otherwise returns SCSI_2. - */ -static int find_lun0_scsi_level(unsigned int channel, unsigned int dev, - struct Scsi_Host *shpnt) -{ - int res = SCSI_2; - Scsi_Device *SDpnt; - - for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next) - { - if ((0 == SDpnt->lun) && (dev == SDpnt->id) && - (channel == SDpnt->channel)) - return (int)SDpnt->scsi_level; - } - /* haven't found lun0, should send INQUIRY but take easy route */ - return res; -} diff --git a/xen/drivers/scsi/scsi_syms.c b/xen/drivers/scsi/scsi_syms.c deleted file mode 100644 index 50397a0d89..0000000000 --- a/xen/drivers/scsi/scsi_syms.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * We should not even be trying to compile this if we are not doing - * a module. - */ -#define __NO_VERSION__ -#include -#include - -#include -#include -/* #include */ -/* #include */ -/* #include */ -/* #include */ -#include -/* #include */ - -#include -#include -#include - -#include "scsi.h" -#include -#include "hosts.h" -#include "constants.h" - -#include "sd.h" -#include - -/* - * This source file contains the symbol table used by scsi loadable - * modules. - */ -EXPORT_SYMBOL(scsi_register_module); -EXPORT_SYMBOL(scsi_unregister_module); -EXPORT_SYMBOL(scsi_free); -EXPORT_SYMBOL(scsi_malloc); -EXPORT_SYMBOL(scsi_register); -EXPORT_SYMBOL(scsi_unregister); -EXPORT_SYMBOL(scsicam_bios_param); -EXPORT_SYMBOL(scsi_partsize); -EXPORT_SYMBOL(scsi_allocate_device); -EXPORT_SYMBOL(scsi_do_cmd); -EXPORT_SYMBOL(scsi_command_size); -EXPORT_SYMBOL(scsi_ioctl); -EXPORT_SYMBOL(print_command); -EXPORT_SYMBOL(print_sense); -EXPORT_SYMBOL(print_req_sense); -EXPORT_SYMBOL(print_msg); -EXPORT_SYMBOL(print_status); -EXPORT_SYMBOL(scsi_dma_free_sectors); -EXPORT_SYMBOL(kernel_scsi_ioctl); -EXPORT_SYMBOL(scsi_need_isa_buffer); -EXPORT_SYMBOL(scsi_release_command); -EXPORT_SYMBOL(print_Scsi_Cmnd); -EXPORT_SYMBOL(scsi_block_when_processing_errors); -EXPORT_SYMBOL(scsi_mark_host_reset); -EXPORT_SYMBOL(scsi_ioctl_send_command); -#if defined(CONFIG_SCSI_LOGGING) /* { */ -EXPORT_SYMBOL(scsi_logging_level); -#endif - -EXPORT_SYMBOL(scsi_allocate_request); -EXPORT_SYMBOL(scsi_release_request); -EXPORT_SYMBOL(scsi_wait_req); -EXPORT_SYMBOL(scsi_do_req); - -EXPORT_SYMBOL(scsi_report_bus_reset); -EXPORT_SYMBOL(scsi_block_requests); -EXPORT_SYMBOL(scsi_unblock_requests); - -EXPORT_SYMBOL(scsi_get_host_dev); -EXPORT_SYMBOL(scsi_free_host_dev); - -EXPORT_SYMBOL(scsi_sleep); - -EXPORT_SYMBOL(proc_print_scsidevice); -EXPORT_SYMBOL(proc_scsi); - -EXPORT_SYMBOL(scsi_io_completion); -EXPORT_SYMBOL(scsi_end_request); - -EXPORT_SYMBOL(scsi_register_blocked_host); -EXPORT_SYMBOL(scsi_deregister_blocked_host); - -/* - * This symbol is for the highlevel drivers (e.g. sg) only. - */ -EXPORT_SYMBOL(scsi_reset_provider); - -/* - * These are here only while I debug the rest of the scsi stuff. - */ -EXPORT_SYMBOL(scsi_hostlist); -EXPORT_SYMBOL(scsi_hosts); -EXPORT_SYMBOL(scsi_devicelist); -EXPORT_SYMBOL(scsi_device_types); - -/* - * Externalize timers so that HBAs can safely start/restart commands. - */ -EXPORT_SYMBOL(scsi_add_timer); -EXPORT_SYMBOL(scsi_delete_timer); diff --git a/xen/drivers/scsi/scsicam.c b/xen/drivers/scsi/scsicam.c deleted file mode 100644 index dce5cf0c48..0000000000 --- a/xen/drivers/scsi/scsicam.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * scsicam.c - SCSI CAM support functions, use for HDIO_GETGEO, etc. - * - * Copyright 1993, 1994 Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@Colorado.EDU - * +1 (303) 786-7975 - * - * For more information, please consult the SCSI-CAM draft. - */ - -#define __NO_VERSION__ - -#include -#include - - -/*#include */ -/*#include */ -#include -/*#include */ -#include -#include "scsi.h" -#include "hosts.h" -#include "sd.h" -#include - -static int setsize(unsigned long capacity, unsigned int *cyls, unsigned int *hds, - unsigned int *secs); - - -/* - * Function : int scsicam_bios_param (Disk *disk, int dev, int *ip) - * - * Purpose : to determine the BIOS mapping used for a drive in a - * SCSI-CAM system, storing the results in ip as required - * by the HDIO_GETGEO ioctl(). - * - * Returns : -1 on failure, 0 on success. - * - */ - -int scsicam_bios_param(Disk * disk, /* SCSI disk */ - kdev_t dev, /* Device major, minor */ - int *ip /* Heads, sectors, cylinders in that order */ ) -{ - struct buffer_head *bh; - int ret_code; - int size = disk->capacity; - unsigned long temp_cyl; - -#if 0 - if (!(bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, block_size(dev)))) - return -1; -#else - bh = NULL; - printk("scsicam_bios_param: bread not avail!\n"); - BUG(); -#endif - - /* try to infer mapping from partition table */ - ret_code = scsi_partsize(bh, (unsigned long) size, (unsigned int *) ip + 2, - (unsigned int *) ip + 0, (unsigned int *) ip + 1); -#if 0 - brelse(bh); -#endif - - if (ret_code == -1) { - /* pick some standard mapping with at most 1024 cylinders, - and at most 62 sectors per track - this works up to - 7905 MB */ - ret_code = setsize((unsigned long) size, (unsigned int *) ip + 2, - (unsigned int *) ip + 0, (unsigned int *) ip + 1); - } - /* if something went wrong, then apparently we have to return - a geometry with more than 1024 cylinders */ - if (ret_code || ip[0] > 255 || ip[1] > 63) { - ip[0] = 64; - ip[1] = 32; - temp_cyl = size / (ip[0] * ip[1]); - if (temp_cyl > 65534) { - ip[0] = 255; - ip[1] = 63; - } - ip[2] = size / (ip[0] * ip[1]); - } - return 0; -} - -/* - * Function : static int scsi_partsize(struct buffer_head *bh, unsigned long - * capacity,unsigned int *cyls, unsigned int *hds, unsigned int *secs); - * - * Purpose : to determine the BIOS mapping used to create the partition - * table, storing the results in *cyls, *hds, and *secs - * - * Returns : -1 on failure, 0 on success. - * - */ - -int scsi_partsize(struct buffer_head *bh, unsigned long capacity, - unsigned int *cyls, unsigned int *hds, unsigned int *secs) -{ - struct partition *p, *largest = NULL; - int i, largest_cyl; - int cyl, ext_cyl, end_head, end_cyl, end_sector; - unsigned int logical_end, physical_end, ext_physical_end; - - - if (*(unsigned short *) (bh->b_data + 510) == 0xAA55) { - for (largest_cyl = -1, p = (struct partition *) - (0x1BE + bh->b_data), i = 0; i < 4; ++i, ++p) { - if (!p->sys_ind) - continue; -#ifdef DEBUG - printk("scsicam_bios_param : partition %d has system \n", - i); -#endif - cyl = p->cyl + ((p->sector & 0xc0) << 2); - if (cyl > largest_cyl) { - largest_cyl = cyl; - largest = p; - } - } - } - if (largest) { - end_cyl = largest->end_cyl + ((largest->end_sector & 0xc0) << 2); - end_head = largest->end_head; - end_sector = largest->end_sector & 0x3f; - - if (end_head + 1 == 0 || end_sector == 0) - return -1; - -#ifdef DEBUG - printk("scsicam_bios_param : end at h = %d, c = %d, s = %d\n", - end_head, end_cyl, end_sector); -#endif - - physical_end = end_cyl * (end_head + 1) * end_sector + - end_head * end_sector + end_sector; - - /* This is the actual _sector_ number at the end */ - logical_end = get_unaligned(&largest->start_sect) - + get_unaligned(&largest->nr_sects); - - /* This is for >1023 cylinders */ - ext_cyl = (logical_end - (end_head * end_sector + end_sector)) - / (end_head + 1) / end_sector; - ext_physical_end = ext_cyl * (end_head + 1) * end_sector + - end_head * end_sector + end_sector; - -#ifdef DEBUG - printk("scsicam_bios_param : logical_end=%d physical_end=%d ext_physical_end=%d ext_cyl=%d\n" - ,logical_end, physical_end, ext_physical_end, ext_cyl); -#endif - - if ((logical_end == physical_end) || - (end_cyl == 1023 && ext_physical_end == logical_end)) { - *secs = end_sector; - *hds = end_head + 1; - *cyls = capacity / ((end_head + 1) * end_sector); - return 0; - } -#ifdef DEBUG - printk("scsicam_bios_param : logical (%u) != physical (%u)\n", - logical_end, physical_end); -#endif - } - return -1; -} - -/* - * Function : static int setsize(unsigned long capacity,unsigned int *cyls, - * unsigned int *hds, unsigned int *secs); - * - * Purpose : to determine a near-optimal int 0x13 mapping for a - * SCSI disk in terms of lost space of size capacity, storing - * the results in *cyls, *hds, and *secs. - * - * Returns : -1 on failure, 0 on success. - * - * Extracted from - * - * WORKING X3T9.2 - * DRAFT 792D - * - * - * Revision 6 - * 10-MAR-94 - * Information technology - - * SCSI-2 Common access method - * transport and SCSI interface module - * - * ANNEX A : - * - * setsize() converts a read capacity value to int 13h - * head-cylinder-sector requirements. It minimizes the value for - * number of heads and maximizes the number of cylinders. This - * will support rather large disks before the number of heads - * will not fit in 4 bits (or 6 bits). This algorithm also - * minimizes the number of sectors that will be unused at the end - * of the disk while allowing for very large disks to be - * accommodated. This algorithm does not use physical geometry. - */ - -static int setsize(unsigned long capacity, unsigned int *cyls, unsigned int *hds, - unsigned int *secs) -{ - unsigned int rv = 0; - unsigned long heads, sectors, cylinders, temp; - - cylinders = 1024L; /* Set number of cylinders to max */ - sectors = 62L; /* Maximize sectors per track */ - - temp = cylinders * sectors; /* Compute divisor for heads */ - heads = capacity / temp; /* Compute value for number of heads */ - if (capacity % temp) { /* If no remainder, done! */ - heads++; /* Else, increment number of heads */ - temp = cylinders * heads; /* Compute divisor for sectors */ - sectors = capacity / temp; /* Compute value for sectors per - track */ - if (capacity % temp) { /* If no remainder, done! */ - sectors++; /* Else, increment number of sectors */ - temp = heads * sectors; /* Compute divisor for cylinders */ - cylinders = capacity / temp; /* Compute number of cylinders */ - } - } - if (cylinders == 0) - rv = (unsigned) -1; /* Give error if 0 cylinders */ - - *cyls = (unsigned int) cylinders; /* Stuff return values */ - *secs = (unsigned int) sectors; - *hds = (unsigned int) heads; - return (rv); -} diff --git a/xen/drivers/scsi/sd.c b/xen/drivers/scsi/sd.c deleted file mode 100644 index c0bbe80dc9..0000000000 --- a/xen/drivers/scsi/sd.c +++ /dev/null @@ -1,1568 +0,0 @@ -/* - * sd.c Copyright (C) 1992 Drew Eckhardt - * Copyright (C) 1993, 1994, 1995, 1999 Eric Youngdale - * - * Linux scsi disk driver - * Initial versions: Drew Eckhardt - * Subsequent revisions: Eric Youngdale - * - * - * - * Modified by Eric Youngdale ericy@andante.org to - * add scatter-gather, multiple outstanding request, and other - * enhancements. - * - * Modified by Eric Youngdale eric@andante.org to support loadable - * low-level scsi drivers. - * - * Modified by Jirka Hanika geo@ff.cuni.cz to support more - * scsi disks using eight major numbers. - * - * Modified by Richard Gooch rgooch@atnf.csiro.au to support devfs. - * - * Modified by Torben Mathiasen tmm@image.dk - * Resource allocation fixes in sd_init and cleanups. - * - * Modified by Alex Davis - * Fix problem where partition info not being read in sd_open. - * - * Modified by Alex Davis - * Fix problem where removable media could be ejected after sd_open. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#define MAJOR_NR SCSI_DISK0_MAJOR -#include -#include -#include "scsi.h" -#include "hosts.h" -#include "sd.h" -#include -#include "constants.h" -#include /* must follow "hosts.h" */ - -#include - -#include /* SMH: for [un_]map_domain_mem() */ - -/* - * static const char RCSid[] = "$Header:"; - */ - -/* system major --> sd_gendisks index */ -#define SD_MAJOR_IDX(i) (MAJOR(i) & SD_MAJOR_MASK) -/* sd_gendisks index --> system major */ -#define SD_MAJOR(i) (!(i) ? SCSI_DISK0_MAJOR : SCSI_DISK1_MAJOR-1+(i)) - -#define SD_PARTITION(dev) ((SD_MAJOR_IDX(dev) << 8) | (MINOR(dev) & 255)) - -#define SCSI_DISKS_PER_MAJOR 16 -#define SD_MAJOR_NUMBER(i) SD_MAJOR((i) >> 8) -#define SD_MINOR_NUMBER(i) ((i) & 255) -#define MKDEV_SD_PARTITION(i) MKDEV(SD_MAJOR_NUMBER(i), (i) & 255) -#define MKDEV_SD(index) MKDEV_SD_PARTITION((index) << 4) -#define N_USED_SCSI_DISKS (sd_template.dev_max + SCSI_DISKS_PER_MAJOR - 1) -#define N_USED_SD_MAJORS (N_USED_SCSI_DISKS / SCSI_DISKS_PER_MAJOR) - -#define MAX_RETRIES 5 - -/* - * Time out in seconds for disks and Magneto-opticals (which are slower). - */ - -#define SD_TIMEOUT (30 * HZ) -#define SD_MOD_TIMEOUT (75 * HZ) - -static Scsi_Disk *rscsi_disks; -static struct gendisk *sd_gendisks; -static int *sd_sizes; -static int *sd_blocksizes; -static int *sd_hardsizes; /* Hardware sector size */ -static int *sd_max_sectors; - -static int check_scsidisk_media_change(kdev_t); -static int fop_revalidate_scsidisk(kdev_t); - -static int sd_init_onedisk(int); - - -static int sd_init(void); -static void sd_finish(void); -static int sd_attach(Scsi_Device *); -static int sd_detect(Scsi_Device *); -static void sd_detach(Scsi_Device *); -static int sd_init_command(Scsi_Cmnd *); - -static struct Scsi_Device_Template sd_template = { - name:"disk", - tag:"sd", - scsi_type:TYPE_DISK, - major:SCSI_DISK0_MAJOR, - /* - * Secondary range of majors that this driver handles. - */ - min_major:SCSI_DISK1_MAJOR, - max_major:SCSI_DISK7_MAJOR, - blk:1, - detect:sd_detect, - init:sd_init, - finish:sd_finish, - attach:sd_attach, - detach:sd_detach, - init_command:sd_init_command, -}; - - -static void rw_intr(Scsi_Cmnd * SCpnt); - -#if defined(CONFIG_PPC) -/* - * Moved from arch/ppc/pmac_setup.c. This is where it really belongs. - */ -kdev_t __init -sd_find_target(void *host, int tgt) -{ - Scsi_Disk *dp; - int i; - for (dp = rscsi_disks, i = 0; i < sd_template.dev_max; ++i, ++dp) - if (dp->device != NULL && dp->device->host == host - && dp->device->id == tgt) - return MKDEV_SD(i); - return 0; -} -#endif - -static int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) -{ - kdev_t dev = inode->i_rdev; - struct Scsi_Host * host; - Scsi_Device * SDev; - int diskinfo[4]; - - SDev = rscsi_disks[DEVICE_NR(dev)].device; - if (!SDev) - return -ENODEV; - - /* - * If we are in the middle of error recovery, don't let anyone - * else try and use this device. Also, if error recovery fails, it - * may try and take the device offline, in which case all further - * access to the device is prohibited. - */ - - if( !scsi_block_when_processing_errors(SDev) ) - { - return -ENODEV; - } - - switch (cmd) - { - case HDIO_GETGEO: /* Return BIOS disk parameters */ - { - struct hd_geometry *loc = (struct hd_geometry *) arg; - if(!loc) - return -EINVAL; - - host = rscsi_disks[DEVICE_NR(dev)].device->host; - - /* default to most commonly used values */ - - diskinfo[0] = 0x40; - diskinfo[1] = 0x20; - diskinfo[2] = - rscsi_disks[DEVICE_NR(dev)].capacity >> 11; - - /* override with calculated, extended default, - or driver values */ - - if(host->hostt->bios_param != NULL) - host->hostt->bios_param( - &rscsi_disks[DEVICE_NR(dev)], dev, - &diskinfo[0]); - else scsicam_bios_param(&rscsi_disks[DEVICE_NR(dev)], - dev, &diskinfo[0]); - - if (put_user(diskinfo[0], &loc->heads) || - put_user(diskinfo[1], &loc->sectors) || - put_user(diskinfo[2], &loc->cylinders) || - put_user(sd_gendisks[SD_MAJOR_IDX( - inode->i_rdev)].part[MINOR( - inode->i_rdev)].start_sect, &loc->start)) - return -EFAULT; - return 0; - } - case HDIO_GETGEO_BIG: - { - struct hd_big_geometry *loc = - (struct hd_big_geometry *) arg; - - if(!loc) - return -EINVAL; - - host = rscsi_disks[DEVICE_NR(dev)].device->host; - - /* default to most commonly used values */ - - diskinfo[0] = 0x40; - diskinfo[1] = 0x20; - diskinfo[2] = - rscsi_disks[DEVICE_NR(dev)].capacity >> 11; - - /* override with calculated, extended default, - or driver values */ - - if(host->hostt->bios_param != NULL) - host->hostt->bios_param( - &rscsi_disks[DEVICE_NR(dev)], dev, - &diskinfo[0]); - else scsicam_bios_param(&rscsi_disks[DEVICE_NR(dev)], - dev, &diskinfo[0]); - - if (put_user(diskinfo[0], &loc->heads) || - put_user(diskinfo[1], &loc->sectors) || - put_user(diskinfo[2], - (unsigned int *) &loc->cylinders) || - put_user(sd_gendisks[SD_MAJOR_IDX( - inode->i_rdev)].part[MINOR( - inode->i_rdev)].start_sect, &loc->start)) - return -EFAULT; - return 0; - } -#if 0 - case BLKGETSIZE: - case BLKGETSIZE64: - case BLKROSET: - case BLKROGET: - case BLKRASET: - case BLKRAGET: - case BLKFLSBUF: - case BLKSSZGET: - case BLKPG: - case BLKELVGET: - case BLKELVSET: - case BLKBSZGET: - case BLKBSZSET: - return blk_ioctl(inode->i_rdev, cmd, arg); - - case BLKRRPART: /* Re-read partition tables */ - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - return revalidate_scsidisk(dev, 1); -#endif - - default: - return scsi_ioctl(rscsi_disks[DEVICE_NR(dev)].device, - cmd, (void *) arg); - } -} - -static void sd_devname(unsigned int disknum, char *buffer) -{ - if (disknum < 26) - sprintf(buffer, "sd%c", 'a' + disknum); - else { - unsigned int min1; - unsigned int min2; - /* - * For larger numbers of disks, we need to go to a new - * naming scheme. - */ - min1 = disknum / 26; - min2 = disknum % 26; - sprintf(buffer, "sd%c%c", 'a' + min1 - 1, 'a' + min2); - } -} - -static request_queue_t *sd_find_queue(kdev_t dev) -{ - Scsi_Disk *dpnt; - int target; - target = DEVICE_NR(dev); - - dpnt = &rscsi_disks[target]; - if (!dpnt->device) - return NULL; /* No such device */ - return &dpnt->device->request_queue; -} - -static int sd_init_command(Scsi_Cmnd * SCpnt) -{ - int dev, block, this_count; - struct hd_struct *ppnt; - Scsi_Disk *dpnt; -#if CONFIG_SCSI_LOGGING - char nbuff[6]; -#endif - - ppnt = &sd_gendisks[SD_MAJOR_IDX(SCpnt->request.rq_dev)].part[MINOR(SCpnt->request.rq_dev)]; - dev = DEVICE_NR(SCpnt->request.rq_dev); - - block = SCpnt->request.sector; - this_count = SCpnt->request_bufflen >> 9; - - SCSI_LOG_HLQUEUE(1, printk("Doing sd request, dev = 0x%x, block = %d\n", - SCpnt->request.rq_dev, block)); - - dpnt = &rscsi_disks[dev]; - if (dev >= sd_template.dev_max || - !dpnt->device || - !dpnt->device->online || - block + SCpnt->request.nr_sectors > ppnt->nr_sects) { - - SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", - SCpnt->request.nr_sectors)); - SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt)); - return 0; - } - block += ppnt->start_sect; - if (dpnt->device->changed) { - /* - * quietly refuse to do anything to a changed disc until the changed - * bit has been reset - */ - /* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */ - return 0; - } - SCSI_LOG_HLQUEUE(2, sd_devname(dev, nbuff)); - SCSI_LOG_HLQUEUE(2, printk("%s : real dev = /dev/%d, block = %d\n", - nbuff, dev, block)); - - /* - * If we have a 1K hardware sectorsize, prevent access to single - * 512 byte sectors. In theory we could handle this - in fact - * the scsi cdrom driver must be able to handle this because - * we typically use 1K blocksizes, and cdroms typically have - * 2K hardware sectorsizes. Of course, things are simpler - * with the cdrom, since it is read-only. For performance - * reasons, the filesystems should be able to handle this - * and not force the scsi disk driver to use bounce buffers - * for this. - */ - if (dpnt->device->sector_size == 1024) { - if ((block & 1) || (SCpnt->request.nr_sectors & 1)) { - printk("sd.c:Bad block number requested"); - return 0; - } else { - block = block >> 1; - this_count = this_count >> 1; - } - } - if (dpnt->device->sector_size == 2048) { - if ((block & 3) || (SCpnt->request.nr_sectors & 3)) { - printk("sd.c:Bad block number requested"); - return 0; - } else { - block = block >> 2; - this_count = this_count >> 2; - } - } - if (dpnt->device->sector_size == 4096) { - if ((block & 7) || (SCpnt->request.nr_sectors & 7)) { - printk("sd.c:Bad block number requested"); - return 0; - } else { - block = block >> 3; - this_count = this_count >> 3; - } - } - switch (SCpnt->request.cmd) { - case WRITE: - if (!dpnt->device->writeable) { - return 0; - } - SCpnt->cmnd[0] = WRITE_6; - SCpnt->sc_data_direction = SCSI_DATA_WRITE; - break; - case READ: - SCpnt->cmnd[0] = READ_6; - SCpnt->sc_data_direction = SCSI_DATA_READ; - break; - default: - panic("Unknown sd command %d\n", SCpnt->request.cmd); - } - - SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n", nbuff, - (SCpnt->request.cmd == WRITE) ? "writing" : - "reading", this_count, - SCpnt->request.nr_sectors)); - - SCpnt->cmnd[1] = (SCpnt->device->scsi_level <= SCSI_2) ? - ((SCpnt->lun << 5) & 0xe0) : 0; - - if (((this_count > 0xff) || (block > 0x1fffff)) || SCpnt->device->ten) { - if (this_count > 0xffff) - this_count = 0xffff; - - SCpnt->cmnd[0] += READ_10 - READ_6; - SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; - SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; - SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff; - SCpnt->cmnd[5] = (unsigned char) block & 0xff; - SCpnt->cmnd[6] = SCpnt->cmnd[9] = 0; - SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff; - SCpnt->cmnd[8] = (unsigned char) this_count & 0xff; - } else { - if (this_count > 0xff) - this_count = 0xff; - - SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f); - SCpnt->cmnd[2] = (unsigned char) ((block >> 8) & 0xff); - SCpnt->cmnd[3] = (unsigned char) block & 0xff; - SCpnt->cmnd[4] = (unsigned char) this_count; - SCpnt->cmnd[5] = 0; - } - - /* - * We shouldn't disconnect in the middle of a sector, so with a dumb - * host adapter, it's safe to assume that we can at least transfer - * this many bytes between each connect / disconnect. - */ - SCpnt->transfersize = dpnt->device->sector_size; - SCpnt->underflow = this_count << 9; - - SCpnt->allowed = MAX_RETRIES; - SCpnt->timeout_per_command = (SCpnt->device->type == TYPE_DISK ? - SD_TIMEOUT : SD_MOD_TIMEOUT); - - /* - * This is the completion routine we use. This is matched in terms - * of capability to this function. - */ - SCpnt->done = rw_intr; - - /* - * This indicates that the command is ready from our end to be - * queued. - */ - return 1; -} - -static int sd_open(struct inode *inode, struct file *filp) -{ - int target, retval = -ENXIO; - Scsi_Device * SDev; - target = DEVICE_NR(inode->i_rdev); - - SCSI_LOG_HLQUEUE(1, printk("target=%d, max=%d\n", target, sd_template.dev_max)); - - if (target >= sd_template.dev_max || !rscsi_disks[target].device) - return -ENXIO; /* No such device */ - - /* - * If the device is in error recovery, wait until it is done. - * If the device is offline, then disallow any access to it. - */ - if (!scsi_block_when_processing_errors(rscsi_disks[target].device)) { - return -ENXIO; - } - /* - * Make sure that only one process can do a check_change_disk at one time. - * This is also used to lock out further access when the partition table - * is being re-read. - */ - - while (rscsi_disks[target].device->busy) { - barrier(); - cpu_relax(); - } - /* - * The following code can sleep. - * Module unloading must be prevented - */ - SDev = rscsi_disks[target].device; - if (SDev->host->hostt->module) - __MOD_INC_USE_COUNT(SDev->host->hostt->module); - if (sd_template.module) - __MOD_INC_USE_COUNT(sd_template.module); - SDev->access_count++; - -#if 0 - if (rscsi_disks[target].device->removable) { - SDev->allow_revalidate = 1; - check_disk_change(inode->i_rdev); - SDev->allow_revalidate = 0; - - - /* - * If the drive is empty, just let the open fail. - */ - if ((!rscsi_disks[target].ready) && !(filp->f_flags & O_NDELAY)) { - retval = -ENOMEDIUM; - goto error_out; - } - - /* - * Similarly, if the device has the write protect tab set, - * have the open fail if the user expects to be able to write - * to the thing. - */ - if ((rscsi_disks[target].write_prot) && (filp->f_mode & 2)) { - retval = -EROFS; - goto error_out; - } - } -#endif - - /* - * It is possible that the disk changing stuff resulted in the device - * being taken offline. If this is the case, report this to the user, - * and don't pretend that - * the open actually succeeded. - */ - if (!SDev->online) { - goto error_out; - } - /* - * See if we are requesting a non-existent partition. Do this - * after checking for disk change. - */ - if (sd_sizes[SD_PARTITION(inode->i_rdev)] == 0) { - goto error_out; - } - - if (SDev->removable) - if (SDev->access_count==1) - if (scsi_block_when_processing_errors(SDev)) - scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, NULL); - - - return 0; - - error_out: - SDev->access_count--; - if (SDev->host->hostt->module) - __MOD_DEC_USE_COUNT(SDev->host->hostt->module); - if (sd_template.module) - __MOD_DEC_USE_COUNT(sd_template.module); - return retval; -} - -static int sd_release(struct inode *inode, struct file *file) -{ - int target; - Scsi_Device * SDev; - - target = DEVICE_NR(inode->i_rdev); - SDev = rscsi_disks[target].device; - if (!SDev) - return -ENODEV; - - SDev->access_count--; - - if (SDev->removable) { - if (!SDev->access_count) - if (scsi_block_when_processing_errors(SDev)) - scsi_ioctl(SDev, SCSI_IOCTL_DOORUNLOCK, NULL); - } - if (SDev->host->hostt->module) - __MOD_DEC_USE_COUNT(SDev->host->hostt->module); - if (sd_template.module) - __MOD_DEC_USE_COUNT(sd_template.module); - return 0; -} - -static struct block_device_operations sd_fops = -{ -/* owner: THIS_MODULE, */ - open: sd_open, - release: sd_release, - ioctl: sd_ioctl, - check_media_change: check_scsidisk_media_change, - revalidate: fop_revalidate_scsidisk -}; - -/* - * If we need more than one SCSI disk major (i.e. more than - * 16 SCSI disks), we'll have to kmalloc() more gendisks later. - */ - -static struct gendisk sd_gendisk = -{ - major: SCSI_DISK0_MAJOR, - major_name: "sd", - minor_shift: 4, - max_p: 1 << 4, - fops: &sd_fops, -}; - -#define SD_GENDISK(i) sd_gendisks[(i) / SCSI_DISKS_PER_MAJOR] - -/* - * rw_intr is the interrupt routine for the device driver. - * It will be notified on the end of a SCSI read / write, and - * will take one of several actions based on success or failure. - */ - -static void rw_intr(Scsi_Cmnd * SCpnt) -{ - int result = SCpnt->result; -#if CONFIG_SCSI_LOGGING - char nbuff[6]; -#endif - int this_count = SCpnt->bufflen >> 9; - int good_sectors = (result == 0 ? this_count : 0); - int block_sectors = 1; - long error_sector; - - SCSI_LOG_HLCOMPLETE(1, sd_devname(DEVICE_NR(SCpnt->request.rq_dev), - nbuff)); - - SCSI_LOG_HLCOMPLETE(1, printk("%s : rw_intr(%d, %x [%x %x])\n", nbuff, - SCpnt->host->host_no, - result, - SCpnt->sense_buffer[0], - SCpnt->sense_buffer[2])); - - /* - Handle MEDIUM ERRORs that indicate partial success. Since this is a - relatively rare error condition, no care is taken to avoid - unnecessary additional work such as memcpy's that could be avoided. - */ - - /* An error occurred */ - if (driver_byte(result) != 0 && /* An error occured */ - SCpnt->sense_buffer[0] == 0xF0) { /* Sense data is valid */ - switch (SCpnt->sense_buffer[2]) { - case MEDIUM_ERROR: - error_sector = (SCpnt->sense_buffer[3] << 24) | - (SCpnt->sense_buffer[4] << 16) | - (SCpnt->sense_buffer[5] << 8) | - SCpnt->sense_buffer[6]; - if (SCpnt->request.bh != NULL) - block_sectors = SCpnt->request.bh->b_size >> 9; - switch (SCpnt->device->sector_size) { - case 1024: - error_sector <<= 1; - if (block_sectors < 2) - block_sectors = 2; - break; - case 2048: - error_sector <<= 2; - if (block_sectors < 4) - block_sectors = 4; - break; - case 4096: - error_sector <<=3; - if (block_sectors < 8) - block_sectors = 8; - break; - case 256: - error_sector >>= 1; - break; - default: - break; - } - error_sector -= sd_gendisks[SD_MAJOR_IDX( - SCpnt->request.rq_dev)].part[MINOR( - SCpnt->request.rq_dev)].start_sect; - error_sector &= ~(block_sectors - 1); - good_sectors = error_sector - SCpnt->request.sector; - if (good_sectors < 0 || good_sectors >= this_count) - good_sectors = 0; - break; - - case RECOVERED_ERROR: - /* - * An error occured, but it recovered. Inform the - * user, but make sure that it's not treated as a - * hard error. - */ - print_sense("sd", SCpnt); - result = 0; - SCpnt->sense_buffer[0] = 0x0; - good_sectors = this_count; - break; - - case ILLEGAL_REQUEST: - if (SCpnt->device->ten == 1) { - if (SCpnt->cmnd[0] == READ_10 || - SCpnt->cmnd[0] == WRITE_10) - SCpnt->device->ten = 0; - } - break; - - default: - break; - } - } - /* - * This calls the generic completion function, now that we know - * how many actual sectors finished, and how many sectors we need - * to say have failed. - */ - scsi_io_completion(SCpnt, good_sectors, block_sectors); -} -/* - * requeue_sd_request() is the request handler function for the sd driver. - * Its function in life is to take block device requests, and translate - * them to SCSI commands. - */ - - -static int check_scsidisk_media_change(kdev_t full_dev) -{ - int retval; - int target; - int flag = 0; - Scsi_Device * SDev; - - target = DEVICE_NR(full_dev); - SDev = rscsi_disks[target].device; - - if (target >= sd_template.dev_max || !SDev) { - printk("SCSI disk request error: invalid device.\n"); - return 0; - } - if (!SDev->removable) - return 0; - - /* - * If the device is offline, don't send any commands - just pretend as - * if the command failed. If the device ever comes back online, we - * can deal with it then. It is only because of unrecoverable errors - * that we would ever take a device offline in the first place. - */ - if (SDev->online == FALSE) { - rscsi_disks[target].ready = 0; - SDev->changed = 1; - return 1; /* This will force a flush, if called from - * check_disk_change */ - } - - /* Using Start/Stop enables differentiation between drive with - * no cartridge loaded - NOT READY, drive with changed cartridge - - * UNIT ATTENTION, or with same cartridge - GOOD STATUS. - * This also handles drives that auto spin down. eg iomega jaz 1GB - * as this will spin up the drive. - */ - retval = -ENODEV; - if (scsi_block_when_processing_errors(SDev)) - retval = scsi_ioctl(SDev, SCSI_IOCTL_START_UNIT, NULL); - - if (retval) { /* Unable to test, unit probably not ready. - * This usually means there is no disc in the - * drive. Mark as changed, and we will figure - * it out later once the drive is available - * again. */ - - rscsi_disks[target].ready = 0; - SDev->changed = 1; - return 1; /* This will force a flush, if called from - * check_disk_change */ - } - /* - * for removable scsi disk ( FLOPTICAL ) we have to recognise the - * presence of disk in the drive. This is kept in the Scsi_Disk - * struct and tested at open ! Daniel Roche ( dan@lectra.fr ) - */ - - rscsi_disks[target].ready = 1; /* FLOPTICAL */ - - retval = SDev->changed; - if (!flag) - SDev->changed = 0; - return retval; -} - -static int sd_init_onedisk(int i) -{ - unsigned char cmd[10]; - char nbuff[6]; - unsigned char *buffer; - unsigned long spintime_value = 0; - int the_result, retries, spintime; - int sector_size; - Scsi_Request *SRpnt; - - /* - * Get the name of the disk, in case we need to log it somewhere. - */ - sd_devname(i, nbuff); - - /* - * If the device is offline, don't try and read capacity or any - * of the other niceties. - */ - if (rscsi_disks[i].device->online == FALSE) - return i; - - /* - * We need to retry the READ_CAPACITY because a UNIT_ATTENTION is - * considered a fatal error, and many devices report such an error - * just after a scsi bus reset. - */ - - SRpnt = scsi_allocate_request(rscsi_disks[i].device); - if (!SRpnt) { - printk(KERN_WARNING - "(sd_init_onedisk:) Request allocation failure.\n"); - return i; - } - - buffer = (unsigned char *) scsi_malloc(512); - if (!buffer) { - printk(KERN_WARNING "(sd_init_onedisk:) Memory allocation failure.\n"); - scsi_release_request(SRpnt); - return i; - } - - spintime = 0; - - /* Spin up drives, as required. Only do this at boot time */ - /* Spinup needs to be done for module loads too. */ - do { - retries = 0; - - while (retries < 3) { - cmd[0] = TEST_UNIT_READY; - cmd[1] = (rscsi_disks[i].device->scsi_level <= SCSI_2) ? - ((rscsi_disks[i].device->lun << 5) & 0xe0) : 0; - memset((void *) &cmd[2], 0, 8); - SRpnt->sr_cmd_len = 0; - SRpnt->sr_sense_buffer[0] = 0; - SRpnt->sr_sense_buffer[2] = 0; - SRpnt->sr_data_direction = SCSI_DATA_NONE; - - scsi_wait_req (SRpnt, (void *) cmd, (void *) buffer, - 0/*512*/, SD_TIMEOUT, MAX_RETRIES); - - the_result = SRpnt->sr_result; - retries++; - if (the_result == 0 - || SRpnt->sr_sense_buffer[2] != UNIT_ATTENTION) - break; - } - - /* - * If the drive has indicated to us that it doesn't have - * any media in it, don't bother with any of the rest of - * this crap. - */ - if( the_result != 0 - && ((driver_byte(the_result) & DRIVER_SENSE) != 0) - && SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION - && SRpnt->sr_sense_buffer[12] == 0x3A ) { - rscsi_disks[i].capacity = 0x1fffff; - sector_size = 512; - rscsi_disks[i].device->changed = 1; - rscsi_disks[i].ready = 0; - break; - } - - /* Look for non-removable devices that return NOT_READY. - * Issue command to spin up drive for these cases. */ - if (the_result && !rscsi_disks[i].device->removable && - SRpnt->sr_sense_buffer[2] == NOT_READY) { - unsigned long time1; - if (!spintime) { - printk("%s: Spinning up disk...", nbuff); - cmd[0] = START_STOP; - cmd[1] = (rscsi_disks[i].device->scsi_level <= SCSI_2) ? - ((rscsi_disks[i].device->lun << 5) & 0xe0) : 0; - cmd[1] |= 1; /* Return immediately */ - memset((void *) &cmd[2], 0, 8); - cmd[4] = 1; /* Start spin cycle */ - SRpnt->sr_cmd_len = 0; - SRpnt->sr_sense_buffer[0] = 0; - SRpnt->sr_sense_buffer[2] = 0; - - SRpnt->sr_data_direction = SCSI_DATA_READ; - scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, - 0/*512*/, SD_TIMEOUT, MAX_RETRIES); - spintime_value = jiffies; - } - spintime = 1; - time1 = HZ; - /* Wait 1 second for next try */ - do { - current->state = TASK_UNINTERRUPTIBLE; - time1 = schedule_timeout(time1); - } while(time1); - printk("."); - } - } while (the_result && spintime && - time_after(spintime_value + 100 * HZ, jiffies)); - if (spintime) { - if (the_result) - printk("not responding...\n"); - else - printk("ready\n"); - } - retries = 3; - do { - cmd[0] = READ_CAPACITY; - cmd[1] = (rscsi_disks[i].device->scsi_level <= SCSI_2) ? - ((rscsi_disks[i].device->lun << 5) & 0xe0) : 0; - memset((void *) &cmd[2], 0, 8); - memset((void *) buffer, 0, 8); - SRpnt->sr_cmd_len = 0; - SRpnt->sr_sense_buffer[0] = 0; - SRpnt->sr_sense_buffer[2] = 0; - - SRpnt->sr_data_direction = SCSI_DATA_READ; - scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, - 8, SD_TIMEOUT, MAX_RETRIES); - - the_result = SRpnt->sr_result; - retries--; - - } while (the_result && retries); - - /* - * The SCSI standard says: - * "READ CAPACITY is necessary for self configuring software" - * While not mandatory, support of READ CAPACITY is strongly - * encouraged. - * We used to die if we couldn't successfully do a READ CAPACITY. - * But, now we go on about our way. The side effects of this are - * - * 1. We can't know block size with certainty. I have said - * "512 bytes is it" as this is most common. - * - * 2. Recovery from when someone attempts to read past the - * end of the raw device will be slower. - */ - - if (the_result) { - printk("%s : READ CAPACITY failed.\n" - "%s : status = %x, message = %02x, host = %d, driver = %02x \n", - nbuff, nbuff, - status_byte(the_result), - msg_byte(the_result), - host_byte(the_result), - driver_byte(the_result) - ); - if (driver_byte(the_result) & DRIVER_SENSE) - print_req_sense("sd", SRpnt); - else - printk("%s : sense not available. \n", nbuff); - - printk("%s : block size assumed to be 512 bytes, disk size 1GB. \n", - nbuff); - rscsi_disks[i].capacity = 0x1fffff; - sector_size = 512; - - /* Set dirty bit for removable devices if not ready - - * sometimes drives will not report this properly. */ - if (rscsi_disks[i].device->removable && - SRpnt->sr_sense_buffer[2] == NOT_READY) - rscsi_disks[i].device->changed = 1; - - } else { - /* - * FLOPTICAL, if read_capa is ok, drive is assumed to be ready - */ - rscsi_disks[i].ready = 1; - - rscsi_disks[i].capacity = 1 + ((buffer[0] << 24) | - (buffer[1] << 16) | - (buffer[2] << 8) | - buffer[3]); - - sector_size = (buffer[4] << 24) | - (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; - - if (sector_size == 0) { - sector_size = 512; - printk("%s : sector size 0 reported, assuming 512.\n", - nbuff); - } - if (sector_size != 512 && - sector_size != 1024 && - sector_size != 2048 && - sector_size != 4096 && - sector_size != 256) { - printk("%s : unsupported sector size %d.\n", - nbuff, sector_size); - /* - * The user might want to re-format the drive with - * a supported sectorsize. Once this happens, it - * would be relatively trivial to set the thing up. - * For this reason, we leave the thing in the table. - */ - rscsi_disks[i].capacity = 0; - } - if (sector_size > 1024) { - int m; - - /* - * We must fix the sd_blocksizes and sd_hardsizes - * to allow us to read the partition tables. - * The disk reading code does not allow for reading - * of partial sectors. - */ - for (m = i << 4; m < ((i + 1) << 4); m++) { - sd_blocksizes[m] = sector_size; - } - } { - /* - * The msdos fs needs to know the hardware sector size - * So I have created this table. See ll_rw_blk.c - * Jacques Gelinas (Jacques@solucorp.qc.ca) - */ - int m; - int hard_sector = sector_size; - int sz = rscsi_disks[i].capacity * (hard_sector/256); - - /* There are 16 minors allocated for each major device */ - for (m = i << 4; m < ((i + 1) << 4); m++) { - sd_hardsizes[m] = hard_sector; - } - - printk("SCSI device %s: " - "%d %d-byte hdwr sectors (%d MB)\n", - nbuff, rscsi_disks[i].capacity, - hard_sector, (sz/2 - sz/1250 + 974)/1950); - } - - /* Rescale capacity to 512-byte units */ - if (sector_size == 4096) - rscsi_disks[i].capacity <<= 3; - if (sector_size == 2048) - rscsi_disks[i].capacity <<= 2; - if (sector_size == 1024) - rscsi_disks[i].capacity <<= 1; - if (sector_size == 256) - rscsi_disks[i].capacity >>= 1; - } - - - /* - * Unless otherwise specified, this is not write protected. - */ - rscsi_disks[i].write_prot = 0; - if (rscsi_disks[i].device->removable && rscsi_disks[i].ready) { - /* FLOPTICAL */ - - /* - * For removable scsi disk ( FLOPTICAL ) we have to recognise - * the Write Protect Flag. This flag is kept in the Scsi_Disk - * struct and tested at open ! - * Daniel Roche ( dan@lectra.fr ) - * - * Changed to get all pages (0x3f) rather than page 1 to - * get around devices which do not have a page 1. Since - * we're only interested in the header anyway, this should - * be fine. - * -- Matthew Dharm (mdharm-scsi@one-eyed-alien.net) - */ - - memset((void *) &cmd[0], 0, 8); - cmd[0] = MODE_SENSE; - cmd[1] = (rscsi_disks[i].device->scsi_level <= SCSI_2) ? - ((rscsi_disks[i].device->lun << 5) & 0xe0) : 0; - cmd[2] = 0x3f; /* Get all pages */ - cmd[4] = 255; /* Ask for 255 bytes, even tho we want just the first 8 */ - SRpnt->sr_cmd_len = 0; - SRpnt->sr_sense_buffer[0] = 0; - SRpnt->sr_sense_buffer[2] = 0; - - /* same code as READCAPA !! */ - SRpnt->sr_data_direction = SCSI_DATA_READ; - scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, - 512, SD_TIMEOUT, MAX_RETRIES); - - the_result = SRpnt->sr_result; - - if (the_result) { - printk("%s: test WP failed, assume Write Enabled\n", nbuff); - } else { - rscsi_disks[i].write_prot = ((buffer[2] & 0x80) != 0); - printk("%s: Write Protect is %s\n", nbuff, - rscsi_disks[i].write_prot ? "on" : "off"); - } - - } /* check for write protect */ - SRpnt->sr_device->ten = 1; - SRpnt->sr_device->remap = 1; - SRpnt->sr_device->sector_size = sector_size; - /* Wake up a process waiting for device */ - scsi_release_request(SRpnt); - SRpnt = NULL; - - scsi_free(buffer, 512); - return i; -} - -/* - * The sd_init() function looks at all SCSI drives present, determines - * their size, and reads partition table entries for them. - */ - -static int sd_registered; - -static int sd_init() -{ - int i; - - if (sd_template.dev_noticed == 0) - return 0; - - if (!rscsi_disks) - sd_template.dev_max = sd_template.dev_noticed + SD_EXTRA_DEVS; - - if (sd_template.dev_max > N_SD_MAJORS * SCSI_DISKS_PER_MAJOR) - sd_template.dev_max = N_SD_MAJORS * SCSI_DISKS_PER_MAJOR; - - if (!sd_registered) { - for (i = 0; i < N_USED_SD_MAJORS; i++) { -#ifdef DEVFS_MUST_DIE - if (devfs_register_blkdev(SD_MAJOR(i), "sd", &sd_fops)) { - printk("Unable to get major %d for SCSI disk\n", SD_MAJOR(i)); - sd_template.dev_noticed = 0; - return 1; - } -#endif - } - sd_registered++; - } - /* We do not support attaching loadable devices yet. */ - if (rscsi_disks) - return 0; - - rscsi_disks = kmalloc(sd_template.dev_max * sizeof(Scsi_Disk), GFP_ATOMIC); - if (!rscsi_disks) - goto cleanup_devfs; - memset(rscsi_disks, 0, sd_template.dev_max * sizeof(Scsi_Disk)); - - /* for every (necessary) major: */ - sd_sizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC); - if (!sd_sizes) - goto cleanup_disks; - memset(sd_sizes, 0, (sd_template.dev_max << 4) * sizeof(int)); - - sd_blocksizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), - GFP_ATOMIC); - if (!sd_blocksizes) - goto cleanup_sizes; - - sd_hardsizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), - GFP_ATOMIC); - if (!sd_hardsizes) - goto cleanup_blocksizes; - - sd_max_sectors = kmalloc((sd_template.dev_max << 4) * sizeof(int), - GFP_ATOMIC); - if (!sd_max_sectors) - goto cleanup_max_sectors; - - for (i = 0; i < sd_template.dev_max << 4; i++) { - sd_blocksizes[i] = 1024; - sd_hardsizes[i] = 512; - /* - * Allow lowlevel device drivers to generate 512k large scsi - * commands if they know what they're doing and they ask for it - * explicitly via the SHpnt->max_sectors API. - */ - sd_max_sectors[i] = MAX_SEGMENTS*8; - } - - for (i = 0; i < N_USED_SD_MAJORS; i++) { - blksize_size[SD_MAJOR(i)] = sd_blocksizes + - i * (SCSI_DISKS_PER_MAJOR << 4); - hardsect_size[SD_MAJOR(i)] = sd_hardsizes + - i * (SCSI_DISKS_PER_MAJOR << 4); - max_sectors[SD_MAJOR(i)] = sd_max_sectors + - i * (SCSI_DISKS_PER_MAJOR << 4); - } - - sd_gendisks = kmalloc(N_USED_SD_MAJORS * sizeof(struct gendisk), - GFP_ATOMIC); - if (!sd_gendisks) - goto cleanup_sd_gendisks; - for (i = 0; i < N_USED_SD_MAJORS; i++) { - sd_gendisks[i] = sd_gendisk; /* memcpy */ -#ifdef DEVFS_MUST_DIE - sd_gendisks[i].de_arr = kmalloc (SCSI_DISKS_PER_MAJOR * - sizeof *sd_gendisks[i].de_arr, - GFP_ATOMIC); - if (!sd_gendisks[i].de_arr) - goto cleanup_gendisks_de_arr; - memset (sd_gendisks[i].de_arr, 0, - SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].de_arr); -#endif - sd_gendisks[i].flags = kmalloc (SCSI_DISKS_PER_MAJOR * - sizeof *sd_gendisks[i].flags, - GFP_ATOMIC); - if (!sd_gendisks[i].flags) - goto cleanup_gendisks_flags; - memset (sd_gendisks[i].flags, 0, - SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].flags); - sd_gendisks[i].major = SD_MAJOR(i); - sd_gendisks[i].major_name = "sd"; - sd_gendisks[i].minor_shift = 4; - sd_gendisks[i].max_p = 1 << 4; - sd_gendisks[i].part = kmalloc((SCSI_DISKS_PER_MAJOR << 4) * - sizeof(struct hd_struct), - GFP_ATOMIC); - if (!sd_gendisks[i].part) - goto cleanup_gendisks_part; - memset(sd_gendisks[i].part, 0, (SCSI_DISKS_PER_MAJOR << 4) * - sizeof(struct hd_struct)); - sd_gendisks[i].sizes = sd_sizes + (i * SCSI_DISKS_PER_MAJOR << 4); - sd_gendisks[i].nr_real = 0; - sd_gendisks[i].real_devices = - (void *) (rscsi_disks + i * SCSI_DISKS_PER_MAJOR); - } - - return 0; - - cleanup_gendisks_part: - kfree(sd_gendisks[i].flags); - cleanup_gendisks_flags: -#ifdef DEVFS_MUST_DIE - kfree(sd_gendisks[i].de_arr); - cleanup_gendisks_de_arr: -#endif - while (--i >= 0 ) { -#ifdef DEVFS_MUST_DIE - kfree(sd_gendisks[i].de_arr); -#endif - kfree(sd_gendisks[i].flags); - kfree(sd_gendisks[i].part); - } - kfree(sd_gendisks); - sd_gendisks = NULL; - cleanup_sd_gendisks: - kfree(sd_max_sectors); - cleanup_max_sectors: - kfree(sd_hardsizes); - cleanup_blocksizes: - kfree(sd_blocksizes); - cleanup_sizes: - kfree(sd_sizes); - cleanup_disks: - kfree(rscsi_disks); - rscsi_disks = NULL; - cleanup_devfs: -#ifdef DEVFS_MUST_DIE - for (i = 0; i < N_USED_SD_MAJORS; i++) { - devfs_unregister_blkdev(SD_MAJOR(i), "sd"); - } -#endif - sd_registered--; - sd_template.dev_noticed = 0; - return 1; -} - - -static void sd_finish() -{ - int i; - - for (i = 0; i < N_USED_SD_MAJORS; i++) { - blk_dev[SD_MAJOR(i)].queue = sd_find_queue; - add_gendisk(&sd_gendisks[i]); - } - - for (i = 0; i < sd_template.dev_max; ++i) - if (!rscsi_disks[i].capacity && rscsi_disks[i].device) { - sd_init_onedisk(i); - if (!rscsi_disks[i].has_part_table) { - sd_sizes[i << 4] = rscsi_disks[i].capacity; - register_disk(&SD_GENDISK(i), MKDEV_SD(i), - 1<<4, &sd_fops, - rscsi_disks[i].capacity); - rscsi_disks[i].has_part_table = 1; - } - } -#if 0 - /* If our host adapter is capable of scatter-gather, then we increase - * the read-ahead to 60 blocks (120 sectors). If not, we use - * a two block (4 sector) read ahead. We can only respect this with the - * granularity of every 16 disks (one device major). - */ - for (i = 0; i < N_USED_SD_MAJORS; i++) { - read_ahead[SD_MAJOR(i)] = - (rscsi_disks[i * SCSI_DISKS_PER_MAJOR].device - && rscsi_disks[i * SCSI_DISKS_PER_MAJOR].device->host->sg_tablesize) - ? 120 /* 120 sector read-ahead */ - : 4; /* 4 sector read-ahead */ - } -#endif - -#if 0 - /* XXX SMH: turn on some logging */ - scsi_logging_level = ~0; - SCSI_SET_LOGGING(SCSI_LOG_HLQUEUE_SHIFT, SCSI_LOG_HLQUEUE_BITS, 1); -#endif - - return; -} - - -/* -** scsi_probe_devices: -** -** add the scsi block devices for this domain to a xen_disk_info_t; -** we assume xdi->count points to the first unused place in the array. -** -** XXX SMH: this is a rather gross 'probe' function to allow xen world -** to grope us; this should really not be in the disk-specific code as -** it should report tapes, CDs, etc. But for now this looks like the -** easiest place to hook it in :-( -** -*/ - -static kdev_t scsi_devs[] = { - MKDEV(SCSI_DISK0_MAJOR, 0), MKDEV(SCSI_DISK0_MAJOR, 16), /* sda, sdb */ - MKDEV(SCSI_DISK0_MAJOR, 32), MKDEV(SCSI_DISK0_MAJOR, 48), /* sdc, sdd */ - MKDEV(SCSI_DISK0_MAJOR, 64), MKDEV(SCSI_DISK0_MAJOR, 80), /* sde, sdf */ - MKDEV(SCSI_DISK0_MAJOR, 96), MKDEV(SCSI_DISK0_MAJOR, 112), /* sdg, sdh */ - MKDEV(SCSI_DISK0_MAJOR, 128), MKDEV(SCSI_DISK0_MAJOR, 144), /* sdi, sdj */ - MKDEV(SCSI_DISK0_MAJOR, 160), MKDEV(SCSI_DISK0_MAJOR, 176), /* sdk, sdl */ - MKDEV(SCSI_DISK0_MAJOR, 192), MKDEV(SCSI_DISK0_MAJOR, 208), /* sdm, sdn */ - MKDEV(SCSI_DISK0_MAJOR, 224), MKDEV(SCSI_DISK0_MAJOR, 240), /* sdo, sdp */ -}; - - -void scsi_probe_devices(xen_disk_info_t *xdi) -{ - int i; - Scsi_Disk *sd; - xen_disk_t *xd = &xdi->disks[xdi->count]; - - for ( sd = rscsi_disks, i = 0; i < sd_template.dev_max; i++, sd++ ) - { - if ( sd->device == NULL ) - continue; - - if ( xdi->count == xdi->max ) - BUG(); - - /* We export 'raw' linux device numbers to domain 0. */ - xd->device = scsi_devs[i]; - xd->info = XD_TYPE_DISK; /* XXX should determine properly */ - xd->capacity = sd->capacity; - xd->domain = 0; - - xdi->count++; - xd++; - } -} - - - - -static int sd_detect(Scsi_Device * SDp) -{ - if (SDp->type != TYPE_DISK && SDp->type != TYPE_MOD) - return 0; - sd_template.dev_noticed++; - return 1; -} - -static int sd_attach(Scsi_Device * SDp) -{ - unsigned int devnum; - Scsi_Disk *dpnt; - int i; - char nbuff[6]; - - if (SDp->type != TYPE_DISK && SDp->type != TYPE_MOD) - return 0; - - if (sd_template.nr_dev >= sd_template.dev_max || rscsi_disks == NULL) { - SDp->attached--; - return 1; - } - for (dpnt = rscsi_disks, i = 0; i < sd_template.dev_max; i++, dpnt++) - if (!dpnt->device) - break; - - if (i >= sd_template.dev_max) { - printk(KERN_WARNING "scsi_devices corrupt (sd)," - " nr_dev %d dev_max %d\n", - sd_template.nr_dev, sd_template.dev_max); - SDp->attached--; - return 1; - } - - rscsi_disks[i].device = SDp; - rscsi_disks[i].has_part_table = 0; - sd_template.nr_dev++; - SD_GENDISK(i).nr_real++; - devnum = i % SCSI_DISKS_PER_MAJOR; -#ifdef DEVFS_MUST_DIE - SD_GENDISK(i).de_arr[devnum] = SDp->de; -#endif - if (SDp->removable) - SD_GENDISK(i).flags[devnum] |= GENHD_FL_REMOVABLE; - sd_devname(i, nbuff); - printk("Attached scsi %sdisk %s at scsi%d, channel %d, id %d, lun %d\n", - SDp->removable ? "removable " : "", - nbuff, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun); - return 0; -} - -#define DEVICE_BUSY rscsi_disks[target].device->busy -#define ALLOW_REVALIDATE rscsi_disks[target].device->allow_revalidate -#define USAGE rscsi_disks[target].device->access_count -#define CAPACITY rscsi_disks[target].capacity -#define MAYBE_REINIT sd_init_onedisk(target) - -/* This routine is called to flush all partitions and partition tables - * for a changed scsi disk, and then re-read the new partition table. - * If we are revalidating a disk because of a media change, then we - * enter with usage == 0. If we are using an ioctl, we automatically have - * usage == 1 (we need an open channel to use an ioctl :-), so this - * is our limit. - */ -int revalidate_scsidisk(kdev_t dev, int maxusage) -{ - struct gendisk *sdgd; - int target; - int max_p; - int start; - int i; - - target = DEVICE_NR(dev); - - if (DEVICE_BUSY || (ALLOW_REVALIDATE == 0 && USAGE > maxusage)) { - printk("Device busy for revalidation (usage=%d)\n", USAGE); - return -EBUSY; - } - DEVICE_BUSY = 1; - - sdgd = &SD_GENDISK(target); - max_p = sd_gendisk.max_p; - start = target << sd_gendisk.minor_shift; - - for (i = max_p - 1; i >= 0; i--) { - int index = start + i; - invalidate_device(MKDEV_SD_PARTITION(index), 1); - sdgd->part[SD_MINOR_NUMBER(index)].start_sect = 0; - sdgd->part[SD_MINOR_NUMBER(index)].nr_sects = 0; - /* - * Reset the blocksize for everything so that we can read - * the partition table. Technically we will determine the - * correct block size when we revalidate, but we do this just - * to make sure that everything remains consistent. - */ - sd_blocksizes[index] = 1024; - if (rscsi_disks[target].device->sector_size == 2048) - sd_blocksizes[index] = 2048; - else - sd_blocksizes[index] = 1024; - } - -#ifdef MAYBE_REINIT - MAYBE_REINIT; -#endif - - grok_partitions(&SD_GENDISK(target), target % SCSI_DISKS_PER_MAJOR, - 1<<4, CAPACITY); - - DEVICE_BUSY = 0; - return 0; -} - -static int fop_revalidate_scsidisk(kdev_t dev) -{ - return revalidate_scsidisk(dev, 0); -} - -static void sd_detach(Scsi_Device * SDp) -{ - Scsi_Disk *dpnt; - struct gendisk *sdgd; - int i, j; - int max_p; - int start; - - if (rscsi_disks == NULL) - return; - - for (dpnt = rscsi_disks, i = 0; i < sd_template.dev_max; i++, dpnt++) - if (dpnt->device == SDp) { - - /* If we are disconnecting a disk driver, sync and invalidate - * everything */ - sdgd = &SD_GENDISK(i); - max_p = sd_gendisk.max_p; - start = i << sd_gendisk.minor_shift; - - for (j = max_p - 1; j >= 0; j--) { - int index = start + j; - invalidate_device(MKDEV_SD_PARTITION(index), 1); - sdgd->part[SD_MINOR_NUMBER(index)].start_sect = 0; - sdgd->part[SD_MINOR_NUMBER(index)].nr_sects = 0; - sd_sizes[index] = 0; - } -#ifdef DEVFS_MUST_DIE - devfs_register_partitions (sdgd, - SD_MINOR_NUMBER (start), 1); -#endif - /* unregister_disk() */ - dpnt->has_part_table = 0; - dpnt->device = NULL; - dpnt->capacity = 0; - SDp->attached--; - sd_template.dev_noticed--; - sd_template.nr_dev--; - SD_GENDISK(i).nr_real--; - return; - } - return; -} - -static int __init init_sd(void) -{ - extern int scsi_register_module(int, void *); - - sd_template.module = THIS_MODULE; - return scsi_register_module(MODULE_SCSI_DEV, &sd_template); -} - -static void __exit exit_sd(void) -{ - int i; - -#if 0 - scsi_unregister_module(MODULE_SCSI_DEV, &sd_template); -#endif - -#ifdef DEVFS_MUST_DIE - for (i = 0; i < N_USED_SD_MAJORS; i++) - devfs_unregister_blkdev(SD_MAJOR(i), "sd"); -#endif - - sd_registered--; - if (rscsi_disks != NULL) { - kfree(rscsi_disks); - kfree(sd_sizes); - kfree(sd_blocksizes); - kfree(sd_hardsizes); - for (i = 0; i < N_USED_SD_MAJORS; i++) { -#if 0 /* XXX aren't we forgetting to deallocate something? */ - kfree(sd_gendisks[i].de_arr); - kfree(sd_gendisks[i].flags); -#endif - kfree(sd_gendisks[i].part); - } - } - for (i = 0; i < N_USED_SD_MAJORS; i++) { - del_gendisk(&sd_gendisks[i]); - blk_size[SD_MAJOR(i)] = NULL; /* XXX blksize_size actually? */ - hardsect_size[SD_MAJOR(i)] = NULL; -#if 0 - read_ahead[SD_MAJOR(i)] = 0; -#endif - } - sd_template.dev_max = 0; - if (sd_gendisks != NULL) /* kfree tests for 0, but leave explicit */ - kfree(sd_gendisks); -} - -module_init(init_sd); -module_exit(exit_sd); -MODULE_LICENSE("GPL"); diff --git a/xen/drivers/scsi/sd.h b/xen/drivers/scsi/sd.h deleted file mode 100644 index b9acfd7add..0000000000 --- a/xen/drivers/scsi/sd.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * sd.h Copyright (C) 1992 Drew Eckhardt - * SCSI disk driver header file by - * Drew Eckhardt - * - * - * - * Modified by Eric Youngdale eric@andante.org to - * add scatter-gather, multiple outstanding request, and other - * enhancements. - */ -#ifndef _SD_H -#define _SD_H -/* - $Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/sd.h,v 1.1 1992/07/24 06:27:38 root Exp root $ - */ - -#ifndef _SCSI_H -#include "scsi.h" -#endif - -#ifndef _GENDISK_H -#include -#endif - -typedef struct scsi_disk { - unsigned capacity; /* size in blocks */ - Scsi_Device *device; - unsigned char ready; /* flag ready for FLOPTICAL */ - unsigned char write_prot; /* flag write_protect for rmvable dev */ - unsigned char sector_bit_size; /* sector_size = 2 to the bit size power */ - unsigned char sector_bit_shift; /* power of 2 sectors per FS block */ - unsigned has_part_table:1; /* has partition table */ -} Scsi_Disk; - -extern int revalidate_scsidisk(kdev_t dev, int maxusage); - -/* - * Used by pmac to find the device associated with a target. - */ -extern kdev_t sd_find_target(void *host, int tgt); - -#define N_SD_MAJORS 8 - -#define SD_MAJOR_MASK (N_SD_MAJORS - 1) - -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/xen/drivers/scsi/sym53c8xx_2/ChangeLog.txt b/xen/drivers/scsi/sym53c8xx_2/ChangeLog.txt deleted file mode 100644 index 6a4a3f8550..0000000000 --- a/xen/drivers/scsi/sym53c8xx_2/ChangeLog.txt +++ /dev/null @@ -1,148 +0,0 @@ -Sat Dec 30 21:30 2000 Gerard Roudier - * version sym-2.1.0-20001230 - - Initial release of SYM-2. - -Mon Jan 08 21:30 2001 Gerard Roudier - * version sym-2.1.1-20010108 - - Change a couple of defines containing ncr or NCR by their - equivalent containing sym or SYM instead. - -Sun Jan 14 22:30 2001 Gerard Roudier - * version sym-2.1.2-20010114 - - Fix a couple of printfs: - * Add the target number to the display of transfer parameters. - * Make the display of TCQ and queue depth clearer. - -Wed Jan 17 23:30 2001 Gerard Roudier - * version sym-2.1.3-20010117 - - Wrong residual values were returned in some situations. - This broke cdrecord with linux-2.4.0, for example. - -Sat Jan 20 18:00 2001 Gerard Roudier - * version sym-2.1.4-20010120 - - Add year 2001 to Copyright. - - A tiny bug in the dma memory freeing path has been fixed. - (Driver unload failed with a bad address reference). - -Wed Jan 24 21:00 2001 Gerard Roudier - * version sym-2.1.5-20010124 - - Make the driver work under Linux-2.4.x when statically linked - with the kernel. - - Check against memory allocation failure for SCRIPTZ and add the - missing free of this memory on instance detach. - - Check against GPIO3 pulled low for HVD controllers (driver did - just the opposite). - Misdetection of BUS mode was triggerred on module reload only, - since BIOS settings were trusted instead on first load. - -Wed Feb 7 21:00 2001 Gerard Roudier - * version sym-2.1.6-20010207 - - Call pci_enable_device() as wished by kernel maintainers. - - Change the sym_queue_scsiio() interface. - This is intended to simplify portability. - - Move the code intended to deal with the dowloading of SCRIPTS - from SCRIPTS :) in the patch method (was wrongly placed in - the SCRIPTS setup method). - - Add a missing cpu_to_scr() (np->abort_tbl.addr) - - Remove a wrong cpu_to_scr() (np->targtbl_ba) - - Cleanup a bit the PPR failure recovery code. - -Sat Mar 3 21:00 2001 Gerard Roudier - - Add option SYM_OPT_ANNOUNCE_TRANSFER_RATE and move the - corresponding code to file sym_misc.c. - Also move the code that sniffes INQUIRY to sym_misc.c. - This allows to share the corresponding code with NetBSD - without polluating the core driver source (sym_hipd.c). - - Add optionnal code that handles IO timeouts from the driver. - (not used under Linux, but required for NetBSD) - - Donnot assume any longer that PAGE_SHIFT and PAGE_SIZE are - defined at compile time, as at least NetBSD uses variables - in memory for that. - - Refine a work-around for the C1010-33 that consists in - disabling internal LOAD/STORE. Was applied up to revision 1. - Is now only applied to revision 0. - - Some code reorganisations due to code moves between files. - -Tues Apr 10 21:00 2001 Gerard Roudier - * version sym-2.1.9-20010412 - - Reset 53C896 and 53C1010 chip according to the manual. - (i.e.: set the ABRT bit in ISTAT if SCRIPTS are running) - - Set #LUN in request sense only if scsi version <= 2 and - #LUN <= 7. - - Set busy_itl in LCB to 1 if the LCB is allocated and a - SCSI command is active. This is a simplification. - - In sym_hcb_free(), donnot scan the free_ccbq if no CCBs - has been allocated. This fixes a panic if attach failed. - - Add DT/ST (double/simple transition) in the transfer - negotiation announce. - - Forces the max number of tasks per LUN to at least 64. - - Use pci_set_dma_mask() for linux-2.4.3 and above. - - A couple of comments fixes. - -Wed May 22:00 2001 Gerard Roudier - * version sym-2.1.10-20010509 - - Mask GPCNTL against 0x1c (was 0xfc) for the reading of the NVRAM. - This ensure LEDC bit will not be set on 896 and later chips. - Fix sent by Chip Salzenberg . - - Define the number of PQS BUSes supported. - Fix sent by Stig Telfer - - Miscellaneous common code rearrangements due to NetBSD accel - ioctl support, without impact on Linux (hopefully). - -Mon July 2 12:00 2001 Gerard Roudier - * version sym-2.1.11-20010702 - - Add Tekram 390 U2B/U2W SCSI LED handling. - Submitted by Chip Salzenberg - - Add call to scsi_set_pci_device() for kernels >= 2.4.4. - - Check pci dma mapping failures and complete the IO with some - error when such mapping fails. - - Fill in instance->max_cmd_len for kernels > 2.4.0. - - A couple of tiny fixes ... - -Sun Sep 9 18:00 2001 Gerard Roudier - * version sym-2.1.12-20010909 - - Change my email address. - - Add infrastructure for the forthcoming 64 bit DMA adressing support. - (Based on PCI 64 bit patch from David S. Miller) - - Donnot use anymore vm_offset_t type. - -Sat Sep 15 20:00 2001 Gerard Roudier - * version sym-2.1.13-20010916 - - Add support for 64 bit DMA addressing using segment registers. - 16 registers for up to 4 GB x 16 -> 64 GB. - -Sat Sep 22 12:00 2001 Gerard Roudier - * version sym-2.1.14-20010922 - - Complete rewrite of the eh handling. The driver is now using a - semaphore in order to behave synchronously as required by the eh - threads. A timer is also used to prevent from waiting indefinitely. - -Sun Sep 30 17:00 2001 Gerard Roudier - * version sym-2.1.15-20010930 - - Include unconditionnaly as expected by latest - kernels. - - Use del_timer_sync() for recent kernels to kill the driver timer - on module release. - -Sun Oct 28 15:00 2001 Gerard Roudier - * version sym-2.1.16-20011028 - - Slightly simplify driver configuration. - - Prepare a new patch against linux-2.4.13. - -Sat Nov 17 10:00 2001 Gerard Roudier - * version sym-2.1.17 - - Fix a couple of gcc/gcc3 warnings. - - Allocate separately from the HCB the array for CCBs hashed by DSA. - All driver memory allocations are now not greater than 1 PAGE - even on PPC64 / 4KB PAGE surprising setup. - -Sat Dec 01 18:00 2001 Gerard Roudier - * version sym-2.1.17a - - Use u_long instead of U32 for the IO base cookie. This is more - consistent with what archs are expecting. - - Use MMIO per default for Power PC instead of some fake normal IO, - as Paul Mackerras stated that MMIO works fine now on this arch. - - - - diff --git a/xen/drivers/scsi/sym53c8xx_2/Documentation.txt b/xen/drivers/scsi/sym53c8xx_2/Documentation.txt deleted file mode 100644 index 713afc8f91..0000000000 --- a/xen/drivers/scsi/sym53c8xx_2/Documentation.txt +++ /dev/null @@ -1,1149 +0,0 @@ -The Linux SYM-2 driver documentation file - -Written by Gerard Roudier -21 Rue Carnot -95170 DEUIL LA BARRE - FRANCE - -Decembre 28 2000 -=============================================================================== - -1. Introduction -2. Supported chips and SCSI features -3. Advantages of this driver for newer chips. - 3.1 Optimized SCSI SCRIPTS - 3.2 New features appeared with the SYM53C896 -4. Memory mapped I/O versus normal I/O -5. Tagged command queueing -6. Parity checking -7. Profiling information -8. Control commands - 8.1 Set minimum synchronous period - 8.2 Set wide size - 8.3 Set maximum number of concurrent tagged commands - 8.4 Set debug mode - 8.5 Set flag (no_disc) - 8.6 Set verbose level - 8.7 Reset all logical units of a target - 8.8 Abort all tasks of all logical units of a target -9. Configuration parameters -10. Boot setup commands - 10.1 Syntax - 10.2 Available arguments - 10.2.1 Master parity checking - 10.2.2 Scsi parity checking - 10.2.3 Default number of tagged commands - 10.2.4 Default synchronous period factor - 10.2.5 Verbosity level - 10.2.6 Debug mode - 10.2.7 Burst max - 10.2.8 LED support - 10.2.9 Max wide - 10.2.10 Differential mode - 10.2.11 IRQ mode - 10.2.12 Reverse probe - 10.2.13 Fix up PCI configuration space - 10.2.14 Serial NVRAM - 10.2.15 Check SCSI BUS - 10.2.16 Exclude a host from being attached - 10.2.17 Suggest a default SCSI id for hosts - 10.3 PCI configuration fix-up boot option - 10.4 Serial NVRAM support boot option - 10.5 SCSI BUS checking boot option -11. SCSI problem troubleshooting - 15.1 Problem tracking - 15.2 Understanding hardware error reports -12. Serial NVRAM support (by Richard Waltham) - 17.1 Features - 17.2 Symbios NVRAM layout - 17.3 Tekram NVRAM layout - -=============================================================================== - -1. Introduction - -This driver supports the whole SYM53C8XX family of PCI-SCSI controllers. -It also support the subset of LSI53C10XX PCI-SCSI controllers that are based -on the SYM53C8XX SCRIPTS language. - -It replaces the sym53c8xx+ncr53c8xx driver bundle and shares its core code -with the FreeBSD SYM-2 driver. The `glue' that allows this driver to work -under Linux is contained in 2 files named sym_glue.h and sym_glue.c. -Other drivers files are intended not to depend on the Operating System -on which the driver is used. - -The history of this driver can be summerized as follows: - -1993: ncr driver written for 386bsd and FreeBSD by: - Wolfgang Stanglmeier - Stefan Esser - -1996: port of the ncr driver to Linux-1.2.13 and rename it ncr53c8xx. - Gerard Roudier - -1998: new sym53c8xx driver for Linux based on LOAD/STORE instruction and that - adds full support for the 896 but drops support for early NCR devices. - Gerard Roudier - -1999: port of the sym53c8xx driver to FreeBSD and support for the LSI53C1010 - 33 MHz and 66MHz Ultra-3 controllers. The new driver is named `sym'. - Gerard Roudier - -2000: Add support for early NCR devices to FreeBSD `sym' driver. - Break the driver into several sources and separate the OS glue - code from the core code that can be shared among different O/Ses. - Write a glue code for Linux. - Gerard Roudier - -This README file addresses the Linux version of the driver. Under FreeBSD, -the driver documentation is the sym.8 man page. - -Information about new chips is available at LSILOGIC web server: - - http://www.lsilogic.com/ - -SCSI standard documentations are available at T10 site: - - http://www.t10.org/ - -Useful SCSI tools written by Eric Youngdale are part of most Linux -distributions: - scsiinfo: command line tool - scsi-config: TCL/Tk tool using scsiinfo - -2. Supported chips and SCSI features - -The following features are supported for all chips: - - Synchronous negotiation - Disconnection - Tagged command queuing - SCSI parity checking - PCI Master parity checking - -Other features depends on chip capabilities. -The driver notably uses optimized SCRIPTS for devices that support -LOAD/STORE and handles PHASE MISMATCH from SCRIPTS for devices that -support the corresponding feature. - -The following table shows some characteristics of the chip family. - - On board LOAD/STORE HARDWARE -Chip SDMS BIOS Wide SCSI std. Max. sync SCRIPTS PHASE MISMATCH ----- --------- ---- --------- ---------- ---------- -------------- -810 N N FAST10 10 MB/s N N -810A N N FAST10 10 MB/s Y N -815 Y N FAST10 10 MB/s N N -825 Y Y FAST10 20 MB/s N N -825A Y Y FAST10 20 MB/s Y N -860 N N FAST20 20 MB/s Y N -875 Y Y FAST20 40 MB/s Y N -875A Y Y FAST20 40 MB/s Y Y -876 Y Y FAST20 40 MB/s Y N -895 Y Y FAST40 80 MB/s Y N -895A Y Y FAST40 80 MB/s Y Y -896 Y Y FAST40 80 MB/s Y Y -897 Y Y FAST40 80 MB/s Y Y -1510D Y Y FAST40 80 MB/s Y Y -1010 Y Y FAST80 160 MB/s Y Y -1010_66* Y Y FAST80 160 MB/s Y Y - -* Chip supports 33MHz and 66MHz PCI bus clock. - - -Summary of other supported features: - -Module: allow to load the driver -Memory mapped I/O: increases performance -Control commands: write operations to the proc SCSI file system -Debugging information: written to syslog (expert only) -Scatter / gather -Shared interrupt -Boot setup commands -Serial NVRAM: Symbios and Tekram formats - - -3. Advantages of this driver for newer chips. - -3.1 Optimized SCSI SCRIPTS. - -All chips except the 810, 815 and 825, support new SCSI SCRIPTS instructions -named LOAD and STORE that allow to move up to 1 DWORD from/to an IO register -to/from memory much faster that the MOVE MEMORY instruction that is supported -by the 53c7xx and 53c8xx family. - -The LOAD/STORE instructions support absolute and DSA relative addressing -modes. The SCSI SCRIPTS had been entirely rewritten using LOAD/STORE instead -of MOVE MEMORY instructions. - -Due to the lack of LOAD/STORE SCRIPTS instructions by earlier chips, this -driver also incorporates a different SCRIPTS set based on MEMORY MOVE, in -order to provide support for the entire SYM53C8XX chips family. - -3.2 New features appeared with the SYM53C896 - -Newer chips (see above) allows handling of the phase mismatch context from -SCRIPTS (avoids the phase mismatch interrupt that stops the SCSI processor -until the C code has saved the context of the transfer). - -The 896 and 1010 chips support 64 bit PCI transactions and addressing, -while the 895A supports 32 bit PCI transactions and 64 bit addressing. -The SCRIPTS processor of these chips is not true 64 bit, but uses segment -registers for bit 32-63. Another interesting feature is that LOAD/STORE -instructions that address the on-chip RAM (8k) remain internal to the chip. - -4. Memory mapped I/O versus normal I/O - -Memory mapped I/O has less latency than normal I/O and is the recommended -way for doing IO with PCI devices. Memory mapped I/O seems to work fine on -most hardware configurations, but some poorly designed chipsets may break -this feature. A configuration option is provided for normal I/O to be -used but the driver defaults to MMIO. - -5. Tagged command queueing - -Queuing more than 1 command at a time to a device allows it to perform -optimizations based on actual head positions and its mechanical -characteristics. This feature may also reduce average command latency. -In order to really gain advantage of this feature, devices must have -a reasonnable cache size (No miracle is to be expected for a low-end -hard disk with 128 KB or less). -Some kown old SCSI devices do not properly support tagged command queuing. -Generally, firmware revisions that fix this kind of problems are available -at respective vendor web/ftp sites. -All I can say is that I never have had problem with tagged queuing using -this driver and its predecessors. Hard disks that behaved correctly for -me using tagged commands are the following: - -- IBM S12 0662 -- Conner 1080S -- Quantum Atlas I -- Quantum Atlas II -- Seagate Cheetah I -- Quantum Viking II -- IBM DRVS -- Quantum Atlas IV -- Seagate Cheetah II - -If your controller has NVRAM, you can configure this feature per target -from the user setup tool. The Tekram Setup program allows to tune the -maximum number of queued commands up to 32. The Symbios Setup only allows -to enable or disable this feature. - -The maximum number of simultaneous tagged commands queued to a device -is currently set to 16 by default. This value is suitable for most SCSI -disks. With large SCSI disks (>= 2GB, cache >= 512KB, average seek time -<= 10 ms), using a larger value may give better performances. - -This driver supports up to 255 commands per device, and but using more than -64 is generally not worth-while, unless you are using a very large disk or -disk arrays. It is noticeable that most of recent hard disks seem not to -accept more than 64 simultaneous commands. So, using more than 64 queued -commands is probably just resource wasting. - -If your controller does not have NVRAM or if it is managed by the SDMS -BIOS/SETUP, you can configure tagged queueing feature and device queue -depths from the boot command-line. For example: - - sym53c8xx=tags:4/t2t3q15-t4q7/t1u0q32 - -will set tagged commands queue depths as follow: - -- target 2 all luns on controller 0 --> 15 -- target 3 all luns on controller 0 --> 15 -- target 4 all luns on controller 0 --> 7 -- target 1 lun 0 on controller 1 --> 32 -- all other target/lun --> 4 - -In some special conditions, some SCSI disk firmwares may return a -QUEUE FULL status for a SCSI command. This behaviour is managed by the -driver using the following heuristic: - -- Each time a QUEUE FULL status is returned, tagged queue depth is reduced - to the actual number of disconnected commands. - -- Every 200 successfully completed SCSI commands, if allowed by the - current limit, the maximum number of queueable commands is incremented. - -Since QUEUE FULL status reception and handling is resource wasting, the -driver notifies by default this problem to user by indicating the actual -number of commands used and their status, as well as its decision on the -device queue depth change. -The heuristic used by the driver in handling QUEUE FULL ensures that the -impact on performances is not too bad. You can get rid of the messages by -setting verbose level to zero, as follow: - -1st method: boot your system using 'sym53c8xx=verb:0' option. -2nd method: apply "setverbose 0" control command to the proc fs entry - corresponding to your controller after boot-up. - -6. Parity checking - -The driver supports SCSI parity checking and PCI bus master parity -checking. These features must be enabled in order to ensure safe data -transfers. However, some flawed devices or mother boards will have -problems with parity. You can disable either PCI parity or SCSI parity -checking by entering appropriate options from the boot command line. -(See 10: Boot setup commands). - -7. Profiling information - -This driver does not provide profiling informations as did its predecessors. -This feature was not this useful and added complexity to the code. -As the driver code got more complex, I have decided to remove everything -that didn't seem actually useful. - -8. Control commands - -Control commands can be sent to the driver with write operations to -the proc SCSI file system. The generic command syntax is the -following: - - echo " " >/proc/scsi/sym53c8xx/0 - (assumes controller number is 0) - -Using "all" for "" parameter with the commands below will -apply to all targets of the SCSI chain (except the controller). - -Available commands: - -8.1 Set minimum synchronous period factor - - setsync - - target: target number - period: minimum synchronous period. - Maximum speed = 1000/(4*period factor) except for special - cases below. - - Specify a period of 0, to force asynchronous transfer mode. - - 9 means 12.5 nano-seconds synchronous period - 10 means 25 nano-seconds synchronous period - 11 means 30 nano-seconds synchronous period - 12 means 50 nano-seconds synchronous period - -8.2 Set wide size - - setwide - - target: target number - size: 0=8 bits, 1=16bits - -8.3 Set maximum number of concurrent tagged commands - - settags - - target: target number - tags: number of concurrent tagged commands - must not be greater than configured (default: 16) - -8.4 Set debug mode - - setdebug - - Available debug flags: - alloc: print info about memory allocations (ccb, lcb) - queue: print info about insertions into the command start queue - result: print sense data on CHECK CONDITION status - scatter: print info about the scatter process - scripts: print info about the script binding process - tiny: print minimal debugging information - timing: print timing information of the NCR chip - nego: print information about SCSI negotiations - phase: print information on script interruptions - - Use "setdebug" with no argument to reset debug flags. - - -8.5 Set flag (no_disc) - - setflag - - target: target number - - For the moment, only one flag is available: - - no_disc: not allow target to disconnect. - - Do not specify any flag in order to reset the flag. For example: - - setflag 4 - will reset no_disc flag for target 4, so will allow it disconnections. - - setflag all - will allow disconnection for all devices on the SCSI bus. - - -8.6 Set verbose level - - setverbose #level - - The driver default verbose level is 1. This command allows to change - th driver verbose level after boot-up. - -8.7 Reset all logical units of a target - - resetdev - - target: target number - The driver will try to send a BUS DEVICE RESET message to the target. - -8.8 Abort all tasks of all logical units of a target - - cleardev - - target: target number - The driver will try to send a ABORT message to all the logical units - of the target. - - -9. Configuration parameters - -Under kernel configuration tools (make menuconfig, for example), it is -possible to change some default driver configuration parameters. -If the firmware of all your devices is perfect enough, all the -features supported by the driver can be enabled at start-up. However, -if only one has a flaw for some SCSI feature, you can disable the -support by the driver of this feature at linux start-up and enable -this feature after boot-up only for devices that support it safely. - -Configuration parameters: - -Use normal IO (default answer: n) - Answer "y" if you suspect your mother board to not allow memory mapped I/O. - May slow down performance a little. - -Default tagged command queue depth (default answer: 16) - Entering 0 defaults to tagged commands not being used. - This parameter can be specified from the boot command line. - -Maximum number of queued commands (default answer: 32) - This option allows you to specify the maximum number of tagged commands - that can be queued to a device. The maximum supported value is 255. - -Synchronous transfers frequency (default answer: 80) - This option allows you to specify the frequency in MHz the driver - will use at boot time for synchronous data transfer negotiations. - 0 means "asynchronous data transfers". - -10. Boot setup commands - -10.1 Syntax - -Setup commands can be passed to the driver either at boot time or as a -string variable using 'insmod'. - -A boot setup command for this driver begins with the driver name "sym53c8xx=". -The kernel syntax parser then expects an optionnal list of integers separated -with comma followed by an optional list of comma-separated strings. - -Example of boot setup command under lilo prompt: - -lilo: linux root=/dev/sda2 sym53c8xx=tags:4,sync:10,debug:0x200 - -- enable tagged commands, up to 4 tagged commands queued. -- set synchronous negotiation speed to 10 Mega-transfers / second. -- set DEBUG_NEGO flag. - -Since comma seems not to be allowed when defining a string variable using -'insmod', the driver also accepts as option separator. -The following command will install driver module with the same options as -above. - - insmod sym53c8xx.o sym53c8xx="tags:4 sync:10 debug:0x200" - -The integer list of arguments is discarded by the driver. - -Each string argument must be specified as "keyword:value". Only lower-case -characters and digits are allowed. - -10.2 Available arguments - -10.2.1 Master parity checking - mpar:y enabled - mpar:n disabled - -10.2.2 Scsi parity checking - spar:y enabled - spar:n disabled - -10.2.3 Default number of tagged commands - tags:0 (or tags:1 ) tagged command queuing disabled - tags:#tags (#tags > 1) tagged command queuing enabled - #tags will be truncated to the max queued commands configuration parameter. - This option also allows to specify a command queue depth for each device - that support tagged command queueing. - Example: - sym53c8xx=tags:10/t2t3q16-t5q24/t1u2q32 - will set devices queue depth as follow: - - controller #0 target #2 and target #3 -> 16 commands, - - controller #0 target #5 -> 24 commands, - - controller #1 target #1 logical unit #2 -> 32 commands, - - all other logical units (all targets, all controllers) -> 10 commands. - -10.2.4 Default synchronous period factor - sync:255 disabled (asynchronous transfer mode) - sync:#factor - #factor = 9 Ultra-3 SCSI 80 Mega-transfers / second (Wide only) - #factor = 10 Ultra-2 SCSI 40 Mega-transfers / second - #factor = 11 Ultra-2 SCSI 33 Mega-transfers / second - #factor < 25 Ultra SCSI 20 Mega-transfers / second - #factor < 50 Fast SCSI-2 - - In all cases, the driver will use the minimum transfer period supported by - controllers according to SYM53C8XX chip type. - -10.2.5 Verbosity level - verb:0 minimal - verb:1 normal - verb:2 too much - -10.2.6 Debug mode - debug:0 clear debug flags - debug:#x set debug flags - #x is an integer value combining the following power-of-2 values: - DEBUG_ALLOC 0x1 - DEBUG_PHASE 0x2 - DEBUG_POLL 0x4 - DEBUG_QUEUE 0x8 - DEBUG_RESULT 0x10 - DEBUG_SCATTER 0x20 - DEBUG_SCRIPT 0x40 - DEBUG_TINY 0x80 - DEBUG_TIMING 0x100 - DEBUG_NEGO 0x200 - DEBUG_TAGS 0x400 - DEBUG_FREEZE 0x800 - DEBUG_RESTART 0x1000 - - You can play safely with DEBUG_NEGO. However, some of these flags may - generate bunches of syslog messages. - -10.2.7 Burst max - burst:0 burst disabled - burst:255 get burst length from initial IO register settings. - burst:#x burst enabled (1<<#x burst transfers max) - #x is an integer value which is log base 2 of the burst transfers max. - By default the driver uses the maximum value supported by the chip. - -10.2.8 LED support - led:1 enable LED support - led:0 disable LED support - Donnot enable LED support if your scsi board does not use SDMS BIOS. - (See 'Configuration parameters') - -10.2.9 Max wide - wide:1 wide scsi enabled - wide:0 wide scsi disabled - Some scsi boards use a 875 (ultra wide) and only supply narrow connectors. - If you have connected a wide device with a 50 pins to 68 pins cable - converter, any accepted wide negotiation will break further data transfers. - In such a case, using "wide:0" in the bootup command will be helpfull. - -10.2.10 Differential mode - diff:0 never set up diff mode - diff:1 set up diff mode if BIOS set it - diff:2 always set up diff mode - diff:3 set diff mode if GPIO3 is not set - -10.2.11 IRQ mode - irqm:0 always open drain - irqm:1 same as initial settings (assumed BIOS settings) - irqm:2 always totem pole - -10.2.12 Reverse probe - revprob:n probe chip ids from the PCI configuration in this order: - 810, 815, 825, 860, 875, 885, 875A, 895, 896, 895A, - 1510D, 1010-33, 1010-66. - revprob:y probe chip ids in the reverse order. - -10.2.13 Fix up PCI configuration space - pcifix: